From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../src/compiler/translator/ASTMetadataHLSL.cpp | 445 + .../src/compiler/translator/ASTMetadataHLSL.h | 62 + .../translator/AtomicCounterFunctionHLSL.cpp | 112 + .../translator/AtomicCounterFunctionHLSL.h | 50 + .../checkout/src/compiler/translator/BaseTypes.cpp | 64 + .../checkout/src/compiler/translator/BaseTypes.h | 1782 ++ .../translator/BuiltInFunctionEmulator.cpp | 161 + .../compiler/translator/BuiltInFunctionEmulator.h | 80 + .../translator/BuiltInFunctionEmulatorGLSL.cpp | 284 + .../translator/BuiltInFunctionEmulatorGLSL.h | 40 + .../translator/BuiltInFunctionEmulatorHLSL.cpp | 173 + .../translator/BuiltInFunctionEmulatorHLSL.h | 27 + .../compiler/translator/BuiltinsWorkaroundGLSL.cpp | 109 + .../compiler/translator/BuiltinsWorkaroundGLSL.h | 24 + .../checkout/src/compiler/translator/CallDAG.cpp | 316 + .../checkout/src/compiler/translator/CallDAG.h | 77 + .../checkout/src/compiler/translator/CodeGen.cpp | 96 + .../src/compiler/translator/CollectVariables.cpp | 1288 + .../src/compiler/translator/CollectVariables.h | 38 + .../checkout/src/compiler/translator/Common.h | 256 + .../checkout/src/compiler/translator/Compiler.cpp | 1746 ++ .../checkout/src/compiler/translator/Compiler.h | 397 + .../src/compiler/translator/ConstantUnion.cpp | 803 + .../src/compiler/translator/ConstantUnion.h | 122 + .../src/compiler/translator/Declarator.cpp | 33 + .../checkout/src/compiler/translator/Declarator.h | 49 + .../src/compiler/translator/Diagnostics.cpp | 106 + .../checkout/src/compiler/translator/Diagnostics.h | 67 + .../src/compiler/translator/DirectiveHandler.cpp | 304 + .../src/compiler/translator/DirectiveHandler.h | 57 + .../src/compiler/translator/DriverUniformMetal.h | 33 + .../src/compiler/translator/ExtensionBehavior.cpp | 125 + .../src/compiler/translator/ExtensionBehavior.h | 93 + .../src/compiler/translator/ExtensionGLSL.cpp | 118 + .../src/compiler/translator/ExtensionGLSL.h | 44 + .../src/compiler/translator/FlagStd140Structs.cpp | 76 + .../src/compiler/translator/FlagStd140Structs.h | 30 + .../src/compiler/translator/FunctionLookup.cpp | 179 + .../src/compiler/translator/FunctionLookup.h | 60 + .../checkout/src/compiler/translator/HashNames.cpp | 99 + .../checkout/src/compiler/translator/HashNames.h | 33 + .../src/compiler/translator/ImageFunctionHLSL.cpp | 401 + .../src/compiler/translator/ImageFunctionHLSL.h | 96 + .../src/compiler/translator/ImmutableString.h | 143 + .../compiler/translator/ImmutableStringBuilder.cpp | 63 + .../compiler/translator/ImmutableStringBuilder.h | 80 + .../translator/ImmutableString_ESSL_autogen.cpp | 345 + .../checkout/src/compiler/translator/InfoSink.cpp | 124 + .../checkout/src/compiler/translator/InfoSink.h | 152 + .../src/compiler/translator/Initialize.cpp | 223 + .../checkout/src/compiler/translator/Initialize.h | 30 + .../src/compiler/translator/InitializeDll.cpp | 33 + .../src/compiler/translator/InitializeDll.h | 15 + .../src/compiler/translator/InitializeGlobals.h | 13 + .../src/compiler/translator/IntermNode.cpp | 4226 +++ .../checkout/src/compiler/translator/IntermNode.h | 1046 + .../compiler/translator/IsASTDepthBelowLimit.cpp | 37 + .../src/compiler/translator/IsASTDepthBelowLimit.h | 20 + .../checkout/src/compiler/translator/Operator.cpp | 171 + .../src/compiler/translator/Operator_autogen.h | 578 + .../src/compiler/translator/OutputESSL.cpp | 55 + .../checkout/src/compiler/translator/OutputESSL.h | 30 + .../src/compiler/translator/OutputGLSL.cpp | 122 + .../checkout/src/compiler/translator/OutputGLSL.h | 31 + .../src/compiler/translator/OutputGLSLBase.cpp | 1513 + .../src/compiler/translator/OutputGLSLBase.h | 154 + .../src/compiler/translator/OutputHLSL.cpp | 3700 +++ .../checkout/src/compiler/translator/OutputHLSL.h | 289 + .../src/compiler/translator/OutputTree.cpp | 723 + .../checkout/src/compiler/translator/OutputTree.h | 22 + .../src/compiler/translator/ParseContext.cpp | 7538 +++++ .../src/compiler/translator/ParseContext.h | 818 + .../checkout/src/compiler/translator/PoolAlloc.cpp | 40 + .../checkout/src/compiler/translator/PoolAlloc.h | 102 + .../checkout/src/compiler/translator/Pragma.h | 28 + .../src/compiler/translator/QualifierTypes.cpp | 1007 + .../src/compiler/translator/QualifierTypes.h | 214 + .../src/compiler/translator/ResourcesHLSL.cpp | 989 + .../src/compiler/translator/ResourcesHLSL.h | 155 + .../checkout/src/compiler/translator/Severity.h | 22 + .../src/compiler/translator/ShaderLang.cpp | 1091 + .../translator/ShaderStorageBlockFunctionHLSL.cpp | 439 + .../translator/ShaderStorageBlockFunctionHLSL.h | 94 + .../translator/ShaderStorageBlockOutputHLSL.cpp | 667 + .../translator/ShaderStorageBlockOutputHLSL.h | 86 + .../src/compiler/translator/ShaderVars.cpp | 625 + .../checkout/src/compiler/translator/StaticType.h | 296 + .../src/compiler/translator/StructureHLSL.cpp | 668 + .../src/compiler/translator/StructureHLSL.h | 102 + .../checkout/src/compiler/translator/Symbol.cpp | 254 + .../checkout/src/compiler/translator/Symbol.h | 402 + .../src/compiler/translator/SymbolTable.cpp | 559 + .../checkout/src/compiler/translator/SymbolTable.h | 363 + .../translator/SymbolTable_ESSL_autogen.cpp | 30071 +++++++++++++++++++ .../src/compiler/translator/SymbolTable_autogen.h | 169 + .../src/compiler/translator/SymbolUniqueId.cpp | 27 + .../src/compiler/translator/SymbolUniqueId.h | 58 + .../compiler/translator/TextureFunctionHLSL.cpp | 1614 + .../src/compiler/translator/TextureFunctionHLSL.h | 77 + .../src/compiler/translator/TranslatorESSL.cpp | 219 + .../src/compiler/translator/TranslatorESSL.h | 35 + .../src/compiler/translator/TranslatorGLSL.cpp | 388 + .../src/compiler/translator/TranslatorGLSL.h | 38 + .../src/compiler/translator/TranslatorHLSL.cpp | 311 + .../src/compiler/translator/TranslatorHLSL.h | 56 + .../src/compiler/translator/TranslatorMetal.h | 62 + .../compiler/translator/TranslatorMetalDirect.h | 195 + .../src/compiler/translator/TranslatorVulkan.h | 60 + .../checkout/src/compiler/translator/Types.cpp | 984 + gfx/angle/checkout/src/compiler/translator/Types.h | 508 + .../checkout/src/compiler/translator/UtilsHLSL.cpp | 1223 + .../checkout/src/compiler/translator/UtilsHLSL.h | 148 + .../src/compiler/translator/ValidateAST.cpp | 1133 + .../checkout/src/compiler/translator/ValidateAST.h | 108 + .../translator/ValidateBarrierFunctionCall.cpp | 100 + .../translator/ValidateBarrierFunctionCall.h | 22 + .../translator/ValidateClipCullDistance.cpp | 200 + .../compiler/translator/ValidateClipCullDistance.h | 27 + .../translator/ValidateGlobalInitializer.cpp | 157 + .../translator/ValidateGlobalInitializer.h | 24 + .../compiler/translator/ValidateLimitations.cpp | 452 + .../src/compiler/translator/ValidateLimitations.h | 26 + .../compiler/translator/ValidateMaxParameters.cpp | 30 + .../compiler/translator/ValidateMaxParameters.h | 21 + .../src/compiler/translator/ValidateOutputs.cpp | 184 + .../src/compiler/translator/ValidateOutputs.h | 30 + .../src/compiler/translator/ValidateSwitch.cpp | 315 + .../src/compiler/translator/ValidateSwitch.h | 27 + .../translator/ValidateTypeSizeLimitations.cpp | 229 + .../translator/ValidateTypeSizeLimitations.h | 25 + .../translator/ValidateVaryingLocations.cpp | 368 + .../compiler/translator/ValidateVaryingLocations.h | 28 + .../src/compiler/translator/VariablePacker.cpp | 409 + .../src/compiler/translator/VariablePacker.h | 32 + .../src/compiler/translator/VersionGLSL.cpp | 156 + .../checkout/src/compiler/translator/VersionGLSL.h | 76 + .../src/compiler/translator/blocklayout.cpp | 666 + .../checkout/src/compiler/translator/blocklayout.h | 322 + .../src/compiler/translator/blocklayoutHLSL.cpp | 167 + .../src/compiler/translator/blocklayoutHLSL.h | 68 + .../emulated_builtin_functions_hlsl_autogen.cpp | 881 + .../checkout/src/compiler/translator/glslang.h | 24 + .../compiler/translator/glslang_lex_autogen.cpp | 4326 +++ .../compiler/translator/glslang_tab_autogen.cpp | 4909 +++ .../src/compiler/translator/glslang_tab_autogen.h | 320 + .../src/compiler/translator/glslang_wrapper.h | 46 + .../src/compiler/translator/length_limits.h | 26 + .../translator/tree_ops/ClampIndirectIndices.cpp | 136 + .../translator/tree_ops/ClampIndirectIndices.h | 27 + .../translator/tree_ops/ClampPointSize.cpp | 52 + .../compiler/translator/tree_ops/ClampPointSize.h | 28 + ...nvertUnsupportedConstructorsToFunctionCalls.cpp | 335 + ...ConvertUnsupportedConstructorsToFunctionCalls.h | 25 + ...DeclareAndInitBuiltinsForInstancedMultiview.cpp | 196 + .../DeclareAndInitBuiltinsForInstancedMultiview.h | 52 + .../tree_ops/DeferGlobalInitializers.cpp | 180 + .../translator/tree_ops/DeferGlobalInitializers.h | 38 + .../tree_ops/EmulateGLFragColorBroadcast.cpp | 142 + .../tree_ops/EmulateGLFragColorBroadcast.h | 35 + .../tree_ops/EmulateMultiDrawShaderBuiltins.cpp | 274 + .../tree_ops/EmulateMultiDrawShaderBuiltins.h | 47 + .../translator/tree_ops/FoldExpressions.cpp | 120 + .../compiler/translator/tree_ops/FoldExpressions.h | 29 + .../tree_ops/ForcePrecisionQualifier.cpp | 101 + .../translator/tree_ops/ForcePrecisionQualifier.h | 17 + .../translator/tree_ops/InitializeVariables.cpp | 359 + .../translator/tree_ops/InitializeVariables.h | 60 + .../tree_ops/MonomorphizeUnsupportedFunctions.cpp | 613 + .../tree_ops/MonomorphizeUnsupportedFunctions.h | 54 + .../tree_ops/NameNamelessUniformBuffers.cpp | 127 + .../tree_ops/NameNamelessUniformBuffers.h | 32 + .../translator/tree_ops/PruneEmptyCases.cpp | 127 + .../compiler/translator/tree_ops/PruneEmptyCases.h | 22 + .../compiler/translator/tree_ops/PruneNoOps.cpp | 215 + .../src/compiler/translator/tree_ops/PruneNoOps.h | 29 + .../tree_ops/RecordConstantPrecision.cpp | 119 + .../translator/tree_ops/RecordConstantPrecision.h | 33 + .../tree_ops/RemoveArrayLengthMethod.cpp | 109 + .../translator/tree_ops/RemoveArrayLengthMethod.h | 37 + .../tree_ops/RemoveAtomicCounterBuiltins.cpp | 74 + .../tree_ops/RemoveAtomicCounterBuiltins.h | 24 + .../translator/tree_ops/RemoveDynamicIndexing.cpp | 597 + .../translator/tree_ops/RemoveDynamicIndexing.h | 41 + .../tree_ops/RemoveInactiveInterfaceVariables.cpp | 209 + .../tree_ops/RemoveInactiveInterfaceVariables.h | 42 + .../tree_ops/RemoveInvariantDeclaration.cpp | 47 + .../tree_ops/RemoveInvariantDeclaration.h | 21 + .../tree_ops/RemoveUnreferencedVariables.cpp | 371 + .../tree_ops/RemoveUnreferencedVariables.h | 29 + .../RewriteArrayOfArrayOfOpaqueUniforms.cpp | 348 + .../tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.h | 25 + .../translator/tree_ops/RewriteAtomicCounters.cpp | 328 + .../translator/tree_ops/RewriteAtomicCounters.h | 28 + .../tree_ops/RewriteCubeMapSamplersAs2DArray.cpp | 984 + .../tree_ops/RewriteCubeMapSamplersAs2DArray.h | 29 + .../compiler/translator/tree_ops/RewriteDfdy.cpp | 141 + .../src/compiler/translator/tree_ops/RewriteDfdy.h | 32 + .../tree_ops/RewritePixelLocalStorage.cpp | 861 + .../translator/tree_ops/RewritePixelLocalStorage.h | 29 + .../translator/tree_ops/RewriteStructSamplers.cpp | 673 + .../translator/tree_ops/RewriteStructSamplers.h | 38 + .../tree_ops/RewriteTexelFetchOffset.cpp | 168 + .../translator/tree_ops/RewriteTexelFetchOffset.h | 34 + .../tree_ops/ScalarizeVecAndMatConstructorArgs.cpp | 223 + .../tree_ops/ScalarizeVecAndMatConstructorArgs.h | 28 + .../translator/tree_ops/SeparateDeclarations.cpp | 199 + .../translator/tree_ops/SeparateDeclarations.h | 32 + .../SeparateStructFromUniformDeclarations.cpp | 115 + .../SeparateStructFromUniformDeclarations.h | 39 + .../translator/tree_ops/SimplifyLoopConditions.cpp | 499 + .../translator/tree_ops/SimplifyLoopConditions.h | 32 + .../translator/tree_ops/SplitSequenceOperator.cpp | 173 + .../translator/tree_ops/SplitSequenceOperator.h | 30 + .../tree_ops/apple/AddAndTrueToLoopCondition.cpp | 60 + .../tree_ops/apple/AddAndTrueToLoopCondition.h | 31 + .../translator/tree_ops/apple/RewriteDoWhile.cpp | 147 + .../translator/tree_ops/apple/RewriteDoWhile.h | 38 + .../tree_ops/apple/RewriteRowMajorMatrices.cpp | 1595 + .../tree_ops/apple/RewriteRowMajorMatrices.h | 37 + .../apple/RewriteUnaryMinusOperatorFloat.cpp | 97 + .../apple/RewriteUnaryMinusOperatorFloat.h | 31 + .../tree_ops/apple/UnfoldShortCircuitAST.cpp | 74 + .../tree_ops/apple/UnfoldShortCircuitAST.h | 33 + .../tree_ops/d3d/AddDefaultReturnStatements.cpp | 61 + .../tree_ops/d3d/AddDefaultReturnStatements.h | 24 + .../tree_ops/d3d/AggregateAssignArraysInSSBOs.cpp | 82 + .../tree_ops/d3d/AggregateAssignArraysInSSBOs.h | 23 + .../tree_ops/d3d/AggregateAssignStructsInSSBOs.cpp | 76 + .../tree_ops/d3d/AggregateAssignStructsInSSBOs.h | 23 + .../d3d/ArrayReturnValueToOutParameter.cpp | 233 + .../tree_ops/d3d/ArrayReturnValueToOutParameter.h | 27 + .../d3d/BreakVariableAliasingInInnerLoops.cpp | 110 + .../d3d/BreakVariableAliasingInInnerLoops.h | 25 + .../tree_ops/d3d/ExpandIntegerPowExpressions.cpp | 152 + .../tree_ops/d3d/ExpandIntegerPowExpressions.h | 34 + .../RecordUniformBlocksWithLargeArrayMember.cpp | 385 + .../d3d/RecordUniformBlocksWithLargeArrayMember.h | 28 + .../tree_ops/d3d/RemoveSwitchFallThrough.cpp | 270 + .../tree_ops/d3d/RemoveSwitchFallThrough.h | 27 + .../d3d/RewriteAtomicFunctionExpressions.cpp | 183 + .../d3d/RewriteAtomicFunctionExpressions.h | 42 + .../translator/tree_ops/d3d/RewriteElseBlocks.cpp | 123 + .../translator/tree_ops/d3d/RewriteElseBlocks.h | 27 + .../RewriteExpressionsWithShaderStorageBlock.cpp | 420 + .../d3d/RewriteExpressionsWithShaderStorageBlock.h | 37 + .../tree_ops/d3d/RewriteUnaryMinusOperatorInt.cpp | 117 + .../tree_ops/d3d/RewriteUnaryMinusOperatorInt.h | 23 + .../d3d/SeparateArrayConstructorStatements.cpp | 83 + .../d3d/SeparateArrayConstructorStatements.h | 25 + .../tree_ops/d3d/SeparateArrayInitialization.cpp | 89 + .../tree_ops/d3d/SeparateArrayInitialization.h | 32 + .../d3d/SeparateExpressionsReturningArrays.cpp | 138 + .../d3d/SeparateExpressionsReturningArrays.h | 28 + .../tree_ops/d3d/UnfoldShortCircuitToIf.cpp | 200 + .../tree_ops/d3d/UnfoldShortCircuitToIf.h | 30 + .../tree_ops/d3d/WrapSwitchStatementsInBlocks.cpp | 126 + .../tree_ops/d3d/WrapSwitchStatementsInBlocks.h | 25 + .../translator/tree_ops/gl/ClampFragDepth.cpp | 54 + .../translator/tree_ops/gl/ClampFragDepth.h | 39 + .../tree_ops/gl/RegenerateStructNames.cpp | 119 + .../translator/tree_ops/gl/RegenerateStructNames.h | 34 + .../gl/RewriteRepeatedAssignToSwizzled.cpp | 97 + .../tree_ops/gl/RewriteRepeatedAssignToSwizzled.h | 40 + .../tree_ops/gl/UseInterfaceBlockFields.cpp | 108 + .../tree_ops/gl/UseInterfaceBlockFields.h | 44 + .../src/compiler/translator/tree_util/AsNode.h | 212 + .../src/compiler/translator/tree_util/BuiltIn.h | 18 + .../translator/tree_util/BuiltIn_ESSL_autogen.h | 4177 +++ .../tree_util/BuiltIn_complete_autogen.h | 5008 +++ .../translator/tree_util/DriverUniform.cpp | 435 + .../compiler/translator/tree_util/DriverUniform.h | 110 + .../compiler/translator/tree_util/FindFunction.cpp | 32 + .../compiler/translator/tree_util/FindFunction.h | 21 + .../src/compiler/translator/tree_util/FindMain.cpp | 54 + .../src/compiler/translator/tree_util/FindMain.h | 24 + .../translator/tree_util/FindPreciseNodes.cpp | 703 + .../translator/tree_util/FindPreciseNodes.h | 25 + .../translator/tree_util/FindSymbolNode.cpp | 53 + .../compiler/translator/tree_util/FindSymbolNode.h | 23 + .../tree_util/IntermNodePatternMatcher.cpp | 213 + .../tree_util/IntermNodePatternMatcher.h | 81 + .../translator/tree_util/IntermNode_util.cpp | 436 + .../translator/tree_util/IntermNode_util.h | 128 + .../translator/tree_util/IntermRebuild.cpp | 1046 + .../compiler/translator/tree_util/IntermRebuild.h | 328 + .../translator/tree_util/IntermTraverse.cpp | 708 + .../compiler/translator/tree_util/IntermTraverse.h | 379 + .../src/compiler/translator/tree_util/NodeSearch.h | 56 + .../src/compiler/translator/tree_util/NodeType.h | 155 + .../tree_util/ReplaceArrayOfMatrixVarying.cpp | 175 + .../tree_util/ReplaceArrayOfMatrixVarying.h | 33 + .../tree_util/ReplaceClipCullDistanceVariable.cpp | 591 + .../tree_util/ReplaceClipCullDistanceVariable.h | 43 + .../tree_util/ReplaceShadowingVariables.cpp | 142 + .../tree_util/ReplaceShadowingVariables.h | 26 + .../translator/tree_util/ReplaceVariable.cpp | 145 + .../translator/tree_util/ReplaceVariable.h | 48 + .../tree_util/RewriteSampleMaskVariable.cpp | 198 + .../tree_util/RewriteSampleMaskVariable.h | 38 + .../tree_util/RunAtTheBeginningOfShader.cpp | 35 + .../tree_util/RunAtTheBeginningOfShader.h | 27 + .../translator/tree_util/RunAtTheEndOfShader.cpp | 129 + .../translator/tree_util/RunAtTheEndOfShader.h | 29 + .../tree_util/SpecializationConstant.cpp | 122 + .../translator/tree_util/SpecializationConstant.h | 55 + .../src/compiler/translator/tree_util/Visit.h | 22 + .../checkout/src/compiler/translator/util.cpp | 1023 + gfx/angle/checkout/src/compiler/translator/util.h | 108 + 308 files changed, 126962 insertions(+) create mode 100644 gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/AtomicCounterFunctionHLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/AtomicCounterFunctionHLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/BaseTypes.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/BaseTypes.h create mode 100644 gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.h create mode 100644 gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/BuiltinsWorkaroundGLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/BuiltinsWorkaroundGLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/CallDAG.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/CallDAG.h create mode 100644 gfx/angle/checkout/src/compiler/translator/CodeGen.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/CollectVariables.h create mode 100644 gfx/angle/checkout/src/compiler/translator/Common.h create mode 100644 gfx/angle/checkout/src/compiler/translator/Compiler.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/Compiler.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ConstantUnion.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ConstantUnion.h create mode 100644 gfx/angle/checkout/src/compiler/translator/Declarator.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/Declarator.h create mode 100644 gfx/angle/checkout/src/compiler/translator/Diagnostics.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/Diagnostics.h create mode 100644 gfx/angle/checkout/src/compiler/translator/DirectiveHandler.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/DirectiveHandler.h create mode 100644 gfx/angle/checkout/src/compiler/translator/DriverUniformMetal.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ExtensionBehavior.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ExtensionBehavior.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ExtensionGLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ExtensionGLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/FlagStd140Structs.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/FlagStd140Structs.h create mode 100644 gfx/angle/checkout/src/compiler/translator/FunctionLookup.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/FunctionLookup.h create mode 100644 gfx/angle/checkout/src/compiler/translator/HashNames.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/HashNames.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ImageFunctionHLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ImageFunctionHLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ImmutableString.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ImmutableStringBuilder.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ImmutableStringBuilder.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ImmutableString_ESSL_autogen.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/InfoSink.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/InfoSink.h create mode 100644 gfx/angle/checkout/src/compiler/translator/Initialize.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/Initialize.h create mode 100644 gfx/angle/checkout/src/compiler/translator/InitializeDll.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/InitializeDll.h create mode 100644 gfx/angle/checkout/src/compiler/translator/InitializeGlobals.h create mode 100644 gfx/angle/checkout/src/compiler/translator/IntermNode.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/IntermNode.h create mode 100644 gfx/angle/checkout/src/compiler/translator/IsASTDepthBelowLimit.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/IsASTDepthBelowLimit.h create mode 100644 gfx/angle/checkout/src/compiler/translator/Operator.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/Operator_autogen.h create mode 100644 gfx/angle/checkout/src/compiler/translator/OutputESSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/OutputESSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/OutputGLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/OutputGLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/OutputGLSLBase.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/OutputGLSLBase.h create mode 100644 gfx/angle/checkout/src/compiler/translator/OutputHLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/OutputHLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/OutputTree.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/OutputTree.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ParseContext.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ParseContext.h create mode 100644 gfx/angle/checkout/src/compiler/translator/PoolAlloc.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/PoolAlloc.h create mode 100644 gfx/angle/checkout/src/compiler/translator/Pragma.h create mode 100644 gfx/angle/checkout/src/compiler/translator/QualifierTypes.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/QualifierTypes.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ResourcesHLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ResourcesHLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/Severity.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ShaderLang.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockFunctionHLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockFunctionHLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockOutputHLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockOutputHLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ShaderVars.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/StaticType.h create mode 100644 gfx/angle/checkout/src/compiler/translator/StructureHLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/StructureHLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/Symbol.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/Symbol.h create mode 100644 gfx/angle/checkout/src/compiler/translator/SymbolTable.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/SymbolTable.h create mode 100644 gfx/angle/checkout/src/compiler/translator/SymbolTable_ESSL_autogen.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/SymbolTable_autogen.h create mode 100644 gfx/angle/checkout/src/compiler/translator/SymbolUniqueId.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/SymbolUniqueId.h create mode 100644 gfx/angle/checkout/src/compiler/translator/TextureFunctionHLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/TextureFunctionHLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/TranslatorESSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/TranslatorESSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/TranslatorGLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/TranslatorGLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/TranslatorHLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/TranslatorHLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/TranslatorMetal.h create mode 100644 gfx/angle/checkout/src/compiler/translator/TranslatorMetalDirect.h create mode 100644 gfx/angle/checkout/src/compiler/translator/TranslatorVulkan.h create mode 100644 gfx/angle/checkout/src/compiler/translator/Types.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/Types.h create mode 100644 gfx/angle/checkout/src/compiler/translator/UtilsHLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/UtilsHLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateAST.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateAST.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateBarrierFunctionCall.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateBarrierFunctionCall.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateClipCullDistance.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateClipCullDistance.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateGlobalInitializer.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateGlobalInitializer.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateLimitations.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateLimitations.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateMaxParameters.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateMaxParameters.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateOutputs.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateOutputs.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateSwitch.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateSwitch.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateTypeSizeLimitations.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateTypeSizeLimitations.h create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateVaryingLocations.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/ValidateVaryingLocations.h create mode 100644 gfx/angle/checkout/src/compiler/translator/VariablePacker.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/VariablePacker.h create mode 100644 gfx/angle/checkout/src/compiler/translator/VersionGLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/VersionGLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/blocklayout.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/blocklayout.h create mode 100644 gfx/angle/checkout/src/compiler/translator/blocklayoutHLSL.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/blocklayoutHLSL.h create mode 100644 gfx/angle/checkout/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/glslang.h create mode 100644 gfx/angle/checkout/src/compiler/translator/glslang_lex_autogen.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/glslang_tab_autogen.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/glslang_tab_autogen.h create mode 100644 gfx/angle/checkout/src/compiler/translator/glslang_wrapper.h create mode 100644 gfx/angle/checkout/src/compiler/translator/length_limits.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/ClampIndirectIndices.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/ClampIndirectIndices.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/ClampPointSize.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/ClampPointSize.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/ConvertUnsupportedConstructorsToFunctionCalls.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/ConvertUnsupportedConstructorsToFunctionCalls.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/DeferGlobalInitializers.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/FoldExpressions.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/FoldExpressions.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/ForcePrecisionQualifier.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/ForcePrecisionQualifier.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/InitializeVariables.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/InitializeVariables.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/NameNamelessUniformBuffers.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/NameNamelessUniformBuffers.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/PruneEmptyCases.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/PruneEmptyCases.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/PruneNoOps.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/PruneNoOps.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RecordConstantPrecision.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RecordConstantPrecision.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveArrayLengthMethod.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveArrayLengthMethod.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveAtomicCounterBuiltins.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveAtomicCounterBuiltins.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveDynamicIndexing.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveDynamicIndexing.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInvariantDeclaration.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInvariantDeclaration.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveUnreferencedVariables.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveUnreferencedVariables.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteAtomicCounters.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteAtomicCounters.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteCubeMapSamplersAs2DArray.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteCubeMapSamplersAs2DArray.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteDfdy.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteDfdy.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RewritePixelLocalStorage.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RewritePixelLocalStorage.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteStructSamplers.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteStructSamplers.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteTexelFetchOffset.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteTexelFetchOffset.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateDeclarations.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateDeclarations.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/SimplifyLoopConditions.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/SimplifyLoopConditions.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/SplitSequenceOperator.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/SplitSequenceOperator.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/apple/AddAndTrueToLoopCondition.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/apple/AddAndTrueToLoopCondition.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteDoWhile.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteDoWhile.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteUnaryMinusOperatorFloat.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteUnaryMinusOperatorFloat.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AddDefaultReturnStatements.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AddDefaultReturnStatements.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignArraysInSSBOs.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignArraysInSSBOs.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ArrayReturnValueToOutParameter.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ArrayReturnValueToOutParameter.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/BreakVariableAliasingInInnerLoops.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/BreakVariableAliasingInInnerLoops.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ExpandIntegerPowExpressions.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ExpandIntegerPowExpressions.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RecordUniformBlocksWithLargeArrayMember.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RecordUniformBlocksWithLargeArrayMember.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RemoveSwitchFallThrough.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RemoveSwitchFallThrough.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteAtomicFunctionExpressions.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteAtomicFunctionExpressions.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteElseBlocks.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteElseBlocks.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteExpressionsWithShaderStorageBlock.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteExpressionsWithShaderStorageBlock.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteUnaryMinusOperatorInt.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteUnaryMinusOperatorInt.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayConstructorStatements.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayConstructorStatements.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayInitialization.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayInitialization.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateExpressionsReturningArrays.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateExpressionsReturningArrays.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/UnfoldShortCircuitToIf.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/UnfoldShortCircuitToIf.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/WrapSwitchStatementsInBlocks.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/WrapSwitchStatementsInBlocks.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/gl/ClampFragDepth.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/gl/ClampFragDepth.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RegenerateStructNames.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RegenerateStructNames.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RewriteRepeatedAssignToSwizzled.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RewriteRepeatedAssignToSwizzled.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/gl/UseInterfaceBlockFields.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/gl/UseInterfaceBlockFields.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/AsNode.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/BuiltIn.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/BuiltIn_ESSL_autogen.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/BuiltIn_complete_autogen.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/DriverUniform.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/DriverUniform.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/FindFunction.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/FindFunction.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/FindMain.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/FindMain.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/FindPreciseNodes.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/FindPreciseNodes.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/FindSymbolNode.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/FindSymbolNode.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/IntermNodePatternMatcher.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/IntermNodePatternMatcher.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/IntermNode_util.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/IntermNode_util.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/IntermRebuild.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/IntermRebuild.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/NodeSearch.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/NodeType.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceClipCullDistanceVariable.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceClipCullDistanceVariable.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceShadowingVariables.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceShadowingVariables.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/RewriteSampleMaskVariable.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/RewriteSampleMaskVariable.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheBeginningOfShader.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheBeginningOfShader.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheEndOfShader.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheEndOfShader.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/SpecializationConstant.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/SpecializationConstant.h create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/Visit.h create mode 100644 gfx/angle/checkout/src/compiler/translator/util.cpp create mode 100644 gfx/angle/checkout/src/compiler/translator/util.h (limited to 'gfx/angle/checkout/src/compiler/translator') diff --git a/gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.cpp new file mode 100644 index 0000000000..69b50c5d7d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.cpp @@ -0,0 +1,445 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Analysis of the AST needed for HLSL generation + +#include "compiler/translator/ASTMetadataHLSL.h" + +#include "compiler/translator/CallDAG.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +// Class used to traverse the AST of a function definition, checking if the +// function uses a gradient, and writing the set of control flow using gradients. +// It assumes that the analysis has already been made for the function's +// callees. +class PullGradient : public TIntermTraverser +{ + public: + PullGradient(MetadataList *metadataList, size_t index, const CallDAG &dag) + : TIntermTraverser(true, false, true), + mMetadataList(metadataList), + mMetadata(&(*metadataList)[index]), + mIndex(index), + mDag(dag) + { + ASSERT(index < metadataList->size()); + + // ESSL 100 builtin gradient functions + mGradientBuiltinFunctions.insert(ImmutableString("texture2D")); + mGradientBuiltinFunctions.insert(ImmutableString("texture2DProj")); + mGradientBuiltinFunctions.insert(ImmutableString("textureCube")); + + // ESSL 300 builtin gradient functions + mGradientBuiltinFunctions.insert(ImmutableString("dFdx")); + mGradientBuiltinFunctions.insert(ImmutableString("dFdy")); + mGradientBuiltinFunctions.insert(ImmutableString("fwidth")); + mGradientBuiltinFunctions.insert(ImmutableString("texture")); + mGradientBuiltinFunctions.insert(ImmutableString("textureProj")); + mGradientBuiltinFunctions.insert(ImmutableString("textureOffset")); + mGradientBuiltinFunctions.insert(ImmutableString("textureProjOffset")); + + // ESSL 310 doesn't add builtin gradient functions + } + + void traverse(TIntermFunctionDefinition *node) + { + node->traverse(this); + ASSERT(mParents.empty()); + } + + // Called when a gradient operation or a call to a function using a gradient is found. + void onGradient() + { + mMetadata->mUsesGradient = true; + // Mark the latest control flow as using a gradient. + if (!mParents.empty()) + { + mMetadata->mControlFlowsContainingGradient.insert(mParents.back()); + } + } + + void visitControlFlow(Visit visit, TIntermNode *node) + { + if (visit == PreVisit) + { + mParents.push_back(node); + } + else if (visit == PostVisit) + { + ASSERT(mParents.back() == node); + mParents.pop_back(); + // A control flow's using a gradient means its parents are too. + if (mMetadata->mControlFlowsContainingGradient.count(node) > 0 && !mParents.empty()) + { + mMetadata->mControlFlowsContainingGradient.insert(mParents.back()); + } + } + } + + bool visitLoop(Visit visit, TIntermLoop *loop) override + { + visitControlFlow(visit, loop); + return true; + } + + bool visitIfElse(Visit visit, TIntermIfElse *ifElse) override + { + visitControlFlow(visit, ifElse); + return true; + } + + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + if (visit == PreVisit) + { + if (node->getOp() == EOpCallFunctionInAST) + { + size_t calleeIndex = mDag.findIndex(node->getFunction()->uniqueId()); + ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex); + + if ((*mMetadataList)[calleeIndex].mUsesGradient) + { + onGradient(); + } + } + else if (BuiltInGroup::IsBuiltIn(node->getOp()) && !BuiltInGroup::IsMath(node->getOp())) + { + if (mGradientBuiltinFunctions.find(node->getFunction()->name()) != + mGradientBuiltinFunctions.end()) + { + onGradient(); + } + } + } + + return true; + } + + private: + MetadataList *mMetadataList; + ASTMetadataHLSL *mMetadata; + size_t mIndex; + const CallDAG &mDag; + + // Contains a stack of the control flow nodes that are parents of the node being + // currently visited. It is used to mark control flows using a gradient. + std::vector mParents; + + // A list of builtin functions that use gradients + std::set mGradientBuiltinFunctions; +}; + +// Traverses the AST of a function definition to compute the the discontinuous loops +// and the if statements containing gradient loops. It assumes that the gradient loops +// (loops that contain a gradient) have already been computed and that it has already +// traversed the current function's callees. +class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser +{ + public: + PullComputeDiscontinuousAndGradientLoops(MetadataList *metadataList, + size_t index, + const CallDAG &dag) + : TIntermTraverser(true, false, true), + mMetadataList(metadataList), + mMetadata(&(*metadataList)[index]), + mIndex(index), + mDag(dag) + {} + + void traverse(TIntermFunctionDefinition *node) + { + node->traverse(this); + ASSERT(mLoopsAndSwitches.empty()); + ASSERT(mIfs.empty()); + } + + // Called when traversing a gradient loop or a call to a function with a + // gradient loop in its call graph. + void onGradientLoop() + { + mMetadata->mHasGradientLoopInCallGraph = true; + // Mark the latest if as using a discontinuous loop. + if (!mIfs.empty()) + { + mMetadata->mIfsContainingGradientLoop.insert(mIfs.back()); + } + } + + bool visitLoop(Visit visit, TIntermLoop *loop) override + { + if (visit == PreVisit) + { + mLoopsAndSwitches.push_back(loop); + + if (mMetadata->hasGradientInCallGraph(loop)) + { + onGradientLoop(); + } + } + else if (visit == PostVisit) + { + ASSERT(mLoopsAndSwitches.back() == loop); + mLoopsAndSwitches.pop_back(); + } + + return true; + } + + bool visitIfElse(Visit visit, TIntermIfElse *node) override + { + if (visit == PreVisit) + { + mIfs.push_back(node); + } + else if (visit == PostVisit) + { + ASSERT(mIfs.back() == node); + mIfs.pop_back(); + // An if using a discontinuous loop means its parents ifs are also discontinuous. + if (mMetadata->mIfsContainingGradientLoop.count(node) > 0 && !mIfs.empty()) + { + mMetadata->mIfsContainingGradientLoop.insert(mIfs.back()); + } + } + + return true; + } + + bool visitBranch(Visit visit, TIntermBranch *node) override + { + if (visit == PreVisit) + { + switch (node->getFlowOp()) + { + case EOpBreak: + { + ASSERT(!mLoopsAndSwitches.empty()); + TIntermLoop *loop = mLoopsAndSwitches.back()->getAsLoopNode(); + if (loop != nullptr) + { + mMetadata->mDiscontinuousLoops.insert(loop); + } + } + break; + case EOpContinue: + { + ASSERT(!mLoopsAndSwitches.empty()); + TIntermLoop *loop = nullptr; + size_t i = mLoopsAndSwitches.size(); + while (loop == nullptr && i > 0) + { + --i; + loop = mLoopsAndSwitches.at(i)->getAsLoopNode(); + } + ASSERT(loop != nullptr); + mMetadata->mDiscontinuousLoops.insert(loop); + } + break; + case EOpKill: + case EOpReturn: + // A return or discard jumps out of all the enclosing loops + if (!mLoopsAndSwitches.empty()) + { + for (TIntermNode *intermNode : mLoopsAndSwitches) + { + TIntermLoop *loop = intermNode->getAsLoopNode(); + if (loop) + { + mMetadata->mDiscontinuousLoops.insert(loop); + } + } + } + break; + default: + UNREACHABLE(); + } + } + + return true; + } + + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + if (visit == PreVisit && node->getOp() == EOpCallFunctionInAST) + { + size_t calleeIndex = mDag.findIndex(node->getFunction()->uniqueId()); + ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex); + + if ((*mMetadataList)[calleeIndex].mHasGradientLoopInCallGraph) + { + onGradientLoop(); + } + } + + return true; + } + + bool visitSwitch(Visit visit, TIntermSwitch *node) override + { + if (visit == PreVisit) + { + mLoopsAndSwitches.push_back(node); + } + else if (visit == PostVisit) + { + ASSERT(mLoopsAndSwitches.back() == node); + mLoopsAndSwitches.pop_back(); + } + return true; + } + + private: + MetadataList *mMetadataList; + ASTMetadataHLSL *mMetadata; + size_t mIndex; + const CallDAG &mDag; + + std::vector mLoopsAndSwitches; + std::vector mIfs; +}; + +// Tags all the functions called in a discontinuous loop +class PushDiscontinuousLoops : public TIntermTraverser +{ + public: + PushDiscontinuousLoops(MetadataList *metadataList, size_t index, const CallDAG &dag) + : TIntermTraverser(true, true, true), + mMetadataList(metadataList), + mMetadata(&(*metadataList)[index]), + mIndex(index), + mDag(dag), + mNestedDiscont(mMetadata->mCalledInDiscontinuousLoop ? 1 : 0) + {} + + void traverse(TIntermFunctionDefinition *node) + { + node->traverse(this); + ASSERT(mNestedDiscont == (mMetadata->mCalledInDiscontinuousLoop ? 1 : 0)); + } + + bool visitLoop(Visit visit, TIntermLoop *loop) override + { + bool isDiscontinuous = mMetadata->mDiscontinuousLoops.count(loop) > 0; + + if (visit == PreVisit && isDiscontinuous) + { + mNestedDiscont++; + } + else if (visit == PostVisit && isDiscontinuous) + { + mNestedDiscont--; + } + + return true; + } + + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + switch (node->getOp()) + { + case EOpCallFunctionInAST: + if (visit == PreVisit && mNestedDiscont > 0) + { + size_t calleeIndex = mDag.findIndex(node->getFunction()->uniqueId()); + ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex); + + (*mMetadataList)[calleeIndex].mCalledInDiscontinuousLoop = true; + } + break; + default: + break; + } + return true; + } + + private: + MetadataList *mMetadataList; + ASTMetadataHLSL *mMetadata; + size_t mIndex; + const CallDAG &mDag; + + int mNestedDiscont; +}; +} // namespace + +bool ASTMetadataHLSL::hasGradientInCallGraph(TIntermLoop *node) +{ + return mControlFlowsContainingGradient.count(node) > 0; +} + +bool ASTMetadataHLSL::hasGradientLoop(TIntermIfElse *node) +{ + return mIfsContainingGradientLoop.count(node) > 0; +} + +MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag) +{ + MetadataList metadataList(callDag.size()); + + // Compute all the information related to when gradient operations are used. + // We want to know for each function and control flow operation if they have + // a gradient operation in their call graph (shortened to "using a gradient" + // in the rest of the file). + // + // This computation is logically split in three steps: + // 1 - For each function compute if it uses a gradient in its body, ignoring + // calls to other user-defined functions. + // 2 - For each function determine if it uses a gradient in its call graph, + // using the result of step 1 and the CallDAG to know its callees. + // 3 - For each control flow statement of each function, check if it uses a + // gradient in the function's body, or if it calls a user-defined function that + // uses a gradient. + // + // We take advantage of the call graph being a DAG and instead compute 1, 2 and 3 + // for leaves first, then going down the tree. This is correct because 1 doesn't + // depend on other functions, and 2 and 3 depend only on callees. + for (size_t i = 0; i < callDag.size(); i++) + { + PullGradient pull(&metadataList, i, callDag); + pull.traverse(callDag.getRecordFromIndex(i).node); + } + + // Compute which loops are discontinuous and which function are called in + // these loops. The same way computing gradient usage is a "pull" process, + // computing "bing used in a discont. loop" is a push process. However we also + // need to know what ifs have a discontinuous loop inside so we do the same type + // of callgraph analysis as for the gradient. + + // First compute which loops are discontinuous (no specific order) and pull + // the ifs and functions using a gradient loop. + for (size_t i = 0; i < callDag.size(); i++) + { + PullComputeDiscontinuousAndGradientLoops pull(&metadataList, i, callDag); + pull.traverse(callDag.getRecordFromIndex(i).node); + } + + // Then push the information to callees, either from the a local discontinuous + // loop or from the caller being called in a discontinuous loop already + for (size_t i = callDag.size(); i-- > 0;) + { + PushDiscontinuousLoops push(&metadataList, i, callDag); + push.traverse(callDag.getRecordFromIndex(i).node); + } + + // We create "Lod0" version of functions with the gradient operations replaced + // by non-gradient operations so that the D3D compiler is happier with discont + // loops. + for (auto &metadata : metadataList) + { + metadata.mNeedsLod0 = metadata.mCalledInDiscontinuousLoop && metadata.mUsesGradient; + } + + return metadataList; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.h b/gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.h new file mode 100644 index 0000000000..8278f9fafe --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.h @@ -0,0 +1,62 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Defines analyses of the AST needed for HLSL generation + +#ifndef COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_ +#define COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_ + +#include +#include + +namespace sh +{ + +class CallDAG; +class TIntermNode; +class TIntermIfElse; +class TIntermLoop; + +struct ASTMetadataHLSL +{ + ASTMetadataHLSL() + : mUsesGradient(false), + mCalledInDiscontinuousLoop(false), + mHasGradientLoopInCallGraph(false), + mNeedsLod0(false) + {} + + // Here "something uses a gradient" means here that it either contains a + // gradient operation, or a call to a function that uses a gradient. + bool hasGradientInCallGraph(TIntermLoop *node); + bool hasGradientLoop(TIntermIfElse *node); + + // Does the function use a gradient. + bool mUsesGradient; + + // Even if usesGradient is true, some control flow might not use a gradient + // so we store the set of all gradient-using control flows. + std::set mControlFlowsContainingGradient; + + // Remember information about the discontinuous loops and which functions + // are called in such loops. + bool mCalledInDiscontinuousLoop; + bool mHasGradientLoopInCallGraph; + std::set mDiscontinuousLoops; + std::set mIfsContainingGradientLoop; + + // Will we need to generate a Lod0 version of the function. + bool mNeedsLod0; +}; + +typedef std::vector MetadataList; + +// Return the AST analysis result, in the order defined by the call DAG +MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/AtomicCounterFunctionHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/AtomicCounterFunctionHLSL.cpp new file mode 100644 index 0000000000..b900bc4d81 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/AtomicCounterFunctionHLSL.cpp @@ -0,0 +1,112 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// AtomicCounterFunctionHLSL: Class for writing implementation of atomic counter functions into HLSL +// output. +// + +#include "compiler/translator/AtomicCounterFunctionHLSL.h" + +#include "compiler/translator/Common.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/IntermNode.h" + +namespace sh +{ + +namespace +{ +constexpr ImmutableString kAtomicCounter("atomicCounter"); +constexpr ImmutableString kAtomicCounterIncrement("atomicCounterIncrement"); +constexpr ImmutableString kAtomicCounterDecrement("atomicCounterDecrement"); +constexpr ImmutableString kAtomicCounterBaseName("_acbase_"); +} // namespace + +AtomicCounterFunctionHLSL::AtomicCounterFunctionHLSL(bool forceResolution) + : mForceResolution(forceResolution) +{} + +ImmutableString AtomicCounterFunctionHLSL::useAtomicCounterFunction(const ImmutableString &name) +{ + // The largest string that will be create created is "_acbase_increment" or "_acbase_decrement" + ImmutableStringBuilder hlslFunctionNameSB(kAtomicCounterBaseName.length() + + strlen("increment")); + hlslFunctionNameSB << kAtomicCounterBaseName; + + AtomicCounterFunction atomicMethod; + if (kAtomicCounter == name) + { + atomicMethod = AtomicCounterFunction::LOAD; + hlslFunctionNameSB << "load"; + } + else if (kAtomicCounterIncrement == name) + { + atomicMethod = AtomicCounterFunction::INCREMENT; + hlslFunctionNameSB << "increment"; + } + else if (kAtomicCounterDecrement == name) + { + atomicMethod = AtomicCounterFunction::DECREMENT; + hlslFunctionNameSB << "decrement"; + } + else + { + atomicMethod = AtomicCounterFunction::INVALID; + UNREACHABLE(); + } + + ImmutableString hlslFunctionName(hlslFunctionNameSB); + mAtomicCounterFunctions[hlslFunctionName] = atomicMethod; + + return hlslFunctionName; +} + +void AtomicCounterFunctionHLSL::atomicCounterFunctionHeader(TInfoSinkBase &out) +{ + for (auto &atomicFunction : mAtomicCounterFunctions) + { + out << "uint " << atomicFunction.first + << "(in RWByteAddressBuffer counter, int address)\n" + "{\n" + " uint ret;\n"; + + switch (atomicFunction.second) + { + case AtomicCounterFunction::INCREMENT: + out << " counter.InterlockedAdd(address, 1u, ret);\n"; + break; + case AtomicCounterFunction::DECREMENT: + out << " counter.InterlockedAdd(address, 0u - 1u, ret);\n" + " ret -= 1u;\n"; // atomicCounterDecrement is a post-decrement op + break; + case AtomicCounterFunction::LOAD: + out << " ret = counter.Load(address);\n"; + break; + default: + UNREACHABLE(); + break; + } + + if (mForceResolution && atomicFunction.second != AtomicCounterFunction::LOAD) + { + out << " if (ret == 0) {\n" + " ret = 0 - ret;\n" + " }\n"; + } + + out << " return ret;\n" + "}\n\n"; + } +} + +ImmutableString getAtomicCounterNameForBinding(int binding) +{ + std::stringstream counterName = sh::InitializeStream(); + counterName << kAtomicCounterBaseName << binding; + return ImmutableString(counterName.str()); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/AtomicCounterFunctionHLSL.h b/gfx/angle/checkout/src/compiler/translator/AtomicCounterFunctionHLSL.h new file mode 100644 index 0000000000..669e567476 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/AtomicCounterFunctionHLSL.h @@ -0,0 +1,50 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// AtomicCounterFunctionHLSL: Class for writing implementation of atomic counter functions into HLSL +// output. +// + +#ifndef COMPILER_TRANSLATOR_ATOMICCOUNTERFUNCTIONHLSL_H_ +#define COMPILER_TRANSLATOR_ATOMICCOUNTERFUNCTIONHLSL_H_ + +#include + +#include "compiler/translator/Common.h" +#include "compiler/translator/ImmutableString.h" + +namespace sh +{ + +class TInfoSinkBase; +struct TLayoutQualifier; + +class AtomicCounterFunctionHLSL final : angle::NonCopyable +{ + public: + AtomicCounterFunctionHLSL(bool forceResolution); + + ImmutableString useAtomicCounterFunction(const ImmutableString &name); + + void atomicCounterFunctionHeader(TInfoSinkBase &out); + + private: + enum class AtomicCounterFunction + { + LOAD, + INCREMENT, + DECREMENT, + INVALID + }; + + std::map mAtomicCounterFunctions; + bool mForceResolution; +}; + +ImmutableString getAtomicCounterNameForBinding(int binding); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_ATOMICCOUNTERFUNCTIONHLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/BaseTypes.cpp b/gfx/angle/checkout/src/compiler/translator/BaseTypes.cpp new file mode 100644 index 0000000000..15a3ebebc8 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/BaseTypes.cpp @@ -0,0 +1,64 @@ +// +// Copyright 2022 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "BaseTypes.h" + +#include "common/PackedEnums.h" + +namespace sh +{ +namespace +{ +constexpr gl::BlendEquationBitSet kAdvancedBlendBits{ + gl::BlendEquationType::Multiply, gl::BlendEquationType::Screen, + gl::BlendEquationType::Overlay, gl::BlendEquationType::Darken, + gl::BlendEquationType::Lighten, gl::BlendEquationType::Colordodge, + gl::BlendEquationType::Colorburn, gl::BlendEquationType::Hardlight, + gl::BlendEquationType::Softlight, gl::BlendEquationType::Difference, + gl::BlendEquationType::Exclusion, gl::BlendEquationType::HslHue, + gl::BlendEquationType::HslSaturation, gl::BlendEquationType::HslColor, + gl::BlendEquationType::HslLuminosity, +}; + +constexpr gl::BlendEquationBitSet kAdvancedBlendHslBits{ + gl::BlendEquationType::HslHue, + gl::BlendEquationType::HslSaturation, + gl::BlendEquationType::HslColor, + gl::BlendEquationType::HslLuminosity, +}; + +bool IsValidAdvancedBlendBitSet(uint32_t enabledEquations) +{ + return (gl::BlendEquationBitSet(enabledEquations) & ~kAdvancedBlendBits).none(); +} +} // anonymous namespace + +bool AdvancedBlendEquations::any() const +{ + ASSERT(IsValidAdvancedBlendBitSet(mEnabledBlendEquations)); + return mEnabledBlendEquations != 0; +} + +bool AdvancedBlendEquations::anyHsl() const +{ + ASSERT(IsValidAdvancedBlendBitSet(mEnabledBlendEquations)); + return (gl::BlendEquationBitSet(mEnabledBlendEquations) & kAdvancedBlendHslBits).any(); +} + +void AdvancedBlendEquations::setAll() +{ + ASSERT(IsValidAdvancedBlendBitSet(mEnabledBlendEquations)); + mEnabledBlendEquations = kAdvancedBlendBits.bits(); +} + +void AdvancedBlendEquations::set(uint32_t blendEquation) +{ + gl::BlendEquationType eq = static_cast(blendEquation); + mEnabledBlendEquations = gl::BlendEquationBitSet(mEnabledBlendEquations).set(eq).bits(); + ASSERT(IsValidAdvancedBlendBitSet(mEnabledBlendEquations)); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/BaseTypes.h b/gfx/angle/checkout/src/compiler/translator/BaseTypes.h new file mode 100644 index 0000000000..7e569f4e9d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/BaseTypes.h @@ -0,0 +1,1782 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_BASETYPES_H_ +#define COMPILER_TRANSLATOR_BASETYPES_H_ + +#include +#include + +#include "GLSLANG/ShaderLang.h" +#include "common/debug.h" +#include "compiler/translator/ImmutableString.h" + +namespace sh +{ + +// +// Precision qualifiers +// +enum TPrecision +{ + // These need to be kept sorted + EbpUndefined, + EbpLow, + EbpMedium, + EbpHigh, + + // end of list + EbpLast +}; + +inline const char *getPrecisionString(TPrecision p) +{ + switch (p) + { + case EbpHigh: + return "highp"; + case EbpMedium: + return "mediump"; + case EbpLow: + return "lowp"; + default: + return "mediump"; // Safest fallback + } +} + +// +// Basic type. Arrays, vectors, etc., are orthogonal to this. +// +enum TBasicType +{ + EbtVoid, + EbtFloat, + EbtDouble, + EbtInt, + EbtUInt, + EbtBool, + + EbtAtomicCounter, + EbtYuvCscStandardEXT, // Only valid if EXT_YUV_target exists. + + EbtGuardSamplerBegin, // non type: see implementation of IsSampler() + EbtSampler2D = EbtGuardSamplerBegin, + EbtSampler3D, + EbtSamplerCube, + EbtSampler2DArray, + EbtSamplerExternalOES, // Only valid if OES_EGL_image_external exists. + EbtSamplerExternal2DY2YEXT, // Only valid if GL_EXT_YUV_target exists. + EbtSampler2DRect, // Only valid if GL_ARB_texture_rectangle exists. + EbtSampler2DMS, + EbtSampler2DMSArray, + EbtISampler2D, + EbtISampler3D, + EbtISamplerCube, + EbtISampler2DArray, + EbtISampler2DMS, + EbtISampler2DMSArray, + EbtUSampler2D, + EbtUSampler3D, + EbtUSamplerCube, + EbtUSampler2DArray, + EbtUSampler2DMS, + EbtUSampler2DMSArray, + EbtSampler2DShadow, + EbtSamplerCubeShadow, + EbtSampler2DArrayShadow, + EbtSampler1D, // Desktop GLSL sampler types + EbtSampler1DArray, + EbtSampler1DArrayShadow, + EbtSamplerBuffer, + EbtSamplerCubeArray, + EbtSamplerCubeArrayShadow, + EbtSampler1DShadow, + EbtSampler2DRectShadow, + EbtISampler1D, + EbtISampler1DArray, + EbtISampler2DRect, + EbtISamplerBuffer, + EbtISamplerCubeArray, + EbtUSampler1D, + EbtUSampler1DArray, + EbtUSampler2DRect, + EbtUSamplerBuffer, + EbtUSamplerCubeArray, + EbtSamplerVideoWEBGL, + EbtGuardSamplerEnd = EbtSamplerVideoWEBGL, // non type: see implementation of IsSampler() + + // images + EbtGuardImageBegin, + EbtImage2D = EbtGuardImageBegin, + EbtImage3D, + EbtImage2DArray, + EbtImageCube, + EbtImage1D, + EbtImage1DArray, + EbtImage2DMS, + EbtImage2DMSArray, + EbtImageCubeArray, + EbtImageRect, + EbtImageBuffer, + EbtIImage2D, + EbtIImage3D, + EbtIImage2DArray, + EbtIImageCube, + EbtIImage1D, + EbtIImage1DArray, + EbtIImage2DMS, + EbtIImage2DMSArray, + EbtIImageCubeArray, + EbtIImageRect, + EbtIImageBuffer, + EbtGuardUIntImageBegin, + EbtUImage2D = EbtGuardUIntImageBegin, + EbtUImage3D, + EbtUImage2DArray, + EbtUImageCube, + EbtUImage1D, + EbtUImage1DArray, + EbtUImage2DMS, + EbtUImage2DMSArray, + EbtUImageCubeArray, + EbtUImageRect, + EbtUImageBuffer, + EbtGuardUIntImageEnd = EbtUImageBuffer, + EbtGuardImageEnd = EbtGuardUIntImageEnd, + + // ANGLE_shader_pixel_local_storage + EbtGuardPixelLocalBegin, + EbtPixelLocalANGLE = EbtGuardPixelLocalBegin, + EbtIPixelLocalANGLE, + EbtUPixelLocalANGLE, + EbtGuardPixelLocalEnd = EbtUPixelLocalANGLE, + + // Subpass Input + EbtGuardSubpassInputBegin, + EbtSubpassInput = EbtGuardSubpassInputBegin, + EbtISubpassInput, + EbtUSubpassInput, + EbtSubpassInputMS, + EbtISubpassInputMS, + EbtUSubpassInputMS, + EbtGuardSubpassInputEnd = EbtUSubpassInputMS, + + EbtLastSimpleType = EbtGuardSubpassInputEnd, + + EbtStruct, + EbtInterfaceBlock, + + // end of list + EbtLast = EbtInterfaceBlock +}; + +class TBasicMangledName +{ + public: + constexpr TBasicMangledName(TBasicType t) : mName{'\0', '\0'} + { + if (t > EbtLastSimpleType) + { + mName[0] = '{'; + mName[1] = '\0'; + } + else if (t < 26) + { + mName[0] = '0'; + mName[1] = static_cast('A' + t); + } + else if (t < 52) + { + mName[0] = '0'; + mName[1] = static_cast('a' - 26 + t); + } + else if (t < 78) + { + mName[0] = '1'; + mName[1] = static_cast('A' - 52 + t); + } + else if (t < 104) + { + mName[0] = '1'; + mName[1] = static_cast('a' - 78 + t); + } + } + + constexpr char *getName() { return mName; } + + static constexpr int mangledNameSize = 2; + + private: + char mName[mangledNameSize]; +}; + +const char *getBasicString(TBasicType t); + +inline bool IsSampler(TBasicType type) +{ + return type >= EbtGuardSamplerBegin && type <= EbtGuardSamplerEnd; +} + +inline bool IsImage(TBasicType type) +{ + return type >= EbtGuardImageBegin && type <= EbtGuardImageEnd; +} + +inline bool IsUIntImage(TBasicType type) +{ + return type >= EbtGuardUIntImageBegin && type <= EbtGuardUIntImageEnd; +} + +inline bool IsAtomicCounter(TBasicType type) +{ + return type == EbtAtomicCounter; +} + +inline bool IsPixelLocal(TBasicType type) +{ + return type >= EbtGuardPixelLocalBegin && type <= EbtGuardPixelLocalEnd; +} + +inline bool IsSubpassInputType(TBasicType type) +{ + return type >= EbtGuardSubpassInputBegin && type <= EbtGuardSubpassInputEnd; +} + +inline bool IsOpaqueType(TBasicType type) +{ + return IsSampler(type) || IsImage(type) || IsAtomicCounter(type) || IsPixelLocal(type) || + IsSubpassInputType(type); +} + +inline bool IsIntegerSampler(TBasicType type) +{ + switch (type) + { + case EbtISampler2D: + case EbtISampler3D: + case EbtISamplerCube: + case EbtISampler2DArray: + case EbtISampler2DMS: + case EbtISampler2DMSArray: + case EbtUSampler2D: + case EbtUSampler3D: + case EbtUSamplerCube: + case EbtUSampler2DArray: + case EbtUSampler2DMS: + case EbtUSampler2DMSArray: + case EbtISampler1D: + case EbtISampler1DArray: + case EbtISampler2DRect: + case EbtISamplerBuffer: + case EbtISamplerCubeArray: + case EbtUSampler1D: + case EbtUSampler1DArray: + case EbtUSampler2DRect: + case EbtUSamplerBuffer: + case EbtUSamplerCubeArray: + return true; + case EbtSampler2D: + case EbtSampler3D: + case EbtSamplerCube: + case EbtSamplerExternalOES: + case EbtSamplerExternal2DY2YEXT: + case EbtSampler2DRect: + case EbtSampler2DArray: + case EbtSampler2DShadow: + case EbtSamplerCubeShadow: + case EbtSampler2DArrayShadow: + case EbtSampler2DMS: + case EbtSampler2DMSArray: + case EbtSampler1D: + case EbtSampler1DArray: + case EbtSampler1DArrayShadow: + case EbtSamplerBuffer: + case EbtSamplerCubeArray: + case EbtSamplerCubeArrayShadow: + case EbtSampler1DShadow: + case EbtSampler2DRectShadow: + case EbtSamplerVideoWEBGL: + return false; + default: + ASSERT(!IsSampler(type)); + } + + return false; +} + +inline bool IsIntegerSamplerUnsigned(TBasicType type) +{ + switch (type) + { + case EbtISampler2D: + case EbtISampler3D: + case EbtISamplerCube: + case EbtISampler2DArray: + case EbtISampler2DMS: + case EbtISampler2DMSArray: + case EbtISampler1D: + case EbtISampler1DArray: + case EbtISampler2DRect: + case EbtISamplerBuffer: + case EbtISamplerCubeArray: + return false; + case EbtUSampler2D: + case EbtUSampler3D: + case EbtUSamplerCube: + case EbtUSampler2DArray: + case EbtUSampler2DMS: + case EbtUSampler2DMSArray: + case EbtUSampler1D: + case EbtUSampler1DArray: + case EbtUSampler2DRect: + case EbtUSamplerBuffer: + case EbtUSamplerCubeArray: + return true; + default: + ASSERT(!IsIntegerSampler(type)); + } + + return false; +} + +inline bool IsSampler2DMS(TBasicType type) +{ + switch (type) + { + case EbtSampler2DMS: + case EbtISampler2DMS: + case EbtUSampler2DMS: + return true; + default: + return false; + } +} + +inline bool IsSampler2DMSArray(TBasicType type) +{ + switch (type) + { + case EbtSampler2DMSArray: + case EbtISampler2DMSArray: + case EbtUSampler2DMSArray: + return true; + default: + return false; + } +} + +inline bool IsSamplerMS(TBasicType type) +{ + return IsSampler2DMS(type) || IsSampler2DMSArray(type); +} + +inline bool IsImageMS(TBasicType type) +{ + switch (type) + { + case EbtImage2DMS: + case EbtImage2DMSArray: + case EbtIImage2DMS: + case EbtIImage2DMSArray: + case EbtUImage2DMS: + case EbtUImage2DMSArray: + return true; + default: + return false; + } +} + +inline bool IsFloatImage(TBasicType type) +{ + switch (type) + { + case EbtImage1D: + case EbtImage2D: + case EbtImage3D: + case EbtImage1DArray: + case EbtImage2DArray: + case EbtImageCube: + case EbtImage2DMS: + case EbtImage2DMSArray: + case EbtImageCubeArray: + case EbtImageRect: + case EbtImageBuffer: + return true; + default: + break; + } + + return false; +} + +inline bool IsIntegerImage(TBasicType type) +{ + + switch (type) + { + case EbtIImage1D: + case EbtIImage2D: + case EbtIImage3D: + case EbtIImage1DArray: + case EbtIImage2DArray: + case EbtIImageCube: + case EbtIImage2DMS: + case EbtIImage2DMSArray: + case EbtIImageCubeArray: + case EbtIImageRect: + case EbtIImageBuffer: + return true; + default: + break; + } + + return false; +} + +inline bool IsUnsignedImage(TBasicType type) +{ + + switch (type) + { + case EbtUImage1D: + case EbtUImage2D: + case EbtUImage3D: + case EbtUImage1DArray: + case EbtUImage2DArray: + case EbtUImageCube: + case EbtUImage2DMS: + case EbtUImage2DMSArray: + case EbtUImageCubeArray: + case EbtUImageRect: + case EbtUImageBuffer: + return true; + default: + break; + } + + return false; +} + +// Samplers are divided into 4 disjoint categories: 2D, cube, 3D, and array. +// Array samplers are not 2D samplers. +inline bool IsSampler2D(TBasicType type) +{ + switch (type) + { + case EbtSampler2D: + case EbtISampler2D: + case EbtUSampler2D: + case EbtSampler2DRect: + case EbtISampler2DRect: + case EbtUSampler2DRect: + case EbtSampler2DRectShadow: + case EbtSamplerExternalOES: + case EbtSamplerExternal2DY2YEXT: + case EbtSampler2DShadow: + case EbtSampler2DMS: + case EbtISampler2DMS: + case EbtUSampler2DMS: + case EbtSamplerVideoWEBGL: + return true; + case EbtSampler2DArray: + case EbtISampler2DArray: + case EbtUSampler2DArray: + case EbtSampler2DMSArray: + case EbtISampler2DMSArray: + case EbtUSampler2DMSArray: + case EbtSampler2DArrayShadow: + case EbtSampler3D: + case EbtISampler3D: + case EbtUSampler3D: + case EbtISamplerCube: + case EbtUSamplerCube: + case EbtSamplerCube: + case EbtSamplerCubeShadow: + case EbtSampler1D: + case EbtSampler1DArray: + case EbtSampler1DArrayShadow: + case EbtSamplerBuffer: + case EbtSamplerCubeArray: + case EbtSamplerCubeArrayShadow: + case EbtSampler1DShadow: + case EbtISampler1D: + case EbtISampler1DArray: + case EbtISamplerBuffer: + case EbtISamplerCubeArray: + case EbtUSampler1D: + case EbtUSampler1DArray: + case EbtUSamplerBuffer: + case EbtUSamplerCubeArray: + return false; + default: + ASSERT(!IsSampler(type)); + } + + return false; +} + +inline bool IsSamplerCube(TBasicType type) +{ + switch (type) + { + case EbtSamplerCube: + case EbtISamplerCube: + case EbtUSamplerCube: + case EbtSamplerCubeShadow: + return true; + case EbtSampler2D: + case EbtSampler3D: + case EbtSamplerExternalOES: + case EbtSamplerExternal2DY2YEXT: + case EbtSampler2DRect: + case EbtSampler2DArray: + case EbtSampler2DMS: + case EbtSampler2DMSArray: + case EbtISampler2D: + case EbtISampler3D: + case EbtISampler2DArray: + case EbtISampler2DMS: + case EbtISampler2DMSArray: + case EbtUSampler2D: + case EbtUSampler3D: + case EbtUSampler2DArray: + case EbtUSampler2DMS: + case EbtUSampler2DMSArray: + case EbtSampler2DShadow: + case EbtSampler2DArrayShadow: + case EbtSampler1D: + case EbtSampler1DArray: + case EbtSampler1DArrayShadow: + case EbtSamplerBuffer: + case EbtSamplerCubeArray: + case EbtSamplerCubeArrayShadow: + case EbtSampler1DShadow: + case EbtSampler2DRectShadow: + case EbtISampler1D: + case EbtISampler1DArray: + case EbtISampler2DRect: + case EbtISamplerBuffer: + case EbtISamplerCubeArray: + case EbtUSampler1D: + case EbtUSampler1DArray: + case EbtUSampler2DRect: + case EbtUSamplerBuffer: + case EbtUSamplerCubeArray: + case EbtSamplerVideoWEBGL: + return false; + default: + ASSERT(!IsSampler(type)); + } + + return false; +} + +inline bool IsSampler3D(TBasicType type) +{ + switch (type) + { + case EbtSampler3D: + case EbtISampler3D: + case EbtUSampler3D: + return true; + case EbtSampler2D: + case EbtSamplerCube: + case EbtSamplerExternalOES: + case EbtSamplerExternal2DY2YEXT: + case EbtSampler2DRect: + case EbtSampler2DArray: + case EbtSampler2DMS: + case EbtSampler2DMSArray: + case EbtISampler2D: + case EbtISamplerCube: + case EbtISampler2DArray: + case EbtISampler2DMS: + case EbtISampler2DMSArray: + case EbtUSampler2D: + case EbtUSamplerCube: + case EbtUSampler2DArray: + case EbtUSampler2DMS: + case EbtUSampler2DMSArray: + case EbtSampler2DShadow: + case EbtSamplerCubeShadow: + case EbtSampler2DArrayShadow: + case EbtSampler1D: + case EbtSampler1DArray: + case EbtSampler1DArrayShadow: + case EbtSamplerBuffer: + case EbtSamplerCubeArray: + case EbtSamplerCubeArrayShadow: + case EbtSampler1DShadow: + case EbtSampler2DRectShadow: + case EbtISampler1D: + case EbtISampler1DArray: + case EbtISampler2DRect: + case EbtISamplerBuffer: + case EbtISamplerCubeArray: + case EbtUSampler1D: + case EbtUSampler1DArray: + case EbtUSampler2DRect: + case EbtUSamplerBuffer: + case EbtUSamplerCubeArray: + case EbtSamplerVideoWEBGL: + return false; + default: + ASSERT(!IsSampler(type)); + } + + return false; +} + +inline bool IsSamplerArray(TBasicType type) +{ + switch (type) + { + case EbtSampler1DArray: + case EbtISampler1DArray: + case EbtUSampler1DArray: + case EbtSampler1DArrayShadow: + case EbtSampler2DArray: + case EbtISampler2DArray: + case EbtUSampler2DArray: + case EbtSampler2DMSArray: + case EbtISampler2DMSArray: + case EbtUSampler2DMSArray: + case EbtSampler2DArrayShadow: + case EbtSamplerCubeArray: + case EbtISamplerCubeArray: + case EbtUSamplerCubeArray: + case EbtSamplerCubeArrayShadow: + return true; + case EbtSampler2D: + case EbtISampler2D: + case EbtUSampler2D: + case EbtSampler2DRect: + case EbtSamplerExternalOES: + case EbtSamplerExternal2DY2YEXT: + case EbtSampler3D: + case EbtISampler3D: + case EbtUSampler3D: + case EbtISamplerCube: + case EbtUSamplerCube: + case EbtSamplerCube: + case EbtSampler2DShadow: + case EbtSamplerCubeShadow: + case EbtSampler2DMS: + case EbtISampler2DMS: + case EbtUSampler2DMS: + case EbtSampler1D: + case EbtSamplerBuffer: + case EbtSampler1DShadow: + case EbtSampler2DRectShadow: + case EbtISampler1D: + case EbtISampler2DRect: + case EbtISamplerBuffer: + case EbtUSampler1D: + case EbtUSampler2DRect: + case EbtUSamplerBuffer: + case EbtSamplerVideoWEBGL: + return false; + default: + ASSERT(!IsSampler(type)); + } + + return false; +} + +inline bool IsSampler1D(TBasicType type) +{ + switch (type) + { + case EbtSampler1D: + case EbtISampler1D: + case EbtUSampler1D: + case EbtSampler1DShadow: + return true; + case EbtSampler2D: + case EbtSamplerCube: + case EbtSampler3D: + case EbtISampler3D: + case EbtUSampler3D: + case EbtSamplerExternalOES: + case EbtSamplerExternal2DY2YEXT: + case EbtSampler2DRect: + case EbtSampler2DArray: + case EbtSampler2DMS: + case EbtSampler2DMSArray: + case EbtISampler2D: + case EbtISamplerCube: + case EbtISampler2DArray: + case EbtISampler2DMS: + case EbtISampler2DMSArray: + case EbtUSampler2D: + case EbtUSamplerCube: + case EbtUSampler2DArray: + case EbtUSampler2DMS: + case EbtUSampler2DMSArray: + case EbtSampler2DShadow: + case EbtSamplerCubeShadow: + case EbtSampler2DArrayShadow: + case EbtSampler1DArray: + case EbtSampler1DArrayShadow: + case EbtSamplerBuffer: + case EbtSamplerCubeArray: + case EbtSamplerCubeArrayShadow: + case EbtSampler2DRectShadow: + case EbtISampler1DArray: + case EbtISampler2DRect: + case EbtISamplerBuffer: + case EbtISamplerCubeArray: + case EbtUSampler1DArray: + case EbtUSampler2DRect: + case EbtUSamplerBuffer: + case EbtUSamplerCubeArray: + case EbtSamplerVideoWEBGL: + return false; + default: + ASSERT(!IsSampler(type)); + } + + return false; +} + +inline bool IsSamplerBuffer(TBasicType type) +{ + switch (type) + { + case EbtSamplerBuffer: + case EbtISamplerBuffer: + case EbtUSamplerBuffer: + return true; + default: + return false; + } +} + +inline bool IsShadowSampler(TBasicType type) +{ + switch (type) + { + case EbtSampler1DShadow: + case EbtSampler2DShadow: + case EbtSamplerCubeShadow: + case EbtSampler1DArrayShadow: + case EbtSampler2DArrayShadow: + case EbtSamplerCubeArrayShadow: + case EbtSampler2DRectShadow: + return true; + case EbtISampler2D: + case EbtISampler3D: + case EbtISamplerCube: + case EbtISampler2DArray: + case EbtISampler2DMS: + case EbtISampler2DMSArray: + case EbtUSampler2D: + case EbtUSampler3D: + case EbtUSamplerCube: + case EbtUSampler2DArray: + case EbtUSampler2DMS: + case EbtUSampler2DMSArray: + case EbtSampler2D: + case EbtSampler3D: + case EbtSamplerCube: + case EbtSamplerExternalOES: + case EbtSamplerExternal2DY2YEXT: + case EbtSampler2DRect: + case EbtSampler2DArray: + case EbtSampler2DMS: + case EbtSampler2DMSArray: + case EbtSampler1D: + case EbtSampler1DArray: + case EbtSamplerBuffer: + case EbtSamplerCubeArray: + case EbtISampler1D: + case EbtISampler1DArray: + case EbtISampler2DRect: + case EbtISamplerBuffer: + case EbtISamplerCubeArray: + case EbtUSampler1D: + case EbtUSampler1DArray: + case EbtUSampler2DRect: + case EbtUSamplerBuffer: + case EbtUSamplerCubeArray: + case EbtSamplerVideoWEBGL: + return false; + default: + ASSERT(!IsSampler(type)); + } + + return false; +} + +inline bool IsImage2D(TBasicType type) +{ + switch (type) + { + case EbtImage2D: + case EbtIImage2D: + case EbtUImage2D: + case EbtImage2DMS: + case EbtIImage2DMS: + case EbtUImage2DMS: + return true; + case EbtImage3D: + case EbtIImage3D: + case EbtUImage3D: + case EbtImage2DArray: + case EbtIImage2DArray: + case EbtUImage2DArray: + case EbtImageCube: + case EbtIImageCube: + case EbtUImageCube: + case EbtImage1D: + case EbtIImage1D: + case EbtUImage1D: + case EbtImage1DArray: + case EbtIImage1DArray: + case EbtUImage1DArray: + case EbtImage2DMSArray: + case EbtIImage2DMSArray: + case EbtUImage2DMSArray: + case EbtImageCubeArray: + case EbtIImageCubeArray: + case EbtUImageCubeArray: + case EbtImageRect: + case EbtIImageRect: + case EbtUImageRect: + case EbtImageBuffer: + case EbtIImageBuffer: + case EbtUImageBuffer: + return false; + default: + ASSERT(!IsImage(type)); + } + + return false; +} + +inline bool IsImage3D(TBasicType type) +{ + switch (type) + { + case EbtImage3D: + case EbtIImage3D: + case EbtUImage3D: + return true; + case EbtImage2D: + case EbtIImage2D: + case EbtUImage2D: + case EbtImage2DArray: + case EbtIImage2DArray: + case EbtUImage2DArray: + case EbtImageCube: + case EbtIImageCube: + case EbtUImageCube: + case EbtImage1D: + case EbtIImage1D: + case EbtUImage1D: + case EbtImage1DArray: + case EbtIImage1DArray: + case EbtUImage1DArray: + case EbtImage2DMS: + case EbtIImage2DMS: + case EbtUImage2DMS: + case EbtImage2DMSArray: + case EbtIImage2DMSArray: + case EbtUImage2DMSArray: + case EbtImageCubeArray: + case EbtIImageCubeArray: + case EbtUImageCubeArray: + case EbtImageRect: + case EbtIImageRect: + case EbtUImageRect: + case EbtImageBuffer: + case EbtIImageBuffer: + case EbtUImageBuffer: + return false; + default: + ASSERT(!IsImage(type)); + } + + return false; +} + +inline bool IsImage2DArray(TBasicType type) +{ + switch (type) + { + case EbtImage2DArray: + case EbtIImage2DArray: + case EbtUImage2DArray: + case EbtImage2DMSArray: + case EbtIImage2DMSArray: + case EbtUImage2DMSArray: + return true; + case EbtImage2D: + case EbtIImage2D: + case EbtUImage2D: + case EbtImage3D: + case EbtIImage3D: + case EbtUImage3D: + case EbtImageCube: + case EbtIImageCube: + case EbtUImageCube: + case EbtImage1D: + case EbtIImage1D: + case EbtUImage1D: + case EbtImage1DArray: + case EbtIImage1DArray: + case EbtUImage1DArray: + case EbtImage2DMS: + case EbtIImage2DMS: + case EbtUImage2DMS: + case EbtImageCubeArray: + case EbtIImageCubeArray: + case EbtUImageCubeArray: + case EbtImageRect: + case EbtIImageRect: + case EbtUImageRect: + case EbtImageBuffer: + case EbtIImageBuffer: + case EbtUImageBuffer: + return false; + default: + ASSERT(!IsImage(type)); + } + + return false; +} + +inline bool IsImageCube(TBasicType type) +{ + switch (type) + { + case EbtImageCube: + case EbtIImageCube: + case EbtUImageCube: + return true; + case EbtImage2D: + case EbtIImage2D: + case EbtUImage2D: + case EbtImage3D: + case EbtIImage3D: + case EbtUImage3D: + case EbtImage2DArray: + case EbtIImage2DArray: + case EbtUImage2DArray: + case EbtImage1D: + case EbtIImage1D: + case EbtUImage1D: + case EbtImage1DArray: + case EbtIImage1DArray: + case EbtUImage1DArray: + case EbtImage2DMS: + case EbtIImage2DMS: + case EbtUImage2DMS: + case EbtImage2DMSArray: + case EbtIImage2DMSArray: + case EbtUImage2DMSArray: + case EbtImageCubeArray: + case EbtIImageCubeArray: + case EbtUImageCubeArray: + case EbtImageRect: + case EbtIImageRect: + case EbtUImageRect: + case EbtImageBuffer: + case EbtIImageBuffer: + case EbtUImageBuffer: + return false; + default: + ASSERT(!IsImage(type)); + } + + return false; +} + +inline bool IsImageBuffer(TBasicType type) +{ + switch (type) + { + case EbtImageBuffer: + case EbtIImageBuffer: + case EbtUImageBuffer: + return true; + default: + return false; + } +} + +inline bool IsInteger(TBasicType type) +{ + return type == EbtInt || type == EbtUInt; +} + +inline bool SupportsPrecision(TBasicType type) +{ + return type == EbtFloat || type == EbtInt || type == EbtUInt || IsOpaqueType(type); +} + +// +// Qualifiers and built-ins. These are mainly used to see what can be read +// or written, and by the machine dependent translator to know which registers +// to allocate variables in. Since built-ins tend to go to different registers +// than varying or uniform, it makes sense they are peers, not sub-classes. +// +enum TQualifier +{ + EvqTemporary, // For temporaries (within a function), read/write + EvqGlobal, // For globals read/write + EvqConst, // User defined constants + EvqAttribute, // Readonly + EvqVaryingIn, // readonly, fragment shaders only + EvqVaryingOut, // vertex shaders only read/write + EvqUniform, // Readonly, vertex and fragment + EvqBuffer, // read/write, vertex, fragment and compute shader + EvqPatch, // EXT_tessellation_shader storage qualifier + + EvqVertexIn, // Vertex shader input + EvqFragmentOut, // Fragment shader output + EvqVertexOut, // Vertex shader output + EvqFragmentIn, // Fragment shader input + + EvqFragmentInOut, // EXT_shader_framebuffer_fetch qualifier + + // parameters + EvqParamIn, + EvqParamOut, + EvqParamInOut, + EvqParamConst, + + // built-ins read by vertex shader + EvqInstanceID, + EvqVertexID, + + // built-ins written by vertex shader + EvqPosition, + EvqPointSize, + + EvqDrawID, // ANGLE_multi_draw + + // built-ins read by fragment shader + EvqFragCoord, + EvqFrontFacing, + EvqPointCoord, + EvqHelperInvocation, + + // built-ins written by fragment shader + EvqFragColor, + EvqFragData, + EvqFragDepth, // gl_FragDepth for ESSL300, or gl_FragDepthEXT for ESSL100, EXT_frag_depth. + + EvqSecondaryFragColorEXT, // EXT_blend_func_extended + EvqSecondaryFragDataEXT, // EXT_blend_func_extended + + EvqViewIDOVR, // OVR_multiview + EvqViewportIndex, // gl_ViewportIndex + + EvqClipDistance, // APPLE_clip_distance/EXT_clip_cull_distance + EvqCullDistance, // EXT_clip_cull_distance + + // built-ins written by the shader_framebuffer_fetch extension(s) + EvqLastFragColor, + EvqLastFragData, + + // GLSL ES 3.0 vertex output and fragment input + EvqSmooth, // Incomplete qualifier, smooth is the default + EvqFlat, // Incomplete qualifier + EvqNoPerspective, // Incomplete qualifier + EvqCentroid, // Incomplete qualifier + EvqSample, + EvqSmoothOut, + EvqFlatOut, + EvqNoPerspectiveOut, + EvqCentroidOut, // Implies smooth + EvqSampleOut, + EvqSmoothIn, + EvqFlatIn, + EvqNoPerspectiveIn, + EvqCentroidIn, // Implies smooth + EvqSampleIn, + + // GLSL ES 3.0 extension OES_sample_variables + EvqSampleID, + EvqSamplePosition, + EvqSampleMaskIn, + EvqSampleMask, + EvqNumSamples, + + // GLSL ES 3.1 compute shader special variables + EvqShared, + EvqComputeIn, + EvqNumWorkGroups, + EvqWorkGroupSize, + EvqWorkGroupID, + EvqLocalInvocationID, + EvqGlobalInvocationID, + EvqLocalInvocationIndex, + + // GLSL ES 3.1 memory qualifiers + EvqReadOnly, + EvqWriteOnly, + EvqCoherent, + EvqRestrict, + EvqVolatile, + + // GLSL ES 3.1 extension EXT_geometry_shader qualifiers + EvqGeometryIn, + EvqGeometryOut, + EvqPerVertexIn, // gl_in + EvqPrimitiveIDIn, // gl_PrimitiveIDIn + EvqInvocationID, // gl_InvocationID + EvqPrimitiveID, // gl_PrimitiveID + EvqLayerOut, // gl_Layer (GS output) + EvqLayerIn, // gl_Layer (FS input) + + // GLSL ES 3.1 extension EXT_gpu_shader5 qualifiers + EvqPrecise, + + // GLES ES 3.1 extension EXT_tessellation_shader qualifiers + EvqPatchIn, + EvqPatchOut, + + EvqTessControlIn, + EvqTessControlOut, + EvqPerVertexOut, + EvqPatchVerticesIn, + EvqTessLevelOuter, + EvqTessLevelInner, + + // GLES ES 3.1 extension EXT_primitive_bounding_box/OES_primitive_bounding_box + EvqBoundingBox, + + EvqTessEvaluationIn, + EvqTessEvaluationOut, + EvqTessCoord, + + // A specialization constant, which is not valid GLSL ES, but is there to support Vulkan output + // generation. In that case, TLayoutQualifier::location will contain the somewhat equivalent + // constant_id. + EvqSpecConst, + + // end of list + EvqLast +}; + +inline bool IsQualifierUnspecified(TQualifier qualifier) +{ + return (qualifier == EvqTemporary || qualifier == EvqGlobal); +} + +inline bool IsStorageBuffer(TQualifier qualifier) +{ + return qualifier == EvqBuffer; +} + +inline bool IsShaderIn(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqVertexIn: + case EvqTessControlIn: + case EvqTessEvaluationIn: + case EvqGeometryIn: + case EvqFragmentIn: + case EvqPerVertexIn: + case EvqAttribute: + case EvqVaryingIn: + case EvqSmoothIn: + case EvqFlatIn: + case EvqNoPerspectiveIn: + case EvqCentroidIn: + case EvqSampleIn: + case EvqPatchIn: + return true; + default: + return false; + } +} + +inline bool IsShaderOut(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqVertexOut: + case EvqTessControlOut: + case EvqTessEvaluationOut: + case EvqGeometryOut: + case EvqFragmentOut: + case EvqPerVertexOut: + case EvqVaryingOut: + case EvqSmoothOut: + case EvqFlatOut: + case EvqNoPerspectiveOut: + case EvqCentroidOut: + case EvqSampleOut: + case EvqPatchOut: + case EvqFragmentInOut: + return true; + default: + return false; + } +} + +inline bool IsShaderIoBlock(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqPerVertexIn: + case EvqPerVertexOut: + case EvqVertexOut: + case EvqTessControlIn: + case EvqTessControlOut: + case EvqTessEvaluationIn: + case EvqTessEvaluationOut: + case EvqPatchIn: + case EvqPatchOut: + case EvqGeometryIn: + case EvqGeometryOut: + case EvqFragmentIn: + return true; + default: + return false; + } +} + +enum TLayoutImageInternalFormat +{ + EiifUnspecified, + EiifRGBA32F, + EiifRGBA16F, + EiifR32F, + EiifRGBA32UI, + EiifRGBA16UI, + EiifRGBA8UI, + EiifR32UI, + EiifRGBA32I, + EiifRGBA16I, + EiifRGBA8I, + EiifR32I, + EiifRGBA8, + EiifRGBA8_SNORM, + + EiifLast = EiifRGBA8_SNORM, +}; + +enum TLayoutMatrixPacking +{ + EmpUnspecified, + EmpRowMajor, + EmpColumnMajor, + + EmpLast = EmpColumnMajor, +}; + +enum TLayoutBlockStorage +{ + EbsUnspecified, + EbsShared, + EbsPacked, + EbsStd140, + EbsStd430, + + EbsLast = EbsStd430, +}; + +enum TYuvCscStandardEXT +{ + EycsUndefined, + EycsItu601, + EycsItu601FullRange, + EycsItu709 +}; + +enum TLayoutPrimitiveType +{ + EptUndefined, + EptPoints, + EptLines, + EptLinesAdjacency, + EptTriangles, + EptTrianglesAdjacency, + EptLineStrip, + EptTriangleStrip +}; + +enum TLayoutTessEvaluationType +{ + EtetUndefined, + EtetTriangles, + EtetQuads, + EtetIsolines, + EtetEqualSpacing, + EtetFractionalEvenSpacing, + EtetFractionalOddSpacing, + EtetCw, + EtetCcw, + EtetPointMode +}; + +class AdvancedBlendEquations +{ + public: + // Must have a trivial default constructor since it is used in YYSTYPE. + AdvancedBlendEquations() = default; + explicit constexpr AdvancedBlendEquations(uint32_t initialState) + : mEnabledBlendEquations(initialState) + {} + + bool any() const; + bool anyHsl() const; + + void setAll(); + void reset() { mEnabledBlendEquations = 0; } + + // Parameter is gl::BlendEquationType, but PackedEnums.h include is not possible here. + void set(uint32_t blendEquation); + + uint32_t bits() const { return mEnabledBlendEquations; } + + AdvancedBlendEquations operator|=(AdvancedBlendEquations other) + { + mEnabledBlendEquations |= other.mEnabledBlendEquations; + return *this; + } + + private: + uint32_t mEnabledBlendEquations; +}; + +struct TLayoutQualifier +{ + // Must have a trivial default constructor since it is used in YYSTYPE. + TLayoutQualifier() = default; + + constexpr static TLayoutQualifier Create() { return TLayoutQualifier(0); } + + bool isEmpty() const + { + return location == -1 && binding == -1 && offset == -1 && numViews == -1 && yuv == false && + earlyFragmentTests == false && matrixPacking == EmpUnspecified && + blockStorage == EbsUnspecified && !localSize.isAnyValueSet() && + imageInternalFormat == EiifUnspecified && primitiveType == EptUndefined && + invocations == 0 && maxVertices == -1 && vertices == 0 && + tesPrimitiveType == EtetUndefined && tesVertexSpacingType == EtetUndefined && + tesOrderingType == EtetUndefined && tesPointType == EtetUndefined && index == -1 && + inputAttachmentIndex == -1 && noncoherent == false && + !advancedBlendEquations.any() && !pushConstant; + } + + bool isCombinationValid() const + { + bool workGroupSizeSpecified = localSize.isAnyValueSet(); + bool numViewsSet = (numViews != -1); + bool geometryShaderSpecified = + (primitiveType != EptUndefined) || (invocations != 0) || (maxVertices != -1); + bool subpassInputSpecified = (inputAttachmentIndex != -1); + bool otherLayoutQualifiersSpecified = + (location != -1 || binding != -1 || index != -1 || matrixPacking != EmpUnspecified || + blockStorage != EbsUnspecified || imageInternalFormat != EiifUnspecified); + bool blendEquationSpecified = advancedBlendEquations.any(); + + // we can have either the work group size specified, or number of views, + // or yuv layout qualifier, or early_fragment_tests layout qualifier, or the other layout + // qualifiers. + return (workGroupSizeSpecified ? 1 : 0) + (numViewsSet ? 1 : 0) + (yuv ? 1 : 0) + + (earlyFragmentTests ? 1 : 0) + (otherLayoutQualifiersSpecified ? 1 : 0) + + (geometryShaderSpecified ? 1 : 0) + (subpassInputSpecified ? 1 : 0) + + (noncoherent ? 1 : 0) + (blendEquationSpecified ? 1 : 0) <= + 1; + } + + bool isLocalSizeEqual(const WorkGroupSize &localSizeIn) const + { + return localSize.isWorkGroupSizeMatching(localSizeIn); + } + + int location; + unsigned int locationsSpecified; + TLayoutMatrixPacking matrixPacking; + TLayoutBlockStorage blockStorage; + + // Compute shader layout qualifiers. + WorkGroupSize localSize; + + int binding; + int offset; + + bool pushConstant; + + // Image format layout qualifier + TLayoutImageInternalFormat imageInternalFormat; + + // OVR_multiview num_views. + int numViews; + + // EXT_YUV_target yuv layout qualifier. + bool yuv; + + // early_fragment_tests qualifier. + bool earlyFragmentTests; + + // OES_geometry_shader layout qualifiers. + TLayoutPrimitiveType primitiveType; + int invocations; + int maxVertices; + + // EXT_tessellation_shader shader layout qualifiers + int vertices; + TLayoutTessEvaluationType tesPrimitiveType; + TLayoutTessEvaluationType tesVertexSpacingType; + TLayoutTessEvaluationType tesOrderingType; + TLayoutTessEvaluationType tesPointType; + + // EXT_blend_func_extended fragment output layout qualifier + int index; + + // EXT_shader_framebuffer_fetch layout qualifiers. + int inputAttachmentIndex; + bool noncoherent; + + // KHR_blend_equation_advanced layout qualifiers. + AdvancedBlendEquations advancedBlendEquations; + + // D3D 11.3 Rasterizer Order Views (ROVs). + // This qualifier is only used internally by ANGLE; it is not visible to the application. + bool rasterOrdered; + + private: + explicit constexpr TLayoutQualifier(int /*placeholder*/) + : location(-1), + locationsSpecified(0), + matrixPacking(EmpUnspecified), + blockStorage(EbsUnspecified), + localSize(-1), + binding(-1), + offset(-1), + pushConstant(false), + imageInternalFormat(EiifUnspecified), + numViews(-1), + yuv(false), + earlyFragmentTests(false), + primitiveType(EptUndefined), + invocations(0), + maxVertices(-1), + vertices(0), + tesPrimitiveType(EtetUndefined), + tesVertexSpacingType(EtetUndefined), + tesOrderingType(EtetUndefined), + tesPointType(EtetUndefined), + index(-1), + inputAttachmentIndex(-1), + noncoherent(false), + advancedBlendEquations(0), + rasterOrdered(false) + {} +}; + +struct TMemoryQualifier +{ + // Must have a trivial default constructor since it is used in YYSTYPE. + TMemoryQualifier() = default; + + bool isEmpty() const + { + return !readonly && !writeonly && !coherent && !restrictQualifier && !volatileQualifier; + } + + constexpr static TMemoryQualifier Create() { return TMemoryQualifier(0); } + + // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers + // An image can be qualified as both readonly and writeonly. It still can be can be used with + // imageSize(). + bool readonly; + bool writeonly; + bool coherent; + + // restrict and volatile are reserved keywords in C/C++ + bool restrictQualifier; + bool volatileQualifier; + + private: + explicit constexpr TMemoryQualifier(int /*placeholder*/) + : readonly(false), + writeonly(false), + coherent(false), + restrictQualifier(false), + volatileQualifier(false) + {} +}; + +inline const char *getWorkGroupSizeString(size_t dimension) +{ + switch (dimension) + { + case 0u: + return "local_size_x"; + case 1u: + return "local_size_y"; + case 2u: + return "local_size_z"; + default: + UNREACHABLE(); + return "dimension out of bounds"; + } +} + +// Used for GLSL generation, debugging and error messages. +inline const char *getQualifierString(TQualifier q) +{ + // clang-format off + switch(q) + { + case EvqTemporary: return "Temporary"; + case EvqGlobal: return "Global"; + case EvqConst: return "const"; + case EvqAttribute: return "attribute"; + case EvqVaryingIn: return "varying"; + case EvqVaryingOut: return "varying"; + case EvqUniform: return "uniform"; + case EvqBuffer: return "buffer"; + case EvqPatch: return "patch"; + case EvqVertexIn: return "in"; + case EvqFragmentOut: return "out"; + case EvqVertexOut: return "out"; + case EvqFragmentIn: return "in"; + case EvqParamIn: return "in"; + case EvqParamOut: return "out"; + case EvqParamInOut: return "inout"; + case EvqParamConst: return "const"; + case EvqInstanceID: return "InstanceID"; + case EvqVertexID: return "VertexID"; + case EvqPosition: return "Position"; + case EvqPointSize: return "PointSize"; + case EvqDrawID: return "DrawID"; + case EvqFragCoord: return "FragCoord"; + case EvqFrontFacing: return "FrontFacing"; + case EvqHelperInvocation: return "HelperInvocation"; + case EvqPointCoord: return "PointCoord"; + case EvqFragColor: return "FragColor"; + case EvqFragData: return "FragData"; + case EvqFragDepth: return "FragDepth"; + case EvqSecondaryFragColorEXT: return "SecondaryFragColorEXT"; + case EvqSecondaryFragDataEXT: return "SecondaryFragDataEXT"; + case EvqViewIDOVR: return "ViewIDOVR"; + case EvqViewportIndex: return "ViewportIndex"; + case EvqLayerOut: return "LayerOut"; + case EvqLayerIn: return "LayerIn"; + case EvqLastFragColor: return "LastFragColor"; + case EvqLastFragData: return "LastFragData"; + case EvqFragmentInOut: return "inout"; + case EvqSmoothOut: return "smooth out"; + case EvqCentroidOut: return "smooth centroid out"; + case EvqFlatOut: return "flat out"; + case EvqNoPerspectiveOut: return "noperspective out"; + case EvqSmoothIn: return "smooth in"; + case EvqFlatIn: return "flat in"; + case EvqNoPerspectiveIn: return "noperspective in"; + case EvqCentroidIn: return "smooth centroid in"; + case EvqCentroid: return "centroid"; + case EvqFlat: return "flat"; + case EvqNoPerspective: return "noperspective"; + case EvqSmooth: return "smooth"; + case EvqShared: return "shared"; + case EvqComputeIn: return "in"; + case EvqNumWorkGroups: return "NumWorkGroups"; + case EvqWorkGroupSize: return "WorkGroupSize"; + case EvqWorkGroupID: return "WorkGroupID"; + case EvqLocalInvocationID: return "LocalInvocationID"; + case EvqGlobalInvocationID: return "GlobalInvocationID"; + case EvqLocalInvocationIndex: return "LocalInvocationIndex"; + case EvqReadOnly: return "readonly"; + case EvqWriteOnly: return "writeonly"; + case EvqGeometryIn: return "in"; + case EvqGeometryOut: return "out"; + case EvqPerVertexIn: return "gl_in"; + case EvqPrimitiveIDIn: return "gl_PrimitiveIDIn"; + case EvqInvocationID: return "gl_InvocationID"; + case EvqPrimitiveID: return "gl_PrimitiveID"; + case EvqPrecise: return "precise"; + case EvqClipDistance: return "ClipDistance"; + case EvqCullDistance: return "CullDistance"; + case EvqSample: return "sample"; + case EvqSampleIn: return "sample in"; + case EvqSampleOut: return "sample out"; + case EvqSampleID: return "SampleID"; + case EvqSamplePosition: return "SamplePosition"; + case EvqSampleMaskIn: return "SampleMaskIn"; + case EvqSampleMask: return "SampleMask"; + case EvqNumSamples: return "NumSamples"; + case EvqPatchIn: return "patch in"; + case EvqPatchOut: return "patch out"; + case EvqTessControlIn: return "in"; + case EvqTessControlOut: return "out"; + case EvqPerVertexOut: return "gl_out"; + case EvqPatchVerticesIn: return "PatchVerticesIn"; + case EvqTessLevelOuter: return "TessLevelOuter"; + case EvqTessLevelInner: return "TessLevelInner"; + case EvqBoundingBox: return "BoundingBox"; + case EvqTessEvaluationIn: return "in"; + case EvqTessEvaluationOut: return "out"; + case EvqTessCoord: return "TessCoord"; + case EvqSpecConst: return "const"; + default: UNREACHABLE(); return "unknown qualifier"; + } + // clang-format on +} + +inline const char *getMatrixPackingString(TLayoutMatrixPacking mpq) +{ + switch (mpq) + { + case EmpUnspecified: + return "mp_unspecified"; + case EmpRowMajor: + return "row_major"; + case EmpColumnMajor: + return "column_major"; + default: + UNREACHABLE(); + return "unknown matrix packing"; + } +} + +inline const char *getBlockStorageString(TLayoutBlockStorage bsq) +{ + switch (bsq) + { + case EbsUnspecified: + return "bs_unspecified"; + case EbsShared: + return "shared"; + case EbsPacked: + return "packed"; + case EbsStd140: + return "std140"; + case EbsStd430: + return "std430"; + default: + UNREACHABLE(); + return "unknown block storage"; + } +} + +inline const char *getImageInternalFormatString(TLayoutImageInternalFormat iifq) +{ + switch (iifq) + { + case EiifRGBA32F: + return "rgba32f"; + case EiifRGBA16F: + return "rgba16f"; + case EiifR32F: + return "r32f"; + case EiifRGBA32UI: + return "rgba32ui"; + case EiifRGBA16UI: + return "rgba16ui"; + case EiifRGBA8UI: + return "rgba8ui"; + case EiifR32UI: + return "r32ui"; + case EiifRGBA32I: + return "rgba32i"; + case EiifRGBA16I: + return "rgba16i"; + case EiifRGBA8I: + return "rgba8i"; + case EiifR32I: + return "r32i"; + case EiifRGBA8: + return "rgba8"; + case EiifRGBA8_SNORM: + return "rgba8_snorm"; + default: + UNREACHABLE(); + return "unknown internal image format"; + } +} + +inline TYuvCscStandardEXT getYuvCscStandardEXT(const ImmutableString &str) +{ + if (str == "itu_601") + return EycsItu601; + else if (str == "itu_601_full_range") + return EycsItu601FullRange; + else if (str == "itu_709") + return EycsItu709; + return EycsUndefined; +} + +inline const char *getYuvCscStandardEXTString(TYuvCscStandardEXT ycsq) +{ + switch (ycsq) + { + case EycsItu601: + return "itu_601"; + case EycsItu601FullRange: + return "itu_601_full_range"; + case EycsItu709: + return "itu_709"; + default: + UNREACHABLE(); + return "unknown color space conversion standard"; + } +} + +inline const char *getGeometryShaderPrimitiveTypeString(TLayoutPrimitiveType primitiveType) +{ + switch (primitiveType) + { + case EptPoints: + return "points"; + case EptLines: + return "lines"; + case EptTriangles: + return "triangles"; + case EptLinesAdjacency: + return "lines_adjacency"; + case EptTrianglesAdjacency: + return "triangles_adjacency"; + case EptLineStrip: + return "line_strip"; + case EptTriangleStrip: + return "triangle_strip"; + default: + UNREACHABLE(); + return "unknown geometry shader primitive type"; + } +} + +inline const char *getTessEvaluationShaderTypeString(TLayoutTessEvaluationType type) +{ + switch (type) + { + case EtetTriangles: + return "triangles"; + case EtetQuads: + return "quads"; + case EtetIsolines: + return "isolines"; + case EtetEqualSpacing: + return "equal_spacing"; + case EtetFractionalEvenSpacing: + return "fractional_even_spacing"; + case EtetFractionalOddSpacing: + return "fractional_odd_spacing"; + case EtetCw: + return "cw"; + case EtetCcw: + return "ccw"; + case EtetPointMode: + return "point_mode"; + default: + UNREACHABLE(); + return "unknown tessellation evaluation shader variable type"; + } +} + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_BASETYPES_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp new file mode 100644 index 0000000000..34b43365cf --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp @@ -0,0 +1,161 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "angle_gl.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser +{ + public: + BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator &emulator) + : TIntermTraverser(true, false, false), mEmulator(emulator) + {} + + bool visitUnary(Visit visit, TIntermUnary *node) override + { + if (node->getFunction()) + { + bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction()); + if (needToEmulate) + node->setUseEmulatedFunction(); + } + return true; + } + + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + // Here we handle all the math built-in functions, not just the ones that are currently + // identified as problematic. + if (!BuiltInGroup::IsMath(node->getOp())) + { + return true; + } + bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction()); + if (needToEmulate) + node->setUseEmulatedFunction(); + return true; + } + + private: + BuiltInFunctionEmulator &mEmulator; +}; + +BuiltInFunctionEmulator::BuiltInFunctionEmulator() {} + +void BuiltInFunctionEmulator::addEmulatedFunction(const TSymbolUniqueId &uniqueId, + const char *emulatedFunctionDefinition) +{ + mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition); +} + +void BuiltInFunctionEmulator::addEmulatedFunctionWithDependency( + const TSymbolUniqueId &dependency, + const TSymbolUniqueId &uniqueId, + const char *emulatedFunctionDefinition) +{ + mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition); + mFunctionDependencies[uniqueId.get()] = dependency.get(); +} + +bool BuiltInFunctionEmulator::isOutputEmpty() const +{ + return (mFunctions.size() == 0); +} + +void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const +{ + for (const auto &function : mFunctions) + { + const char *body = findEmulatedFunction(function); + ASSERT(body); + out << body; + out << "\n\n"; + } +} + +const char *BuiltInFunctionEmulator::findEmulatedFunction(int uniqueId) const +{ + for (const auto &queryFunction : mQueryFunctions) + { + const char *result = queryFunction(uniqueId); + if (result) + { + return result; + } + } + + const auto &result = mEmulatedFunctions.find(uniqueId); + if (result != mEmulatedFunctions.end()) + { + return result->second.c_str(); + } + + return nullptr; +} + +bool BuiltInFunctionEmulator::setFunctionCalled(const TFunction *function) +{ + ASSERT(function != nullptr); + return setFunctionCalled(function->uniqueId().get()); +} + +bool BuiltInFunctionEmulator::setFunctionCalled(int uniqueId) +{ + if (!findEmulatedFunction(uniqueId)) + { + return false; + } + + for (size_t i = 0; i < mFunctions.size(); ++i) + { + if (mFunctions[i] == uniqueId) + return true; + } + // If the function depends on another, mark the dependency as called. + auto dependency = mFunctionDependencies.find(uniqueId); + if (dependency != mFunctionDependencies.end()) + { + setFunctionCalled((*dependency).second); + } + mFunctions.push_back(uniqueId); + return true; +} + +void BuiltInFunctionEmulator::markBuiltInFunctionsForEmulation(TIntermNode *root) +{ + ASSERT(root); + + if (mEmulatedFunctions.empty() && mQueryFunctions.empty()) + return; + + BuiltInFunctionEmulationMarker marker(*this); + root->traverse(&marker); +} + +void BuiltInFunctionEmulator::cleanup() +{ + mFunctions.clear(); + mFunctionDependencies.clear(); +} + +void BuiltInFunctionEmulator::addFunctionMap(BuiltinQueryFunc queryFunc) +{ + mQueryFunctions.push_back(queryFunc); +} + +// static +void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name) +{ + ASSERT(name[strlen(name) - 1] != '('); + out << name << "_emu"; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.h b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.h new file mode 100644 index 0000000000..7ebd6bc087 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.h @@ -0,0 +1,80 @@ +// +// Copyright 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ +#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ + +#include "compiler/translator/InfoSink.h" + +namespace sh +{ + +class TIntermNode; +class TFunction; +class TSymbolUniqueId; + +using BuiltinQueryFunc = const char *(int); + +// +// This class decides which built-in functions need to be replaced with the emulated ones. It can be +// used to work around driver bugs or implement functions that are not natively implemented on a +// specific platform. +// +class BuiltInFunctionEmulator +{ + public: + BuiltInFunctionEmulator(); + + void markBuiltInFunctionsForEmulation(TIntermNode *root); + + void cleanup(); + + // "name" gets written as "name_emu". + static void WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name); + + bool isOutputEmpty() const; + + // Output function emulation definition. This should be before any other shader source. + void outputEmulatedFunctions(TInfoSinkBase &out) const; + + // Add functions that need to be emulated. + void addEmulatedFunction(const TSymbolUniqueId &uniqueId, + const char *emulatedFunctionDefinition); + + void addEmulatedFunctionWithDependency(const TSymbolUniqueId &dependency, + const TSymbolUniqueId &uniqueId, + const char *emulatedFunctionDefinition); + + void addFunctionMap(BuiltinQueryFunc queryFunc); + + private: + class BuiltInFunctionEmulationMarker; + + // Records that a function is called by the shader and might need to be emulated. If the + // function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function + // call needs to be replaced with an emulated one. + bool setFunctionCalled(const TFunction *function); + bool setFunctionCalled(int uniqueId); + + const char *findEmulatedFunction(int uniqueId) const; + + // Map from function unique id to emulated function definition + std::map mEmulatedFunctions; + + // Map from dependent functions to their dependencies. This structure allows each function to + // have at most one dependency. + std::map mFunctionDependencies; + + // Called function ids + std::vector mFunctions; + + // Constexpr function tables. + std::vector mQueryFunctions; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp new file mode 100644 index 0000000000..9212336585 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp @@ -0,0 +1,284 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" + +#include "angle_gl.h" +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/VersionGLSL.h" +#include "compiler/translator/tree_util/BuiltIn.h" + +namespace sh +{ + +void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, + sh::GLenum shaderType) +{ + if (shaderType == GL_VERTEX_SHADER) + { + emu->addEmulatedFunction(BuiltInId::abs_Int1, "int abs_emu(int x) { return x * sign(x); }"); + } +} + +void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, + int targetGLSLVersion) +{ + // isnan() is supported since GLSL 1.3. + if (targetGLSLVersion < GLSL_VERSION_130) + return; + + // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false. + emu->addEmulatedFunction( + BuiltInId::isnan_Float1, + "bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }"); + emu->addEmulatedFunction( + BuiltInId::isnan_Float2, + "bvec2 isnan_emu(vec2 x)\n" + "{\n" + " bvec2 isnan;\n" + " for (int i = 0; i < 2; i++)\n" + " {\n" + " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" + " }\n" + " return isnan;\n" + "}\n"); + emu->addEmulatedFunction( + BuiltInId::isnan_Float3, + "bvec3 isnan_emu(vec3 x)\n" + "{\n" + " bvec3 isnan;\n" + " for (int i = 0; i < 3; i++)\n" + " {\n" + " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" + " }\n" + " return isnan;\n" + "}\n"); + emu->addEmulatedFunction( + BuiltInId::isnan_Float4, + "bvec4 isnan_emu(vec4 x)\n" + "{\n" + " bvec4 isnan;\n" + " for (int i = 0; i < 4; i++)\n" + " {\n" + " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" + " }\n" + " return isnan;\n" + "}\n"); +} + +void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu) +{ + emu->addEmulatedFunction(BuiltInId::atan_Float1_Float1, + "emu_precision float atan_emu(emu_precision float y, emu_precision " + "float x)\n" + "{\n" + " if (x > 0.0) return atan(y / x);\n" + " else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n" + " else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n" + " else return 1.57079632 * sign(y);\n" + "}\n"); + static const std::array ids = { + BuiltInId::atan_Float1_Float1, + BuiltInId::atan_Float2_Float2, + BuiltInId::atan_Float3_Float3, + BuiltInId::atan_Float4_Float4, + }; + for (int dim = 2; dim <= 4; ++dim) + { + std::stringstream ss = sh::InitializeStream(); + ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim + << " y, emu_precision vec" << dim << " x)\n" + << "{\n" + " return vec" + << dim << "("; + for (int i = 0; i < dim; ++i) + { + ss << "atan_emu(y[" << i << "], x[" << i << "])"; + if (i < dim - 1) + { + ss << ", "; + } + } + ss << ");\n" + "}\n"; + emu->addEmulatedFunctionWithDependency(BuiltInId::atan_Float1_Float1, ids[dim - 1], + ss.str().c_str()); + } +} + +// Emulate built-in functions missing from GLSL 1.30 and higher +void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu, + sh::GLenum shaderType, + int targetGLSLVersion) +{ + // Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10) + if (targetGLSLVersion < GLSL_VERSION_410) + { + // clang-format off + emu->addEmulatedFunction(BuiltInId::packUnorm2x16_Float2, + "uint packUnorm2x16_emu(vec2 v)\n" + "{\n" + " int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n" + " int y = int(round(clamp(v.y, 0.0, 1.0) * 65535.0));\n" + " return uint((y << 16) | (x & 0xFFFF));\n" + "}\n"); + + emu->addEmulatedFunction(BuiltInId::unpackUnorm2x16_UInt1, + "vec2 unpackUnorm2x16_emu(uint u)\n" + "{\n" + " float x = float(u & 0xFFFFu) / 65535.0;\n" + " float y = float(u >> 16) / 65535.0;\n" + " return vec2(x, y);\n" + "}\n"); + // clang-format on + } + + // Emulate packSnorm2x16, packHalf2x16, unpackSnorm2x16, and unpackHalf2x16 (GLSL 4.20) + // by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30). + if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420) + { + // clang-format off + emu->addEmulatedFunction(BuiltInId::packSnorm2x16_Float2, + "uint packSnorm2x16_emu(vec2 v)\n" + "{\n" + " #if defined(GL_ARB_shading_language_packing)\n" + " return packSnorm2x16(v);\n" + " #else\n" + " int x = int(round(clamp(v.x, -1.0, 1.0) * 32767.0));\n" + " int y = int(round(clamp(v.y, -1.0, 1.0) * 32767.0));\n" + " return uint((y << 16) | (x & 0xFFFF));\n" + " #endif\n" + "}\n"); + emu->addEmulatedFunction(BuiltInId::unpackSnorm2x16_UInt1, + "#if !defined(GL_ARB_shading_language_packing)\n" + " float fromSnorm(uint x)\n" + " {\n" + " int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n" + " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n" + " }\n" + "#endif\n" + "\n" + "vec2 unpackSnorm2x16_emu(uint u)\n" + "{\n" + " #if defined(GL_ARB_shading_language_packing)\n" + " return unpackSnorm2x16(u);\n" + " #else\n" + " uint y = (u >> 16);\n" + " uint x = u;\n" + " return vec2(fromSnorm(x), fromSnorm(y));\n" + " #endif\n" + "}\n"); + // Functions uint f32tof16(float val) and float f16tof32(uint val) are + // based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL". + emu->addEmulatedFunction(BuiltInId::packHalf2x16_Float2, + "#if !defined(GL_ARB_shading_language_packing)\n" + " uint f32tof16(float val)\n" + " {\n" + " uint f32 = floatBitsToUint(val);\n" + " uint f16 = 0u;\n" + " uint sign = (f32 >> 16) & 0x8000u;\n" + " int exponent = int((f32 >> 23) & 0xFFu) - 127;\n" + " uint mantissa = f32 & 0x007FFFFFu;\n" + " if (exponent == 128)\n" + " {\n" + " // Infinity or NaN\n" + " // NaN bits that are masked out by 0x3FF get discarded.\n" + " // This can turn some NaNs to infinity, but this is allowed by the spec.\n" + " f16 = sign | (0x1Fu << 10);\n" + " f16 |= (mantissa & 0x3FFu);\n" + " }\n" + " else if (exponent > 15)\n" + " {\n" + " // Overflow - flush to Infinity\n" + " f16 = sign | (0x1Fu << 10);\n" + " }\n" + " else if (exponent > -15)\n" + " {\n" + " // Representable value\n" + " exponent += 15;\n" + " mantissa >>= 13;\n" + " f16 = sign | uint(exponent << 10) | mantissa;\n" + " }\n" + " else\n" + " {\n" + " f16 = sign;\n" + " }\n" + " return f16;\n" + " }\n" + "#endif\n" + "\n" + "uint packHalf2x16_emu(vec2 v)\n" + "{\n" + " #if defined(GL_ARB_shading_language_packing)\n" + " return packHalf2x16(v);\n" + " #else\n" + " uint x = f32tof16(v.x);\n" + " uint y = f32tof16(v.y);\n" + " return (y << 16) | x;\n" + " #endif\n" + "}\n"); + emu->addEmulatedFunction(BuiltInId::unpackHalf2x16_UInt1, + "#if !defined(GL_ARB_shading_language_packing)\n" + " float f16tof32(uint val)\n" + " {\n" + " uint sign = (val & 0x8000u) << 16;\n" + " int exponent = int((val & 0x7C00u) >> 10);\n" + " uint mantissa = val & 0x03FFu;\n" + " float f32 = 0.0;\n" + " if(exponent == 0)\n" + " {\n" + " if (mantissa != 0u)\n" + " {\n" + " const float scale = 1.0 / (1 << 24);\n" + " f32 = scale * mantissa;\n" + " }\n" + " }\n" + " else if (exponent == 31)\n" + " {\n" + " return uintBitsToFloat(sign | 0x7F800000u | mantissa);\n" + " }\n" + " else\n" + " {\n" + " exponent -= 15;\n" + " float scale;\n" + " if(exponent < 0)\n" + " {\n" + " // The negative unary operator is buggy on OSX.\n" + " // Work around this by using abs instead.\n" + " scale = 1.0 / (1 << abs(exponent));\n" + " }\n" + " else\n" + " {\n" + " scale = 1 << exponent;\n" + " }\n" + " float decimal = 1.0 + float(mantissa) / float(1 << 10);\n" + " f32 = scale * decimal;\n" + " }\n" + "\n" + " if (sign != 0u)\n" + " {\n" + " f32 = -f32;\n" + " }\n" + "\n" + " return f32;\n" + " }\n" + "#endif\n" + "\n" + "vec2 unpackHalf2x16_emu(uint u)\n" + "{\n" + " #if defined(GL_ARB_shading_language_packing)\n" + " return unpackHalf2x16(u);\n" + " #else\n" + " uint y = (u >> 16);\n" + " uint x = u & 0xFFFFu;\n" + " return vec2(f16tof32(x), f16tof32(y));\n" + " #endif\n" + "}\n"); + // clang-format on + } +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h new file mode 100644 index 0000000000..91ba67f3aa --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h @@ -0,0 +1,40 @@ +// +// Copyright 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ +#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ + +#include "GLSLANG/ShaderLang.h" + +namespace sh +{ +class BuiltInFunctionEmulator; + +// +// This works around bug in Intel Mac drivers. +// +void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, + sh::GLenum shaderType); + +// +// This works around isnan() bug in Intel Mac drivers +// +void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, + int targetGLSLVersion); +// +// This works around atan(y, x) bug in NVIDIA drivers. +// +void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu); + +// +// This function is emulating built-in functions missing from GLSL 1.30 and higher. +// +void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu, + sh::GLenum shaderType, + int targetGLSLVersion); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp new file mode 100644 index 0000000000..66a0be39e7 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp @@ -0,0 +1,173 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h" +#include "angle_gl.h" +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/VersionGLSL.h" +#include "compiler/translator/tree_util/BuiltIn.h" + +namespace sh +{ + +// Defined in emulated_builtin_functions_hlsl_autogen.cpp. +const char *FindHLSLFunction(int uniqueId); + +void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu, + int targetGLSLVersion) +{ + if (targetGLSLVersion < GLSL_VERSION_130) + return; + + emu->addEmulatedFunction(BuiltInId::isnan_Float1, + "bool isnan_emu(float x)\n" + "{\n" + " return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n" + "}\n" + "\n"); + + emu->addEmulatedFunction( + BuiltInId::isnan_Float2, + "bool2 isnan_emu(float2 x)\n" + "{\n" + " bool2 isnan;\n" + " for (int i = 0; i < 2; i++)\n" + " {\n" + " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" + " }\n" + " return isnan;\n" + "}\n"); + + emu->addEmulatedFunction( + BuiltInId::isnan_Float3, + "bool3 isnan_emu(float3 x)\n" + "{\n" + " bool3 isnan;\n" + " for (int i = 0; i < 3; i++)\n" + " {\n" + " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" + " }\n" + " return isnan;\n" + "}\n"); + + emu->addEmulatedFunction( + BuiltInId::isnan_Float4, + "bool4 isnan_emu(float4 x)\n" + "{\n" + " bool4 isnan;\n" + " for (int i = 0; i < 4; i++)\n" + " {\n" + " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" + " }\n" + " return isnan;\n" + "}\n"); +} + +void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu) +{ + emu->addFunctionMap(FindHLSLFunction); + + // (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32 + // Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because: + // a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000 + emu->addEmulatedFunction(BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1, + "void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n" + "{\n" + " lsb = x * y;\n" + " uint a = (x & 0xffffu);\n" + " uint b = (x >> 16);\n" + " uint c = (y & 0xffffu);\n" + " uint d = (y >> 16);\n" + " uint ad = a * d + ((a * c) >> 16);\n" + " uint bc = b * c;\n" + " uint carry = uint(ad > (0xffffffffu - bc));\n" + " msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n" + "}\n"); + emu->addEmulatedFunctionWithDependency( + BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1, + BuiltInId::umulExtended_UInt2_UInt2_UInt2_UInt2, + "void umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n" + "{\n" + " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" + " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" + "}\n"); + emu->addEmulatedFunctionWithDependency( + BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1, + BuiltInId::umulExtended_UInt3_UInt3_UInt3_UInt3, + "void umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n" + "{\n" + " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" + " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" + " umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" + "}\n"); + emu->addEmulatedFunctionWithDependency( + BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1, + BuiltInId::umulExtended_UInt4_UInt4_UInt4_UInt4, + "void umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n" + "{\n" + " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" + " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" + " umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" + " umulExtended_emu(x.w, y.w, msb.w, lsb.w);\n" + "}\n"); + + // The imul emulation does two's complement negation on the lsb and msb manually in case the + // result needs to be negative. + // TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is + // -2^31. abs(-2^31) is undefined. + emu->addEmulatedFunctionWithDependency( + BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1, + BuiltInId::imulExtended_Int1_Int1_Int1_Int1, + "void imulExtended_emu(int x, int y, out int msb, out int lsb)\n" + "{\n" + " uint unsignedMsb;\n" + " uint unsignedLsb;\n" + " bool negative = (x < 0) != (y < 0);\n" + " umulExtended_emu(uint(abs(x)), uint(abs(y)), unsignedMsb, unsignedLsb);\n" + " lsb = asint(unsignedLsb);\n" + " msb = asint(unsignedMsb);\n" + " if (negative)\n" + " {\n" + " lsb = ~lsb;\n" + " msb = ~msb;\n" + " if (lsb == 0xffffffff)\n" + " {\n" + " lsb = 0;\n" + " msb += 1;\n" + " }\n" + " else\n" + " {\n" + " lsb += 1;\n" + " }\n" + " }\n" + "}\n"); + emu->addEmulatedFunctionWithDependency( + BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int2_Int2_Int2_Int2, + "void imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n" + "{\n" + " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" + " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" + "}\n"); + emu->addEmulatedFunctionWithDependency( + BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int3_Int3_Int3_Int3, + "void imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n" + "{\n" + " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" + " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" + " imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" + "}\n"); + emu->addEmulatedFunctionWithDependency( + BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int4_Int4_Int4_Int4, + "void imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n" + "{\n" + " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" + " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" + " imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" + " imulExtended_emu(x.w, y.w, msb.w, lsb.w);\n" + "}\n"); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h new file mode 100644 index 0000000000..e5c6070fe6 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h @@ -0,0 +1,27 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ +#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ + +#include "GLSLANG/ShaderLang.h" + +namespace sh +{ + +class BuiltInFunctionEmulator; + +void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu); + +// +// This works around isnan() bug on some Intel drivers. +// +void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu, + int targetGLSLVersion); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/BuiltinsWorkaroundGLSL.cpp b/gfx/angle/checkout/src/compiler/translator/BuiltinsWorkaroundGLSL.cpp new file mode 100644 index 0000000000..6409f85c3c --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/BuiltinsWorkaroundGLSL.cpp @@ -0,0 +1,109 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/BuiltinsWorkaroundGLSL.h" + +#include "angle_gl.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/BuiltIn.h" + +namespace sh +{ + +namespace +{ +constexpr const ImmutableString kGlInstanceIDString("gl_InstanceID"); +constexpr const ImmutableString kGlVertexIDString("gl_VertexID"); + +class TBuiltinsWorkaroundGLSL : public TIntermTraverser +{ + public: + TBuiltinsWorkaroundGLSL(TSymbolTable *symbolTable, const ShCompileOptions &options); + + void visitSymbol(TIntermSymbol *node) override; + bool visitDeclaration(Visit, TIntermDeclaration *node) override; + + private: + void ensureVersionIsAtLeast(int version); + + const ShCompileOptions &mCompileOptions; + + bool isBaseInstanceDeclared = false; +}; + +TBuiltinsWorkaroundGLSL::TBuiltinsWorkaroundGLSL(TSymbolTable *symbolTable, + const ShCompileOptions &options) + : TIntermTraverser(true, false, false, symbolTable), mCompileOptions(options) +{} + +void TBuiltinsWorkaroundGLSL::visitSymbol(TIntermSymbol *node) +{ + if (node->variable().symbolType() == SymbolType::BuiltIn) + { + if (node->getName() == kGlInstanceIDString) + { + TIntermSymbol *instanceIndexRef = + new TIntermSymbol(BuiltInVariable::gl_InstanceIndex()); + + if (isBaseInstanceDeclared) + { + TIntermSymbol *baseInstanceRef = + new TIntermSymbol(BuiltInVariable::angle_BaseInstance()); + + TIntermBinary *subBaseInstance = + new TIntermBinary(EOpSub, instanceIndexRef, baseInstanceRef); + queueReplacement(subBaseInstance, OriginalNode::IS_DROPPED); + } + else + { + queueReplacement(instanceIndexRef, OriginalNode::IS_DROPPED); + } + } + else if (node->getName() == kGlVertexIDString) + { + TIntermSymbol *vertexIndexRef = new TIntermSymbol(BuiltInVariable::gl_VertexIndex()); + queueReplacement(vertexIndexRef, OriginalNode::IS_DROPPED); + } + } +} + +bool TBuiltinsWorkaroundGLSL::visitDeclaration(Visit, TIntermDeclaration *node) +{ + const TIntermSequence &sequence = *(node->getSequence()); + ASSERT(!sequence.empty()); + + for (TIntermNode *variableNode : sequence) + { + TIntermSymbol *variable = variableNode->getAsSymbolNode(); + if (variable && variable->variable().symbolType() == SymbolType::BuiltIn) + { + if (variable->getName() == "angle_BaseInstance") + { + isBaseInstanceDeclared = true; + } + } + } + return true; +} + +} // anonymous namespace + +[[nodiscard]] bool ShaderBuiltinsWorkaround(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const ShCompileOptions &compileOptions) +{ + TBuiltinsWorkaroundGLSL builtins(symbolTable, compileOptions); + root->traverse(&builtins); + if (!builtins.updateTree(compiler, root)) + { + return false; + } + return true; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/BuiltinsWorkaroundGLSL.h b/gfx/angle/checkout/src/compiler/translator/BuiltinsWorkaroundGLSL.h new file mode 100644 index 0000000000..e49273dae9 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/BuiltinsWorkaroundGLSL.h @@ -0,0 +1,24 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_BUILTINSWORKAROUNDGLSL_H_ +#define COMPILER_TRANSLATOR_BUILTINSWORKAROUNDGLSL_H_ + +#include "compiler/translator/tree_util/IntermTraverse.h" + +#include "compiler/translator/Pragma.h" + +namespace sh +{ + +[[nodiscard]] bool ShaderBuiltinsWorkaround(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const ShCompileOptions &compileOptions); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_BUILTINSWORKAROUNDGLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/CallDAG.cpp b/gfx/angle/checkout/src/compiler/translator/CallDAG.cpp new file mode 100644 index 0000000000..5d47518eba --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/CallDAG.cpp @@ -0,0 +1,316 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// CallDAG.h: Implements a call graph DAG of functions to be re-used accross +// analyses, allows to efficiently traverse the functions in topological +// order. + +#include "compiler/translator/CallDAG.h" + +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +// The CallDAGCreator does all the processing required to create the CallDAG +// structure so that the latter contains only the necessary variables. +class CallDAG::CallDAGCreator : public TIntermTraverser +{ + public: + CallDAGCreator(TDiagnostics *diagnostics) + : TIntermTraverser(true, false, false), + mDiagnostics(diagnostics), + mCurrentFunction(nullptr), + mCurrentIndex(0) + {} + + InitResult assignIndices() + { + int skipped = 0; + for (auto &it : mFunctions) + { + // Skip unimplemented functions + if (it.second.definitionNode) + { + InitResult result = assignIndicesInternal(&it.second); + if (result != INITDAG_SUCCESS) + { + return result; + } + } + else + { + skipped++; + } + } + + ASSERT(mFunctions.size() == mCurrentIndex + skipped); + return INITDAG_SUCCESS; + } + + void fillDataStructures(std::vector *records, std::map *idToIndex) + { + ASSERT(records->empty()); + ASSERT(idToIndex->empty()); + + records->resize(mCurrentIndex); + + for (auto &it : mFunctions) + { + CreatorFunctionData &data = it.second; + // Skip unimplemented functions + if (!data.definitionNode) + { + continue; + } + ASSERT(data.index < records->size()); + Record &record = (*records)[data.index]; + + record.node = data.definitionNode; + + record.callees.reserve(data.callees.size()); + for (auto &callee : data.callees) + { + record.callees.push_back(static_cast(callee->index)); + } + + (*idToIndex)[it.first] = static_cast(data.index); + } + } + + private: + struct CreatorFunctionData + { + CreatorFunctionData() + : definitionNode(nullptr), name(""), index(0), indexAssigned(false), visiting(false) + {} + + std::set callees; + TIntermFunctionDefinition *definitionNode; + ImmutableString name; + size_t index; + bool indexAssigned; + bool visiting; + }; + + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override + { + // Create the record if need be and remember the definition node. + mCurrentFunction = &mFunctions[node->getFunction()->uniqueId().get()]; + // Name will be overwritten here. If we've already traversed the prototype of this function, + // it should have had the same name. + ASSERT(mCurrentFunction->name == "" || + mCurrentFunction->name == node->getFunction()->name()); + mCurrentFunction->name = node->getFunction()->name(); + mCurrentFunction->definitionNode = node; + + node->getBody()->traverse(this); + mCurrentFunction = nullptr; + return false; + } + + void visitFunctionPrototype(TIntermFunctionPrototype *node) override + { + ASSERT(mCurrentFunction == nullptr); + + // Function declaration, create an empty record. + auto &record = mFunctions[node->getFunction()->uniqueId().get()]; + record.name = node->getFunction()->name(); + } + + // Track functions called from another function. + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + if (node->getOp() == EOpCallFunctionInAST) + { + // Function call, add the callees + auto it = mFunctions.find(node->getFunction()->uniqueId().get()); + ASSERT(it != mFunctions.end()); + + // We might be traversing the initializer of a global variable. Even though function + // calls in global scope are forbidden by the parser, some subsequent AST + // transformations can add them to emulate particular features. + if (mCurrentFunction) + { + mCurrentFunction->callees.insert(&it->second); + } + } + return true; + } + + // Recursively assigns indices to a sub DAG + InitResult assignIndicesInternal(CreatorFunctionData *root) + { + // Iterative implementation of the index assignment algorithm. A recursive version + // would be prettier but since the CallDAG creation runs before the limiting of the + // call depth, we might get stack overflows (computation of the call depth uses the + // CallDAG). + + ASSERT(root); + + if (root->indexAssigned) + { + return INITDAG_SUCCESS; + } + + // If we didn't have to detect recursion, functionsToProcess could be a simple queue + // in which we add the function being processed's callees. However in order to detect + // recursion we need to know which functions we are currently visiting. For that reason + // functionsToProcess will look like a concatenation of segments of the form + // [F visiting = true, subset of F callees with visiting = false] and the following + // segment (if any) will be start with a callee of F. + // This way we can remember when we started visiting a function, to put visiting back + // to false. + TVector functionsToProcess; + functionsToProcess.push_back(root); + + InitResult result = INITDAG_SUCCESS; + + std::stringstream errorStream = sh::InitializeStream(); + + while (!functionsToProcess.empty()) + { + CreatorFunctionData *function = functionsToProcess.back(); + + if (function->visiting) + { + function->visiting = false; + function->index = mCurrentIndex++; + function->indexAssigned = true; + + functionsToProcess.pop_back(); + continue; + } + + if (!function->definitionNode) + { + errorStream << "Undefined function '" << function->name + << "()' used in the following call chain:"; + result = INITDAG_UNDEFINED; + break; + } + + if (function->indexAssigned) + { + functionsToProcess.pop_back(); + continue; + } + + function->visiting = true; + + for (auto callee : function->callees) + { + functionsToProcess.push_back(callee); + + // Check if the callee is already being visited after pushing it so that it appears + // in the chain printed in the info log. + if (callee->visiting) + { + errorStream << "Recursive function call in the following call chain:"; + result = INITDAG_RECURSION; + break; + } + } + + if (result != INITDAG_SUCCESS) + { + break; + } + } + + // The call chain is made of the function we were visiting when the error was detected. + if (result != INITDAG_SUCCESS) + { + bool first = true; + for (auto function : functionsToProcess) + { + if (function->visiting) + { + if (!first) + { + errorStream << " -> "; + } + errorStream << function->name << ")"; + first = false; + } + } + if (mDiagnostics) + { + std::string errorStr = errorStream.str(); + mDiagnostics->globalError(errorStr.c_str()); + } + } + + return result; + } + + TDiagnostics *mDiagnostics; + + std::map mFunctions; + CreatorFunctionData *mCurrentFunction; + size_t mCurrentIndex; +}; + +// CallDAG + +CallDAG::CallDAG() {} + +CallDAG::~CallDAG() {} + +const size_t CallDAG::InvalidIndex = std::numeric_limits::max(); + +size_t CallDAG::findIndex(const TSymbolUniqueId &id) const +{ + auto it = mFunctionIdToIndex.find(id.get()); + + if (it == mFunctionIdToIndex.end()) + { + return InvalidIndex; + } + else + { + return it->second; + } +} + +const CallDAG::Record &CallDAG::getRecordFromIndex(size_t index) const +{ + ASSERT(index != InvalidIndex && index < mRecords.size()); + return mRecords[index]; +} + +size_t CallDAG::size() const +{ + return mRecords.size(); +} + +void CallDAG::clear() +{ + mRecords.clear(); + mFunctionIdToIndex.clear(); +} + +CallDAG::InitResult CallDAG::init(TIntermNode *root, TDiagnostics *diagnostics) +{ + CallDAGCreator creator(diagnostics); + + // Creates the mapping of functions to callees + root->traverse(&creator); + + // Does the topological sort and detects recursions + InitResult result = creator.assignIndices(); + if (result != INITDAG_SUCCESS) + { + return result; + } + + creator.fillDataStructures(&mRecords, &mFunctionIdToIndex); + return INITDAG_SUCCESS; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/CallDAG.h b/gfx/angle/checkout/src/compiler/translator/CallDAG.h new file mode 100644 index 0000000000..7e80f2e855 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/CallDAG.h @@ -0,0 +1,77 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// CallDAG.h: Defines a call graph DAG of functions to be re-used accross +// analyses, allows to efficiently traverse the functions in topological +// order. + +#ifndef COMPILER_TRANSLATOR_CALLDAG_H_ +#define COMPILER_TRANSLATOR_CALLDAG_H_ + +#include + +#include "compiler/translator/IntermNode.h" + +namespace sh +{ + +// The translator needs to analyze the the graph of the function calls +// to run checks and analyses; since in GLSL recursion is not allowed +// that graph is a DAG. +// This class is used to precompute that function call DAG so that it +// can be reused by multiple analyses. +// +// It stores a vector of function records, with one record per defined function. +// Records are accessed by index but a function symbol id can be converted +// to the index of the corresponding record. The records contain the AST node +// of the function definition and the indices of the function's callees. +// +// In addition, records are in reverse topological order: a function F being +// called by a function G will have index index(F) < index(G), that way +// depth-first analysis becomes analysis in the order of indices. + +class CallDAG : angle::NonCopyable +{ + public: + CallDAG(); + ~CallDAG(); + + struct Record + { + TIntermFunctionDefinition *node; // Guaranteed to be non-null. + std::vector callees; + }; + + enum InitResult + { + INITDAG_SUCCESS, + INITDAG_RECURSION, + INITDAG_UNDEFINED, + }; + + // Returns INITDAG_SUCCESS if it was able to create the DAG, otherwise prints + // the initialization error in diagnostics, if present. + InitResult init(TIntermNode *root, TDiagnostics *diagnostics); + + // Returns InvalidIndex if the function wasn't found + size_t findIndex(const TSymbolUniqueId &id) const; + + const Record &getRecordFromIndex(size_t index) const; + size_t size() const; + void clear(); + + const static size_t InvalidIndex; + + private: + std::vector mRecords; + std::map mFunctionIdToIndex; + + class CallDAGCreator; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_CALLDAG_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/CodeGen.cpp b/gfx/angle/checkout/src/compiler/translator/CodeGen.cpp new file mode 100644 index 0000000000..497ef881e2 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/CodeGen.cpp @@ -0,0 +1,96 @@ +// +// Copyright 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifdef ANGLE_ENABLE_ESSL +# include "compiler/translator/TranslatorESSL.h" +#endif // ANGLE_ENABLE_ESSL + +#ifdef ANGLE_ENABLE_GLSL +# include "compiler/translator/TranslatorGLSL.h" +#endif // ANGLE_ENABLE_GLSL + +#ifdef ANGLE_ENABLE_HLSL +# include "compiler/translator/TranslatorHLSL.h" +#endif // ANGLE_ENABLE_HLSL + +#ifdef ANGLE_ENABLE_VULKAN +# include "compiler/translator/TranslatorVulkan.h" +#endif // ANGLE_ENABLE_VULKAN + +#ifdef ANGLE_ENABLE_METAL +# include "compiler/translator/TranslatorMetalDirect.h" +#endif // ANGLE_ENABLE_METAL + +#ifdef ANGLE_ENABLE_METAL_SPIRV +# include "compiler/translator/TranslatorMetal.h" +#endif // ANGLE_ENABLE_METAL_SPIRV + +#include "compiler/translator/util.h" + +namespace sh +{ + +// +// This function must be provided to create the actual +// compile object used by higher level code. It returns +// a subclass of TCompiler. +// +TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) +{ +#ifdef ANGLE_ENABLE_ESSL + if (IsOutputESSL(output)) + { + return new TranslatorESSL(type, spec); + } +#endif // ANGLE_ENABLE_ESSL + +#ifdef ANGLE_ENABLE_GLSL + if (IsOutputGLSL(output)) + { + return new TranslatorGLSL(type, spec, output); + } +#endif // ANGLE_ENABLE_GLSL + +#ifdef ANGLE_ENABLE_HLSL + if (IsOutputHLSL(output)) + { + return new TranslatorHLSL(type, spec, output); + } +#endif // ANGLE_ENABLE_HLSL + +#ifdef ANGLE_ENABLE_VULKAN + if (IsOutputVulkan(output)) + { + return new TranslatorVulkan(type, spec); + } +#endif // ANGLE_ENABLE_VULKAN + +#ifdef ANGLE_ENABLE_METAL_SPIRV + if (IsOutputMetal(output)) + { + return new TranslatorMetal(type, spec); + } +#endif +#ifdef ANGLE_ENABLE_METAL + if (IsOutputMetalDirect(output)) + { + return new TranslatorMetalDirect(type, spec, output); + } +#endif // ANGLE_ENABLE_METAL + + // Unsupported compiler or unknown format. Return nullptr per the sh::ConstructCompiler API. + return nullptr; +} + +// +// Delete the compiler made by ConstructCompiler +// +void DeleteCompiler(TCompiler *compiler) +{ + SafeDelete(compiler); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp b/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp new file mode 100644 index 0000000000..d6c58bebcb --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp @@ -0,0 +1,1288 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// CollectVariables.cpp: Collect lists of shader interface variables based on the AST. + +#include "compiler/translator/CollectVariables.h" + +#include "angle_gl.h" +#include "common/utilities.h" +#include "compiler/translator/HashNames.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage) +{ + switch (blockStorage) + { + case EbsPacked: + return BLOCKLAYOUT_PACKED; + case EbsShared: + return BLOCKLAYOUT_SHARED; + case EbsStd140: + return BLOCKLAYOUT_STD140; + case EbsStd430: + return BLOCKLAYOUT_STD430; + default: + UNREACHABLE(); + return BLOCKLAYOUT_SHARED; + } +} + +BlockType GetBlockType(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqUniform: + return BlockType::BLOCK_UNIFORM; + case EvqBuffer: + return BlockType::BLOCK_BUFFER; + default: + UNREACHABLE(); + return BlockType::BLOCK_UNIFORM; + } +} + +template +VarT *FindVariable(const ImmutableString &name, std::vector *infoList) +{ + // TODO(zmo): optimize this function. + for (size_t ii = 0; ii < infoList->size(); ++ii) + { + if (name == (*infoList)[ii].name) + return &((*infoList)[ii]); + } + + return nullptr; +} + +void MarkActive(ShaderVariable *variable) +{ + if (!variable->active) + { + if (variable->isStruct()) + { + // Conservatively assume all fields are statically used as well. + for (auto &field : variable->fields) + { + MarkActive(&field); + } + } + variable->staticUse = true; + variable->active = true; + } +} + +ShaderVariable *FindVariableInInterfaceBlock(const ImmutableString &name, + const TInterfaceBlock *interfaceBlock, + std::vector *infoList) +{ + ASSERT(interfaceBlock); + InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList); + ASSERT(namedBlock); + + // Set static use on the parent interface block here + namedBlock->staticUse = true; + namedBlock->active = true; + return FindVariable(name, &namedBlock->fields); +} + +ShaderVariable *FindShaderIOBlockVariable(const ImmutableString &blockName, + std::vector *infoList) +{ + for (size_t index = 0; index < infoList->size(); ++index) + { + if (blockName == (*infoList)[index].structOrBlockName) + return &(*infoList)[index]; + } + + return nullptr; +} + +// Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs, +// shared data and interface blocks. +class CollectVariablesTraverser : public TIntermTraverser +{ + public: + CollectVariablesTraverser(std::vector *attribs, + std::vector *outputVariables, + std::vector *uniforms, + std::vector *inputVaryings, + std::vector *outputVaryings, + std::vector *sharedVariables, + std::vector *uniformBlocks, + std::vector *shaderStorageBlocks, + ShHashFunction64 hashFunction, + TSymbolTable *symbolTable, + GLenum shaderType, + const TExtensionBehavior &extensionBehavior, + const ShBuiltInResources &resources, + int tessControlShaderOutputVertices); + + bool visitGlobalQualifierDeclaration(Visit visit, + TIntermGlobalQualifierDeclaration *node) override; + void visitSymbol(TIntermSymbol *symbol) override; + bool visitDeclaration(Visit, TIntermDeclaration *node) override; + bool visitBinary(Visit visit, TIntermBinary *binaryNode) override; + + private: + std::string getMappedName(const TSymbol *symbol) const; + + void setFieldOrVariableProperties(const TType &type, + bool staticUse, + bool isShaderIOBlock, + bool isPatch, + ShaderVariable *variableOut) const; + void setFieldProperties(const TType &type, + const ImmutableString &name, + bool staticUse, + bool isShaderIOBlock, + bool isPatch, + SymbolType symbolType, + ShaderVariable *variableOut) const; + void setCommonVariableProperties(const TType &type, + const TVariable &variable, + ShaderVariable *variableOut) const; + + ShaderVariable recordAttribute(const TIntermSymbol &variable) const; + ShaderVariable recordOutputVariable(const TIntermSymbol &variable) const; + ShaderVariable recordVarying(const TIntermSymbol &variable) const; + void recordInterfaceBlock(const char *instanceName, + const TType &interfaceBlockType, + InterfaceBlock *interfaceBlock) const; + ShaderVariable recordUniform(const TIntermSymbol &variable) const; + + void setBuiltInInfoFromSymbol(const TVariable &variable, ShaderVariable *info); + + void recordBuiltInVaryingUsed(const TVariable &variable, + bool *addedFlag, + std::vector *varyings); + void recordBuiltInFragmentOutputUsed(const TVariable &variable, bool *addedFlag); + void recordBuiltInAttributeUsed(const TVariable &variable, bool *addedFlag); + InterfaceBlock *findNamedInterfaceBlock(const ImmutableString &name) const; + + std::vector *mAttribs; + std::vector *mOutputVariables; + std::vector *mUniforms; + std::vector *mInputVaryings; + std::vector *mOutputVaryings; + std::vector *mSharedVariables; + std::vector *mUniformBlocks; + std::vector *mShaderStorageBlocks; + + std::map mInterfaceBlockFields; + + // Shader uniforms + bool mDepthRangeAdded; + bool mNumSamplesAdded; + + // Compute Shader builtins + bool mNumWorkGroupsAdded; + bool mWorkGroupIDAdded; + bool mLocalInvocationIDAdded; + bool mGlobalInvocationIDAdded; + bool mLocalInvocationIndexAdded; + + // Vertex Shader builtins + bool mInstanceIDAdded; + bool mVertexIDAdded; + bool mPointSizeAdded; + bool mDrawIDAdded; + + // Vertex Shader and Geometry Shader builtins + bool mPositionAdded; + bool mClipDistanceAdded; + bool mCullDistanceAdded; + + // Fragment Shader builtins + bool mPointCoordAdded; + bool mFrontFacingAdded; + bool mHelperInvocationAdded; + bool mFragCoordAdded; + bool mLastFragDataAdded; + bool mFragColorAdded; + bool mFragDataAdded; + bool mFragDepthAdded; + bool mSecondaryFragColorEXTAdded; + bool mSecondaryFragDataEXTAdded; + bool mSampleIDAdded; + bool mSamplePositionAdded; + bool mSampleMaskAdded; + bool mSampleMaskInAdded; + + // Geometry and Tessellation Shader builtins + bool mPerVertexInAdded; + bool mPerVertexOutAdded; + + // Geometry Shader builtins + bool mPrimitiveIDInAdded; + bool mInvocationIDAdded; + + // Geometry Shader and Fragment Shader builtins + bool mPrimitiveIDAdded; + bool mLayerAdded; + + // Shared memory variables + bool mSharedVariableAdded; + + // Tessellation Shader builtins + bool mPatchVerticesInAdded; + bool mTessLevelOuterAdded; + bool mTessLevelInnerAdded; + bool mBoundingBoxAdded; + bool mTessCoordAdded; + const int mTessControlShaderOutputVertices; + + ShHashFunction64 mHashFunction; + + GLenum mShaderType; + const TExtensionBehavior &mExtensionBehavior; + const ShBuiltInResources &mResources; +}; + +CollectVariablesTraverser::CollectVariablesTraverser( + std::vector *attribs, + std::vector *outputVariables, + std::vector *uniforms, + std::vector *inputVaryings, + std::vector *outputVaryings, + std::vector *sharedVariables, + std::vector *uniformBlocks, + std::vector *shaderStorageBlocks, + ShHashFunction64 hashFunction, + TSymbolTable *symbolTable, + GLenum shaderType, + const TExtensionBehavior &extensionBehavior, + const ShBuiltInResources &resources, + int tessControlShaderOutputVertices) + : TIntermTraverser(true, false, false, symbolTable), + mAttribs(attribs), + mOutputVariables(outputVariables), + mUniforms(uniforms), + mInputVaryings(inputVaryings), + mOutputVaryings(outputVaryings), + mSharedVariables(sharedVariables), + mUniformBlocks(uniformBlocks), + mShaderStorageBlocks(shaderStorageBlocks), + mDepthRangeAdded(false), + mNumSamplesAdded(false), + mNumWorkGroupsAdded(false), + mWorkGroupIDAdded(false), + mLocalInvocationIDAdded(false), + mGlobalInvocationIDAdded(false), + mLocalInvocationIndexAdded(false), + mInstanceIDAdded(false), + mVertexIDAdded(false), + mPointSizeAdded(false), + mDrawIDAdded(false), + mPositionAdded(false), + mClipDistanceAdded(false), + mCullDistanceAdded(false), + mPointCoordAdded(false), + mFrontFacingAdded(false), + mHelperInvocationAdded(false), + mFragCoordAdded(false), + mLastFragDataAdded(false), + mFragColorAdded(false), + mFragDataAdded(false), + mFragDepthAdded(false), + mSecondaryFragColorEXTAdded(false), + mSecondaryFragDataEXTAdded(false), + mSampleIDAdded(false), + mSamplePositionAdded(false), + mSampleMaskAdded(false), + mSampleMaskInAdded(false), + mPerVertexInAdded(false), + mPerVertexOutAdded(false), + mPrimitiveIDInAdded(false), + mInvocationIDAdded(false), + mPrimitiveIDAdded(false), + mLayerAdded(false), + mSharedVariableAdded(false), + mPatchVerticesInAdded(false), + mTessLevelOuterAdded(false), + mTessLevelInnerAdded(false), + mBoundingBoxAdded(false), + mTessCoordAdded(false), + mTessControlShaderOutputVertices(tessControlShaderOutputVertices), + mHashFunction(hashFunction), + mShaderType(shaderType), + mExtensionBehavior(extensionBehavior), + mResources(resources) +{} + +std::string CollectVariablesTraverser::getMappedName(const TSymbol *symbol) const +{ + return HashName(symbol, mHashFunction, nullptr).data(); +} + +void CollectVariablesTraverser::setBuiltInInfoFromSymbol(const TVariable &variable, + ShaderVariable *info) +{ + const TType &type = variable.getType(); + + info->name = variable.name().data(); + info->mappedName = variable.name().data(); + + bool isShaderIOBlock = + IsShaderIoBlock(type.getQualifier()) && type.getInterfaceBlock() != nullptr; + bool isPatch = type.getQualifier() == EvqTessLevelInner || + type.getQualifier() == EvqTessLevelOuter || + type.getQualifier() == EvqBoundingBox; + + setFieldOrVariableProperties(type, true, isShaderIOBlock, isPatch, info); +} + +void CollectVariablesTraverser::recordBuiltInVaryingUsed(const TVariable &variable, + bool *addedFlag, + std::vector *varyings) +{ + ASSERT(varyings); + if (!(*addedFlag)) + { + ShaderVariable info; + setBuiltInInfoFromSymbol(variable, &info); + info.active = true; + info.isInvariant = mSymbolTable->isVaryingInvariant(variable); + + varyings->push_back(info); + (*addedFlag) = true; + } +} + +void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const TVariable &variable, + bool *addedFlag) +{ + if (!(*addedFlag)) + { + ShaderVariable info; + setBuiltInInfoFromSymbol(variable, &info); + info.active = true; + mOutputVariables->push_back(info); + (*addedFlag) = true; + } +} + +void CollectVariablesTraverser::recordBuiltInAttributeUsed(const TVariable &variable, + bool *addedFlag) +{ + if (!(*addedFlag)) + { + ShaderVariable info; + setBuiltInInfoFromSymbol(variable, &info); + info.active = true; + info.location = -1; + mAttribs->push_back(info); + (*addedFlag) = true; + } +} + +bool CollectVariablesTraverser::visitGlobalQualifierDeclaration( + Visit visit, + TIntermGlobalQualifierDeclaration *node) +{ + // We should not mark variables as active just based on an invariant/precise declaration, so we + // don't traverse the symbols declared invariant. + return false; +} + +// We want to check whether a uniform/varying is active because we need to skip updating inactive +// ones. We also only count the active ones in packing computing. Also, gl_FragCoord, gl_PointCoord, +// and gl_FrontFacing count toward varying counting if they are active in a fragment shader. +void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol) +{ + ASSERT(symbol != nullptr); + + if (symbol->variable().symbolType() == SymbolType::AngleInternal || + symbol->variable().symbolType() == SymbolType::Empty) + { + // Internal variables or nameless variables are not collected. + return; + } + + ShaderVariable *var = nullptr; + + const ImmutableString &symbolName = symbol->getName(); + + // Check the qualifier from the variable, not from the symbol node. The node may have a + // different qualifier if it's the result of a folded ternary node. + TQualifier qualifier = symbol->variable().getType().getQualifier(); + const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock(); + + if (IsVaryingIn(qualifier)) + { + if (interfaceBlock) + { + var = FindShaderIOBlockVariable(interfaceBlock->name(), mInputVaryings); + } + else + { + var = FindVariable(symbolName, mInputVaryings); + } + } + else if (IsVaryingOut(qualifier)) + { + if (interfaceBlock) + { + var = FindShaderIOBlockVariable(interfaceBlock->name(), mOutputVaryings); + } + else + { + var = FindVariable(symbolName, mOutputVaryings); + } + } + else if (symbol->getType().getBasicType() == EbtInterfaceBlock) + { + UNREACHABLE(); + } + else if (symbolName == "gl_DepthRange") + { + ASSERT(qualifier == EvqUniform); + + if (!mDepthRangeAdded) + { + ShaderVariable info; + const char kName[] = "gl_DepthRange"; + info.name = kName; + info.mappedName = kName; + info.type = GL_NONE; + info.precision = GL_NONE; + info.staticUse = true; + info.active = true; + + ShaderVariable nearInfo(GL_FLOAT); + const char kNearName[] = "near"; + nearInfo.name = kNearName; + nearInfo.mappedName = kNearName; + nearInfo.precision = GL_HIGH_FLOAT; + nearInfo.staticUse = true; + nearInfo.active = true; + + ShaderVariable farInfo(GL_FLOAT); + const char kFarName[] = "far"; + farInfo.name = kFarName; + farInfo.mappedName = kFarName; + farInfo.precision = GL_HIGH_FLOAT; + farInfo.staticUse = true; + farInfo.active = true; + + ShaderVariable diffInfo(GL_FLOAT); + const char kDiffName[] = "diff"; + diffInfo.name = kDiffName; + diffInfo.mappedName = kDiffName; + diffInfo.precision = GL_HIGH_FLOAT; + diffInfo.staticUse = true; + diffInfo.active = true; + + info.fields.push_back(nearInfo); + info.fields.push_back(farInfo); + info.fields.push_back(diffInfo); + + mUniforms->push_back(info); + mDepthRangeAdded = true; + } + } + else if (symbolName == "gl_NumSamples") + { + ASSERT(qualifier == EvqUniform); + + if (!mNumSamplesAdded) + { + ShaderVariable info; + const char kName[] = "gl_NumSamples"; + info.name = kName; + info.mappedName = kName; + info.type = GL_INT; + info.precision = GL_LOW_INT; + info.staticUse = true; + info.active = true; + + mUniforms->push_back(info); + mNumSamplesAdded = true; + } + } + else + { + switch (qualifier) + { + case EvqAttribute: + case EvqVertexIn: + var = FindVariable(symbolName, mAttribs); + break; + case EvqFragmentOut: + case EvqFragmentInOut: + var = FindVariable(symbolName, mOutputVariables); + var->isFragmentInOut = qualifier == EvqFragmentInOut; + break; + case EvqUniform: + { + if (interfaceBlock) + { + var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks); + } + else + { + var = FindVariable(symbolName, mUniforms); + } + + // It's an internal error to reference an undefined user uniform + ASSERT(!gl::IsBuiltInName(symbolName.data()) || var); + } + break; + case EvqBuffer: + { + var = + FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks); + } + break; + case EvqFragCoord: + recordBuiltInVaryingUsed(symbol->variable(), &mFragCoordAdded, mInputVaryings); + return; + case EvqFrontFacing: + recordBuiltInVaryingUsed(symbol->variable(), &mFrontFacingAdded, mInputVaryings); + return; + case EvqHelperInvocation: + recordBuiltInVaryingUsed(symbol->variable(), &mHelperInvocationAdded, + mInputVaryings); + return; + case EvqPointCoord: + recordBuiltInVaryingUsed(symbol->variable(), &mPointCoordAdded, mInputVaryings); + return; + case EvqNumWorkGroups: + recordBuiltInAttributeUsed(symbol->variable(), &mNumWorkGroupsAdded); + return; + case EvqWorkGroupID: + recordBuiltInAttributeUsed(symbol->variable(), &mWorkGroupIDAdded); + return; + case EvqLocalInvocationID: + recordBuiltInAttributeUsed(symbol->variable(), &mLocalInvocationIDAdded); + return; + case EvqGlobalInvocationID: + recordBuiltInAttributeUsed(symbol->variable(), &mGlobalInvocationIDAdded); + return; + case EvqLocalInvocationIndex: + recordBuiltInAttributeUsed(symbol->variable(), &mLocalInvocationIndexAdded); + return; + case EvqInstanceID: + // Whenever the initializeBuiltinsForInstancedMultiview option is set, + // gl_InstanceID is added inside expressions to initialize ViewID_OVR and + // InstanceID. Note that gl_InstanceID is not added to the symbol table for ESSL1 + // shaders. + recordBuiltInAttributeUsed(symbol->variable(), &mInstanceIDAdded); + return; + case EvqVertexID: + recordBuiltInAttributeUsed(symbol->variable(), &mVertexIDAdded); + return; + case EvqPosition: + recordBuiltInVaryingUsed(symbol->variable(), &mPositionAdded, mOutputVaryings); + return; + case EvqPointSize: + recordBuiltInVaryingUsed(symbol->variable(), &mPointSizeAdded, mOutputVaryings); + return; + case EvqDrawID: + recordBuiltInAttributeUsed(symbol->variable(), &mDrawIDAdded); + return; + case EvqLastFragData: + recordBuiltInVaryingUsed(symbol->variable(), &mLastFragDataAdded, mInputVaryings); + return; + case EvqFragColor: + recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragColorAdded); + return; + case EvqFragData: + recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDataAdded); + return; + case EvqFragDepth: + recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDepthAdded); + return; + case EvqSecondaryFragColorEXT: + recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragColorEXTAdded); + return; + case EvqSecondaryFragDataEXT: + recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragDataEXTAdded); + return; + case EvqInvocationID: + recordBuiltInVaryingUsed(symbol->variable(), &mInvocationIDAdded, mInputVaryings); + break; + case EvqPrimitiveIDIn: + recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDInAdded, mInputVaryings); + break; + case EvqPrimitiveID: + if (mShaderType == GL_GEOMETRY_SHADER_EXT) + { + recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded, + mOutputVaryings); + } + else + { + ASSERT(mShaderType == GL_FRAGMENT_SHADER || + mShaderType == GL_TESS_CONTROL_SHADER || + mShaderType == GL_TESS_EVALUATION_SHADER); + recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded, + mInputVaryings); + } + break; + case EvqLayerOut: + if (mShaderType == GL_GEOMETRY_SHADER_EXT) + { + recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mOutputVaryings); + } + else + { + ASSERT(mShaderType == GL_VERTEX_SHADER && + (IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview2) || + IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview))); + } + break; + case EvqLayerIn: + ASSERT(mShaderType == GL_FRAGMENT_SHADER); + recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mInputVaryings); + break; + case EvqShared: + if (mShaderType == GL_COMPUTE_SHADER) + { + recordBuiltInVaryingUsed(symbol->variable(), &mSharedVariableAdded, + mSharedVariables); + } + break; + case EvqClipDistance: + recordBuiltInVaryingUsed( + symbol->variable(), &mClipDistanceAdded, + mShaderType == GL_FRAGMENT_SHADER ? mInputVaryings : mOutputVaryings); + return; + case EvqCullDistance: + recordBuiltInVaryingUsed( + symbol->variable(), &mCullDistanceAdded, + mShaderType == GL_FRAGMENT_SHADER ? mInputVaryings : mOutputVaryings); + return; + case EvqSampleID: + recordBuiltInVaryingUsed(symbol->variable(), &mSampleIDAdded, mInputVaryings); + return; + case EvqSamplePosition: + recordBuiltInVaryingUsed(symbol->variable(), &mSamplePositionAdded, mInputVaryings); + return; + case EvqSampleMaskIn: + recordBuiltInVaryingUsed(symbol->variable(), &mSampleMaskInAdded, mInputVaryings); + return; + case EvqSampleMask: + recordBuiltInFragmentOutputUsed(symbol->variable(), &mSampleMaskAdded); + return; + case EvqPatchVerticesIn: + recordBuiltInVaryingUsed(symbol->variable(), &mPatchVerticesInAdded, + mInputVaryings); + break; + case EvqTessCoord: + recordBuiltInVaryingUsed(symbol->variable(), &mTessCoordAdded, mInputVaryings); + break; + case EvqTessLevelOuter: + if (mShaderType == GL_TESS_CONTROL_SHADER) + { + recordBuiltInVaryingUsed(symbol->variable(), &mTessLevelOuterAdded, + mOutputVaryings); + } + else + { + ASSERT(mShaderType == GL_TESS_EVALUATION_SHADER); + recordBuiltInVaryingUsed(symbol->variable(), &mTessLevelOuterAdded, + mInputVaryings); + } + break; + case EvqTessLevelInner: + if (mShaderType == GL_TESS_CONTROL_SHADER) + { + recordBuiltInVaryingUsed(symbol->variable(), &mTessLevelInnerAdded, + mOutputVaryings); + } + else + { + ASSERT(mShaderType == GL_TESS_EVALUATION_SHADER); + recordBuiltInVaryingUsed(symbol->variable(), &mTessLevelInnerAdded, + mInputVaryings); + } + break; + case EvqBoundingBox: + recordBuiltInVaryingUsed(symbol->variable(), &mBoundingBoxAdded, mOutputVaryings); + break; + default: + break; + } + } + if (var) + { + MarkActive(var); + } +} + +void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type, + bool staticUse, + bool isShaderIOBlock, + bool isPatch, + ShaderVariable *variableOut) const +{ + ASSERT(variableOut); + + variableOut->staticUse = staticUse; + variableOut->isShaderIOBlock = isShaderIOBlock; + variableOut->isPatch = isPatch; + + const TStructure *structure = type.getStruct(); + const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + if (structure) + { + // Structures use a NONE type that isn't exposed outside ANGLE. + variableOut->type = GL_NONE; + if (structure->symbolType() != SymbolType::Empty) + { + variableOut->structOrBlockName = structure->name().data(); + } + + const TFieldList &fields = structure->fields(); + + for (const TField *field : fields) + { + // Regardless of the variable type (uniform, in/out etc.) its fields are always plain + // ShaderVariable objects. + ShaderVariable fieldVariable; + setFieldProperties(*field->type(), field->name(), staticUse, isShaderIOBlock, isPatch, + field->symbolType(), &fieldVariable); + variableOut->fields.push_back(fieldVariable); + } + } + else if (interfaceBlock && isShaderIOBlock) + { + const bool isPerVertex = (interfaceBlock->name() == "gl_PerVertex"); + variableOut->type = GL_NONE; + if (interfaceBlock->symbolType() != SymbolType::Empty) + { + variableOut->structOrBlockName = interfaceBlock->name().data(); + variableOut->mappedStructOrBlockName = + isPerVertex ? interfaceBlock->name().data() + : HashName(interfaceBlock->name(), mHashFunction, nullptr).data(); + } + const TFieldList &fields = interfaceBlock->fields(); + for (const TField *field : fields) + { + ShaderVariable fieldVariable; + + setFieldProperties(*field->type(), field->name(), staticUse, true, isPatch, + field->symbolType(), &fieldVariable); + fieldVariable.isShaderIOBlock = true; + variableOut->fields.push_back(fieldVariable); + } + } + else + { + variableOut->type = GLVariableType(type); + variableOut->precision = GLVariablePrecision(type); + } + + const TSpan &arraySizes = type.getArraySizes(); + if (!arraySizes.empty()) + { + variableOut->arraySizes.assign(arraySizes.begin(), arraySizes.end()); + + if (arraySizes[0] == 0) + { + // Tessellation Control & Evaluation shader inputs: + // Declaring an array size is optional. If no size is specified, it will be taken from + // the implementation-dependent maximum patch size (gl_MaxPatchVertices). + if (type.getQualifier() == EvqTessControlIn || + type.getQualifier() == EvqTessEvaluationIn) + { + variableOut->arraySizes[0] = mResources.MaxPatchVertices; + } + + // Tessellation Control shader outputs: + // Declaring an array size is optional. If no size is specified, it will be taken from + // output patch size declared in the shader. + if (type.getQualifier() == EvqTessControlOut) + { + ASSERT(mTessControlShaderOutputVertices > 0); + variableOut->arraySizes[0] = mTessControlShaderOutputVertices; + } + } + } +} + +void CollectVariablesTraverser::setFieldProperties(const TType &type, + const ImmutableString &name, + bool staticUse, + bool isShaderIOBlock, + bool isPatch, + SymbolType symbolType, + ShaderVariable *variableOut) const +{ + ASSERT(variableOut); + setFieldOrVariableProperties(type, staticUse, isShaderIOBlock, isPatch, variableOut); + variableOut->name.assign(name.data(), name.length()); + variableOut->mappedName = (symbolType == SymbolType::BuiltIn) + ? name.data() + : HashName(name, mHashFunction, nullptr).data(); +} + +void CollectVariablesTraverser::setCommonVariableProperties(const TType &type, + const TVariable &variable, + ShaderVariable *variableOut) const +{ + ASSERT(variableOut); + ASSERT(type.getInterfaceBlock() == nullptr || IsShaderIoBlock(type.getQualifier()) || + type.getQualifier() == EvqPatchIn || type.getQualifier() == EvqPatchOut); + + const bool staticUse = mSymbolTable->isStaticallyUsed(variable); + const bool isShaderIOBlock = type.getInterfaceBlock() != nullptr; + const bool isPatch = type.getQualifier() == EvqPatchIn || type.getQualifier() == EvqPatchOut; + + setFieldOrVariableProperties(type, staticUse, isShaderIOBlock, isPatch, variableOut); + + const bool isNamed = variable.symbolType() != SymbolType::Empty; + + ASSERT(isNamed || isShaderIOBlock); + if (isNamed) + { + variableOut->name.assign(variable.name().data(), variable.name().length()); + variableOut->mappedName = getMappedName(&variable); + } + + // For I/O blocks, additionally store the name of the block as blockName. If the variable is + // unnamed, this name will be used instead for the purpose of interface matching. + if (isShaderIOBlock) + { + const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + ASSERT(interfaceBlock); + + variableOut->structOrBlockName.assign(interfaceBlock->name().data(), + interfaceBlock->name().length()); + variableOut->mappedStructOrBlockName = + HashName(interfaceBlock->name(), mHashFunction, nullptr).data(); + variableOut->isShaderIOBlock = true; + } +} + +ShaderVariable CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const +{ + const TType &type = variable.getType(); + ASSERT(!type.getStruct()); + + ShaderVariable attribute; + setCommonVariableProperties(type, variable.variable(), &attribute); + + attribute.location = type.getLayoutQualifier().location; + return attribute; +} + +ShaderVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const +{ + const TType &type = variable.getType(); + ASSERT(!type.getStruct()); + + ShaderVariable outputVariable; + setCommonVariableProperties(type, variable.variable(), &outputVariable); + + outputVariable.location = type.getLayoutQualifier().location; + outputVariable.index = type.getLayoutQualifier().index; + outputVariable.yuv = type.getLayoutQualifier().yuv; + return outputVariable; +} + +ShaderVariable CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const +{ + const TType &type = variable.getType(); + + ShaderVariable varying; + setCommonVariableProperties(type, variable.variable(), &varying); + varying.location = type.getLayoutQualifier().location; + + switch (type.getQualifier()) + { + case EvqVaryingIn: + case EvqVaryingOut: + case EvqVertexOut: + case EvqSmoothOut: + case EvqFlatOut: + case EvqNoPerspectiveOut: + case EvqCentroidOut: + case EvqGeometryOut: + case EvqSampleOut: + if (mSymbolTable->isVaryingInvariant(variable.variable()) || type.isInvariant()) + { + varying.isInvariant = true; + } + break; + case EvqPatchIn: + case EvqPatchOut: + varying.isPatch = true; + break; + default: + break; + } + + varying.interpolation = GetInterpolationType(type.getQualifier()); + + // Shader I/O block properties + if (type.getBasicType() == EbtInterfaceBlock) + { + bool isBlockImplicitLocation = false; + int location = type.getLayoutQualifier().location; + + // when a interface has not location in layout, assign to the zero. + if (location < 0) + { + location = 0; + isBlockImplicitLocation = true; + } + + const TInterfaceBlock *blockType = type.getInterfaceBlock(); + ASSERT(blockType->fields().size() == varying.fields.size()); + + for (size_t fieldIndex = 0; fieldIndex < varying.fields.size(); ++fieldIndex) + { + const TField *blockField = blockType->fields()[fieldIndex]; + ShaderVariable &fieldVariable = varying.fields[fieldIndex]; + const TType &fieldType = *blockField->type(); + + fieldVariable.hasImplicitLocation = isBlockImplicitLocation; + fieldVariable.isPatch = varying.isPatch; + + int fieldLocation = fieldType.getLayoutQualifier().location; + if (fieldLocation >= 0) + { + fieldVariable.hasImplicitLocation = false; + fieldVariable.location = fieldLocation; + location = fieldLocation; + } + else + { + fieldVariable.location = location; + location += fieldType.getLocationCount(); + } + + if (fieldType.getQualifier() != EvqGlobal) + { + fieldVariable.interpolation = GetFieldInterpolationType(fieldType.getQualifier()); + } + } + } + + return varying; +} + +void CollectVariablesTraverser::recordInterfaceBlock(const char *instanceName, + const TType &interfaceBlockType, + InterfaceBlock *interfaceBlock) const +{ + ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock); + ASSERT(interfaceBlock); + + const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock(); + ASSERT(blockType); + + interfaceBlock->name = blockType->name().data(); + interfaceBlock->mappedName = getMappedName(blockType); + + const bool isGLInBuiltin = (instanceName != nullptr) && strncmp(instanceName, "gl_in", 5u) == 0; + if (instanceName != nullptr) + { + interfaceBlock->instanceName = instanceName; + const TSymbol *blockSymbol = nullptr; + if (isGLInBuiltin) + { + blockSymbol = mSymbolTable->getGlInVariableWithArraySize(); + } + else + { + blockSymbol = mSymbolTable->findGlobal(ImmutableString(instanceName)); + } + ASSERT(blockSymbol && blockSymbol->isVariable()); + interfaceBlock->staticUse = + mSymbolTable->isStaticallyUsed(*static_cast(blockSymbol)); + } + + ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9 + interfaceBlock->arraySize = + interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0; + + interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier()); + if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM || + interfaceBlock->blockType == BlockType::BLOCK_BUFFER) + { + // TODO(oetuaho): Remove setting isRowMajorLayout. + interfaceBlock->isRowMajorLayout = false; + interfaceBlock->binding = blockType->blockBinding(); + interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage()); + } + + // Gather field information + bool anyFieldStaticallyUsed = false; + + for (const TField *field : blockType->fields()) + { + const TType &fieldType = *field->type(); + + bool staticUse = false; + if (instanceName == nullptr) + { + // Static use of individual fields has been recorded, since they are present in the + // symbol table as variables. + const TSymbol *fieldSymbol = mSymbolTable->findGlobal(field->name()); + ASSERT(fieldSymbol && fieldSymbol->isVariable()); + staticUse = + mSymbolTable->isStaticallyUsed(*static_cast(fieldSymbol)); + if (staticUse) + { + anyFieldStaticallyUsed = true; + } + } + + ShaderVariable fieldVariable; + setFieldProperties(fieldType, field->name(), staticUse, false, false, field->symbolType(), + &fieldVariable); + fieldVariable.isRowMajorLayout = + (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); + interfaceBlock->fields.push_back(fieldVariable); + } + if (anyFieldStaticallyUsed) + { + interfaceBlock->staticUse = true; + } +} + +ShaderVariable CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const +{ + ShaderVariable uniform; + setCommonVariableProperties(variable.getType(), variable.variable(), &uniform); + uniform.binding = variable.getType().getLayoutQualifier().binding; + uniform.imageUnitFormat = + GetImageInternalFormatType(variable.getType().getLayoutQualifier().imageInternalFormat); + uniform.location = variable.getType().getLayoutQualifier().location; + uniform.offset = variable.getType().getLayoutQualifier().offset; + uniform.rasterOrdered = variable.getType().getLayoutQualifier().rasterOrdered; + uniform.readonly = variable.getType().getMemoryQualifier().readonly; + uniform.writeonly = variable.getType().getMemoryQualifier().writeonly; + return uniform; +} + +bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node) +{ + const TIntermSequence &sequence = *(node->getSequence()); + ASSERT(!sequence.empty()); + + const TIntermTyped &typedNode = *(sequence.front()->getAsTyped()); + TQualifier qualifier = typedNode.getQualifier(); + + bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn || + qualifier == EvqFragmentOut || qualifier == EvqFragmentInOut || + qualifier == EvqUniform || IsVarying(qualifier); + + if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable) + { + return true; + } + + for (TIntermNode *variableNode : sequence) + { + // The only case in which the sequence will not contain a TIntermSymbol node is + // initialization. It will contain a TInterBinary node in that case. Since attributes, + // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we + // must have only TIntermSymbol nodes in the sequence in the cases we are interested in. + const TIntermSymbol &variable = *variableNode->getAsSymbolNode(); + if (variable.variable().symbolType() == SymbolType::AngleInternal) + { + // Internal variables are not collected. + continue; + } + + // SpirvTransformer::transform uses a map of ShaderVariables, it needs member variables and + // (named or unnamed) structure as ShaderVariable. at link between two shaders, validation + // between of named and unnamed, needs the same structure, its members, and members order + // except instance name. + if (typedNode.getBasicType() == EbtInterfaceBlock && !IsShaderIoBlock(qualifier) && + qualifier != EvqPatchIn && qualifier != EvqPatchOut) + { + InterfaceBlock interfaceBlock; + bool isUnnamed = variable.variable().symbolType() == SymbolType::Empty; + const TType &type = variable.getType(); + recordInterfaceBlock(isUnnamed ? nullptr : variable.getName().data(), type, + &interfaceBlock); + + // all fields in interface block will be added for updating interface variables because + // the temporal structure variable will be ignored. + switch (qualifier) + { + case EvqUniform: + mUniformBlocks->push_back(interfaceBlock); + break; + case EvqBuffer: + mShaderStorageBlocks->push_back(interfaceBlock); + break; + default: + UNREACHABLE(); + } + } + else + { + ASSERT(variable.variable().symbolType() != SymbolType::Empty || + IsShaderIoBlock(qualifier) || qualifier == EvqPatchIn || + qualifier == EvqPatchOut); + switch (qualifier) + { + case EvqAttribute: + case EvqVertexIn: + mAttribs->push_back(recordAttribute(variable)); + break; + case EvqFragmentOut: + case EvqFragmentInOut: + mOutputVariables->push_back(recordOutputVariable(variable)); + break; + case EvqUniform: + mUniforms->push_back(recordUniform(variable)); + break; + default: + if (IsVaryingIn(qualifier)) + { + mInputVaryings->push_back(recordVarying(variable)); + } + else + { + ASSERT(IsVaryingOut(qualifier)); + mOutputVaryings->push_back(recordVarying(variable)); + } + break; + } + } + } + + // None of the recorded variables can have initializers, so we don't need to traverse the + // declarators. + return false; +} + +InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock( + const ImmutableString &blockName) const +{ + InterfaceBlock *namedBlock = FindVariable(blockName, mUniformBlocks); + if (!namedBlock) + { + namedBlock = FindVariable(blockName, mShaderStorageBlocks); + } + return namedBlock; +} + +bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode) +{ + if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock) + { + // NOTE: we do not determine static use / activeness for individual blocks of an array. + TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped(); + ASSERT(blockNode); + + TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion(); + ASSERT(constantUnion); + + InterfaceBlock *namedBlock = nullptr; + + bool traverseIndexExpression = false; + TIntermBinary *interfaceIndexingNode = blockNode->getAsBinaryNode(); + if (interfaceIndexingNode) + { + ASSERT(interfaceIndexingNode->getOp() == EOpIndexDirect || + interfaceIndexingNode->getOp() == EOpIndexIndirect); + traverseIndexExpression = true; + blockNode = interfaceIndexingNode->getLeft(); + } + + const TType &interfaceNodeType = blockNode->getType(); + const TInterfaceBlock *interfaceBlock = interfaceNodeType.getInterfaceBlock(); + const TQualifier qualifier = interfaceNodeType.getQualifier(); + + // If it's a shader I/O block, look in varyings + ShaderVariable *ioBlockVar = nullptr; + if (qualifier == EvqPerVertexIn) + { + TIntermSymbol *symbolNode = blockNode->getAsSymbolNode(); + ASSERT(symbolNode); + recordBuiltInVaryingUsed(symbolNode->variable(), &mPerVertexInAdded, mInputVaryings); + ioBlockVar = FindShaderIOBlockVariable(interfaceBlock->name(), mInputVaryings); + } + else if (IsVaryingIn(qualifier)) + { + ioBlockVar = FindShaderIOBlockVariable(interfaceBlock->name(), mInputVaryings); + } + else if (qualifier == EvqPerVertexOut) + { + TIntermSymbol *symbolNode = blockNode->getAsSymbolNode(); + ASSERT(symbolNode); + recordBuiltInVaryingUsed(symbolNode->variable(), &mPerVertexOutAdded, mOutputVaryings); + ioBlockVar = FindShaderIOBlockVariable(interfaceBlock->name(), mOutputVaryings); + } + else if (IsVaryingOut(qualifier)) + { + ioBlockVar = FindShaderIOBlockVariable(interfaceBlock->name(), mOutputVaryings); + } + + if (ioBlockVar) + { + MarkActive(ioBlockVar); + } + else + { + if (!namedBlock) + { + namedBlock = findNamedInterfaceBlock(interfaceBlock->name()); + } + ASSERT(namedBlock); + ASSERT(namedBlock->staticUse); + namedBlock->active = true; + unsigned int fieldIndex = static_cast(constantUnion->getIConst(0)); + ASSERT(fieldIndex < namedBlock->fields.size()); + // TODO(oetuaho): Would be nicer to record static use of fields of named interface + // blocks more accurately at parse time - now we only mark the fields statically used if + // they are active. http://anglebug.com/2440 We need to mark this field and all of its + // sub-fields, as static/active + MarkActive(&namedBlock->fields[fieldIndex]); + } + + if (traverseIndexExpression) + { + ASSERT(interfaceIndexingNode); + interfaceIndexingNode->getRight()->traverse(this); + } + return false; + } + + return true; +} + +} // anonymous namespace + +void CollectVariables(TIntermBlock *root, + std::vector *attributes, + std::vector *outputVariables, + std::vector *uniforms, + std::vector *inputVaryings, + std::vector *outputVaryings, + std::vector *sharedVariables, + std::vector *uniformBlocks, + std::vector *shaderStorageBlocks, + ShHashFunction64 hashFunction, + TSymbolTable *symbolTable, + GLenum shaderType, + const TExtensionBehavior &extensionBehavior, + const ShBuiltInResources &resources, + int tessControlShaderOutputVertices) +{ + CollectVariablesTraverser collect( + attributes, outputVariables, uniforms, inputVaryings, outputVaryings, sharedVariables, + uniformBlocks, shaderStorageBlocks, hashFunction, symbolTable, shaderType, + extensionBehavior, resources, tessControlShaderOutputVertices); + root->traverse(&collect); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/CollectVariables.h b/gfx/angle/checkout/src/compiler/translator/CollectVariables.h new file mode 100644 index 0000000000..6ea4b172a0 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/CollectVariables.h @@ -0,0 +1,38 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// CollectVariables.h: Collect lists of shader interface variables based on the AST. + +#ifndef COMPILER_TRANSLATOR_COLLECTVARIABLES_H_ +#define COMPILER_TRANSLATOR_COLLECTVARIABLES_H_ + +#include + +#include "compiler/translator/ExtensionBehavior.h" + +namespace sh +{ + +class TIntermBlock; +class TSymbolTable; + +void CollectVariables(TIntermBlock *root, + std::vector *attributes, + std::vector *outputVariables, + std::vector *uniforms, + std::vector *inputVaryings, + std::vector *outputVaryings, + std::vector *sharedVariables, + std::vector *uniformBlocks, + std::vector *shaderStorageBlocks, + ShHashFunction64 hashFunction, + TSymbolTable *symbolTable, + GLenum shaderType, + const TExtensionBehavior &extensionBehavior, + const ShBuiltInResources &resources, + int tessControlShaderOutputVertices); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_COLLECTVARIABLES_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/Common.h b/gfx/angle/checkout/src/compiler/translator/Common.h new file mode 100644 index 0000000000..77907fc3a4 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Common.h @@ -0,0 +1,256 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_COMMON_H_ +#define COMPILER_TRANSLATOR_COMMON_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "common/angleutils.h" +#include "common/debug.h" +#include "common/third_party/smhasher/src/PMurHash.h" +#include "compiler/translator/PoolAlloc.h" + +namespace sh +{ + +struct TSourceLoc +{ + int first_file; + int first_line; + int last_file; + int last_line; +}; + +constexpr TSourceLoc kNoSourceLoc{-1, -1, -1, -1}; + +// +// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. +// +#define POOL_ALLOCATOR_NEW_DELETE \ + void *operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ + void *operator new(size_t, void *_Where) { return (_Where); } \ + void operator delete(void *) {} \ + void operator delete(void *, void *) {} \ + void *operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ + void *operator new[](size_t, void *_Where) { return (_Where); } \ + void operator delete[](void *) {} \ + void operator delete[](void *, void *) {} + +// +// Pool version of string. +// +typedef pool_allocator TStringAllocator; +typedef std::basic_string, TStringAllocator> TString; +typedef std::basic_ostringstream, TStringAllocator> TStringStream; + +// +// Persistent memory. Should only be used for strings that survive across compiles. +// +using TPersistString = std::string; +using TPersistStringStream = std::ostringstream; + +// +// Pool allocator versions of vectors, lists, and maps +// +template +class TVector : public std::vector> +{ + public: + POOL_ALLOCATOR_NEW_DELETE + + typedef typename std::vector>::size_type size_type; + TVector() : std::vector>() {} + TVector(const pool_allocator &a) : std::vector>(a) {} + TVector(size_type i) : std::vector>(i) {} + TVector(size_type i, const T &value) : std::vector>(i, value) {} + template + TVector(InputIt first, InputIt last) : std::vector>(first, last) + {} + TVector(std::initializer_list init) : std::vector>(init) {} +}; + +template , class CMP = std::equal_to> +class TUnorderedMap : public std::unordered_map>> +{ + public: + POOL_ALLOCATOR_NEW_DELETE + typedef pool_allocator> tAllocator; + + TUnorderedMap() : std::unordered_map() {} + // use correct two-stage name lookup supported in gcc 3.4 and above + TUnorderedMap(const tAllocator &a) + : std::unordered_map( + std::unordered_map::key_compare(), + a) + {} +}; + +template > +class TMap : public std::map>> +{ + public: + POOL_ALLOCATOR_NEW_DELETE + typedef pool_allocator> tAllocator; + + TMap() : std::map() {} + // use correct two-stage name lookup supported in gcc 3.4 and above + TMap(const tAllocator &a) + : std::map(std::map::key_compare(), a) + {} +}; + +// Basic implementation of C++20's span for use with pool-allocated containers (TVector) or static +// arrays. This is used by the array sizes member of TType to allow arrayed types to be +// constexpr-constructed. +// See the reference for std::span here: https://en.cppreference.com/w/cpp/container/span +template +class TSpan +{ + public: + typedef size_t size_type; + + constexpr TSpan() {} + constexpr TSpan(T *ptr, size_type size) : mData(ptr), mSize(size) {} + + constexpr TSpan(const TSpan &that) : mData(that.mData), mSize(that.mSize) {} + constexpr TSpan &operator=(const TSpan &that) + { + mData = that.mData; + mSize = that.mSize; + return *this; + } + + // Note: the pointer is taken out of the TVector because TVector's memory is pool allocated, + // so the memory will live on even if the TVector is destroyed. + template + TSpan(const TVector &vec) : mData(vec.data()), mSize(vec.size()) + {} + template + TSpan &operator=(const TVector &vec) + { + mData = vec.data(); + mSize = vec.size(); + return *this; + } + + constexpr bool operator==(const TSpan &that) const + { + if (mSize != that.mSize) + { + return false; + } + + if (mData == that.mData) + { + return true; + } + + for (size_type index = 0; index < mSize; ++index) + { + if (mData[index] != that.mData[index]) + { + return false; + } + } + + return true; + } + constexpr bool operator!=(const TSpan &that) const { return !(*this == that); } + + constexpr T *data() const { return mData; } + constexpr size_type size() const { return mSize; } + constexpr bool empty() const { return mSize == 0; } + + constexpr T &operator[](size_type index) const { return mData[index]; } + constexpr T &front() const { return mData[0]; } + constexpr T &back() const { return mData[mSize - 1]; } + + constexpr T *begin() const { return mData; } + constexpr T *end() const { return mData + mSize; } + + constexpr std::reverse_iterator rbegin() const + { + return std::make_reverse_iterator(end()); + } + constexpr std::reverse_iterator rend() const + { + return std::make_reverse_iterator(begin()); + } + + constexpr TSpan first(size_type count) const + { + ASSERT(count <= mSize); + return count == 0 ? TSpan() : TSpan(mData, count); + } + constexpr TSpan last(size_type count) const + { + ASSERT(count <= mSize); + return count == 0 ? TSpan() : TSpan(mData + mSize - count, count); + } + constexpr TSpan subspan(size_type offset, size_type count) const + { + ASSERT(offset + count <= mSize); + return count == 0 ? TSpan() : TSpan(mData + offset, count); + } + + private: + T *mData = nullptr; + size_t mSize = 0; +}; + +// Integer to TString conversion +template +inline TString str(T i) +{ + ASSERT(std::numeric_limits::is_integer); + char buffer[((8 * sizeof(T)) / 3) + 3]; + const char *formatStr = std::numeric_limits::is_signed ? "%d" : "%u"; + snprintf(buffer, sizeof(buffer), formatStr, i); + return buffer; +} + +// Allocate a char array in the global memory pool. str must be a null terminated string. strLength +// is the length without the null terminator. +inline const char *AllocatePoolCharArray(const char *str, size_t strLength) +{ + size_t requiredSize = strLength + 1; + char *buffer = static_cast(GetGlobalPoolAllocator()->allocate(requiredSize)); + memcpy(buffer, str, requiredSize); + ASSERT(buffer[strLength] == '\0'); + return buffer; +} + +// Initialize a new stream which must be imbued with the classic locale +template +T InitializeStream() +{ + T stream; + stream.imbue(std::locale::classic()); + return stream; +} + +} // namespace sh + +namespace std +{ +template <> +struct hash +{ + size_t operator()(const sh::TString &s) const + { + return angle::PMurHash32(0, s.data(), static_cast(s.length())); + } +}; +} // namespace std + +#endif // COMPILER_TRANSLATOR_COMMON_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/Compiler.cpp b/gfx/angle/checkout/src/compiler/translator/Compiler.cpp new file mode 100644 index 0000000000..891d1ddf61 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Compiler.cpp @@ -0,0 +1,1746 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/Compiler.h" + +#include + +#include "angle_gl.h" +#include "common/utilities.h" +#include "compiler/translator/CallDAG.h" +#include "compiler/translator/CollectVariables.h" +#include "compiler/translator/Initialize.h" +#include "compiler/translator/IsASTDepthBelowLimit.h" +#include "compiler/translator/OutputTree.h" +#include "compiler/translator/ParseContext.h" +#include "compiler/translator/ValidateBarrierFunctionCall.h" +#include "compiler/translator/ValidateClipCullDistance.h" +#include "compiler/translator/ValidateLimitations.h" +#include "compiler/translator/ValidateMaxParameters.h" +#include "compiler/translator/ValidateOutputs.h" +#include "compiler/translator/ValidateTypeSizeLimitations.h" +#include "compiler/translator/ValidateVaryingLocations.h" +#include "compiler/translator/VariablePacker.h" +#include "compiler/translator/tree_ops/ClampIndirectIndices.h" +#include "compiler/translator/tree_ops/ClampPointSize.h" +#include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h" +#include "compiler/translator/tree_ops/DeferGlobalInitializers.h" +#include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h" +#include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h" +#include "compiler/translator/tree_ops/FoldExpressions.h" +#include "compiler/translator/tree_ops/ForcePrecisionQualifier.h" +#include "compiler/translator/tree_ops/InitializeVariables.h" +#include "compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.h" +#include "compiler/translator/tree_ops/PruneEmptyCases.h" +#include "compiler/translator/tree_ops/PruneNoOps.h" +#include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h" +#include "compiler/translator/tree_ops/RemoveDynamicIndexing.h" +#include "compiler/translator/tree_ops/RemoveInvariantDeclaration.h" +#include "compiler/translator/tree_ops/RemoveUnreferencedVariables.h" +#include "compiler/translator/tree_ops/RewritePixelLocalStorage.h" +#include "compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h" +#include "compiler/translator/tree_ops/SeparateDeclarations.h" +#include "compiler/translator/tree_ops/SimplifyLoopConditions.h" +#include "compiler/translator/tree_ops/SplitSequenceOperator.h" +#include "compiler/translator/tree_ops/apple/AddAndTrueToLoopCondition.h" +#include "compiler/translator/tree_ops/apple/RewriteDoWhile.h" +#include "compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.h" +#include "compiler/translator/tree_ops/gl/ClampFragDepth.h" +#include "compiler/translator/tree_ops/gl/RegenerateStructNames.h" +#include "compiler/translator/tree_ops/gl/RewriteRepeatedAssignToSwizzled.h" +#include "compiler/translator/tree_ops/gl/UseInterfaceBlockFields.h" +#include "compiler/translator/tree_util/BuiltIn.h" +#include "compiler/translator/tree_util/IntermNodePatternMatcher.h" +#include "compiler/translator/tree_util/ReplaceShadowingVariables.h" +#include "compiler/translator/util.h" + +// #define ANGLE_FUZZER_CORPUS_OUTPUT_DIR "corpus/" + +#if defined(ANGLE_FUZZER_CORPUS_OUTPUT_DIR) +# include "common/hash_utils.h" +# include "common/mathutil.h" +#endif + +namespace sh +{ + +namespace +{ +// Helper that returns if a top-level node is unused. If it's a function, the function prototype is +// returned as well. +bool IsTopLevelNodeUnusedFunction(const CallDAG &callDag, + const std::vector &metadata, + TIntermNode *node, + const TFunction **functionOut) +{ + const TIntermFunctionPrototype *asFunctionPrototype = node->getAsFunctionPrototypeNode(); + const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition(); + + *functionOut = nullptr; + + if (asFunctionDefinition) + { + *functionOut = asFunctionDefinition->getFunction(); + } + else if (asFunctionPrototype) + { + *functionOut = asFunctionPrototype->getFunction(); + } + if (*functionOut == nullptr) + { + return false; + } + + size_t callDagIndex = callDag.findIndex((*functionOut)->uniqueId()); + if (callDagIndex == CallDAG::InvalidIndex) + { + // This happens only for unimplemented prototypes which are thus unused + ASSERT(asFunctionPrototype); + return true; + } + + ASSERT(callDagIndex < metadata.size()); + return !metadata[callDagIndex].used; +} + +#if defined(ANGLE_FUZZER_CORPUS_OUTPUT_DIR) +void DumpFuzzerCase(char const *const *shaderStrings, + size_t numStrings, + uint32_t type, + uint32_t spec, + uint32_t output, + const ShCompileOptions &options) +{ + ShaderDumpHeader header{}; + header.type = type; + header.spec = spec; + header.output = output; + memcpy(&header.basicCompileOptions, &options, offsetof(ShCompileOptions, metal)); + static_assert(offsetof(ShCompileOptions, metal) <= sizeof(header.basicCompileOptions)); + memcpy(&header.metalCompileOptions, &options.metal, sizeof(options.metal)); + static_assert(sizeof(options.metal) <= sizeof(header.metalCompileOptions)); + memcpy(&header.plsCompileOptions, &options.pls, sizeof(options.pls)); + static_assert(sizeof(options.pls) <= sizeof(header.plsCompileOptions)); + size_t contentsLength = sizeof(header) + 1; // Extra: header + nul terminator. + for (size_t i = 0; i < numStrings; i++) + { + contentsLength += strlen(shaderStrings[i]); + } + std::vector contents(rx::roundUp(contentsLength, 4), 0); + memcpy(&contents[0], &header, sizeof(header)); + uint8_t *data = &contents[sizeof(header)]; + for (size_t i = 0; i < numStrings; i++) + { + auto length = strlen(shaderStrings[i]); + memcpy(data, shaderStrings[i], length); + data += length; + } + auto hash = angle::ComputeGenericHash(contents.data(), contents.size()); + + std::ostringstream o = sh::InitializeStream(); + o << ANGLE_FUZZER_CORPUS_OUTPUT_DIR << std::hex << std::setw(16) << std::setfill('0') << hash + << ".sample"; + std::string s = o.str(); + + // Must match the input format of the fuzzer + FILE *f = fopen(s.c_str(), "w"); + fwrite(contents.data(), sizeof(char), contentsLength, f); + fclose(f); +} +#endif // defined(ANGLE_FUZZER_CORPUS_OUTPUT_DIR) +} // anonymous namespace + +bool IsGLSL130OrNewer(ShShaderOutput output) +{ + return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT || + output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT || + output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT || + output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT || + output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT); +} + +bool IsGLSL420OrNewer(ShShaderOutput output) +{ + return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT || + output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT); +} + +bool IsGLSL410OrOlder(ShShaderOutput output) +{ + return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT || + output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT || + output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT); +} + +bool RemoveInvariant(sh::GLenum shaderType, + int shaderVersion, + ShShaderOutput outputType, + const ShCompileOptions &compileOptions) +{ + if (shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType)) + return true; + + if (compileOptions.removeInvariantAndCentroidForESSL3 && shaderVersion >= 300 && + shaderType == GL_VERTEX_SHADER) + return true; + + return false; +} + +size_t GetGlobalMaxTokenSize(ShShaderSpec spec) +{ + // WebGL defines a max token length of 256, while ES2 leaves max token + // size undefined. ES3 defines a max size of 1024 characters. + switch (spec) + { + case SH_WEBGL_SPEC: + return 256; + default: + return 1024; + } +} + +int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResources &resources) +{ + switch (shaderType) + { + case GL_VERTEX_SHADER: + return resources.MaxVertexUniformVectors; + case GL_FRAGMENT_SHADER: + return resources.MaxFragmentUniformVectors; + + // TODO (jiawei.shao@intel.com): check if we need finer-grained component counting + case GL_COMPUTE_SHADER: + return resources.MaxComputeUniformComponents / 4; + case GL_GEOMETRY_SHADER_EXT: + return resources.MaxGeometryUniformComponents / 4; + default: + UNREACHABLE(); + return -1; + } +} + +namespace +{ + +class [[nodiscard]] TScopedPoolAllocator +{ + public: + TScopedPoolAllocator(angle::PoolAllocator *allocator) : mAllocator(allocator) + { + mAllocator->push(); + SetGlobalPoolAllocator(mAllocator); + } + ~TScopedPoolAllocator() + { + SetGlobalPoolAllocator(nullptr); + mAllocator->pop(); + } + + private: + angle::PoolAllocator *mAllocator; +}; + +class [[nodiscard]] TScopedSymbolTableLevel +{ + public: + TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table) + { + ASSERT(mTable->isEmpty()); + mTable->push(); + } + ~TScopedSymbolTableLevel() + { + while (!mTable->isEmpty()) + mTable->pop(); + } + + private: + TSymbolTable *mTable; +}; + +int GetMaxShaderVersionForSpec(ShShaderSpec spec) +{ + switch (spec) + { + case SH_GLES2_SPEC: + case SH_WEBGL_SPEC: + return 100; + case SH_GLES3_SPEC: + case SH_WEBGL2_SPEC: + return 300; + case SH_GLES3_1_SPEC: + case SH_WEBGL3_SPEC: + return 310; + case SH_GLES3_2_SPEC: + return 320; + case SH_GL_CORE_SPEC: + case SH_GL_COMPATIBILITY_SPEC: + return 460; + default: + UNREACHABLE(); + return 0; + } +} + +bool ValidateFragColorAndFragData(GLenum shaderType, + int shaderVersion, + const TSymbolTable &symbolTable, + TDiagnostics *diagnostics) +{ + if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER) + { + return true; + } + + bool usesFragColor = false; + bool usesFragData = false; + // This validation is a bit stricter than the spec - it's only an error to write to + // both FragData and FragColor. But because it's better not to have reads from undefined + // variables, we always return an error if they are both referenced, rather than only if they + // are written. + if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) || + symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT())) + { + usesFragColor = true; + } + // Extension variables may not always be initialized (saves some time at symbol table init). + bool secondaryFragDataUsed = + symbolTable.gl_SecondaryFragDataEXT() != nullptr && + symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT()); + if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed) + { + usesFragData = true; + } + if (usesFragColor && usesFragData) + { + const char *errorMessage = "cannot use both gl_FragData and gl_FragColor"; + if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) || + secondaryFragDataUsed) + { + errorMessage = + "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)" + " and (gl_FragColor, gl_SecondaryFragColorEXT)"; + } + diagnostics->globalError(errorMessage); + return false; + } + return true; +} + +} // namespace + +TShHandleBase::TShHandleBase() +{ + allocator.push(); + SetGlobalPoolAllocator(&allocator); +} + +TShHandleBase::~TShHandleBase() +{ + SetGlobalPoolAllocator(nullptr); + allocator.popAll(); +} + +TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) + : mVariablesCollected(false), + mGLPositionInitialized(false), + mShaderType(type), + mShaderSpec(spec), + mOutputType(output), + mBuiltInFunctionEmulator(), + mDiagnostics(mInfoSink.info), + mSourcePath(nullptr), + mComputeShaderLocalSizeDeclared(false), + mComputeShaderLocalSize(1), + mGeometryShaderMaxVertices(-1), + mGeometryShaderInvocations(0), + mGeometryShaderInputPrimitiveType(EptUndefined), + mGeometryShaderOutputPrimitiveType(EptUndefined), + mTessControlShaderOutputVertices(0), + mTessEvaluationShaderInputPrimitiveType(EtetUndefined), + mTessEvaluationShaderInputVertexSpacingType(EtetUndefined), + mTessEvaluationShaderInputOrderingType(EtetUndefined), + mTessEvaluationShaderInputPointType(EtetUndefined), + mHasAnyPreciseType(false), + mAdvancedBlendEquations(0), + mHasPixelLocalStorageUniforms(false), + mCompileOptions{} +{} + +TCompiler::~TCompiler() {} + +bool TCompiler::isHighPrecisionSupported() const +{ + return mShaderVersion > 100 || mShaderType != GL_FRAGMENT_SHADER || + mResources.FragmentPrecisionHigh == 1; +} + +bool TCompiler::shouldRunLoopAndIndexingValidation(const ShCompileOptions &compileOptions) const +{ + // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API, + // validate loop and indexing as well (to verify that the shader only uses minimal functionality + // of ESSL 1.00 as in Appendix A of the spec). + return (IsWebGLBasedSpec(mShaderSpec) && mShaderVersion == 100) || + compileOptions.validateLoopIndexing; +} + +bool TCompiler::shouldLimitTypeSizes() const +{ + // WebGL shaders limit the size of variables' types in shaders, + // including arrays, structs and interface blocks. + return IsWebGLBasedSpec(mShaderSpec); +} + +bool TCompiler::Init(const ShBuiltInResources &resources) +{ + SetGlobalPoolAllocator(&allocator); + + // Generate built-in symbol table. + if (!initBuiltInSymbolTable(resources)) + return false; + + mResources = resources; + setResourceString(); + + InitExtensionBehavior(resources, mExtensionBehavior); + return true; +} + +TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[], + size_t numStrings, + const ShCompileOptions &compileOptions) +{ + return compileTreeImpl(shaderStrings, numStrings, compileOptions); +} + +TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], + size_t numStrings, + const ShCompileOptions &compileOptions) +{ + // Remember the compile options for helper functions such as validateAST. + mCompileOptions = compileOptions; + + clearResults(); + + ASSERT(numStrings > 0); + ASSERT(GetGlobalPoolAllocator()); + + // Reset the extension behavior for each compilation unit. + ResetExtensionBehavior(mResources, mExtensionBehavior, compileOptions); + + // If gl_DrawID is not supported, remove it from the available extensions + // Currently we only allow emulation of gl_DrawID + const bool glDrawIDSupported = compileOptions.emulateGLDrawID; + if (!glDrawIDSupported) + { + auto it = mExtensionBehavior.find(TExtension::ANGLE_multi_draw); + if (it != mExtensionBehavior.end()) + { + mExtensionBehavior.erase(it); + } + } + + const bool glBaseVertexBaseInstanceSupported = compileOptions.emulateGLBaseVertexBaseInstance; + if (!glBaseVertexBaseInstanceSupported) + { + auto it = + mExtensionBehavior.find(TExtension::ANGLE_base_vertex_base_instance_shader_builtin); + if (it != mExtensionBehavior.end()) + { + mExtensionBehavior.erase(it); + } + } + + // First string is path of source file if flag is set. The actual source follows. + size_t firstSource = 0; + if (compileOptions.sourcePath) + { + mSourcePath = shaderStrings[0]; + ++firstSource; + } + + TParseContext parseContext(mSymbolTable, mExtensionBehavior, mShaderType, mShaderSpec, + compileOptions, !IsDesktopGLSpec(mShaderSpec), &mDiagnostics, + getResources(), getOutputType()); + + parseContext.setFragmentPrecisionHighOnESSL1(mResources.FragmentPrecisionHigh == 1); + + // We preserve symbols at the built-in level from compile-to-compile. + // Start pushing the user-defined symbols at global level. + TScopedSymbolTableLevel globalLevel(&mSymbolTable); + ASSERT(mSymbolTable.atGlobalLevel()); + + // Parse shader. + if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr, + &parseContext) != 0) + { + return nullptr; + } + + if (!postParseChecks(parseContext)) + { + return nullptr; + } + + setASTMetadata(parseContext); + + if (!checkShaderVersion(&parseContext)) + { + return nullptr; + } + + TIntermBlock *root = parseContext.getTreeRoot(); + if (!checkAndSimplifyAST(root, parseContext, compileOptions)) + { + return nullptr; + } + + return root; +} + +bool TCompiler::checkShaderVersion(TParseContext *parseContext) +{ + if (GetMaxShaderVersionForSpec(mShaderSpec) < mShaderVersion) + { + mDiagnostics.globalError("unsupported shader version"); + return false; + } + + ASSERT(parseContext); + switch (mShaderType) + { + case GL_COMPUTE_SHADER: + if (mShaderVersion < 310) + { + mDiagnostics.globalError("Compute shader is not supported in this shader version."); + return false; + } + break; + + case GL_GEOMETRY_SHADER_EXT: + if (mShaderVersion < 310) + { + mDiagnostics.globalError( + "Geometry shader is not supported in this shader version."); + return false; + } + else if (mShaderVersion == 310) + { + if (!parseContext->checkCanUseOneOfExtensions( + sh::TSourceLoc(), + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}})) + { + return false; + } + } + break; + + case GL_TESS_CONTROL_SHADER_EXT: + case GL_TESS_EVALUATION_SHADER_EXT: + if (mShaderVersion < 310) + { + mDiagnostics.globalError( + "Tessellation shaders are not supported in this shader version."); + return false; + } + else if (mShaderVersion == 310) + { + if (!parseContext->checkCanUseExtension(sh::TSourceLoc(), + TExtension::EXT_tessellation_shader)) + { + return false; + } + } + break; + + default: + break; + } + + return true; +} + +void TCompiler::setASTMetadata(const TParseContext &parseContext) +{ + mShaderVersion = parseContext.getShaderVersion(); + + mPragma = parseContext.pragma(); + mSymbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll); + + mEarlyFragmentTestsSpecified = parseContext.isEarlyFragmentTestsSpecified(); + + mHasDiscard = parseContext.hasDiscard(); + + mEnablesPerSampleShading = parseContext.isSampleQualifierSpecified(); + + mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared(); + mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize(); + + mNumViews = parseContext.getNumViews(); + + mHasAnyPreciseType = parseContext.hasAnyPreciseType(); + + if (mShaderType == GL_FRAGMENT_SHADER) + { + mAdvancedBlendEquations = parseContext.getAdvancedBlendEquations(); + mHasPixelLocalStorageUniforms = !parseContext.pixelLocalStorageBindings().empty(); + } + if (mShaderType == GL_GEOMETRY_SHADER_EXT) + { + mGeometryShaderInputPrimitiveType = parseContext.getGeometryShaderInputPrimitiveType(); + mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType(); + mGeometryShaderMaxVertices = parseContext.getGeometryShaderMaxVertices(); + mGeometryShaderInvocations = parseContext.getGeometryShaderInvocations(); + } + if (mShaderType == GL_TESS_CONTROL_SHADER_EXT) + { + mTessControlShaderOutputVertices = parseContext.getTessControlShaderOutputVertices(); + } + if (mShaderType == GL_TESS_EVALUATION_SHADER_EXT) + { + mTessEvaluationShaderInputPrimitiveType = + parseContext.getTessEvaluationShaderInputPrimitiveType(); + mTessEvaluationShaderInputVertexSpacingType = + parseContext.getTessEvaluationShaderInputVertexSpacingType(); + mTessEvaluationShaderInputOrderingType = + parseContext.getTessEvaluationShaderInputOrderingType(); + mTessEvaluationShaderInputPointType = parseContext.getTessEvaluationShaderInputPointType(); + } +} + +unsigned int TCompiler::getSharedMemorySize() const +{ + unsigned int sharedMemSize = 0; + for (const sh::ShaderVariable &var : mSharedVariables) + { + sharedMemSize += var.getExternalSize(); + } + + return sharedMemSize; +} + +bool TCompiler::validateAST(TIntermNode *root) +{ + if (mCompileOptions.validateAST) + { + bool valid = ValidateAST(root, &mDiagnostics, mValidateASTOptions); + +#if defined(ANGLE_ENABLE_ASSERTS) + if (!valid) + { + OutputTree(root, mInfoSink.info); + fprintf(stderr, "AST validation error(s):\n%s\n", mInfoSink.info.c_str()); + } +#endif + // In debug, assert validation. In release, validation errors will be returned back to the + // application as internal ANGLE errors. + ASSERT(valid); + + return valid; + } + return true; +} + +bool TCompiler::disableValidateFunctionCall() +{ + bool wasEnabled = mValidateASTOptions.validateFunctionCall; + mValidateASTOptions.validateFunctionCall = false; + return wasEnabled; +} + +void TCompiler::restoreValidateFunctionCall(bool enable) +{ + ASSERT(!mValidateASTOptions.validateFunctionCall); + mValidateASTOptions.validateFunctionCall = enable; +} + +bool TCompiler::disableValidateVariableReferences() +{ + bool wasEnabled = mValidateASTOptions.validateVariableReferences; + mValidateASTOptions.validateVariableReferences = false; + return wasEnabled; +} + +void TCompiler::restoreValidateVariableReferences(bool enable) +{ + ASSERT(!mValidateASTOptions.validateVariableReferences); + mValidateASTOptions.validateVariableReferences = enable; +} + +void TCompiler::enableValidateNoMoreTransformations() +{ + mValidateASTOptions.validateNoMoreTransformations = true; +} + +bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, + const TParseContext &parseContext, + const ShCompileOptions &compileOptions) +{ + mValidateASTOptions = {}; + + // Desktop GLSL shaders don't have precision, so don't expect them to be specified. + mValidateASTOptions.validatePrecision = !IsDesktopGLSpec(mShaderSpec); + + if (!validateAST(root)) + { + return false; + } + + // For now, rewrite pixel local storage before collecting variables or any operations on images. + // + // TODO(anglebug.com/7279): + // Should this actually run after collecting variables? + // Do we need more introspection? + // Do we want to hide rewritten shader image uniforms from glGetActiveUniform? + if (hasPixelLocalStorageUniforms()) + { + ASSERT( + IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_shader_pixel_local_storage)); + if (!RewritePixelLocalStorage(this, root, getSymbolTable(), compileOptions, + getShaderVersion())) + { + mDiagnostics.globalError("internal compiler error translating pixel local storage"); + return false; + } + } + + // Disallow expressions deemed too complex. + if (compileOptions.limitExpressionComplexity && !limitExpressionComplexity(root)) + { + return false; + } + + if (shouldRunLoopAndIndexingValidation(compileOptions) && + !ValidateLimitations(root, mShaderType, &mSymbolTable, &mDiagnostics)) + { + return false; + } + + if (shouldLimitTypeSizes() && !ValidateTypeSizeLimitations(root, &mSymbolTable, &mDiagnostics)) + { + return false; + } + + if (!ValidateFragColorAndFragData(mShaderType, mShaderVersion, mSymbolTable, &mDiagnostics)) + { + return false; + } + + // Fold expressions that could not be folded before validation that was done as a part of + // parsing. + if (!FoldExpressions(this, root, &mDiagnostics)) + { + return false; + } + // Folding should only be able to generate warnings. + ASSERT(mDiagnostics.numErrors() == 0); + + // Validate no barrier() after return before prunning it in |PruneNoOps()| below. + if (mShaderType == GL_TESS_CONTROL_SHADER && !ValidateBarrierFunctionCall(root, &mDiagnostics)) + { + return false; + } + + // We prune no-ops to work around driver bugs and to keep AST processing and output simple. + // The following kinds of no-ops are pruned: + // 1. Empty declarations "int;". + // 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision + // for float, so float literal statements would end up with no precision which is + // invalid ESSL. + // 3. Any unreachable statement after a discard, return, break or continue. + // After this empty declarations are not allowed in the AST. + if (!PruneNoOps(this, root, &mSymbolTable)) + { + return false; + } + mValidateASTOptions.validateNoStatementsAfterBranch = true; + + // We need to generate globals early if we have non constant initializers enabled + bool initializeLocalsAndGlobals = + compileOptions.initializeUninitializedLocals && !IsOutputHLSL(getOutputType()); + bool canUseLoopsToInitialize = !compileOptions.dontUseLoopsToInitializeVariables; + bool highPrecisionSupported = isHighPrecisionSupported(); + bool enableNonConstantInitializers = IsExtensionEnabled( + mExtensionBehavior, TExtension::EXT_shader_non_constant_global_initializers); + // forceDeferGlobalInitializers is needed for MSL + // to convert a non-const global. For example: + // + // int someGlobal = 123; + // + // to + // + // int someGlobal; + // void main() { + // someGlobal = 123; + // + // This is because MSL doesn't allow statically initialized globals. + bool forceDeferGlobalInitializers = getOutputType() == SH_MSL_METAL_OUTPUT; + + if (enableNonConstantInitializers && + !DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize, + highPrecisionSupported, forceDeferGlobalInitializers, + &mSymbolTable)) + { + return false; + } + + // Create the function DAG and check there is no recursion + if (!initCallDag(root)) + { + return false; + } + + if (compileOptions.limitCallStackDepth && !checkCallDepth()) + { + return false; + } + + // Checks which functions are used and if "main" exists + mFunctionMetadata.clear(); + mFunctionMetadata.resize(mCallDag.size()); + if (!tagUsedFunctions()) + { + return false; + } + + if (!pruneUnusedFunctions(root)) + { + return false; + } + + if (IsSpecWithFunctionBodyNewScope(mShaderSpec, mShaderVersion)) + { + if (!ReplaceShadowingVariables(this, root, &mSymbolTable)) + { + return false; + } + } + + if (mShaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, mShaderType)) + { + return false; + } + + // anglebug.com/7484: The ESSL spec has a bug with images as function arguments. The recommended + // workaround is to inline functions that accept image arguments. + if (mShaderVersion >= 310 && !MonomorphizeUnsupportedFunctions( + this, root, &mSymbolTable, compileOptions, + UnsupportedFunctionArgsBitSet{UnsupportedFunctionArgs::Image})) + { + return false; + } + + if (mShaderVersion >= 300 && mShaderType == GL_FRAGMENT_SHADER && + !ValidateOutputs(root, getExtensionBehavior(), mResources.MaxDrawBuffers, &mDiagnostics)) + { + return false; + } + + if (parseContext.isExtensionEnabled(TExtension::EXT_clip_cull_distance)) + { + if (!ValidateClipCullDistance(root, &mDiagnostics, + mResources.MaxCombinedClipAndCullDistances)) + { + return false; + } + } + + // Clamping uniform array bounds needs to happen after validateLimitations pass. + if (compileOptions.clampIndirectArrayBounds) + { + if (!ClampIndirectIndices(this, root, &mSymbolTable)) + { + return false; + } + } + + if (compileOptions.initializeBuiltinsForInstancedMultiview && + (parseContext.isExtensionEnabled(TExtension::OVR_multiview2) || + parseContext.isExtensionEnabled(TExtension::OVR_multiview)) && + getShaderType() != GL_COMPUTE_SHADER) + { + if (!DeclareAndInitBuiltinsForInstancedMultiview( + this, root, mNumViews, mShaderType, compileOptions, mOutputType, &mSymbolTable)) + { + return false; + } + } + + // This pass might emit short circuits so keep it before the short circuit unfolding + if (compileOptions.rewriteDoWhileLoops) + { + if (!RewriteDoWhile(this, root, &mSymbolTable)) + { + return false; + } + } + + if (compileOptions.addAndTrueToLoopCondition) + { + if (!AddAndTrueToLoopCondition(this, root)) + { + return false; + } + } + + if (compileOptions.unfoldShortCircuit) + { + if (!UnfoldShortCircuitAST(this, root)) + { + return false; + } + } + + if (compileOptions.regenerateStructNames) + { + if (!RegenerateStructNames(this, root, &mSymbolTable)) + { + return false; + } + } + + if (mShaderType == GL_VERTEX_SHADER && + IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw)) + { + if (compileOptions.emulateGLDrawID) + { + if (!EmulateGLDrawID(this, root, &mSymbolTable, &mUniforms, + shouldCollectVariables(compileOptions))) + { + return false; + } + } + } + + if (mShaderType == GL_VERTEX_SHADER && + IsExtensionEnabled(mExtensionBehavior, + TExtension::ANGLE_base_vertex_base_instance_shader_builtin)) + { + if (compileOptions.emulateGLBaseVertexBaseInstance) + { + if (!EmulateGLBaseVertexBaseInstance(this, root, &mSymbolTable, &mUniforms, + shouldCollectVariables(compileOptions), + compileOptions.addBaseVertexToVertexID)) + { + return false; + } + } + } + + if (mShaderType == GL_FRAGMENT_SHADER && mShaderVersion == 100 && mResources.EXT_draw_buffers && + mResources.MaxDrawBuffers > 1 && + IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers)) + { + if (!EmulateGLFragColorBroadcast(this, root, mResources.MaxDrawBuffers, &mOutputVariables, + &mSymbolTable, mShaderVersion)) + { + return false; + } + } + + int simplifyScalarized = compileOptions.scalarizeVecAndMatConstructorArgs + ? IntermNodePatternMatcher::kScalarizedVecOrMatConstructor + : 0; + + // Split multi declarations and remove calls to array length(). + // Note that SimplifyLoopConditions needs to be run before any other AST transformations + // that may need to generate new statements from loop conditions or loop expressions. + if (!SimplifyLoopConditions(this, root, + IntermNodePatternMatcher::kMultiDeclaration | + IntermNodePatternMatcher::kArrayLengthMethod | + simplifyScalarized, + &getSymbolTable())) + { + return false; + } + + // Note that separate declarations need to be run before other AST transformations that + // generate new statements from expressions. + if (!SeparateDeclarations(this, root, &getSymbolTable())) + { + return false; + } + mValidateASTOptions.validateMultiDeclarations = true; + + if (!SplitSequenceOperator(this, root, + IntermNodePatternMatcher::kArrayLengthMethod | simplifyScalarized, + &getSymbolTable())) + { + return false; + } + + if (!RemoveArrayLengthMethod(this, root)) + { + return false; + } + + if (!RemoveUnreferencedVariables(this, root, &mSymbolTable)) + { + return false; + } + + // In case the last case inside a switch statement is a certain type of no-op, GLSL compilers in + // drivers may not accept it. In this case we clean up the dead code from the end of switch + // statements. This is also required because PruneNoOps or RemoveUnreferencedVariables may have + // left switch statements that only contained an empty declaration inside the final case in an + // invalid state. Relies on that PruneNoOps and RemoveUnreferencedVariables have already been + // run. + if (!PruneEmptyCases(this, root)) + { + return false; + } + + // Built-in function emulation needs to happen after validateLimitations pass. + GetGlobalPoolAllocator()->lock(); + initBuiltInFunctionEmulator(&mBuiltInFunctionEmulator, compileOptions); + GetGlobalPoolAllocator()->unlock(); + mBuiltInFunctionEmulator.markBuiltInFunctionsForEmulation(root); + + if (compileOptions.scalarizeVecAndMatConstructorArgs) + { + if (!ScalarizeVecAndMatConstructorArgs(this, root, &mSymbolTable)) + { + return false; + } + } + + if (compileOptions.forceShaderPrecisionHighpToMediump) + { + if (!ForceShaderPrecisionToMediump(root, &mSymbolTable, mShaderType)) + { + return false; + } + } + + if (shouldCollectVariables(compileOptions)) + { + ASSERT(!mVariablesCollected); + CollectVariables(root, &mAttributes, &mOutputVariables, &mUniforms, &mInputVaryings, + &mOutputVaryings, &mSharedVariables, &mUniformBlocks, + &mShaderStorageBlocks, mResources.HashFunction, &mSymbolTable, mShaderType, + mExtensionBehavior, mResources, mTessControlShaderOutputVertices); + collectInterfaceBlocks(); + mVariablesCollected = true; + if (compileOptions.useUnusedStandardSharedBlocks) + { + if (!useAllMembersInUnusedStandardAndSharedBlocks(root)) + { + return false; + } + } + if (compileOptions.enforcePackingRestrictions) + { + int maxUniformVectors = GetMaxUniformVectorsForShaderType(mShaderType, mResources); + // Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec + // Appendix A, section 7, the shader does not use too many uniforms. + if (!CheckVariablesInPackingLimits(maxUniformVectors, mUniforms)) + { + mDiagnostics.globalError("too many uniforms"); + return false; + } + } + bool needInitializeOutputVariables = + compileOptions.initOutputVariables && mShaderType != GL_COMPUTE_SHADER; + needInitializeOutputVariables |= + compileOptions.initFragmentOutputVariables && mShaderType == GL_FRAGMENT_SHADER; + if (needInitializeOutputVariables) + { + if (!initializeOutputVariables(root)) + { + return false; + } + } + } + + // Removing invariant declarations must be done after collecting variables. + // Otherwise, built-in invariant declarations don't apply. + if (RemoveInvariant(mShaderType, mShaderVersion, mOutputType, compileOptions)) + { + if (!RemoveInvariantDeclaration(this, root)) + { + return false; + } + } + + // gl_Position is always written in compatibility output mode. + // It may have been already initialized among other output variables, in that case we don't + // need to initialize it twice. + if (mShaderType == GL_VERTEX_SHADER && !mGLPositionInitialized && + (compileOptions.initGLPosition || mOutputType == SH_GLSL_COMPATIBILITY_OUTPUT)) + { + if (!initializeGLPosition(root)) + { + return false; + } + mGLPositionInitialized = true; + } + + if (mShaderType == GL_VERTEX_SHADER && compileOptions.initGLPointSize) + { + sh::ShaderVariable var(GL_FLOAT); + var.name = "gl_PointSize"; + if (!InitializeVariables(this, root, {var}, &mSymbolTable, mShaderVersion, + mExtensionBehavior, false, false)) + { + return false; + } + } + + // DeferGlobalInitializers needs to be run before other AST transformations that generate new + // statements from expressions. But it's fine to run DeferGlobalInitializers after the above + // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST + // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00. + // Exception: if EXT_shader_non_constant_global_initializers is enabled, we must generate global + // initializers before we generate the DAG, since initializers may call functions which must not + // be optimized out + if (!enableNonConstantInitializers && + !DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize, + highPrecisionSupported, forceDeferGlobalInitializers, + &mSymbolTable)) + { + return false; + } + + if (initializeLocalsAndGlobals) + { + // Initialize uninitialized local variables. + // In some cases initializing can generate extra statements in the parent block, such as + // when initializing nameless structs or initializing arrays in ESSL 1.00. In that case + // we need to first simplify loop conditions. We've already separated declarations + // earlier, which is also required. If we don't follow the Appendix A limitations, loop + // init statements can declare arrays or nameless structs and have multiple + // declarations. + + if (!shouldRunLoopAndIndexingValidation(compileOptions)) + { + if (!SimplifyLoopConditions(this, root, + IntermNodePatternMatcher::kArrayDeclaration | + IntermNodePatternMatcher::kNamelessStructDeclaration, + &getSymbolTable())) + { + return false; + } + } + + if (!InitializeUninitializedLocals(this, root, getShaderVersion(), canUseLoopsToInitialize, + highPrecisionSupported, &getSymbolTable())) + { + return false; + } + } + + if (getShaderType() == GL_VERTEX_SHADER && compileOptions.clampPointSize) + { + if (!ClampPointSize(this, root, mResources.MaxPointSize, &getSymbolTable())) + { + return false; + } + } + + if (getShaderType() == GL_FRAGMENT_SHADER && compileOptions.clampFragDepth) + { + if (!ClampFragDepth(this, root, &getSymbolTable())) + { + return false; + } + } + + if (compileOptions.rewriteRepeatedAssignToSwizzled) + { + if (!sh::RewriteRepeatedAssignToSwizzled(this, root)) + { + return false; + } + } + + if (compileOptions.removeDynamicIndexingOfSwizzledVector) + { + if (!sh::RemoveDynamicIndexingOfSwizzledVector(this, root, &getSymbolTable(), nullptr)) + { + return false; + } + } + + return true; +} + +bool TCompiler::postParseChecks(const TParseContext &parseContext) +{ + std::stringstream errorMessage; + + if (parseContext.getTreeRoot() == nullptr) + { + errorMessage << "Shader parsing failed (mTreeRoot == nullptr)"; + } + + for (TType *type : parseContext.getDeferredArrayTypesToSize()) + { + errorMessage << "Unsized global array type: " << type->getBasicString(); + } + + if (!errorMessage.str().empty()) + { + mDiagnostics.globalError(errorMessage.str().c_str()); + return false; + } + + return true; +} + +bool TCompiler::compile(const char *const shaderStrings[], + size_t numStrings, + const ShCompileOptions &compileOptionsIn) +{ +#if defined(ANGLE_FUZZER_CORPUS_OUTPUT_DIR) + DumpFuzzerCase(shaderStrings, numStrings, mShaderType, mShaderSpec, mOutputType, + compileOptionsIn); +#endif // defined(ANGLE_FUZZER_CORPUS_OUTPUT_DIR) + + if (numStrings == 0) + return true; + + ShCompileOptions compileOptions = compileOptionsIn; + + // Apply key workarounds. + if (shouldFlattenPragmaStdglInvariantAll()) + { + // This should be harmless to do in all cases, but for the moment, do it only conditionally. + compileOptions.flattenPragmaSTDGLInvariantAll = true; + } + + TScopedPoolAllocator scopedAlloc(&allocator); + TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions); + + if (root) + { + if (compileOptions.intermediateTree) + { + OutputTree(root, mInfoSink.info); + } + + if (compileOptions.objectCode) + { + PerformanceDiagnostics perfDiagnostics(&mDiagnostics); + if (!translate(root, compileOptions, &perfDiagnostics)) + { + return false; + } + } + + if (mShaderType == GL_VERTEX_SHADER) + { + bool lookForDrawID = + IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw) && + compileOptions.emulateGLDrawID; + bool lookForBaseVertexBaseInstance = + IsExtensionEnabled(mExtensionBehavior, + TExtension::ANGLE_base_vertex_base_instance_shader_builtin) && + compileOptions.emulateGLBaseVertexBaseInstance; + + if (lookForDrawID || lookForBaseVertexBaseInstance) + { + for (auto &uniform : mUniforms) + { + if (lookForDrawID && uniform.name == "angle_DrawID" && + uniform.mappedName == "angle_DrawID") + { + uniform.name = "gl_DrawID"; + } + else if (lookForBaseVertexBaseInstance && uniform.name == "angle_BaseVertex" && + uniform.mappedName == "angle_BaseVertex") + { + uniform.name = "gl_BaseVertex"; + } + else if (lookForBaseVertexBaseInstance && + uniform.name == "angle_BaseInstance" && + uniform.mappedName == "angle_BaseInstance") + { + uniform.name = "gl_BaseInstance"; + } + } + } + } + + // The IntermNode tree doesn't need to be deleted here, since the + // memory will be freed in a big chunk by the PoolAllocator. + return true; + } + return false; +} + +bool TCompiler::initBuiltInSymbolTable(const ShBuiltInResources &resources) +{ + if (resources.MaxDrawBuffers < 1) + { + return false; + } + if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1) + { + return false; + } + + mSymbolTable.initializeBuiltIns(mShaderType, mShaderSpec, resources); + + return true; +} + +void TCompiler::setResourceString() +{ + std::ostringstream strstream = sh::InitializeStream(); + + // clang-format off + strstream << ":MaxVertexAttribs:" << mResources.MaxVertexAttribs + << ":MaxVertexUniformVectors:" << mResources.MaxVertexUniformVectors + << ":MaxVaryingVectors:" << mResources.MaxVaryingVectors + << ":MaxVertexTextureImageUnits:" << mResources.MaxVertexTextureImageUnits + << ":MaxCombinedTextureImageUnits:" << mResources.MaxCombinedTextureImageUnits + << ":MaxTextureImageUnits:" << mResources.MaxTextureImageUnits + << ":MaxFragmentUniformVectors:" << mResources.MaxFragmentUniformVectors + << ":MaxDrawBuffers:" << mResources.MaxDrawBuffers + << ":OES_standard_derivatives:" << mResources.OES_standard_derivatives + << ":OES_EGL_image_external:" << mResources.OES_EGL_image_external + << ":OES_EGL_image_external_essl3:" << mResources.OES_EGL_image_external_essl3 + << ":NV_EGL_stream_consumer_external:" << mResources.NV_EGL_stream_consumer_external + << ":ARB_texture_rectangle:" << mResources.ARB_texture_rectangle + << ":EXT_draw_buffers:" << mResources.EXT_draw_buffers + << ":FragmentPrecisionHigh:" << mResources.FragmentPrecisionHigh + << ":MaxExpressionComplexity:" << mResources.MaxExpressionComplexity + << ":MaxCallStackDepth:" << mResources.MaxCallStackDepth + << ":MaxFunctionParameters:" << mResources.MaxFunctionParameters + << ":EXT_blend_func_extended:" << mResources.EXT_blend_func_extended + << ":EXT_frag_depth:" << mResources.EXT_frag_depth + << ":EXT_primitive_bounding_box:" << mResources.EXT_primitive_bounding_box + << ":OES_primitive_bounding_box:" << mResources.OES_primitive_bounding_box + << ":EXT_shader_texture_lod:" << mResources.EXT_shader_texture_lod + << ":EXT_shader_framebuffer_fetch:" << mResources.EXT_shader_framebuffer_fetch + << ":EXT_shader_framebuffer_fetch_non_coherent:" << mResources.EXT_shader_framebuffer_fetch_non_coherent + << ":NV_shader_framebuffer_fetch:" << mResources.NV_shader_framebuffer_fetch + << ":ARM_shader_framebuffer_fetch:" << mResources.ARM_shader_framebuffer_fetch + << ":OVR_multiview2:" << mResources.OVR_multiview2 + << ":OVR_multiview:" << mResources.OVR_multiview + << ":EXT_YUV_target:" << mResources.EXT_YUV_target + << ":EXT_geometry_shader:" << mResources.EXT_geometry_shader + << ":OES_geometry_shader:" << mResources.OES_geometry_shader + << ":OES_shader_io_blocks:" << mResources.OES_shader_io_blocks + << ":EXT_shader_io_blocks:" << mResources.EXT_shader_io_blocks + << ":EXT_gpu_shader5:" << mResources.EXT_gpu_shader5 + << ":OES_texture_3D:" << mResources.OES_texture_3D + << ":MaxVertexOutputVectors:" << mResources.MaxVertexOutputVectors + << ":MaxFragmentInputVectors:" << mResources.MaxFragmentInputVectors + << ":MinProgramTexelOffset:" << mResources.MinProgramTexelOffset + << ":MaxProgramTexelOffset:" << mResources.MaxProgramTexelOffset + << ":MaxDualSourceDrawBuffers:" << mResources.MaxDualSourceDrawBuffers + << ":MaxViewsOVR:" << mResources.MaxViewsOVR + << ":NV_draw_buffers:" << mResources.NV_draw_buffers + << ":ANGLE_multi_draw:" << mResources.ANGLE_multi_draw + << ":ANGLE_base_vertex_base_instance_shader_builtin:" << mResources.ANGLE_base_vertex_base_instance_shader_builtin + << ":APPLE_clip_distance:" << mResources.APPLE_clip_distance + << ":OES_texture_cube_map_array:" << mResources.OES_texture_cube_map_array + << ":EXT_texture_cube_map_array:" << mResources.EXT_texture_cube_map_array + << ":EXT_shadow_samplers:" << mResources.EXT_shadow_samplers + << ":OES_shader_multisample_interpolation:" << mResources.OES_shader_multisample_interpolation + << ":OES_shader_image_atomic:" << mResources.OES_shader_image_atomic + << ":EXT_tessellation_shader:" << mResources.EXT_tessellation_shader + << ":OES_texture_buffer:" << mResources.OES_texture_buffer + << ":EXT_texture_buffer:" << mResources.EXT_texture_buffer + << ":OES_sample_variables:" << mResources.OES_sample_variables + << ":EXT_clip_cull_distance:" << mResources.EXT_clip_cull_distance + << ":MinProgramTextureGatherOffset:" << mResources.MinProgramTextureGatherOffset + << ":MaxProgramTextureGatherOffset:" << mResources.MaxProgramTextureGatherOffset + << ":MaxImageUnits:" << mResources.MaxImageUnits + << ":MaxSamples:" << mResources.MaxSamples + << ":MaxVertexImageUniforms:" << mResources.MaxVertexImageUniforms + << ":MaxFragmentImageUniforms:" << mResources.MaxFragmentImageUniforms + << ":MaxComputeImageUniforms:" << mResources.MaxComputeImageUniforms + << ":MaxCombinedImageUniforms:" << mResources.MaxCombinedImageUniforms + << ":MaxCombinedShaderOutputResources:" << mResources.MaxCombinedShaderOutputResources + << ":MaxComputeWorkGroupCountX:" << mResources.MaxComputeWorkGroupCount[0] + << ":MaxComputeWorkGroupCountY:" << mResources.MaxComputeWorkGroupCount[1] + << ":MaxComputeWorkGroupCountZ:" << mResources.MaxComputeWorkGroupCount[2] + << ":MaxComputeWorkGroupSizeX:" << mResources.MaxComputeWorkGroupSize[0] + << ":MaxComputeWorkGroupSizeY:" << mResources.MaxComputeWorkGroupSize[1] + << ":MaxComputeWorkGroupSizeZ:" << mResources.MaxComputeWorkGroupSize[2] + << ":MaxComputeUniformComponents:" << mResources.MaxComputeUniformComponents + << ":MaxComputeTextureImageUnits:" << mResources.MaxComputeTextureImageUnits + << ":MaxComputeAtomicCounters:" << mResources.MaxComputeAtomicCounters + << ":MaxComputeAtomicCounterBuffers:" << mResources.MaxComputeAtomicCounterBuffers + << ":MaxVertexAtomicCounters:" << mResources.MaxVertexAtomicCounters + << ":MaxFragmentAtomicCounters:" << mResources.MaxFragmentAtomicCounters + << ":MaxCombinedAtomicCounters:" << mResources.MaxCombinedAtomicCounters + << ":MaxAtomicCounterBindings:" << mResources.MaxAtomicCounterBindings + << ":MaxVertexAtomicCounterBuffers:" << mResources.MaxVertexAtomicCounterBuffers + << ":MaxFragmentAtomicCounterBuffers:" << mResources.MaxFragmentAtomicCounterBuffers + << ":MaxCombinedAtomicCounterBuffers:" << mResources.MaxCombinedAtomicCounterBuffers + << ":MaxAtomicCounterBufferSize:" << mResources.MaxAtomicCounterBufferSize + << ":MaxGeometryUniformComponents:" << mResources.MaxGeometryUniformComponents + << ":MaxGeometryUniformBlocks:" << mResources.MaxGeometryUniformBlocks + << ":MaxGeometryInputComponents:" << mResources.MaxGeometryInputComponents + << ":MaxGeometryOutputComponents:" << mResources.MaxGeometryOutputComponents + << ":MaxGeometryOutputVertices:" << mResources.MaxGeometryOutputVertices + << ":MaxGeometryTotalOutputComponents:" << mResources.MaxGeometryTotalOutputComponents + << ":MaxGeometryTextureImageUnits:" << mResources.MaxGeometryTextureImageUnits + << ":MaxGeometryAtomicCounterBuffers:" << mResources.MaxGeometryAtomicCounterBuffers + << ":MaxGeometryAtomicCounters:" << mResources.MaxGeometryAtomicCounters + << ":MaxGeometryShaderStorageBlocks:" << mResources.MaxGeometryShaderStorageBlocks + << ":MaxGeometryShaderInvocations:" << mResources.MaxGeometryShaderInvocations + << ":MaxGeometryImageUniforms:" << mResources.MaxGeometryImageUniforms + << ":MaxClipDistances" << mResources.MaxClipDistances + << ":MaxCullDistances" << mResources.MaxCullDistances + << ":MaxCombinedClipAndCullDistances" << mResources.MaxCombinedClipAndCullDistances + << ":MaxTessControlInputComponents:" << mResources.MaxTessControlInputComponents + << ":MaxTessControlOutputComponents:" << mResources.MaxTessControlOutputComponents + << ":MaxTessControlTextureImageUnits:" << mResources.MaxTessControlTextureImageUnits + << ":MaxTessControlUniformComponents:" << mResources.MaxTessControlUniformComponents + << ":MaxTessControlTotalOutputComponents:" << mResources.MaxTessControlTotalOutputComponents + << ":MaxTessControlImageUniforms:" << mResources.MaxTessControlImageUniforms + << ":MaxTessControlAtomicCounters:" << mResources.MaxTessControlAtomicCounters + << ":MaxTessControlAtomicCounterBuffers:" << mResources.MaxTessControlAtomicCounterBuffers + << ":MaxTessPatchComponents:" << mResources.MaxTessPatchComponents + << ":MaxPatchVertices:" << mResources.MaxPatchVertices + << ":MaxTessGenLevel:" << mResources.MaxTessGenLevel + << ":MaxTessEvaluationInputComponents:" << mResources.MaxTessEvaluationInputComponents + << ":MaxTessEvaluationOutputComponents:" << mResources.MaxTessEvaluationOutputComponents + << ":MaxTessEvaluationTextureImageUnits:" << mResources.MaxTessEvaluationTextureImageUnits + << ":MaxTessEvaluationUniformComponents:" << mResources.MaxTessEvaluationUniformComponents + << ":MaxTessEvaluationImageUniforms:" << mResources.MaxTessEvaluationImageUniforms + << ":MaxTessEvaluationAtomicCounters:" << mResources.MaxTessEvaluationAtomicCounters + << ":MaxTessEvaluationAtomicCounterBuffers:" << mResources.MaxTessEvaluationAtomicCounterBuffers; + // clang-format on + + mBuiltInResourcesString = strstream.str(); +} + +void TCompiler::collectInterfaceBlocks() +{ + ASSERT(mInterfaceBlocks.empty()); + mInterfaceBlocks.reserve(mUniformBlocks.size() + mShaderStorageBlocks.size()); + mInterfaceBlocks.insert(mInterfaceBlocks.end(), mUniformBlocks.begin(), mUniformBlocks.end()); + mInterfaceBlocks.insert(mInterfaceBlocks.end(), mShaderStorageBlocks.begin(), + mShaderStorageBlocks.end()); +} + +void TCompiler::clearResults() +{ + mInfoSink.info.erase(); + mInfoSink.obj.erase(); + mInfoSink.debug.erase(); + mDiagnostics.resetErrorCount(); + + mAttributes.clear(); + mOutputVariables.clear(); + mUniforms.clear(); + mInputVaryings.clear(); + mOutputVaryings.clear(); + mSharedVariables.clear(); + mInterfaceBlocks.clear(); + mUniformBlocks.clear(); + mShaderStorageBlocks.clear(); + mVariablesCollected = false; + mGLPositionInitialized = false; + + mNumViews = -1; + + mGeometryShaderInputPrimitiveType = EptUndefined; + mGeometryShaderOutputPrimitiveType = EptUndefined; + mGeometryShaderInvocations = 0; + mGeometryShaderMaxVertices = -1; + + mTessControlShaderOutputVertices = 0; + mTessEvaluationShaderInputPrimitiveType = EtetUndefined; + mTessEvaluationShaderInputVertexSpacingType = EtetUndefined; + mTessEvaluationShaderInputOrderingType = EtetUndefined; + mTessEvaluationShaderInputPointType = EtetUndefined; + + mBuiltInFunctionEmulator.cleanup(); + + mNameMap.clear(); + + mSourcePath = nullptr; + + mSymbolTable.clearCompilationResults(); +} + +bool TCompiler::initCallDag(TIntermNode *root) +{ + mCallDag.clear(); + + switch (mCallDag.init(root, &mDiagnostics)) + { + case CallDAG::INITDAG_SUCCESS: + return true; + case CallDAG::INITDAG_RECURSION: + case CallDAG::INITDAG_UNDEFINED: + // Error message has already been written out. + ASSERT(mDiagnostics.numErrors() > 0); + return false; + } + + UNREACHABLE(); + return true; +} + +bool TCompiler::checkCallDepth() +{ + std::vector depths(mCallDag.size()); + + for (size_t i = 0; i < mCallDag.size(); i++) + { + int depth = 0; + const CallDAG::Record &record = mCallDag.getRecordFromIndex(i); + + for (int calleeIndex : record.callees) + { + depth = std::max(depth, depths[calleeIndex] + 1); + } + + depths[i] = depth; + + if (depth >= mResources.MaxCallStackDepth) + { + // Trace back the function chain to have a meaningful info log. + std::stringstream errorStream = sh::InitializeStream(); + errorStream << "Call stack too deep (larger than " << mResources.MaxCallStackDepth + << ") with the following call chain: " + << record.node->getFunction()->name(); + + int currentFunction = static_cast(i); + int currentDepth = depth; + + while (currentFunction != -1) + { + errorStream + << " -> " + << mCallDag.getRecordFromIndex(currentFunction).node->getFunction()->name(); + + int nextFunction = -1; + for (const int &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees) + { + if (depths[calleeIndex] == currentDepth - 1) + { + currentDepth--; + nextFunction = calleeIndex; + } + } + + currentFunction = nextFunction; + } + + std::string errorStr = errorStream.str(); + mDiagnostics.globalError(errorStr.c_str()); + + return false; + } + } + + return true; +} + +bool TCompiler::tagUsedFunctions() +{ + // Search from main, starting from the end of the DAG as it usually is the root. + for (size_t i = mCallDag.size(); i-- > 0;) + { + if (mCallDag.getRecordFromIndex(i).node->getFunction()->isMain()) + { + internalTagUsedFunction(i); + return true; + } + } + + mDiagnostics.globalError("Missing main()"); + return false; +} + +void TCompiler::internalTagUsedFunction(size_t index) +{ + if (mFunctionMetadata[index].used) + { + return; + } + + mFunctionMetadata[index].used = true; + + for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees) + { + internalTagUsedFunction(calleeIndex); + } +} + +bool TCompiler::pruneUnusedFunctions(TIntermBlock *root) +{ + TIntermSequence *sequence = root->getSequence(); + + size_t writeIndex = 0; + for (size_t readIndex = 0; readIndex < sequence->size(); ++readIndex) + { + TIntermNode *node = sequence->at(readIndex); + + // Keep anything that's not unused. + const TFunction *function = nullptr; + const bool shouldPrune = + IsTopLevelNodeUnusedFunction(mCallDag, mFunctionMetadata, node, &function); + if (!shouldPrune) + { + (*sequence)[writeIndex++] = node; + continue; + } + + // If a function is unused, it may have a struct declaration in its return value which + // shouldn't be pruned. In that case, replace the function definition with the struct + // definition. + ASSERT(function != nullptr); + const TType &returnType = function->getReturnType(); + if (!returnType.isStructSpecifier()) + { + continue; + } + + TVariable *structVariable = + new TVariable(&mSymbolTable, kEmptyImmutableString, &returnType, SymbolType::Empty); + TIntermSymbol *structSymbol = new TIntermSymbol(structVariable); + TIntermDeclaration *structDeclaration = new TIntermDeclaration; + structDeclaration->appendDeclarator(structSymbol); + + structSymbol->setLine(node->getLine()); + structDeclaration->setLine(node->getLine()); + + (*sequence)[writeIndex++] = structDeclaration; + } + + sequence->resize(writeIndex); + + return validateAST(root); +} + +bool TCompiler::limitExpressionComplexity(TIntermBlock *root) +{ + if (!IsASTDepthBelowLimit(root, mResources.MaxExpressionComplexity)) + { + mDiagnostics.globalError("Expression too complex."); + return false; + } + + if (!ValidateMaxParameters(root, mResources.MaxFunctionParameters)) + { + mDiagnostics.globalError("Function has too many parameters."); + return false; + } + + return true; +} + +bool TCompiler::shouldCollectVariables(const ShCompileOptions &compileOptions) +{ + return compileOptions.variables; +} + +bool TCompiler::wereVariablesCollected() const +{ + return mVariablesCollected; +} + +bool TCompiler::initializeGLPosition(TIntermBlock *root) +{ + sh::ShaderVariable var(GL_FLOAT_VEC4); + var.name = "gl_Position"; + return InitializeVariables(this, root, {var}, &mSymbolTable, mShaderVersion, mExtensionBehavior, + false, false); +} + +bool TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root) +{ + sh::InterfaceBlockList list; + + for (const sh::InterfaceBlock &block : mUniformBlocks) + { + if (!block.staticUse && + (block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED)) + { + list.push_back(block); + } + } + + return sh::UseInterfaceBlockFields(this, root, list, mSymbolTable); +} + +bool TCompiler::initializeOutputVariables(TIntermBlock *root) +{ + InitVariableList list; + list.reserve(mOutputVaryings.size()); + if (mShaderType == GL_VERTEX_SHADER || mShaderType == GL_GEOMETRY_SHADER_EXT) + { + for (const sh::ShaderVariable &var : mOutputVaryings) + { + list.push_back(var); + if (var.name == "gl_Position") + { + ASSERT(!mGLPositionInitialized); + mGLPositionInitialized = true; + } + } + } + else + { + ASSERT(mShaderType == GL_FRAGMENT_SHADER); + for (const sh::ShaderVariable &var : mOutputVariables) + { + // in-out variables represent the context of the framebuffer + // when the draw call starts, so they have to be considered + // as already initialized. + if (!var.isFragmentInOut) + { + list.push_back(var); + } + } + } + return InitializeVariables(this, root, list, &mSymbolTable, mShaderVersion, mExtensionBehavior, + false, false); +} + +const TExtensionBehavior &TCompiler::getExtensionBehavior() const +{ + return mExtensionBehavior; +} + +const char *TCompiler::getSourcePath() const +{ + return mSourcePath; +} + +const ShBuiltInResources &TCompiler::getResources() const +{ + return mResources; +} + +const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const +{ + return mBuiltInFunctionEmulator; +} + +bool TCompiler::isVaryingDefined(const char *varyingName) +{ + ASSERT(mVariablesCollected); + for (size_t ii = 0; ii < mInputVaryings.size(); ++ii) + { + if (mInputVaryings[ii].name == varyingName) + { + return true; + } + } + for (size_t ii = 0; ii < mOutputVaryings.size(); ++ii) + { + if (mOutputVaryings[ii].name == varyingName) + { + return true; + } + } + + return false; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/Compiler.h b/gfx/angle/checkout/src/compiler/translator/Compiler.h new file mode 100644 index 0000000000..8a87d5ea24 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Compiler.h @@ -0,0 +1,397 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_COMPILER_H_ +#define COMPILER_TRANSLATOR_COMPILER_H_ + +// +// Machine independent part of the compiler private objects +// sent as ShHandle to the driver. +// +// This should not be included by driver code. +// + +#include + +#include "common/PackedEnums.h" +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/CallDAG.h" +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/ExtensionBehavior.h" +#include "compiler/translator/HashNames.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/Pragma.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/ValidateAST.h" + +namespace sh +{ + +class TCompiler; +class TParseContext; +#ifdef ANGLE_ENABLE_HLSL +class TranslatorHLSL; +#endif // ANGLE_ENABLE_HLSL +#ifdef ANGLE_ENABLE_METAL +class TranslatorMetalDirect; +#endif // ANGLE_ENABLE_METAL + +using SpecConstUsageBits = angle::PackedEnumBitSet; + +// +// Helper function to check if the shader type is GLSL. +// +bool IsGLSL130OrNewer(ShShaderOutput output); +bool IsGLSL420OrNewer(ShShaderOutput output); +bool IsGLSL410OrOlder(ShShaderOutput output); + +// +// Helper function to check if the invariant qualifier can be removed. +// +bool RemoveInvariant(sh::GLenum shaderType, + int shaderVersion, + ShShaderOutput outputType, + const ShCompileOptions &compileOptions); + +// +// The base class used to back handles returned to the driver. +// +class TShHandleBase +{ + public: + TShHandleBase(); + virtual ~TShHandleBase(); + virtual TCompiler *getAsCompiler() { return 0; } +#ifdef ANGLE_ENABLE_HLSL + virtual TranslatorHLSL *getAsTranslatorHLSL() { return 0; } +#endif // ANGLE_ENABLE_HLSL +#ifdef ANGLE_ENABLE_METAL + virtual TranslatorMetalDirect *getAsTranslatorMetalDirect() { return nullptr; } +#endif // ANGLE_ENABLE_METAL + + protected: + // Memory allocator. Allocates and tracks memory required by the compiler. + // Deallocates all memory when compiler is destructed. + angle::PoolAllocator allocator; +}; + +struct TFunctionMetadata +{ + bool used = false; +}; + +// +// The base class for the machine dependent compiler to derive from +// for managing object code from the compile. +// +class TCompiler : public TShHandleBase +{ + public: + TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); + ~TCompiler() override; + TCompiler *getAsCompiler() override { return this; } + + bool Init(const ShBuiltInResources &resources); + + // compileTreeForTesting should be used only when tests require access to + // the AST. Users of this function need to manually manage the global pool + // allocator. Returns nullptr whenever there are compilation errors. + TIntermBlock *compileTreeForTesting(const char *const shaderStrings[], + size_t numStrings, + const ShCompileOptions &compileOptions); + + bool compile(const char *const shaderStrings[], + size_t numStrings, + const ShCompileOptions &compileOptions); + + // Get results of the last compilation. + int getShaderVersion() const { return mShaderVersion; } + TInfoSink &getInfoSink() { return mInfoSink; } + + bool specifyEarlyFragmentTests() { return mEarlyFragmentTestsSpecified = true; } + bool isEarlyFragmentTestsSpecified() const { return mEarlyFragmentTestsSpecified; } + bool hasDiscard() const { return mHasDiscard; } + bool enablesPerSampleShading() const { return mEnablesPerSampleShading; } + SpecConstUsageBits getSpecConstUsageBits() const { return mSpecConstUsageBits; } + + bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; } + const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; } + int getNumViews() const { return mNumViews; } + + // Clears the results from the previous compilation. + void clearResults(); + + const std::vector &getAttributes() const { return mAttributes; } + const std::vector &getOutputVariables() const { return mOutputVariables; } + const std::vector &getUniforms() const { return mUniforms; } + const std::vector &getInputVaryings() const { return mInputVaryings; } + const std::vector &getOutputVaryings() const { return mOutputVaryings; } + const std::vector &getInterfaceBlocks() const { return mInterfaceBlocks; } + const std::vector &getUniformBlocks() const { return mUniformBlocks; } + const std::vector &getShaderStorageBlocks() const + { + return mShaderStorageBlocks; + } + + ShHashFunction64 getHashFunction() const { return mResources.HashFunction; } + NameMap &getNameMap() { return mNameMap; } + TSymbolTable &getSymbolTable() { return mSymbolTable; } + ShShaderSpec getShaderSpec() const { return mShaderSpec; } + ShShaderOutput getOutputType() const { return mOutputType; } + ShBuiltInResources getBuiltInResources() const { return mResources; } + const std::string &getBuiltInResourcesString() const { return mBuiltInResourcesString; } + + bool isHighPrecisionSupported() const; + + bool shouldRunLoopAndIndexingValidation(const ShCompileOptions &compileOptions) const; + bool shouldLimitTypeSizes() const; + + // Get the resources set by InitBuiltInSymbolTable + const ShBuiltInResources &getResources() const; + + const TPragma &getPragma() const { return mPragma; } + + int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; } + int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; } + TLayoutPrimitiveType getGeometryShaderInputPrimitiveType() const + { + return mGeometryShaderInputPrimitiveType; + } + TLayoutPrimitiveType getGeometryShaderOutputPrimitiveType() const + { + return mGeometryShaderOutputPrimitiveType; + } + + unsigned int getStructSize(const ShaderVariable &var) const; + + int getTessControlShaderOutputVertices() const { return mTessControlShaderOutputVertices; } + TLayoutTessEvaluationType getTessEvaluationShaderInputPrimitiveType() const + { + return mTessEvaluationShaderInputPrimitiveType; + } + TLayoutTessEvaluationType getTessEvaluationShaderInputVertexSpacingType() const + { + return mTessEvaluationShaderInputVertexSpacingType; + } + TLayoutTessEvaluationType getTessEvaluationShaderInputOrderingType() const + { + return mTessEvaluationShaderInputOrderingType; + } + TLayoutTessEvaluationType getTessEvaluationShaderInputPointType() const + { + return mTessEvaluationShaderInputPointType; + } + + bool hasAnyPreciseType() const { return mHasAnyPreciseType; } + + AdvancedBlendEquations getAdvancedBlendEquations() const { return mAdvancedBlendEquations; } + + bool hasPixelLocalStorageUniforms() const { return mHasPixelLocalStorageUniforms; } + + unsigned int getSharedMemorySize() const; + + sh::GLenum getShaderType() const { return mShaderType; } + + // Validate the AST and produce errors if it is inconsistent. + bool validateAST(TIntermNode *root); + // Some transformations may need to temporarily disable validation until they are complete. A + // set of disable/enable helpers are used for this purpose. + bool disableValidateFunctionCall(); + void restoreValidateFunctionCall(bool enable); + bool disableValidateVariableReferences(); + void restoreValidateVariableReferences(bool enable); + // When the AST is post-processed (such as to determine precise-ness of intermediate nodes), + // it's expected to no longer transform. + void enableValidateNoMoreTransformations(); + + protected: + // Add emulated functions to the built-in function emulator. + virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, + const ShCompileOptions &compileOptions) + {} + // Translate to object code. May generate performance warnings through the diagnostics. + [[nodiscard]] virtual bool translate(TIntermBlock *root, + const ShCompileOptions &compileOptions, + PerformanceDiagnostics *perfDiagnostics) = 0; + // Get built-in extensions with default behavior. + const TExtensionBehavior &getExtensionBehavior() const; + const char *getSourcePath() const; + // Relies on collectVariables having been called. + bool isVaryingDefined(const char *varyingName); + + const BuiltInFunctionEmulator &getBuiltInFunctionEmulator() const; + + virtual bool shouldFlattenPragmaStdglInvariantAll() = 0; + virtual bool shouldCollectVariables(const ShCompileOptions &compileOptions); + + bool wereVariablesCollected() const; + std::vector mAttributes; + std::vector mOutputVariables; + std::vector mUniforms; + std::vector mInputVaryings; + std::vector mOutputVaryings; + std::vector mSharedVariables; + std::vector mInterfaceBlocks; + std::vector mUniformBlocks; + std::vector mShaderStorageBlocks; + + // Track what should be validated given passes currently applied. + ValidateASTOptions mValidateASTOptions; + + // Specialization constant usage bits + SpecConstUsageBits mSpecConstUsageBits; + + private: + // Initialize symbol-table with built-in symbols. + bool initBuiltInSymbolTable(const ShBuiltInResources &resources); + // Compute the string representation of the built-in resources + void setResourceString(); + // Return false if the call depth is exceeded. + bool checkCallDepth(); + // Insert statements to reference all members in unused uniform blocks with standard and shared + // layout. This is to work around a Mac driver that treats unused standard/shared + // uniform blocks as inactive. + [[nodiscard]] bool useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root); + // Insert statements to initialize output variables in the beginning of main(). + // This is to avoid undefined behaviors. + [[nodiscard]] bool initializeOutputVariables(TIntermBlock *root); + // Insert gl_Position = vec4(0,0,0,0) to the beginning of main(). + // It is to work around a Linux driver bug where missing this causes compile failure + // while spec says it is allowed. + // This function should only be applied to vertex shaders. + [[nodiscard]] bool initializeGLPosition(TIntermBlock *root); + // Return true if the maximum expression complexity is below the limit. + bool limitExpressionComplexity(TIntermBlock *root); + // Creates the function call DAG for further analysis, returning false if there is a recursion + bool initCallDag(TIntermNode *root); + // Return false if "main" doesn't exist + bool tagUsedFunctions(); + void internalTagUsedFunction(size_t index); + + void collectInterfaceBlocks(); + + bool mVariablesCollected; + + bool mGLPositionInitialized; + + // Removes unused function declarations and prototypes from the AST + bool pruneUnusedFunctions(TIntermBlock *root); + + TIntermBlock *compileTreeImpl(const char *const shaderStrings[], + size_t numStrings, + const ShCompileOptions &compileOptions); + + // Fetches and stores shader metadata that is not stored within the AST itself, such as shader + // version. + void setASTMetadata(const TParseContext &parseContext); + + // Check if shader version meets the requirement. + bool checkShaderVersion(TParseContext *parseContext); + + // Does checks that need to be run after parsing is complete and returns true if they pass. + bool checkAndSimplifyAST(TIntermBlock *root, + const TParseContext &parseContext, + const ShCompileOptions &compileOptions); + + bool postParseChecks(const TParseContext &parseContext); + + sh::GLenum mShaderType; + ShShaderSpec mShaderSpec; + ShShaderOutput mOutputType; + + CallDAG mCallDag; + std::vector mFunctionMetadata; + + ShBuiltInResources mResources; + std::string mBuiltInResourcesString; + + // Built-in symbol table for the given language, spec, and resources. + // It is preserved from compile-to-compile. + TSymbolTable mSymbolTable; + // Built-in extensions with default behavior. + TExtensionBehavior mExtensionBehavior; + + BuiltInFunctionEmulator mBuiltInFunctionEmulator; + + // Results of compilation. + int mShaderVersion; + TInfoSink mInfoSink; // Output sink. + TDiagnostics mDiagnostics; + const char *mSourcePath; // Path of source file or NULL + + // Fragment shader early fragment tests + bool mEarlyFragmentTestsSpecified; + + // Fragment shader has the discard instruction + bool mHasDiscard; + + // Whether per-sample shading is enabled by the shader. In OpenGL, this keyword should + // implicitly trigger per-sample shading without the API enabling it. + bool mEnablesPerSampleShading; + + // compute shader local group size + bool mComputeShaderLocalSizeDeclared; + sh::WorkGroupSize mComputeShaderLocalSize; + + // GL_OVR_multiview num_views. + int mNumViews; + + // geometry shader parameters. + int mGeometryShaderMaxVertices; + int mGeometryShaderInvocations; + TLayoutPrimitiveType mGeometryShaderInputPrimitiveType; + TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType; + + // tesssellation shader parameters + int mTessControlShaderOutputVertices; + TLayoutTessEvaluationType mTessEvaluationShaderInputPrimitiveType; + TLayoutTessEvaluationType mTessEvaluationShaderInputVertexSpacingType; + TLayoutTessEvaluationType mTessEvaluationShaderInputOrderingType; + TLayoutTessEvaluationType mTessEvaluationShaderInputPointType; + + bool mHasAnyPreciseType; + + // advanced blend equation parameters + AdvancedBlendEquations mAdvancedBlendEquations; + + // ANGLE_shader_pixel_local_storage. + bool mHasPixelLocalStorageUniforms; + + // name hashing. + NameMap mNameMap; + + TPragma mPragma; + + ShCompileOptions mCompileOptions; +}; + +// +// This is the interface between the machine independent code +// and the machine dependent code. +// +// The machine dependent code should derive from the classes +// above. Then Construct*() and Delete*() will create and +// destroy the machine dependent objects, which contain the +// above machine independent information. +// +TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); +void DeleteCompiler(TCompiler *); + +struct ShaderDumpHeader +{ + uint32_t type; + uint32_t spec; + uint32_t output; + uint8_t basicCompileOptions[32]; + uint8_t metalCompileOptions[32]; + uint8_t plsCompileOptions[32]; + uint8_t padding[20]; +}; +static_assert(sizeof(ShaderDumpHeader) == 128); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_COMPILER_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ConstantUnion.cpp b/gfx/angle/checkout/src/compiler/translator/ConstantUnion.cpp new file mode 100644 index 0000000000..99af1c4f6c --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ConstantUnion.cpp @@ -0,0 +1,803 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ConstantUnion: Constant folding helper class. + +#include "compiler/translator/ConstantUnion.h" + +#include "common/mathutil.h" +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +float CheckedSum(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line) +{ + float result = lhs + rhs; + if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs)) + { + diag->warning(line, "Constant folded undefined addition generated NaN", "+"); + } + else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs)) + { + diag->warning(line, "Constant folded addition overflowed to infinity", "+"); + } + return result; +} + +float CheckedDiff(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line) +{ + float result = lhs - rhs; + if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs)) + { + diag->warning(line, "Constant folded undefined subtraction generated NaN", "-"); + } + else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs)) + { + diag->warning(line, "Constant folded subtraction overflowed to infinity", "-"); + } + return result; +} + +float CheckedMul(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line) +{ + float result = lhs * rhs; + if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs)) + { + diag->warning(line, "Constant folded undefined multiplication generated NaN", "*"); + } + else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs)) + { + diag->warning(line, "Constant folded multiplication overflowed to infinity", "*"); + } + return result; +} + +bool IsValidShiftOffset(const TConstantUnion &rhs) +{ + return (rhs.getType() == EbtInt && (rhs.getIConst() >= 0 && rhs.getIConst() <= 31)) || + (rhs.getType() == EbtUInt && rhs.getUConst() <= 31u); +} + +} // anonymous namespace + +TConstantUnion::TConstantUnion() : iConst(0), type(EbtVoid) {} + +TConstantUnion::TConstantUnion(int i) : iConst(i), type(EbtInt) {} + +TConstantUnion::TConstantUnion(unsigned int u) : uConst(u), type(EbtUInt) {} + +TConstantUnion::TConstantUnion(float f) : fConst(f), type(EbtFloat) {} + +TConstantUnion::TConstantUnion(bool b) : bConst(b), type(EbtBool) {} + +int TConstantUnion::getIConst() const +{ + ASSERT(type == EbtInt); + return iConst; +} + +unsigned int TConstantUnion::getUConst() const +{ + ASSERT(type == EbtUInt); + return uConst; +} + +float TConstantUnion::getFConst() const +{ + switch (type) + { + case EbtInt: + return static_cast(iConst); + case EbtUInt: + return static_cast(uConst); + default: + ASSERT(type == EbtFloat); + return fConst; + } +} + +bool TConstantUnion::getBConst() const +{ + ASSERT(type == EbtBool); + return bConst; +} + +bool TConstantUnion::isZero() const +{ + switch (type) + { + case EbtInt: + return getIConst() == 0; + case EbtUInt: + return getUConst() == 0; + case EbtFloat: + return getFConst() == 0.0f; + case EbtBool: + return getBConst() == false; + default: + return false; + } +} + +TYuvCscStandardEXT TConstantUnion::getYuvCscStandardEXTConst() const +{ + ASSERT(type == EbtYuvCscStandardEXT); + return yuvCscStandardEXTConst; +} + +bool TConstantUnion::cast(TBasicType newType, const TConstantUnion &constant) +{ + switch (newType) + { + case EbtFloat: + switch (constant.type) + { + case EbtInt: + setFConst(static_cast(constant.getIConst())); + break; + case EbtUInt: + setFConst(static_cast(constant.getUConst())); + break; + case EbtBool: + setFConst(static_cast(constant.getBConst())); + break; + case EbtFloat: + setFConst(static_cast(constant.getFConst())); + break; + default: + return false; + } + break; + case EbtInt: + switch (constant.type) + { + case EbtInt: + setIConst(static_cast(constant.getIConst())); + break; + case EbtUInt: + setIConst(static_cast(constant.getUConst())); + break; + case EbtBool: + setIConst(static_cast(constant.getBConst())); + break; + case EbtFloat: + setIConst(static_cast(constant.getFConst())); + break; + default: + return false; + } + break; + case EbtUInt: + switch (constant.type) + { + case EbtInt: + setUConst(static_cast(constant.getIConst())); + break; + case EbtUInt: + setUConst(static_cast(constant.getUConst())); + break; + case EbtBool: + setUConst(static_cast(constant.getBConst())); + break; + case EbtFloat: + if (constant.getFConst() < 0.0f) + { + // Avoid undefined behavior in C++ by first casting to signed int. + setUConst( + static_cast(static_cast(constant.getFConst()))); + } + else + { + setUConst(static_cast(constant.getFConst())); + } + break; + default: + return false; + } + break; + case EbtBool: + switch (constant.type) + { + case EbtInt: + setBConst(constant.getIConst() != 0); + break; + case EbtUInt: + setBConst(constant.getUConst() != 0); + break; + case EbtBool: + setBConst(constant.getBConst()); + break; + case EbtFloat: + setBConst(constant.getFConst() != 0.0f); + break; + default: + return false; + } + break; + case EbtStruct: // Struct fields don't get cast + switch (constant.type) + { + case EbtInt: + setIConst(constant.getIConst()); + break; + case EbtUInt: + setUConst(constant.getUConst()); + break; + case EbtBool: + setBConst(constant.getBConst()); + break; + case EbtFloat: + setFConst(constant.getFConst()); + break; + default: + return false; + } + break; + case EbtYuvCscStandardEXT: + switch (constant.type) + { + case EbtYuvCscStandardEXT: + setYuvCscStandardEXTConst(constant.getYuvCscStandardEXTConst()); + break; + default: + return false; + } + break; + default: + return false; + } + + return true; +} + +bool TConstantUnion::operator==(const int i) const +{ + switch (type) + { + case EbtFloat: + return static_cast(i) == fConst; + default: + return i == iConst; + } +} + +bool TConstantUnion::operator==(const unsigned int u) const +{ + switch (type) + { + case EbtFloat: + return static_cast(u) == fConst; + default: + return u == uConst; + } +} + +bool TConstantUnion::operator==(const float f) const +{ + switch (type) + { + case EbtInt: + return f == static_cast(iConst); + case EbtUInt: + return f == static_cast(uConst); + default: + return f == fConst; + } +} + +bool TConstantUnion::operator==(const bool b) const +{ + return b == bConst; +} + +bool TConstantUnion::operator==(const TYuvCscStandardEXT s) const +{ + return s == yuvCscStandardEXTConst; +} + +bool TConstantUnion::operator==(const TConstantUnion &constant) const +{ + ImplicitTypeConversion conversion = GetConversion(constant.type, type); + if (conversion == ImplicitTypeConversion::Same) + { + switch (type) + { + case EbtInt: + return constant.iConst == iConst; + case EbtUInt: + return constant.uConst == uConst; + case EbtFloat: + return constant.fConst == fConst; + case EbtBool: + return constant.bConst == bConst; + case EbtYuvCscStandardEXT: + return constant.yuvCscStandardEXTConst == yuvCscStandardEXTConst; + default: + return false; + } + } + else if (conversion == ImplicitTypeConversion::Invalid) + { + return false; + } + else + { + return constant.getFConst() == getFConst(); + } +} + +bool TConstantUnion::operator!=(const int i) const +{ + return !operator==(i); +} + +bool TConstantUnion::operator!=(const unsigned int u) const +{ + return !operator==(u); +} + +bool TConstantUnion::operator!=(const float f) const +{ + return !operator==(f); +} + +bool TConstantUnion::operator!=(const bool b) const +{ + return !operator==(b); +} + +bool TConstantUnion::operator!=(const TYuvCscStandardEXT s) const +{ + return !operator==(s); +} + +bool TConstantUnion::operator!=(const TConstantUnion &constant) const +{ + return !operator==(constant); +} + +bool TConstantUnion::operator>(const TConstantUnion &constant) const +{ + + ImplicitTypeConversion conversion = GetConversion(constant.type, type); + if (conversion == ImplicitTypeConversion::Same) + { + switch (type) + { + case EbtInt: + return iConst > constant.iConst; + case EbtUInt: + return uConst > constant.uConst; + case EbtFloat: + return fConst > constant.fConst; + default: + return false; // Invalid operation, handled at semantic analysis + } + } + else + { + ASSERT(conversion != ImplicitTypeConversion::Invalid); + return getFConst() > constant.getFConst(); + } +} + +bool TConstantUnion::operator<(const TConstantUnion &constant) const +{ + ImplicitTypeConversion conversion = GetConversion(constant.type, type); + if (conversion == ImplicitTypeConversion::Same) + { + switch (type) + { + case EbtInt: + return iConst < constant.iConst; + case EbtUInt: + return uConst < constant.uConst; + case EbtFloat: + return fConst < constant.fConst; + default: + return false; // Invalid operation, handled at semantic analysis + } + } + else + { + ASSERT(conversion != ImplicitTypeConversion::Invalid); + return getFConst() < constant.getFConst(); + } +} + +// static +TConstantUnion TConstantUnion::add(const TConstantUnion &lhs, + const TConstantUnion &rhs, + TDiagnostics *diag, + const TSourceLoc &line) +{ + TConstantUnion returnValue; + + ImplicitTypeConversion conversion = GetConversion(lhs.type, rhs.type); + if (conversion == ImplicitTypeConversion::Same) + { + switch (lhs.type) + { + case EbtInt: + returnValue.setIConst(gl::WrappingSum(lhs.iConst, rhs.iConst)); + break; + case EbtUInt: + returnValue.setUConst(gl::WrappingSum(lhs.uConst, rhs.uConst)); + break; + case EbtFloat: + returnValue.setFConst(CheckedSum(lhs.fConst, rhs.fConst, diag, line)); + break; + default: + UNREACHABLE(); + } + } + else + { + ASSERT(conversion != ImplicitTypeConversion::Invalid); + returnValue.setFConst(CheckedSum(lhs.getFConst(), rhs.getFConst(), diag, line)); + } + + return returnValue; +} + +// static +TConstantUnion TConstantUnion::sub(const TConstantUnion &lhs, + const TConstantUnion &rhs, + TDiagnostics *diag, + const TSourceLoc &line) +{ + TConstantUnion returnValue; + + ImplicitTypeConversion conversion = GetConversion(lhs.type, rhs.type); + if (conversion == ImplicitTypeConversion::Same) + { + switch (lhs.type) + { + case EbtInt: + returnValue.setIConst(gl::WrappingDiff(lhs.iConst, rhs.iConst)); + break; + case EbtUInt: + returnValue.setUConst(gl::WrappingDiff(lhs.uConst, rhs.uConst)); + break; + case EbtFloat: + returnValue.setFConst(CheckedDiff(lhs.fConst, rhs.fConst, diag, line)); + break; + default: + UNREACHABLE(); + } + } + else + { + ASSERT(conversion != ImplicitTypeConversion::Invalid); + returnValue.setFConst(CheckedDiff(lhs.getFConst(), rhs.getFConst(), diag, line)); + } + + return returnValue; +} + +// static +TConstantUnion TConstantUnion::mul(const TConstantUnion &lhs, + const TConstantUnion &rhs, + TDiagnostics *diag, + const TSourceLoc &line) +{ + TConstantUnion returnValue; + + ImplicitTypeConversion conversion = GetConversion(lhs.type, rhs.type); + if (conversion == ImplicitTypeConversion::Same) + { + switch (lhs.type) + { + case EbtInt: + returnValue.setIConst(gl::WrappingMul(lhs.iConst, rhs.iConst)); + break; + case EbtUInt: + // Unsigned integer math in C++ is defined to be done in modulo 2^n, so we rely + // on that to implement wrapping multiplication. + returnValue.setUConst(lhs.uConst * rhs.uConst); + break; + case EbtFloat: + returnValue.setFConst(CheckedMul(lhs.fConst, rhs.fConst, diag, line)); + break; + default: + UNREACHABLE(); + } + } + else + { + ASSERT(conversion != ImplicitTypeConversion::Invalid); + returnValue.setFConst(CheckedMul(lhs.getFConst(), rhs.getFConst(), diag, line)); + } + + return returnValue; +} + +TConstantUnion TConstantUnion::operator%(const TConstantUnion &constant) const +{ + TConstantUnion returnValue; + ASSERT(type == constant.type); + switch (type) + { + case EbtInt: + returnValue.setIConst(iConst % constant.iConst); + break; + case EbtUInt: + returnValue.setUConst(uConst % constant.uConst); + break; + default: + UNREACHABLE(); + } + + return returnValue; +} + +// static +TConstantUnion TConstantUnion::rshift(const TConstantUnion &lhs, + const TConstantUnion &rhs, + TDiagnostics *diag, + const TSourceLoc &line) +{ + TConstantUnion returnValue; + ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt); + ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt); + if (!IsValidShiftOffset(rhs)) + { + diag->warning(line, "Undefined shift (operand out of range)", ">>"); + switch (lhs.type) + { + case EbtInt: + returnValue.setIConst(0); + break; + case EbtUInt: + returnValue.setUConst(0u); + break; + default: + UNREACHABLE(); + } + return returnValue; + } + + switch (lhs.type) + { + case EbtInt: + { + unsigned int shiftOffset = 0; + switch (rhs.type) + { + case EbtInt: + shiftOffset = static_cast(rhs.iConst); + break; + case EbtUInt: + shiftOffset = rhs.uConst; + break; + default: + UNREACHABLE(); + } + if (shiftOffset > 0) + { + // ESSL 3.00.6 section 5.9: "If E1 is a signed integer, the right-shift will extend + // the sign bit." In C++ shifting negative integers is undefined, so we implement + // extending the sign bit manually. + int lhsSafe = lhs.iConst; + if (lhsSafe == std::numeric_limits::min()) + { + // The min integer needs special treatment because only bit it has set is the + // sign bit, which we clear later to implement safe right shift of negative + // numbers. + lhsSafe = -0x40000000; + --shiftOffset; + } + if (shiftOffset > 0) + { + bool extendSignBit = false; + if (lhsSafe < 0) + { + extendSignBit = true; + // Clear the sign bit so that bitshift right is defined in C++. + lhsSafe &= 0x7fffffff; + ASSERT(lhsSafe > 0); + } + returnValue.setIConst(lhsSafe >> shiftOffset); + + // Manually fill in the extended sign bit if necessary. + if (extendSignBit) + { + int extendedSignBit = static_cast(0xffffffffu << (31 - shiftOffset)); + returnValue.setIConst(returnValue.getIConst() | extendedSignBit); + } + } + else + { + returnValue.setIConst(lhsSafe); + } + } + else + { + returnValue.setIConst(lhs.iConst); + } + break; + } + case EbtUInt: + switch (rhs.type) + { + case EbtInt: + returnValue.setUConst(lhs.uConst >> rhs.iConst); + break; + case EbtUInt: + returnValue.setUConst(lhs.uConst >> rhs.uConst); + break; + default: + UNREACHABLE(); + } + break; + + default: + UNREACHABLE(); + } + return returnValue; +} + +// static +TConstantUnion TConstantUnion::lshift(const TConstantUnion &lhs, + const TConstantUnion &rhs, + TDiagnostics *diag, + const TSourceLoc &line) +{ + TConstantUnion returnValue; + ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt); + ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt); + if (!IsValidShiftOffset(rhs)) + { + diag->warning(line, "Undefined shift (operand out of range)", "<<"); + switch (lhs.type) + { + case EbtInt: + returnValue.setIConst(0); + break; + case EbtUInt: + returnValue.setUConst(0u); + break; + default: + UNREACHABLE(); + } + return returnValue; + } + + switch (lhs.type) + { + case EbtInt: + switch (rhs.type) + { + // Cast to unsigned integer before shifting, since ESSL 3.00.6 section 5.9 says that + // lhs is "interpreted as a bit pattern". This also avoids the possibility of signed + // integer overflow or undefined shift of a negative integer. + case EbtInt: + returnValue.setIConst( + static_cast(static_cast(lhs.iConst) << rhs.iConst)); + break; + case EbtUInt: + returnValue.setIConst( + static_cast(static_cast(lhs.iConst) << rhs.uConst)); + break; + default: + UNREACHABLE(); + } + break; + + case EbtUInt: + switch (rhs.type) + { + case EbtInt: + returnValue.setUConst(lhs.uConst << rhs.iConst); + break; + case EbtUInt: + returnValue.setUConst(lhs.uConst << rhs.uConst); + break; + default: + UNREACHABLE(); + } + break; + + default: + UNREACHABLE(); + } + return returnValue; +} + +TConstantUnion TConstantUnion::operator&(const TConstantUnion &constant) const +{ + TConstantUnion returnValue; + ASSERT(constant.type == EbtInt || constant.type == EbtUInt); + switch (type) + { + case EbtInt: + returnValue.setIConst(iConst & constant.iConst); + break; + case EbtUInt: + returnValue.setUConst(uConst & constant.uConst); + break; + default: + UNREACHABLE(); + } + + return returnValue; +} + +TConstantUnion TConstantUnion::operator|(const TConstantUnion &constant) const +{ + TConstantUnion returnValue; + ASSERT(type == constant.type); + switch (type) + { + case EbtInt: + returnValue.setIConst(iConst | constant.iConst); + break; + case EbtUInt: + returnValue.setUConst(uConst | constant.uConst); + break; + default: + UNREACHABLE(); + } + + return returnValue; +} + +TConstantUnion TConstantUnion::operator^(const TConstantUnion &constant) const +{ + TConstantUnion returnValue; + ASSERT(type == constant.type); + switch (type) + { + case EbtInt: + returnValue.setIConst(iConst ^ constant.iConst); + break; + case EbtUInt: + returnValue.setUConst(uConst ^ constant.uConst); + break; + default: + UNREACHABLE(); + } + + return returnValue; +} + +TConstantUnion TConstantUnion::operator&&(const TConstantUnion &constant) const +{ + TConstantUnion returnValue; + ASSERT(type == constant.type); + switch (type) + { + case EbtBool: + returnValue.setBConst(bConst && constant.bConst); + break; + default: + UNREACHABLE(); + } + + return returnValue; +} + +TConstantUnion TConstantUnion::operator||(const TConstantUnion &constant) const +{ + TConstantUnion returnValue; + ASSERT(type == constant.type); + switch (type) + { + case EbtBool: + returnValue.setBConst(bConst || constant.bConst); + break; + default: + UNREACHABLE(); + } + + return returnValue; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ConstantUnion.h b/gfx/angle/checkout/src/compiler/translator/ConstantUnion.h new file mode 100644 index 0000000000..df53857dd3 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ConstantUnion.h @@ -0,0 +1,122 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_CONSTANTUNION_H_ +#define COMPILER_TRANSLATOR_CONSTANTUNION_H_ + +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/Common.h" + +namespace sh +{ + +class TDiagnostics; + +class TConstantUnion +{ + public: + POOL_ALLOCATOR_NEW_DELETE + TConstantUnion(); + TConstantUnion(int i); + TConstantUnion(unsigned int u); + TConstantUnion(float f); + TConstantUnion(bool b); + + bool cast(TBasicType newType, const TConstantUnion &constant); + + void setIConst(int i) + { + iConst = i; + type = EbtInt; + } + void setUConst(unsigned int u) + { + uConst = u; + type = EbtUInt; + } + void setFConst(float f) + { + fConst = f; + type = EbtFloat; + } + void setBConst(bool b) + { + bConst = b; + type = EbtBool; + } + + void setYuvCscStandardEXTConst(TYuvCscStandardEXT s) + { + yuvCscStandardEXTConst = s; + type = EbtYuvCscStandardEXT; + } + + int getIConst() const; + unsigned int getUConst() const; + float getFConst() const; + bool getBConst() const; + bool isZero() const; + TYuvCscStandardEXT getYuvCscStandardEXTConst() const; + + bool operator==(const int i) const; + bool operator==(const unsigned int u) const; + bool operator==(const float f) const; + bool operator==(const bool b) const; + bool operator==(const TYuvCscStandardEXT s) const; + bool operator==(const TConstantUnion &constant) const; + bool operator!=(const int i) const; + bool operator!=(const unsigned int u) const; + bool operator!=(const float f) const; + bool operator!=(const bool b) const; + bool operator!=(const TYuvCscStandardEXT s) const; + bool operator!=(const TConstantUnion &constant) const; + bool operator>(const TConstantUnion &constant) const; + bool operator<(const TConstantUnion &constant) const; + static TConstantUnion add(const TConstantUnion &lhs, + const TConstantUnion &rhs, + TDiagnostics *diag, + const TSourceLoc &line); + static TConstantUnion sub(const TConstantUnion &lhs, + const TConstantUnion &rhs, + TDiagnostics *diag, + const TSourceLoc &line); + static TConstantUnion mul(const TConstantUnion &lhs, + const TConstantUnion &rhs, + TDiagnostics *diag, + const TSourceLoc &line); + TConstantUnion operator%(const TConstantUnion &constant) const; + static TConstantUnion rshift(const TConstantUnion &lhs, + const TConstantUnion &rhs, + TDiagnostics *diag, + const TSourceLoc &line); + static TConstantUnion lshift(const TConstantUnion &lhs, + const TConstantUnion &rhs, + TDiagnostics *diag, + const TSourceLoc &line); + TConstantUnion operator&(const TConstantUnion &constant) const; + TConstantUnion operator|(const TConstantUnion &constant) const; + TConstantUnion operator^(const TConstantUnion &constant) const; + TConstantUnion operator&&(const TConstantUnion &constant) const; + TConstantUnion operator||(const TConstantUnion &constant) const; + + TBasicType getType() const { return type; } + + private: + union + { + int iConst; // used for ivec, scalar ints + unsigned int uConst; // used for uvec, scalar uints + bool bConst; // used for bvec, scalar bools + float fConst; // used for vec, mat, scalar floats + TYuvCscStandardEXT yuvCscStandardEXTConst; + }; + + TBasicType type; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_CONSTANTUNION_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/Declarator.cpp b/gfx/angle/checkout/src/compiler/translator/Declarator.cpp new file mode 100644 index 0000000000..7680c054d3 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Declarator.cpp @@ -0,0 +1,33 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Declarator.cpp: +// Declarator type for parsing structure field declarators. + +#include "compiler/translator/Declarator.h" + +namespace sh +{ + +TDeclarator::TDeclarator(const ImmutableString &name, const TSourceLoc &line) + : mName(name), mArraySizes(nullptr), mLine(line) +{ + ASSERT(mName != ""); +} + +TDeclarator::TDeclarator(const ImmutableString &name, + const TVector *arraySizes, + const TSourceLoc &line) + : mName(name), mArraySizes(arraySizes), mLine(line) +{ + ASSERT(mArraySizes); +} + +bool TDeclarator::isArray() const +{ + return mArraySizes != nullptr && mArraySizes->size() > 0; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/Declarator.h b/gfx/angle/checkout/src/compiler/translator/Declarator.h new file mode 100644 index 0000000000..5268334946 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Declarator.h @@ -0,0 +1,49 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Declarator.h: +// Declarator type for parsing structure field declarators. + +#ifndef COMPILER_TRANSLATOR_DECLARATOR_H_ +#define COMPILER_TRANSLATOR_DECLARATOR_H_ + +#include "compiler/translator/Common.h" +#include "compiler/translator/ImmutableString.h" + +namespace sh +{ + +// Declarator like "a[2][4]". Only used for parsing structure field declarators. +class TDeclarator : angle::NonCopyable +{ + public: + POOL_ALLOCATOR_NEW_DELETE + TDeclarator(const ImmutableString &name, const TSourceLoc &line); + + TDeclarator(const ImmutableString &name, + const TVector *arraySizes, + const TSourceLoc &line); + + const ImmutableString &name() const { return mName; } + + bool isArray() const; + const TVector *arraySizes() const { return mArraySizes; } + + const TSourceLoc &line() const { return mLine; } + + private: + const ImmutableString mName; + + // Outermost array size is stored at the end of the vector. + const TVector *const mArraySizes; + + const TSourceLoc mLine; +}; + +using TDeclaratorList = TVector; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_DECLARATOR_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/Diagnostics.cpp b/gfx/angle/checkout/src/compiler/translator/Diagnostics.cpp new file mode 100644 index 0000000000..03066a319d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Diagnostics.cpp @@ -0,0 +1,106 @@ +// +// Copyright 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/Diagnostics.h" + +#include "common/debug.h" +#include "compiler/preprocessor/SourceLocation.h" +#include "compiler/translator/Common.h" +#include "compiler/translator/InfoSink.h" + +namespace sh +{ + +TDiagnostics::TDiagnostics(TInfoSinkBase &infoSink) + : mInfoSink(infoSink), mNumErrors(0), mNumWarnings(0) +{} + +TDiagnostics::~TDiagnostics() {} + +void TDiagnostics::writeInfo(Severity severity, + const angle::pp::SourceLocation &loc, + const char *reason, + const char *token) +{ + switch (severity) + { + case SH_ERROR: + ++mNumErrors; + break; + case SH_WARNING: + ++mNumWarnings; + break; + default: + UNREACHABLE(); + break; + } + + /* VC++ format: file(linenum) : error #: 'token' : extrainfo */ + mInfoSink.prefix(severity); + mInfoSink.location(loc.file, loc.line); + mInfoSink << "'" << token << "' : " << reason << "\n"; +} + +void TDiagnostics::globalError(const char *message) +{ + ++mNumErrors; + mInfoSink.prefix(SH_ERROR); + mInfoSink << message << "\n"; +} + +void TDiagnostics::error(const angle::pp::SourceLocation &loc, + const char *reason, + const char *token) +{ + writeInfo(SH_ERROR, loc, reason, token); +} + +void TDiagnostics::warning(const angle::pp::SourceLocation &loc, + const char *reason, + const char *token) +{ + writeInfo(SH_WARNING, loc, reason, token); +} + +void TDiagnostics::error(const TSourceLoc &loc, const char *reason, const char *token) +{ + angle::pp::SourceLocation srcLoc; + srcLoc.file = loc.first_file; + srcLoc.line = loc.first_line; + error(srcLoc, reason, token); +} + +void TDiagnostics::warning(const TSourceLoc &loc, const char *reason, const char *token) +{ + angle::pp::SourceLocation srcLoc; + srcLoc.file = loc.first_file; + srcLoc.line = loc.first_line; + warning(srcLoc, reason, token); +} + +void TDiagnostics::print(ID id, const angle::pp::SourceLocation &loc, const std::string &text) +{ + writeInfo(isError(id) ? SH_ERROR : SH_WARNING, loc, message(id), text.c_str()); +} + +void TDiagnostics::resetErrorCount() +{ + mNumErrors = 0; + mNumWarnings = 0; +} + +PerformanceDiagnostics::PerformanceDiagnostics(TDiagnostics *diagnostics) + : mDiagnostics(diagnostics) +{ + ASSERT(diagnostics); +} + +void PerformanceDiagnostics::warning(const TSourceLoc &loc, const char *reason, const char *token) +{ + mDiagnostics->warning(loc, reason, token); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/Diagnostics.h b/gfx/angle/checkout/src/compiler/translator/Diagnostics.h new file mode 100644 index 0000000000..8ed71b3d2b --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Diagnostics.h @@ -0,0 +1,67 @@ +// +// Copyright 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_DIAGNOSTICS_H_ +#define COMPILER_TRANSLATOR_DIAGNOSTICS_H_ + +#include "common/angleutils.h" +#include "compiler/preprocessor/DiagnosticsBase.h" +#include "compiler/translator/Severity.h" + +namespace sh +{ + +class TInfoSinkBase; +struct TSourceLoc; + +class TDiagnostics : public angle::pp::Diagnostics, angle::NonCopyable +{ + public: + TDiagnostics(TInfoSinkBase &infoSink); + ~TDiagnostics() override; + + int numErrors() const { return mNumErrors; } + int numWarnings() const { return mNumWarnings; } + + void error(const angle::pp::SourceLocation &loc, const char *reason, const char *token); + void warning(const angle::pp::SourceLocation &loc, const char *reason, const char *token); + + void error(const TSourceLoc &loc, const char *reason, const char *token); + void warning(const TSourceLoc &loc, const char *reason, const char *token); + + void globalError(const char *message); + + void resetErrorCount(); + + protected: + void writeInfo(Severity severity, + const angle::pp::SourceLocation &loc, + const char *reason, + const char *token); + + void print(ID id, const angle::pp::SourceLocation &loc, const std::string &text) override; + + private: + TInfoSinkBase &mInfoSink; + int mNumErrors; + int mNumWarnings; +}; + +// Diagnostics wrapper to use when the code is only allowed to generate warnings. +class PerformanceDiagnostics : public angle::NonCopyable +{ + public: + PerformanceDiagnostics(TDiagnostics *diagnostics); + + void warning(const TSourceLoc &loc, const char *reason, const char *token); + + private: + TDiagnostics *mDiagnostics; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_DIAGNOSTICS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/DirectiveHandler.cpp b/gfx/angle/checkout/src/compiler/translator/DirectiveHandler.cpp new file mode 100644 index 0000000000..80b238e055 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/DirectiveHandler.cpp @@ -0,0 +1,304 @@ +// +// Copyright 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/DirectiveHandler.h" + +#include + +#include "angle_gl.h" +#include "common/debug.h" +#include "compiler/translator/Common.h" +#include "compiler/translator/Diagnostics.h" + +namespace sh +{ + +static TBehavior getBehavior(const std::string &str) +{ + const char kRequire[] = "require"; + const char kEnable[] = "enable"; + const char kDisable[] = "disable"; + const char kWarn[] = "warn"; + + if (str == kRequire) + return EBhRequire; + else if (str == kEnable) + return EBhEnable; + else if (str == kDisable) + return EBhDisable; + else if (str == kWarn) + return EBhWarn; + return EBhUndefined; +} + +TDirectiveHandler::TDirectiveHandler(TExtensionBehavior &extBehavior, + TDiagnostics &diagnostics, + int &shaderVersion, + sh::GLenum shaderType) + : mExtensionBehavior(extBehavior), + mDiagnostics(diagnostics), + mShaderVersion(shaderVersion), + mShaderType(shaderType) +{} + +TDirectiveHandler::~TDirectiveHandler() {} + +void TDirectiveHandler::handleError(const angle::pp::SourceLocation &loc, const std::string &msg) +{ + mDiagnostics.error(loc, msg.c_str(), ""); +} + +void TDirectiveHandler::handlePragma(const angle::pp::SourceLocation &loc, + const std::string &name, + const std::string &value, + bool stdgl) +{ + if (stdgl) + { + const char kInvariant[] = "invariant"; + const char kAll[] = "all"; + + if (name == kInvariant && value == kAll) + { + if (mShaderVersion == 300 && mShaderType == GL_FRAGMENT_SHADER) + { + // ESSL 3.00.4 section 4.6.1 + mDiagnostics.error( + loc, "#pragma STDGL invariant(all) can not be used in fragment shader", + name.c_str()); + } + mPragma.stdgl.invariantAll = true; + } + // The STDGL pragma is used to reserve pragmas for use by future + // revisions of GLSL. Do not generate an error on unexpected + // name and value. + return; + } + else + { + const char kOptimize[] = "optimize"; + const char kDebug[] = "debug"; + const char kOn[] = "on"; + const char kOff[] = "off"; + + bool invalidValue = false; + if (name == kOptimize) + { + if (value == kOn) + mPragma.optimize = true; + else if (value == kOff) + mPragma.optimize = false; + else + invalidValue = true; + } + else if (name == kDebug) + { + if (value == kOn) + mPragma.debug = true; + else if (value == kOff) + mPragma.debug = false; + else + invalidValue = true; + } + else + { + mDiagnostics.report(angle::pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name); + return; + } + + if (invalidValue) + { + mDiagnostics.error(loc, "invalid pragma value - 'on' or 'off' expected", value.c_str()); + } + } +} + +void TDirectiveHandler::handleExtension(const angle::pp::SourceLocation &loc, + const std::string &name, + const std::string &behavior) +{ + const char kExtAll[] = "all"; + + TBehavior behaviorVal = getBehavior(behavior); + if (behaviorVal == EBhUndefined) + { + mDiagnostics.error(loc, "behavior invalid", name.c_str()); + return; + } + + if (name == kExtAll) + { + if (behaviorVal == EBhRequire) + { + mDiagnostics.error(loc, "extension cannot have 'require' behavior", name.c_str()); + } + else if (behaviorVal == EBhEnable) + { + mDiagnostics.error(loc, "extension cannot have 'enable' behavior", name.c_str()); + } + else + { + for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin(); + iter != mExtensionBehavior.end(); ++iter) + iter->second = behaviorVal; + } + return; + } + + TExtensionBehavior::iterator iter = mExtensionBehavior.find(GetExtensionByName(name.c_str())); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + // OVR_multiview is implicitly enabled when OVR_multiview2 is enabled + if (name == "GL_OVR_multiview2") + { + constexpr char kMultiviewExtName[] = "GL_OVR_multiview"; + iter = mExtensionBehavior.find(GetExtensionByName(kMultiviewExtName)); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + } + } + // All the extensions listed in the spec here: + // https://www.khronos.org/registry/OpenGL/extensions/ANDROID/ANDROID_extension_pack_es31a.txt + // are implicitly enabled when GL_ANDROID_extension_pack_es31a is enabled + if (name == "GL_ANDROID_extension_pack_es31a") + { + constexpr char kGeometryShaderExtName[] = "GL_EXT_geometry_shader"; + constexpr char kTessellationShaderExtName[] = "GL_EXT_tessellation_shader"; + constexpr char kGpuShader5ExtName[] = "GL_EXT_gpu_shader5"; + constexpr char kTextureBufferExtName[] = "GL_EXT_texture_buffer"; + constexpr char kTextureCubeMapArrayExtName[] = "GL_EXT_texture_cube_map_array"; + constexpr char kSampleVariablesExtName[] = "GL_OES_sample_variables"; + constexpr char kShaderMultisampleInterpolationExtName[] = + "GL_OES_shader_multisample_interpolation"; + constexpr char kShaderImageAtomicExtName[] = "GL_OES_shader_image_atomic"; + constexpr char kTextureStorageMultisample2dArrayExtName[] = + "GL_OES_texture_storage_multisample_2d_array"; + iter = mExtensionBehavior.find(GetExtensionByName(kGeometryShaderExtName)); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + } + + iter = mExtensionBehavior.find(GetExtensionByName(kTessellationShaderExtName)); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + } + + iter = mExtensionBehavior.find(GetExtensionByName(kGpuShader5ExtName)); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + } + + iter = mExtensionBehavior.find(GetExtensionByName(kTextureBufferExtName)); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + } + + iter = mExtensionBehavior.find(GetExtensionByName(kTextureCubeMapArrayExtName)); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + } + + iter = mExtensionBehavior.find(GetExtensionByName(kSampleVariablesExtName)); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + } + + iter = + mExtensionBehavior.find(GetExtensionByName(kShaderMultisampleInterpolationExtName)); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + } + + iter = mExtensionBehavior.find(GetExtensionByName(kShaderImageAtomicExtName)); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + } + + iter = mExtensionBehavior.find( + GetExtensionByName(kTextureStorageMultisample2dArrayExtName)); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + } + } + // EXT_shader_io_blocks is implicitly enabled when EXT_geometry_shader or + // EXT_tessellation_shader is enabled. + if (name == "GL_EXT_geometry_shader" || name == "GL_EXT_tessellation_shader") + { + constexpr char kIOBlocksExtName[] = "GL_EXT_shader_io_blocks"; + iter = mExtensionBehavior.find(GetExtensionByName(kIOBlocksExtName)); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + } + } + // GL_APPLE_clip_distance is implicitly enabled when GL_EXT_clip_cull_distance is enabled + else if (name == "GL_EXT_clip_cull_distance") + { + // This extension only can be enabled on greater than ESSL 300 + if (mShaderVersion < 300) + { + mDiagnostics.error(loc, "extension can be enabled on greater than ESSL 300", + name.c_str()); + return; + } + + constexpr char kAPPLEClipDistanceEXTName[] = "GL_APPLE_clip_distance"; + iter = mExtensionBehavior.find(GetExtensionByName(kAPPLEClipDistanceEXTName)); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + } + } + return; + } + + switch (behaviorVal) + { + case EBhRequire: + mDiagnostics.error(loc, "extension is not supported", name.c_str()); + break; + case EBhEnable: + case EBhWarn: + case EBhDisable: + mDiagnostics.warning(loc, "extension is not supported", name.c_str()); + break; + default: + UNREACHABLE(); + break; + } +} + +void TDirectiveHandler::handleVersion(const angle::pp::SourceLocation &loc, + int version, + ShShaderSpec spec) +{ + if (((version == 100 || version == 300 || version == 310 || version == 320) && + !IsDesktopGLSpec(spec)) || + IsDesktopGLSpec(spec)) + { + mShaderVersion = version; + } + else + { + std::stringstream stream = sh::InitializeStream(); + stream << version; + std::string str = stream.str(); + mDiagnostics.error(loc, "client/version number not supported", str.c_str()); + } +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/DirectiveHandler.h b/gfx/angle/checkout/src/compiler/translator/DirectiveHandler.h new file mode 100644 index 0000000000..6fb54558ef --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/DirectiveHandler.h @@ -0,0 +1,57 @@ +// +// Copyright 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ +#define COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ + +#include "GLSLANG/ShaderLang.h" +#include "common/angleutils.h" +#include "compiler/preprocessor/DirectiveHandlerBase.h" +#include "compiler/translator/ExtensionBehavior.h" +#include "compiler/translator/Pragma.h" + +namespace sh +{ +class TDiagnostics; + +class TDirectiveHandler : public angle::pp::DirectiveHandler, angle::NonCopyable +{ + public: + TDirectiveHandler(TExtensionBehavior &extBehavior, + TDiagnostics &diagnostics, + int &shaderVersion, + sh::GLenum shaderType); + ~TDirectiveHandler() override; + + const TPragma &pragma() const { return mPragma; } + const TExtensionBehavior &extensionBehavior() const { return mExtensionBehavior; } + + void handleError(const angle::pp::SourceLocation &loc, const std::string &msg) override; + + void handlePragma(const angle::pp::SourceLocation &loc, + const std::string &name, + const std::string &value, + bool stdgl) override; + + void handleExtension(const angle::pp::SourceLocation &loc, + const std::string &name, + const std::string &behavior) override; + + void handleVersion(const angle::pp::SourceLocation &loc, + int version, + ShShaderSpec spec) override; + + private: + TPragma mPragma; + TExtensionBehavior &mExtensionBehavior; + TDiagnostics &mDiagnostics; + int &mShaderVersion; + sh::GLenum mShaderType; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/DriverUniformMetal.h b/gfx/angle/checkout/src/compiler/translator/DriverUniformMetal.h new file mode 100644 index 0000000000..47e075b2e7 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/DriverUniformMetal.h @@ -0,0 +1,33 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// DriverUniformMetal: +// Struct defining the default driver uniforms for direct and SpirV based ANGLE translation +// + +#ifndef LIBANGLE_RENDERER_METAL_DRIVERUNIFORMMETAL_H_ +#define LIBANGLE_RENDERER_METAL_DRIVERUNIFORMMETAL_H_ + +#include "compiler/translator/tree_util/DriverUniform.h" + +namespace sh +{ + +class DriverUniformMetal : public DriverUniformExtended +{ + public: + DriverUniformMetal(DriverUniformMode mode) : DriverUniformExtended(mode) {} + DriverUniformMetal() : DriverUniformExtended(DriverUniformMode::InterfaceBlock) {} + ~DriverUniformMetal() override {} + + TIntermTyped *getCoverageMaskField() const; + + protected: + TFieldList *createUniformFields(TSymbolTable *symbolTable) override; +}; + +} // namespace sh + +#endif /* LIBANGLE_RENDERER_METAL_DRIVERUNIFORMMETAL_H_ */ diff --git a/gfx/angle/checkout/src/compiler/translator/ExtensionBehavior.cpp b/gfx/angle/checkout/src/compiler/translator/ExtensionBehavior.cpp new file mode 100644 index 0000000000..9c16393272 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ExtensionBehavior.cpp @@ -0,0 +1,125 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ExtensionBehavior.cpp: Extension name enumeration and data structures for storing extension +// behavior. + +#include "compiler/translator/ExtensionBehavior.h" + +#include "common/debug.h" + +#include + +#define LIST_EXTENSIONS(OP) \ + OP(ANDROID_extension_pack_es31a) \ + OP(ANGLE_base_vertex_base_instance_shader_builtin) \ + OP(ANGLE_multi_draw) \ + OP(ANGLE_shader_pixel_local_storage) \ + OP(ANGLE_texture_multisample) \ + OP(APPLE_clip_distance) \ + OP(ARB_texture_rectangle) \ + OP(ARM_shader_framebuffer_fetch) \ + OP(EXT_blend_func_extended) \ + OP(EXT_clip_cull_distance) \ + OP(EXT_draw_buffers) \ + OP(EXT_frag_depth) \ + OP(EXT_geometry_shader) \ + OP(OES_geometry_shader) \ + OP(OES_shader_io_blocks) \ + OP(EXT_shader_io_blocks) \ + OP(EXT_gpu_shader5) \ + OP(EXT_primitive_bounding_box) \ + OP(OES_primitive_bounding_box) \ + OP(EXT_shader_framebuffer_fetch) \ + OP(EXT_shader_framebuffer_fetch_non_coherent) \ + OP(EXT_shader_non_constant_global_initializers) \ + OP(EXT_shader_texture_lod) \ + OP(EXT_shadow_samplers) \ + OP(EXT_tessellation_shader) \ + OP(EXT_texture_buffer) \ + OP(EXT_texture_cube_map_array) \ + OP(EXT_YUV_target) \ + OP(KHR_blend_equation_advanced) \ + OP(NV_EGL_stream_consumer_external) \ + OP(NV_shader_framebuffer_fetch) \ + OP(NV_shader_noperspective_interpolation) \ + OP(OES_EGL_image_external) \ + OP(OES_EGL_image_external_essl3) \ + OP(OES_sample_variables) \ + OP(OES_shader_multisample_interpolation) \ + OP(OES_shader_image_atomic) \ + OP(OES_standard_derivatives) \ + OP(OES_texture_3D) \ + OP(OES_texture_buffer) \ + OP(OES_texture_cube_map_array) \ + OP(OES_texture_storage_multisample_2d_array) \ + OP(OVR_multiview) \ + OP(OVR_multiview2) \ + OP(WEBGL_video_texture) + +namespace sh +{ + +#define RETURN_EXTENSION_NAME_CASE(ext) \ + case TExtension::ext: \ + return "GL_" #ext; + +const char *GetExtensionNameString(TExtension extension) +{ + switch (extension) + { + LIST_EXTENSIONS(RETURN_EXTENSION_NAME_CASE) + default: + UNREACHABLE(); + return ""; + } +} + +#define RETURN_EXTENSION_IF_NAME_MATCHES(ext) \ + if (strcmp(extWithoutGLPrefix, #ext) == 0) \ + { \ + return TExtension::ext; \ + } + +TExtension GetExtensionByName(const char *extension) +{ + // If first characters of the extension don't equal "GL_", early out. + if (strncmp(extension, "GL_", 3) != 0) + { + return TExtension::UNDEFINED; + } + const char *extWithoutGLPrefix = extension + 3; + + LIST_EXTENSIONS(RETURN_EXTENSION_IF_NAME_MATCHES) + + return TExtension::UNDEFINED; +} + +const char *GetBehaviorString(TBehavior b) +{ + switch (b) + { + case EBhRequire: + return "require"; + case EBhEnable: + return "enable"; + case EBhWarn: + return "warn"; + case EBhDisable: + return "disable"; + default: + return nullptr; + } +} + +bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, TExtension extension) +{ + ASSERT(extension != TExtension::UNDEFINED); + auto iter = extBehavior.find(extension); + return iter != extBehavior.end() && + (iter->second == EBhEnable || iter->second == EBhRequire || iter->second == EBhWarn); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ExtensionBehavior.h b/gfx/angle/checkout/src/compiler/translator/ExtensionBehavior.h new file mode 100644 index 0000000000..64b0748854 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ExtensionBehavior.h @@ -0,0 +1,93 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ExtensionBehavior.h: Extension name enumeration and data structures for storing extension +// behavior. + +#ifndef COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ +#define COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ + +#include +#include + +namespace sh +{ + +enum class TExtension : uint8_t +{ + UNDEFINED, // Special value used to indicate no extension. + + ANDROID_extension_pack_es31a, + ANGLE_base_vertex_base_instance_shader_builtin, + ANGLE_multi_draw, + ANGLE_shader_pixel_local_storage, + ANGLE_texture_multisample, + APPLE_clip_distance, + ARB_fragment_shader_interlock, + ARB_texture_rectangle, + ARM_shader_framebuffer_fetch, + EXT_YUV_target, + EXT_blend_func_extended, + EXT_clip_cull_distance, + EXT_draw_buffers, + EXT_frag_depth, + EXT_geometry_shader, + EXT_gpu_shader5, + EXT_primitive_bounding_box, + EXT_shader_framebuffer_fetch, + EXT_shader_framebuffer_fetch_non_coherent, + EXT_shader_io_blocks, + EXT_shader_non_constant_global_initializers, + EXT_shader_texture_lod, + EXT_shadow_samplers, + EXT_tessellation_shader, + EXT_texture_buffer, + EXT_texture_cube_map_array, + INTEL_fragment_shader_ordering, + KHR_blend_equation_advanced, + NV_EGL_stream_consumer_external, + NV_fragment_shader_interlock, + NV_shader_framebuffer_fetch, + NV_shader_noperspective_interpolation, + OES_EGL_image_external, + OES_EGL_image_external_essl3, + OES_geometry_shader, + OES_primitive_bounding_box, + OES_sample_variables, + OES_shader_image_atomic, + OES_shader_io_blocks, + OES_shader_multisample_interpolation, + OES_standard_derivatives, + OES_texture_3D, + OES_texture_buffer, + OES_texture_cube_map_array, + OES_texture_storage_multisample_2d_array, + OVR_multiview, + OVR_multiview2, + WEBGL_video_texture, +}; + +enum TBehavior : uint8_t +{ + EBhRequire, + EBhEnable, + EBhWarn, + EBhDisable, + EBhUndefined +}; + +const char *GetExtensionNameString(TExtension extension); +TExtension GetExtensionByName(const char *extension); + +const char *GetBehaviorString(TBehavior b); + +// Mapping between extension id and behavior. +typedef std::map TExtensionBehavior; + +bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, TExtension extension); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ExtensionGLSL.cpp b/gfx/angle/checkout/src/compiler/translator/ExtensionGLSL.cpp new file mode 100644 index 0000000000..563dbab185 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ExtensionGLSL.cpp @@ -0,0 +1,118 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ExtensionGLSL.cpp: Implements the TExtensionGLSL class that tracks GLSL extension requirements +// of shaders. + +#include "compiler/translator/ExtensionGLSL.h" + +#include "compiler/translator/VersionGLSL.h" + +namespace sh +{ + +TExtensionGLSL::TExtensionGLSL(ShShaderOutput output) + : TIntermTraverser(true, false, false), mTargetVersion(ShaderOutputTypeToGLSLVersion(output)) +{} + +const std::set &TExtensionGLSL::getEnabledExtensions() const +{ + return mEnabledExtensions; +} + +const std::set &TExtensionGLSL::getRequiredExtensions() const +{ + return mRequiredExtensions; +} + +bool TExtensionGLSL::visitUnary(Visit, TIntermUnary *node) +{ + checkOperator(node); + + return true; +} + +bool TExtensionGLSL::visitAggregate(Visit, TIntermAggregate *node) +{ + checkOperator(node); + + return true; +} + +void TExtensionGLSL::checkOperator(TIntermOperator *node) +{ + if (mTargetVersion < GLSL_VERSION_130) + { + return; + } + + switch (node->getOp()) + { + case EOpAbs: + break; + + case EOpSign: + break; + + case EOpMix: + break; + + case EOpFloatBitsToInt: + case EOpFloatBitsToUint: + case EOpIntBitsToFloat: + case EOpUintBitsToFloat: + if (mTargetVersion < GLSL_VERSION_330) + { + // Bit conversion functions cannot be emulated. + mRequiredExtensions.insert("GL_ARB_shader_bit_encoding"); + } + break; + + case EOpPackSnorm2x16: + case EOpPackHalf2x16: + case EOpUnpackSnorm2x16: + case EOpUnpackHalf2x16: + if (mTargetVersion < GLSL_VERSION_420) + { + mEnabledExtensions.insert("GL_ARB_shading_language_packing"); + + if (mTargetVersion < GLSL_VERSION_330) + { + // floatBitsToUint and uintBitsToFloat are needed to emulate + // packHalf2x16 and unpackHalf2x16 respectively and cannot be + // emulated themselves. + mRequiredExtensions.insert("GL_ARB_shader_bit_encoding"); + } + } + break; + + case EOpPackUnorm2x16: + case EOpUnpackUnorm2x16: + if (mTargetVersion < GLSL_VERSION_410) + { + mEnabledExtensions.insert("GL_ARB_shading_language_packing"); + } + break; + + case EOpBeginInvocationInterlockNV: + case EOpEndInvocationInterlockNV: + mRequiredExtensions.insert("GL_NV_fragment_shader_interlock"); + break; + + case EOpBeginFragmentShaderOrderingINTEL: + mRequiredExtensions.insert("GL_INTEL_fragment_shader_ordering"); + break; + + case EOpBeginInvocationInterlockARB: + case EOpEndInvocationInterlockARB: + mRequiredExtensions.insert("GL_ARB_fragment_shader_interlock"); + break; + + default: + break; + } +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ExtensionGLSL.h b/gfx/angle/checkout/src/compiler/translator/ExtensionGLSL.h new file mode 100644 index 0000000000..b07e4e95a9 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ExtensionGLSL.h @@ -0,0 +1,44 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ExtensionGLSL.h: Defines the TExtensionGLSL class that tracks GLSL extension requirements of +// shaders. + +#ifndef COMPILER_TRANSLATOR_EXTENSIONGLSL_H_ +#define COMPILER_TRANSLATOR_EXTENSIONGLSL_H_ + +#include +#include + +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +// Traverses the intermediate tree to determine which GLSL extensions are required +// to support the shader. +class TExtensionGLSL : public TIntermTraverser +{ + public: + TExtensionGLSL(ShShaderOutput output); + + const std::set &getEnabledExtensions() const; + const std::set &getRequiredExtensions() const; + + bool visitUnary(Visit visit, TIntermUnary *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + + private: + void checkOperator(TIntermOperator *node); + + int mTargetVersion; + + std::set mEnabledExtensions; + std::set mRequiredExtensions; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_EXTENSIONGLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/FlagStd140Structs.cpp b/gfx/angle/checkout/src/compiler/translator/FlagStd140Structs.cpp new file mode 100644 index 0000000000..729e452893 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/FlagStd140Structs.cpp @@ -0,0 +1,76 @@ +// +// Copyright 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// FlagStd140Structs.cpp: Find structs in std140 blocks, where the padding added in the translator +// conflicts with the "natural" unpadded type. + +#include "compiler/translator/FlagStd140Structs.h" + +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class FlagStd140StructsTraverser : public TIntermTraverser +{ + public: + FlagStd140StructsTraverser() : TIntermTraverser(true, false, false) {} + + const std::vector getMappedStructs() const { return mMappedStructs; } + + protected: + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; + + private: + void mapBlockStructMembers(TIntermSymbol *blockDeclarator, const TInterfaceBlock *block); + + std::vector mMappedStructs; +}; + +void FlagStd140StructsTraverser::mapBlockStructMembers(TIntermSymbol *blockDeclarator, + const TInterfaceBlock *block) +{ + for (auto *field : block->fields()) + { + if (field->type()->getBasicType() == EbtStruct) + { + MappedStruct mappedStruct; + mappedStruct.blockDeclarator = blockDeclarator; + mappedStruct.field = field; + mMappedStructs.push_back(mappedStruct); + } + } +} + +bool FlagStd140StructsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) +{ + TIntermTyped *declarator = node->getSequence()->back()->getAsTyped(); + if (declarator->getBasicType() == EbtInterfaceBlock) + { + const TInterfaceBlock *block = declarator->getType().getInterfaceBlock(); + if (block->blockStorage() == EbsStd140) + { + mapBlockStructMembers(declarator->getAsSymbolNode(), block); + } + } + return false; +} + +} // anonymous namespace + +std::vector FlagStd140Structs(TIntermNode *node) +{ + FlagStd140StructsTraverser flaggingTraversal; + + node->traverse(&flaggingTraversal); + + return flaggingTraversal.getMappedStructs(); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/FlagStd140Structs.h b/gfx/angle/checkout/src/compiler/translator/FlagStd140Structs.h new file mode 100644 index 0000000000..2ff10b2319 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/FlagStd140Structs.h @@ -0,0 +1,30 @@ +// +// Copyright 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// FlagStd140Structs.h: Find structs in std140 blocks, where the padding added in the translator +// conflicts with the "natural" unpadded type. + +#ifndef COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ +#define COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ + +#include + +namespace sh +{ + +class TField; +class TIntermNode; +class TIntermSymbol; + +struct MappedStruct +{ + TIntermSymbol *blockDeclarator; + TField *field; +}; + +std::vector FlagStd140Structs(TIntermNode *node); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/FunctionLookup.cpp b/gfx/angle/checkout/src/compiler/translator/FunctionLookup.cpp new file mode 100644 index 0000000000..8b574e9363 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/FunctionLookup.cpp @@ -0,0 +1,179 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// FunctionLookup.cpp: Used for storing function calls that have not yet been resolved during +// parsing. +// + +#include "compiler/translator/FunctionLookup.h" +#include "compiler/translator/ImmutableStringBuilder.h" + +namespace sh +{ + +namespace +{ + +const char kFunctionMangledNameSeparator = '('; + +constexpr const ImmutableString kEmptyName(""); + +// Helper function for GetMangledNames +// Gets all ordered combinations of elements in list[currentIndex, end] +std::vector> GetImplicitConversionCombinations(const std::vector &list) +{ + std::vector> target; + target.push_back(std::vector()); + + for (size_t currentIndex = 0; currentIndex < list.size(); currentIndex++) + { + size_t prevIterSize = target.size(); + for (size_t copyIndex = 0; copyIndex < prevIterSize; copyIndex++) + { + std::vector combination = target[copyIndex]; + combination.push_back(list[currentIndex]); + target.push_back(combination); + } + } + + return target; +} + +} // anonymous namespace + +TFunctionLookup::TFunctionLookup(const ImmutableString &name, + const TType *constructorType, + const TSymbol *symbol) + : mName(name), mConstructorType(constructorType), mThisNode(nullptr), mSymbol(symbol) +{} + +// static +TFunctionLookup *TFunctionLookup::CreateConstructor(const TType *type) +{ + ASSERT(type != nullptr); + return new TFunctionLookup(kEmptyName, type, nullptr); +} + +// static +TFunctionLookup *TFunctionLookup::CreateFunctionCall(const ImmutableString &name, + const TSymbol *symbol) +{ + ASSERT(name != ""); + return new TFunctionLookup(name, nullptr, symbol); +} + +const ImmutableString &TFunctionLookup::name() const +{ + return mName; +} + +ImmutableString TFunctionLookup::getMangledName() const +{ + return GetMangledName(mName.data(), mArguments); +} + +ImmutableString TFunctionLookup::GetMangledName(const char *functionName, + const TIntermSequence &arguments) +{ + std::string newName(functionName); + newName += kFunctionMangledNameSeparator; + + for (TIntermNode *argument : arguments) + { + newName += argument->getAsTyped()->getType().getMangledName(); + } + return ImmutableString(newName); +} + +std::vector GetMangledNames(const char *functionName, + const TIntermSequence &arguments) +{ + std::vector target; + + std::vector indexes; + for (int i = 0; i < static_cast(arguments.size()); i++) + { + TIntermNode *argument = arguments[i]; + TBasicType argType = argument->getAsTyped()->getType().getBasicType(); + if (argType == EbtInt || argType == EbtUInt) + { + indexes.push_back(i); + } + } + + std::vector> combinations = GetImplicitConversionCombinations(indexes); + for (const std::vector &combination : combinations) + { + // combination: ordered list of indexes for arguments that should be converted to float + std::string newName(functionName); + newName += kFunctionMangledNameSeparator; + // combination[currentIndex] represents index of next argument to be converted + int currentIndex = 0; + for (int i = 0; i < (int)arguments.size(); i++) + { + TIntermNode *argument = arguments[i]; + + if (currentIndex != static_cast(combination.size()) && + combination[currentIndex] == i) + { + // Convert + TType type = argument->getAsTyped()->getType(); + type.setBasicType(EbtFloat); + newName += type.getMangledName(); + currentIndex++; + } + else + { + // Don't convert + newName += argument->getAsTyped()->getType().getMangledName(); + } + } + target.push_back(ImmutableString(newName)); + } + + return target; +} + +std::vector TFunctionLookup::getMangledNamesForImplicitConversions() const +{ + return GetMangledNames(mName.data(), mArguments); +} + +bool TFunctionLookup::isConstructor() const +{ + return mConstructorType != nullptr; +} + +const TType &TFunctionLookup::constructorType() const +{ + return *mConstructorType; +} + +void TFunctionLookup::setThisNode(TIntermTyped *thisNode) +{ + mThisNode = thisNode; +} + +TIntermTyped *TFunctionLookup::thisNode() const +{ + return mThisNode; +} + +void TFunctionLookup::addArgument(TIntermTyped *argument) +{ + mArguments.push_back(argument); +} + +TIntermSequence &TFunctionLookup::arguments() +{ + return mArguments; +} + +const TSymbol *TFunctionLookup::symbol() const +{ + return mSymbol; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/FunctionLookup.h b/gfx/angle/checkout/src/compiler/translator/FunctionLookup.h new file mode 100644 index 0000000000..6565c205eb --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/FunctionLookup.h @@ -0,0 +1,60 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// FunctionLookup.h: Used for storing function calls that have not yet been resolved during parsing. +// + +#ifndef COMPILER_TRANSLATOR_FUNCTIONLOOKUP_H_ +#define COMPILER_TRANSLATOR_FUNCTIONLOOKUP_H_ + +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/IntermNode.h" + +namespace sh +{ + +// A function look-up. +class TFunctionLookup : angle::NonCopyable +{ + public: + POOL_ALLOCATOR_NEW_DELETE + + static TFunctionLookup *CreateConstructor(const TType *type); + static TFunctionLookup *CreateFunctionCall(const ImmutableString &name, const TSymbol *symbol); + + const ImmutableString &name() const; + ImmutableString getMangledName() const; + static ImmutableString GetMangledName(const char *functionName, + const TIntermSequence &arguments); + std::vector getMangledNamesForImplicitConversions() const; + + bool isConstructor() const; + const TType &constructorType() const; + + void setThisNode(TIntermTyped *thisNode); + TIntermTyped *thisNode() const; + + void addArgument(TIntermTyped *argument); + TIntermSequence &arguments(); + + // Symbol looked up in the lexical phase using only the name of the function. + // This does not necessarily correspond to the correct overloaded function. + const TSymbol *symbol() const; + + private: + TFunctionLookup(const ImmutableString &name, + const TType *constructorType, + const TSymbol *symbol); + + const ImmutableString mName; + const TType *const mConstructorType; + TIntermTyped *mThisNode; + TIntermSequence mArguments; + const TSymbol *mSymbol; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_FUNCTIONLOOKUP_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/HashNames.cpp b/gfx/angle/checkout/src/compiler/translator/HashNames.cpp new file mode 100644 index 0000000000..fc188ff582 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/HashNames.cpp @@ -0,0 +1,99 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/HashNames.h" + +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Symbol.h" + +namespace sh +{ + +namespace +{ +constexpr const ImmutableString kHashedNamePrefix("webgl_"); + +ImmutableString HashName(const ImmutableString &name, ShHashFunction64 hashFunction) +{ + ASSERT(!name.empty()); + ASSERT(hashFunction); + khronos_uint64_t number = (*hashFunction)(name.data(), name.length()); + + // Build the hashed name in place. + static const unsigned int kHexStrMaxLength = sizeof(number) * 2; + static const size_t kHashedNameMaxLength = kHashedNamePrefix.length() + kHexStrMaxLength; + + ImmutableStringBuilder hashedName(kHashedNameMaxLength); + hashedName << kHashedNamePrefix; + + hashedName.appendHex(number); + + return hashedName; +} + +void AddToNameMapIfNotMapped(const ImmutableString &name, + const ImmutableString &hashedName, + NameMap *nameMap) +{ + if (nameMap) + { + NameMap::const_iterator it = nameMap->find(name.data()); + if (it != nameMap->end()) + { + // (How bout returning?) + return; + } + (*nameMap)[name.data()] = hashedName.data(); + } +} + +} // anonymous namespace + +ImmutableString HashName(const ImmutableString &name, + ShHashFunction64 hashFunction, + NameMap *nameMap) +{ + const ImmutableString kUnhashedNamePrefix(kUserDefinedNamePrefix); + + if (hashFunction == nullptr) + { + if (name.length() + kUnhashedNamePrefix.length() > kESSLMaxIdentifierLength) + { + // If the identifier length is already close to the limit, we can't prefix it. This is + // not a problem since there are no builtins or ANGLE's internal variables that would + // have as long names and could conflict. + return name; + } + ImmutableStringBuilder prefixedName(kUnhashedNamePrefix.length() + name.length()); + prefixedName << kUnhashedNamePrefix << name; + ImmutableString res = prefixedName; + AddToNameMapIfNotMapped(name, res, nameMap); + return res; + } + + // Has a hash function + ImmutableString hashedName = HashName(name, hashFunction); + AddToNameMapIfNotMapped(name, hashedName, nameMap); + return hashedName; +} + +ImmutableString HashName(const TSymbol *symbol, ShHashFunction64 hashFunction, NameMap *nameMap) +{ + if (symbol->symbolType() == SymbolType::Empty) + { + return kEmptyImmutableString; + } + if (symbol->symbolType() == SymbolType::AngleInternal || + symbol->symbolType() == SymbolType::BuiltIn) + { + return symbol->name(); + } + return HashName(symbol->name(), hashFunction, nameMap); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/HashNames.h b/gfx/angle/checkout/src/compiler/translator/HashNames.h new file mode 100644 index 0000000000..3742095129 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/HashNames.h @@ -0,0 +1,33 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_HASHNAMES_H_ +#define COMPILER_TRANSLATOR_HASHNAMES_H_ + +#include + +#include "GLSLANG/ShaderLang.h" +#include "compiler/translator/Common.h" + +namespace sh +{ + +typedef std::map NameMap; + +class ImmutableString; +class TSymbol; + +ImmutableString HashName(const ImmutableString &name, + ShHashFunction64 hashFunction, + NameMap *nameMap); + +// Hash user-defined name for GLSL output, with special handling for internal names. +// The nameMap parameter is optional and is used to cache hashed names if set. +ImmutableString HashName(const TSymbol *symbol, ShHashFunction64 hashFunction, NameMap *nameMap); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_HASHNAMES_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ImageFunctionHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/ImageFunctionHLSL.cpp new file mode 100644 index 0000000000..51d1a1abdd --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ImageFunctionHLSL.cpp @@ -0,0 +1,401 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output. +// + +#include "compiler/translator/ImageFunctionHLSL.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/UtilsHLSL.h" + +namespace sh +{ + +// static +ImmutableString ImageFunctionHLSL::GetImageReference( + TInfoSinkBase &out, + const ImageFunctionHLSL::ImageFunction &imageFunction) +{ + static const ImmutableString kImageIndexStr("[index]"); + if (imageFunction.readonly) + { + static const ImmutableString kReadonlyImagesStr("readonlyImages"); + ImmutableString suffix( + TextureGroupSuffix(imageFunction.image, imageFunction.imageInternalFormat)); + out << " const uint index = imageIndex - readonlyImageIndexOffset" << suffix.data() + << ";\n"; + ImmutableStringBuilder imageRefBuilder(kReadonlyImagesStr.length() + suffix.length() + + kImageIndexStr.length()); + imageRefBuilder << kReadonlyImagesStr << suffix << kImageIndexStr; + return imageRefBuilder; + } + else + { + static const ImmutableString kImagesStr("images"); + ImmutableString suffix( + RWTextureGroupSuffix(imageFunction.image, imageFunction.imageInternalFormat)); + out << " const uint index = imageIndex - imageIndexOffset" << suffix.data() << ";\n"; + ImmutableStringBuilder imageRefBuilder(kImagesStr.length() + suffix.length() + + kImageIndexStr.length()); + imageRefBuilder << kImagesStr << suffix << kImageIndexStr; + return imageRefBuilder; + } +} + +void ImageFunctionHLSL::OutputImageFunctionArgumentList( + TInfoSinkBase &out, + const ImageFunctionHLSL::ImageFunction &imageFunction) +{ + out << "uint imageIndex"; + + if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::LOAD || + imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE) + { + switch (imageFunction.image) + { + case EbtImage2D: + case EbtIImage2D: + case EbtUImage2D: + out << ", int2 p"; + break; + case EbtImage3D: + case EbtIImage3D: + case EbtUImage3D: + case EbtImageCube: + case EbtIImageCube: + case EbtUImageCube: + case EbtImage2DArray: + case EbtIImage2DArray: + case EbtUImage2DArray: + out << ", int3 p"; + break; + case EbtUImageBuffer: + case EbtIImageBuffer: + case EbtImageBuffer: + out << ", int p"; + break; + + default: + UNREACHABLE(); + } + + if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE) + { + switch (imageFunction.image) + { + case EbtImage2D: + case EbtImage3D: + case EbtImageCube: + case EbtImage2DArray: + case EbtImageBuffer: + out << ", float4 data"; + break; + case EbtIImage2D: + case EbtIImage3D: + case EbtIImageCube: + case EbtIImage2DArray: + case EbtIImageBuffer: + out << ", int4 data"; + break; + case EbtUImage2D: + case EbtUImage3D: + case EbtUImageCube: + case EbtUImage2DArray: + case EbtUImageBuffer: + out << ", uint4 data"; + break; + default: + UNREACHABLE(); + } + } + } +} + +// static +void ImageFunctionHLSL::OutputImageSizeFunctionBody( + TInfoSinkBase &out, + const ImageFunctionHLSL::ImageFunction &imageFunction, + const ImmutableString &imageReference) +{ + if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) || + IsImageCube(imageFunction.image)) + { + // "depth" stores either the number of layers in an array texture or 3D depth + out << " uint width; uint height; uint depth;\n" + << " " << imageReference << ".GetDimensions(width, height, depth);\n"; + } + else if (IsImage2D(imageFunction.image)) + { + out << " uint width; uint height;\n" + << " " << imageReference << ".GetDimensions(width, height);\n"; + } + else if (IsImageBuffer(imageFunction.image)) + { + out << " uint width;\n" + << " " << imageReference << ".GetDimensions(width);\n"; + } + else + UNREACHABLE(); + + if (strcmp(imageFunction.getReturnType(), "int3") == 0) + { + out << " return int3(width, height, depth);\n"; + } + else if (strcmp(imageFunction.getReturnType(), "int2") == 0) + { + out << " return int2(width, height);\n"; + } + else if (strcmp(imageFunction.getReturnType(), "int") == 0) + out << " return int(width);\n"; + else + UNREACHABLE(); +} + +// static +void ImageFunctionHLSL::OutputImageLoadFunctionBody( + TInfoSinkBase &out, + const ImageFunctionHLSL::ImageFunction &imageFunction, + const ImmutableString &imageReference) +{ + if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) || + IsImageCube(imageFunction.image)) + { + out << " return " << imageReference << "[uint3(p.x, p.y, p.z)];\n"; + } + else if (IsImage2D(imageFunction.image)) + { + out << " return " << imageReference << "[uint2(p.x, p.y)];\n"; + } + else if (IsImageBuffer(imageFunction.image)) + { + out << " return " << imageReference << "[uint(p.x)];\n"; + } + else + UNREACHABLE(); +} + +// static +void ImageFunctionHLSL::OutputImageStoreFunctionBody( + TInfoSinkBase &out, + const ImageFunctionHLSL::ImageFunction &imageFunction, + const ImmutableString &imageReference) +{ + if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) || + IsImage2D(imageFunction.image) || IsImageCube(imageFunction.image) || + IsImageBuffer(imageFunction.image)) + { + out << " " << imageReference << "[p] = data;\n"; + } + else + UNREACHABLE(); +} + +ImmutableString ImageFunctionHLSL::ImageFunction::name() const +{ + static const ImmutableString kGlImageName("gl_image"); + + ImmutableString suffix(nullptr); + if (readonly) + { + suffix = ImmutableString(TextureTypeSuffix(image, imageInternalFormat)); + } + else + { + suffix = ImmutableString(RWTextureTypeSuffix(image, imageInternalFormat)); + } + + ImmutableStringBuilder name(kGlImageName.length() + suffix.length() + 5u); + + name << kGlImageName << suffix; + + switch (method) + { + case Method::SIZE: + name << "Size"; + break; + case Method::LOAD: + name << "Load"; + break; + case Method::STORE: + name << "Store"; + break; + default: + UNREACHABLE(); + } + + return name; +} + +ImageFunctionHLSL::ImageFunction::DataType ImageFunctionHLSL::ImageFunction::getDataType( + TLayoutImageInternalFormat format) const +{ + switch (format) + { + case EiifRGBA32F: + case EiifRGBA16F: + case EiifR32F: + return ImageFunction::DataType::FLOAT4; + case EiifRGBA32UI: + case EiifRGBA16UI: + case EiifRGBA8UI: + case EiifR32UI: + return ImageFunction::DataType::UINT4; + case EiifRGBA32I: + case EiifRGBA16I: + case EiifRGBA8I: + case EiifR32I: + return ImageFunction::DataType::INT4; + case EiifRGBA8: + return ImageFunction::DataType::UNORM_FLOAT4; + case EiifRGBA8_SNORM: + return ImageFunction::DataType::SNORM_FLOAT4; + default: + UNREACHABLE(); + } + + return ImageFunction::DataType::NONE; +} + +const char *ImageFunctionHLSL::ImageFunction::getReturnType() const +{ + if (method == ImageFunction::Method::SIZE) + { + switch (image) + { + case EbtImage2D: + case EbtIImage2D: + case EbtUImage2D: + case EbtImageCube: + case EbtIImageCube: + case EbtUImageCube: + return "int2"; + case EbtImage3D: + case EbtIImage3D: + case EbtUImage3D: + case EbtImage2DArray: + case EbtIImage2DArray: + case EbtUImage2DArray: + return "int3"; + case EbtImageBuffer: + case EbtIImageBuffer: + case EbtUImageBuffer: + return "int"; + default: + UNREACHABLE(); + } + } + else if (method == ImageFunction::Method::LOAD) + { + switch (image) + { + case EbtImageBuffer: + case EbtImage2D: + case EbtImage3D: + case EbtImageCube: + case EbtImage2DArray: + return "float4"; + case EbtIImageBuffer: + case EbtIImage2D: + case EbtIImage3D: + case EbtIImageCube: + case EbtIImage2DArray: + return "int4"; + case EbtUImageBuffer: + case EbtUImage2D: + case EbtUImage3D: + case EbtUImageCube: + case EbtUImage2DArray: + return "uint4"; + default: + UNREACHABLE(); + } + } + else if (method == ImageFunction::Method::STORE) + { + return "void"; + } + else + { + UNREACHABLE(); + } + return ""; +} + +bool ImageFunctionHLSL::ImageFunction::operator<(const ImageFunction &rhs) const +{ + return std::tie(image, type, method, readonly) < + std::tie(rhs.image, rhs.type, rhs.method, rhs.readonly); +} + +ImmutableString ImageFunctionHLSL::useImageFunction(const ImmutableString &name, + const TBasicType &type, + TLayoutImageInternalFormat imageInternalFormat, + bool readonly) +{ + ASSERT(IsImage(type)); + ImageFunction imageFunction; + imageFunction.image = type; + imageFunction.imageInternalFormat = imageInternalFormat; + imageFunction.readonly = readonly; + imageFunction.type = imageFunction.getDataType(imageInternalFormat); + + if (name == "imageSize") + { + imageFunction.method = ImageFunction::Method::SIZE; + } + else if (name == "imageLoad") + { + imageFunction.method = ImageFunction::Method::LOAD; + } + else if (name == "imageStore") + { + imageFunction.method = ImageFunction::Method::STORE; + } + else + UNREACHABLE(); + + mUsesImage.insert(imageFunction); + return imageFunction.name(); +} + +void ImageFunctionHLSL::imageFunctionHeader(TInfoSinkBase &out) +{ + for (const ImageFunction &imageFunction : mUsesImage) + { + // Skip to generate image2D functions here, dynamically generate these + // functions when linking, or after dispatch or draw. + if (IsImage2D(imageFunction.image)) + { + mUsedImage2DFunctionNames.insert(imageFunction.name().data()); + continue; + } + // Function header + out << imageFunction.getReturnType() << " " << imageFunction.name() << "("; + + OutputImageFunctionArgumentList(out, imageFunction); + + out << ")\n" + "{\n"; + + ImmutableString imageReference = GetImageReference(out, imageFunction); + if (imageFunction.method == ImageFunction::Method::SIZE) + { + OutputImageSizeFunctionBody(out, imageFunction, imageReference); + } + else if (imageFunction.method == ImageFunction::Method::LOAD) + { + OutputImageLoadFunctionBody(out, imageFunction, imageReference); + } + else + { + OutputImageStoreFunctionBody(out, imageFunction, imageReference); + } + + out << "}\n" + "\n"; + } +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ImageFunctionHLSL.h b/gfx/angle/checkout/src/compiler/translator/ImageFunctionHLSL.h new file mode 100644 index 0000000000..12a4a9de27 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ImageFunctionHLSL.h @@ -0,0 +1,96 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output. +// + +#ifndef COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_ +#define COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_ + +#include + +#include "GLSLANG/ShaderLang.h" +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/Common.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/Types.h" + +namespace sh +{ + +class ImageFunctionHLSL final : angle::NonCopyable +{ + public: + // Returns the name of the image function implementation to caller. + // The name that's passed in is the name of the GLSL image function that it should implement. + ImmutableString useImageFunction(const ImmutableString &name, + const TBasicType &type, + TLayoutImageInternalFormat imageInternalFormat, + bool readonly); + + void imageFunctionHeader(TInfoSinkBase &out); + const std::set &getUsedImage2DFunctionNames() const + { + return mUsedImage2DFunctionNames; + } + + private: + struct ImageFunction + { + // See ESSL 3.10.4 section 8.12 for reference about what the different methods below do. + enum class Method + { + SIZE, + LOAD, + STORE + }; + + enum class DataType + { + NONE, + FLOAT4, + UINT4, + INT4, + UNORM_FLOAT4, + SNORM_FLOAT4 + }; + + ImmutableString name() const; + + bool operator<(const ImageFunction &rhs) const; + + DataType getDataType(TLayoutImageInternalFormat format) const; + + const char *getReturnType() const; + + TBasicType image; + TLayoutImageInternalFormat imageInternalFormat; + bool readonly; + Method method; + DataType type; + }; + + static ImmutableString GetImageReference(TInfoSinkBase &out, + const ImageFunctionHLSL::ImageFunction &imageFunction); + static void OutputImageFunctionArgumentList( + TInfoSinkBase &out, + const ImageFunctionHLSL::ImageFunction &imageFunction); + static void OutputImageSizeFunctionBody(TInfoSinkBase &out, + const ImageFunctionHLSL::ImageFunction &imageFunction, + const ImmutableString &imageReference); + static void OutputImageLoadFunctionBody(TInfoSinkBase &out, + const ImageFunctionHLSL::ImageFunction &imageFunction, + const ImmutableString &imageReference); + static void OutputImageStoreFunctionBody(TInfoSinkBase &out, + const ImageFunctionHLSL::ImageFunction &imageFunction, + const ImmutableString &imageReference); + using ImageFunctionSet = std::set; + ImageFunctionSet mUsesImage; + std::set mUsedImage2DFunctionNames; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ImmutableString.h b/gfx/angle/checkout/src/compiler/translator/ImmutableString.h new file mode 100644 index 0000000000..f172708d7d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ImmutableString.h @@ -0,0 +1,143 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ImmutableString.h: Wrapper for static or pool allocated char arrays, that are guaranteed to be +// valid and unchanged for the duration of the compilation. +// + +#ifndef COMPILER_TRANSLATOR_IMMUTABLESTRING_H_ +#define COMPILER_TRANSLATOR_IMMUTABLESTRING_H_ + +#include + +#include "common/string_utils.h" +#include "compiler/translator/Common.h" + +namespace sh +{ + +namespace +{ +constexpr size_t constStrlen(const char *str) +{ + if (str == nullptr) + { + return 0u; + } + size_t len = 0u; + while (*(str + len) != '\0') + { + ++len; + } + return len; +} +} // namespace + +class ImmutableString +{ + public: + // The data pointer passed in must be one of: + // 1. nullptr (only valid with length 0). + // 2. a null-terminated static char array like a string literal. + // 3. a null-terminated pool allocated char array. This can't be c_str() of a local TString, + // since when a TString goes out of scope it clears its first character. + explicit constexpr ImmutableString(const char *data) : mData(data), mLength(constStrlen(data)) + {} + + constexpr ImmutableString(const char *data, size_t length) : mData(data), mLength(length) {} + + ImmutableString(const std::string &str) + : mData(AllocatePoolCharArray(str.c_str(), str.size())), mLength(str.size()) + {} + + constexpr ImmutableString(const ImmutableString &) = default; + + ImmutableString &operator=(const ImmutableString &) = default; + + constexpr const char *data() const { return mData ? mData : ""; } + constexpr size_t length() const { return mLength; } + + char operator[](size_t index) const { return data()[index]; } + + constexpr bool empty() const { return mLength == 0; } + bool beginsWith(const char *prefix) const { return angle::BeginsWith(data(), prefix); } + constexpr bool beginsWith(const ImmutableString &prefix) const + { + return mLength >= prefix.length() && memcmp(data(), prefix.data(), prefix.length()) == 0; + } + bool contains(const char *substr) const { return strstr(data(), substr) != nullptr; } + + constexpr bool operator==(const ImmutableString &b) const + { + if (mLength != b.mLength) + { + return false; + } + return memcmp(data(), b.data(), mLength) == 0; + } + constexpr bool operator!=(const ImmutableString &b) const { return !(*this == b); } + constexpr bool operator==(const char *b) const + { + if (b == nullptr) + { + return empty(); + } + return strcmp(data(), b) == 0; + } + constexpr bool operator!=(const char *b) const { return !(*this == b); } + bool operator==(const std::string &b) const + { + return mLength == b.length() && memcmp(data(), b.c_str(), mLength) == 0; + } + bool operator!=(const std::string &b) const { return !(*this == b); } + + constexpr bool operator<(const ImmutableString &b) const + { + if (mLength < b.mLength) + { + return true; + } + if (mLength > b.mLength) + { + return false; + } + return (memcmp(data(), b.data(), mLength) < 0); + } + + template + struct FowlerNollVoHash + { + static const size_t kFnvOffsetBasis; + static const size_t kFnvPrime; + + constexpr size_t operator()(const ImmutableString &a) const + { + const char *data = a.data(); + size_t hash = kFnvOffsetBasis; + while ((*data) != '\0') + { + hash = hash ^ (*data); + hash = hash * kFnvPrime; + ++data; + } + return hash; + } + }; + + // Perfect hash functions + uint32_t mangledNameHash() const; + uint32_t unmangledNameHash() const; + + private: + const char *mData; + size_t mLength; +}; + +constexpr ImmutableString kEmptyImmutableString(""); +} // namespace sh + +std::ostream &operator<<(std::ostream &os, const sh::ImmutableString &str); + +#endif // COMPILER_TRANSLATOR_IMMUTABLESTRING_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ImmutableStringBuilder.cpp b/gfx/angle/checkout/src/compiler/translator/ImmutableStringBuilder.cpp new file mode 100644 index 0000000000..3c7c01041f --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ImmutableStringBuilder.cpp @@ -0,0 +1,63 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ImmutableStringBuilder.cpp: Stringstream-like utility for building pool allocated strings where +// the maximum length is known in advance. +// + +#include "compiler/translator/ImmutableStringBuilder.h" + +#include + +namespace sh +{ + +ImmutableStringBuilder &ImmutableStringBuilder::operator<<(const ImmutableString &str) +{ + ASSERT(mData != nullptr); + ASSERT(mPos + str.length() <= mMaxLength); + memcpy(mData + mPos, str.data(), str.length()); + mPos += str.length(); + return *this; +} + +ImmutableStringBuilder &ImmutableStringBuilder::operator<<(const char *str) +{ + ASSERT(mData != nullptr); + size_t len = strlen(str); + ASSERT(mPos + len <= mMaxLength); + memcpy(mData + mPos, str, len); + mPos += len; + return *this; +} + +ImmutableStringBuilder &ImmutableStringBuilder::operator<<(const char &c) +{ + ASSERT(mData != nullptr); + ASSERT(mPos + 1 <= mMaxLength); + mData[mPos++] = c; + return *this; +} + +void ImmutableStringBuilder::appendDecimal(const uint32_t &u) +{ + int numChars = snprintf(mData + mPos, mMaxLength - mPos, "%d", u); + ASSERT(numChars >= 0); + ASSERT(mPos + numChars <= mMaxLength); + mPos += numChars; +} + +ImmutableStringBuilder::operator ImmutableString() +{ + mData[mPos] = '\0'; + ImmutableString str(static_cast(mData), mPos); +#if defined(ANGLE_ENABLE_ASSERTS) + // Make sure that nothing is added to the string after it is finalized. + mData = nullptr; +#endif + return str; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ImmutableStringBuilder.h b/gfx/angle/checkout/src/compiler/translator/ImmutableStringBuilder.h new file mode 100644 index 0000000000..2af963821c --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ImmutableStringBuilder.h @@ -0,0 +1,80 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ImmutableStringBuilder.h: Stringstream-like utility for building pool allocated strings where the +// maximum length is known in advance. +// + +#ifndef COMPILER_TRANSLATOR_IMMUTABLESTRINGBUILDER_H_ +#define COMPILER_TRANSLATOR_IMMUTABLESTRINGBUILDER_H_ + +#include "compiler/translator/ImmutableString.h" + +namespace sh +{ + +class ImmutableStringBuilder +{ + public: + ImmutableStringBuilder(size_t maxLength) + : mPos(0u), mMaxLength(maxLength), mData(AllocateEmptyPoolCharArray(maxLength)) + {} + + ImmutableStringBuilder &operator<<(const ImmutableString &str); + + ImmutableStringBuilder &operator<<(const char *str); + + ImmutableStringBuilder &operator<<(const char &c); + + // This invalidates the ImmutableStringBuilder, so it should only be called once. + operator ImmutableString(); + + void appendDecimal(const uint32_t &i); + + template + void appendHex(T number) + { + ASSERT(mData != nullptr); + ASSERT(mPos + sizeof(T) * 2u <= mMaxLength); + int index = static_cast(sizeof(T)) * 2 - 1; + // Loop through leading zeroes. + while (((number >> (index * 4)) & 0xfu) == 0 && index > 0) + { + --index; + } + // Write the rest of the hex digits. + while (index >= 0) + { + char digit = static_cast((number >> (index * 4)) & 0xfu); + char digitChar = (digit < 10) ? (digit + '0') : (digit + ('a' - 10)); + mData[mPos++] = digitChar; + --index; + } + } + + template + static constexpr size_t GetHexCharCount() + { + return sizeof(T) * 2; + } + + private: + inline static char *AllocateEmptyPoolCharArray(size_t strLength) + { + size_t requiredSize = strLength + 1u; + return static_cast(GetGlobalPoolAllocator()->allocate(requiredSize)); + } + + size_t mPos; + size_t mMaxLength; + char *mData; +}; + +// GLSL ES 3.00.6 section 3.9: the maximum length of an identifier is 1024 characters. +constexpr unsigned int kESSLMaxIdentifierLength = 1024u; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_IMMUTABLESTRINGBUILDER_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ImmutableString_ESSL_autogen.cpp b/gfx/angle/checkout/src/compiler/translator/ImmutableString_ESSL_autogen.cpp new file mode 100644 index 0000000000..6199adb2b4 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ImmutableString_ESSL_autogen.cpp @@ -0,0 +1,345 @@ +// GENERATED FILE - DO NOT EDIT. +// Generated by gen_builtin_symbols.py using data from builtin_variables.json and +// builtin_function_declarations.txt. +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ImmutableString_ESSL_autogen.cpp: Wrapper for static or pool allocated char arrays, that are +// guaranteed to be valid and unchanged for the duration of the compilation. Implements +// mangledNameHash using perfect hash function from gen_builtin_symbols.py + +#include "compiler/translator/ImmutableString.h" + +std::ostream &operator<<(std::ostream &os, const sh::ImmutableString &str) +{ + return os.write(str.data(), str.length()); +} + +#if defined(_MSC_VER) +# pragma warning(disable : 4309) // truncation of constant value +#endif + +namespace +{ + +constexpr int mangledkT1[] = {3297, 2629, 2651, 2337, 2303, 3220, 3385, 1210, 2130, 1919, + 3300, 2529, 2310, 3215, 1751, 2155, 96, 2644, 3105, 1639, + 1010, 851, 1501, 558, 2641, 328, 1973, 296, 1999, 2273, + 441, 2860, 911, 1153, 2602, 1727, 2732, 521, 1672, 1330}; +constexpr int mangledkT2[] = {1661, 42, 548, 942, 2329, 3201, 841, 3274, 1976, 3379, + 1752, 1024, 961, 2388, 3033, 1547, 591, 2585, 1383, 473, + 319, 3081, 1789, 734, 478, 219, 1353, 381, 1660, 408, + 1440, 2281, 2126, 1243, 1080, 2835, 3286, 168, 458, 1343}; +constexpr int mangledkG[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1017, 0, 0, 2710, 0, 0, 0, + 0, 0, 2927, 578, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2927, 632, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1534, 0, 0, 0, 1494, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3388, 0, 0, 0, 0, 575, 0, 1229, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2918, 0, 0, 0, 0, 0, 0, 479, 0, 0, 0, + 1595, 0, 0, 0, 3263, 0, 3229, 372, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3123, 0, 0, 900, 0, 0, + 0, 459, 0, 0, 0, 0, 0, 0, 2582, 1333, 0, 172, 126, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2180, 0, 841, 0, 0, 0, 2145, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 954, 0, 811, 0, 0, 0, 677, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1862, 2279, 0, 2634, 0, 0, 2477, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2784, 0, 0, 0, 3384, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2761, 0, 0, 0, 1572, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 905, + 0, 0, 0, 3350, 0, 0, 0, 0, 1371, 2614, 0, 0, 3227, 0, 0, 0, + 1772, 0, 601, 0, 944, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1928, + 0, 0, 0, 0, 0, 0, 0, 0, 2236, 0, 0, 0, 3179, 0, 0, 619, + 0, 0, 3251, 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 1825, + 0, 0, 0, 0, 3177, 2489, 0, 0, 70, 0, 519, 0, 505, 1676, 0, 0, + 0, 0, 0, 1871, 0, 0, 2289, 0, 0, 0, 1192, 0, 2362, 776, 2964, 0, + 0, 0, 2478, 0, 1303, 0, 96, 0, 0, 3408, 0, 0, 0, 2894, 250, 0, + 0, 0, 0, 0, 0, 0, 0, 2894, 0, 3389, 930, 2489, 0, 2755, 0, 1807, + 701, 2938, 0, 0, 0, 0, 609, 0, 0, 0, 1985, 343, 0, 2608, 0, 368, + 1367, 1387, 0, 0, 3160, 0, 0, 0, 2036, 0, 0, 2231, 0, 0, 2248, 2652, + 0, 306, 0, 0, 3308, 0, 0, 0, 525, 0, 0, 1300, 0, 0, 1432, 2594, + 2612, 53, 1093, 0, 1779, 3020, 3237, 458, 47, 0, 0, 526, 1378, 0, 0, 0, + 442, 1063, 3293, 0, 0, 0, 0, 0, 0, 832, 2958, 1452, 0, 0, 349, 0, + 1871, 0, 0, 2548, 1826, 441, 2846, 0, 2601, 1910, 1415, 0, 0, 0, 420, 0, + 3073, 620, 0, 0, 1333, 1133, 0, 0, 1402, 0, 0, 0, 0, 292, 0, 0, + 0, 0, 0, 1598, 364, 0, 1161, 0, 0, 0, 0, 218, 0, 2572, 226, 0, + 527, 270, 2558, 2814, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1796, 0, + 0, 173, 610, 2959, 0, 0, 0, 0, 0, 301, 0, 0, 0, 0, 0, 0, + 0, 0, 1954, 0, 0, 0, 0, 414, 0, 0, 0, 0, 0, 0, 0, 265, + 0, 0, 0, 0, 230, 0, 502, 0, 1243, 0, 0, 2474, 0, 0, 0, 0, + 23, 0, 668, 0, 3125, 0, 3209, 0, 0, 928, 402, 0, 39, 117, 443, 852, + 0, 767, 0, 0, 0, 0, 3067, 0, 0, 0, 1532, 0, 0, 0, 3202, 0, + 0, 0, 0, 0, 2801, 0, 2221, 0, 0, 3, 0, 0, 0, 0, 0, 3241, + 1620, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 665, 0, 0, 1803, 0, + 2475, 0, 0, 0, 499, 0, 1386, 3147, 0, 0, 1168, 0, 0, 0, 1824, 0, + 0, 78, 935, 136, 0, 0, 882, 0, 0, 421, 257, 381, 0, 0, 643, 0, + 0, 284, 0, 2581, 0, 0, 0, 0, 0, 0, 963, 0, 0, 0, 3217, 681, + 479, 0, 529, 0, 0, 0, 0, 0, 2901, 0, 1026, 0, 1190, 0, 0, 0, + 0, 0, 0, 3265, 0, 0, 2287, 0, 0, 0, 0, 594, 0, 0, 0, 0, + 0, 114, 0, 608, 0, 2750, 0, 3179, 0, 161, 0, 0, 0, 556, 3087, 2490, + 1878, 0, 0, 0, 0, 2550, 0, 0, 0, 0, 0, 1638, 0, 746, 0, 0, + 338, 0, 1430, 0, 0, 1407, 0, 1134, 0, 0, 0, 0, 0, 0, 0, 0, + 113, 227, 0, 433, 927, 0, 0, 0, 1526, 1343, 38, 0, 2017, 1986, 3079, 0, + 3409, 0, 0, 0, 0, 2612, 1300, 138, 0, 0, 2020, 486, 0, 0, 1627, 0, + 0, 209, 0, 2406, 563, 97, 0, 578, 0, 0, 1064, 0, 1394, 61, 1962, 1613, + 534, 134, 994, 0, 0, 3180, 0, 0, 0, 0, 0, 0, 0, 1648, 0, 0, + 0, 0, 0, 0, 0, 2627, 0, 0, 955, 3301, 0, 414, 395, 0, 467, 681, + 0, 0, 0, 3070, 747, 1612, 0, 2987, 429, 0, 0, 438, 0, 627, 2229, 0, + 0, 0, 0, 0, 0, 2486, 35, 0, 307, 450, 0, 0, 0, 0, 0, 3382, + 2994, 3119, 0, 992, 1257, 781, 1249, 0, 915, 981, 837, 3177, 0, 0, 0, 0, + 748, 0, 0, 66, 3212, 0, 0, 3142, 0, 311, 744, 767, 0, 0, 0, 0, + 0, 0, 1164, 0, 1138, 757, 67, 1332, 724, 2680, 0, 0, 0, 275, 1321, 0, + 0, 750, 1072, 0, 660, 1228, 546, 0, 543, 0, 0, 0, 0, 1429, 356, 0, + 1200, 0, 0, 914, 1270, 0, 149, 474, 936, 336, 2834, 0, 0, 0, 0, 0, + 93, 0, 0, 0, 588, 0, 2776, 0, 1485, 0, 3193, 1133, 0, 0, 1386, 0, + 0, 0, 435, 87, 0, 0, 679, 1588, 321, 0, 0, 0, 2574, 0, 0, 0, + 0, 1079, 156, 0, 0, 582, 0, 793, 3388, 2758, 2508, 2915, 0, 0, 1326, 925, + 2685, 0, 0, 3305, 0, 469, 0, 1874, 120, 0, 0, 0, 0, 567, 549, 0, + 1237, 0, 0, 0, 2254, 0, 0, 1747, 348, 0, 0, 0, 2774, 0, 0, 0, + 0, 572, 0, 0, 1785, 251, 0, 767, 0, 3365, 0, 586, 1354, 0, 1039, 0, + 0, 625, 0, 0, 34, 2733, 0, 888, 522, 0, 518, 0, 2166, 0, 1502, 2652, + 0, 1277, 2808, 0, 1369, 1428, 0, 0, 0, 711, 0, 159, 1118, 0, 0, 0, + 248, 996, 2274, 0, 537, 2856, 0, 0, 0, 0, 0, 0, 2313, 769, 0, 0, + 0, 1145, 0, 0, 0, 0, 0, 0, 0, 0, 1582, 1138, 0, 0, 0, 967, + 1194, 0, 273, 1590, 459, 0, 0, 1620, 0, 0, 0, 1331, 0, 661, 0, 0, + 339, 0, 1582, 807, 0, 0, 1082, 0, 0, 0, 0, 0, 0, 0, 293, 0, + 1065, 1277, 0, 0, 949, 916, 36, 867, 0, 1335, 1355, 0, 997, 1273, 0, 0, + 0, 1508, 0, 0, 1632, 896, 0, 3338, 0, 1280, 1145, 278, 0, 1361, 2064, 1030, + 0, 435, 0, 0, 384, 2984, 0, 0, 0, 0, 909, 0, 0, 0, 149, 539, + 2604, 0, 463, 1583, 554, 1663, 0, 446, 0, 0, 0, 1075, 0, 2395, 0, 82, + 258, 0, 580, 0, 0, 549, 1508, 0, 1160, 0, 108, 195, 0, 136, 0, 704, + 0, 0, 3108, 0, 0, 0, 1625, 0, 359, 986, 3338, 1596, 1316, 47, 718, 479, + 560, 0, 33, 0, 879, 0, 0, 3021, 0, 616, 342, 0, 882, 776, 3251, 0, + 32, 513, 273, 232, 745, 1184, 0, 3288, 364, 0, 0, 3102, 0, 3193, 481, 0, + 842, 0, 3113, 647, 0, 0, 0, 2239, 0, 720, 0, 1193, 0, 980, 0, 0, + 0, 0, 661, 1493, 3369, 3348, 31, 1970, 0, 1251, 1513, 0, 0, 2199, 673, 562, + 33, 186, 1457, 0, 788, 0, 1036, 0, 0, 1998, 0, 0, 0, 1906, 0, 1148, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1047, 980, 0, 1363, 0, 0, 2893, + 0, 0, 0, 1442, 0, 0, 2735, 1044, 0, 0, 1197, 0, 434, 0, 420, 1008, + 3104, 0, 2979, 823, 0, 0, 0, 98, 2814, 1534, 2319, 996, 2897, 0, 0, 2194, + 961, 0, 0, 1551, 0, 0, 0, 0, 0, 0, 0, 0, 565, 2808, 0, 1868, + 667, 0, 0, 0, 0, 1017, 139, 0, 0, 0, 154, 0, 3155, 0, 769, 2996, + 1247, 1113, 0, 0, 3203, 0, 1183, 0, 1469, 0, 1193, 375, 88, 0, 0, 0, + 0, 0, 0, 1037, 0, 3370, 180, 1947, 0, 0, 0, 2759, 2065, 0, 0, 0, + 3345, 564, 0, 2730, 0, 2979, 0, 5, 0, 2986, 155, 0, 393, 1884, 1845, 0, + 0, 2673, 0, 453, 945, 123, 1252, 0, 550, 1599, 231, 150, 1215, 0, 233, 3394, + 3370, 455, 0, 1620, 0, 0, 2860, 0, 1569, 0, 2095, 0, 1392, 0, 0, 373, + 0, 388, 0, 0, 2856, 2919, 2416, 0, 0, 0, 0, 0, 0, 933, 2108, 0, + 1536, 666, 675, 495, 0, 1705, 0, 0, 656, 0, 0, 63, 1484, 0, 0, 1033, + 0, 914, 3397, 0, 2927, 193, 597, 2666, 0, 1035, 0, 0, 0, 0, 1726, 1719, + 3405, 0, 0, 1644, 0, 0, 555, 0, 58, 1168, 0, 430, 236, 997, 935, 0, + 0, 659, 402, 3243, 0, 1010, 0, 2241, 0, 1140, 2556, 0, 1002, 748, 539, 213, + 0, 1602, 263, 0, 0, 0, 1286, 669, 333, 2327, 0, 0, 911, 0, 157, 716, + 0, 0, 0, 0, 180, 0, 0, 0, 359, 0, 3042, 0, 0, 808, 982, 732, + 1539, 0, 324, 0, 0, 0, 0, 3325, 698, 0, 1799, 0, 2942, 2667, 0, 519, + 2898, 1068, 0, 0, 0, 1460, 3022, 0, 0, 0, 2842, 927, 3152, 0, 0, 1521, + 1362, 0, 0, 588, 0, 34, 2910, 0, 0, 0, 2621, 0, 2712, 315, 2628, 0, + 286, 718, 0, 267, 775, 76, 0, 0, 0, 0, 0, 0, 0, 3229, 0, 1924, + 0, 0, 0, 0, 1454, 1384, 2952, 0, 0, 154, 0, 0, 0, 271, 0, 0, + 289, 179, 2419, 2348, 0, 766, 0, 1462, 2514, 930, 768, 0, 0, 0, 0, 0, + 0, 0, 331, 1380, 0, 1161, 0, 0, 3313, 0, 3367, 0, 0, 0, 0, 0, + 1147, 0, 1866, 0, 0, 1649, 0, 0, 0, 858, 964, 0, 1975, 0, 0, 0, + 0, 1031, 0, 0, 2901, 3008, 0, 0, 2440, 1174, 910, 1006, 3125, 0, 2724, 825, + 0, 2250, 1465, 0, 0, 0, 1104, 476, 1673, 0, 1429, 130, 1183, 1909, 183, 650, + 487, 0, 0, 676, 0, 1528, 0, 0, 426, 2746, 731, 0, 0, 1225, 0, 0, + 662, 2458, 0, 2203, 0, 0, 998, 0, 3016, 223, 0, 2759, 1006, 0, 0, 3356, + 1197, 0, 0, 1165, 940, 1424, 365, 1120, 0, 0, 0, 0, 838, 0, 2166, 0, + 1592, 2396, 859, 1542, 0, 0, 0, 406, 0, 1468, 1315, 3385, 186, 672, 3019, 853, + 301, 2253, 1429, 1225, 845, 1067, 128, 0, 0, 1144, 0, 207, 0, 400, 0, 1051, + 0, 492, 0, 0, 0, 0, 283, 0, 161, 0, 2649, 1013, 0, 3075, 0, 62, + 2968, 1449, 0, 641, 2728, 0, 1912, 1170, 1553, 1466, 120, 0, 0, 812, 0, 188, + 0, 0, 1278, 3176, 0, 0, 0, 0, 2742, 0, 0, 1772, 0, 874, 680, 0, + 1378, 2733, 53, 0, 0, 329, 2, 1014, 2786, 719, 1868, 0, 2296, 0, 357, 0, + 0, 0, 0, 2371, 1203, 1109, 1302, 3047, 2319, 0, 2834, 1711, 0, 849, 1658, 131, + 0, 1191, 268, 1519, 0, 1080, 0, 0, 488, 0, 46, 0, 658, 0, 0, 1838, + 0, 0, 0, 0, 1741, 2096, 1701, 0, 0, 691, 3262, 950, 0, 0, 0, 704, + 734, 2177, 3260, 0, 0, 897, 291, 1318, 866, 3105, 3161, 1205, 0, 0, 0, 0, + 0, 0, 0, 835, 0, 0, 0, 0, 0, 0, 1283, 0, 0, 772, 0, 1482, + 1609, 1279, 1121, 870, 0, 3184, 818, 1521, 0, 0, 297, 0, 0, 1360, 0, 0, + 249, 0, 2112, 72, 0, 1110, 2278, 619, 0, 1014, 809, 397, 0, 0, 1406, 0, + 905, 0, 690, 751, 0, 0, 0, 19, 3355, 0, 0, 0, 0, 1345, 114, 945, + 0, 122, 173, 0, 133, 0, 971, 0, 453, 1183, 0, 0, 2729, 632, 678, 1572, + 0, 1304, 1433, 926, 0, 0, 302, 941, 0, 0, 0, 0, 0, 1222, 0, 0, + 0, 0, 1771, 0, 884, 872, 0, 0, 1234, 1928, 3190, 0, 0, 0, 0, 0, + 238, 615, 522, 287, 654, 798, 0, 1264, 0, 0, 0, 0, 466, 395, 1175, 1406, + 633, 1146, 3235, 3347, 62, 237, 0, 0, 0, 0, 0, 10, 1461, 0, 0, 1914, + 447, 0, 3148, 1253, 1970, 0, 1404, 744, 3377, 1362, 3085, 0, 3083, 1529, 0, 0, + 1441, 0, 1476, 0, 955, 156, 0, 0, 1753, 1212, 0, 45, 1193, 1605, 0, 0, + 0, 0, 209, 180, 447, 1584, 25, 1520, 2177, 0, 74, 0, 3334, 2718, 0, 728, + 0, 1000, 0, 1366, 978, 0, 0, 1488, 3222, 122, 388, 1642, 946, 0, 0, 0, + 0, 0, 741, 0, 0, 0, 0, 1875, 1116, 880, 0, 343, 1376, 0, 1700, 0, + 2350, 605, 132, 0, 0, 1430, 0, 0, 528, 564, 0, 1571, 1265, 0, 0, 625, + 3052, 1040, 1470, 266, 603, 3325, 0, 679, 0, 1902, 265, 2718, 1591, 671, 3356, 0, + 0, 321, 0, 3219, 990, 0, 408, 0, 716, 0, 0, 0, 823, 99, 754, 780, + 3334, 365, 0, 1681, 2332, 0, 3209, 0, 0, 774, 589, 0, 0, 841, 138, 679, + 320, 0, 0, 2355, 491, 3001, 0, 3280, 0, 0, 1743, 0, 0, 0, 2191, 0, + 1177, 0, 0, 0, 0, 0, 1143, 0, 0, 0, 580, 0, 0, 0, 0, 0, + 0, 620, 0, 1207, 0, 1603, 494, 433, 0, 847, 44, 2265, 2101, 2457, 0, 0, + 0, 389, 1429, 2257, 3104, 455, 0, 0, 0, 0, 0, 0, 1468, 966, 978, 1878, + 1217, 3122, 2407, 0, 3022, 0, 0, 910, 466, 0, 2931, 2770, 173, 209, 1004, 0, + 160, 0, 1405, 0, 965, 0, 0, 1455, 1314, 2643, 0, 713, 1544, 0, 0, 0, + 544, 0, 476, 847, 1029, 983, 231, 285, 2181, 0, 0, 513, 739, 336, 0, 1206, + 0, 3020, 492, 0, 0, 596, 0, 0, 1282, 0, 121, 0, 0, 667, 873, 0, + 0, 1015, 196, 0, 1390, 469, 563, 1091, 349, 0, 2300, 0, 0, 104, 0, 23, + 1619, 0, 1649, 0, 0, 499, 558, 0, 0, 0, 0, 0, 1089, 0, 2932, 473, + 700, 2599, 0, 3, 3365, 557, 1347, 1138, 380, 2427, 0, 1084, 0, 0, 0, 701, + 0, 0, 2747, 0, 0, 1481, 0, 2017, 1487, 0, 0, 0, 0, 0, 2867, 609, + 0, 1453, 1383, 0, 0, 489, 0, 663, 3399, 0, 0, 2629, 1525, 2947, 0, 1472, + 0, 0, 744, 14, 0, 2982, 639, 0, 741, 389, 0, 0, 795, 0, 527, 0, + 0, 0, 404, 768, 2738, 1877, 0, 900, 82, 0, 0, 967, 0, 573, 103, 0, + 0, 498, 2837, 0, 0, 0, 340, 1070, 0, 0, 1127, 0, 1028, 1166, 0, 0, + 0, 0, 1111, 0, 1238, 2206, 222, 0, 632, 0, 3368, 923, 433, 0, 705, 57, + 536, 1427, 0, 0, 1232, 101, 0, 0, 255, 1427, 828, 0, 160, 613, 2986, 0, + 1010, 0, 0, 0, 2915, 2185, 1519, 2988, 2817, 3387, 3090, 1538, 43, 0, 781, 0, + 0, 0, 0, 0, 804, 2815, 3088, 3021, 1095, 0, 0, 0, 0, 1285, 0, 0, + 244, 0, 713, 0, 899, 0, 0, 0, 142, 16, 0, 1655, 119, 22, 2957, 0, + 785, 2620, 666, 0, 263, 0, 2359, 1150, 0, 243, 0, 946, 988, 1510, 637, 1271, + 1038, 0, 2893, 0, 0, 938, 0, 0, 175, 0, 0, 0, 0, 0, 0, 277, + 0, 2910, 0, 0, 0, 0, 1516, 2054, 0, 3270, 0, 3088, 410, 0, 3203, 1216, + 0, 0, 0, 1076, 590, 141, 282, 0, 0, 193, 2844, 225, 2981, 0, 0, 555, + 0, 1054, 275, 0, 1142, 0, 504, 1045, 550, 0, 799, 188, 2264, 1137, 0, 298, + 2843, 3120, 3365, 0, 881, 1430, 2165, 2552, 0, 0, 2305, 0, 1944, 0, 2030, 606, + 3296, 3028, 274, 936, 3036, 1285, 642, 0, 116, 834, 0, 1485, 1322, 0, 1667, 0, + 697, 2746, 893, 1561, 1264, 102, 0, 0, 362, 1242, 142, 0, 225, 957, 1153, 117, + 0, 515, 0, 0, 1393, 365, 266, 834, 0, 1317, 0, 0, 2334, 0, 0, 0, + 0, 0, 0, 165, 1293, 526, 17, 0, 71, 0, 2986, 0, 808, 1195, 6, 1124, + 0, 0, 0, 0, 0, 274, 0, 0, 0, 0, 0, 0, 1511, 380, 0, 250, + 0, 2324, 771, 0, 195, 0, 393, 0, 2126, 258, 0, 21, 354, 0, 0, 198, + 0, 0, 514, 0, 0, 0, 0, 0, 0, 0, 0, 564, 1284, 0, 0, 735, + 2316, 1196, 831, 1279, 2599, 504, 0, 1174, 3177, 0, 1224, 1308, 574, 119, 1426, 1969, + 0, 197, 1029, 0, 860, 928, 0, 1114, 767, 2884, 0, 0, 492, 1549, 2358, 0, + 2878, 930, 581, 1368, 0, 1223, 0, 96, 0, 3313, 868, 0, 2962, 2697, 2823, 1086, + 3239, 448, 0, 0, 0, 1236, 0, 0, 1310, 886, 531, 0, 9, 0, 0, 293, + 0, 0, 2627, 3078, 3408, 1297, 883, 115, 0, 2906, 3009, 0, 1405, 1046, 1101, 0, + 1556, 1118, 1103, 0, 0, 2284, 434, 922, 0, 0, 941, 3194, 1069, 2741, 307, 668, + 2373, 3061, 945, 643, 0, 1503, 0, 561, 0, 618, 0, 1172, 3050, 3218, 0, 752, + 2992, 0, 0, 0, 0, 839, 1252, 348, 144, 0, 29, 1190, 441, 3202, 705, 2600, + 1516, 73, 472, 814, 3042, 360, 0, 3256, 0, 0, 0, 0, 0, 0, 1748, 1007, + 3384, 0, 0, 1412, 473, 0, 0, 1325, 0, 3170, 541, 0, 1066, 1126, 1215, 0, + 0, 624, 0, 1219, 0, 949, 0, 730, 1376, 2256, 733, 0, 1577, 0, 576, 1594, + 181, 0, 461, 3238, 1436, 0, 900, 2191, 0, 894, 698, 0, 777, 59, 845, 2941, + 0, 0, 1408, 0, 224, 0, 0, 0, 2322, 1129, 1511, 0, 870, 239, 3365, 0, + 918, 1107, 0, 2483, 0, 0, 0, 0, 0, 0, 235, 1152, 1300, 304, 0, 396, + 0, 0, 130, 0, 0, 0, 0, 0, 212, 0, 0, 0, 0, 1554, 0, 0, + 394, 3180, 1050, 0, 1363, 861, 0, 1069, 1015, 0, 3146, 0, 1352, 0, 876, 1221, + 0, 325, 0, 0, 53, 107, 0, 2951, 0, 0, 310, 424, 49, 0, 0, 815, + 0, 749, 0, 3227, 1192, 2310, 1281, 3210, 0, 252, 380, 0, 514, 0, 1404, 908, + 0, 0, 300, 920, 0, 0, 2257, 1566, 0, 396, 558, 0, 0, 936, 0, 663, + 2840, 0, 0, 1325, 2928, 1798, 0, 2180, 1327, 568, 1585, 662, 0, 0, 0, 1910, + 976, 0, 58, 0, 0, 3353, 0, 0, 0, 2580, 2798, 3201, 1146, 1352, 0, 858, + 104, 0, 1668, 0, 3186, 781, 987, 0, 571, 193, 13, 415, 657, 52, 0, 0, + 333, 729, 207, 696, 0, 3378, 1198, 2332, 0, 1327, 1564, 1009, 0, 0, 0, 0, + 153, 2698, 89, 1114, 3368, 2898, 3117, 2837, 0, 2690, 0, 2278, 2025, 921, 3232, 0, + 0, 1036, 2620, 0, 0, 0, 0, 300, 0, 1075, 1668, 0, 0, 0, 3159, 0, + 3032, 0, 3083, 982, 1684, 0, 0, 0, 523, 0, 0, 0, 0, 0, 294, 0, + 434, 52, 2034, 0, 0, 497, 2951, 1499, 0, 1874, 0, 2853, 0, 3319, 442, 1411, + 0, 2945, 0, 1324, 251, 3096, 0, 723, 3150, 0, 0, 0, 0, 570, 0, 3295, + 1259, 0, 1395, 2545, 885, 1991, 1730, 1268, 2599, 0, 1289, 275, 0, 0, 113, 1835, + 885, 1259, 2295, 682, 0, 0, 932, 0, 286, 0, 0, 60, 864, 0, 0, 1483, + 0, 86, 587, 9, 459, 0, 1342, 0, 1287, 416, 14, 371, 0, 0, 507, 0, + 350, 2826, 0, 0, 0, 3293, 3183, 0, 238, 0, 1501, 2720, 0, 3107, 0, 2340, + 1602, 2599, 0, 314, 0, 0, 1062, 347, 0, 1546, 0, 0, 0, 0, 895, 158, + 217, 1351, 0, 0, 2160, 0, 0, 120, 755, 407, 2490, 305, 288, 0, 182, 745, + 0, 1666, 3220, 177, 0, 0, 958, 0, 0, 0, 0, 2293, 0, 0, 0, 503, + 0, 0, 0, 1256, 2600, 987, 2318, 529, 1617, 3147, 1601, 0, 3178, 2050, 569, 0, + 513, 0, 0, 689, 1308, 0, 0, 0, 0, 746, 0, 398, 2399, 1141, 0, 3356, + 214, 0, 0, 2903, 0, 431, 2902, 356, 1944, 1430, 1478, 6, 0, 0, 117, 0, + 2887, 2267}; + +int MangledHashG(const char *key, const int *T) +{ + int sum = 0; + + for (int i = 0; key[i] != '\0'; i++) + { + sum += T[i] * key[i]; + sum %= 3410; + } + return mangledkG[sum]; +} + +int MangledPerfectHash(const char *key) +{ + if (strlen(key) > 40) + return 0; + + return (MangledHashG(key, mangledkT1) + MangledHashG(key, mangledkT2)) % 3410; +} + +constexpr int unmangledkT1[] = {258, 260, 73, 6, 294, 235, 86, 89, 66, 164, 215, + 28, 84, 215, 207, 246, 53, 166, 227, 83, 238, 195, + 109, 294, 270, 27, 167, 281, 55, 194, 257, 4}; +constexpr int unmangledkT2[] = {67, 64, 203, 266, 212, 293, 215, 33, 106, 81, 61, + 214, 272, 162, 248, 114, 4, 202, 197, 98, 169, 304, + 196, 197, 294, 217, 1, 201, 74, 46, 38, 221}; +constexpr int unmangledkG[] = { + 0, 0, 0, 0, 132, 0, 0, 123, 0, 152, 0, 87, 196, 305, 0, 0, 229, 273, + 130, 0, 87, 27, 163, 284, 0, 0, 0, 179, 233, 88, 0, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 126, 0, 104, 0, 222, 0, 0, 0, + 0, 0, 171, 36, 129, 0, 0, 0, 113, 0, 142, 303, 0, 138, 246, 0, 21, 0, + 121, 0, 162, 0, 0, 0, 0, 0, 147, 205, 0, 0, 232, 19, 0, 200, 0, 0, + 0, 68, 277, 68, 63, 0, 31, 0, 0, 255, 0, 0, 122, 0, 0, 108, 1, 63, + 74, 20, 130, 0, 0, 284, 0, 98, 158, 245, 0, 22, 2, 157, 195, 0, 257, 0, + 0, 0, 2, 172, 0, 0, 0, 0, 0, 132, 0, 0, 72, 27, 35, 269, 224, 0, + 216, 45, 151, 44, 9, 21, 0, 0, 188, 0, 229, 132, 212, 0, 75, 279, 119, 0, + 0, 0, 261, 25, 3, 180, 0, 0, 42, 40, 133, 200, 51, 0, 0, 232, 137, 128, + 9, 0, 0, 0, 278, 0, 0, 100, 0, 0, 0, 11, 137, 0, 0, 6, 0, 97, + 63, 0, 0, 166, 86, 0, 43, 228, 0, 0, 88, 272, 242, 61, 25, 99, 0, 260, + 169, 0, 0, 0, 99, 123, 39, 289, 77, 83, 0, 0, 33, 167, 0, 305, 0, 230, + 22, 0, 284, 0, 85, 26, 0, 80, 0, 0, 19, 206, 266, 0, 292, 74, 233, 86, + 218, 0, 63, 104, 15, 0, 0, 26, 132, 303, 0, 155, 256, 0, 109, 0, 215, 52, + 0, 0, 155, 95, 240, 112, 0, 95, 54, 89, 0, 171, 0, 158, 0, 51, 23, 125, + 276, 16, 107, 177, 92, 113, 32, 45, 136, 0, 0, 90, 241, 279, 38, 185, 0, 169}; + +int UnmangledHashG(const char *key, const int *T) +{ + int sum = 0; + + for (int i = 0; key[i] != '\0'; i++) + { + sum += T[i] * key[i]; + sum %= 306; + } + return unmangledkG[sum]; +} + +int UnmangledPerfectHash(const char *key) +{ + if (strlen(key) > 32) + return 0; + + return (UnmangledHashG(key, unmangledkT1) + UnmangledHashG(key, unmangledkT2)) % 306; +} + +} // namespace + +namespace sh +{ + +template <> +const size_t ImmutableString::FowlerNollVoHash<4>::kFnvPrime = 16777619u; + +template <> +const size_t ImmutableString::FowlerNollVoHash<4>::kFnvOffsetBasis = 0x811c9dc5u; + +template <> +const size_t ImmutableString::FowlerNollVoHash<8>::kFnvPrime = + static_cast(1099511628211ull); + +template <> +const size_t ImmutableString::FowlerNollVoHash<8>::kFnvOffsetBasis = + static_cast(0xcbf29ce484222325ull); + +uint32_t ImmutableString::mangledNameHash() const +{ + return MangledPerfectHash(data()); +} + +uint32_t ImmutableString::unmangledNameHash() const +{ + return UnmangledPerfectHash(data()); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/InfoSink.cpp b/gfx/angle/checkout/src/compiler/translator/InfoSink.cpp new file mode 100644 index 0000000000..0e67d7324e --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/InfoSink.cpp @@ -0,0 +1,124 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/InfoSink.h" + +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/Types.h" + +namespace sh +{ + +void TInfoSinkBase::prefix(Severity severity) +{ + switch (severity) + { + case SH_WARNING: + sink.append("WARNING: "); + break; + case SH_ERROR: + sink.append("ERROR: "); + break; + default: + sink.append("UNKOWN ERROR: "); + break; + } +} + +TInfoSinkBase &TInfoSinkBase::operator<<(const ImmutableString &str) +{ + sink.append(str.data()); + return *this; +} + +TInfoSinkBase &TInfoSinkBase::operator<<(const TType &type) +{ + if (type.isInvariant()) + sink.append("invariant "); + if (type.getQualifier() != EvqTemporary && type.getQualifier() != EvqGlobal) + { + sink.append(type.getQualifierString()); + sink.append(" "); + } + if (type.getPrecision() != EbpUndefined) + { + sink.append(type.getPrecisionString()); + sink.append(" "); + } + + const TMemoryQualifier &memoryQualifier = type.getMemoryQualifier(); + if (memoryQualifier.readonly) + { + sink.append("readonly "); + } + if (memoryQualifier.writeonly) + { + sink.append("writeonly "); + } + if (memoryQualifier.coherent) + { + sink.append("coherent "); + } + if (memoryQualifier.restrictQualifier) + { + sink.append("restrict "); + } + if (memoryQualifier.volatileQualifier) + { + sink.append("volatile "); + } + + if (type.isArray()) + { + for (auto arraySizeIter = type.getArraySizes().rbegin(); + arraySizeIter != type.getArraySizes().rend(); ++arraySizeIter) + { + *this << "array[" << (*arraySizeIter) << "] of "; + } + } + if (type.isMatrix()) + { + *this << static_cast(type.getCols()) << "X" + << static_cast(type.getRows()) << " matrix of "; + } + else if (type.isVector()) + *this << static_cast(type.getNominalSize()) << "-component vector of "; + + sink.append(type.getBasicString()); + + if (type.getStruct() != nullptr) + { + if (type.getStruct()->symbolType() == SymbolType::Empty) + { + *this << " "; + } + else + { + *this << " '" << type.getStruct()->name() << "'"; + } + if (type.isStructSpecifier()) + { + *this << " (specifier)"; + } + } + + return *this; +} + +void TInfoSinkBase::location(int file, int line) +{ + TPersistStringStream stream = sh::InitializeStream(); + if (line) + stream << file << ":" << line; + else + stream << file << ":? "; + stream << ": "; + + sink.append(stream.str()); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/InfoSink.h b/gfx/angle/checkout/src/compiler/translator/InfoSink.h new file mode 100644 index 0000000000..bf6df8800c --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/InfoSink.h @@ -0,0 +1,152 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_INFOSINK_H_ +#define COMPILER_TRANSLATOR_INFOSINK_H_ + +#include +#include +#include "GLSLANG/ShaderLang.h" +#include "compiler/translator/Common.h" +#include "compiler/translator/Severity.h" + +namespace sh +{ + +class ImmutableString; +class TType; + +// Returns the fractional part of the given floating-point number. +inline float fractionalPart(float f) +{ + float intPart = 0.0f; + return modff(f, &intPart); +} + +class ImmutableString; + +// +// Encapsulate info logs for all objects that have them. +// +// The methods are a general set of tools for getting a variety of +// messages and types inserted into the log. +// +class TInfoSinkBase +{ + public: + TInfoSinkBase() {} + + template + TInfoSinkBase &operator<<(const T &t) + { + TPersistStringStream stream = sh::InitializeStream(); + stream << t; + sink.append(stream.str()); + return *this; + } + // Override << operator for specific types. It is faster to append strings + // and characters directly to the sink. + TInfoSinkBase &operator<<(char c) + { + sink.append(1, c); + return *this; + } + TInfoSinkBase &operator<<(const char *str) + { + sink.append(str); + return *this; + } + TInfoSinkBase &operator<<(const TPersistString &str) + { + sink.append(str); + return *this; + } + TInfoSinkBase &operator<<(const TString &str) + { + sink.append(str.c_str()); + return *this; + } + TInfoSinkBase &operator<<(const ImmutableString &str); + + TInfoSinkBase &operator<<(const TType &type); + + // Make sure floats are written with correct precision. + TInfoSinkBase &operator<<(float f) + { + // Make sure that at least one decimal point is written. If a number + // does not have a fractional part, the default precision format does + // not write the decimal portion which gets interpreted as integer by + // the compiler. + TPersistStringStream stream = sh::InitializeStream(); + if (fractionalPart(f) == 0.0f) + { + stream.precision(1); + stream << std::showpoint << std::fixed << f; + } + else + { + stream.unsetf(std::ios::fixed); + stream.unsetf(std::ios::scientific); + stream.precision(8); + stream << f; + } + sink.append(stream.str()); + return *this; + } + // Write boolean values as their names instead of integral value. + TInfoSinkBase &operator<<(bool b) + { + const char *str = b ? "true" : "false"; + sink.append(str); + return *this; + } + + void erase() + { + sink.clear(); + binarySink.clear(); + } + int size() { return static_cast(isBinary() ? binarySink.size() : sink.size()); } + + const TPersistString &str() const + { + ASSERT(!isBinary()); + return sink; + } + const char *c_str() const + { + ASSERT(!isBinary()); + return sink.c_str(); + } + + void prefix(Severity severity); + void location(int file, int line); + + bool isBinary() const { return !binarySink.empty(); } + void setBinary(BinaryBlob &&binary) { binarySink = std::move(binary); } + const BinaryBlob &getBinary() const + { + ASSERT(isBinary()); + return binarySink; + } + + private: + // The data in the info sink is either in human readable form (|sink|) or binary (|binarySink|). + TPersistString sink; + BinaryBlob binarySink; +}; + +class TInfoSink +{ + public: + TInfoSinkBase info; + TInfoSinkBase debug; + TInfoSinkBase obj; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_INFOSINK_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/Initialize.cpp b/gfx/angle/checkout/src/compiler/translator/Initialize.cpp new file mode 100644 index 0000000000..287765db8f --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Initialize.cpp @@ -0,0 +1,223 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/Initialize.h" + +namespace sh +{ + +void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavior &extBehavior) +{ + if (resources.OES_standard_derivatives) + { + extBehavior[TExtension::OES_standard_derivatives] = EBhUndefined; + } + if (resources.OES_EGL_image_external) + { + extBehavior[TExtension::OES_EGL_image_external] = EBhUndefined; + } + if (resources.OES_EGL_image_external_essl3) + { + extBehavior[TExtension::OES_EGL_image_external_essl3] = EBhUndefined; + } + if (resources.NV_EGL_stream_consumer_external) + { + extBehavior[TExtension::NV_EGL_stream_consumer_external] = EBhUndefined; + } + if (resources.ARB_texture_rectangle) + { + // Special: ARB_texture_rectangle extension does not follow the standard for #extension + // directives - it is enabled by default. An extension directive may still disable it. + extBehavior[TExtension::ARB_texture_rectangle] = EBhEnable; + } + if (resources.EXT_blend_func_extended) + { + extBehavior[TExtension::EXT_blend_func_extended] = EBhUndefined; + } + if (resources.EXT_draw_buffers) + { + extBehavior[TExtension::EXT_draw_buffers] = EBhUndefined; + } + if (resources.EXT_frag_depth) + { + extBehavior[TExtension::EXT_frag_depth] = EBhUndefined; + } + if (resources.EXT_primitive_bounding_box) + { + extBehavior[TExtension::EXT_primitive_bounding_box] = EBhUndefined; + } + if (resources.OES_primitive_bounding_box) + { + extBehavior[TExtension::OES_primitive_bounding_box] = EBhUndefined; + } + if (resources.EXT_shader_texture_lod) + { + extBehavior[TExtension::EXT_shader_texture_lod] = EBhUndefined; + } + if (resources.EXT_shader_framebuffer_fetch) + { + extBehavior[TExtension::EXT_shader_framebuffer_fetch] = EBhUndefined; + } + if (resources.EXT_shader_framebuffer_fetch_non_coherent) + { + extBehavior[TExtension::EXT_shader_framebuffer_fetch_non_coherent] = EBhUndefined; + } + if (resources.NV_shader_framebuffer_fetch) + { + extBehavior[TExtension::NV_shader_framebuffer_fetch] = EBhUndefined; + } + if (resources.NV_shader_noperspective_interpolation) + { + extBehavior[TExtension::NV_shader_noperspective_interpolation] = EBhUndefined; + } + if (resources.ARM_shader_framebuffer_fetch) + { + extBehavior[TExtension::ARM_shader_framebuffer_fetch] = EBhUndefined; + } + if (resources.OVR_multiview) + { + extBehavior[TExtension::OVR_multiview] = EBhUndefined; + } + if (resources.OVR_multiview2) + { + extBehavior[TExtension::OVR_multiview2] = EBhUndefined; + } + if (resources.EXT_YUV_target) + { + extBehavior[TExtension::EXT_YUV_target] = EBhUndefined; + } + if (resources.EXT_geometry_shader) + { + extBehavior[TExtension::EXT_geometry_shader] = EBhUndefined; + } + if (resources.OES_geometry_shader) + { + extBehavior[TExtension::OES_geometry_shader] = EBhUndefined; + } + if (resources.OES_shader_io_blocks) + { + extBehavior[TExtension::OES_shader_io_blocks] = EBhUndefined; + } + if (resources.EXT_shader_io_blocks) + { + extBehavior[TExtension::EXT_shader_io_blocks] = EBhUndefined; + } + if (resources.EXT_gpu_shader5) + { + extBehavior[TExtension::EXT_gpu_shader5] = EBhUndefined; + } + if (resources.EXT_shader_non_constant_global_initializers) + { + extBehavior[TExtension::EXT_shader_non_constant_global_initializers] = EBhUndefined; + } + if (resources.OES_texture_storage_multisample_2d_array) + { + extBehavior[TExtension::OES_texture_storage_multisample_2d_array] = EBhUndefined; + } + if (resources.OES_texture_3D) + { + extBehavior[TExtension::OES_texture_3D] = EBhUndefined; + } + if (resources.ANGLE_shader_pixel_local_storage) + { + extBehavior[TExtension::ANGLE_shader_pixel_local_storage] = EBhUndefined; + } + if (resources.ANGLE_texture_multisample) + { + extBehavior[TExtension::ANGLE_texture_multisample] = EBhUndefined; + } + if (resources.ANGLE_multi_draw) + { + extBehavior[TExtension::ANGLE_multi_draw] = EBhUndefined; + } + if (resources.ANGLE_base_vertex_base_instance_shader_builtin) + { + extBehavior[TExtension::ANGLE_base_vertex_base_instance_shader_builtin] = EBhUndefined; + } + if (resources.WEBGL_video_texture) + { + extBehavior[TExtension::WEBGL_video_texture] = EBhUndefined; + } + if (resources.APPLE_clip_distance) + { + extBehavior[TExtension::APPLE_clip_distance] = EBhUndefined; + } + if (resources.OES_texture_cube_map_array) + { + extBehavior[TExtension::OES_texture_cube_map_array] = EBhUndefined; + } + if (resources.EXT_texture_cube_map_array) + { + extBehavior[TExtension::EXT_texture_cube_map_array] = EBhUndefined; + } + if (resources.EXT_shadow_samplers) + { + extBehavior[TExtension::EXT_shadow_samplers] = EBhUndefined; + } + if (resources.OES_shader_multisample_interpolation) + { + extBehavior[TExtension::OES_shader_multisample_interpolation] = EBhUndefined; + } + if (resources.OES_shader_image_atomic) + { + extBehavior[TExtension::OES_shader_image_atomic] = EBhUndefined; + } + if (resources.EXT_tessellation_shader) + { + extBehavior[TExtension::EXT_tessellation_shader] = EBhUndefined; + } + if (resources.OES_texture_buffer) + { + extBehavior[TExtension::OES_texture_buffer] = EBhUndefined; + } + if (resources.EXT_texture_buffer) + { + extBehavior[TExtension::EXT_texture_buffer] = EBhUndefined; + } + if (resources.OES_sample_variables) + { + extBehavior[TExtension::OES_sample_variables] = EBhUndefined; + } + if (resources.EXT_clip_cull_distance) + { + extBehavior[TExtension::EXT_clip_cull_distance] = EBhUndefined; + } + if (resources.ANDROID_extension_pack_es31a) + { + extBehavior[TExtension::ANDROID_extension_pack_es31a] = EBhUndefined; + } + if (resources.KHR_blend_equation_advanced) + { + extBehavior[TExtension::KHR_blend_equation_advanced] = EBhUndefined; + } +} + +void ResetExtensionBehavior(const ShBuiltInResources &resources, + TExtensionBehavior &extBehavior, + const ShCompileOptions &compileOptions) +{ + for (auto &ext : extBehavior) + { + ext.second = EBhUndefined; + } + if (resources.ARB_texture_rectangle) + { + if (compileOptions.disableARBTextureRectangle) + { + // Remove ARB_texture_rectangle so it can't be enabled by extension directives. + extBehavior.erase(TExtension::ARB_texture_rectangle); + } + else + { + // Restore ARB_texture_rectangle in case it was removed during an earlier reset. As + // noted above, it doesn't follow the standard for extension directives and is + // enabled by default. + extBehavior[TExtension::ARB_texture_rectangle] = EBhEnable; + } + } +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/Initialize.h b/gfx/angle/checkout/src/compiler/translator/Initialize.h new file mode 100644 index 0000000000..727e44e277 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Initialize.h @@ -0,0 +1,30 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_INITIALIZE_H_ +#define COMPILER_TRANSLATOR_INITIALIZE_H_ + +#include "compiler/translator/Common.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/SymbolTable.h" + +namespace sh +{ + +void InitExtensionBehavior(const ShBuiltInResources &resources, + TExtensionBehavior &extensionBehavior); + +// Resets the behavior of the extensions listed in |extensionBehavior| to the +// undefined state. These extensions will only be those initially supported in +// the ShBuiltInResources object for this compiler instance. All other +// extensions will remain unsupported. +void ResetExtensionBehavior(const ShBuiltInResources &resources, + TExtensionBehavior &extensionBehavior, + const ShCompileOptions &compileOptions); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_INITIALIZE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/InitializeDll.cpp b/gfx/angle/checkout/src/compiler/translator/InitializeDll.cpp new file mode 100644 index 0000000000..99a0fea19b --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/InitializeDll.cpp @@ -0,0 +1,33 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/InitializeDll.h" +#include "compiler/translator/InitializeGlobals.h" + +#include "common/platform.h" + +#include + +namespace sh +{ + +bool InitProcess() +{ + if (!InitializePoolIndex()) + { + assert(0 && "InitProcess(): Failed to initalize global pool"); + return false; + } + + return true; +} + +void DetachProcess() +{ + FreePoolIndex(); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/InitializeDll.h b/gfx/angle/checkout/src/compiler/translator/InitializeDll.h new file mode 100644 index 0000000000..a75a13c2d9 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/InitializeDll.h @@ -0,0 +1,15 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +#ifndef COMPILER_TRANSLATOR_INITIALIZEDLL_H_ +#define COMPILER_TRANSLATOR_INITIALIZEDLL_H_ + +namespace sh +{ +bool InitProcess(); +void DetachProcess(); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_INITIALIZEDLL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/InitializeGlobals.h b/gfx/angle/checkout/src/compiler/translator/InitializeGlobals.h new file mode 100644 index 0000000000..cf431ef4f1 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/InitializeGlobals.h @@ -0,0 +1,13 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ +#define COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ + +bool InitializePoolIndex(); +void FreePoolIndex(); + +#endif // COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/IntermNode.cpp b/gfx/angle/checkout/src/compiler/translator/IntermNode.cpp new file mode 100644 index 0000000000..a932b534be --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/IntermNode.cpp @@ -0,0 +1,4226 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// Build the intermediate representation. +// + +#include +#include +#include +#include +#include +#include + +#include "common/mathutil.h" +#include "common/matrix_utils.h" +#include "common/utilities.h" +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +const float kPi = 3.14159265358979323846f; +const float kDegreesToRadiansMultiplier = kPi / 180.0f; +const float kRadiansToDegreesMultiplier = 180.0f / kPi; + +TPrecision GetHigherPrecision(TPrecision left, TPrecision right) +{ + return left > right ? left : right; +} + +TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size) +{ + TConstantUnion *constUnion = new TConstantUnion[size]; + for (size_t i = 0; i < size; ++i) + constUnion[i] = constant; + + return constUnion; +} + +void UndefinedConstantFoldingError(const TSourceLoc &loc, + const TFunction *function, + TBasicType basicType, + TDiagnostics *diagnostics, + TConstantUnion *result) +{ + diagnostics->warning(loc, "operation result is undefined for the values passed in", + function->name().data()); + + switch (basicType) + { + case EbtFloat: + result->setFConst(0.0f); + break; + case EbtInt: + result->setIConst(0); + break; + case EbtUInt: + result->setUConst(0u); + break; + case EbtBool: + result->setBConst(false); + break; + default: + break; + } +} + +float VectorLength(const TConstantUnion *paramArray, size_t paramArraySize) +{ + float result = 0.0f; + for (size_t i = 0; i < paramArraySize; i++) + { + float f = paramArray[i].getFConst(); + result += f * f; + } + return sqrtf(result); +} + +float VectorDotProduct(const TConstantUnion *paramArray1, + const TConstantUnion *paramArray2, + size_t paramArraySize) +{ + float result = 0.0f; + for (size_t i = 0; i < paramArraySize; i++) + result += paramArray1[i].getFConst() * paramArray2[i].getFConst(); + return result; +} + +TIntermTyped *CreateFoldedNode(const TConstantUnion *constArray, const TIntermTyped *originalNode) +{ + ASSERT(constArray != nullptr); + // Note that we inherit whatever qualifier the folded node had. Nodes may be constant folded + // without being qualified as constant. + TIntermTyped *folded = new TIntermConstantUnion(constArray, originalNode->getType()); + folded->setLine(originalNode->getLine()); + return folded; +} + +angle::Matrix GetMatrix(const TConstantUnion *paramArray, + const unsigned int rows, + const unsigned int cols) +{ + std::vector elements; + for (size_t i = 0; i < rows * cols; i++) + elements.push_back(paramArray[i].getFConst()); + // Transpose is used since the Matrix constructor expects arguments in row-major order, + // whereas the paramArray is in column-major order. Rows/cols parameters are also flipped below + // so that the created matrix will have the expected dimensions after the transpose. + return angle::Matrix(elements, cols, rows).transpose(); +} + +angle::Matrix GetMatrix(const TConstantUnion *paramArray, const unsigned int size) +{ + std::vector elements; + for (size_t i = 0; i < size * size; i++) + elements.push_back(paramArray[i].getFConst()); + // Transpose is used since the Matrix constructor expects arguments in row-major order, + // whereas the paramArray is in column-major order. + return angle::Matrix(elements, size).transpose(); +} + +void SetUnionArrayFromMatrix(const angle::Matrix &m, TConstantUnion *resultArray) +{ + // Transpose is used since the input Matrix is in row-major order, + // whereas the actual result should be in column-major order. + angle::Matrix result = m.transpose(); + std::vector resultElements = result.elements(); + for (size_t i = 0; i < resultElements.size(); i++) + resultArray[i].setFConst(resultElements[i]); +} + +bool CanFoldAggregateBuiltInOp(TOperator op) +{ + switch (op) + { + case EOpAtan: + case EOpPow: + case EOpMod: + case EOpMin: + case EOpMax: + case EOpClamp: + case EOpMix: + case EOpStep: + case EOpSmoothstep: + case EOpFma: + case EOpLdexp: + case EOpMatrixCompMult: + case EOpOuterProduct: + case EOpEqualComponentWise: + case EOpNotEqualComponentWise: + case EOpLessThanComponentWise: + case EOpLessThanEqualComponentWise: + case EOpGreaterThanComponentWise: + case EOpGreaterThanEqualComponentWise: + case EOpDistance: + case EOpDot: + case EOpCross: + case EOpFaceforward: + case EOpReflect: + case EOpRefract: + case EOpBitfieldExtract: + case EOpBitfieldInsert: + case EOpDFdx: + case EOpDFdy: + case EOpFwidth: + return true; + default: + return false; + } +} + +void PropagatePrecisionIfApplicable(TIntermTyped *node, TPrecision precision) +{ + if (precision == EbpUndefined || node->getPrecision() != EbpUndefined) + { + return; + } + + if (IsPrecisionApplicableToType(node->getBasicType())) + { + node->propagatePrecision(precision); + } +} + +} // namespace + +//////////////////////////////////////////////////////////////// +// +// Member functions of the nodes used for building the tree. +// +//////////////////////////////////////////////////////////////// + +TIntermExpression::TIntermExpression(const TType &t) : TIntermTyped(), mType(t) {} + +#define REPLACE_IF_IS(node, type, original, replacement) \ + do \ + { \ + if (node == original) \ + { \ + node = static_cast(replacement); \ + return true; \ + } \ + } while (0) + +size_t TIntermSymbol::getChildCount() const +{ + return 0; +} + +TIntermNode *TIntermSymbol::getChildNode(size_t index) const +{ + UNREACHABLE(); + return nullptr; +} + +size_t TIntermConstantUnion::getChildCount() const +{ + return 0; +} + +TIntermNode *TIntermConstantUnion::getChildNode(size_t index) const +{ + UNREACHABLE(); + return nullptr; +} + +size_t TIntermLoop::getChildCount() const +{ + return (mInit ? 1 : 0) + (mCond ? 1 : 0) + (mExpr ? 1 : 0) + (mBody ? 1 : 0); +} + +TIntermNode *TIntermLoop::getChildNode(size_t index) const +{ + TIntermNode *children[4]; + unsigned int childIndex = 0; + if (mInit) + { + children[childIndex] = mInit; + ++childIndex; + } + if (mCond) + { + children[childIndex] = mCond; + ++childIndex; + } + if (mExpr) + { + children[childIndex] = mExpr; + ++childIndex; + } + if (mBody) + { + children[childIndex] = mBody; + ++childIndex; + } + ASSERT(index < childIndex); + return children[index]; +} + +bool TIntermLoop::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +{ + ASSERT(original != nullptr); // This risks replacing multiple children. + REPLACE_IF_IS(mInit, TIntermNode, original, replacement); + REPLACE_IF_IS(mCond, TIntermTyped, original, replacement); + REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement); + REPLACE_IF_IS(mBody, TIntermBlock, original, replacement); + return false; +} + +TIntermBranch::TIntermBranch(const TIntermBranch &node) + : TIntermBranch(node.mFlowOp, node.mExpression ? node.mExpression->deepCopy() : nullptr) +{} + +size_t TIntermBranch::getChildCount() const +{ + return (mExpression ? 1 : 0); +} + +TIntermNode *TIntermBranch::getChildNode(size_t index) const +{ + ASSERT(mExpression); + ASSERT(index == 0); + return mExpression; +} + +bool TIntermBranch::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement); + return false; +} + +size_t TIntermSwizzle::getChildCount() const +{ + return 1; +} + +TIntermNode *TIntermSwizzle::getChildNode(size_t index) const +{ + ASSERT(mOperand); + ASSERT(index == 0); + return mOperand; +} + +bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +{ + ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType()); + REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); + return false; +} + +size_t TIntermBinary::getChildCount() const +{ + return 2; +} + +TIntermNode *TIntermBinary::getChildNode(size_t index) const +{ + ASSERT(index < 2); + if (index == 0) + { + return mLeft; + } + return mRight; +} + +bool TIntermBinary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement); + REPLACE_IF_IS(mRight, TIntermTyped, original, replacement); + return false; +} + +size_t TIntermUnary::getChildCount() const +{ + return 1; +} + +TIntermNode *TIntermUnary::getChildNode(size_t index) const +{ + ASSERT(mOperand); + ASSERT(index == 0); + return mOperand; +} + +bool TIntermUnary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +{ + ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType()); + REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); + return false; +} + +size_t TIntermGlobalQualifierDeclaration::getChildCount() const +{ + return 1; +} + +TIntermNode *TIntermGlobalQualifierDeclaration::getChildNode(size_t index) const +{ + ASSERT(mSymbol); + ASSERT(index == 0); + return mSymbol; +} + +bool TIntermGlobalQualifierDeclaration::replaceChildNode(TIntermNode *original, + TIntermNode *replacement) +{ + REPLACE_IF_IS(mSymbol, TIntermSymbol, original, replacement); + return false; +} + +size_t TIntermFunctionDefinition::getChildCount() const +{ + return 2; +} + +TIntermNode *TIntermFunctionDefinition::getChildNode(size_t index) const +{ + ASSERT(index < 2); + if (index == 0) + { + return mPrototype; + } + return mBody; +} + +bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mPrototype, TIntermFunctionPrototype, original, replacement); + REPLACE_IF_IS(mBody, TIntermBlock, original, replacement); + return false; +} + +size_t TIntermAggregate::getChildCount() const +{ + return mArguments.size(); +} + +TIntermNode *TIntermAggregate::getChildNode(size_t index) const +{ + return mArguments[index]; +} + +bool TIntermAggregate::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +{ + return replaceChildNodeInternal(original, replacement); +} + +TIntermBlock::TIntermBlock(const TIntermBlock &node) +{ + for (TIntermNode *intermNode : node.mStatements) + { + mStatements.push_back(intermNode->deepCopy()); + } + + ASSERT(!node.mIsTreeRoot); + mIsTreeRoot = false; +} + +TIntermBlock::TIntermBlock(std::initializer_list stmts) +{ + for (TIntermNode *stmt : stmts) + { + appendStatement(stmt); + } +} + +size_t TIntermBlock::getChildCount() const +{ + return mStatements.size(); +} + +TIntermNode *TIntermBlock::getChildNode(size_t index) const +{ + return mStatements[index]; +} + +bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +{ + return replaceChildNodeInternal(original, replacement); +} + +void TIntermBlock::replaceAllChildren(const TIntermSequence &newStatements) +{ + mStatements.clear(); + mStatements.insert(mStatements.begin(), newStatements.begin(), newStatements.end()); +} + +size_t TIntermFunctionPrototype::getChildCount() const +{ + return 0; +} + +TIntermNode *TIntermFunctionPrototype::getChildNode(size_t index) const +{ + UNREACHABLE(); + return nullptr; +} + +bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +{ + return false; +} + +TIntermDeclaration::TIntermDeclaration(const TVariable *var, TIntermTyped *initExpr) +{ + if (initExpr) + { + appendDeclarator( + new TIntermBinary(TOperator::EOpInitialize, new TIntermSymbol(var), initExpr)); + } + else + { + appendDeclarator(new TIntermSymbol(var)); + } +} + +TIntermDeclaration::TIntermDeclaration(std::initializer_list declarators) + : TIntermDeclaration() +{ + for (const TVariable *d : declarators) + { + appendDeclarator(new TIntermSymbol(d)); + } +} + +TIntermDeclaration::TIntermDeclaration(std::initializer_list declarators) + : TIntermDeclaration() +{ + for (TIntermTyped *d : declarators) + { + appendDeclarator(d); + } +} + +size_t TIntermDeclaration::getChildCount() const +{ + return mDeclarators.size(); +} + +TIntermNode *TIntermDeclaration::getChildNode(size_t index) const +{ + return mDeclarators[index]; +} + +bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +{ + return replaceChildNodeInternal(original, replacement); +} + +TIntermDeclaration::TIntermDeclaration(const TIntermDeclaration &node) +{ + for (TIntermNode *intermNode : node.mDeclarators) + { + mDeclarators.push_back(intermNode->deepCopy()); + } +} + +bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement) +{ + for (size_t ii = 0; ii < getSequence()->size(); ++ii) + { + REPLACE_IF_IS((*getSequence())[ii], TIntermNode, original, replacement); + } + return false; +} + +bool TIntermAggregateBase::replaceChildNodeWithMultiple(TIntermNode *original, + const TIntermSequence &replacements) +{ + for (auto it = getSequence()->begin(); it < getSequence()->end(); ++it) + { + if (*it == original) + { + it = getSequence()->erase(it); + getSequence()->insert(it, replacements.begin(), replacements.end()); + return true; + } + } + return false; +} + +bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position, + const TIntermSequence &insertions) +{ + if (position > getSequence()->size()) + { + return false; + } + auto it = getSequence()->begin() + position; + getSequence()->insert(it, insertions.begin(), insertions.end()); + return true; +} + +TIntermSymbol::TIntermSymbol(const TVariable *variable) : TIntermTyped(), mVariable(variable) {} + +bool TIntermSymbol::hasConstantValue() const +{ + return variable().getConstPointer() != nullptr; +} + +const TConstantUnion *TIntermSymbol::getConstantValue() const +{ + return variable().getConstPointer(); +} + +const TSymbolUniqueId &TIntermSymbol::uniqueId() const +{ + return mVariable->uniqueId(); +} + +ImmutableString TIntermSymbol::getName() const +{ + return mVariable->name(); +} + +const TType &TIntermSymbol::getType() const +{ + return mVariable->getType(); +} + +void TIntermSymbol::propagatePrecision(TPrecision precision) +{ + // Every declared variable should already have a precision. Some built-ins don't have a defined + // precision. This is not asserted however: + // + // - A shader with no precision specified either globally or on a variable will fail with a + // compilation error later on. + // - Transformations declaring variables without precision will be caught by AST validation. +} + +TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TFunction &func, + TIntermSequence *arguments) +{ + return new TIntermAggregate(&func, func.getReturnType(), EOpCallFunctionInAST, arguments); +} + +TIntermAggregate *TIntermAggregate::CreateRawFunctionCall(const TFunction &func, + TIntermSequence *arguments) +{ + return new TIntermAggregate(&func, func.getReturnType(), EOpCallInternalRawFunction, arguments); +} + +TIntermAggregate *TIntermAggregate::CreateBuiltInFunctionCall(const TFunction &func, + TIntermSequence *arguments) +{ + // Every built-in function should have an op. + ASSERT(func.getBuiltInOp() != EOpNull); + return new TIntermAggregate(&func, func.getReturnType(), func.getBuiltInOp(), arguments); +} + +TIntermAggregate *TIntermAggregate::CreateConstructor(const TType &type, TIntermSequence *arguments) +{ + return new TIntermAggregate(nullptr, type, EOpConstruct, arguments); +} + +TIntermAggregate *TIntermAggregate::CreateConstructor( + const TType &type, + const std::initializer_list &arguments) +{ + TIntermSequence argSequence(arguments); + return CreateConstructor(type, &argSequence); +} + +TIntermAggregate::TIntermAggregate(const TFunction *func, + const TType &type, + TOperator op, + TIntermSequence *arguments) + : TIntermOperator(op, type), mUseEmulatedFunction(false), mFunction(func) +{ + if (arguments != nullptr) + { + mArguments.swap(*arguments); + } + ASSERT(mFunction == nullptr || mFunction->symbolType() != SymbolType::Empty); + setPrecisionAndQualifier(); +} + +void TIntermAggregate::setPrecisionAndQualifier() +{ + mType.setQualifier(EvqTemporary); + if ((!BuiltInGroup::IsBuiltIn(mOp) && !isFunctionCall()) || BuiltInGroup::IsMath(mOp)) + { + if (areChildrenConstQualified()) + { + mType.setQualifier(EvqConst); + } + } + + propagatePrecision(derivePrecision()); +} + +bool TIntermAggregate::areChildrenConstQualified() +{ + for (TIntermNode *arg : mArguments) + { + TIntermTyped *typedArg = arg->getAsTyped(); + if (typedArg && typedArg->getQualifier() != EvqConst) + { + return false; + } + } + return true; +} + +// Derive precision from children nodes +TPrecision TIntermAggregate::derivePrecision() const +{ + if (getBasicType() == EbtBool || getBasicType() == EbtVoid || getBasicType() == EbtStruct) + { + return EbpUndefined; + } + + // For AST function calls, take the qualifier from the declared one. + if (isFunctionCall()) + { + return mType.getPrecision(); + } + + // Some built-ins explicitly specify their precision. + switch (mOp) + { + case EOpBitfieldExtract: + return mArguments[0]->getAsTyped()->getPrecision(); + case EOpBitfieldInsert: + return GetHigherPrecision(mArguments[0]->getAsTyped()->getPrecision(), + mArguments[1]->getAsTyped()->getPrecision()); + case EOpTextureSize: + case EOpImageSize: + case EOpUaddCarry: + case EOpUsubBorrow: + case EOpUmulExtended: + case EOpImulExtended: + case EOpFrexp: + case EOpLdexp: + return EbpHigh; + default: + break; + } + + // The rest of the math operations and constructors get their precision from their arguments. + if (BuiltInGroup::IsMath(mOp) || mOp == EOpConstruct) + { + TPrecision precision = EbpUndefined; + for (TIntermNode *argument : mArguments) + { + precision = GetHigherPrecision(argument->getAsTyped()->getPrecision(), precision); + } + return precision; + } + + // Atomic operations return highp. + if (BuiltInGroup::IsImageAtomic(mOp) || BuiltInGroup::IsAtomicCounter(mOp) || + BuiltInGroup::IsAtomicMemory(mOp)) + { + return EbpHigh; + } + + // Texture functions return the same precision as that of the sampler (textureSize returns + // highp, but that's handled above). imageLoad similar takes the precision of the image. The + // same is true for dFd*, interpolateAt* and subpassLoad operations. + if (BuiltInGroup::IsTexture(mOp) || BuiltInGroup::IsImageLoad(mOp) || + BuiltInGroup::IsDerivativesFS(mOp) || BuiltInGroup::IsInterpolationFS(mOp) || + mOp == EOpSubpassLoad) + { + return mArguments[0]->getAsTyped()->getPrecision(); + } + + // Every possibility must be explicitly handled, except for desktop-GLSL-specific built-ins + // for which precision does't matter. + return EbpUndefined; +} + +// Propagate precision to children nodes that don't already have it defined. +void TIntermAggregate::propagatePrecision(TPrecision precision) +{ + mType.setPrecision(precision); + + // For constructors, propagate precision to arguments. + if (isConstructor()) + { + for (TIntermNode *arg : mArguments) + { + PropagatePrecisionIfApplicable(arg->getAsTyped(), precision); + } + return; + } + + // For function calls, propagate precision of each parameter to its corresponding argument. + if (isFunctionCall()) + { + for (size_t paramIndex = 0; paramIndex < mFunction->getParamCount(); ++paramIndex) + { + const TVariable *paramVariable = mFunction->getParam(paramIndex); + PropagatePrecisionIfApplicable(mArguments[paramIndex]->getAsTyped(), + paramVariable->getType().getPrecision()); + } + return; + } + + // Some built-ins explicitly specify the precision of their parameters. + switch (mOp) + { + case EOpUaddCarry: + case EOpUsubBorrow: + case EOpUmulExtended: + case EOpImulExtended: + PropagatePrecisionIfApplicable(mArguments[0]->getAsTyped(), EbpHigh); + PropagatePrecisionIfApplicable(mArguments[1]->getAsTyped(), EbpHigh); + break; + case EOpFindMSB: + case EOpFrexp: + case EOpLdexp: + PropagatePrecisionIfApplicable(mArguments[0]->getAsTyped(), EbpHigh); + break; + default: + break; + } +} + +const char *TIntermAggregate::functionName() const +{ + ASSERT(!isConstructor()); + switch (mOp) + { + case EOpCallInternalRawFunction: + case EOpCallFunctionInAST: + return mFunction->name().data(); + default: + if (BuiltInGroup::IsBuiltIn(mOp)) + { + return mFunction->name().data(); + } + return GetOperatorString(mOp); + } +} + +bool TIntermAggregate::hasConstantValue() const +{ + if (!isConstructor()) + { + return false; + } + for (TIntermNode *constructorArg : mArguments) + { + if (!constructorArg->getAsTyped()->hasConstantValue()) + { + return false; + } + } + return true; +} + +bool TIntermAggregate::isConstantNullValue() const +{ + if (!isConstructor()) + { + return false; + } + for (TIntermNode *constructorArg : mArguments) + { + if (!constructorArg->getAsTyped()->isConstantNullValue()) + { + return false; + } + } + return true; +} + +const TConstantUnion *TIntermAggregate::getConstantValue() const +{ + if (!hasConstantValue()) + { + return nullptr; + } + ASSERT(isConstructor()); + ASSERT(mArguments.size() > 0u); + + TConstantUnion *constArray = nullptr; + if (isArray()) + { + size_t elementSize = mArguments.front()->getAsTyped()->getType().getObjectSize(); + constArray = new TConstantUnion[elementSize * getOutermostArraySize()]; + + size_t elementOffset = 0u; + for (TIntermNode *constructorArg : mArguments) + { + const TConstantUnion *elementConstArray = + constructorArg->getAsTyped()->getConstantValue(); + ASSERT(elementConstArray); + size_t elementSizeBytes = sizeof(TConstantUnion) * elementSize; + memcpy(static_cast(&constArray[elementOffset]), + static_cast(elementConstArray), elementSizeBytes); + elementOffset += elementSize; + } + return constArray; + } + + size_t resultSize = getType().getObjectSize(); + constArray = new TConstantUnion[resultSize]; + TBasicType basicType = getBasicType(); + + size_t resultIndex = 0u; + + if (mArguments.size() == 1u) + { + TIntermNode *argument = mArguments.front(); + TIntermTyped *argumentTyped = argument->getAsTyped(); + const TConstantUnion *argumentConstantValue = argumentTyped->getConstantValue(); + // Check the special case of constructing a matrix diagonal from a single scalar, + // or a vector from a single scalar. + if (argumentTyped->getType().getObjectSize() == 1u) + { + if (isMatrix()) + { + const uint8_t resultCols = getType().getCols(); + const uint8_t resultRows = getType().getRows(); + for (uint8_t col = 0; col < resultCols; ++col) + { + for (uint8_t row = 0; row < resultRows; ++row) + { + if (col == row) + { + constArray[resultIndex].cast(basicType, argumentConstantValue[0]); + } + else + { + constArray[resultIndex].setFConst(0.0f); + } + ++resultIndex; + } + } + } + else + { + while (resultIndex < resultSize) + { + constArray[resultIndex].cast(basicType, argumentConstantValue[0]); + ++resultIndex; + } + } + ASSERT(resultIndex == resultSize); + return constArray; + } + else if (isMatrix() && argumentTyped->isMatrix()) + { + // The special case of constructing a matrix from a matrix. + const uint8_t argumentCols = argumentTyped->getType().getCols(); + const uint8_t argumentRows = argumentTyped->getType().getRows(); + const uint8_t resultCols = getType().getCols(); + const uint8_t resultRows = getType().getRows(); + for (uint8_t col = 0; col < resultCols; ++col) + { + for (uint8_t row = 0; row < resultRows; ++row) + { + if (col < argumentCols && row < argumentRows) + { + constArray[resultIndex].cast( + basicType, argumentConstantValue[col * argumentRows + row]); + } + else if (col == row) + { + constArray[resultIndex].setFConst(1.0f); + } + else + { + constArray[resultIndex].setFConst(0.0f); + } + ++resultIndex; + } + } + ASSERT(resultIndex == resultSize); + return constArray; + } + } + + for (TIntermNode *argument : mArguments) + { + TIntermTyped *argumentTyped = argument->getAsTyped(); + size_t argumentSize = argumentTyped->getType().getObjectSize(); + const TConstantUnion *argumentConstantValue = argumentTyped->getConstantValue(); + for (size_t i = 0u; i < argumentSize; ++i) + { + if (resultIndex >= resultSize) + break; + constArray[resultIndex].cast(basicType, argumentConstantValue[i]); + ++resultIndex; + } + } + ASSERT(resultIndex == resultSize); + return constArray; +} + +bool TIntermAggregate::hasSideEffects() const +{ + if (getQualifier() == EvqConst) + { + return false; + } + + // If the function itself is known to have a side effect, the expression has a side effect. + const bool calledFunctionHasSideEffects = + mFunction != nullptr && !mFunction->isKnownToNotHaveSideEffects(); + + if (calledFunctionHasSideEffects) + { + return true; + } + + // Otherwise it only has a side effect if one of the arguments does. + for (TIntermNode *arg : mArguments) + { + if (arg->getAsTyped()->hasSideEffects()) + { + return true; + } + } + return false; +} + +void TIntermBlock::appendStatement(TIntermNode *statement) +{ + // Declaration nodes with no children can appear if it was an empty declaration or if all the + // declarators just added constants to the symbol table instead of generating code. We still + // need to add the declaration to the AST in that case because it might be relevant to the + // validity of switch/case. + if (statement != nullptr) + { + mStatements.push_back(statement); + } +} + +void TIntermBlock::insertStatement(size_t insertPosition, TIntermNode *statement) +{ + ASSERT(statement != nullptr); + mStatements.insert(mStatements.begin() + insertPosition, statement); +} + +void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator) +{ + ASSERT(declarator != nullptr); + ASSERT(declarator->getAsSymbolNode() != nullptr || + (declarator->getAsBinaryNode() != nullptr && + declarator->getAsBinaryNode()->getOp() == EOpInitialize)); + ASSERT(mDeclarators.empty() || + declarator->getType().sameNonArrayType(mDeclarators.back()->getAsTyped()->getType())); + mDeclarators.push_back(declarator); +} + +size_t TIntermTernary::getChildCount() const +{ + return 3; +} + +TIntermNode *TIntermTernary::getChildNode(size_t index) const +{ + ASSERT(index < 3); + if (index == 0) + { + return mCondition; + } + if (index == 1) + { + return mTrueExpression; + } + return mFalseExpression; +} + +bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); + REPLACE_IF_IS(mTrueExpression, TIntermTyped, original, replacement); + REPLACE_IF_IS(mFalseExpression, TIntermTyped, original, replacement); + return false; +} + +size_t TIntermIfElse::getChildCount() const +{ + return 1 + (mTrueBlock ? 1 : 0) + (mFalseBlock ? 1 : 0); +} + +TIntermNode *TIntermIfElse::getChildNode(size_t index) const +{ + if (index == 0) + { + return mCondition; + } + if (mTrueBlock && index == 1) + { + return mTrueBlock; + } + return mFalseBlock; +} + +bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); + REPLACE_IF_IS(mTrueBlock, TIntermBlock, original, replacement); + REPLACE_IF_IS(mFalseBlock, TIntermBlock, original, replacement); + return false; +} + +size_t TIntermSwitch::getChildCount() const +{ + return 2; +} + +TIntermNode *TIntermSwitch::getChildNode(size_t index) const +{ + ASSERT(index < 2); + if (index == 0) + { + return mInit; + } + return mStatementList; +} + +bool TIntermSwitch::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mInit, TIntermTyped, original, replacement); + REPLACE_IF_IS(mStatementList, TIntermBlock, original, replacement); + ASSERT(mStatementList); + return false; +} + +TIntermCase::TIntermCase(const TIntermCase &node) : TIntermCase(node.mCondition->deepCopy()) {} + +size_t TIntermCase::getChildCount() const +{ + return (mCondition ? 1 : 0); +} + +TIntermNode *TIntermCase::getChildNode(size_t index) const +{ + ASSERT(index == 0); + ASSERT(mCondition); + return mCondition; +} + +bool TIntermCase::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); + return false; +} + +TIntermTyped::TIntermTyped() : mIsPrecise(false) {} +TIntermTyped::TIntermTyped(const TIntermTyped &node) : TIntermTyped() +{ + // Copy constructor is disallowed for TIntermNode in order to disallow it for subclasses that + // don't explicitly allow it, so normal TIntermNode constructor is used to construct the copy. + // We need to manually copy any fields of TIntermNode. + mLine = node.mLine; + + // Once deteremined, the tree is not expected to transform. + ASSERT(!mIsPrecise); +} + +bool TIntermTyped::hasConstantValue() const +{ + return false; +} + +bool TIntermTyped::isConstantNullValue() const +{ + return false; +} + +const TConstantUnion *TIntermTyped::getConstantValue() const +{ + return nullptr; +} + +TPrecision TIntermTyped::derivePrecision() const +{ + UNREACHABLE(); + return EbpUndefined; +} + +void TIntermTyped::propagatePrecision(TPrecision precision) +{ + UNREACHABLE(); +} + +TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) + : TIntermExpression(node) +{ + mUnionArrayPointer = node.mUnionArrayPointer; +} + +TIntermFunctionPrototype::TIntermFunctionPrototype(const TFunction *function) + : TIntermTyped(), mFunction(function) +{ + ASSERT(mFunction->symbolType() != SymbolType::Empty); +} + +const TType &TIntermFunctionPrototype::getType() const +{ + return mFunction->getReturnType(); +} + +TIntermAggregate::TIntermAggregate(const TIntermAggregate &node) + : TIntermOperator(node), + mUseEmulatedFunction(node.mUseEmulatedFunction), + mFunction(node.mFunction) +{ + for (TIntermNode *arg : node.mArguments) + { + TIntermTyped *typedArg = arg->getAsTyped(); + ASSERT(typedArg != nullptr); + TIntermTyped *argCopy = typedArg->deepCopy(); + mArguments.push_back(argCopy); + } +} + +TIntermAggregate *TIntermAggregate::shallowCopy() const +{ + TIntermSequence copySeq; + copySeq.insert(copySeq.begin(), getSequence()->begin(), getSequence()->end()); + TIntermAggregate *copyNode = new TIntermAggregate(mFunction, mType, mOp, ©Seq); + copyNode->setLine(mLine); + return copyNode; +} + +TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermExpression(node) +{ + TIntermTyped *operandCopy = node.mOperand->deepCopy(); + ASSERT(operandCopy != nullptr); + mOperand = operandCopy; + mSwizzleOffsets = node.mSwizzleOffsets; + mHasFoldedDuplicateOffsets = node.mHasFoldedDuplicateOffsets; +} + +TIntermBinary::TIntermBinary(const TIntermBinary &node) : TIntermOperator(node) +{ + TIntermTyped *leftCopy = node.mLeft->deepCopy(); + TIntermTyped *rightCopy = node.mRight->deepCopy(); + ASSERT(leftCopy != nullptr && rightCopy != nullptr); + mLeft = leftCopy; + mRight = rightCopy; +} + +TIntermUnary::TIntermUnary(const TIntermUnary &node) + : TIntermOperator(node), + mUseEmulatedFunction(node.mUseEmulatedFunction), + mFunction(node.mFunction) +{ + TIntermTyped *operandCopy = node.mOperand->deepCopy(); + ASSERT(operandCopy != nullptr); + mOperand = operandCopy; +} + +TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermExpression(node) +{ + TIntermTyped *conditionCopy = node.mCondition->deepCopy(); + TIntermTyped *trueCopy = node.mTrueExpression->deepCopy(); + TIntermTyped *falseCopy = node.mFalseExpression->deepCopy(); + ASSERT(conditionCopy != nullptr && trueCopy != nullptr && falseCopy != nullptr); + mCondition = conditionCopy; + mTrueExpression = trueCopy; + mFalseExpression = falseCopy; +} + +bool TIntermOperator::isAssignment() const +{ + return IsAssignment(mOp); +} + +bool TIntermOperator::isMultiplication() const +{ + switch (mOp) + { + case EOpMul: + case EOpMatrixTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpVectorTimesMatrix: + case EOpVectorTimesScalar: + return true; + default: + return false; + } +} + +bool TIntermOperator::isConstructor() const +{ + return (mOp == EOpConstruct); +} + +bool TIntermOperator::isFunctionCall() const +{ + switch (mOp) + { + case EOpCallFunctionInAST: + case EOpCallInternalRawFunction: + return true; + default: + return false; + } +} + +TOperator TIntermBinary::GetMulOpBasedOnOperands(const TType &left, const TType &right) +{ + if (left.isMatrix()) + { + if (right.isMatrix()) + { + return EOpMatrixTimesMatrix; + } + else + { + if (right.isVector()) + { + return EOpMatrixTimesVector; + } + else + { + return EOpMatrixTimesScalar; + } + } + } + else + { + if (right.isMatrix()) + { + if (left.isVector()) + { + return EOpVectorTimesMatrix; + } + else + { + return EOpMatrixTimesScalar; + } + } + else + { + // Neither operand is a matrix. + if (left.isVector() == right.isVector()) + { + // Leave as component product. + return EOpMul; + } + else + { + return EOpVectorTimesScalar; + } + } + } +} + +TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const TType &right) +{ + if (left.isMatrix()) + { + if (right.isMatrix()) + { + return EOpMatrixTimesMatrixAssign; + } + else + { + // right should be scalar, but this may not be validated yet. + return EOpMatrixTimesScalarAssign; + } + } + else + { + if (right.isMatrix()) + { + // Left should be a vector, but this may not be validated yet. + return EOpVectorTimesMatrixAssign; + } + else + { + // Neither operand is a matrix. + if (left.isVector() == right.isVector()) + { + // Leave as component product. + return EOpMulAssign; + } + else + { + // left should be vector and right should be scalar, but this may not be validated + // yet. + return EOpVectorTimesScalarAssign; + } + } + } +} + +// +// Make sure the type of a unary operator is appropriate for its +// combination of operation and operand type. +// +void TIntermUnary::promote() +{ + if (mOp == EOpArrayLength) + { + // Special case: the qualifier of .length() doesn't depend on the operand qualifier. + setType(TType(EbtInt, EbpHigh, EvqConst)); + return; + } + + TQualifier resultQualifier = EvqTemporary; + if (mOperand->getQualifier() == EvqConst) + resultQualifier = EvqConst; + + TType resultType = mOperand->getType(); + resultType.setQualifier(resultQualifier); + + // Result is an intermediate value, so make sure it's identified as such. + resultType.setInterfaceBlock(nullptr); + + // Override type properties for special built-ins. Precision is determined later by + // |derivePrecision|. + switch (mOp) + { + case EOpFloatBitsToInt: + resultType.setBasicType(EbtInt); + break; + case EOpFloatBitsToUint: + resultType.setBasicType(EbtUInt); + break; + case EOpIntBitsToFloat: + case EOpUintBitsToFloat: + resultType.setBasicType(EbtFloat); + break; + case EOpPackSnorm2x16: + case EOpPackUnorm2x16: + case EOpPackHalf2x16: + case EOpPackUnorm4x8: + case EOpPackSnorm4x8: + resultType.setBasicType(EbtUInt); + resultType.setPrimarySize(1); + break; + case EOpUnpackSnorm2x16: + case EOpUnpackUnorm2x16: + case EOpUnpackHalf2x16: + resultType.setBasicType(EbtFloat); + resultType.setPrimarySize(2); + break; + case EOpUnpackUnorm4x8: + case EOpUnpackSnorm4x8: + resultType.setBasicType(EbtFloat); + resultType.setPrimarySize(4); + break; + case EOpAny: + case EOpAll: + resultType.setBasicType(EbtBool); + resultType.setPrimarySize(1); + break; + case EOpLength: + case EOpDeterminant: + resultType.setBasicType(EbtFloat); + resultType.setPrimarySize(1); + resultType.setSecondarySize(1); + break; + case EOpTranspose: + ASSERT(resultType.getBasicType() == EbtFloat); + resultType.setPrimarySize(mOperand->getType().getRows()); + resultType.setSecondarySize(mOperand->getType().getCols()); + break; + case EOpIsinf: + case EOpIsnan: + resultType.setBasicType(EbtBool); + break; + case EOpBitCount: + case EOpFindLSB: + case EOpFindMSB: + resultType.setBasicType(EbtInt); + break; + default: + break; + } + + setType(resultType); + propagatePrecision(derivePrecision()); +} + +// Derive precision from children nodes +TPrecision TIntermUnary::derivePrecision() const +{ + // Unary operators generally derive their precision from their operand, except for a few + // built-ins where this is overriden. + switch (mOp) + { + case EOpArrayLength: + case EOpFloatBitsToInt: + case EOpFloatBitsToUint: + case EOpIntBitsToFloat: + case EOpUintBitsToFloat: + case EOpPackSnorm2x16: + case EOpPackUnorm2x16: + case EOpPackHalf2x16: + case EOpPackUnorm4x8: + case EOpPackSnorm4x8: + case EOpUnpackSnorm2x16: + case EOpUnpackUnorm2x16: + case EOpBitfieldReverse: + return EbpHigh; + case EOpUnpackHalf2x16: + case EOpUnpackUnorm4x8: + case EOpUnpackSnorm4x8: + return EbpMedium; + case EOpBitCount: + case EOpFindLSB: + case EOpFindMSB: + return EbpLow; + case EOpAny: + case EOpAll: + case EOpIsinf: + case EOpIsnan: + return EbpUndefined; + default: + return mOperand->getPrecision(); + } +} + +void TIntermUnary::propagatePrecision(TPrecision precision) +{ + mType.setPrecision(precision); + + // Generally precision of the operand and the precision of the result match. A few built-ins + // are exceptional. + switch (mOp) + { + case EOpArrayLength: + case EOpPackSnorm2x16: + case EOpPackUnorm2x16: + case EOpPackUnorm4x8: + case EOpPackSnorm4x8: + case EOpPackHalf2x16: + case EOpBitCount: + case EOpFindLSB: + case EOpFindMSB: + case EOpIsinf: + case EOpIsnan: + // Precision of result does not affect the operand in any way. + break; + case EOpFloatBitsToInt: + case EOpFloatBitsToUint: + case EOpIntBitsToFloat: + case EOpUintBitsToFloat: + case EOpUnpackSnorm2x16: + case EOpUnpackUnorm2x16: + case EOpUnpackUnorm4x8: + case EOpUnpackSnorm4x8: + case EOpUnpackHalf2x16: + case EOpBitfieldReverse: + PropagatePrecisionIfApplicable(mOperand, EbpHigh); + break; + default: + PropagatePrecisionIfApplicable(mOperand, precision); + } +} + +TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector &swizzleOffsets) + : TIntermExpression(TType(EbtFloat, EbpUndefined)), + mOperand(operand), + mSwizzleOffsets(swizzleOffsets), + mHasFoldedDuplicateOffsets(false) +{ + ASSERT(mOperand); + ASSERT(mOperand->getType().isVector()); + ASSERT(mSwizzleOffsets.size() <= 4); + promote(); +} + +TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function) + : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false), mFunction(function) +{ + ASSERT(mOperand); + ASSERT(!BuiltInGroup::IsBuiltIn(op) || (function != nullptr && function->getBuiltInOp() == op)); + promote(); +} + +TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right) + : TIntermOperator(op), mLeft(left), mRight(right) +{ + ASSERT(mLeft); + ASSERT(mRight); + promote(); +} + +TIntermBinary *TIntermBinary::CreateComma(TIntermTyped *left, + TIntermTyped *right, + int shaderVersion) +{ + TIntermBinary *node = new TIntermBinary(EOpComma, left, right); + node->getTypePointer()->setQualifier(GetCommaQualifier(shaderVersion, left, right)); + return node; +} + +TIntermGlobalQualifierDeclaration::TIntermGlobalQualifierDeclaration(TIntermSymbol *symbol, + bool isPrecise, + const TSourceLoc &line) + : TIntermNode(), mSymbol(symbol), mIsPrecise(isPrecise) +{ + ASSERT(symbol); + setLine(line); +} + +TIntermGlobalQualifierDeclaration::TIntermGlobalQualifierDeclaration( + const TIntermGlobalQualifierDeclaration &node) + : TIntermGlobalQualifierDeclaration(static_cast(node.mSymbol->deepCopy()), + node.mIsPrecise, + node.mLine) +{} + +TIntermTernary::TIntermTernary(TIntermTyped *cond, + TIntermTyped *trueExpression, + TIntermTyped *falseExpression) + : TIntermExpression(trueExpression->getType()), + mCondition(cond), + mTrueExpression(trueExpression), + mFalseExpression(falseExpression) +{ + ASSERT(mCondition); + ASSERT(mTrueExpression); + ASSERT(mFalseExpression); + getTypePointer()->setQualifier( + TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression)); + + propagatePrecision(derivePrecision()); +} + +TIntermLoop::TIntermLoop(TLoopType type, + TIntermNode *init, + TIntermTyped *cond, + TIntermTyped *expr, + TIntermBlock *body) + : mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body) +{ + // Declaration nodes with no children can appear if all the declarators just added constants to + // the symbol table instead of generating code. They're no-ops so don't add them to the tree. + if (mInit && mInit->getAsDeclarationNode() && + mInit->getAsDeclarationNode()->getSequence()->empty()) + { + mInit = nullptr; + } +} + +TIntermLoop::TIntermLoop(const TIntermLoop &node) + : TIntermLoop(node.mType, + node.mInit ? node.mInit->deepCopy() : nullptr, + node.mCond ? node.mCond->deepCopy() : nullptr, + node.mExpr ? node.mExpr->deepCopy() : nullptr, + node.mBody ? node.mBody->deepCopy() : nullptr) +{} + +TIntermIfElse::TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB) + : TIntermNode(), mCondition(cond), mTrueBlock(trueB), mFalseBlock(falseB) +{ + ASSERT(mCondition); + // Prune empty false blocks so that there won't be unnecessary operations done on it. + if (mFalseBlock && mFalseBlock->getSequence()->empty()) + { + mFalseBlock = nullptr; + } +} + +TIntermIfElse::TIntermIfElse(const TIntermIfElse &node) + : TIntermIfElse(node.mCondition->deepCopy(), + node.mTrueBlock->deepCopy(), + node.mFalseBlock ? node.mFalseBlock->deepCopy() : nullptr) +{} + +TIntermSwitch::TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList) + : TIntermNode(), mInit(init), mStatementList(statementList) +{ + ASSERT(mInit); + ASSERT(mStatementList); +} + +TIntermSwitch::TIntermSwitch(const TIntermSwitch &node) + : TIntermSwitch(node.mInit->deepCopy(), node.mStatementList->deepCopy()) +{} + +void TIntermSwitch::setStatementList(TIntermBlock *statementList) +{ + ASSERT(statementList); + mStatementList = statementList; +} + +// static +TQualifier TIntermTernary::DetermineQualifier(TIntermTyped *cond, + TIntermTyped *trueExpression, + TIntermTyped *falseExpression) +{ + if (cond->getQualifier() == EvqConst && trueExpression->getQualifier() == EvqConst && + falseExpression->getQualifier() == EvqConst) + { + return EvqConst; + } + return EvqTemporary; +} + +// Derive precision from children nodes +TPrecision TIntermTernary::derivePrecision() const +{ + return GetHigherPrecision(mTrueExpression->getPrecision(), mFalseExpression->getPrecision()); +} + +void TIntermTernary::propagatePrecision(TPrecision precision) +{ + mType.setPrecision(precision); + + PropagatePrecisionIfApplicable(mTrueExpression, precision); + PropagatePrecisionIfApplicable(mFalseExpression, precision); +} + +TIntermTyped *TIntermTernary::fold(TDiagnostics * /* diagnostics */) +{ + if (mCondition->getAsConstantUnion()) + { + if (mCondition->getAsConstantUnion()->getBConst(0)) + { + return mTrueExpression; + } + else + { + return mFalseExpression; + } + } + return this; +} + +void TIntermSwizzle::promote() +{ + TQualifier resultQualifier = EvqTemporary; + if (mOperand->getQualifier() == EvqConst) + resultQualifier = EvqConst; + + size_t numFields = mSwizzleOffsets.size(); + setType(TType(mOperand->getBasicType(), EbpUndefined, resultQualifier, + static_cast(numFields))); + propagatePrecision(derivePrecision()); +} + +// Derive precision from children nodes +TPrecision TIntermSwizzle::derivePrecision() const +{ + return mOperand->getPrecision(); +} + +void TIntermSwizzle::propagatePrecision(TPrecision precision) +{ + mType.setPrecision(precision); + + PropagatePrecisionIfApplicable(mOperand, precision); +} + +bool TIntermSwizzle::hasDuplicateOffsets() const +{ + if (mHasFoldedDuplicateOffsets) + { + return true; + } + int offsetCount[4] = {0u, 0u, 0u, 0u}; + for (const auto offset : mSwizzleOffsets) + { + offsetCount[offset]++; + if (offsetCount[offset] > 1) + { + return true; + } + } + return false; +} + +void TIntermSwizzle::setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets) +{ + mHasFoldedDuplicateOffsets = hasFoldedDuplicateOffsets; +} + +bool TIntermSwizzle::offsetsMatch(int offset) const +{ + return mSwizzleOffsets.size() == 1 && mSwizzleOffsets[0] == offset; +} + +void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const +{ + for (const int offset : mSwizzleOffsets) + { + switch (offset) + { + case 0: + *out << "x"; + break; + case 1: + *out << "y"; + break; + case 2: + *out << "z"; + break; + case 3: + *out << "w"; + break; + default: + UNREACHABLE(); + } + } +} + +TQualifier TIntermBinary::GetCommaQualifier(int shaderVersion, + const TIntermTyped *left, + const TIntermTyped *right) +{ + // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression. + if (shaderVersion >= 300 || left->getQualifier() != EvqConst || + right->getQualifier() != EvqConst) + { + return EvqTemporary; + } + return EvqConst; +} + +// Establishes the type of the result of the binary operation. +void TIntermBinary::promote() +{ + ASSERT(!isMultiplication() || + mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType())); + + // Comma is handled as a special case. Note that the comma node qualifier depends on the shader + // version and so is not being set here. + if (mOp == EOpComma) + { + setType(mRight->getType()); + return; + } + + // Base assumption: just make the type the same as the left + // operand. Then only deviations from this need be coded. + setType(mLeft->getType()); + + TQualifier resultQualifier = EvqConst; + // Binary operations results in temporary variables unless both + // operands are const. If initializing a specialization constant, make the declarator also + // EvqSpecConst. + const bool isSpecConstInit = mOp == EOpInitialize && mLeft->getQualifier() == EvqSpecConst; + const bool isEitherNonConst = + mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst; + if (!isSpecConstInit && isEitherNonConst) + { + resultQualifier = EvqTemporary; + getTypePointer()->setQualifier(EvqTemporary); + } + + // Result is an intermediate value, so make sure it's identified as such. That's not true for + // interface block arrays being indexed. + if (mOp != EOpIndexDirect && mOp != EOpIndexIndirect) + { + getTypePointer()->setInterfaceBlock(nullptr); + } + + // Handle indexing ops. + switch (mOp) + { + case EOpIndexDirect: + case EOpIndexIndirect: + if (mLeft->isArray()) + { + mType.toArrayElementType(); + } + else if (mLeft->isMatrix()) + { + mType.toMatrixColumnType(); + } + else if (mLeft->isVector()) + { + mType.toComponentType(); + } + else + { + UNREACHABLE(); + } + return; + case EOpIndexDirectStruct: + { + const TFieldList &fields = mLeft->getType().getStruct()->fields(); + const int fieldIndex = mRight->getAsConstantUnion()->getIConst(0); + setType(*fields[fieldIndex]->type()); + getTypePointer()->setQualifier(resultQualifier); + return; + } + case EOpIndexDirectInterfaceBlock: + { + const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields(); + const int fieldIndex = mRight->getAsConstantUnion()->getIConst(0); + setType(*fields[fieldIndex]->type()); + getTypePointer()->setQualifier(resultQualifier); + return; + } + default: + break; + } + + ASSERT(mLeft->isArray() == mRight->isArray()); + + const uint8_t nominalSize = std::max(mLeft->getNominalSize(), mRight->getNominalSize()); + + switch (mOp) + { + case EOpMul: + break; + case EOpMatrixTimesScalar: + if (mRight->isMatrix()) + { + getTypePointer()->setPrimarySize(mRight->getCols()); + getTypePointer()->setSecondarySize(mRight->getRows()); + } + break; + case EOpMatrixTimesVector: + getTypePointer()->setPrimarySize(mLeft->getRows()); + getTypePointer()->setSecondarySize(1); + break; + case EOpMatrixTimesMatrix: + getTypePointer()->setPrimarySize(mRight->getCols()); + getTypePointer()->setSecondarySize(mLeft->getRows()); + break; + case EOpVectorTimesScalar: + getTypePointer()->setPrimarySize(nominalSize); + break; + case EOpVectorTimesMatrix: + getTypePointer()->setPrimarySize(mRight->getCols()); + ASSERT(getType().getSecondarySize() == 1); + break; + case EOpMulAssign: + case EOpVectorTimesScalarAssign: + case EOpVectorTimesMatrixAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + ASSERT(mOp == GetMulAssignOpBasedOnOperands(mLeft->getType(), mRight->getType())); + break; + case EOpAssign: + case EOpInitialize: + ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) && + (mLeft->getSecondarySize() == mRight->getSecondarySize())); + break; + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpIMod: + case EOpBitShiftLeft: + case EOpBitShiftRight: + case EOpBitwiseAnd: + case EOpBitwiseXor: + case EOpBitwiseOr: + case EOpAddAssign: + case EOpSubAssign: + case EOpDivAssign: + case EOpIModAssign: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: + { + ASSERT(!mLeft->isArray() && !mRight->isArray()); + const uint8_t secondarySize = + std::max(mLeft->getSecondarySize(), mRight->getSecondarySize()); + getTypePointer()->setPrimarySize(nominalSize); + getTypePointer()->setSecondarySize(secondarySize); + break; + } + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) && + (mLeft->getSecondarySize() == mRight->getSecondarySize())); + setType(TType(EbtBool, EbpUndefined, resultQualifier)); + break; + + // + // And and Or operate on conditionals + // + case EOpLogicalAnd: + case EOpLogicalXor: + case EOpLogicalOr: + ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool); + break; + + case EOpIndexDirect: + case EOpIndexIndirect: + case EOpIndexDirectInterfaceBlock: + case EOpIndexDirectStruct: + // These ops should be already fully handled. + UNREACHABLE(); + break; + default: + UNREACHABLE(); + break; + } + + propagatePrecision(derivePrecision()); +} + +// Derive precision from children nodes +TPrecision TIntermBinary::derivePrecision() const +{ + // Assignments use the type and precision of the lvalue-expression + // GLSL ES spec section 5.8: Assignments + // "The assignment operator stores the value of rvalue-expression into the l-value and returns + // an r-value with the type and precision of lvalue-expression." + if (IsAssignment(mOp)) + { + return mLeft->getPrecision(); + } + + const TPrecision higherPrecision = + GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision()); + + switch (mOp) + { + case EOpComma: + // Comma takes the right node's value. + return mRight->getPrecision(); + + case EOpIndexDirect: + case EOpIndexIndirect: + case EOpBitShiftLeft: + case EOpBitShiftRight: + // When indexing an array, the precision of the array is preserved (which is the left + // node). + // For shift operations, the precision is derived from the expression being shifted + // (which is also the left node). + return mLeft->getPrecision(); + + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: + { + // When selecting the field of a block, the precision is taken from the field's + // declaration. + const TFieldList &fields = mOp == EOpIndexDirectStruct + ? mLeft->getType().getStruct()->fields() + : mLeft->getType().getInterfaceBlock()->fields(); + const int fieldIndex = mRight->getAsConstantUnion()->getIConst(0); + return fields[fieldIndex]->type()->getPrecision(); + } + + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + case EOpLogicalAnd: + case EOpLogicalXor: + case EOpLogicalOr: + // No precision specified on bool results. + return EbpUndefined; + + default: + // All other operations are evaluated at the higher of the two operands' precisions. + return higherPrecision; + } +} + +void TIntermBinary::propagatePrecision(TPrecision precision) +{ + getTypePointer()->setPrecision(precision); + + if (mOp != EOpComma) + { + PropagatePrecisionIfApplicable(mLeft, precision); + } + + if (mOp != EOpIndexDirect && mOp != EOpIndexIndirect && mOp != EOpIndexDirectStruct && + mOp != EOpIndexDirectInterfaceBlock) + { + PropagatePrecisionIfApplicable(mRight, precision); + } + + // For indices, always apply highp. This is purely for the purpose of making sure constant and + // constructor nodes are also given a precision, so if they are hoisted to a temp variable, + // there would be a precision to apply to that variable. + if (mOp == EOpIndexDirect || mOp == EOpIndexIndirect) + { + PropagatePrecisionIfApplicable(mRight, EbpHigh); + } +} + +bool TIntermConstantUnion::hasConstantValue() const +{ + return true; +} + +bool TIntermConstantUnion::isConstantNullValue() const +{ + const size_t size = mType.getObjectSize(); + for (size_t index = 0; index < size; ++index) + { + if (!mUnionArrayPointer[index].isZero()) + { + return false; + } + } + return true; +} + +const TConstantUnion *TIntermConstantUnion::getConstantValue() const +{ + return mUnionArrayPointer; +} + +const TConstantUnion *TIntermConstantUnion::FoldIndexing(const TType &type, + const TConstantUnion *constArray, + int index) +{ + if (type.isArray()) + { + ASSERT(index < static_cast(type.getOutermostArraySize())); + TType arrayElementType(type); + arrayElementType.toArrayElementType(); + size_t arrayElementSize = arrayElementType.getObjectSize(); + return &constArray[arrayElementSize * index]; + } + else if (type.isMatrix()) + { + ASSERT(index < type.getCols()); + const uint8_t size = type.getRows(); + return &constArray[size * index]; + } + else if (type.isVector()) + { + ASSERT(index < type.getNominalSize()); + return &constArray[index]; + } + else + { + UNREACHABLE(); + return nullptr; + } +} + +TIntermTyped *TIntermSwizzle::fold(TDiagnostics * /* diagnostics */) +{ + TIntermSwizzle *operandSwizzle = mOperand->getAsSwizzleNode(); + if (operandSwizzle) + { + // We need to fold the two swizzles into one, so that repeated swizzling can't cause stack + // overflow in ParseContext::checkCanBeLValue(). + bool hadDuplicateOffsets = operandSwizzle->hasDuplicateOffsets(); + TVector foldedOffsets; + for (int offset : mSwizzleOffsets) + { + // Offset should already be validated. + ASSERT(static_cast(offset) < operandSwizzle->mSwizzleOffsets.size()); + foldedOffsets.push_back(operandSwizzle->mSwizzleOffsets[offset]); + } + operandSwizzle->mSwizzleOffsets = foldedOffsets; + operandSwizzle->setType(getType()); + operandSwizzle->setHasFoldedDuplicateOffsets(hadDuplicateOffsets); + return operandSwizzle; + } + TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion(); + if (operandConstant == nullptr) + { + return this; + } + + TConstantUnion *constArray = new TConstantUnion[mSwizzleOffsets.size()]; + for (size_t i = 0; i < mSwizzleOffsets.size(); ++i) + { + constArray[i] = *TIntermConstantUnion::FoldIndexing( + operandConstant->getType(), operandConstant->getConstantValue(), mSwizzleOffsets.at(i)); + } + return CreateFoldedNode(constArray, this); +} + +TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics) +{ + const TConstantUnion *rightConstant = mRight->getConstantValue(); + switch (mOp) + { + case EOpComma: + { + if (mLeft->hasSideEffects()) + { + return this; + } + return mRight; + } + case EOpIndexDirect: + case EOpIndexDirectStruct: + { + if (rightConstant == nullptr) + { + return this; + } + size_t index = static_cast(rightConstant->getIConst()); + TIntermAggregate *leftAggregate = mLeft->getAsAggregate(); + if (leftAggregate && leftAggregate->isConstructor() && leftAggregate->isArray() && + !leftAggregate->hasSideEffects()) + { + ASSERT(index < leftAggregate->getSequence()->size()); + // This transformation can't add complexity as we're eliminating the constructor + // entirely. + return leftAggregate->getSequence()->at(index)->getAsTyped(); + } + + // If the indexed value is already a constant union, we can't increase duplication of + // data by folding the indexing. Also fold the node in case it's generally beneficial to + // replace this type of node with a constant union even if that would mean duplicating + // data. + if (mLeft->getAsConstantUnion() || getType().canReplaceWithConstantUnion()) + { + const TConstantUnion *constantValue = getConstantValue(); + if (constantValue == nullptr) + { + return this; + } + return CreateFoldedNode(constantValue, this); + } + return this; + } + case EOpIndexIndirect: + case EOpIndexDirectInterfaceBlock: + case EOpInitialize: + // Can never be constant folded. + return this; + default: + { + if (rightConstant == nullptr) + { + return this; + } + const TConstantUnion *leftConstant = mLeft->getConstantValue(); + if (leftConstant == nullptr) + { + return this; + } + const TConstantUnion *constArray = + TIntermConstantUnion::FoldBinary(mOp, leftConstant, mLeft->getType(), rightConstant, + mRight->getType(), diagnostics, mLeft->getLine()); + if (!constArray) + { + return this; + } + return CreateFoldedNode(constArray, this); + } + } +} + +bool TIntermBinary::hasConstantValue() const +{ + switch (mOp) + { + case EOpIndexDirect: + case EOpIndexDirectStruct: + { + if (mLeft->hasConstantValue() && mRight->hasConstantValue()) + { + return true; + } + break; + } + default: + break; + } + return false; +} + +const TConstantUnion *TIntermBinary::getConstantValue() const +{ + if (!hasConstantValue()) + { + return nullptr; + } + + const TConstantUnion *leftConstantValue = mLeft->getConstantValue(); + int index = mRight->getConstantValue()->getIConst(); + const TConstantUnion *constIndexingResult = nullptr; + if (mOp == EOpIndexDirect) + { + constIndexingResult = + TIntermConstantUnion::FoldIndexing(mLeft->getType(), leftConstantValue, index); + } + else + { + ASSERT(mOp == EOpIndexDirectStruct); + const TFieldList &fields = mLeft->getType().getStruct()->fields(); + + size_t previousFieldsSize = 0; + for (int i = 0; i < index; ++i) + { + previousFieldsSize += fields[i]->type()->getObjectSize(); + } + constIndexingResult = leftConstantValue + previousFieldsSize; + } + return constIndexingResult; +} + +const ImmutableString &TIntermBinary::getIndexStructFieldName() const +{ + ASSERT(mOp == EOpIndexDirectStruct); + + const TType &lhsType = mLeft->getType(); + const TStructure *structure = lhsType.getStruct(); + const int index = mRight->getAsConstantUnion()->getIConst(0); + + return structure->fields()[index]->name(); +} + +TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics) +{ + TConstantUnion *constArray = nullptr; + + if (mOp == EOpArrayLength) + { + // The size of runtime-sized arrays may only be determined at runtime. + if (mOperand->hasSideEffects() || mOperand->getType().isUnsizedArray()) + { + return this; + } + constArray = new TConstantUnion[1]; + constArray->setIConst(mOperand->getOutermostArraySize()); + } + else + { + TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion(); + if (operandConstant == nullptr) + { + return this; + } + + switch (mOp) + { + case EOpAny: + case EOpAll: + case EOpLength: + case EOpTranspose: + case EOpDeterminant: + case EOpInverse: + case EOpPackSnorm2x16: + case EOpUnpackSnorm2x16: + case EOpPackUnorm2x16: + case EOpUnpackUnorm2x16: + case EOpPackHalf2x16: + case EOpUnpackHalf2x16: + case EOpPackUnorm4x8: + case EOpPackSnorm4x8: + case EOpUnpackUnorm4x8: + case EOpUnpackSnorm4x8: + constArray = operandConstant->foldUnaryNonComponentWise(mOp); + break; + default: + constArray = operandConstant->foldUnaryComponentWise(mOp, mFunction, diagnostics); + break; + } + } + if (constArray == nullptr) + { + return this; + } + return CreateFoldedNode(constArray, this); +} + +TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics) +{ + // Make sure that all params are constant before actual constant folding. + for (auto *param : *getSequence()) + { + if (param->getAsConstantUnion() == nullptr) + { + return this; + } + } + const TConstantUnion *constArray = nullptr; + if (isConstructor()) + { + if (mType.canReplaceWithConstantUnion()) + { + constArray = getConstantValue(); + if (constArray && mType.getBasicType() == EbtUInt) + { + // Check if we converted a negative float to uint and issue a warning in that case. + size_t sizeRemaining = mType.getObjectSize(); + for (TIntermNode *arg : mArguments) + { + TIntermTyped *typedArg = arg->getAsTyped(); + if (typedArg->getBasicType() == EbtFloat) + { + const TConstantUnion *argValue = typedArg->getConstantValue(); + size_t castSize = + std::min(typedArg->getType().getObjectSize(), sizeRemaining); + for (size_t i = 0; i < castSize; ++i) + { + if (argValue[i].getFConst() < 0.0f) + { + // ESSL 3.00.6 section 5.4.1. + diagnostics->warning( + mLine, "casting a negative float to uint is undefined", + mType.getBuiltInTypeNameString()); + } + } + } + sizeRemaining -= typedArg->getType().getObjectSize(); + } + } + } + } + else if (CanFoldAggregateBuiltInOp(mOp)) + { + constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics); + } + if (constArray == nullptr) + { + return this; + } + return CreateFoldedNode(constArray, this); +} + +// +// The fold functions see if an operation on a constant can be done in place, +// without generating run-time code. +// +// Returns the constant value to keep using or nullptr. +// +const TConstantUnion *TIntermConstantUnion::FoldBinary(TOperator op, + const TConstantUnion *leftArray, + const TType &leftType, + const TConstantUnion *rightArray, + const TType &rightType, + TDiagnostics *diagnostics, + const TSourceLoc &line) +{ + ASSERT(leftArray && rightArray); + + size_t objectSize = leftType.getObjectSize(); + + // for a case like float f = vec4(2, 3, 4, 5) + 1.2; + if (rightType.getObjectSize() == 1 && objectSize > 1) + { + rightArray = Vectorize(*rightArray, objectSize); + } + else if (rightType.getObjectSize() > 1 && objectSize == 1) + { + // for a case like float f = 1.2 + vec4(2, 3, 4, 5); + leftArray = Vectorize(*leftArray, rightType.getObjectSize()); + objectSize = rightType.getObjectSize(); + } + + TConstantUnion *resultArray = nullptr; + + switch (op) + { + case EOpAdd: + resultArray = new TConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + resultArray[i] = + TConstantUnion::add(leftArray[i], rightArray[i], diagnostics, line); + break; + case EOpSub: + resultArray = new TConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + resultArray[i] = + TConstantUnion::sub(leftArray[i], rightArray[i], diagnostics, line); + break; + + case EOpMul: + case EOpVectorTimesScalar: + case EOpMatrixTimesScalar: + resultArray = new TConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + resultArray[i] = + TConstantUnion::mul(leftArray[i], rightArray[i], diagnostics, line); + break; + + case EOpMatrixTimesMatrix: + { + // TODO(jmadll): This code should check for overflows. + ASSERT(leftType.getBasicType() == EbtFloat && rightType.getBasicType() == EbtFloat); + + const uint8_t leftCols = leftType.getCols(); + const uint8_t leftRows = leftType.getRows(); + const uint8_t rightCols = rightType.getCols(); + const uint8_t rightRows = rightType.getRows(); + const uint8_t resultCols = rightCols; + const uint8_t resultRows = leftRows; + + resultArray = new TConstantUnion[resultCols * resultRows]; + for (uint8_t row = 0; row < resultRows; row++) + { + for (uint8_t column = 0; column < resultCols; column++) + { + resultArray[resultRows * column + row].setFConst(0.0f); + for (uint8_t i = 0; i < leftCols; i++) + { + resultArray[resultRows * column + row].setFConst( + resultArray[resultRows * column + row].getFConst() + + leftArray[i * leftRows + row].getFConst() * + rightArray[column * rightRows + i].getFConst()); + } + } + } + } + break; + + case EOpDiv: + case EOpIMod: + { + resultArray = new TConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + if (IsFloatDivision(leftType.getBasicType(), rightType.getBasicType())) + { + // Float division requested, possibly with implicit conversion + ASSERT(op == EOpDiv); + float dividend = leftArray[i].getFConst(); + float divisor = rightArray[i].getFConst(); + + if (divisor == 0.0f) + { + if (dividend == 0.0f) + { + diagnostics->warning(line, + "Zero divided by zero during constant " + "folding generated NaN", + "/"); + resultArray[i].setFConst(std::numeric_limits::quiet_NaN()); + } + else + { + diagnostics->warning(line, "Divide by zero during constant folding", + "/"); + bool negativeResult = std::signbit(dividend) != std::signbit(divisor); + resultArray[i].setFConst(negativeResult + ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity()); + } + } + else if (gl::isInf(dividend) && gl::isInf(divisor)) + { + diagnostics->warning(line, + "Infinity divided by infinity during constant " + "folding generated NaN", + "/"); + resultArray[i].setFConst(std::numeric_limits::quiet_NaN()); + } + else + { + float result = dividend / divisor; + if (!gl::isInf(dividend) && gl::isInf(result)) + { + diagnostics->warning( + line, "Constant folded division overflowed to infinity", "/"); + } + resultArray[i].setFConst(result); + } + } + else + { + // Types are either both int or both uint + switch (leftType.getBasicType()) + { + case EbtInt: + { + if (rightArray[i] == 0) + { + diagnostics->warning( + line, "Divide by zero error during constant folding", "/"); + resultArray[i].setIConst(INT_MAX); + } + else + { + int lhs = leftArray[i].getIConst(); + int divisor = rightArray[i].getIConst(); + if (op == EOpDiv) + { + // Check for the special case where the minimum + // representable number is divided by -1. If left alone this + // leads to integer overflow in C++. ESSL 3.00.6 + // section 4.1.3 Integers: "However, for the case where the + // minimum representable value is divided by -1, it is + // allowed to return either the minimum representable value + // or the maximum representable value." + if (lhs == -0x7fffffff - 1 && divisor == -1) + { + resultArray[i].setIConst(0x7fffffff); + } + else + { + resultArray[i].setIConst(lhs / divisor); + } + } + else + { + ASSERT(op == EOpIMod); + if (lhs < 0 || divisor < 0) + { + // ESSL 3.00.6 section 5.9: Results of modulus are + // undefined when either one of the operands is + // negative. + diagnostics->warning(line, + "Negative modulus operator operand " + "encountered during constant folding. " + "Results are undefined.", + "%"); + resultArray[i].setIConst(0); + } + else + { + resultArray[i].setIConst(lhs % divisor); + } + } + } + break; + } + case EbtUInt: + { + if (rightArray[i] == 0) + { + diagnostics->warning( + line, "Divide by zero error during constant folding", "/"); + resultArray[i].setUConst(UINT_MAX); + } + else + { + if (op == EOpDiv) + { + resultArray[i].setUConst(leftArray[i].getUConst() / + rightArray[i].getUConst()); + } + else + { + ASSERT(op == EOpIMod); + resultArray[i].setUConst(leftArray[i].getUConst() % + rightArray[i].getUConst()); + } + } + break; + } + default: + UNREACHABLE(); + return nullptr; + } + } + } + } + break; + + case EOpMatrixTimesVector: + { + // TODO(jmadll): This code should check for overflows. + ASSERT(rightType.getBasicType() == EbtFloat); + + const uint8_t matrixCols = leftType.getCols(); + const uint8_t matrixRows = leftType.getRows(); + + resultArray = new TConstantUnion[matrixRows]; + + for (uint8_t matrixRow = 0; matrixRow < matrixRows; matrixRow++) + { + resultArray[matrixRow].setFConst(0.0f); + for (uint8_t col = 0; col < matrixCols; col++) + { + resultArray[matrixRow].setFConst( + resultArray[matrixRow].getFConst() + + leftArray[col * matrixRows + matrixRow].getFConst() * + rightArray[col].getFConst()); + } + } + } + break; + + case EOpVectorTimesMatrix: + { + // TODO(jmadll): This code should check for overflows. + ASSERT(leftType.getBasicType() == EbtFloat); + + const uint8_t matrixCols = rightType.getCols(); + const uint8_t matrixRows = rightType.getRows(); + + resultArray = new TConstantUnion[matrixCols]; + + for (uint8_t matrixCol = 0; matrixCol < matrixCols; matrixCol++) + { + resultArray[matrixCol].setFConst(0.0f); + for (uint8_t matrixRow = 0; matrixRow < matrixRows; matrixRow++) + { + resultArray[matrixCol].setFConst( + resultArray[matrixCol].getFConst() + + leftArray[matrixRow].getFConst() * + rightArray[matrixCol * matrixRows + matrixRow].getFConst()); + } + } + } + break; + + case EOpLogicalAnd: + { + resultArray = new TConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + resultArray[i] = leftArray[i] && rightArray[i]; + } + } + break; + + case EOpLogicalOr: + { + resultArray = new TConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + resultArray[i] = leftArray[i] || rightArray[i]; + } + } + break; + + case EOpLogicalXor: + { + ASSERT(leftType.getBasicType() == EbtBool); + resultArray = new TConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + resultArray[i].setBConst(leftArray[i] != rightArray[i]); + } + } + break; + + case EOpBitwiseAnd: + resultArray = new TConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + resultArray[i] = leftArray[i] & rightArray[i]; + break; + case EOpBitwiseXor: + resultArray = new TConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + resultArray[i] = leftArray[i] ^ rightArray[i]; + break; + case EOpBitwiseOr: + resultArray = new TConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + resultArray[i] = leftArray[i] | rightArray[i]; + break; + case EOpBitShiftLeft: + resultArray = new TConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + resultArray[i] = + TConstantUnion::lshift(leftArray[i], rightArray[i], diagnostics, line); + break; + case EOpBitShiftRight: + resultArray = new TConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + resultArray[i] = + TConstantUnion::rshift(leftArray[i], rightArray[i], diagnostics, line); + break; + + case EOpLessThan: + ASSERT(objectSize == 1); + resultArray = new TConstantUnion[1]; + resultArray->setBConst(*leftArray < *rightArray); + break; + + case EOpGreaterThan: + ASSERT(objectSize == 1); + resultArray = new TConstantUnion[1]; + resultArray->setBConst(*leftArray > *rightArray); + break; + + case EOpLessThanEqual: + ASSERT(objectSize == 1); + resultArray = new TConstantUnion[1]; + resultArray->setBConst(!(*leftArray > *rightArray)); + break; + + case EOpGreaterThanEqual: + ASSERT(objectSize == 1); + resultArray = new TConstantUnion[1]; + resultArray->setBConst(!(*leftArray < *rightArray)); + break; + + case EOpEqual: + case EOpNotEqual: + { + resultArray = new TConstantUnion[1]; + bool equal = true; + for (size_t i = 0; i < objectSize; i++) + { + if (leftArray[i] != rightArray[i]) + { + equal = false; + break; // break out of for loop + } + } + if (op == EOpEqual) + { + resultArray->setBConst(equal); + } + else + { + resultArray->setBConst(!equal); + } + } + break; + + default: + UNREACHABLE(); + return nullptr; + } + return resultArray; +} + +// The fold functions do operations on a constant at GLSL compile time, without generating run-time +// code. Returns the constant value to keep using. Nullptr should not be returned. +TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op) +{ + // Do operations where the return type may have a different number of components compared to the + // operand type. + + const TConstantUnion *operandArray = getConstantValue(); + ASSERT(operandArray); + + size_t objectSize = getType().getObjectSize(); + TConstantUnion *resultArray = nullptr; + switch (op) + { + case EOpAny: + ASSERT(getType().getBasicType() == EbtBool); + resultArray = new TConstantUnion(); + resultArray->setBConst(false); + for (size_t i = 0; i < objectSize; i++) + { + if (operandArray[i].getBConst()) + { + resultArray->setBConst(true); + break; + } + } + break; + + case EOpAll: + ASSERT(getType().getBasicType() == EbtBool); + resultArray = new TConstantUnion(); + resultArray->setBConst(true); + for (size_t i = 0; i < objectSize; i++) + { + if (!operandArray[i].getBConst()) + { + resultArray->setBConst(false); + break; + } + } + break; + + case EOpLength: + ASSERT(getType().getBasicType() == EbtFloat); + resultArray = new TConstantUnion(); + resultArray->setFConst(VectorLength(operandArray, objectSize)); + break; + + case EOpTranspose: + { + ASSERT(getType().getBasicType() == EbtFloat); + resultArray = new TConstantUnion[objectSize]; + angle::Matrix result = + GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose(); + SetUnionArrayFromMatrix(result, resultArray); + break; + } + + case EOpDeterminant: + { + ASSERT(getType().getBasicType() == EbtFloat); + const uint8_t size = getType().getNominalSize(); + ASSERT(size >= 2 && size <= 4); + resultArray = new TConstantUnion(); + resultArray->setFConst(GetMatrix(operandArray, size).determinant()); + break; + } + + case EOpInverse: + { + ASSERT(getType().getBasicType() == EbtFloat); + const uint8_t size = getType().getNominalSize(); + ASSERT(size >= 2 && size <= 4); + resultArray = new TConstantUnion[objectSize]; + angle::Matrix result = GetMatrix(operandArray, size).inverse(); + SetUnionArrayFromMatrix(result, resultArray); + break; + } + + case EOpPackSnorm2x16: + ASSERT(getType().getBasicType() == EbtFloat); + ASSERT(getType().getNominalSize() == 2); + resultArray = new TConstantUnion(); + resultArray->setUConst( + gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); + break; + + case EOpUnpackSnorm2x16: + { + ASSERT(getType().getBasicType() == EbtUInt); + resultArray = new TConstantUnion[2]; + float f1, f2; + gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2); + resultArray[0].setFConst(f1); + resultArray[1].setFConst(f2); + break; + } + + case EOpPackUnorm2x16: + ASSERT(getType().getBasicType() == EbtFloat); + ASSERT(getType().getNominalSize() == 2); + resultArray = new TConstantUnion(); + resultArray->setUConst( + gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); + break; + + case EOpUnpackUnorm2x16: + { + ASSERT(getType().getBasicType() == EbtUInt); + resultArray = new TConstantUnion[2]; + float f1, f2; + gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2); + resultArray[0].setFConst(f1); + resultArray[1].setFConst(f2); + break; + } + + case EOpPackHalf2x16: + ASSERT(getType().getBasicType() == EbtFloat); + ASSERT(getType().getNominalSize() == 2); + resultArray = new TConstantUnion(); + resultArray->setUConst( + gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); + break; + + case EOpUnpackHalf2x16: + { + ASSERT(getType().getBasicType() == EbtUInt); + resultArray = new TConstantUnion[2]; + float f1, f2; + gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2); + resultArray[0].setFConst(f1); + resultArray[1].setFConst(f2); + break; + } + + case EOpPackUnorm4x8: + { + ASSERT(getType().getBasicType() == EbtFloat); + resultArray = new TConstantUnion(); + resultArray->setUConst( + gl::PackUnorm4x8(operandArray[0].getFConst(), operandArray[1].getFConst(), + operandArray[2].getFConst(), operandArray[3].getFConst())); + break; + } + case EOpPackSnorm4x8: + { + ASSERT(getType().getBasicType() == EbtFloat); + resultArray = new TConstantUnion(); + resultArray->setUConst( + gl::PackSnorm4x8(operandArray[0].getFConst(), operandArray[1].getFConst(), + operandArray[2].getFConst(), operandArray[3].getFConst())); + break; + } + case EOpUnpackUnorm4x8: + { + ASSERT(getType().getBasicType() == EbtUInt); + resultArray = new TConstantUnion[4]; + float f[4]; + gl::UnpackUnorm4x8(operandArray[0].getUConst(), f); + for (size_t i = 0; i < 4; ++i) + { + resultArray[i].setFConst(f[i]); + } + break; + } + case EOpUnpackSnorm4x8: + { + ASSERT(getType().getBasicType() == EbtUInt); + resultArray = new TConstantUnion[4]; + float f[4]; + gl::UnpackSnorm4x8(operandArray[0].getUConst(), f); + for (size_t i = 0; i < 4; ++i) + { + resultArray[i].setFConst(f[i]); + } + break; + } + + default: + UNREACHABLE(); + break; + } + + return resultArray; +} + +TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op, + const TFunction *function, + TDiagnostics *diagnostics) +{ + // Do unary operations where each component of the result is computed based on the corresponding + // component of the operand. Also folds normalize, though the divisor in that case takes all + // components into account. + + const TConstantUnion *operandArray = getConstantValue(); + ASSERT(operandArray); + + size_t objectSize = getType().getObjectSize(); + + TConstantUnion *resultArray = new TConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + switch (op) + { + case EOpNegative: + switch (getType().getBasicType()) + { + case EbtFloat: + resultArray[i].setFConst(-operandArray[i].getFConst()); + break; + case EbtInt: + if (operandArray[i] == std::numeric_limits::min()) + { + // The minimum representable integer doesn't have a positive + // counterpart, rather the negation overflows and in ESSL is supposed to + // wrap back to the minimum representable integer. Make sure that we + // don't actually let the negation overflow, which has undefined + // behavior in C++. + resultArray[i].setIConst(std::numeric_limits::min()); + } + else + { + resultArray[i].setIConst(-operandArray[i].getIConst()); + } + break; + case EbtUInt: + if (operandArray[i] == 0x80000000u) + { + resultArray[i].setUConst(0x80000000u); + } + else + { + resultArray[i].setUConst(static_cast( + -static_cast(operandArray[i].getUConst()))); + } + break; + default: + UNREACHABLE(); + return nullptr; + } + break; + + case EOpPositive: + switch (getType().getBasicType()) + { + case EbtFloat: + resultArray[i].setFConst(operandArray[i].getFConst()); + break; + case EbtInt: + resultArray[i].setIConst(operandArray[i].getIConst()); + break; + case EbtUInt: + resultArray[i].setUConst(static_cast( + static_cast(operandArray[i].getUConst()))); + break; + default: + UNREACHABLE(); + return nullptr; + } + break; + + case EOpLogicalNot: + switch (getType().getBasicType()) + { + case EbtBool: + resultArray[i].setBConst(!operandArray[i].getBConst()); + break; + default: + UNREACHABLE(); + return nullptr; + } + break; + + case EOpBitwiseNot: + switch (getType().getBasicType()) + { + case EbtInt: + resultArray[i].setIConst(~operandArray[i].getIConst()); + break; + case EbtUInt: + resultArray[i].setUConst(~operandArray[i].getUConst()); + break; + default: + UNREACHABLE(); + return nullptr; + } + break; + + case EOpRadians: + ASSERT(getType().getBasicType() == EbtFloat); + resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst()); + break; + + case EOpDegrees: + ASSERT(getType().getBasicType() == EbtFloat); + resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst()); + break; + + case EOpSin: + foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]); + break; + + case EOpCos: + foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]); + break; + + case EOpTan: + foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]); + break; + + case EOpAsin: + // For asin(x), results are undefined if |x| > 1, we are choosing to set result to + // 0. + if (fabsf(operandArray[i].getFConst()) > 1.0f) + UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), + diagnostics, &resultArray[i]); + else + foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]); + break; + + case EOpAcos: + // For acos(x), results are undefined if |x| > 1, we are choosing to set result to + // 0. + if (fabsf(operandArray[i].getFConst()) > 1.0f) + UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), + diagnostics, &resultArray[i]); + else + foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]); + break; + + case EOpAtan: + foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]); + break; + + case EOpSinh: + foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]); + break; + + case EOpCosh: + foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]); + break; + + case EOpTanh: + foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]); + break; + + case EOpAsinh: + foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]); + break; + + case EOpAcosh: + // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0. + if (operandArray[i].getFConst() < 1.0f) + UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), + diagnostics, &resultArray[i]); + else + foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]); + break; + + case EOpAtanh: + // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to + // 0. + if (fabsf(operandArray[i].getFConst()) >= 1.0f) + UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), + diagnostics, &resultArray[i]); + else + foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]); + break; + + case EOpAbs: + switch (getType().getBasicType()) + { + case EbtFloat: + resultArray[i].setFConst(fabsf(operandArray[i].getFConst())); + break; + case EbtInt: + resultArray[i].setIConst(abs(operandArray[i].getIConst())); + break; + default: + UNREACHABLE(); + return nullptr; + } + break; + + case EOpSign: + switch (getType().getBasicType()) + { + case EbtFloat: + { + float fConst = operandArray[i].getFConst(); + float fResult = 0.0f; + if (fConst > 0.0f) + fResult = 1.0f; + else if (fConst < 0.0f) + fResult = -1.0f; + resultArray[i].setFConst(fResult); + break; + } + case EbtInt: + { + int iConst = operandArray[i].getIConst(); + int iResult = 0; + if (iConst > 0) + iResult = 1; + else if (iConst < 0) + iResult = -1; + resultArray[i].setIConst(iResult); + break; + } + default: + UNREACHABLE(); + return nullptr; + } + break; + + case EOpFloor: + foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]); + break; + + case EOpTrunc: + foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]); + break; + + case EOpRound: + foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]); + break; + + case EOpRoundEven: + { + ASSERT(getType().getBasicType() == EbtFloat); + float x = operandArray[i].getFConst(); + float result; + float fractPart = modff(x, &result); + if (fabsf(fractPart) == 0.5f) + result = 2.0f * roundf(x / 2.0f); + else + result = roundf(x); + resultArray[i].setFConst(result); + break; + } + + case EOpCeil: + foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]); + break; + + case EOpFract: + { + ASSERT(getType().getBasicType() == EbtFloat); + float x = operandArray[i].getFConst(); + resultArray[i].setFConst(x - floorf(x)); + break; + } + + case EOpIsnan: + ASSERT(getType().getBasicType() == EbtFloat); + resultArray[i].setBConst(gl::isNaN(operandArray[0].getFConst())); + break; + + case EOpIsinf: + ASSERT(getType().getBasicType() == EbtFloat); + resultArray[i].setBConst(gl::isInf(operandArray[0].getFConst())); + break; + + case EOpFloatBitsToInt: + ASSERT(getType().getBasicType() == EbtFloat); + resultArray[i].setIConst(gl::bitCast(operandArray[0].getFConst())); + break; + + case EOpFloatBitsToUint: + ASSERT(getType().getBasicType() == EbtFloat); + resultArray[i].setUConst(gl::bitCast(operandArray[0].getFConst())); + break; + + case EOpIntBitsToFloat: + ASSERT(getType().getBasicType() == EbtInt); + resultArray[i].setFConst(gl::bitCast(operandArray[0].getIConst())); + break; + + case EOpUintBitsToFloat: + ASSERT(getType().getBasicType() == EbtUInt); + resultArray[i].setFConst(gl::bitCast(operandArray[0].getUConst())); + break; + + case EOpExp: + foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]); + break; + + case EOpLog: + // For log(x), results are undefined if x <= 0, we are choosing to set result to 0. + if (operandArray[i].getFConst() <= 0.0f) + UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), + diagnostics, &resultArray[i]); + else + foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]); + break; + + case EOpExp2: + foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]); + break; + + case EOpLog2: + // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0. + // And log2f is not available on some plarforms like old android, so just using + // log(x)/log(2) here. + if (operandArray[i].getFConst() <= 0.0f) + UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), + diagnostics, &resultArray[i]); + else + { + foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]); + resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f)); + } + break; + + case EOpSqrt: + // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0. + if (operandArray[i].getFConst() < 0.0f) + UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), + diagnostics, &resultArray[i]); + else + foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]); + break; + + case EOpInversesqrt: + // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(), + // so getting the square root first using builtin function sqrt() and then taking + // its inverse. + // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set + // result to 0. + if (operandArray[i].getFConst() <= 0.0f) + UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), + diagnostics, &resultArray[i]); + else + { + foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]); + resultArray[i].setFConst(1.0f / resultArray[i].getFConst()); + } + break; + + case EOpNotComponentWise: + ASSERT(getType().getBasicType() == EbtBool); + resultArray[i].setBConst(!operandArray[i].getBConst()); + break; + + case EOpNormalize: + { + ASSERT(getType().getBasicType() == EbtFloat); + float x = operandArray[i].getFConst(); + float length = VectorLength(operandArray, objectSize); + if (length != 0.0f) + resultArray[i].setFConst(x / length); + else + UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), + diagnostics, &resultArray[i]); + break; + } + case EOpBitfieldReverse: + { + uint32_t value; + if (getType().getBasicType() == EbtInt) + { + value = static_cast(operandArray[i].getIConst()); + } + else + { + ASSERT(getType().getBasicType() == EbtUInt); + value = operandArray[i].getUConst(); + } + uint32_t result = gl::BitfieldReverse(value); + if (getType().getBasicType() == EbtInt) + { + resultArray[i].setIConst(static_cast(result)); + } + else + { + resultArray[i].setUConst(result); + } + break; + } + case EOpBitCount: + { + uint32_t value; + if (getType().getBasicType() == EbtInt) + { + value = static_cast(operandArray[i].getIConst()); + } + else + { + ASSERT(getType().getBasicType() == EbtUInt); + value = operandArray[i].getUConst(); + } + int result = gl::BitCount(value); + resultArray[i].setIConst(result); + break; + } + case EOpFindLSB: + { + uint32_t value; + if (getType().getBasicType() == EbtInt) + { + value = static_cast(operandArray[i].getIConst()); + } + else + { + ASSERT(getType().getBasicType() == EbtUInt); + value = operandArray[i].getUConst(); + } + resultArray[i].setIConst(gl::FindLSB(value)); + break; + } + case EOpFindMSB: + { + uint32_t value; + if (getType().getBasicType() == EbtInt) + { + int intValue = operandArray[i].getIConst(); + value = static_cast(intValue); + if (intValue < 0) + { + // Look for zero instead of one in value. This also handles the intValue == + // -1 special case, where the return value needs to be -1. + value = ~value; + } + } + else + { + ASSERT(getType().getBasicType() == EbtUInt); + value = operandArray[i].getUConst(); + } + resultArray[i].setIConst(gl::FindMSB(value)); + break; + } + + default: + return nullptr; + } + } + + return resultArray; +} + +void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion ¶meter, + FloatTypeUnaryFunc builtinFunc, + TConstantUnion *result) const +{ + ASSERT(builtinFunc); + + ASSERT(getType().getBasicType() == EbtFloat); + result->setFConst(builtinFunc(parameter.getFConst())); +} + +void TIntermConstantUnion::propagatePrecision(TPrecision precision) +{ + mType.setPrecision(precision); +} + +// static +TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate, + TDiagnostics *diagnostics) +{ + const TOperator op = aggregate->getOp(); + const TFunction *function = aggregate->getFunction(); + TIntermSequence *arguments = aggregate->getSequence(); + unsigned int argsCount = static_cast(arguments->size()); + std::vector unionArrays(argsCount); + std::vector objectSizes(argsCount); + size_t maxObjectSize = 0; + TBasicType basicType = EbtVoid; + TSourceLoc loc; + for (unsigned int i = 0; i < argsCount; i++) + { + TIntermConstantUnion *argConstant = (*arguments)[i]->getAsConstantUnion(); + ASSERT(argConstant != nullptr); // Should be checked already. + + if (i == 0) + { + basicType = argConstant->getType().getBasicType(); + loc = argConstant->getLine(); + } + unionArrays[i] = argConstant->getConstantValue(); + objectSizes[i] = argConstant->getType().getObjectSize(); + if (objectSizes[i] > maxObjectSize) + maxObjectSize = objectSizes[i]; + } + + if (!(*arguments)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct) + { + for (unsigned int i = 0; i < argsCount; i++) + if (objectSizes[i] != maxObjectSize) + unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize); + } + + TConstantUnion *resultArray = nullptr; + + switch (op) + { + case EOpAtan: + { + ASSERT(basicType == EbtFloat); + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + float y = unionArrays[0][i].getFConst(); + float x = unionArrays[1][i].getFConst(); + // Results are undefined if x and y are both 0. + if (x == 0.0f && y == 0.0f) + UndefinedConstantFoldingError(loc, function, basicType, diagnostics, + &resultArray[i]); + else + resultArray[i].setFConst(atan2f(y, x)); + } + break; + } + + case EOpPow: + { + ASSERT(basicType == EbtFloat); + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + float x = unionArrays[0][i].getFConst(); + float y = unionArrays[1][i].getFConst(); + // Results are undefined if x < 0. + // Results are undefined if x = 0 and y <= 0. + if (x < 0.0f) + UndefinedConstantFoldingError(loc, function, basicType, diagnostics, + &resultArray[i]); + else if (x == 0.0f && y <= 0.0f) + UndefinedConstantFoldingError(loc, function, basicType, diagnostics, + &resultArray[i]); + else + resultArray[i].setFConst(powf(x, y)); + } + break; + } + + case EOpMod: + { + ASSERT(basicType == EbtFloat); + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + float x = unionArrays[0][i].getFConst(); + float y = unionArrays[1][i].getFConst(); + resultArray[i].setFConst(x - y * floorf(x / y)); + } + break; + } + + case EOpMin: + { + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + switch (basicType) + { + case EbtFloat: + resultArray[i].setFConst( + std::min(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst())); + break; + case EbtInt: + resultArray[i].setIConst( + std::min(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst())); + break; + case EbtUInt: + resultArray[i].setUConst( + std::min(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst())); + break; + default: + UNREACHABLE(); + break; + } + } + break; + } + + case EOpMax: + { + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + switch (basicType) + { + case EbtFloat: + resultArray[i].setFConst( + std::max(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst())); + break; + case EbtInt: + resultArray[i].setIConst( + std::max(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst())); + break; + case EbtUInt: + resultArray[i].setUConst( + std::max(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst())); + break; + default: + UNREACHABLE(); + break; + } + } + break; + } + + case EOpStep: + { + ASSERT(basicType == EbtFloat); + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + resultArray[i].setFConst( + unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f : 1.0f); + break; + } + + case EOpLessThanComponentWise: + { + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + switch (basicType) + { + case EbtFloat: + resultArray[i].setBConst(unionArrays[0][i].getFConst() < + unionArrays[1][i].getFConst()); + break; + case EbtInt: + resultArray[i].setBConst(unionArrays[0][i].getIConst() < + unionArrays[1][i].getIConst()); + break; + case EbtUInt: + resultArray[i].setBConst(unionArrays[0][i].getUConst() < + unionArrays[1][i].getUConst()); + break; + default: + UNREACHABLE(); + break; + } + } + break; + } + + case EOpLessThanEqualComponentWise: + { + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + switch (basicType) + { + case EbtFloat: + resultArray[i].setBConst(unionArrays[0][i].getFConst() <= + unionArrays[1][i].getFConst()); + break; + case EbtInt: + resultArray[i].setBConst(unionArrays[0][i].getIConst() <= + unionArrays[1][i].getIConst()); + break; + case EbtUInt: + resultArray[i].setBConst(unionArrays[0][i].getUConst() <= + unionArrays[1][i].getUConst()); + break; + default: + UNREACHABLE(); + break; + } + } + break; + } + + case EOpGreaterThanComponentWise: + { + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + switch (basicType) + { + case EbtFloat: + resultArray[i].setBConst(unionArrays[0][i].getFConst() > + unionArrays[1][i].getFConst()); + break; + case EbtInt: + resultArray[i].setBConst(unionArrays[0][i].getIConst() > + unionArrays[1][i].getIConst()); + break; + case EbtUInt: + resultArray[i].setBConst(unionArrays[0][i].getUConst() > + unionArrays[1][i].getUConst()); + break; + default: + UNREACHABLE(); + break; + } + } + break; + } + case EOpGreaterThanEqualComponentWise: + { + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + switch (basicType) + { + case EbtFloat: + resultArray[i].setBConst(unionArrays[0][i].getFConst() >= + unionArrays[1][i].getFConst()); + break; + case EbtInt: + resultArray[i].setBConst(unionArrays[0][i].getIConst() >= + unionArrays[1][i].getIConst()); + break; + case EbtUInt: + resultArray[i].setBConst(unionArrays[0][i].getUConst() >= + unionArrays[1][i].getUConst()); + break; + default: + UNREACHABLE(); + break; + } + } + } + break; + + case EOpEqualComponentWise: + { + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + switch (basicType) + { + case EbtFloat: + resultArray[i].setBConst(unionArrays[0][i].getFConst() == + unionArrays[1][i].getFConst()); + break; + case EbtInt: + resultArray[i].setBConst(unionArrays[0][i].getIConst() == + unionArrays[1][i].getIConst()); + break; + case EbtUInt: + resultArray[i].setBConst(unionArrays[0][i].getUConst() == + unionArrays[1][i].getUConst()); + break; + case EbtBool: + resultArray[i].setBConst(unionArrays[0][i].getBConst() == + unionArrays[1][i].getBConst()); + break; + default: + UNREACHABLE(); + break; + } + } + break; + } + + case EOpNotEqualComponentWise: + { + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + switch (basicType) + { + case EbtFloat: + resultArray[i].setBConst(unionArrays[0][i].getFConst() != + unionArrays[1][i].getFConst()); + break; + case EbtInt: + resultArray[i].setBConst(unionArrays[0][i].getIConst() != + unionArrays[1][i].getIConst()); + break; + case EbtUInt: + resultArray[i].setBConst(unionArrays[0][i].getUConst() != + unionArrays[1][i].getUConst()); + break; + case EbtBool: + resultArray[i].setBConst(unionArrays[0][i].getBConst() != + unionArrays[1][i].getBConst()); + break; + default: + UNREACHABLE(); + break; + } + } + break; + } + + case EOpDistance: + { + ASSERT(basicType == EbtFloat); + TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize]; + resultArray = new TConstantUnion(); + for (size_t i = 0; i < maxObjectSize; i++) + { + float x = unionArrays[0][i].getFConst(); + float y = unionArrays[1][i].getFConst(); + distanceArray[i].setFConst(x - y); + } + resultArray->setFConst(VectorLength(distanceArray, maxObjectSize)); + break; + } + + case EOpDot: + ASSERT(basicType == EbtFloat); + resultArray = new TConstantUnion(); + resultArray->setFConst(VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize)); + break; + + case EOpCross: + { + ASSERT(basicType == EbtFloat && maxObjectSize == 3); + resultArray = new TConstantUnion[maxObjectSize]; + float x0 = unionArrays[0][0].getFConst(); + float x1 = unionArrays[0][1].getFConst(); + float x2 = unionArrays[0][2].getFConst(); + float y0 = unionArrays[1][0].getFConst(); + float y1 = unionArrays[1][1].getFConst(); + float y2 = unionArrays[1][2].getFConst(); + resultArray[0].setFConst(x1 * y2 - y1 * x2); + resultArray[1].setFConst(x2 * y0 - y2 * x0); + resultArray[2].setFConst(x0 * y1 - y0 * x1); + break; + } + + case EOpReflect: + { + ASSERT(basicType == EbtFloat); + // genType reflect (genType I, genType N) : + // For the incident vector I and surface orientation N, returns the reflection + // direction: + // I - 2 * dot(N, I) * N. + resultArray = new TConstantUnion[maxObjectSize]; + float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize); + for (size_t i = 0; i < maxObjectSize; i++) + { + float result = unionArrays[0][i].getFConst() - + 2.0f * dotProduct * unionArrays[1][i].getFConst(); + resultArray[i].setFConst(result); + } + break; + } + + case EOpMatrixCompMult: + { + ASSERT(basicType == EbtFloat && (*arguments)[0]->getAsTyped()->isMatrix() && + (*arguments)[1]->getAsTyped()->isMatrix()); + // Perform component-wise matrix multiplication. + resultArray = new TConstantUnion[maxObjectSize]; + const uint8_t rows = (*arguments)[0]->getAsTyped()->getRows(); + const uint8_t cols = (*arguments)[0]->getAsTyped()->getCols(); + angle::Matrix lhs = GetMatrix(unionArrays[0], rows, cols); + angle::Matrix rhs = GetMatrix(unionArrays[1], rows, cols); + angle::Matrix result = lhs.compMult(rhs); + SetUnionArrayFromMatrix(result, resultArray); + break; + } + + case EOpOuterProduct: + { + ASSERT(basicType == EbtFloat); + size_t numRows = (*arguments)[0]->getAsTyped()->getType().getObjectSize(); + size_t numCols = (*arguments)[1]->getAsTyped()->getType().getObjectSize(); + resultArray = new TConstantUnion[numRows * numCols]; + angle::Matrix result = + GetMatrix(unionArrays[0], static_cast(numRows), 1) + .outerProduct(GetMatrix(unionArrays[1], 1, static_cast(numCols))); + SetUnionArrayFromMatrix(result, resultArray); + break; + } + + case EOpClamp: + { + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + switch (basicType) + { + case EbtFloat: + { + float x = unionArrays[0][i].getFConst(); + float min = unionArrays[1][i].getFConst(); + float max = unionArrays[2][i].getFConst(); + // Results are undefined if min > max. + if (min > max) + UndefinedConstantFoldingError(loc, function, basicType, diagnostics, + &resultArray[i]); + else + resultArray[i].setFConst(gl::clamp(x, min, max)); + break; + } + + case EbtInt: + { + int x = unionArrays[0][i].getIConst(); + int min = unionArrays[1][i].getIConst(); + int max = unionArrays[2][i].getIConst(); + // Results are undefined if min > max. + if (min > max) + UndefinedConstantFoldingError(loc, function, basicType, diagnostics, + &resultArray[i]); + else + resultArray[i].setIConst(gl::clamp(x, min, max)); + break; + } + case EbtUInt: + { + unsigned int x = unionArrays[0][i].getUConst(); + unsigned int min = unionArrays[1][i].getUConst(); + unsigned int max = unionArrays[2][i].getUConst(); + // Results are undefined if min > max. + if (min > max) + UndefinedConstantFoldingError(loc, function, basicType, diagnostics, + &resultArray[i]); + else + resultArray[i].setUConst(gl::clamp(x, min, max)); + break; + } + default: + UNREACHABLE(); + break; + } + } + break; + } + + case EOpMix: + { + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + TBasicType type = (*arguments)[2]->getAsTyped()->getType().getBasicType(); + if (type == EbtFloat) + { + ASSERT(basicType == EbtFloat); + float x = unionArrays[0][i].getFConst(); + float y = unionArrays[1][i].getFConst(); + + // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a. + float a = unionArrays[2][i].getFConst(); + resultArray[i].setFConst(x * (1.0f - a) + y * a); + } + else // 3rd parameter is EbtBool + { + ASSERT(type == EbtBool); + // Selects which vector each returned component comes from. + // For a component of a that is false, the corresponding component of x is + // returned. + // For a component of a that is true, the corresponding component of y is + // returned. + bool a = unionArrays[2][i].getBConst(); + switch (basicType) + { + case EbtFloat: + { + float x = unionArrays[0][i].getFConst(); + float y = unionArrays[1][i].getFConst(); + resultArray[i].setFConst(a ? y : x); + } + break; + case EbtInt: + { + int x = unionArrays[0][i].getIConst(); + int y = unionArrays[1][i].getIConst(); + resultArray[i].setIConst(a ? y : x); + } + break; + case EbtUInt: + { + unsigned int x = unionArrays[0][i].getUConst(); + unsigned int y = unionArrays[1][i].getUConst(); + resultArray[i].setUConst(a ? y : x); + } + break; + case EbtBool: + { + bool x = unionArrays[0][i].getBConst(); + bool y = unionArrays[1][i].getBConst(); + resultArray[i].setBConst(a ? y : x); + } + break; + default: + UNREACHABLE(); + break; + } + } + } + break; + } + + case EOpSmoothstep: + { + ASSERT(basicType == EbtFloat); + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + float edge0 = unionArrays[0][i].getFConst(); + float edge1 = unionArrays[1][i].getFConst(); + float x = unionArrays[2][i].getFConst(); + // Results are undefined if edge0 >= edge1. + if (edge0 >= edge1) + { + UndefinedConstantFoldingError(loc, function, basicType, diagnostics, + &resultArray[i]); + } + else + { + // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth + // Hermite interpolation between 0 and 1 when edge0 < x < edge1. + float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f); + resultArray[i].setFConst(t * t * (3.0f - 2.0f * t)); + } + } + break; + } + + case EOpFma: + { + ASSERT(basicType == EbtFloat); + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + float a = unionArrays[0][i].getFConst(); + float b = unionArrays[1][i].getFConst(); + float c = unionArrays[2][i].getFConst(); + + // Returns a * b + c. + resultArray[i].setFConst(a * b + c); + } + break; + } + + case EOpLdexp: + { + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + float x = unionArrays[0][i].getFConst(); + int exp = unionArrays[1][i].getIConst(); + if (exp > 128) + { + UndefinedConstantFoldingError(loc, function, basicType, diagnostics, + &resultArray[i]); + } + else + { + resultArray[i].setFConst(gl::Ldexp(x, exp)); + } + } + break; + } + + case EOpFaceforward: + { + ASSERT(basicType == EbtFloat); + // genType faceforward(genType N, genType I, genType Nref) : + // If dot(Nref, I) < 0 return N, otherwise return -N. + resultArray = new TConstantUnion[maxObjectSize]; + float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize); + for (size_t i = 0; i < maxObjectSize; i++) + { + if (dotProduct < 0) + resultArray[i].setFConst(unionArrays[0][i].getFConst()); + else + resultArray[i].setFConst(-unionArrays[0][i].getFConst()); + } + break; + } + + case EOpRefract: + { + ASSERT(basicType == EbtFloat); + // genType refract(genType I, genType N, float eta) : + // For the incident vector I and surface normal N, and the ratio of indices of + // refraction eta, + // return the refraction vector. The result is computed by + // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) + // if (k < 0.0) + // return genType(0.0) + // else + // return eta * I - (eta * dot(N, I) + sqrt(k)) * N + resultArray = new TConstantUnion[maxObjectSize]; + float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize); + for (size_t i = 0; i < maxObjectSize; i++) + { + float eta = unionArrays[2][i].getFConst(); + float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct); + if (k < 0.0f) + resultArray[i].setFConst(0.0f); + else + resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() - + (eta * dotProduct + sqrtf(k)) * + unionArrays[1][i].getFConst()); + } + break; + } + case EOpBitfieldExtract: + { + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; ++i) + { + int offset = unionArrays[1][0].getIConst(); + int bits = unionArrays[2][0].getIConst(); + if (bits == 0) + { + if (aggregate->getBasicType() == EbtInt) + { + resultArray[i].setIConst(0); + } + else + { + ASSERT(aggregate->getBasicType() == EbtUInt); + resultArray[i].setUConst(0); + } + } + else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32) + { + UndefinedConstantFoldingError(loc, function, aggregate->getBasicType(), + diagnostics, &resultArray[i]); + } + else + { + // bits can be 32 here, so we need to avoid bit shift overflow. + uint32_t maskMsb = 1u << (bits - 1); + uint32_t mask = ((maskMsb - 1u) | maskMsb) << offset; + if (aggregate->getBasicType() == EbtInt) + { + uint32_t value = static_cast(unionArrays[0][i].getIConst()); + uint32_t resultUnsigned = (value & mask) >> offset; + if ((resultUnsigned & maskMsb) != 0) + { + // The most significant bits (from bits+1 to the most significant bit) + // should be set to 1. + uint32_t higherBitsMask = ((1u << (32 - bits)) - 1u) << bits; + resultUnsigned |= higherBitsMask; + } + resultArray[i].setIConst(static_cast(resultUnsigned)); + } + else + { + ASSERT(aggregate->getBasicType() == EbtUInt); + uint32_t value = unionArrays[0][i].getUConst(); + resultArray[i].setUConst((value & mask) >> offset); + } + } + } + break; + } + case EOpBitfieldInsert: + { + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; ++i) + { + int offset = unionArrays[2][0].getIConst(); + int bits = unionArrays[3][0].getIConst(); + if (bits == 0) + { + if (aggregate->getBasicType() == EbtInt) + { + int32_t base = unionArrays[0][i].getIConst(); + resultArray[i].setIConst(base); + } + else + { + ASSERT(aggregate->getBasicType() == EbtUInt); + uint32_t base = unionArrays[0][i].getUConst(); + resultArray[i].setUConst(base); + } + } + else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32) + { + UndefinedConstantFoldingError(loc, function, aggregate->getBasicType(), + diagnostics, &resultArray[i]); + } + else + { + // bits can be 32 here, so we need to avoid bit shift overflow. + uint32_t maskMsb = 1u << (bits - 1); + uint32_t insertMask = ((maskMsb - 1u) | maskMsb) << offset; + uint32_t baseMask = ~insertMask; + if (aggregate->getBasicType() == EbtInt) + { + uint32_t base = static_cast(unionArrays[0][i].getIConst()); + uint32_t insert = static_cast(unionArrays[1][i].getIConst()); + uint32_t resultUnsigned = + (base & baseMask) | ((insert << offset) & insertMask); + resultArray[i].setIConst(static_cast(resultUnsigned)); + } + else + { + ASSERT(aggregate->getBasicType() == EbtUInt); + uint32_t base = unionArrays[0][i].getUConst(); + uint32_t insert = unionArrays[1][i].getUConst(); + resultArray[i].setUConst((base & baseMask) | + ((insert << offset) & insertMask)); + } + } + } + break; + } + case EOpDFdx: + case EOpDFdy: + case EOpFwidth: + ASSERT(basicType == EbtFloat); + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + // Derivatives of constant arguments should be 0. + resultArray[i].setFConst(0.0f); + } + break; + + default: + UNREACHABLE(); + return nullptr; + } + return resultArray; +} + +bool TIntermConstantUnion::IsFloatDivision(TBasicType t1, TBasicType t2) +{ + ImplicitTypeConversion conversion = GetConversion(t1, t2); + ASSERT(conversion != ImplicitTypeConversion::Invalid); + if (conversion == ImplicitTypeConversion::Same) + { + if (t1 == EbtFloat) + return true; + return false; + } + ASSERT(t1 == EbtFloat || t2 == EbtFloat); + return true; +} + +// TIntermPreprocessorDirective implementation. +TIntermPreprocessorDirective::TIntermPreprocessorDirective(PreprocessorDirective directive, + ImmutableString command) + : mDirective(directive), mCommand(std::move(command)) +{} + +TIntermPreprocessorDirective::TIntermPreprocessorDirective(const TIntermPreprocessorDirective &node) + : TIntermPreprocessorDirective(node.mDirective, node.mCommand) +{} + +TIntermPreprocessorDirective::~TIntermPreprocessorDirective() = default; + +size_t TIntermPreprocessorDirective::getChildCount() const +{ + return 0; +} + +TIntermNode *TIntermPreprocessorDirective::getChildNode(size_t index) const +{ + UNREACHABLE(); + return nullptr; +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/IntermNode.h b/gfx/angle/checkout/src/compiler/translator/IntermNode.h new file mode 100644 index 0000000000..81b5fcce43 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/IntermNode.h @@ -0,0 +1,1046 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// Definition of the in-memory high-level intermediate representation +// of shaders. This is a tree that parser creates. +// +// Nodes in the tree are defined as a hierarchy of classes derived from +// TIntermNode. Each is a node in a tree. There is no preset branching factor; +// each node can have it's own type of list of children. +// + +#ifndef COMPILER_TRANSLATOR_INTERMNODE_H_ +#define COMPILER_TRANSLATOR_INTERMNODE_H_ + +#include "GLSLANG/ShaderLang.h" + +#include +#include + +#include "common/angleutils.h" +#include "compiler/translator/Common.h" +#include "compiler/translator/ConstantUnion.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/Operator_autogen.h" +#include "compiler/translator/SymbolUniqueId.h" +#include "compiler/translator/Types.h" +#include "compiler/translator/tree_util/Visit.h" + +namespace sh +{ + +class TDiagnostics; + +class TIntermTraverser; +class TIntermAggregate; +class TIntermBlock; +class TIntermGlobalQualifierDeclaration; +class TIntermDeclaration; +class TIntermFunctionPrototype; +class TIntermFunctionDefinition; +class TIntermSwizzle; +class TIntermBinary; +class TIntermUnary; +class TIntermConstantUnion; +class TIntermTernary; +class TIntermIfElse; +class TIntermSwitch; +class TIntermCase; +class TIntermTyped; +class TIntermSymbol; +class TIntermLoop; +class TInfoSink; +class TInfoSinkBase; +class TIntermBranch; +class TIntermPreprocessorDirective; + +class TSymbolTable; +class TFunction; +class TVariable; + +// +// Base class for the tree nodes +// +class TIntermNode : angle::NonCopyable +{ + public: + POOL_ALLOCATOR_NEW_DELETE + TIntermNode() + { + // TODO: Move this to TSourceLoc constructor + // after getting rid of TPublicType. + mLine.first_file = mLine.last_file = 0; + mLine.first_line = mLine.last_line = 0; + } + virtual ~TIntermNode() {} + + const TSourceLoc &getLine() const { return mLine; } + void setLine(const TSourceLoc &l) { mLine = l; } + + virtual void traverse(TIntermTraverser *it); + virtual bool visit(Visit visit, TIntermTraverser *it) = 0; + + virtual TIntermTyped *getAsTyped() { return nullptr; } + virtual TIntermConstantUnion *getAsConstantUnion() { return nullptr; } + virtual TIntermFunctionDefinition *getAsFunctionDefinition() { return nullptr; } + virtual TIntermAggregate *getAsAggregate() { return nullptr; } + virtual TIntermBlock *getAsBlock() { return nullptr; } + virtual TIntermFunctionPrototype *getAsFunctionPrototypeNode() { return nullptr; } + virtual TIntermGlobalQualifierDeclaration *getAsGlobalQualifierDeclarationNode() + { + return nullptr; + } + virtual TIntermDeclaration *getAsDeclarationNode() { return nullptr; } + virtual TIntermSwizzle *getAsSwizzleNode() { return nullptr; } + virtual TIntermBinary *getAsBinaryNode() { return nullptr; } + virtual TIntermUnary *getAsUnaryNode() { return nullptr; } + virtual TIntermTernary *getAsTernaryNode() { return nullptr; } + virtual TIntermIfElse *getAsIfElseNode() { return nullptr; } + virtual TIntermSwitch *getAsSwitchNode() { return nullptr; } + virtual TIntermCase *getAsCaseNode() { return nullptr; } + virtual TIntermSymbol *getAsSymbolNode() { return nullptr; } + virtual TIntermLoop *getAsLoopNode() { return nullptr; } + virtual TIntermBranch *getAsBranchNode() { return nullptr; } + virtual TIntermPreprocessorDirective *getAsPreprocessorDirective() { return nullptr; } + + virtual TIntermNode *deepCopy() const = 0; + + virtual size_t getChildCount() const = 0; + virtual TIntermNode *getChildNode(size_t index) const = 0; + // Replace a child node. Return true if |original| is a child + // node and it is replaced; otherwise, return false. + virtual bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) = 0; + + protected: + TSourceLoc mLine; +}; + +// +// This is just to help yacc. +// +struct TIntermNodePair +{ + TIntermNode *node1; + TIntermNode *node2; +}; + +// +// Intermediate class for nodes that have a type. +// +class TIntermTyped : public TIntermNode +{ + public: + TIntermTyped(); + + virtual TIntermTyped *deepCopy() const override = 0; + + TIntermTyped *getAsTyped() override { return this; } + + virtual TIntermTyped *fold(TDiagnostics *diagnostics) { return this; } + + // getConstantValue() returns the constant value that this node represents, if any. It + // should only be used after nodes have been replaced with their folded versions returned + // from fold(). hasConstantValue() returns true if getConstantValue() will return a value. + virtual bool hasConstantValue() const; + virtual bool isConstantNullValue() const; + virtual const TConstantUnion *getConstantValue() const; + + // True if executing the expression represented by this node affects state, like values of + // variables. False if the executing the expression only computes its return value without + // affecting state. May return true conservatively. + virtual bool hasSideEffects() const = 0; + + virtual const TType &getType() const = 0; + + // Derive the precision of the node based on its children's. + virtual TPrecision derivePrecision() const; + // Set precision of the current node and propagate it to any child node that doesn't have + // precision. This should be the case only for TIntermConstantUnion nodes as every other node + // would already need to have its precision specified or derived. + virtual void propagatePrecision(TPrecision precision); + + TBasicType getBasicType() const { return getType().getBasicType(); } + TQualifier getQualifier() const { return getType().getQualifier(); } + TPrecision getPrecision() const { return getType().getPrecision(); } + TMemoryQualifier getMemoryQualifier() const { return getType().getMemoryQualifier(); } + uint8_t getCols() const { return getType().getCols(); } + uint8_t getRows() const { return getType().getRows(); } + uint8_t getNominalSize() const { return getType().getNominalSize(); } + uint8_t getSecondarySize() const { return getType().getSecondarySize(); } + + bool isInterfaceBlock() const { return getType().isInterfaceBlock(); } + bool isMatrix() const { return getType().isMatrix(); } + bool isArray() const { return getType().isArray(); } + bool isVector() const { return getType().isVector(); } + bool isScalar() const { return getType().isScalar(); } + bool isScalarInt() const { return getType().isScalarInt(); } + const char *getBasicString() const { return getType().getBasicString(); } + + unsigned int getOutermostArraySize() const { return getType().getOutermostArraySize(); } + + // After every transformation is done and just before outputting the tree (i.e. when the tree + // nodes are no longer going to change), the tree is traversed to gather some information to be + // stored in the intermediate nodes: + // + // - Precise-ness, which is set for arithmetic nodes that are involved in the calculation of a + // value assigned to a |precise| variable. + void setIsPrecise() { mIsPrecise = true; } + bool isPrecise() const { return mIsPrecise; } + + protected: + TIntermTyped(const TIntermTyped &node); + + bool mIsPrecise; +}; + +// +// Handle for, do-while, and while loops. +// +enum TLoopType +{ + ELoopFor, + ELoopWhile, + ELoopDoWhile +}; + +class TIntermLoop : public TIntermNode +{ + public: + TIntermLoop(TLoopType type, + TIntermNode *init, + TIntermTyped *cond, + TIntermTyped *expr, + TIntermBlock *body); + + TIntermLoop *getAsLoopNode() override { return this; } + void traverse(TIntermTraverser *it) final; + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + + TLoopType getType() const { return mType; } + TIntermNode *getInit() { return mInit; } + TIntermTyped *getCondition() { return mCond; } + TIntermTyped *getExpression() { return mExpr; } + TIntermBlock *getBody() { return mBody; } + + void setInit(TIntermNode *init) { mInit = init; } + void setCondition(TIntermTyped *condition) { mCond = condition; } + void setExpression(TIntermTyped *expression) { mExpr = expression; } + void setBody(TIntermBlock *body) { mBody = body; } + + virtual TIntermLoop *deepCopy() const override { return new TIntermLoop(*this); } + + protected: + TLoopType mType; + TIntermNode *mInit; // for-loop initialization + TIntermTyped *mCond; // loop exit condition + TIntermTyped *mExpr; // for-loop expression + TIntermBlock *mBody; // loop body + + private: + TIntermLoop(const TIntermLoop &); +}; + +// +// Handle break, continue, return, and kill. +// +class TIntermBranch : public TIntermNode +{ + public: + TIntermBranch(TOperator op, TIntermTyped *e) : mFlowOp(op), mExpression(e) {} + + TIntermBranch *getAsBranchNode() override { return this; } + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + + TOperator getFlowOp() { return mFlowOp; } + TIntermTyped *getExpression() { return mExpression; } + + virtual TIntermBranch *deepCopy() const override { return new TIntermBranch(*this); } + + protected: + TOperator mFlowOp; + TIntermTyped *mExpression; // zero except for "return exp;" statements + + private: + TIntermBranch(const TIntermBranch &); +}; + +// Nodes that correspond to variable symbols in the source code. These may be regular variables or +// interface block instances. In declarations that only declare a struct type but no variables, a +// TIntermSymbol node with an empty variable is used to store the type. +class TIntermSymbol : public TIntermTyped +{ + public: + TIntermSymbol(const TVariable *variable); + + TIntermTyped *deepCopy() const override { return new TIntermSymbol(*this); } + + bool hasConstantValue() const override; + const TConstantUnion *getConstantValue() const override; + + bool hasSideEffects() const override { return false; } + + const TType &getType() const override; + + const TSymbolUniqueId &uniqueId() const; + ImmutableString getName() const; + const TVariable &variable() const { return *mVariable; } + + TIntermSymbol *getAsSymbolNode() override { return this; } + void traverse(TIntermTraverser *it) final; + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; } + + private: + TIntermSymbol(const TIntermSymbol &) = default; // Note: not deleted, just private! + void propagatePrecision(TPrecision precision) override; + + const TVariable *const mVariable; // Guaranteed to be non-null +}; + +// A typed expression that is not just representing a symbol table symbol. +class TIntermExpression : public TIntermTyped +{ + public: + TIntermExpression(const TType &t); + + const TType &getType() const override { return mType; } + + protected: + TType *getTypePointer() { return &mType; } + void setType(const TType &t) { mType = t; } + + TIntermExpression(const TIntermExpression &node) = default; + + TType mType; +}; + +// Constant folded node. +// Note that nodes may be constant folded and not be constant expressions with the EvqConst +// qualifier. This happens for example when the following expression is processed: +// "true ? 1.0 : non_constant" +// Other nodes than TIntermConstantUnion may also be constant expressions. +// +class TIntermConstantUnion : public TIntermExpression +{ + public: + TIntermConstantUnion(const TConstantUnion *unionPointer, const TType &type) + : TIntermExpression(type), mUnionArrayPointer(unionPointer) + { + ASSERT(unionPointer); + } + + TIntermTyped *deepCopy() const override { return new TIntermConstantUnion(*this); } + + bool hasConstantValue() const override; + bool isConstantNullValue() const override; + const TConstantUnion *getConstantValue() const override; + + bool hasSideEffects() const override { return false; } + + int getIConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0; + } + unsigned int getUConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0; + } + float getFConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f; + } + bool getBConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false; + } + bool isZero(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].isZero() : false; + } + + TIntermConstantUnion *getAsConstantUnion() override { return this; } + void traverse(TIntermTraverser *it) final; + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; } + + TConstantUnion *foldUnaryNonComponentWise(TOperator op); + TConstantUnion *foldUnaryComponentWise(TOperator op, + const TFunction *function, + TDiagnostics *diagnostics); + + static const TConstantUnion *FoldBinary(TOperator op, + const TConstantUnion *leftArray, + const TType &leftType, + const TConstantUnion *rightArray, + const TType &rightType, + TDiagnostics *diagnostics, + const TSourceLoc &line); + + static const TConstantUnion *FoldIndexing(const TType &type, + const TConstantUnion *constArray, + int index); + static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate, + TDiagnostics *diagnostics); + static bool IsFloatDivision(TBasicType t1, TBasicType t2); + + protected: + // Same data may be shared between multiple constant unions, so it can't be modified. + const TConstantUnion *mUnionArrayPointer; + + private: + typedef float (*FloatTypeUnaryFunc)(float); + void foldFloatTypeUnary(const TConstantUnion ¶meter, + FloatTypeUnaryFunc builtinFunc, + TConstantUnion *result) const; + void propagatePrecision(TPrecision precision) override; + + TIntermConstantUnion(const TIntermConstantUnion &node); // Note: not deleted, just private! +}; + +// +// Intermediate class for node types that hold operators. +// +class TIntermOperator : public TIntermExpression +{ + public: + TOperator getOp() const { return mOp; } + + bool isAssignment() const; + bool isMultiplication() const; + bool isConstructor() const; + + // Returns true for calls mapped to EOpCall*, false for all built-ins. + bool isFunctionCall() const; + + bool hasSideEffects() const override { return isAssignment(); } + + protected: + TIntermOperator(TOperator op) : TIntermExpression(TType(EbtFloat, EbpUndefined)), mOp(op) {} + TIntermOperator(TOperator op, const TType &type) : TIntermExpression(type), mOp(op) {} + + TIntermOperator(const TIntermOperator &) = default; + + const TOperator mOp; +}; + +// Node for vector swizzles. +class TIntermSwizzle : public TIntermExpression +{ + public: + // This constructor determines the type of the node based on the operand. + TIntermSwizzle(TIntermTyped *operand, const TVector &swizzleOffsets); + + TIntermTyped *deepCopy() const override { return new TIntermSwizzle(*this); } + + TIntermSwizzle *getAsSwizzleNode() override { return this; } + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + + bool hasSideEffects() const override { return mOperand->hasSideEffects(); } + + TIntermTyped *getOperand() { return mOperand; } + void writeOffsetsAsXYZW(TInfoSinkBase *out) const; + + const TVector &getSwizzleOffsets() { return mSwizzleOffsets; } + + bool hasDuplicateOffsets() const; + void setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets); + bool offsetsMatch(int offset) const; + + TIntermTyped *fold(TDiagnostics *diagnostics) override; + + protected: + TIntermTyped *mOperand; + TVector mSwizzleOffsets; + bool mHasFoldedDuplicateOffsets; + + private: + void promote(); + TPrecision derivePrecision() const override; + void propagatePrecision(TPrecision precision) override; + + TIntermSwizzle(const TIntermSwizzle &node); // Note: not deleted, just private! +}; + +// +// Nodes for all the basic binary math operators. +// +class TIntermBinary : public TIntermOperator +{ + public: + // This constructor determines the type of the binary node based on the operands and op. + TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right); + // Comma qualifier depends on the shader version, so use this to create comma nodes: + static TIntermBinary *CreateComma(TIntermTyped *left, TIntermTyped *right, int shaderVersion); + + TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); } + + bool hasConstantValue() const override; + const TConstantUnion *getConstantValue() const override; + + static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right); + static TOperator GetMulAssignOpBasedOnOperands(const TType &left, const TType &right); + + TIntermBinary *getAsBinaryNode() override { return this; } + void traverse(TIntermTraverser *it) final; + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + + bool hasSideEffects() const override + { + return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects(); + } + + TIntermTyped *getLeft() const { return mLeft; } + TIntermTyped *getRight() const { return mRight; } + TIntermTyped *fold(TDiagnostics *diagnostics) override; + + // This method is only valid for EOpIndexDirectStruct. It returns the name of the field. + const ImmutableString &getIndexStructFieldName() const; + + protected: + TIntermTyped *mLeft; + TIntermTyped *mRight; + + private: + void promote(); + TPrecision derivePrecision() const override; + void propagatePrecision(TPrecision precision) override; + + static TQualifier GetCommaQualifier(int shaderVersion, + const TIntermTyped *left, + const TIntermTyped *right); + + TIntermBinary(const TIntermBinary &node); // Note: not deleted, just private! +}; + +// +// Nodes for unary math operators. +// +class TIntermUnary : public TIntermOperator +{ + public: + TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function); + + TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); } + + TIntermUnary *getAsUnaryNode() override { return this; } + void traverse(TIntermTraverser *it) final; + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + + bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); } + + TIntermTyped *getOperand() { return mOperand; } + TIntermTyped *fold(TDiagnostics *diagnostics) override; + + const TFunction *getFunction() const { return mFunction; } + + void setUseEmulatedFunction() { mUseEmulatedFunction = true; } + bool getUseEmulatedFunction() { return mUseEmulatedFunction; } + + protected: + TIntermTyped *mOperand; + + // If set to true, replace the built-in function call with an emulated one + // to work around driver bugs. + bool mUseEmulatedFunction; + + const TFunction *const mFunction; + + private: + void promote(); + TPrecision derivePrecision() const override; + void propagatePrecision(TPrecision precision) override; + + TIntermUnary(const TIntermUnary &node); // note: not deleted, just private! +}; + +typedef TVector TIntermSequence; +typedef TVector TQualifierList; + +// Interface for node classes that have an arbitrarily sized set of children. +class TIntermAggregateBase +{ + public: + virtual ~TIntermAggregateBase() {} + + virtual TIntermSequence *getSequence() = 0; + virtual const TIntermSequence *getSequence() const = 0; + + bool replaceChildNodeWithMultiple(TIntermNode *original, const TIntermSequence &replacements); + bool insertChildNodes(TIntermSequence::size_type position, const TIntermSequence &insertions); + + protected: + TIntermAggregateBase() {} + + bool replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement); +}; + +// +// Nodes that operate on an arbitrary sized set of children. +// +class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase +{ + public: + static TIntermAggregate *CreateFunctionCall(const TFunction &func, TIntermSequence *arguments); + + static TIntermAggregate *CreateRawFunctionCall(const TFunction &func, + TIntermSequence *arguments); + + // This covers all built-in function calls. + static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func, + TIntermSequence *arguments); + static TIntermAggregate *CreateConstructor(const TType &type, TIntermSequence *arguments); + static TIntermAggregate *CreateConstructor( + const TType &type, + const std::initializer_list &arguments); + ~TIntermAggregate() override {} + + // Note: only supported for nodes that can be a part of an expression. + TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); } + + TIntermAggregate *shallowCopy() const; + + bool hasConstantValue() const override; + bool isConstantNullValue() const override; + const TConstantUnion *getConstantValue() const override; + + TIntermAggregate *getAsAggregate() override { return this; } + void traverse(TIntermTraverser *it) final; + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + + bool hasSideEffects() const override; + + TIntermTyped *fold(TDiagnostics *diagnostics) override; + + TIntermSequence *getSequence() override { return &mArguments; } + const TIntermSequence *getSequence() const override { return &mArguments; } + + void setUseEmulatedFunction() { mUseEmulatedFunction = true; } + bool getUseEmulatedFunction() { return mUseEmulatedFunction; } + + const TFunction *getFunction() const { return mFunction; } + + // Get the function name to display to the user in an error message. + const char *functionName() const; + + protected: + TIntermSequence mArguments; + + // If set to true, replace the built-in function call with an emulated one + // to work around driver bugs. Only for calls mapped to ops other than EOpCall*. + bool mUseEmulatedFunction; + + const TFunction *const mFunction; + + private: + TIntermAggregate(const TFunction *func, + const TType &type, + TOperator op, + TIntermSequence *arguments); + + TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private! + + void setPrecisionAndQualifier(); + TPrecision derivePrecision() const override; + void propagatePrecision(TPrecision precision) override; + + bool areChildrenConstQualified(); +}; + +// A list of statements. Either the root node which contains declarations and function definitions, +// or a block that can be marked with curly braces {}. +class TIntermBlock : public TIntermNode, public TIntermAggregateBase +{ + public: + TIntermBlock() : TIntermNode(), mIsTreeRoot(false) {} + TIntermBlock(std::initializer_list stmts); + ~TIntermBlock() override {} + + TIntermBlock *getAsBlock() override { return this; } + void traverse(TIntermTraverser *it) final; + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + void replaceAllChildren(const TIntermSequence &newStatements); + + // Only intended for initially building the block. + void appendStatement(TIntermNode *statement); + void insertStatement(size_t insertPosition, TIntermNode *statement); + + TIntermSequence *getSequence() override { return &mStatements; } + const TIntermSequence *getSequence() const override { return &mStatements; } + + TIntermBlock *deepCopy() const override { return new TIntermBlock(*this); } + + void setIsTreeRoot() { mIsTreeRoot = true; } + bool isTreeRoot() const { return mIsTreeRoot; } + + protected: + TIntermSequence mStatements; + + // Used to distinguish the tree root from the other blocks. When validating the AST, some + // validations are not applicable if not run on the entire tree and are thus skipped. + bool mIsTreeRoot; + + private: + TIntermBlock(const TIntermBlock &); +}; + +// Function prototype. May be in the AST either as a function prototype declaration or as a part of +// a function definition. The type of the node is the function return type. +class TIntermFunctionPrototype : public TIntermTyped +{ + public: + TIntermFunctionPrototype(const TFunction *function); + ~TIntermFunctionPrototype() override {} + + TIntermFunctionPrototype *getAsFunctionPrototypeNode() override { return this; } + void traverse(TIntermTraverser *it) final; + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + + const TType &getType() const override; + + TIntermTyped *deepCopy() const override + { + UNREACHABLE(); + return nullptr; + } + bool hasSideEffects() const override + { + UNREACHABLE(); + return true; + } + + const TFunction *getFunction() const { return mFunction; } + + protected: + const TFunction *const mFunction; +}; + +// Node for function definitions. The prototype child node stores the function header including +// parameters, and the body child node stores the function body. +class TIntermFunctionDefinition : public TIntermNode +{ + public: + TIntermFunctionDefinition(TIntermFunctionPrototype *prototype, TIntermBlock *body) + : TIntermNode(), mPrototype(prototype), mBody(body) + { + ASSERT(prototype != nullptr); + ASSERT(body != nullptr); + } + + TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; } + void traverse(TIntermTraverser *it) final; + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + + TIntermFunctionPrototype *getFunctionPrototype() const { return mPrototype; } + TIntermBlock *getBody() const { return mBody; } + + const TFunction *getFunction() const { return mPrototype->getFunction(); } + + TIntermNode *deepCopy() const override + { + UNREACHABLE(); + return nullptr; + } + + private: + TIntermFunctionPrototype *mPrototype; + TIntermBlock *mBody; +}; + +// Struct, interface block or variable declaration. Can contain multiple variable declarators. +class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase +{ + public: + TIntermDeclaration() : TIntermNode() {} + TIntermDeclaration(const TVariable *var, TIntermTyped *initExpr); + TIntermDeclaration(std::initializer_list declarators); + TIntermDeclaration(std::initializer_list declarators); + ~TIntermDeclaration() override {} + + TIntermDeclaration *getAsDeclarationNode() override { return this; } + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + + // Only intended for initially building the declaration. + // The declarator node should be either TIntermSymbol or TIntermBinary with op set to + // EOpInitialize. + void appendDeclarator(TIntermTyped *declarator); + + TIntermSequence *getSequence() override { return &mDeclarators; } + const TIntermSequence *getSequence() const override { return &mDeclarators; } + + TIntermDeclaration *deepCopy() const override + { + // Note: This is only useful as support for deepCopy of TIntermBlock and TIntermLoop, but is + // not sufficient as it will be redeclaring the same TVariable. If a function body is + // duplicated for example, it means that both functions reference the same TVariable pointer + // which works, but is technically not correct. In particular, maps with TVariable * as key + // can get confused. + // + // After deepCopy() is issued, ReplaceVariables must be used to replace every declared + // variable with a duplicate. This is NOT automatically done when deepCopy-ing TIntermBlock + // and TIntermLoop nodes. + return new TIntermDeclaration(*this); + } + + protected: + TIntermDeclaration(const TIntermDeclaration &node); + + TIntermSequence mDeclarators; +}; + +// Specialized declarations for attributing invariance. +class TIntermGlobalQualifierDeclaration : public TIntermNode +{ + public: + TIntermGlobalQualifierDeclaration(TIntermSymbol *symbol, + bool isPrecise, + const TSourceLoc &line); + + virtual TIntermGlobalQualifierDeclaration *getAsGlobalQualifierDeclarationNode() override + { + return this; + } + bool visit(Visit visit, TIntermTraverser *it) final; + + TIntermSymbol *getSymbol() { return mSymbol; } + bool isInvariant() const { return !mIsPrecise; } + bool isPrecise() const { return mIsPrecise; } + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + + TIntermGlobalQualifierDeclaration *deepCopy() const override + { + return new TIntermGlobalQualifierDeclaration(*this); + } + + private: + TIntermSymbol *mSymbol; + // Either |precise| or |invariant|, determined based on this flag. + bool mIsPrecise; + + TIntermGlobalQualifierDeclaration(const TIntermGlobalQualifierDeclaration &); +}; + +// For ternary operators like a ? b : c. +class TIntermTernary : public TIntermExpression +{ + public: + TIntermTernary(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression); + + TIntermTernary *getAsTernaryNode() override { return this; } + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + + TIntermTyped *getCondition() const { return mCondition; } + TIntermTyped *getTrueExpression() const { return mTrueExpression; } + TIntermTyped *getFalseExpression() const { return mFalseExpression; } + + TIntermTyped *deepCopy() const override { return new TIntermTernary(*this); } + + bool hasSideEffects() const override + { + return mCondition->hasSideEffects() || mTrueExpression->hasSideEffects() || + mFalseExpression->hasSideEffects(); + } + + TIntermTyped *fold(TDiagnostics *diagnostics) override; + + private: + TIntermTernary(const TIntermTernary &node); // Note: not deleted, just private! + + static TQualifier DetermineQualifier(TIntermTyped *cond, + TIntermTyped *trueExpression, + TIntermTyped *falseExpression); + TPrecision derivePrecision() const override; + void propagatePrecision(TPrecision precision) override; + + TIntermTyped *mCondition; + TIntermTyped *mTrueExpression; + TIntermTyped *mFalseExpression; +}; + +class TIntermIfElse : public TIntermNode +{ + public: + TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB); + + TIntermIfElse *getAsIfElseNode() override { return this; } + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + + TIntermTyped *getCondition() const { return mCondition; } + TIntermBlock *getTrueBlock() const { return mTrueBlock; } + TIntermBlock *getFalseBlock() const { return mFalseBlock; } + + TIntermIfElse *deepCopy() const override { return new TIntermIfElse(*this); } + + protected: + TIntermTyped *mCondition; + TIntermBlock *mTrueBlock; + TIntermBlock *mFalseBlock; + + private: + TIntermIfElse(const TIntermIfElse &); +}; + +// +// Switch statement. +// +class TIntermSwitch : public TIntermNode +{ + public: + TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList); + + TIntermSwitch *getAsSwitchNode() override { return this; } + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + + TIntermTyped *getInit() { return mInit; } + TIntermBlock *getStatementList() { return mStatementList; } + + // Must be called with a non-null statementList. + void setStatementList(TIntermBlock *statementList); + + TIntermSwitch *deepCopy() const override { return new TIntermSwitch(*this); } + + protected: + TIntermTyped *mInit; + TIntermBlock *mStatementList; + + private: + TIntermSwitch(const TIntermSwitch &); +}; + +// +// Case label. +// +class TIntermCase : public TIntermNode +{ + public: + TIntermCase(TIntermTyped *condition) : TIntermNode(), mCondition(condition) {} + + TIntermCase *getAsCaseNode() override { return this; } + bool visit(Visit visit, TIntermTraverser *it) final; + + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + + bool hasCondition() const { return mCondition != nullptr; } + TIntermTyped *getCondition() const { return mCondition; } + + TIntermCase *deepCopy() const override { return new TIntermCase(*this); } + + protected: + TIntermTyped *mCondition; + + private: + TIntermCase(const TIntermCase &); +}; + +// +// Preprocessor Directive. +// #ifdef, #define, #if, #endif, etc. +// + +enum class PreprocessorDirective +{ + Define, + Ifdef, + If, + Endif, +}; + +class TIntermPreprocessorDirective final : public TIntermNode +{ + public: + // This could also take an ImmutableString as an argument. + TIntermPreprocessorDirective(PreprocessorDirective directive, ImmutableString command); + ~TIntermPreprocessorDirective() final; + + void traverse(TIntermTraverser *it) final; + bool visit(Visit visit, TIntermTraverser *it) final; + bool replaceChildNode(TIntermNode *, TIntermNode *) final { return false; } + + TIntermPreprocessorDirective *getAsPreprocessorDirective() final { return this; } + size_t getChildCount() const final; + TIntermNode *getChildNode(size_t index) const final; + + PreprocessorDirective getDirective() const { return mDirective; } + const ImmutableString &getCommand() const { return mCommand; } + + TIntermPreprocessorDirective *deepCopy() const override + { + return new TIntermPreprocessorDirective(*this); + } + + private: + PreprocessorDirective mDirective; + ImmutableString mCommand; + + TIntermPreprocessorDirective(const TIntermPreprocessorDirective &); +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_INTERMNODE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/IsASTDepthBelowLimit.cpp b/gfx/angle/checkout/src/compiler/translator/IsASTDepthBelowLimit.cpp new file mode 100644 index 0000000000..74a1b55807 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/IsASTDepthBelowLimit.cpp @@ -0,0 +1,37 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/IsASTDepthBelowLimit.h" + +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +// Traverse the tree and compute max depth. Takes a maximum depth limit to prevent stack overflow. +class MaxDepthTraverser : public TIntermTraverser +{ + public: + MaxDepthTraverser(int depthLimit) : TIntermTraverser(true, false, false, nullptr) + { + setMaxAllowedDepth(depthLimit); + } +}; + +} // anonymous namespace + +bool IsASTDepthBelowLimit(TIntermNode *root, int maxDepth) +{ + MaxDepthTraverser traverser(maxDepth + 1); + root->traverse(&traverser); + + return traverser.getMaxDepth() <= maxDepth; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/IsASTDepthBelowLimit.h b/gfx/angle/checkout/src/compiler/translator/IsASTDepthBelowLimit.h new file mode 100644 index 0000000000..17f85b513a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/IsASTDepthBelowLimit.h @@ -0,0 +1,20 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// IsASTDepthBelowLimit: Check whether AST depth is below a specific limit. + +#ifndef COMPILER_TRANSLATOR_ISASTDEPTHBELOWLIMIT_H_ +#define COMPILER_TRANSLATOR_ISASTDEPTHBELOWLIMIT_H_ + +namespace sh +{ + +class TIntermNode; + +bool IsASTDepthBelowLimit(TIntermNode *root, int maxDepth); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_ISASTDEPTHBELOWLIMIT_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/Operator.cpp b/gfx/angle/checkout/src/compiler/translator/Operator.cpp new file mode 100644 index 0000000000..3b636ad2af --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Operator.cpp @@ -0,0 +1,171 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/Operator_autogen.h" + +#include "common/debug.h" + +namespace sh +{ + +const char *GetOperatorString(TOperator op) +{ + switch (op) + { + // Note: EOpNull and EOpCall* can't be handled here. + + case EOpNegative: + return "-"; + case EOpPositive: + return "+"; + case EOpLogicalNot: + return "!"; + case EOpBitwiseNot: + return "~"; + + case EOpPostIncrement: + return "++"; + case EOpPostDecrement: + return "--"; + case EOpPreIncrement: + return "++"; + case EOpPreDecrement: + return "--"; + + case EOpArrayLength: + return ".length()"; + + case EOpAdd: + return "+"; + case EOpSub: + return "-"; + case EOpMul: + return "*"; + case EOpDiv: + return "/"; + case EOpIMod: + return "%"; + + case EOpEqual: + return "=="; + case EOpNotEqual: + return "!="; + case EOpLessThan: + return "<"; + case EOpGreaterThan: + return ">"; + case EOpLessThanEqual: + return "<="; + case EOpGreaterThanEqual: + return ">="; + + case EOpComma: + return ","; + + // Fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: + return "*"; + + case EOpLogicalOr: + return "||"; + case EOpLogicalXor: + return "^^"; + case EOpLogicalAnd: + return "&&"; + + case EOpBitShiftLeft: + return "<<"; + case EOpBitShiftRight: + return ">>"; + + case EOpBitwiseAnd: + return "&"; + case EOpBitwiseXor: + return "^"; + case EOpBitwiseOr: + return "|"; + + // Fall-through. + case EOpIndexDirect: + case EOpIndexIndirect: + return "[]"; + + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: + return "."; + + case EOpAssign: + case EOpInitialize: + return "="; + case EOpAddAssign: + return "+="; + case EOpSubAssign: + return "-="; + + // Fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + return "*="; + + case EOpDivAssign: + return "/="; + case EOpIModAssign: + return "%="; + case EOpBitShiftLeftAssign: + return "<<="; + case EOpBitShiftRightAssign: + return ">>="; + case EOpBitwiseAndAssign: + return "&="; + case EOpBitwiseXorAssign: + return "^="; + case EOpBitwiseOrAssign: + return "|="; + + default: + UNREACHABLE(); + break; + } + return ""; +} + +bool IsAssignment(TOperator op) +{ + switch (op) + { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + case EOpAssign: + case EOpAddAssign: + case EOpSubAssign: + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + case EOpDivAssign: + case EOpIModAssign: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: + return true; + default: + return false; + } +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/Operator_autogen.h b/gfx/angle/checkout/src/compiler/translator/Operator_autogen.h new file mode 100644 index 0000000000..153dcb6339 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Operator_autogen.h @@ -0,0 +1,578 @@ +// GENERATED FILE - DO NOT EDIT. +// Generated by gen_builtin_symbols.py using data from builtin_function_declarations.txt. +// +// Copyright 2021 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Operator_autogen.h: +// Operators used by the high-level (parse tree) representation. + +#ifndef COMPILER_TRANSLATOR_OPERATOR_AUTOGEN_H_ +#define COMPILER_TRANSLATOR_OPERATOR_AUTOGEN_H_ + +#include + +namespace sh +{ + +enum TOperator : uint16_t +{ + EOpNull, // if in a node, should only mean a node is still being built + + // Call a function defined in the AST. This might be a user-defined function or a function + // inserted by an AST transformation. + EOpCallFunctionInAST, + + // Call an internal helper function with a raw implementation - the implementation can't be + // subject to AST transformations. Raw functions have a few constraints to keep them compatible + // with AST traversers: + // * They should not return arrays. + // * They should not have out parameters. + // + // DEPRECATED; DO NOT USE. TODO: remove this. http://anglebug.com/6059 + // + EOpCallInternalRawFunction, + + // + // Branch (TIntermBranch) + // + + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, + + // + // Constructor (TIntermAggregate) + // + + EOpConstruct, + + // + // Unary operators with special GLSL syntax (TIntermUnary). + // + + EOpNegative, + EOpPositive, + EOpLogicalNot, + EOpBitwiseNot, + + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, + + EOpArrayLength, + + // + // Binary operators with special GLSL syntax (TIntermBinary). + // + + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpIMod, + + EOpEqual, + EOpNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + + EOpComma, + + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, + EOpMatrixTimesMatrix, + + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, + + EOpBitShiftLeft, + EOpBitShiftRight, + + EOpBitwiseAnd, + EOpBitwiseXor, + EOpBitwiseOr, + + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + EOpIndexDirectInterfaceBlock, + + // + // Moves (TIntermBinary) + // + + EOpAssign, + EOpInitialize, + EOpAddAssign, + EOpSubAssign, + + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + + EOpDivAssign, + EOpIModAssign, + EOpBitShiftLeftAssign, + EOpBitShiftRightAssign, + EOpBitwiseAndAssign, + EOpBitwiseXorAssign, + EOpBitwiseOrAssign, + + // Not an op, but a marker for the start of built-in ops. + EOpLastNonBuiltIn = EOpBitwiseOrAssign, + + // + // Built-in functions mapped to operators (either unary (TIntermUnary) or with multiple + // parameters (TIntermAggregate)) + // + + // Group Math + + // Group MathTrigonometric + EOpRadians, // Unary + EOpDegrees, // Unary + EOpSin, // Unary + EOpCos, // Unary + EOpTan, // Unary + EOpAsin, // Unary + EOpAcos, // Unary + EOpAtan, + EOpSinh, // Unary + EOpCosh, // Unary + EOpTanh, // Unary + EOpAsinh, // Unary + EOpAcosh, // Unary + EOpAtanh, // Unary + + // Group MathExponential + EOpPow, + EOpExp, // Unary + EOpLog, // Unary + EOpExp2, // Unary + EOpLog2, // Unary + EOpSqrt, // Unary + EOpInversesqrt, // Unary + + // Group MathCommon + EOpAbs, // Unary + EOpSign, // Unary + EOpFloor, // Unary + EOpTrunc, // Unary + EOpRound, // Unary + EOpRoundEven, // Unary + EOpCeil, // Unary + EOpFract, // Unary + EOpMod, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothstep, + EOpModf, + EOpIsnan, // Unary + EOpIsinf, // Unary + EOpFloatBitsToInt, // Unary + EOpFloatBitsToUint, // Unary + EOpIntBitsToFloat, // Unary + EOpUintBitsToFloat, // Unary + EOpFma, + EOpFrexp, + EOpLdexp, + EOpPackSnorm2x16, // Unary + EOpPackHalf2x16, // Unary + EOpUnpackSnorm2x16, // Unary + EOpUnpackHalf2x16, // Unary + EOpPackUnorm2x16, // Unary + EOpUnpackUnorm2x16, // Unary + EOpPackUnorm4x8, // Unary + EOpPackSnorm4x8, // Unary + EOpUnpackUnorm4x8, // Unary + EOpUnpackSnorm4x8, // Unary + EOpPackDouble2x32, // Unary + EOpUnpackDouble2x32, // Unary + + // Group MathGeometric + EOpLength, // Unary + EOpDistance, + EOpDot, + EOpCross, + EOpNormalize, // Unary + EOpFaceforward, + EOpReflect, + EOpRefract, + + // Group MathGeometricVS + EOpFtransform, + + // Group MathMatrix + EOpMatrixCompMult, + EOpOuterProduct, + EOpTranspose, // Unary + EOpDeterminant, // Unary + EOpInverse, // Unary + + // Group MathVector + EOpLessThanComponentWise, + EOpLessThanEqualComponentWise, + EOpGreaterThanComponentWise, + EOpGreaterThanEqualComponentWise, + EOpEqualComponentWise, + EOpNotEqualComponentWise, + EOpAny, // Unary + EOpAll, // Unary + EOpNotComponentWise, // Unary + + // Group MathInteger + EOpBitfieldExtract, + EOpBitfieldInsert, + EOpBitfieldReverse, // Unary + EOpBitCount, // Unary + EOpFindLSB, // Unary + EOpFindMSB, // Unary + EOpUaddCarry, + EOpUsubBorrow, + EOpUmulExtended, + EOpImulExtended, + + // Group Texture + + // Group TextureFirstVersions + EOpTexture2D, + EOpTexture2DProj, + EOpTextureCube, + EOpTexture1D, + EOpTexture1DProj, + EOpTexture3D, + EOpTexture3DProj, + EOpShadow1D, + EOpShadow1DProj, + EOpShadow2D, + EOpShadow2DProj, + EOpShadow2DEXT, + EOpShadow2DProjEXT, + EOpTexture2DRect, + EOpTexture2DRectProj, + EOpTexture2DGradEXT, + EOpTexture2DProjGradEXT, + EOpTextureCubeGradEXT, + EOpTextureVideoWEBGL, + + // Group TextureFirstVersionsBias + EOpTexture2DBias, + EOpTexture2DProjBias, + EOpTextureCubeBias, + EOpTexture3DBias, + EOpTexture3DProjBias, + EOpTexture1DBias, + EOpTexture1DProjBias, + EOpShadow1DBias, + EOpShadow1DProjBias, + EOpShadow2DBias, + EOpShadow2DProjBias, + + // Group TextureFirstVersionsLod + EOpTexture2DLod, + EOpTexture2DProjLod, + EOpTextureCubeLod, + EOpTexture1DLod, + EOpTexture1DProjLod, + EOpShadow1DLod, + EOpShadow1DProjLod, + EOpShadow2DLod, + EOpShadow2DProjLod, + EOpTexture3DLod, + EOpTexture3DProjLod, + + // Group TextureFirstVersionsLodVS + EOpTexture2DLodVS, + EOpTexture2DProjLodVS, + EOpTextureCubeLodVS, + + // Group TextureFirstVersionsLodFS + EOpTexture2DLodEXTFS, + EOpTexture2DProjLodEXTFS, + EOpTextureCubeLodEXTFS, + + // Group TextureNoBias + EOpTexture, + EOpTextureProj, + EOpTextureLod, + EOpTextureSize, + EOpTextureProjLod, + EOpTexelFetch, + EOpTextureGrad, + EOpTextureProjGrad, + EOpTextureQueryLevels, + EOpTextureSamples, + + // Group TextureBias + EOpTextureBias, + EOpTextureProjBias, + + // Group TextureQueryLod + EOpTextureQueryLod, + + // Group TextureOffsetNoBias + EOpTextureOffset, + EOpTextureProjOffset, + EOpTextureLodOffset, + EOpTextureProjLodOffset, + EOpTexelFetchOffset, + EOpTextureGradOffset, + EOpTextureProjGradOffset, + + // Group TextureOffsetBias + EOpTextureOffsetBias, + EOpTextureProjOffsetBias, + + // Group TextureGather + EOpTextureGather, + + // Group TextureGatherOffset + + // Group TextureGatherOffsetNoComp + EOpTextureGatherOffset, + + // Group TextureGatherOffsetComp + EOpTextureGatherOffsetComp, + + // Group TextureGatherOffsets + + // Group TextureGatherOffsetsNoComp + EOpTextureGatherOffsets, + + // Group TextureGatherOffsetsComp + EOpTextureGatherOffsetsComp, + + // Group EXT_YUV_target + EOpRgb_2_yuv, + EOpYuv_2_rgb, + + // Group DerivativesFS + EOpDFdx, + EOpDFdy, + EOpFwidth, + EOpDFdxFine, + EOpDFdyFine, + EOpDFdxCoarse, + EOpDFdyCoarse, + EOpFwidthFine, + EOpFwidthCoarse, + + // Group InterpolationFS + EOpInterpolateAtCentroid, + EOpInterpolateAtSample, + EOpInterpolateAtOffset, + + // Group AtomicCounter + EOpAtomicCounter, + EOpAtomicCounterIncrement, + EOpAtomicCounterDecrement, + EOpAtomicCounterAdd, + EOpAtomicCounterSubtract, + EOpAtomicCounterMin, + EOpAtomicCounterMax, + EOpAtomicCounterAnd, + EOpAtomicCounterOr, + EOpAtomicCounterXor, + EOpAtomicCounterExchange, + EOpAtomicCounterCompSwap, + + // Group AtomicMemory + EOpAtomicAdd, + EOpAtomicMin, + EOpAtomicMax, + EOpAtomicAnd, + EOpAtomicOr, + EOpAtomicXor, + EOpAtomicExchange, + EOpAtomicCompSwap, + + // Group Image + EOpImageSize, + EOpImageSamples, + + // Group ImageStore + EOpImageStore, + + // Group ImageLoad + EOpImageLoad, + + // Group ImageAtomic + EOpImageAtomicAdd, + EOpImageAtomicMin, + EOpImageAtomicMax, + EOpImageAtomicAnd, + EOpImageAtomicOr, + EOpImageAtomicXor, + EOpImageAtomicExchange, + EOpImageAtomicCompSwap, + + // Group PixelLocal + + // Group PixelLocalLoad + EOpPixelLocalLoadANGLE, + + // Group PixelLocalStore + EOpPixelLocalStoreANGLE, + + // Group FragmentSynchronization + EOpBeginInvocationInterlockNV, + EOpEndInvocationInterlockNV, + EOpBeginFragmentShaderOrderingINTEL, + EOpBeginInvocationInterlockARB, + EOpEndInvocationInterlockARB, + + // Group Noise + EOpNoise1, + EOpNoise2, + EOpNoise3, + EOpNoise4, + + // Group Barrier + EOpMemoryBarrier, + EOpMemoryBarrierAtomicCounter, + EOpMemoryBarrierBuffer, + EOpMemoryBarrierImage, + + // Group ESSL310CS + EOpBarrier, + EOpMemoryBarrierShared, + EOpGroupMemoryBarrier, + + // Group ESSL310TCS + EOpBarrierTCS, + + // Group GS + EOpEmitVertex, + EOpEndPrimitive, + EOpEmitStreamVertex, + EOpEndStreamPrimitive, + + // Group SubpassInput + EOpSubpassLoad, + + // Group ShaderInvocationGroup + EOpAnyInvocation, + EOpAllInvocations, + EOpAllInvocationsEqual, +}; + +// Returns the string corresponding to the operator in GLSL. For built-in functions use the +// function name directly. +const char *GetOperatorString(TOperator op); + +// Say whether or not a binary or unary operation changes the value of a variable. +bool IsAssignment(TOperator op); + +namespace BuiltInGroup +{ +static inline bool IsBuiltIn(TOperator op) +{ + return op > EOpLastNonBuiltIn; +} +static inline bool IsMath(TOperator op) +{ + return op >= EOpRadians && op <= EOpImulExtended; +} +static inline bool IsTextureOffsetNoBias(TOperator op) +{ + return op >= EOpTextureOffset && op <= EOpTextureProjGradOffset; +} +static inline bool IsTextureOffsetBias(TOperator op) +{ + return op >= EOpTextureOffsetBias && op <= EOpTextureProjOffsetBias; +} +static inline bool IsTextureGatherOffsetNoComp(TOperator op) +{ + return op >= EOpTextureGatherOffset && op <= EOpTextureGatherOffset; +} +static inline bool IsTextureGatherOffsetComp(TOperator op) +{ + return op >= EOpTextureGatherOffsetComp && op <= EOpTextureGatherOffsetComp; +} +static inline bool IsTextureGatherOffset(TOperator op) +{ + return op >= EOpTextureGatherOffset && op <= EOpTextureGatherOffsetComp; +} +static inline bool IsTextureGatherOffsetsNoComp(TOperator op) +{ + return op >= EOpTextureGatherOffsets && op <= EOpTextureGatherOffsets; +} +static inline bool IsTextureGatherOffsetsComp(TOperator op) +{ + return op >= EOpTextureGatherOffsetsComp && op <= EOpTextureGatherOffsetsComp; +} +static inline bool IsTextureGatherOffsets(TOperator op) +{ + return op >= EOpTextureGatherOffsets && op <= EOpTextureGatherOffsetsComp; +} +static inline bool IsTextureGather(TOperator op) +{ + return op >= EOpTextureGather && op <= EOpTextureGatherOffsetsComp; +} +static inline bool IsTexture(TOperator op) +{ + return op >= EOpTexture2D && op <= EOpTextureGatherOffsetsComp; +} +static inline bool IsDerivativesFS(TOperator op) +{ + return op >= EOpDFdx && op <= EOpFwidthCoarse; +} +static inline bool IsInterpolationFS(TOperator op) +{ + return op >= EOpInterpolateAtCentroid && op <= EOpInterpolateAtOffset; +} +static inline bool IsAtomicCounter(TOperator op) +{ + return op >= EOpAtomicCounter && op <= EOpAtomicCounterCompSwap; +} +static inline bool IsAtomicMemory(TOperator op) +{ + return op >= EOpAtomicAdd && op <= EOpAtomicCompSwap; +} +static inline bool IsImageStore(TOperator op) +{ + return op >= EOpImageStore && op <= EOpImageStore; +} +static inline bool IsImageLoad(TOperator op) +{ + return op >= EOpImageLoad && op <= EOpImageLoad; +} +static inline bool IsImageAtomic(TOperator op) +{ + return op >= EOpImageAtomicAdd && op <= EOpImageAtomicCompSwap; +} +static inline bool IsImage(TOperator op) +{ + return op >= EOpImageSize && op <= EOpImageAtomicCompSwap; +} +static inline bool IsPixelLocalLoad(TOperator op) +{ + return op >= EOpPixelLocalLoadANGLE && op <= EOpPixelLocalLoadANGLE; +} +static inline bool IsPixelLocalStore(TOperator op) +{ + return op >= EOpPixelLocalStoreANGLE && op <= EOpPixelLocalStoreANGLE; +} +static inline bool IsPixelLocal(TOperator op) +{ + return op >= EOpPixelLocalLoadANGLE && op <= EOpPixelLocalStoreANGLE; +} +} // namespace BuiltInGroup + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_OPERATOR_AUTOGEN_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/OutputESSL.cpp b/gfx/angle/checkout/src/compiler/translator/OutputESSL.cpp new file mode 100644 index 0000000000..95c7e1e0be --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/OutputESSL.cpp @@ -0,0 +1,55 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/OutputESSL.h" + +namespace sh +{ + +TOutputESSL::TOutputESSL(TCompiler *compiler, + TInfoSinkBase &objSink, + const ShCompileOptions &compileOptions) + : TOutputGLSLBase(compiler, objSink, compileOptions) +{} + +bool TOutputESSL::writeVariablePrecision(TPrecision precision) +{ + if (precision == EbpUndefined) + return false; + + if (precision == EbpHigh && !isHighPrecisionSupported()) + { + precision = EbpMedium; + } + + TInfoSinkBase &out = objSink(); + out << getPrecisionString(precision); + return true; +} + +ImmutableString TOutputESSL::translateTextureFunction(const ImmutableString &name, + const ShCompileOptions &option) +{ + // Check WEBGL_video_texture invocation first. + if (name == "textureVideoWEBGL") + { + if (option.takeVideoTextureAsExternalOES) + { + // TODO(http://anglebug.com/3889): Implement external image situation. + UNIMPLEMENTED(); + return ImmutableString(""); + } + else + { + // Default translating textureVideoWEBGL to texture2D. + return ImmutableString("texture2D"); + } + } + + return name; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/OutputESSL.h b/gfx/angle/checkout/src/compiler/translator/OutputESSL.h new file mode 100644 index 0000000000..9d14de2081 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/OutputESSL.h @@ -0,0 +1,30 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_OUTPUTESSL_H_ +#define COMPILER_TRANSLATOR_OUTPUTESSL_H_ + +#include "compiler/translator/OutputGLSLBase.h" + +namespace sh +{ + +class TOutputESSL : public TOutputGLSLBase +{ + public: + TOutputESSL(TCompiler *compiler, + TInfoSinkBase &objSink, + const ShCompileOptions &compileOptions); + + protected: + bool writeVariablePrecision(TPrecision precision) override; + ImmutableString translateTextureFunction(const ImmutableString &name, + const ShCompileOptions &option) override; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_OUTPUTESSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/OutputGLSL.cpp b/gfx/angle/checkout/src/compiler/translator/OutputGLSL.cpp new file mode 100644 index 0000000000..0045a76dfc --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/OutputGLSL.cpp @@ -0,0 +1,122 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/OutputGLSL.h" + +#include "compiler/translator/Compiler.h" + +namespace sh +{ + +TOutputGLSL::TOutputGLSL(TCompiler *compiler, + TInfoSinkBase &objSink, + const ShCompileOptions &compileOptions) + : TOutputGLSLBase(compiler, objSink, compileOptions) +{} + +bool TOutputGLSL::writeVariablePrecision(TPrecision) +{ + return false; +} + +void TOutputGLSL::visitSymbol(TIntermSymbol *node) +{ + TInfoSinkBase &out = objSink(); + + // All the special cases are built-ins, so if it's not a built-in we can return early. + if (node->variable().symbolType() != SymbolType::BuiltIn) + { + TOutputGLSLBase::visitSymbol(node); + return; + } + + // Some built-ins get a special translation. + const ImmutableString &name = node->getName(); + if (name == "gl_FragDepthEXT") + { + out << "gl_FragDepth"; + } + else if (name == "gl_FragColor" && sh::IsGLSL130OrNewer(getShaderOutput())) + { + out << "webgl_FragColor"; + } + else if (name == "gl_FragData" && sh::IsGLSL130OrNewer(getShaderOutput())) + { + out << "webgl_FragData"; + } + else if (name == "gl_SecondaryFragColorEXT") + { + out << "webgl_SecondaryFragColor"; + } + else if (name == "gl_SecondaryFragDataEXT") + { + out << "webgl_SecondaryFragData"; + } + else + { + TOutputGLSLBase::visitSymbol(node); + } +} + +ImmutableString TOutputGLSL::translateTextureFunction(const ImmutableString &name, + const ShCompileOptions &option) +{ + // Check WEBGL_video_texture invocation first. + if (name == "textureVideoWEBGL") + { + if (option.takeVideoTextureAsExternalOES) + { + // TODO(http://anglebug.com/3889): Implement external image situation. + UNIMPLEMENTED(); + return ImmutableString(""); + } + else + { + // Default translating textureVideoWEBGL to texture2D. + return ImmutableString("texture2D"); + } + } + + static const char *simpleRename[] = {"texture2DLodEXT", + "texture2DLod", + "texture2DProjLodEXT", + "texture2DProjLod", + "textureCubeLodEXT", + "textureCubeLod", + "texture2DGradEXT", + "texture2DGradARB", + "texture2DProjGradEXT", + "texture2DProjGradARB", + "textureCubeGradEXT", + "textureCubeGradARB", + nullptr, + nullptr}; + static const char *legacyToCoreRename[] = { + "texture2D", "texture", "texture2DProj", "textureProj", "texture2DLod", "textureLod", + "texture2DProjLod", "textureProjLod", "texture2DRect", "texture", "texture2DRectProj", + "textureProj", "textureCube", "texture", "textureCubeLod", "textureLod", + // Extensions + "texture2DLodEXT", "textureLod", "texture2DProjLodEXT", "textureProjLod", + "textureCubeLodEXT", "textureLod", "texture2DGradEXT", "textureGrad", + "texture2DProjGradEXT", "textureProjGrad", "textureCubeGradEXT", "textureGrad", "texture3D", + "texture", "texture3DProj", "textureProj", "texture3DLod", "textureLod", "texture3DProjLod", + "textureProjLod", "shadow2DEXT", "texture", "shadow2DProjEXT", "textureProj", nullptr, + nullptr}; + const char **mapping = + (sh::IsGLSL130OrNewer(getShaderOutput())) ? legacyToCoreRename : simpleRename; + + for (int i = 0; mapping[i] != nullptr; i += 2) + { + if (name == mapping[i]) + { + return ImmutableString(mapping[i + 1]); + } + } + + return name; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/OutputGLSL.h b/gfx/angle/checkout/src/compiler/translator/OutputGLSL.h new file mode 100644 index 0000000000..ff55e16a2a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/OutputGLSL.h @@ -0,0 +1,31 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_OUTPUTGLSL_H_ +#define COMPILER_TRANSLATOR_OUTPUTGLSL_H_ + +#include "compiler/translator/OutputGLSLBase.h" + +namespace sh +{ + +class TOutputGLSL : public TOutputGLSLBase +{ + public: + TOutputGLSL(TCompiler *compiler, + TInfoSinkBase &objSink, + const ShCompileOptions &compileOptions); + + protected: + bool writeVariablePrecision(TPrecision) override; + void visitSymbol(TIntermSymbol *node) override; + ImmutableString translateTextureFunction(const ImmutableString &name, + const ShCompileOptions &option) override; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_OUTPUTGLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/OutputGLSLBase.cpp b/gfx/angle/checkout/src/compiler/translator/OutputGLSLBase.cpp new file mode 100644 index 0000000000..9536fe1d03 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/OutputGLSLBase.cpp @@ -0,0 +1,1513 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/OutputGLSLBase.h" + +#include "angle_gl.h" +#include "common/debug.h" +#include "common/mathutil.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/util.h" + +#include + +namespace sh +{ + +namespace +{ + +bool isSingleStatement(TIntermNode *node) +{ + if (node->getAsFunctionDefinition()) + { + return false; + } + else if (node->getAsBlock()) + { + return false; + } + else if (node->getAsIfElseNode()) + { + return false; + } + else if (node->getAsLoopNode()) + { + return false; + } + else if (node->getAsSwitchNode()) + { + return false; + } + else if (node->getAsCaseNode()) + { + return false; + } + else if (node->getAsPreprocessorDirective()) + { + return false; + } + return true; +} + +class CommaSeparatedListItemPrefixGenerator +{ + public: + CommaSeparatedListItemPrefixGenerator() : mFirst(true) {} + + private: + bool mFirst; + + template + friend Stream &operator<<(Stream &out, CommaSeparatedListItemPrefixGenerator &gen); +}; + +template +Stream &operator<<(Stream &out, CommaSeparatedListItemPrefixGenerator &gen) +{ + if (gen.mFirst) + { + gen.mFirst = false; + } + else + { + out << ", "; + } + return out; +} + +} // namespace + +TOutputGLSLBase::TOutputGLSLBase(TCompiler *compiler, + TInfoSinkBase &objSink, + const ShCompileOptions &compileOptions) + : TIntermTraverser(true, true, true, &compiler->getSymbolTable()), + mObjSink(objSink), + mDeclaringVariable(false), + mHashFunction(compiler->getHashFunction()), + mNameMap(compiler->getNameMap()), + mShaderType(compiler->getShaderType()), + mShaderVersion(compiler->getShaderVersion()), + mOutput(compiler->getOutputType()), + mHighPrecisionSupported(compiler->isHighPrecisionSupported()), + // If pixel local storage introduces new fragment outputs, we are now required to specify a + // location for _all_ fragment outputs, including previously valid outputs that had an + // implicit location of zero. + mAlwaysSpecifyFragOutLocation(compiler->hasPixelLocalStorageUniforms() && + compileOptions.pls.type == + ShPixelLocalStorageType::FramebufferFetch), + mCompileOptions(compileOptions) +{} + +void TOutputGLSLBase::writeInvariantQualifier(const TType &type) +{ + if (!sh::RemoveInvariant(mShaderType, mShaderVersion, mOutput, mCompileOptions)) + { + TInfoSinkBase &out = objSink(); + out << "invariant "; + } +} + +void TOutputGLSLBase::writePreciseQualifier(const TType &type) +{ + TInfoSinkBase &out = objSink(); + out << "precise "; +} + +void TOutputGLSLBase::writeFloat(TInfoSinkBase &out, float f) +{ + if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300) + { + out << "uintBitsToFloat(" << gl::bitCast(f) << "u)"; + } + else + { + out << std::min(FLT_MAX, std::max(-FLT_MAX, f)); + } +} + +void TOutputGLSLBase::writeTriplet(Visit visit, + const char *preStr, + const char *inStr, + const char *postStr) +{ + TInfoSinkBase &out = objSink(); + if (visit == PreVisit && preStr) + out << preStr; + else if (visit == InVisit && inStr) + out << inStr; + else if (visit == PostVisit && postStr) + out << postStr; +} + +void TOutputGLSLBase::writeFunctionTriplet(Visit visit, + const ImmutableString &functionName, + bool useEmulatedFunction) +{ + TInfoSinkBase &out = objSink(); + if (visit == PreVisit) + { + if (useEmulatedFunction) + { + BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, functionName.data()); + } + else + { + out << functionName; + } + out << "("; + } + else + { + writeTriplet(visit, nullptr, ", ", ")"); + } +} + +// Outputs what goes inside layout(), except for location and binding qualifiers, as they are +// handled differently between GL GLSL and Vulkan GLSL. +std::string TOutputGLSLBase::getCommonLayoutQualifiers(TIntermSymbol *variable) +{ + std::ostringstream out; + CommaSeparatedListItemPrefixGenerator listItemPrefix; + + const TType &type = variable->getType(); + const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); + + if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqFragmentInOut) + { + if (layoutQualifier.index >= 0) + { + out << listItemPrefix << "index = " << layoutQualifier.index; + } + if (layoutQualifier.yuv) + { + out << listItemPrefix << "yuv"; + } + } + + if (type.getQualifier() == EvqFragmentInOut && layoutQualifier.noncoherent) + { + out << listItemPrefix << "noncoherent"; + } + + if (IsImage(type.getBasicType())) + { + if (layoutQualifier.imageInternalFormat != EiifUnspecified) + { + ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform); + out << listItemPrefix + << getImageInternalFormatString(layoutQualifier.imageInternalFormat); + } + } + + if (IsAtomicCounter(type.getBasicType())) + { + out << listItemPrefix << "offset = " << layoutQualifier.offset; + } + + return out.str(); +} + +// Outputs memory qualifiers applied to images, buffers and its fields, as well as image function +// arguments. +std::string TOutputGLSLBase::getMemoryQualifiers(const TType &type) +{ + std::ostringstream out; + + const TMemoryQualifier &memoryQualifier = type.getMemoryQualifier(); + if (memoryQualifier.readonly) + { + out << "readonly "; + } + + if (memoryQualifier.writeonly) + { + out << "writeonly "; + } + + if (memoryQualifier.coherent) + { + out << "coherent "; + } + + if (memoryQualifier.restrictQualifier) + { + out << "restrict "; + } + + if (memoryQualifier.volatileQualifier) + { + out << "volatile "; + } + + return out.str(); +} + +void TOutputGLSLBase::writeLayoutQualifier(TIntermSymbol *variable) +{ + const TType &type = variable->getType(); + + if (!needsToWriteLayoutQualifier(type)) + { + return; + } + + if (type.getBasicType() == EbtInterfaceBlock) + { + declareInterfaceBlockLayout(type); + return; + } + + TInfoSinkBase &out = objSink(); + const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); + out << "layout("; + + CommaSeparatedListItemPrefixGenerator listItemPrefix; + + if (IsFragmentOutput(type.getQualifier()) || type.getQualifier() == EvqVertexIn || + IsVarying(type.getQualifier())) + { + if (layoutQualifier.location >= 0 || + (mAlwaysSpecifyFragOutLocation && IsFragmentOutput(type.getQualifier()))) + { + out << listItemPrefix << "location = " << std::max(layoutQualifier.location, 0); + } + } + + if (IsOpaqueType(type.getBasicType())) + { + if (layoutQualifier.binding >= 0) + { + out << listItemPrefix << "binding = " << layoutQualifier.binding; + } + } + + std::string otherQualifiers = getCommonLayoutQualifiers(variable); + if (!otherQualifiers.empty()) + { + out << listItemPrefix << otherQualifiers; + } + + out << ") "; +} + +void TOutputGLSLBase::writeFieldLayoutQualifier(const TField *field) +{ + if (!field->type()->isMatrix() && !field->type()->isStructureContainingMatrices()) + { + return; + } + + TInfoSinkBase &out = objSink(); + + out << "layout("; + switch (field->type()->getLayoutQualifier().matrixPacking) + { + case EmpUnspecified: + case EmpColumnMajor: + // Default matrix packing is column major. + out << "column_major"; + break; + + case EmpRowMajor: + out << "row_major"; + break; + + default: + UNREACHABLE(); + break; + } + out << ") "; +} + +void TOutputGLSLBase::writeQualifier(TQualifier qualifier, const TType &type, const TSymbol *symbol) +{ + const char *result = mapQualifierToString(qualifier); + if (result && result[0] != '\0') + { + objSink() << result << " "; + } + + objSink() << getMemoryQualifiers(type); +} + +const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier) +{ + if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 && + mCompileOptions.removeInvariantAndCentroidForESSL3) + { + switch (qualifier) + { + // The return string is consistent with sh::getQualifierString() from + // BaseTypes.h minus the "centroid" keyword. + case EvqCentroid: + return ""; + case EvqCentroidIn: + return "smooth in"; + case EvqCentroidOut: + return "smooth out"; + default: + break; + } + } + if (sh::IsGLSL130OrNewer(mOutput)) + { + switch (qualifier) + { + case EvqAttribute: + return "in"; + case EvqVaryingIn: + return "in"; + case EvqVaryingOut: + return "out"; + default: + break; + } + } + + switch (qualifier) + { + // gl_ClipDistance / gl_CullDistance require different qualifiers based on shader type. + case EvqClipDistance: + case EvqCullDistance: + return mShaderType == GL_FRAGMENT_SHADER ? "in" : "out"; + + // gl_LastFragColor / gl_LastFragData have no qualifiers. + case EvqLastFragData: + case EvqLastFragColor: + return nullptr; + + default: + return sh::getQualifierString(qualifier); + } +} + +namespace +{ + +constexpr char kIndent[] = " "; // 10x2 spaces +constexpr int kIndentWidth = 2; +constexpr int kMaxIndentLevel = sizeof(kIndent) / kIndentWidth; + +} // namespace + +const char *TOutputGLSLBase::getIndentPrefix(int extraIndentation) +{ + int indentDepth = std::min(kMaxIndentLevel, getCurrentBlockDepth() + extraIndentation); + ASSERT(indentDepth >= 0); + return kIndent + (kMaxIndentLevel - indentDepth) * kIndentWidth; +} + +void TOutputGLSLBase::writeVariableType(const TType &type, + const TSymbol *symbol, + bool isFunctionArgument) +{ + TQualifier qualifier = type.getQualifier(); + TInfoSinkBase &out = objSink(); + if (type.isInvariant()) + { + writeInvariantQualifier(type); + } + if (type.isPrecise()) + { + writePreciseQualifier(type); + } + if (qualifier != EvqTemporary && qualifier != EvqGlobal) + { + writeQualifier(qualifier, type, symbol); + } + if (isFunctionArgument) + { + // Function arguments are the only place (other than image/SSBO/field declaration) where + // memory qualifiers can appear. + out << getMemoryQualifiers(type); + } + + // Declare the struct. + if (type.isStructSpecifier()) + { + const TStructure *structure = type.getStruct(); + + declareStruct(structure); + } + else if (type.getBasicType() == EbtInterfaceBlock) + { + declareInterfaceBlock(type); + } + else + { + if (writeVariablePrecision(type.getPrecision())) + out << " "; + out << getTypeName(type); + } +} + +void TOutputGLSLBase::writeFunctionParameters(const TFunction *func) +{ + TInfoSinkBase &out = objSink(); + size_t paramCount = func->getParamCount(); + for (size_t i = 0; i < paramCount; ++i) + { + const TVariable *param = func->getParam(i); + const TType &type = param->getType(); + writeVariableType(type, param, true); + + if (param->symbolType() != SymbolType::Empty) + { + out << " " << hashName(param); + } + if (type.isArray()) + { + out << ArrayString(type); + } + + // Put a comma if this is not the last argument. + if (i != paramCount - 1) + out << ", "; + } +} + +const TConstantUnion *TOutputGLSLBase::writeConstantUnion(const TType &type, + const TConstantUnion *pConstUnion) +{ + TInfoSinkBase &out = objSink(); + + if (type.getBasicType() == EbtStruct) + { + const TStructure *structure = type.getStruct(); + out << hashName(structure) << "("; + + const TFieldList &fields = structure->fields(); + for (size_t i = 0; i < fields.size(); ++i) + { + const TType *fieldType = fields[i]->type(); + ASSERT(fieldType != nullptr); + pConstUnion = writeConstantUnion(*fieldType, pConstUnion); + if (i != fields.size() - 1) + out << ", "; + } + out << ")"; + } + else + { + size_t size = type.getObjectSize(); + bool writeType = size > 1; + if (writeType) + out << getTypeName(type) << "("; + for (size_t i = 0; i < size; ++i, ++pConstUnion) + { + switch (pConstUnion->getType()) + { + case EbtFloat: + writeFloat(out, pConstUnion->getFConst()); + break; + case EbtInt: + out << pConstUnion->getIConst(); + break; + case EbtUInt: + out << pConstUnion->getUConst() << "u"; + break; + case EbtBool: + out << pConstUnion->getBConst(); + break; + case EbtYuvCscStandardEXT: + out << getYuvCscStandardEXTString(pConstUnion->getYuvCscStandardEXTConst()); + break; + default: + UNREACHABLE(); + } + if (i != size - 1) + out << ", "; + } + if (writeType) + out << ")"; + } + return pConstUnion; +} + +void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type) +{ + TInfoSinkBase &out = objSink(); + if (visit == PreVisit) + { + if (type.isArray()) + { + out << getTypeName(type); + out << ArrayString(type); + out << "("; + } + else + { + out << getTypeName(type) << "("; + } + } + else + { + writeTriplet(visit, nullptr, ", ", ")"); + } +} + +void TOutputGLSLBase::visitSymbol(TIntermSymbol *node) +{ + TInfoSinkBase &out = objSink(); + out << hashName(&node->variable()); + + if (mDeclaringVariable && node->getType().isArray()) + out << ArrayString(node->getType()); +} + +void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node) +{ + writeConstantUnion(node->getType(), node->getConstantValue()); +} + +bool TOutputGLSLBase::visitSwizzle(Visit visit, TIntermSwizzle *node) +{ + TInfoSinkBase &out = objSink(); + if (visit == PostVisit) + { + out << "."; + node->writeOffsetsAsXYZW(&out); + } + return true; +} + +bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) +{ + bool visitChildren = true; + TInfoSinkBase &out = objSink(); + switch (node->getOp()) + { + case EOpComma: + writeTriplet(visit, "(", ", ", ")"); + break; + case EOpInitialize: + if (visit == InVisit) + { + out << " = "; + // RHS of initialize is not being declared. + mDeclaringVariable = false; + } + break; + case EOpAssign: + writeTriplet(visit, "(", " = ", ")"); + break; + case EOpAddAssign: + writeTriplet(visit, "(", " += ", ")"); + break; + case EOpSubAssign: + writeTriplet(visit, "(", " -= ", ")"); + break; + case EOpDivAssign: + writeTriplet(visit, "(", " /= ", ")"); + break; + case EOpIModAssign: + writeTriplet(visit, "(", " %= ", ")"); + break; + // Notice the fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + writeTriplet(visit, "(", " *= ", ")"); + break; + case EOpBitShiftLeftAssign: + writeTriplet(visit, "(", " <<= ", ")"); + break; + case EOpBitShiftRightAssign: + writeTriplet(visit, "(", " >>= ", ")"); + break; + case EOpBitwiseAndAssign: + writeTriplet(visit, "(", " &= ", ")"); + break; + case EOpBitwiseXorAssign: + writeTriplet(visit, "(", " ^= ", ")"); + break; + case EOpBitwiseOrAssign: + writeTriplet(visit, "(", " |= ", ")"); + break; + + case EOpIndexDirect: + case EOpIndexIndirect: + writeTriplet(visit, nullptr, "[", "]"); + break; + case EOpIndexDirectStruct: + if (visit == InVisit) + { + // Here we are writing out "foo.bar", where "foo" is struct + // and "bar" is field. In AST, it is represented as a binary + // node, where left child represents "foo" and right child "bar". + // The node itself represents ".". The struct field "bar" is + // actually stored as an index into TStructure::fields. + out << "."; + const TStructure *structure = node->getLeft()->getType().getStruct(); + const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); + const TField *field = structure->fields()[index->getIConst(0)]; + + out << hashFieldName(field); + visitChildren = false; + } + break; + case EOpIndexDirectInterfaceBlock: + if (visit == InVisit) + { + out << "."; + const TInterfaceBlock *interfaceBlock = + node->getLeft()->getType().getInterfaceBlock(); + const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); + const TField *field = interfaceBlock->fields()[index->getIConst(0)]; + out << hashFieldName(field); + visitChildren = false; + } + break; + + case EOpAdd: + writeTriplet(visit, "(", " + ", ")"); + break; + case EOpSub: + writeTriplet(visit, "(", " - ", ")"); + break; + case EOpMul: + writeTriplet(visit, "(", " * ", ")"); + break; + case EOpDiv: + writeTriplet(visit, "(", " / ", ")"); + break; + case EOpIMod: + writeTriplet(visit, "(", " % ", ")"); + break; + case EOpBitShiftLeft: + writeTriplet(visit, "(", " << ", ")"); + break; + case EOpBitShiftRight: + writeTriplet(visit, "(", " >> ", ")"); + break; + case EOpBitwiseAnd: + writeTriplet(visit, "(", " & ", ")"); + break; + case EOpBitwiseXor: + writeTriplet(visit, "(", " ^ ", ")"); + break; + case EOpBitwiseOr: + writeTriplet(visit, "(", " | ", ")"); + break; + + case EOpEqual: + writeTriplet(visit, "(", " == ", ")"); + break; + case EOpNotEqual: + writeTriplet(visit, "(", " != ", ")"); + break; + case EOpLessThan: + writeTriplet(visit, "(", " < ", ")"); + break; + case EOpGreaterThan: + writeTriplet(visit, "(", " > ", ")"); + break; + case EOpLessThanEqual: + writeTriplet(visit, "(", " <= ", ")"); + break; + case EOpGreaterThanEqual: + writeTriplet(visit, "(", " >= ", ")"); + break; + + // Notice the fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: + writeTriplet(visit, "(", " * ", ")"); + break; + + case EOpLogicalOr: + writeTriplet(visit, "(", " || ", ")"); + break; + case EOpLogicalXor: + writeTriplet(visit, "(", " ^^ ", ")"); + break; + case EOpLogicalAnd: + writeTriplet(visit, "(", " && ", ")"); + break; + default: + UNREACHABLE(); + } + + return visitChildren; +} + +bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) +{ + const char *preString = ""; + const char *postString = ")"; + + switch (node->getOp()) + { + case EOpNegative: + preString = "(-"; + break; + case EOpPositive: + preString = "(+"; + break; + case EOpLogicalNot: + preString = "(!"; + break; + case EOpBitwiseNot: + preString = "(~"; + break; + + case EOpPostIncrement: + preString = "("; + postString = "++)"; + break; + case EOpPostDecrement: + preString = "("; + postString = "--)"; + break; + case EOpPreIncrement: + preString = "(++"; + break; + case EOpPreDecrement: + preString = "(--"; + break; + case EOpArrayLength: + preString = "(("; + postString = ").length())"; + break; + + default: + writeFunctionTriplet(visit, node->getFunction()->name(), + node->getUseEmulatedFunction()); + return true; + } + + writeTriplet(visit, preString, nullptr, postString); + + return true; +} + +bool TOutputGLSLBase::visitTernary(Visit visit, TIntermTernary *node) +{ + TInfoSinkBase &out = objSink(); + // Notice two brackets at the beginning and end. The outer ones + // encapsulate the whole ternary expression. This preserves the + // order of precedence when ternary expressions are used in a + // compound expression, i.e., c = 2 * (a < b ? 1 : 2). + out << "(("; + node->getCondition()->traverse(this); + out << ") ? ("; + node->getTrueExpression()->traverse(this); + out << ") : ("; + node->getFalseExpression()->traverse(this); + out << "))"; + return false; +} + +bool TOutputGLSLBase::visitIfElse(Visit visit, TIntermIfElse *node) +{ + TInfoSinkBase &out = objSink(); + + out << "if ("; + node->getCondition()->traverse(this); + out << ")\n"; + + visitCodeBlock(node->getTrueBlock()); + + if (node->getFalseBlock()) + { + out << getIndentPrefix() << "else\n"; + visitCodeBlock(node->getFalseBlock()); + } + return false; +} + +bool TOutputGLSLBase::visitSwitch(Visit visit, TIntermSwitch *node) +{ + ASSERT(node->getStatementList()); + writeTriplet(visit, "switch (", ") ", nullptr); + // The curly braces get written when visiting the statementList aggregate + return true; +} + +bool TOutputGLSLBase::visitCase(Visit visit, TIntermCase *node) +{ + if (node->hasCondition()) + { + writeTriplet(visit, "case (", nullptr, "):\n"); + return true; + } + else + { + TInfoSinkBase &out = objSink(); + out << "default:\n"; + return false; + } +} + +bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node) +{ + TInfoSinkBase &out = objSink(); + // Scope the blocks except when at the global scope. + if (getCurrentTraversalDepth() > 0) + { + out << "{\n"; + } + + for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); + iter != node->getSequence()->end(); ++iter) + { + TIntermNode *curNode = *iter; + ASSERT(curNode != nullptr); + + out << getIndentPrefix(curNode->getAsCaseNode() ? -1 : 0); + + curNode->traverse(this); + + if (isSingleStatement(curNode)) + out << ";\n"; + } + + // Scope the blocks except when at the global scope. + if (getCurrentTraversalDepth() > 0) + { + out << getIndentPrefix(-1) << "}\n"; + } + return false; +} + +bool TOutputGLSLBase::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) +{ + TIntermFunctionPrototype *prototype = node->getFunctionPrototype(); + prototype->traverse(this); + visitCodeBlock(node->getBody()); + + // Fully processed; no need to visit children. + return false; +} + +bool TOutputGLSLBase::visitGlobalQualifierDeclaration(Visit visit, + TIntermGlobalQualifierDeclaration *node) +{ + TInfoSinkBase &out = objSink(); + ASSERT(visit == PreVisit); + const TIntermSymbol *symbol = node->getSymbol(); + out << (node->isPrecise() ? "precise " : "invariant ") << hashName(&symbol->variable()); + return false; +} + +void TOutputGLSLBase::visitFunctionPrototype(TIntermFunctionPrototype *node) +{ + TInfoSinkBase &out = objSink(); + + const TType &type = node->getType(); + writeVariableType(type, node->getFunction(), false); + if (type.isArray()) + out << ArrayString(type); + + out << " " << hashFunctionNameIfNeeded(node->getFunction()); + + out << "("; + writeFunctionParameters(node->getFunction()); + out << ")"; +} + +bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) +{ + bool visitChildren = true; + if (node->getOp() == EOpConstruct) + { + writeConstructorTriplet(visit, node->getType()); + } + else + { + // Function call. + ImmutableString functionName = node->getFunction()->name(); + if (visit == PreVisit) + { + // No raw function is expected. + ASSERT(node->getOp() != EOpCallInternalRawFunction); + + if (node->getOp() == EOpCallFunctionInAST) + { + functionName = hashFunctionNameIfNeeded(node->getFunction()); + } + else + { + functionName = + translateTextureFunction(node->getFunction()->name(), mCompileOptions); + } + } + writeFunctionTriplet(visit, functionName, node->getUseEmulatedFunction()); + } + return visitChildren; +} + +bool TOutputGLSLBase::visitDeclaration(Visit visit, TIntermDeclaration *node) +{ + TInfoSinkBase &out = objSink(); + + // Variable declaration. + if (visit == PreVisit) + { + const TIntermSequence &sequence = *(node->getSequence()); + TIntermTyped *decl = sequence.front()->getAsTyped(); + TIntermSymbol *symbolNode = decl->getAsSymbolNode(); + if (symbolNode == nullptr) + { + ASSERT(decl->getAsBinaryNode() && decl->getAsBinaryNode()->getOp() == EOpInitialize); + symbolNode = decl->getAsBinaryNode()->getLeft()->getAsSymbolNode(); + } + ASSERT(symbolNode); + + if (symbolNode->getName() != "gl_ClipDistance" && + symbolNode->getName() != "gl_CullDistance") + { + // gl_Clip/CullDistance re-declaration doesn't need layout. + writeLayoutQualifier(symbolNode); + } + + writeVariableType(symbolNode->getType(), &symbolNode->variable(), false); + if (symbolNode->variable().symbolType() != SymbolType::Empty) + { + out << " "; + } + mDeclaringVariable = true; + } + else if (visit == InVisit) + { + UNREACHABLE(); + } + else + { + mDeclaringVariable = false; + } + return true; +} + +bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) +{ + TInfoSinkBase &out = objSink(); + + TLoopType loopType = node->getType(); + + if (loopType == ELoopFor) // for loop + { + out << "for ("; + if (node->getInit()) + node->getInit()->traverse(this); + out << "; "; + + if (node->getCondition()) + node->getCondition()->traverse(this); + out << "; "; + + if (node->getExpression()) + node->getExpression()->traverse(this); + out << ")\n"; + + visitCodeBlock(node->getBody()); + } + else if (loopType == ELoopWhile) // while loop + { + out << "while ("; + ASSERT(node->getCondition() != nullptr); + node->getCondition()->traverse(this); + out << ")\n"; + + visitCodeBlock(node->getBody()); + } + else // do-while loop + { + ASSERT(loopType == ELoopDoWhile); + out << "do\n"; + + visitCodeBlock(node->getBody()); + + out << "while ("; + ASSERT(node->getCondition() != nullptr); + node->getCondition()->traverse(this); + out << ");\n"; + } + + // No need to visit children. They have been already processed in + // this function. + return false; +} + +bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch *node) +{ + switch (node->getFlowOp()) + { + case EOpKill: + writeTriplet(visit, "discard", nullptr, nullptr); + break; + case EOpBreak: + writeTriplet(visit, "break", nullptr, nullptr); + break; + case EOpContinue: + writeTriplet(visit, "continue", nullptr, nullptr); + break; + case EOpReturn: + writeTriplet(visit, "return ", nullptr, nullptr); + break; + default: + UNREACHABLE(); + } + + return true; +} + +void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node) +{ + TInfoSinkBase &out = objSink(); + if (node != nullptr) + { + out << getIndentPrefix(); + node->traverse(this); + // Single statements not part of a sequence need to be terminated + // with semi-colon. + if (isSingleStatement(node)) + out << ";\n"; + } + else + { + out << "{\n}\n"; // Empty code block. + } +} + +void TOutputGLSLBase::visitPreprocessorDirective(TIntermPreprocessorDirective *node) +{ + TInfoSinkBase &out = objSink(); + + out << "\n"; + + switch (node->getDirective()) + { + case PreprocessorDirective::Define: + out << "#define"; + break; + case PreprocessorDirective::Endif: + out << "#endif"; + break; + case PreprocessorDirective::If: + out << "#if"; + break; + case PreprocessorDirective::Ifdef: + out << "#ifdef"; + break; + + default: + UNREACHABLE(); + break; + } + + if (!node->getCommand().empty()) + { + out << " " << node->getCommand(); + } + + out << "\n"; +} + +ImmutableString TOutputGLSLBase::getTypeName(const TType &type) +{ + if (type.getBasicType() == EbtSamplerVideoWEBGL) + { + // TODO(http://anglebug.com/3889): translate SamplerVideoWEBGL into different token + // when necessary (e.g. on Android devices) + return ImmutableString("sampler2D"); + } + + return GetTypeName(type, mHashFunction, &mNameMap); +} + +ImmutableString TOutputGLSLBase::hashName(const TSymbol *symbol) +{ + return HashName(symbol, mHashFunction, &mNameMap); +} + +ImmutableString TOutputGLSLBase::hashFieldName(const TField *field) +{ + ASSERT(field->symbolType() != SymbolType::Empty); + if (field->symbolType() == SymbolType::UserDefined) + { + return HashName(field->name(), mHashFunction, &mNameMap); + } + + return field->name(); +} + +ImmutableString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunction *func) +{ + if (func->isMain()) + { + return func->name(); + } + else + { + return hashName(func); + } +} + +void TOutputGLSLBase::declareStruct(const TStructure *structure) +{ + TInfoSinkBase &out = objSink(); + + out << "struct "; + + if (structure->symbolType() != SymbolType::Empty) + { + out << hashName(structure) << " "; + } + out << "{\n"; + const TFieldList &fields = structure->fields(); + for (size_t i = 0; i < fields.size(); ++i) + { + out << getIndentPrefix(1); + const TField *field = fields[i]; + const TType &fieldType = *field->type(); + if (writeVariablePrecision(fieldType.getPrecision())) + { + out << " "; + } + if (fieldType.isPrecise()) + { + writePreciseQualifier(fieldType); + } + out << getTypeName(fieldType) << " " << hashFieldName(field); + if (fieldType.isArray()) + { + out << ArrayString(fieldType); + } + out << ";\n"; + } + out << getIndentPrefix() << "}"; +} + +void TOutputGLSLBase::declareInterfaceBlockLayout(const TType &type) +{ + // 4.4.5 Uniform and Shader Storage Block Layout Qualifiers in GLSL 4.5 spec. + // Layout qualifiers can be used for uniform and shader storage blocks, + // but not for non-block uniform declarations. + if (IsShaderIoBlock(type.getQualifier())) + { + return; + } + + const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + TInfoSinkBase &out = objSink(); + + out << "layout("; + + switch (interfaceBlock->blockStorage()) + { + case EbsUnspecified: + case EbsShared: + // Default block storage is shared. + out << "shared"; + break; + + case EbsPacked: + out << "packed"; + break; + + case EbsStd140: + out << "std140"; + break; + + case EbsStd430: + out << "std430"; + break; + + default: + UNREACHABLE(); + break; + } + + if (interfaceBlock->blockBinding() >= 0) + { + out << ", "; + out << "binding = " << interfaceBlock->blockBinding(); + } + + out << ") "; +} + +const char *getVariableInterpolation(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqSmoothOut: + return "smooth out "; + case EvqFlatOut: + return "flat out "; + case EvqNoPerspectiveOut: + return "noperspective out "; + case EvqCentroidOut: + return "centroid out "; + case EvqSmoothIn: + return "smooth in "; + case EvqFlatIn: + return "flat in "; + case EvqNoPerspectiveIn: + return "noperspective in "; + case EvqCentroidIn: + return "centroid in "; + default: + break; + } + return nullptr; +} + +void TOutputGLSLBase::declareInterfaceBlock(const TType &type) +{ + const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + TInfoSinkBase &out = objSink(); + + out << hashName(interfaceBlock) << "{\n"; + const TFieldList &fields = interfaceBlock->fields(); + for (const TField *field : fields) + { + out << getIndentPrefix(1); + if (!IsShaderIoBlock(type.getQualifier()) && type.getQualifier() != EvqPatchIn && + type.getQualifier() != EvqPatchOut) + { + writeFieldLayoutQualifier(field); + } + + const TType &fieldType = *field->type(); + + out << getMemoryQualifiers(fieldType); + if (writeVariablePrecision(fieldType.getPrecision())) + out << " "; + if (fieldType.isInvariant()) + { + writeInvariantQualifier(fieldType); + } + if (fieldType.isPrecise()) + { + writePreciseQualifier(fieldType); + } + + const char *qualifier = getVariableInterpolation(fieldType.getQualifier()); + if (qualifier != nullptr) + out << qualifier; + + out << getTypeName(fieldType) << " " << hashFieldName(field); + + if (fieldType.isArray()) + out << ArrayString(fieldType); + out << ";\n"; + } + out << "}"; +} + +void WritePragma(TInfoSinkBase &out, const ShCompileOptions &compileOptions, const TPragma &pragma) +{ + if (!compileOptions.flattenPragmaSTDGLInvariantAll) + { + if (pragma.stdgl.invariantAll) + out << "#pragma STDGL invariant(all)\n"; + } +} + +void WriteGeometryShaderLayoutQualifiers(TInfoSinkBase &out, + sh::TLayoutPrimitiveType inputPrimitive, + int invocations, + sh::TLayoutPrimitiveType outputPrimitive, + int maxVertices) +{ + // Omit 'invocations = 1' + if (inputPrimitive != EptUndefined || invocations > 1) + { + out << "layout ("; + + if (inputPrimitive != EptUndefined) + { + out << getGeometryShaderPrimitiveTypeString(inputPrimitive); + } + + if (invocations > 1) + { + if (inputPrimitive != EptUndefined) + { + out << ", "; + } + out << "invocations = " << invocations; + } + out << ") in;\n"; + } + + if (outputPrimitive != EptUndefined || maxVertices != -1) + { + out << "layout ("; + + if (outputPrimitive != EptUndefined) + { + out << getGeometryShaderPrimitiveTypeString(outputPrimitive); + } + + if (maxVertices != -1) + { + if (outputPrimitive != EptUndefined) + { + out << ", "; + } + out << "max_vertices = " << maxVertices; + } + out << ") out;\n"; + } +} + +void WriteTessControlShaderLayoutQualifiers(TInfoSinkBase &out, int inputVertices) +{ + if (inputVertices != 0) + { + out << "layout (vertices = " << inputVertices << ") out;\n"; + } +} + +void WriteTessEvaluationShaderLayoutQualifiers(TInfoSinkBase &out, + sh::TLayoutTessEvaluationType inputPrimitive, + sh::TLayoutTessEvaluationType inputVertexSpacing, + sh::TLayoutTessEvaluationType inputOrdering, + sh::TLayoutTessEvaluationType inputPoint) +{ + if (inputPrimitive != EtetUndefined) + { + out << "layout ("; + out << getTessEvaluationShaderTypeString(inputPrimitive); + if (inputVertexSpacing != EtetUndefined) + { + out << ", " << getTessEvaluationShaderTypeString(inputVertexSpacing); + } + if (inputOrdering != EtetUndefined) + { + out << ", " << getTessEvaluationShaderTypeString(inputOrdering); + } + if (inputPoint != EtetUndefined) + { + out << ", " << getTessEvaluationShaderTypeString(inputPoint); + } + out << ") in;\n"; + } +} + +// If SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS is enabled, layout qualifiers are spilled whenever +// variables with specified layout qualifiers are copied. Additional checks are needed against the +// type and storage qualifier of the variable to verify that layout qualifiers have to be outputted. +// TODO (mradev): Fix layout qualifier spilling in ScalarizeVecAndMatConstructorArgs and remove +// NeedsToWriteLayoutQualifier. +bool TOutputGLSLBase::needsToWriteLayoutQualifier(const TType &type) +{ + if (type.getBasicType() == EbtInterfaceBlock) + { + return true; + } + + const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); + + if (IsFragmentOutput(type.getQualifier()) || type.getQualifier() == EvqVertexIn || + IsVarying(type.getQualifier())) + { + if (layoutQualifier.location >= 0 || + (mAlwaysSpecifyFragOutLocation && IsFragmentOutput(type.getQualifier()))) + { + return true; + } + } + + if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqFragmentInOut) + { + if (layoutQualifier.index >= 0) + { + return true; + } + if (layoutQualifier.yuv) + { + return true; + } + } + + if (type.getQualifier() == EvqFragmentInOut && layoutQualifier.noncoherent) + { + return true; + } + + if (IsOpaqueType(type.getBasicType()) && layoutQualifier.binding != -1) + { + return true; + } + + if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified) + { + return true; + } + return false; +} + +void EmitEarlyFragmentTestsGLSL(const TCompiler &compiler, TInfoSinkBase &sink) +{ + if (compiler.isEarlyFragmentTestsSpecified()) + { + sink << "layout (early_fragment_tests) in;\n"; + } +} + +void EmitWorkGroupSizeGLSL(const TCompiler &compiler, TInfoSinkBase &sink) +{ + if (compiler.isComputeShaderLocalSizeDeclared()) + { + const sh::WorkGroupSize &localSize = compiler.getComputeShaderLocalSize(); + sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1] + << ", local_size_z=" << localSize[2] << ") in;\n"; + } +} + +void EmitMultiviewGLSL(const TCompiler &compiler, + const ShCompileOptions &compileOptions, + const TExtension extension, + const TBehavior behavior, + TInfoSinkBase &sink) +{ + ASSERT(behavior != EBhUndefined); + if (behavior == EBhDisable) + return; + + const bool isVertexShader = (compiler.getShaderType() == GL_VERTEX_SHADER); + if (compileOptions.initializeBuiltinsForInstancedMultiview) + { + // Emit ARB_shader_viewport_layer_array/NV_viewport_array2 in a vertex shader if the + // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set and the + // OVR_multiview(2) extension is requested. + if (isVertexShader && compileOptions.selectViewInNvGLSLVertexShader) + { + sink << "#if defined(GL_ARB_shader_viewport_layer_array)\n" + << "#extension GL_ARB_shader_viewport_layer_array : require\n" + << "#elif defined(GL_NV_viewport_array2)\n" + << "#extension GL_NV_viewport_array2 : require\n" + << "#endif\n"; + } + } + else + { + sink << "#extension GL_OVR_multiview"; + if (extension == TExtension::OVR_multiview2) + { + sink << "2"; + } + sink << " : " << GetBehaviorString(behavior) << "\n"; + + const auto &numViews = compiler.getNumViews(); + if (isVertexShader && numViews != -1) + { + sink << "layout(num_views=" << numViews << ") in;\n"; + } + } +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/OutputGLSLBase.h b/gfx/angle/checkout/src/compiler/translator/OutputGLSLBase.h new file mode 100644 index 0000000000..5552eb606f --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/OutputGLSLBase.h @@ -0,0 +1,154 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ +#define COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ + +#include + +#include "compiler/translator/ExtensionBehavior.h" +#include "compiler/translator/HashNames.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/Pragma.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ +class TCompiler; + +class TOutputGLSLBase : public TIntermTraverser +{ + public: + TOutputGLSLBase(TCompiler *compiler, + TInfoSinkBase &objSink, + const ShCompileOptions &compileOptions); + + ShShaderOutput getShaderOutput() const { return mOutput; } + + // Return the original name if hash function pointer is NULL; + // otherwise return the hashed name. Has special handling for internal names and built-ins, + // which are not hashed. + ImmutableString hashName(const TSymbol *symbol); + + protected: + TInfoSinkBase &objSink() { return mObjSink; } + void writeFloat(TInfoSinkBase &out, float f); + void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr); + std::string getCommonLayoutQualifiers(TIntermSymbol *variable); + std::string getMemoryQualifiers(const TType &type); + virtual void writeLayoutQualifier(TIntermSymbol *variable); + void writeFieldLayoutQualifier(const TField *field); + void writeInvariantQualifier(const TType &type); + void writePreciseQualifier(const TType &type); + virtual void writeVariableType(const TType &type, + const TSymbol *symbol, + bool isFunctionArgument); + virtual bool writeVariablePrecision(TPrecision precision) = 0; + void writeFunctionParameters(const TFunction *func); + const TConstantUnion *writeConstantUnion(const TType &type, const TConstantUnion *pConstUnion); + void writeConstructorTriplet(Visit visit, const TType &type); + ImmutableString getTypeName(const TType &type); + + void visitSymbol(TIntermSymbol *node) override; + void visitConstantUnion(TIntermConstantUnion *node) override; + bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; + bool visitBinary(Visit visit, TIntermBinary *node) override; + bool visitUnary(Visit visit, TIntermUnary *node) override; + bool visitTernary(Visit visit, TIntermTernary *node) override; + bool visitIfElse(Visit visit, TIntermIfElse *node) override; + bool visitSwitch(Visit visit, TIntermSwitch *node) override; + bool visitCase(Visit visit, TIntermCase *node) override; + void visitFunctionPrototype(TIntermFunctionPrototype *node) override; + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + bool visitBlock(Visit visit, TIntermBlock *node) override; + bool visitGlobalQualifierDeclaration(Visit visit, + TIntermGlobalQualifierDeclaration *node) override; + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; + bool visitLoop(Visit visit, TIntermLoop *node) override; + bool visitBranch(Visit visit, TIntermBranch *node) override; + void visitPreprocessorDirective(TIntermPreprocessorDirective *node) override; + + void visitCodeBlock(TIntermBlock *node); + + ImmutableString hashFieldName(const TField *field); + // Same as hashName(), but without hashing "main". + ImmutableString hashFunctionNameIfNeeded(const TFunction *func); + // Used to translate function names for differences between ESSL and GLSL + virtual ImmutableString translateTextureFunction(const ImmutableString &name, + const ShCompileOptions &option) + { + return name; + } + + void declareStruct(const TStructure *structure); + void writeQualifier(TQualifier qualifier, const TType &type, const TSymbol *symbol); + + const char *mapQualifierToString(TQualifier qualifier); + + sh::GLenum getShaderType() const { return mShaderType; } + bool isHighPrecisionSupported() const { return mHighPrecisionSupported; } + const char *getIndentPrefix(int extraIndentDepth = 0); + + bool needsToWriteLayoutQualifier(const TType &type); + + private: + void declareInterfaceBlockLayout(const TType &type); + void declareInterfaceBlock(const TType &type); + + void writeFunctionTriplet(Visit visit, + const ImmutableString &functionName, + bool useEmulatedFunction); + + TInfoSinkBase &mObjSink; + bool mDeclaringVariable; + + // name hashing. + ShHashFunction64 mHashFunction; + NameMap &mNameMap; + + sh::GLenum mShaderType; + const int mShaderVersion; + ShShaderOutput mOutput; + + bool mHighPrecisionSupported; + + // Emit "layout(locaton = 0)" for fragment outputs whose location is unspecified. This is for + // transformations like pixel local storage, where new outputs are introduced to the shader, and + // previously valid fragment outputs with an implicit location of 0 are now required to specify + // their location. + bool mAlwaysSpecifyFragOutLocation; + + const ShCompileOptions &mCompileOptions; +}; + +void WritePragma(TInfoSinkBase &out, const ShCompileOptions &compileOptions, const TPragma &pragma); + +void WriteGeometryShaderLayoutQualifiers(TInfoSinkBase &out, + sh::TLayoutPrimitiveType inputPrimitive, + int invocations, + sh::TLayoutPrimitiveType outputPrimitive, + int maxVertices); + +void WriteTessControlShaderLayoutQualifiers(TInfoSinkBase &out, int inputVertices); + +void WriteTessEvaluationShaderLayoutQualifiers(TInfoSinkBase &out, + sh::TLayoutTessEvaluationType inputPrimitive, + sh::TLayoutTessEvaluationType inputVertexSpacing, + sh::TLayoutTessEvaluationType inputOrdering, + sh::TLayoutTessEvaluationType inputPoint); + +void EmitEarlyFragmentTestsGLSL(const TCompiler &, TInfoSinkBase &sink); +void EmitWorkGroupSizeGLSL(const TCompiler &, TInfoSinkBase &sink); +void EmitMultiviewGLSL(const TCompiler &, + const ShCompileOptions &, + const TExtension, + const TBehavior, + TInfoSinkBase &sink); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/OutputHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/OutputHLSL.cpp new file mode 100644 index 0000000000..12f220b448 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/OutputHLSL.cpp @@ -0,0 +1,3700 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/OutputHLSL.h" + +#include +#include +#include + +#include "common/angleutils.h" +#include "common/debug.h" +#include "common/utilities.h" +#include "compiler/translator/AtomicCounterFunctionHLSL.h" +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h" +#include "compiler/translator/ImageFunctionHLSL.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/ResourcesHLSL.h" +#include "compiler/translator/StructureHLSL.h" +#include "compiler/translator/TextureFunctionHLSL.h" +#include "compiler/translator/TranslatorHLSL.h" +#include "compiler/translator/UtilsHLSL.h" +#include "compiler/translator/blocklayout.h" +#include "compiler/translator/tree_ops/d3d/RemoveSwitchFallThrough.h" +#include "compiler/translator/tree_util/FindSymbolNode.h" +#include "compiler/translator/tree_util/NodeSearch.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +constexpr const char kImage2DFunctionString[] = "// @@ IMAGE2D DECLARATION FUNCTION STRING @@"; + +TString ArrayHelperFunctionName(const char *prefix, const TType &type) +{ + TStringStream fnName = sh::InitializeStream(); + fnName << prefix << "_"; + if (type.isArray()) + { + for (unsigned int arraySize : type.getArraySizes()) + { + fnName << arraySize << "_"; + } + } + fnName << TypeString(type); + return fnName.str(); +} + +bool IsDeclarationWrittenOut(TIntermDeclaration *node) +{ + TIntermSequence *sequence = node->getSequence(); + TIntermTyped *variable = (*sequence)[0]->getAsTyped(); + ASSERT(sequence->size() == 1); + ASSERT(variable); + return (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal || + variable->getQualifier() == EvqConst || variable->getQualifier() == EvqShared); +} + +bool IsInStd140UniformBlock(TIntermTyped *node) +{ + TIntermBinary *binaryNode = node->getAsBinaryNode(); + + if (binaryNode) + { + return IsInStd140UniformBlock(binaryNode->getLeft()); + } + + const TType &type = node->getType(); + + if (type.getQualifier() == EvqUniform) + { + // determine if we are in the standard layout + const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + if (interfaceBlock) + { + return (interfaceBlock->blockStorage() == EbsStd140); + } + } + + return false; +} + +const TInterfaceBlock *GetInterfaceBlockOfUniformBlockNearestIndexOperator(TIntermTyped *node) +{ + const TIntermBinary *binaryNode = node->getAsBinaryNode(); + if (binaryNode) + { + if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock) + { + return binaryNode->getLeft()->getType().getInterfaceBlock(); + } + } + + const TIntermSymbol *symbolNode = node->getAsSymbolNode(); + if (symbolNode) + { + const TVariable &variable = symbolNode->variable(); + const TType &variableType = variable.getType(); + + if (variableType.getQualifier() == EvqUniform && + variable.symbolType() == SymbolType::UserDefined) + { + return variableType.getInterfaceBlock(); + } + } + + return nullptr; +} + +const char *GetHLSLAtomicFunctionStringAndLeftParenthesis(TOperator op) +{ + switch (op) + { + case EOpAtomicAdd: + return "InterlockedAdd("; + case EOpAtomicMin: + return "InterlockedMin("; + case EOpAtomicMax: + return "InterlockedMax("; + case EOpAtomicAnd: + return "InterlockedAnd("; + case EOpAtomicOr: + return "InterlockedOr("; + case EOpAtomicXor: + return "InterlockedXor("; + case EOpAtomicExchange: + return "InterlockedExchange("; + case EOpAtomicCompSwap: + return "InterlockedCompareExchange("; + default: + UNREACHABLE(); + return ""; + } +} + +bool IsAtomicFunctionForSharedVariableDirectAssign(const TIntermBinary &node) +{ + TIntermAggregate *aggregateNode = node.getRight()->getAsAggregate(); + if (aggregateNode == nullptr) + { + return false; + } + + if (node.getOp() == EOpAssign && BuiltInGroup::IsAtomicMemory(aggregateNode->getOp())) + { + return !IsInShaderStorageBlock((*aggregateNode->getSequence())[0]->getAsTyped()); + } + + return false; +} + +const char *kZeros = "_ANGLE_ZEROS_"; +constexpr int kZeroCount = 256; +std::string DefineZeroArray() +{ + std::stringstream ss = sh::InitializeStream(); + // For 'static', if the declaration does not include an initializer, the value is set to zero. + // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-variable-syntax + ss << "static uint " << kZeros << "[" << kZeroCount << "];\n"; + return ss.str(); +} + +std::string GetZeroInitializer(size_t size) +{ + std::stringstream ss = sh::InitializeStream(); + size_t quotient = size / kZeroCount; + size_t reminder = size % kZeroCount; + + for (size_t i = 0; i < quotient; ++i) + { + if (i != 0) + { + ss << ", "; + } + ss << kZeros; + } + + for (size_t i = 0; i < reminder; ++i) + { + if (quotient != 0 || i != 0) + { + ss << ", "; + } + ss << "0"; + } + + return ss.str(); +} + +} // anonymous namespace + +TReferencedBlock::TReferencedBlock(const TInterfaceBlock *aBlock, + const TVariable *aInstanceVariable) + : block(aBlock), instanceVariable(aInstanceVariable) +{} + +bool OutputHLSL::needStructMapping(TIntermTyped *node) +{ + ASSERT(node->getBasicType() == EbtStruct); + for (unsigned int n = 0u; getAncestorNode(n) != nullptr; ++n) + { + TIntermNode *ancestor = getAncestorNode(n); + const TIntermBinary *ancestorBinary = ancestor->getAsBinaryNode(); + if (ancestorBinary) + { + switch (ancestorBinary->getOp()) + { + case EOpIndexDirectStruct: + { + const TStructure *structure = ancestorBinary->getLeft()->getType().getStruct(); + const TIntermConstantUnion *index = + ancestorBinary->getRight()->getAsConstantUnion(); + const TField *field = structure->fields()[index->getIConst(0)]; + if (field->type()->getStruct() == nullptr) + { + return false; + } + break; + } + case EOpIndexDirect: + case EOpIndexIndirect: + break; + default: + return true; + } + } + else + { + const TIntermAggregate *ancestorAggregate = ancestor->getAsAggregate(); + if (ancestorAggregate) + { + return true; + } + return false; + } + } + return true; +} + +void OutputHLSL::writeFloat(TInfoSinkBase &out, float f) +{ + // This is known not to work for NaN on all drivers but make the best effort to output NaNs + // regardless. + if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300 && + mOutputType == SH_HLSL_4_1_OUTPUT) + { + out << "asfloat(" << gl::bitCast(f) << "u)"; + } + else + { + out << std::min(FLT_MAX, std::max(-FLT_MAX, f)); + } +} + +void OutputHLSL::writeSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion) +{ + ASSERT(constUnion != nullptr); + switch (constUnion->getType()) + { + case EbtFloat: + writeFloat(out, constUnion->getFConst()); + break; + case EbtInt: + out << constUnion->getIConst(); + break; + case EbtUInt: + out << constUnion->getUConst(); + break; + case EbtBool: + out << constUnion->getBConst(); + break; + default: + UNREACHABLE(); + } +} + +const TConstantUnion *OutputHLSL::writeConstantUnionArray(TInfoSinkBase &out, + const TConstantUnion *const constUnion, + const size_t size) +{ + const TConstantUnion *constUnionIterated = constUnion; + for (size_t i = 0; i < size; i++, constUnionIterated++) + { + writeSingleConstant(out, constUnionIterated); + + if (i != size - 1) + { + out << ", "; + } + } + return constUnionIterated; +} + +OutputHLSL::OutputHLSL(sh::GLenum shaderType, + ShShaderSpec shaderSpec, + int shaderVersion, + const TExtensionBehavior &extensionBehavior, + const char *sourcePath, + ShShaderOutput outputType, + int numRenderTargets, + int maxDualSourceDrawBuffers, + const std::vector &uniforms, + const ShCompileOptions &compileOptions, + sh::WorkGroupSize workGroupSize, + TSymbolTable *symbolTable, + PerformanceDiagnostics *perfDiagnostics, + const std::map &uniformBlockOptimizedMap, + const std::vector &shaderStorageBlocks, + bool isEarlyFragmentTestsSpecified) + : TIntermTraverser(true, true, true, symbolTable), + mShaderType(shaderType), + mShaderSpec(shaderSpec), + mShaderVersion(shaderVersion), + mExtensionBehavior(extensionBehavior), + mSourcePath(sourcePath), + mOutputType(outputType), + mCompileOptions(compileOptions), + mInsideFunction(false), + mInsideMain(false), + mUniformBlockOptimizedMap(uniformBlockOptimizedMap), + mNumRenderTargets(numRenderTargets), + mMaxDualSourceDrawBuffers(maxDualSourceDrawBuffers), + mCurrentFunctionMetadata(nullptr), + mWorkGroupSize(workGroupSize), + mPerfDiagnostics(perfDiagnostics), + mIsEarlyFragmentTestsSpecified(isEarlyFragmentTestsSpecified), + mNeedStructMapping(false) +{ + mUsesFragColor = false; + mUsesFragData = false; + mUsesDepthRange = false; + mUsesFragCoord = false; + mUsesPointCoord = false; + mUsesFrontFacing = false; + mUsesHelperInvocation = false; + mUsesPointSize = false; + mUsesInstanceID = false; + mHasMultiviewExtensionEnabled = + IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview) || + IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview2); + mUsesViewID = false; + mUsesVertexID = false; + mUsesFragDepth = false; + mUsesNumWorkGroups = false; + mUsesWorkGroupID = false; + mUsesLocalInvocationID = false; + mUsesGlobalInvocationID = false; + mUsesLocalInvocationIndex = false; + mUsesXor = false; + mUsesDiscardRewriting = false; + mUsesNestedBreak = false; + mRequiresIEEEStrictCompiling = false; + mUseZeroArray = false; + mUsesSecondaryColor = false; + + mUniqueIndex = 0; + + mOutputLod0Function = false; + mInsideDiscontinuousLoop = false; + mNestedLoopDepth = 0; + + mExcessiveLoopIndex = nullptr; + + mStructureHLSL = new StructureHLSL; + mTextureFunctionHLSL = new TextureFunctionHLSL; + mImageFunctionHLSL = new ImageFunctionHLSL; + mAtomicCounterFunctionHLSL = + new AtomicCounterFunctionHLSL(compileOptions.forceAtomicValueResolution); + + unsigned int firstUniformRegister = compileOptions.skipD3DConstantRegisterZero ? 1u : 0u; + mResourcesHLSL = new ResourcesHLSL(mStructureHLSL, outputType, uniforms, firstUniformRegister); + + if (mOutputType == SH_HLSL_3_0_OUTPUT) + { + // Fragment shaders need dx_DepthRange, dx_ViewCoords, dx_DepthFront, + // and dx_FragCoordOffset. + // Vertex shaders need a slightly different set: dx_DepthRange, dx_ViewCoords and + // dx_ViewAdjust. + if (mShaderType == GL_VERTEX_SHADER) + { + mResourcesHLSL->reserveUniformRegisters(3); + } + else + { + mResourcesHLSL->reserveUniformRegisters(4); + } + } + + // Reserve registers for the default uniform block and driver constants + mResourcesHLSL->reserveUniformBlockRegisters(2); + + mSSBOOutputHLSL = new ShaderStorageBlockOutputHLSL(this, mResourcesHLSL, shaderStorageBlocks); +} + +OutputHLSL::~OutputHLSL() +{ + SafeDelete(mSSBOOutputHLSL); + SafeDelete(mStructureHLSL); + SafeDelete(mResourcesHLSL); + SafeDelete(mTextureFunctionHLSL); + SafeDelete(mImageFunctionHLSL); + SafeDelete(mAtomicCounterFunctionHLSL); + for (auto &eqFunction : mStructEqualityFunctions) + { + SafeDelete(eqFunction); + } + for (auto &eqFunction : mArrayEqualityFunctions) + { + SafeDelete(eqFunction); + } +} + +void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink) +{ + BuiltInFunctionEmulator builtInFunctionEmulator; + InitBuiltInFunctionEmulatorForHLSL(&builtInFunctionEmulator); + if (mCompileOptions.emulateIsnanFloatFunction) + { + InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(&builtInFunctionEmulator, + mShaderVersion); + } + + builtInFunctionEmulator.markBuiltInFunctionsForEmulation(treeRoot); + + // Now that we are done changing the AST, do the analyses need for HLSL generation + CallDAG::InitResult success = mCallDag.init(treeRoot, nullptr); + ASSERT(success == CallDAG::INITDAG_SUCCESS); + mASTMetadataList = CreateASTMetadataHLSL(treeRoot, mCallDag); + + const std::vector std140Structs = FlagStd140Structs(treeRoot); + // TODO(oetuaho): The std140Structs could be filtered based on which ones actually get used in + // the shader code. When we add shader storage blocks we might also consider an alternative + // solution, since the struct mapping won't work very well for shader storage blocks. + + // Output the body and footer first to determine what has to go in the header + mInfoSinkStack.push(&mBody); + treeRoot->traverse(this); + mInfoSinkStack.pop(); + + mInfoSinkStack.push(&mFooter); + mInfoSinkStack.pop(); + + mInfoSinkStack.push(&mHeader); + header(mHeader, std140Structs, &builtInFunctionEmulator); + mInfoSinkStack.pop(); + + objSink << mHeader.c_str(); + objSink << mBody.c_str(); + objSink << mFooter.c_str(); + + builtInFunctionEmulator.cleanup(); +} + +const std::map &OutputHLSL::getShaderStorageBlockRegisterMap() const +{ + return mResourcesHLSL->getShaderStorageBlockRegisterMap(); +} + +const std::map &OutputHLSL::getUniformBlockRegisterMap() const +{ + return mResourcesHLSL->getUniformBlockRegisterMap(); +} + +const std::map &OutputHLSL::getUniformBlockUseStructuredBufferMap() const +{ + return mResourcesHLSL->getUniformBlockUseStructuredBufferMap(); +} + +const std::map &OutputHLSL::getUniformRegisterMap() const +{ + return mResourcesHLSL->getUniformRegisterMap(); +} + +unsigned int OutputHLSL::getReadonlyImage2DRegisterIndex() const +{ + return mResourcesHLSL->getReadonlyImage2DRegisterIndex(); +} + +unsigned int OutputHLSL::getImage2DRegisterIndex() const +{ + return mResourcesHLSL->getImage2DRegisterIndex(); +} + +const std::set &OutputHLSL::getUsedImage2DFunctionNames() const +{ + return mImageFunctionHLSL->getUsedImage2DFunctionNames(); +} + +TString OutputHLSL::structInitializerString(int indent, + const TType &type, + const TString &name) const +{ + TString init; + + TString indentString; + for (int spaces = 0; spaces < indent; spaces++) + { + indentString += " "; + } + + if (type.isArray()) + { + init += indentString + "{\n"; + for (unsigned int arrayIndex = 0u; arrayIndex < type.getOutermostArraySize(); ++arrayIndex) + { + TStringStream indexedString = sh::InitializeStream(); + indexedString << name << "[" << arrayIndex << "]"; + TType elementType = type; + elementType.toArrayElementType(); + init += structInitializerString(indent + 1, elementType, indexedString.str()); + if (arrayIndex < type.getOutermostArraySize() - 1) + { + init += ","; + } + init += "\n"; + } + init += indentString + "}"; + } + else if (type.getBasicType() == EbtStruct) + { + init += indentString + "{\n"; + const TStructure &structure = *type.getStruct(); + const TFieldList &fields = structure.fields(); + for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) + { + const TField &field = *fields[fieldIndex]; + const TString &fieldName = name + "." + Decorate(field.name()); + const TType &fieldType = *field.type(); + + init += structInitializerString(indent + 1, fieldType, fieldName); + if (fieldIndex < fields.size() - 1) + { + init += ","; + } + init += "\n"; + } + init += indentString + "}"; + } + else + { + init += indentString + name; + } + + return init; +} + +TString OutputHLSL::generateStructMapping(const std::vector &std140Structs) const +{ + TString mappedStructs; + + for (auto &mappedStruct : std140Structs) + { + const TInterfaceBlock *interfaceBlock = + mappedStruct.blockDeclarator->getType().getInterfaceBlock(); + TQualifier qualifier = mappedStruct.blockDeclarator->getType().getQualifier(); + switch (qualifier) + { + case EvqUniform: + if (mReferencedUniformBlocks.count(interfaceBlock->uniqueId().get()) == 0) + { + continue; + } + break; + case EvqBuffer: + continue; + default: + UNREACHABLE(); + return mappedStructs; + } + + unsigned int instanceCount = 1u; + bool isInstanceArray = mappedStruct.blockDeclarator->isArray(); + if (isInstanceArray) + { + instanceCount = mappedStruct.blockDeclarator->getOutermostArraySize(); + } + + for (unsigned int instanceArrayIndex = 0; instanceArrayIndex < instanceCount; + ++instanceArrayIndex) + { + TString originalName; + TString mappedName("map"); + + if (mappedStruct.blockDeclarator->variable().symbolType() != SymbolType::Empty) + { + const ImmutableString &instanceName = + mappedStruct.blockDeclarator->variable().name(); + unsigned int instanceStringArrayIndex = GL_INVALID_INDEX; + if (isInstanceArray) + instanceStringArrayIndex = instanceArrayIndex; + TString instanceString = mResourcesHLSL->InterfaceBlockInstanceString( + instanceName, instanceStringArrayIndex); + originalName += instanceString; + mappedName += instanceString; + originalName += "."; + mappedName += "_"; + } + + TString fieldName = Decorate(mappedStruct.field->name()); + originalName += fieldName; + mappedName += fieldName; + + TType *structType = mappedStruct.field->type(); + mappedStructs += + "static " + Decorate(structType->getStruct()->name()) + " " + mappedName; + + if (structType->isArray()) + { + mappedStructs += ArrayString(*mappedStruct.field->type()).data(); + } + + mappedStructs += " =\n"; + mappedStructs += structInitializerString(0, *structType, originalName); + mappedStructs += ";\n"; + } + } + return mappedStructs; +} + +void OutputHLSL::writeReferencedAttributes(TInfoSinkBase &out) const +{ + for (const auto &attribute : mReferencedAttributes) + { + const TType &type = attribute.second->getType(); + const ImmutableString &name = attribute.second->name(); + + out << "static " << TypeString(type) << " " << Decorate(name) << ArrayString(type) << " = " + << zeroInitializer(type) << ";\n"; + } +} + +void OutputHLSL::writeReferencedVaryings(TInfoSinkBase &out) const +{ + for (const auto &varying : mReferencedVaryings) + { + const TType &type = varying.second->getType(); + + // Program linking depends on this exact format + out << "static " << InterpolationString(type.getQualifier()) << " " << TypeString(type) + << " " << DecorateVariableIfNeeded(*varying.second) << ArrayString(type) << " = " + << zeroInitializer(type) << ";\n"; + } +} + +void OutputHLSL::header(TInfoSinkBase &out, + const std::vector &std140Structs, + const BuiltInFunctionEmulator *builtInFunctionEmulator) const +{ + TString mappedStructs; + if (mNeedStructMapping) + { + mappedStructs = generateStructMapping(std140Structs); + } + + // Suppress some common warnings: + // 3556 : Integer divides might be much slower, try using uints if possible. + // 3571 : The pow(f, e) intrinsic function won't work for negative f, use abs(f) or + // conditionally handle negative values if you expect them. + out << "#pragma warning( disable: 3556 3571 )\n"; + + out << mStructureHLSL->structsHeader(); + + mResourcesHLSL->uniformsHeader(out, mOutputType, mReferencedUniforms, mSymbolTable); + out << mResourcesHLSL->uniformBlocksHeader(mReferencedUniformBlocks, mUniformBlockOptimizedMap); + mSSBOOutputHLSL->writeShaderStorageBlocksHeader(mShaderType, out); + + if (!mEqualityFunctions.empty()) + { + out << "\n// Equality functions\n\n"; + for (const auto &eqFunction : mEqualityFunctions) + { + out << eqFunction->functionDefinition << "\n"; + } + } + if (!mArrayAssignmentFunctions.empty()) + { + out << "\n// Assignment functions\n\n"; + for (const auto &assignmentFunction : mArrayAssignmentFunctions) + { + out << assignmentFunction.functionDefinition << "\n"; + } + } + if (!mArrayConstructIntoFunctions.empty()) + { + out << "\n// Array constructor functions\n\n"; + for (const auto &constructIntoFunction : mArrayConstructIntoFunctions) + { + out << constructIntoFunction.functionDefinition << "\n"; + } + } + + if (mUsesDiscardRewriting) + { + out << "#define ANGLE_USES_DISCARD_REWRITING\n"; + } + + if (mUsesNestedBreak) + { + out << "#define ANGLE_USES_NESTED_BREAK\n"; + } + + if (mRequiresIEEEStrictCompiling) + { + out << "#define ANGLE_REQUIRES_IEEE_STRICT_COMPILING\n"; + } + + out << "#ifdef ANGLE_ENABLE_LOOP_FLATTEN\n" + "#define LOOP [loop]\n" + "#define FLATTEN [flatten]\n" + "#else\n" + "#define LOOP\n" + "#define FLATTEN\n" + "#endif\n"; + + // array stride for atomic counter buffers is always 4 per original extension + // ARB_shader_atomic_counters and discussion on + // https://github.com/KhronosGroup/OpenGL-API/issues/5 + out << "\n#define ATOMIC_COUNTER_ARRAY_STRIDE 4\n\n"; + + if (mUseZeroArray) + { + out << DefineZeroArray() << "\n"; + } + + if (mShaderType == GL_FRAGMENT_SHADER) + { + const bool usingMRTExtension = + IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers); + const bool usingBFEExtension = + IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_blend_func_extended); + + out << "// Varyings\n"; + writeReferencedVaryings(out); + out << "\n"; + + if ((IsDesktopGLSpec(mShaderSpec) && mShaderVersion >= 130) || + (!IsDesktopGLSpec(mShaderSpec) && mShaderVersion >= 300)) + { + for (const auto &outputVariable : mReferencedOutputVariables) + { + const ImmutableString &variableName = outputVariable.second->name(); + const TType &variableType = outputVariable.second->getType(); + + out << "static " << TypeString(variableType) << " out_" << variableName + << ArrayString(variableType) << " = " << zeroInitializer(variableType) << ";\n"; + } + } + else + { + const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1; + + out << "static float4 gl_Color[" << numColorValues + << "] =\n" + "{\n"; + for (unsigned int i = 0; i < numColorValues; i++) + { + out << " float4(0, 0, 0, 0)"; + if (i + 1 != numColorValues) + { + out << ","; + } + out << "\n"; + } + + out << "};\n"; + + if (usingBFEExtension && mUsesSecondaryColor) + { + out << "static float4 gl_SecondaryColor[" << mMaxDualSourceDrawBuffers + << "] = \n" + "{\n"; + for (int i = 0; i < mMaxDualSourceDrawBuffers; i++) + { + out << " float4(0, 0, 0, 0)"; + if (i + 1 != mMaxDualSourceDrawBuffers) + { + out << ","; + } + out << "\n"; + } + out << "};\n"; + } + } + + if (mUsesFragDepth) + { + out << "static float gl_Depth = 0.0;\n"; + } + + if (mUsesFragCoord) + { + out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n"; + } + + if (mUsesPointCoord) + { + out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n"; + } + + if (mUsesFrontFacing) + { + out << "static bool gl_FrontFacing = false;\n"; + } + + if (mUsesHelperInvocation) + { + out << "static bool gl_HelperInvocation = false;\n"; + } + + out << "\n"; + + if (mUsesDepthRange) + { + out << "struct gl_DepthRangeParameters\n" + "{\n" + " float near;\n" + " float far;\n" + " float diff;\n" + "};\n" + "\n"; + } + + if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) + { + out << "cbuffer DriverConstants : register(b1)\n" + "{\n"; + + if (mUsesDepthRange) + { + out << " float3 dx_DepthRange : packoffset(c0);\n"; + } + + if (mUsesFragCoord) + { + out << " float4 dx_ViewCoords : packoffset(c1);\n"; + out << " float2 dx_FragCoordOffset : packoffset(c3);\n"; + } + + if (mUsesFragCoord || mUsesFrontFacing) + { + out << " float3 dx_DepthFront : packoffset(c2);\n"; + } + + if (mUsesFragCoord) + { + // dx_ViewScale is only used in the fragment shader to correct + // the value for glFragCoord if necessary + out << " float2 dx_ViewScale : packoffset(c3.z);\n"; + } + + if (mHasMultiviewExtensionEnabled) + { + // We have to add a value which we can use to keep track of which multi-view code + // path is to be selected in the GS. + out << " float multiviewSelectViewportIndex : packoffset(c4.x);\n"; + } + + if (mOutputType == SH_HLSL_4_1_OUTPUT) + { + unsigned int registerIndex = 5; + mResourcesHLSL->samplerMetadataUniforms(out, registerIndex); + // Sampler metadata struct must be two 4-vec, 32 bytes. + registerIndex += mResourcesHLSL->getSamplerCount() * 2; + mResourcesHLSL->imageMetadataUniforms(out, registerIndex); + } + + out << "};\n"; + + if (mOutputType == SH_HLSL_4_1_OUTPUT && mResourcesHLSL->hasImages()) + { + out << kImage2DFunctionString << "\n"; + } + } + else + { + if (mUsesDepthRange) + { + out << "uniform float3 dx_DepthRange : register(c0);"; + } + + if (mUsesFragCoord) + { + out << "uniform float4 dx_ViewCoords : register(c1);\n"; + } + + if (mUsesFragCoord || mUsesFrontFacing) + { + out << "uniform float3 dx_DepthFront : register(c2);\n"; + out << "uniform float2 dx_FragCoordOffset : register(c3);\n"; + } + } + + out << "\n"; + + if (mUsesDepthRange) + { + out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, " + "dx_DepthRange.y, dx_DepthRange.z};\n" + "\n"; + } + + if (usingMRTExtension && mNumRenderTargets > 1) + { + out << "#define GL_USES_MRT\n"; + } + + if (mUsesFragColor) + { + out << "#define GL_USES_FRAG_COLOR\n"; + } + + if (mUsesFragData) + { + out << "#define GL_USES_FRAG_DATA\n"; + } + + if (mShaderVersion < 300 && usingBFEExtension && mUsesSecondaryColor) + { + out << "#define GL_USES_SECONDARY_COLOR\n"; + } + } + else if (mShaderType == GL_VERTEX_SHADER) + { + out << "// Attributes\n"; + writeReferencedAttributes(out); + out << "\n" + "static float4 gl_Position = float4(0, 0, 0, 0);\n"; + + if (mUsesPointSize) + { + out << "static float gl_PointSize = float(1);\n"; + } + + if (mUsesInstanceID) + { + out << "static int gl_InstanceID;"; + } + + if (mUsesVertexID) + { + out << "static int gl_VertexID;"; + } + + out << "\n" + "// Varyings\n"; + writeReferencedVaryings(out); + out << "\n"; + + if (mUsesDepthRange) + { + out << "struct gl_DepthRangeParameters\n" + "{\n" + " float near;\n" + " float far;\n" + " float diff;\n" + "};\n" + "\n"; + } + + if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) + { + out << "cbuffer DriverConstants : register(b1)\n" + "{\n"; + + if (mUsesDepthRange) + { + out << " float3 dx_DepthRange : packoffset(c0);\n"; + } + + // dx_ViewAdjust and dx_ViewCoords will only be used in Feature Level 9 + // shaders. However, we declare it for all shaders (including Feature Level 10+). + // The bytecode is the same whether we declare it or not, since D3DCompiler removes it + // if it's unused. + out << " float4 dx_ViewAdjust : packoffset(c1);\n"; + out << " float2 dx_ViewCoords : packoffset(c2);\n"; + out << " float2 dx_ViewScale : packoffset(c3);\n"; + + if (mHasMultiviewExtensionEnabled) + { + // We have to add a value which we can use to keep track of which multi-view code + // path is to be selected in the GS. + out << " float multiviewSelectViewportIndex : packoffset(c3.z);\n"; + } + + out << " float clipControlOrigin : packoffset(c3.w);\n"; + out << " float clipControlZeroToOne : packoffset(c4);\n"; + + if (mOutputType == SH_HLSL_4_1_OUTPUT) + { + mResourcesHLSL->samplerMetadataUniforms(out, 5); + } + + if (mUsesVertexID) + { + out << " uint dx_VertexID : packoffset(c4.y);\n"; + } + + out << "};\n" + "\n"; + } + else + { + if (mUsesDepthRange) + { + out << "uniform float3 dx_DepthRange : register(c0);\n"; + } + + out << "uniform float4 dx_ViewAdjust : register(c1);\n"; + out << "uniform float2 dx_ViewCoords : register(c2);\n"; + + out << "static const float clipControlOrigin = -1.0f;\n"; + out << "static const float clipControlZeroToOne = 0.0f;\n"; + + out << "\n"; + } + + if (mUsesDepthRange) + { + out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, " + "dx_DepthRange.y, dx_DepthRange.z};\n" + "\n"; + } + } + else // Compute shader + { + ASSERT(mShaderType == GL_COMPUTE_SHADER); + + out << "cbuffer DriverConstants : register(b1)\n" + "{\n"; + if (mUsesNumWorkGroups) + { + out << " uint3 gl_NumWorkGroups : packoffset(c0);\n"; + } + ASSERT(mOutputType == SH_HLSL_4_1_OUTPUT); + unsigned int registerIndex = 1; + mResourcesHLSL->samplerMetadataUniforms(out, registerIndex); + // Sampler metadata struct must be two 4-vec, 32 bytes. + registerIndex += mResourcesHLSL->getSamplerCount() * 2; + mResourcesHLSL->imageMetadataUniforms(out, registerIndex); + out << "};\n"; + + out << kImage2DFunctionString << "\n"; + + std::ostringstream systemValueDeclaration = sh::InitializeStream(); + std::ostringstream glBuiltinInitialization = sh::InitializeStream(); + + systemValueDeclaration << "\nstruct CS_INPUT\n{\n"; + glBuiltinInitialization << "\nvoid initGLBuiltins(CS_INPUT input)\n" + << "{\n"; + + if (mUsesWorkGroupID) + { + out << "static uint3 gl_WorkGroupID = uint3(0, 0, 0);\n"; + systemValueDeclaration << " uint3 dx_WorkGroupID : " + << "SV_GroupID;\n"; + glBuiltinInitialization << " gl_WorkGroupID = input.dx_WorkGroupID;\n"; + } + + if (mUsesLocalInvocationID) + { + out << "static uint3 gl_LocalInvocationID = uint3(0, 0, 0);\n"; + systemValueDeclaration << " uint3 dx_LocalInvocationID : " + << "SV_GroupThreadID;\n"; + glBuiltinInitialization << " gl_LocalInvocationID = input.dx_LocalInvocationID;\n"; + } + + if (mUsesGlobalInvocationID) + { + out << "static uint3 gl_GlobalInvocationID = uint3(0, 0, 0);\n"; + systemValueDeclaration << " uint3 dx_GlobalInvocationID : " + << "SV_DispatchThreadID;\n"; + glBuiltinInitialization << " gl_GlobalInvocationID = input.dx_GlobalInvocationID;\n"; + } + + if (mUsesLocalInvocationIndex) + { + out << "static uint gl_LocalInvocationIndex = uint(0);\n"; + systemValueDeclaration << " uint dx_LocalInvocationIndex : " + << "SV_GroupIndex;\n"; + glBuiltinInitialization + << " gl_LocalInvocationIndex = input.dx_LocalInvocationIndex;\n"; + } + + systemValueDeclaration << "};\n\n"; + glBuiltinInitialization << "};\n\n"; + + out << systemValueDeclaration.str(); + out << glBuiltinInitialization.str(); + } + + if (!mappedStructs.empty()) + { + out << "// Structures from std140 blocks with padding removed\n"; + out << "\n"; + out << mappedStructs; + out << "\n"; + } + + bool getDimensionsIgnoresBaseLevel = mCompileOptions.HLSLGetDimensionsIgnoresBaseLevel; + mTextureFunctionHLSL->textureFunctionHeader(out, mOutputType, getDimensionsIgnoresBaseLevel); + mImageFunctionHLSL->imageFunctionHeader(out); + mAtomicCounterFunctionHLSL->atomicCounterFunctionHeader(out); + + if (mUsesFragCoord) + { + out << "#define GL_USES_FRAG_COORD\n"; + } + + if (mUsesPointCoord) + { + out << "#define GL_USES_POINT_COORD\n"; + } + + if (mUsesFrontFacing) + { + out << "#define GL_USES_FRONT_FACING\n"; + } + + if (mUsesHelperInvocation) + { + out << "#define GL_USES_HELPER_INVOCATION\n"; + } + + if (mUsesPointSize) + { + out << "#define GL_USES_POINT_SIZE\n"; + } + + if (mHasMultiviewExtensionEnabled) + { + out << "#define GL_ANGLE_MULTIVIEW_ENABLED\n"; + } + + if (mUsesVertexID) + { + out << "#define GL_USES_VERTEX_ID\n"; + } + + if (mUsesViewID) + { + out << "#define GL_USES_VIEW_ID\n"; + } + + if (mUsesFragDepth) + { + out << "#define GL_USES_FRAG_DEPTH\n"; + } + + if (mUsesDepthRange) + { + out << "#define GL_USES_DEPTH_RANGE\n"; + } + + if (mUsesXor) + { + out << "bool xor(bool p, bool q)\n" + "{\n" + " return (p || q) && !(p && q);\n" + "}\n" + "\n"; + } + + builtInFunctionEmulator->outputEmulatedFunctions(out); +} + +void OutputHLSL::visitSymbol(TIntermSymbol *node) +{ + const TVariable &variable = node->variable(); + + // Empty symbols can only appear in declarations and function arguments, and in either of those + // cases the symbol nodes are not visited. + ASSERT(variable.symbolType() != SymbolType::Empty); + + TInfoSinkBase &out = getInfoSink(); + + // Handle accessing std140 structs by value + if (IsInStd140UniformBlock(node) && node->getBasicType() == EbtStruct && + needStructMapping(node)) + { + mNeedStructMapping = true; + out << "map"; + } + + const ImmutableString &name = variable.name(); + const TSymbolUniqueId &uniqueId = variable.uniqueId(); + + if (name == "gl_DepthRange") + { + mUsesDepthRange = true; + out << name; + } + else if (IsAtomicCounter(variable.getType().getBasicType())) + { + const TType &variableType = variable.getType(); + if (variableType.getQualifier() == EvqUniform) + { + TLayoutQualifier layout = variableType.getLayoutQualifier(); + mReferencedUniforms[uniqueId.get()] = &variable; + out << getAtomicCounterNameForBinding(layout.binding) << ", " << layout.offset; + } + else + { + TString varName = DecorateVariableIfNeeded(variable); + out << varName << ", " << varName << "_offset"; + } + } + else + { + const TType &variableType = variable.getType(); + TQualifier qualifier = variable.getType().getQualifier(); + + ensureStructDefined(variableType); + + if (qualifier == EvqUniform) + { + const TInterfaceBlock *interfaceBlock = variableType.getInterfaceBlock(); + + if (interfaceBlock) + { + if (mReferencedUniformBlocks.count(interfaceBlock->uniqueId().get()) == 0) + { + const TVariable *instanceVariable = nullptr; + if (variableType.isInterfaceBlock()) + { + instanceVariable = &variable; + } + mReferencedUniformBlocks[interfaceBlock->uniqueId().get()] = + new TReferencedBlock(interfaceBlock, instanceVariable); + } + } + else + { + mReferencedUniforms[uniqueId.get()] = &variable; + } + + out << DecorateVariableIfNeeded(variable); + } + else if (qualifier == EvqBuffer) + { + UNREACHABLE(); + } + else if (qualifier == EvqAttribute || qualifier == EvqVertexIn) + { + mReferencedAttributes[uniqueId.get()] = &variable; + out << Decorate(name); + } + else if (IsVarying(qualifier)) + { + mReferencedVaryings[uniqueId.get()] = &variable; + out << DecorateVariableIfNeeded(variable); + if (variable.symbolType() == SymbolType::AngleInternal && name == "ViewID_OVR") + { + mUsesViewID = true; + } + } + else if (qualifier == EvqFragmentOut) + { + mReferencedOutputVariables[uniqueId.get()] = &variable; + out << "out_" << name; + } + else if (qualifier == EvqFragColor) + { + out << "gl_Color[0]"; + mUsesFragColor = true; + } + else if (qualifier == EvqFragData) + { + out << "gl_Color"; + mUsesFragData = true; + } + else if (qualifier == EvqSecondaryFragColorEXT) + { + out << "gl_SecondaryColor[0]"; + mUsesSecondaryColor = true; + } + else if (qualifier == EvqSecondaryFragDataEXT) + { + out << "gl_SecondaryColor"; + mUsesSecondaryColor = true; + } + else if (qualifier == EvqFragCoord) + { + mUsesFragCoord = true; + out << name; + } + else if (qualifier == EvqPointCoord) + { + mUsesPointCoord = true; + out << name; + } + else if (qualifier == EvqFrontFacing) + { + mUsesFrontFacing = true; + out << name; + } + else if (qualifier == EvqHelperInvocation) + { + mUsesHelperInvocation = true; + out << name; + } + else if (qualifier == EvqPointSize) + { + mUsesPointSize = true; + out << name; + } + else if (qualifier == EvqInstanceID) + { + mUsesInstanceID = true; + out << name; + } + else if (qualifier == EvqVertexID) + { + mUsesVertexID = true; + out << name; + } + else if (name == "gl_FragDepthEXT" || name == "gl_FragDepth") + { + mUsesFragDepth = true; + out << "gl_Depth"; + } + else if (qualifier == EvqNumWorkGroups) + { + mUsesNumWorkGroups = true; + out << name; + } + else if (qualifier == EvqWorkGroupID) + { + mUsesWorkGroupID = true; + out << name; + } + else if (qualifier == EvqLocalInvocationID) + { + mUsesLocalInvocationID = true; + out << name; + } + else if (qualifier == EvqGlobalInvocationID) + { + mUsesGlobalInvocationID = true; + out << name; + } + else if (qualifier == EvqLocalInvocationIndex) + { + mUsesLocalInvocationIndex = true; + out << name; + } + else + { + out << DecorateVariableIfNeeded(variable); + } + } +} + +void OutputHLSL::outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out) +{ + if (type.isScalar() && !type.isArray()) + { + if (op == EOpEqual) + { + outputTriplet(out, visit, "(", " == ", ")"); + } + else + { + outputTriplet(out, visit, "(", " != ", ")"); + } + } + else + { + if (visit == PreVisit && op == EOpNotEqual) + { + out << "!"; + } + + if (type.isArray()) + { + const TString &functionName = addArrayEqualityFunction(type); + outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")"); + } + else if (type.getBasicType() == EbtStruct) + { + const TStructure &structure = *type.getStruct(); + const TString &functionName = addStructEqualityFunction(structure); + outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")"); + } + else + { + ASSERT(type.isMatrix() || type.isVector()); + outputTriplet(out, visit, "all(", " == ", ")"); + } + } +} + +void OutputHLSL::outputAssign(Visit visit, const TType &type, TInfoSinkBase &out) +{ + if (type.isArray()) + { + const TString &functionName = addArrayAssignmentFunction(type); + outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")"); + } + else + { + outputTriplet(out, visit, "(", " = ", ")"); + } +} + +bool OutputHLSL::ancestorEvaluatesToSamplerInStruct() +{ + for (unsigned int n = 0u; getAncestorNode(n) != nullptr; ++n) + { + TIntermNode *ancestor = getAncestorNode(n); + const TIntermBinary *ancestorBinary = ancestor->getAsBinaryNode(); + if (ancestorBinary == nullptr) + { + return false; + } + switch (ancestorBinary->getOp()) + { + case EOpIndexDirectStruct: + { + const TStructure *structure = ancestorBinary->getLeft()->getType().getStruct(); + const TIntermConstantUnion *index = + ancestorBinary->getRight()->getAsConstantUnion(); + const TField *field = structure->fields()[index->getIConst(0)]; + if (IsSampler(field->type()->getBasicType())) + { + return true; + } + break; + } + case EOpIndexDirect: + break; + default: + // Returning a sampler from indirect indexing is not supported. + return false; + } + } + return false; +} + +bool OutputHLSL::visitSwizzle(Visit visit, TIntermSwizzle *node) +{ + TInfoSinkBase &out = getInfoSink(); + if (visit == PostVisit) + { + out << "."; + node->writeOffsetsAsXYZW(&out); + } + return true; +} + +bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) +{ + TInfoSinkBase &out = getInfoSink(); + + switch (node->getOp()) + { + case EOpComma: + outputTriplet(out, visit, "(", ", ", ")"); + break; + case EOpAssign: + if (node->isArray()) + { + TIntermAggregate *rightAgg = node->getRight()->getAsAggregate(); + if (rightAgg != nullptr && rightAgg->isConstructor()) + { + const TString &functionName = addArrayConstructIntoFunction(node->getType()); + out << functionName << "("; + node->getLeft()->traverse(this); + TIntermSequence *seq = rightAgg->getSequence(); + for (auto &arrayElement : *seq) + { + out << ", "; + arrayElement->traverse(this); + } + out << ")"; + return false; + } + // ArrayReturnValueToOutParameter should have eliminated expressions where a + // function call is assigned. + ASSERT(rightAgg == nullptr); + } + // Assignment expressions with atomic functions should be transformed into atomic + // function calls in HLSL. + // e.g. original_value = atomicAdd(dest, value) should be translated into + // InterlockedAdd(dest, value, original_value); + else if (IsAtomicFunctionForSharedVariableDirectAssign(*node)) + { + TIntermAggregate *atomicFunctionNode = node->getRight()->getAsAggregate(); + TOperator atomicFunctionOp = atomicFunctionNode->getOp(); + out << GetHLSLAtomicFunctionStringAndLeftParenthesis(atomicFunctionOp); + TIntermSequence *argumentSeq = atomicFunctionNode->getSequence(); + ASSERT(argumentSeq->size() >= 2u); + for (auto &argument : *argumentSeq) + { + argument->traverse(this); + out << ", "; + } + node->getLeft()->traverse(this); + out << ")"; + return false; + } + else if (IsInShaderStorageBlock(node->getLeft())) + { + mSSBOOutputHLSL->outputStoreFunctionCallPrefix(node->getLeft()); + out << ", "; + if (IsInShaderStorageBlock(node->getRight())) + { + mSSBOOutputHLSL->outputLoadFunctionCall(node->getRight()); + } + else + { + node->getRight()->traverse(this); + } + + out << ")"; + return false; + } + else if (IsInShaderStorageBlock(node->getRight())) + { + node->getLeft()->traverse(this); + out << " = "; + mSSBOOutputHLSL->outputLoadFunctionCall(node->getRight()); + return false; + } + + outputAssign(visit, node->getType(), out); + break; + case EOpInitialize: + if (visit == PreVisit) + { + TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode(); + ASSERT(symbolNode); + TIntermTyped *initializer = node->getRight(); + + // Global initializers must be constant at this point. + ASSERT(symbolNode->getQualifier() != EvqGlobal || initializer->hasConstantValue()); + + // GLSL allows to write things like "float x = x;" where a new variable x is defined + // and the value of an existing variable x is assigned. HLSL uses C semantics (the + // new variable is created before the assignment is evaluated), so we need to + // convert + // this to "float t = x, x = t;". + if (writeSameSymbolInitializer(out, symbolNode, initializer)) + { + // Skip initializing the rest of the expression + return false; + } + else if (writeConstantInitialization(out, symbolNode, initializer)) + { + return false; + } + } + else if (visit == InVisit) + { + out << " = "; + if (IsInShaderStorageBlock(node->getRight())) + { + mSSBOOutputHLSL->outputLoadFunctionCall(node->getRight()); + return false; + } + } + break; + case EOpAddAssign: + outputTriplet(out, visit, "(", " += ", ")"); + break; + case EOpSubAssign: + outputTriplet(out, visit, "(", " -= ", ")"); + break; + case EOpMulAssign: + outputTriplet(out, visit, "(", " *= ", ")"); + break; + case EOpVectorTimesScalarAssign: + outputTriplet(out, visit, "(", " *= ", ")"); + break; + case EOpMatrixTimesScalarAssign: + outputTriplet(out, visit, "(", " *= ", ")"); + break; + case EOpVectorTimesMatrixAssign: + if (visit == PreVisit) + { + out << "("; + } + else if (visit == InVisit) + { + out << " = mul("; + node->getLeft()->traverse(this); + out << ", transpose("; + } + else + { + out << ")))"; + } + break; + case EOpMatrixTimesMatrixAssign: + if (visit == PreVisit) + { + out << "("; + } + else if (visit == InVisit) + { + out << " = transpose(mul(transpose("; + node->getLeft()->traverse(this); + out << "), transpose("; + } + else + { + out << "))))"; + } + break; + case EOpDivAssign: + outputTriplet(out, visit, "(", " /= ", ")"); + break; + case EOpIModAssign: + outputTriplet(out, visit, "(", " %= ", ")"); + break; + case EOpBitShiftLeftAssign: + outputTriplet(out, visit, "(", " <<= ", ")"); + break; + case EOpBitShiftRightAssign: + outputTriplet(out, visit, "(", " >>= ", ")"); + break; + case EOpBitwiseAndAssign: + outputTriplet(out, visit, "(", " &= ", ")"); + break; + case EOpBitwiseXorAssign: + outputTriplet(out, visit, "(", " ^= ", ")"); + break; + case EOpBitwiseOrAssign: + outputTriplet(out, visit, "(", " |= ", ")"); + break; + case EOpIndexDirect: + { + const TType &leftType = node->getLeft()->getType(); + if (leftType.isInterfaceBlock()) + { + if (visit == PreVisit) + { + TIntermSymbol *instanceArraySymbol = node->getLeft()->getAsSymbolNode(); + const TInterfaceBlock *interfaceBlock = leftType.getInterfaceBlock(); + + ASSERT(leftType.getQualifier() == EvqUniform); + if (mReferencedUniformBlocks.count(interfaceBlock->uniqueId().get()) == 0) + { + mReferencedUniformBlocks[interfaceBlock->uniqueId().get()] = + new TReferencedBlock(interfaceBlock, &instanceArraySymbol->variable()); + } + const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0); + out << mResourcesHLSL->InterfaceBlockInstanceString( + instanceArraySymbol->getName(), arrayIndex); + return false; + } + } + else if (ancestorEvaluatesToSamplerInStruct()) + { + // All parts of an expression that access a sampler in a struct need to use _ as + // separator to access the sampler variable that has been moved out of the struct. + outputTriplet(out, visit, "", "_", ""); + } + else if (IsAtomicCounter(leftType.getBasicType())) + { + outputTriplet(out, visit, "", " + (", ") * ATOMIC_COUNTER_ARRAY_STRIDE"); + } + else + { + outputTriplet(out, visit, "", "[", "]"); + if (visit == PostVisit) + { + const TInterfaceBlock *interfaceBlock = + GetInterfaceBlockOfUniformBlockNearestIndexOperator(node->getLeft()); + if (interfaceBlock && + mUniformBlockOptimizedMap.count(interfaceBlock->uniqueId().get()) != 0) + { + // If the uniform block member's type is not structure, we had explicitly + // packed the member into a structure, so need to add an operator of field + // slection. + const TField *field = interfaceBlock->fields()[0]; + const TType *fieldType = field->type(); + if (fieldType->isMatrix() || fieldType->isVectorArray() || + fieldType->isScalarArray()) + { + out << "." << Decorate(field->name()); + } + } + } + } + } + break; + case EOpIndexIndirect: + { + // We do not currently support indirect references to interface blocks + ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock); + + const TType &leftType = node->getLeft()->getType(); + if (IsAtomicCounter(leftType.getBasicType())) + { + outputTriplet(out, visit, "", " + (", ") * ATOMIC_COUNTER_ARRAY_STRIDE"); + } + else + { + outputTriplet(out, visit, "", "[", "]"); + if (visit == PostVisit) + { + const TInterfaceBlock *interfaceBlock = + GetInterfaceBlockOfUniformBlockNearestIndexOperator(node->getLeft()); + if (interfaceBlock && + mUniformBlockOptimizedMap.count(interfaceBlock->uniqueId().get()) != 0) + { + // If the uniform block member's type is not structure, we had explicitly + // packed the member into a structure, so need to add an operator of field + // slection. + const TField *field = interfaceBlock->fields()[0]; + const TType *fieldType = field->type(); + if (fieldType->isMatrix() || fieldType->isVectorArray() || + fieldType->isScalarArray()) + { + out << "." << Decorate(field->name()); + } + } + } + } + break; + } + case EOpIndexDirectStruct: + { + const TStructure *structure = node->getLeft()->getType().getStruct(); + const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); + const TField *field = structure->fields()[index->getIConst(0)]; + + // In cases where indexing returns a sampler, we need to access the sampler variable + // that has been moved out of the struct. + bool indexingReturnsSampler = IsSampler(field->type()->getBasicType()); + if (visit == PreVisit && indexingReturnsSampler) + { + // Samplers extracted from structs have "angle" prefix to avoid name conflicts. + // This prefix is only output at the beginning of the indexing expression, which + // may have multiple parts. + out << "angle"; + } + if (!indexingReturnsSampler) + { + // All parts of an expression that access a sampler in a struct need to use _ as + // separator to access the sampler variable that has been moved out of the struct. + indexingReturnsSampler = ancestorEvaluatesToSamplerInStruct(); + } + if (visit == InVisit) + { + if (indexingReturnsSampler) + { + out << "_" << field->name(); + } + else + { + out << "." << DecorateField(field->name(), *structure); + } + + return false; + } + } + break; + case EOpIndexDirectInterfaceBlock: + { + ASSERT(!IsInShaderStorageBlock(node->getLeft())); + bool structInStd140UniformBlock = node->getBasicType() == EbtStruct && + IsInStd140UniformBlock(node->getLeft()) && + needStructMapping(node); + if (visit == PreVisit && structInStd140UniformBlock) + { + mNeedStructMapping = true; + out << "map"; + } + if (visit == InVisit) + { + const TInterfaceBlock *interfaceBlock = + node->getLeft()->getType().getInterfaceBlock(); + const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); + const TField *field = interfaceBlock->fields()[index->getIConst(0)]; + if (structInStd140UniformBlock || + mUniformBlockOptimizedMap.count(interfaceBlock->uniqueId().get()) != 0) + { + out << "_"; + } + else + { + out << "."; + } + out << Decorate(field->name()); + + return false; + } + break; + } + case EOpAdd: + outputTriplet(out, visit, "(", " + ", ")"); + break; + case EOpSub: + outputTriplet(out, visit, "(", " - ", ")"); + break; + case EOpMul: + outputTriplet(out, visit, "(", " * ", ")"); + break; + case EOpDiv: + outputTriplet(out, visit, "(", " / ", ")"); + break; + case EOpIMod: + outputTriplet(out, visit, "(", " % ", ")"); + break; + case EOpBitShiftLeft: + outputTriplet(out, visit, "(", " << ", ")"); + break; + case EOpBitShiftRight: + outputTriplet(out, visit, "(", " >> ", ")"); + break; + case EOpBitwiseAnd: + outputTriplet(out, visit, "(", " & ", ")"); + break; + case EOpBitwiseXor: + outputTriplet(out, visit, "(", " ^ ", ")"); + break; + case EOpBitwiseOr: + outputTriplet(out, visit, "(", " | ", ")"); + break; + case EOpEqual: + case EOpNotEqual: + outputEqual(visit, node->getLeft()->getType(), node->getOp(), out); + break; + case EOpLessThan: + outputTriplet(out, visit, "(", " < ", ")"); + break; + case EOpGreaterThan: + outputTriplet(out, visit, "(", " > ", ")"); + break; + case EOpLessThanEqual: + outputTriplet(out, visit, "(", " <= ", ")"); + break; + case EOpGreaterThanEqual: + outputTriplet(out, visit, "(", " >= ", ")"); + break; + case EOpVectorTimesScalar: + outputTriplet(out, visit, "(", " * ", ")"); + break; + case EOpMatrixTimesScalar: + outputTriplet(out, visit, "(", " * ", ")"); + break; + case EOpVectorTimesMatrix: + outputTriplet(out, visit, "mul(", ", transpose(", "))"); + break; + case EOpMatrixTimesVector: + outputTriplet(out, visit, "mul(transpose(", "), ", ")"); + break; + case EOpMatrixTimesMatrix: + outputTriplet(out, visit, "transpose(mul(transpose(", "), transpose(", ")))"); + break; + case EOpLogicalOr: + // HLSL doesn't short-circuit ||, so we assume that || affected by short-circuiting have + // been unfolded. + ASSERT(!node->getRight()->hasSideEffects()); + outputTriplet(out, visit, "(", " || ", ")"); + return true; + case EOpLogicalXor: + mUsesXor = true; + outputTriplet(out, visit, "xor(", ", ", ")"); + break; + case EOpLogicalAnd: + // HLSL doesn't short-circuit &&, so we assume that && affected by short-circuiting have + // been unfolded. + ASSERT(!node->getRight()->hasSideEffects()); + outputTriplet(out, visit, "(", " && ", ")"); + return true; + default: + UNREACHABLE(); + } + + return true; +} + +bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) +{ + TInfoSinkBase &out = getInfoSink(); + + switch (node->getOp()) + { + case EOpNegative: + outputTriplet(out, visit, "(-", "", ")"); + break; + case EOpPositive: + outputTriplet(out, visit, "(+", "", ")"); + break; + case EOpLogicalNot: + outputTriplet(out, visit, "(!", "", ")"); + break; + case EOpBitwiseNot: + outputTriplet(out, visit, "(~", "", ")"); + break; + case EOpPostIncrement: + outputTriplet(out, visit, "(", "", "++)"); + break; + case EOpPostDecrement: + outputTriplet(out, visit, "(", "", "--)"); + break; + case EOpPreIncrement: + outputTriplet(out, visit, "(++", "", ")"); + break; + case EOpPreDecrement: + outputTriplet(out, visit, "(--", "", ")"); + break; + case EOpRadians: + outputTriplet(out, visit, "radians(", "", ")"); + break; + case EOpDegrees: + outputTriplet(out, visit, "degrees(", "", ")"); + break; + case EOpSin: + outputTriplet(out, visit, "sin(", "", ")"); + break; + case EOpCos: + outputTriplet(out, visit, "cos(", "", ")"); + break; + case EOpTan: + outputTriplet(out, visit, "tan(", "", ")"); + break; + case EOpAsin: + outputTriplet(out, visit, "asin(", "", ")"); + break; + case EOpAcos: + outputTriplet(out, visit, "acos(", "", ")"); + break; + case EOpAtan: + outputTriplet(out, visit, "atan(", "", ")"); + break; + case EOpSinh: + outputTriplet(out, visit, "sinh(", "", ")"); + break; + case EOpCosh: + outputTriplet(out, visit, "cosh(", "", ")"); + break; + case EOpTanh: + case EOpAsinh: + case EOpAcosh: + case EOpAtanh: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, node->getFunction()); + break; + case EOpExp: + outputTriplet(out, visit, "exp(", "", ")"); + break; + case EOpLog: + outputTriplet(out, visit, "log(", "", ")"); + break; + case EOpExp2: + outputTriplet(out, visit, "exp2(", "", ")"); + break; + case EOpLog2: + outputTriplet(out, visit, "log2(", "", ")"); + break; + case EOpSqrt: + outputTriplet(out, visit, "sqrt(", "", ")"); + break; + case EOpInversesqrt: + outputTriplet(out, visit, "rsqrt(", "", ")"); + break; + case EOpAbs: + outputTriplet(out, visit, "abs(", "", ")"); + break; + case EOpSign: + outputTriplet(out, visit, "sign(", "", ")"); + break; + case EOpFloor: + outputTriplet(out, visit, "floor(", "", ")"); + break; + case EOpTrunc: + outputTriplet(out, visit, "trunc(", "", ")"); + break; + case EOpRound: + outputTriplet(out, visit, "round(", "", ")"); + break; + case EOpRoundEven: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, node->getFunction()); + break; + case EOpCeil: + outputTriplet(out, visit, "ceil(", "", ")"); + break; + case EOpFract: + outputTriplet(out, visit, "frac(", "", ")"); + break; + case EOpIsnan: + if (node->getUseEmulatedFunction()) + writeEmulatedFunctionTriplet(out, visit, node->getFunction()); + else + outputTriplet(out, visit, "isnan(", "", ")"); + mRequiresIEEEStrictCompiling = true; + break; + case EOpIsinf: + outputTriplet(out, visit, "isinf(", "", ")"); + break; + case EOpFloatBitsToInt: + outputTriplet(out, visit, "asint(", "", ")"); + break; + case EOpFloatBitsToUint: + outputTriplet(out, visit, "asuint(", "", ")"); + break; + case EOpIntBitsToFloat: + outputTriplet(out, visit, "asfloat(", "", ")"); + break; + case EOpUintBitsToFloat: + outputTriplet(out, visit, "asfloat(", "", ")"); + break; + case EOpPackSnorm2x16: + case EOpPackUnorm2x16: + case EOpPackHalf2x16: + case EOpUnpackSnorm2x16: + case EOpUnpackUnorm2x16: + case EOpUnpackHalf2x16: + case EOpPackUnorm4x8: + case EOpPackSnorm4x8: + case EOpUnpackUnorm4x8: + case EOpUnpackSnorm4x8: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, node->getFunction()); + break; + case EOpLength: + outputTriplet(out, visit, "length(", "", ")"); + break; + case EOpNormalize: + outputTriplet(out, visit, "normalize(", "", ")"); + break; + case EOpTranspose: + outputTriplet(out, visit, "transpose(", "", ")"); + break; + case EOpDeterminant: + outputTriplet(out, visit, "determinant(transpose(", "", "))"); + break; + case EOpInverse: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, node->getFunction()); + break; + + case EOpAny: + outputTriplet(out, visit, "any(", "", ")"); + break; + case EOpAll: + outputTriplet(out, visit, "all(", "", ")"); + break; + case EOpNotComponentWise: + outputTriplet(out, visit, "(!", "", ")"); + break; + case EOpBitfieldReverse: + outputTriplet(out, visit, "reversebits(", "", ")"); + break; + case EOpBitCount: + outputTriplet(out, visit, "countbits(", "", ")"); + break; + case EOpFindLSB: + // Note that it's unclear from the HLSL docs what this returns for 0, but this is tested + // in GLSLTest and results are consistent with GL. + outputTriplet(out, visit, "firstbitlow(", "", ")"); + break; + case EOpFindMSB: + // Note that it's unclear from the HLSL docs what this returns for 0 or -1, but this is + // tested in GLSLTest and results are consistent with GL. + outputTriplet(out, visit, "firstbithigh(", "", ")"); + break; + case EOpArrayLength: + { + TIntermTyped *operand = node->getOperand(); + ASSERT(IsInShaderStorageBlock(operand)); + mSSBOOutputHLSL->outputLengthFunctionCall(operand); + return false; + } + default: + UNREACHABLE(); + } + + return true; +} + +ImmutableString OutputHLSL::samplerNamePrefixFromStruct(TIntermTyped *node) +{ + if (node->getAsSymbolNode()) + { + ASSERT(node->getAsSymbolNode()->variable().symbolType() != SymbolType::Empty); + return node->getAsSymbolNode()->getName(); + } + TIntermBinary *nodeBinary = node->getAsBinaryNode(); + switch (nodeBinary->getOp()) + { + case EOpIndexDirect: + { + int index = nodeBinary->getRight()->getAsConstantUnion()->getIConst(0); + + std::stringstream prefixSink = sh::InitializeStream(); + prefixSink << samplerNamePrefixFromStruct(nodeBinary->getLeft()) << "_" << index; + return ImmutableString(prefixSink.str()); + } + case EOpIndexDirectStruct: + { + const TStructure *s = nodeBinary->getLeft()->getAsTyped()->getType().getStruct(); + int index = nodeBinary->getRight()->getAsConstantUnion()->getIConst(0); + const TField *field = s->fields()[index]; + + std::stringstream prefixSink = sh::InitializeStream(); + prefixSink << samplerNamePrefixFromStruct(nodeBinary->getLeft()) << "_" + << field->name(); + return ImmutableString(prefixSink.str()); + } + default: + UNREACHABLE(); + return kEmptyImmutableString; + } +} + +bool OutputHLSL::visitBlock(Visit visit, TIntermBlock *node) +{ + TInfoSinkBase &out = getInfoSink(); + + bool isMainBlock = mInsideMain && getParentNode()->getAsFunctionDefinition(); + + if (mInsideFunction) + { + outputLineDirective(out, node->getLine().first_line); + out << "{\n"; + if (isMainBlock) + { + if (mShaderType == GL_COMPUTE_SHADER) + { + out << "initGLBuiltins(input);\n"; + } + else + { + out << "@@ MAIN PROLOGUE @@\n"; + } + } + } + + for (TIntermNode *statement : *node->getSequence()) + { + outputLineDirective(out, statement->getLine().first_line); + + statement->traverse(this); + + // Don't output ; after case labels, they're terminated by : + // This is needed especially since outputting a ; after a case statement would turn empty + // case statements into non-empty case statements, disallowing fall-through from them. + // Also the output code is clearer if we don't output ; after statements where it is not + // needed: + // * if statements + // * switch statements + // * blocks + // * function definitions + // * loops (do-while loops output the semicolon in VisitLoop) + // * declarations that don't generate output. + if (statement->getAsCaseNode() == nullptr && statement->getAsIfElseNode() == nullptr && + statement->getAsBlock() == nullptr && statement->getAsLoopNode() == nullptr && + statement->getAsSwitchNode() == nullptr && + statement->getAsFunctionDefinition() == nullptr && + (statement->getAsDeclarationNode() == nullptr || + IsDeclarationWrittenOut(statement->getAsDeclarationNode())) && + statement->getAsGlobalQualifierDeclarationNode() == nullptr) + { + out << ";\n"; + } + } + + if (mInsideFunction) + { + outputLineDirective(out, node->getLine().last_line); + if (isMainBlock && shaderNeedsGenerateOutput()) + { + // We could have an empty main, a main function without a branch at the end, or a main + // function with a discard statement at the end. In these cases we need to add a return + // statement. + bool needReturnStatement = + node->getSequence()->empty() || !node->getSequence()->back()->getAsBranchNode() || + node->getSequence()->back()->getAsBranchNode()->getFlowOp() != EOpReturn; + if (needReturnStatement) + { + out << "return " << generateOutputCall() << ";\n"; + } + } + out << "}\n"; + } + + return false; +} + +bool OutputHLSL::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) +{ + TInfoSinkBase &out = getInfoSink(); + + ASSERT(mCurrentFunctionMetadata == nullptr); + + size_t index = mCallDag.findIndex(node->getFunction()->uniqueId()); + ASSERT(index != CallDAG::InvalidIndex); + mCurrentFunctionMetadata = &mASTMetadataList[index]; + + const TFunction *func = node->getFunction(); + + if (func->isMain()) + { + // The stub strings below are replaced when shader is dynamically defined by its layout: + switch (mShaderType) + { + case GL_VERTEX_SHADER: + out << "@@ VERTEX ATTRIBUTES @@\n\n" + << "@@ VERTEX OUTPUT @@\n\n" + << "VS_OUTPUT main(VS_INPUT input)"; + break; + case GL_FRAGMENT_SHADER: + out << "@@ PIXEL OUTPUT @@\n\n"; + if (mIsEarlyFragmentTestsSpecified) + { + out << "[earlydepthstencil]\n"; + } + out << "PS_OUTPUT main(@@ PIXEL MAIN PARAMETERS @@)"; + break; + case GL_COMPUTE_SHADER: + out << "[numthreads(" << mWorkGroupSize[0] << ", " << mWorkGroupSize[1] << ", " + << mWorkGroupSize[2] << ")]\n"; + out << "void main(CS_INPUT input)"; + break; + default: + UNREACHABLE(); + break; + } + } + else + { + out << TypeString(node->getFunctionPrototype()->getType()) << " "; + out << DecorateFunctionIfNeeded(func) << DisambiguateFunctionName(func) + << (mOutputLod0Function ? "Lod0(" : "("); + + size_t paramCount = func->getParamCount(); + for (unsigned int i = 0; i < paramCount; i++) + { + const TVariable *param = func->getParam(i); + ensureStructDefined(param->getType()); + + writeParameter(param, out); + + if (i < paramCount - 1) + { + out << ", "; + } + } + + out << ")\n"; + } + + mInsideFunction = true; + if (func->isMain()) + { + mInsideMain = true; + } + // The function body node will output braces. + node->getBody()->traverse(this); + mInsideFunction = false; + mInsideMain = false; + + mCurrentFunctionMetadata = nullptr; + + bool needsLod0 = mASTMetadataList[index].mNeedsLod0; + if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER) + { + ASSERT(!node->getFunction()->isMain()); + mOutputLod0Function = true; + node->traverse(this); + mOutputLod0Function = false; + } + + return false; +} + +bool OutputHLSL::visitDeclaration(Visit visit, TIntermDeclaration *node) +{ + if (visit == PreVisit) + { + TIntermSequence *sequence = node->getSequence(); + TIntermTyped *declarator = (*sequence)[0]->getAsTyped(); + ASSERT(sequence->size() == 1); + ASSERT(declarator); + + if (IsDeclarationWrittenOut(node)) + { + TInfoSinkBase &out = getInfoSink(); + ensureStructDefined(declarator->getType()); + + if (!declarator->getAsSymbolNode() || + declarator->getAsSymbolNode()->variable().symbolType() != + SymbolType::Empty) // Variable declaration + { + if (declarator->getQualifier() == EvqShared) + { + out << "groupshared "; + } + else if (!mInsideFunction) + { + out << "static "; + } + + out << TypeString(declarator->getType()) + " "; + + TIntermSymbol *symbol = declarator->getAsSymbolNode(); + + if (symbol) + { + symbol->traverse(this); + out << ArrayString(symbol->getType()); + // Temporarily disable shadred memory initialization. It is very slow for D3D11 + // drivers to compile a compute shader if we add code to initialize a + // groupshared array variable with a large array size. And maybe produce + // incorrect result. See http://anglebug.com/3226. + if (declarator->getQualifier() != EvqShared) + { + out << " = " + zeroInitializer(symbol->getType()); + } + } + else + { + declarator->traverse(this); + } + } + } + else if (IsVaryingOut(declarator->getQualifier())) + { + TIntermSymbol *symbol = declarator->getAsSymbolNode(); + ASSERT(symbol); // Varying declarations can't have initializers. + + const TVariable &variable = symbol->variable(); + + if (variable.symbolType() != SymbolType::Empty) + { + // Vertex outputs which are declared but not written to should still be declared to + // allow successful linking. + mReferencedVaryings[symbol->uniqueId().get()] = &variable; + } + } + } + return false; +} + +bool OutputHLSL::visitGlobalQualifierDeclaration(Visit visit, + TIntermGlobalQualifierDeclaration *node) +{ + // Do not do any translation + return false; +} + +void OutputHLSL::visitFunctionPrototype(TIntermFunctionPrototype *node) +{ + TInfoSinkBase &out = getInfoSink(); + + size_t index = mCallDag.findIndex(node->getFunction()->uniqueId()); + // Skip the prototype if it is not implemented (and thus not used) + if (index == CallDAG::InvalidIndex) + { + return; + } + + const TFunction *func = node->getFunction(); + + TString name = DecorateFunctionIfNeeded(func); + out << TypeString(node->getType()) << " " << name << DisambiguateFunctionName(func) + << (mOutputLod0Function ? "Lod0(" : "("); + + size_t paramCount = func->getParamCount(); + for (unsigned int i = 0; i < paramCount; i++) + { + writeParameter(func->getParam(i), out); + + if (i < paramCount - 1) + { + out << ", "; + } + } + + out << ");\n"; + + // Also prototype the Lod0 variant if needed + bool needsLod0 = mASTMetadataList[index].mNeedsLod0; + if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER) + { + mOutputLod0Function = true; + node->traverse(this); + mOutputLod0Function = false; + } +} + +bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) +{ + TInfoSinkBase &out = getInfoSink(); + + switch (node->getOp()) + { + case EOpCallFunctionInAST: + case EOpCallInternalRawFunction: + default: + { + TIntermSequence *arguments = node->getSequence(); + + bool lod0 = (mInsideDiscontinuousLoop || mOutputLod0Function) && + mShaderType == GL_FRAGMENT_SHADER; + + // No raw function is expected. + ASSERT(node->getOp() != EOpCallInternalRawFunction); + + if (node->getOp() == EOpCallFunctionInAST) + { + if (node->isArray()) + { + UNIMPLEMENTED(); + } + size_t index = mCallDag.findIndex(node->getFunction()->uniqueId()); + ASSERT(index != CallDAG::InvalidIndex); + lod0 &= mASTMetadataList[index].mNeedsLod0; + + out << DecorateFunctionIfNeeded(node->getFunction()); + out << DisambiguateFunctionName(node->getSequence()); + out << (lod0 ? "Lod0(" : "("); + } + else if (node->getFunction()->isImageFunction()) + { + const ImmutableString &name = node->getFunction()->name(); + TType type = (*arguments)[0]->getAsTyped()->getType(); + const ImmutableString &imageFunctionName = mImageFunctionHLSL->useImageFunction( + name, type.getBasicType(), type.getLayoutQualifier().imageInternalFormat, + type.getMemoryQualifier().readonly); + out << imageFunctionName << "("; + } + else if (node->getFunction()->isAtomicCounterFunction()) + { + const ImmutableString &name = node->getFunction()->name(); + ImmutableString atomicFunctionName = + mAtomicCounterFunctionHLSL->useAtomicCounterFunction(name); + out << atomicFunctionName << "("; + } + else + { + const ImmutableString &name = node->getFunction()->name(); + TBasicType samplerType = (*arguments)[0]->getAsTyped()->getType().getBasicType(); + int coords = 0; // textureSize(gsampler2DMS) doesn't have a second argument. + if (arguments->size() > 1) + { + coords = (*arguments)[1]->getAsTyped()->getNominalSize(); + } + const ImmutableString &textureFunctionName = + mTextureFunctionHLSL->useTextureFunction(name, samplerType, coords, + arguments->size(), lod0, mShaderType); + out << textureFunctionName << "("; + } + + for (TIntermSequence::iterator arg = arguments->begin(); arg != arguments->end(); arg++) + { + TIntermTyped *typedArg = (*arg)->getAsTyped(); + if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(typedArg->getBasicType())) + { + out << "texture_"; + (*arg)->traverse(this); + out << ", sampler_"; + } + + (*arg)->traverse(this); + + if (typedArg->getType().isStructureContainingSamplers()) + { + const TType &argType = typedArg->getType(); + TVector samplerSymbols; + ImmutableString structName = samplerNamePrefixFromStruct(typedArg); + std::string namePrefix = "angle_"; + namePrefix += structName.data(); + argType.createSamplerSymbols(ImmutableString(namePrefix), "", &samplerSymbols, + nullptr, mSymbolTable); + for (const TVariable *sampler : samplerSymbols) + { + if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) + { + out << ", texture_" << sampler->name(); + out << ", sampler_" << sampler->name(); + } + else + { + // In case of HLSL 4.1+, this symbol is the sampler index, and in case + // of D3D9, it's the sampler variable. + out << ", " << sampler->name(); + } + } + } + + if (arg < arguments->end() - 1) + { + out << ", "; + } + } + + out << ")"; + + return false; + } + case EOpConstruct: + outputConstructor(out, visit, node); + break; + case EOpEqualComponentWise: + outputTriplet(out, visit, "(", " == ", ")"); + break; + case EOpNotEqualComponentWise: + outputTriplet(out, visit, "(", " != ", ")"); + break; + case EOpLessThanComponentWise: + outputTriplet(out, visit, "(", " < ", ")"); + break; + case EOpGreaterThanComponentWise: + outputTriplet(out, visit, "(", " > ", ")"); + break; + case EOpLessThanEqualComponentWise: + outputTriplet(out, visit, "(", " <= ", ")"); + break; + case EOpGreaterThanEqualComponentWise: + outputTriplet(out, visit, "(", " >= ", ")"); + break; + case EOpMod: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, node->getFunction()); + break; + case EOpModf: + outputTriplet(out, visit, "modf(", ", ", ")"); + break; + case EOpPow: + outputTriplet(out, visit, "pow(", ", ", ")"); + break; + case EOpAtan: + ASSERT(node->getSequence()->size() == 2); // atan(x) is a unary operator + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, node->getFunction()); + break; + case EOpMin: + outputTriplet(out, visit, "min(", ", ", ")"); + break; + case EOpMax: + outputTriplet(out, visit, "max(", ", ", ")"); + break; + case EOpClamp: + outputTriplet(out, visit, "clamp(", ", ", ")"); + break; + case EOpMix: + { + TIntermTyped *lastParamNode = (*(node->getSequence()))[2]->getAsTyped(); + if (lastParamNode->getType().getBasicType() == EbtBool) + { + // There is no HLSL equivalent for ESSL3 built-in "genType mix (genType x, genType + // y, genBType a)", + // so use emulated version. + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, node->getFunction()); + } + else + { + outputTriplet(out, visit, "lerp(", ", ", ")"); + } + break; + } + case EOpStep: + outputTriplet(out, visit, "step(", ", ", ")"); + break; + case EOpSmoothstep: + outputTriplet(out, visit, "smoothstep(", ", ", ")"); + break; + case EOpFma: + outputTriplet(out, visit, "mad(", ", ", ")"); + break; + case EOpFrexp: + case EOpLdexp: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, node->getFunction()); + break; + case EOpDistance: + outputTriplet(out, visit, "distance(", ", ", ")"); + break; + case EOpDot: + outputTriplet(out, visit, "dot(", ", ", ")"); + break; + case EOpCross: + outputTriplet(out, visit, "cross(", ", ", ")"); + break; + case EOpFaceforward: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, node->getFunction()); + break; + case EOpReflect: + outputTriplet(out, visit, "reflect(", ", ", ")"); + break; + case EOpRefract: + outputTriplet(out, visit, "refract(", ", ", ")"); + break; + case EOpOuterProduct: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, node->getFunction()); + break; + case EOpMatrixCompMult: + outputTriplet(out, visit, "(", " * ", ")"); + break; + case EOpBitfieldExtract: + case EOpBitfieldInsert: + case EOpUaddCarry: + case EOpUsubBorrow: + case EOpUmulExtended: + case EOpImulExtended: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, node->getFunction()); + break; + case EOpDFdx: + if (mInsideDiscontinuousLoop || mOutputLod0Function) + { + outputTriplet(out, visit, "(", "", ", 0.0)"); + } + else + { + outputTriplet(out, visit, "ddx(", "", ")"); + } + break; + case EOpDFdy: + if (mInsideDiscontinuousLoop || mOutputLod0Function) + { + outputTriplet(out, visit, "(", "", ", 0.0)"); + } + else + { + outputTriplet(out, visit, "ddy(", "", ")"); + } + break; + case EOpFwidth: + if (mInsideDiscontinuousLoop || mOutputLod0Function) + { + outputTriplet(out, visit, "(", "", ", 0.0)"); + } + else + { + outputTriplet(out, visit, "fwidth(", "", ")"); + } + break; + case EOpBarrier: + // barrier() is translated to GroupMemoryBarrierWithGroupSync(), which is the + // cheapest *WithGroupSync() function, without any functionality loss, but + // with the potential for severe performance loss. + outputTriplet(out, visit, "GroupMemoryBarrierWithGroupSync(", "", ")"); + break; + case EOpMemoryBarrierShared: + outputTriplet(out, visit, "GroupMemoryBarrier(", "", ")"); + break; + case EOpMemoryBarrierAtomicCounter: + case EOpMemoryBarrierBuffer: + case EOpMemoryBarrierImage: + outputTriplet(out, visit, "DeviceMemoryBarrier(", "", ")"); + break; + case EOpGroupMemoryBarrier: + case EOpMemoryBarrier: + outputTriplet(out, visit, "AllMemoryBarrier(", "", ")"); + break; + + // Single atomic function calls without return value. + // e.g. atomicAdd(dest, value) should be translated into InterlockedAdd(dest, value). + case EOpAtomicAdd: + case EOpAtomicMin: + case EOpAtomicMax: + case EOpAtomicAnd: + case EOpAtomicOr: + case EOpAtomicXor: + // The parameter 'original_value' of InterlockedExchange(dest, value, original_value) + // and InterlockedCompareExchange(dest, compare_value, value, original_value) is not + // optional. + // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/interlockedexchange + // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/interlockedcompareexchange + // So all the call of atomicExchange(dest, value) and atomicCompSwap(dest, + // compare_value, value) should all be modified into the form of "int temp; temp = + // atomicExchange(dest, value);" and "int temp; temp = atomicCompSwap(dest, + // compare_value, value);" in the intermediate tree before traversing outputHLSL. + case EOpAtomicExchange: + case EOpAtomicCompSwap: + { + ASSERT(node->getChildCount() > 1); + TIntermTyped *memNode = (*node->getSequence())[0]->getAsTyped(); + if (IsInShaderStorageBlock(memNode)) + { + // Atomic memory functions for SSBO. + // "_ssbo_atomicXXX_TYPE(RWByteAddressBuffer buffer, uint loc" is written to |out|. + mSSBOOutputHLSL->outputAtomicMemoryFunctionCallPrefix(memNode, node->getOp()); + // Write the rest argument list to |out|. + for (size_t i = 1; i < node->getChildCount(); i++) + { + out << ", "; + TIntermTyped *argument = (*node->getSequence())[i]->getAsTyped(); + if (IsInShaderStorageBlock(argument)) + { + mSSBOOutputHLSL->outputLoadFunctionCall(argument); + } + else + { + argument->traverse(this); + } + } + + out << ")"; + return false; + } + else + { + // Atomic memory functions for shared variable. + if (node->getOp() != EOpAtomicExchange && node->getOp() != EOpAtomicCompSwap) + { + outputTriplet(out, visit, + GetHLSLAtomicFunctionStringAndLeftParenthesis(node->getOp()), ",", + ")"); + } + else + { + UNREACHABLE(); + } + } + + break; + } + } + + return true; +} + +void OutputHLSL::writeIfElse(TInfoSinkBase &out, TIntermIfElse *node) +{ + out << "if ("; + + node->getCondition()->traverse(this); + + out << ")\n"; + + outputLineDirective(out, node->getLine().first_line); + + bool discard = false; + + if (node->getTrueBlock()) + { + // The trueBlock child node will output braces. + node->getTrueBlock()->traverse(this); + + // Detect true discard + discard = (discard || FindDiscard::search(node->getTrueBlock())); + } + else + { + // TODO(oetuaho): Check if the semicolon inside is necessary. + // It's there as a result of conservative refactoring of the output. + out << "{;}\n"; + } + + outputLineDirective(out, node->getLine().first_line); + + if (node->getFalseBlock()) + { + out << "else\n"; + + outputLineDirective(out, node->getFalseBlock()->getLine().first_line); + + // The falseBlock child node will output braces. + node->getFalseBlock()->traverse(this); + + outputLineDirective(out, node->getFalseBlock()->getLine().first_line); + + // Detect false discard + discard = (discard || FindDiscard::search(node->getFalseBlock())); + } + + // ANGLE issue 486: Detect problematic conditional discard + if (discard) + { + mUsesDiscardRewriting = true; + } +} + +bool OutputHLSL::visitTernary(Visit, TIntermTernary *) +{ + // Ternary ops should have been already converted to something else in the AST. HLSL ternary + // operator doesn't short-circuit, so it's not the same as the GLSL ternary operator. + UNREACHABLE(); + return false; +} + +bool OutputHLSL::visitIfElse(Visit visit, TIntermIfElse *node) +{ + TInfoSinkBase &out = getInfoSink(); + + ASSERT(mInsideFunction); + + // D3D errors when there is a gradient operation in a loop in an unflattened if. + if (mShaderType == GL_FRAGMENT_SHADER && mCurrentFunctionMetadata->hasGradientLoop(node)) + { + out << "FLATTEN "; + } + + writeIfElse(out, node); + + return false; +} + +bool OutputHLSL::visitSwitch(Visit visit, TIntermSwitch *node) +{ + TInfoSinkBase &out = getInfoSink(); + + ASSERT(node->getStatementList()); + if (visit == PreVisit) + { + node->setStatementList(RemoveSwitchFallThrough(node->getStatementList(), mPerfDiagnostics)); + } + outputTriplet(out, visit, "switch (", ") ", ""); + // The curly braces get written when visiting the statementList block. + return true; +} + +bool OutputHLSL::visitCase(Visit visit, TIntermCase *node) +{ + TInfoSinkBase &out = getInfoSink(); + + if (node->hasCondition()) + { + outputTriplet(out, visit, "case (", "", "):\n"); + return true; + } + else + { + out << "default:\n"; + return false; + } +} + +void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node) +{ + TInfoSinkBase &out = getInfoSink(); + writeConstantUnion(out, node->getType(), node->getConstantValue()); +} + +bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) +{ + mNestedLoopDepth++; + + bool wasDiscontinuous = mInsideDiscontinuousLoop; + mInsideDiscontinuousLoop = + mInsideDiscontinuousLoop || mCurrentFunctionMetadata->mDiscontinuousLoops.count(node) > 0; + + TInfoSinkBase &out = getInfoSink(); + + if (mOutputType == SH_HLSL_3_0_OUTPUT) + { + if (handleExcessiveLoop(out, node)) + { + mInsideDiscontinuousLoop = wasDiscontinuous; + mNestedLoopDepth--; + + return false; + } + } + + const char *unroll = mCurrentFunctionMetadata->hasGradientInCallGraph(node) ? "LOOP" : ""; + if (node->getType() == ELoopDoWhile) + { + out << "{" << unroll << " do\n"; + + outputLineDirective(out, node->getLine().first_line); + } + else + { + out << "{" << unroll << " for("; + + if (node->getInit()) + { + node->getInit()->traverse(this); + } + + out << "; "; + + if (node->getCondition()) + { + node->getCondition()->traverse(this); + } + + out << "; "; + + if (node->getExpression()) + { + node->getExpression()->traverse(this); + } + + out << ")\n"; + + outputLineDirective(out, node->getLine().first_line); + } + + if (node->getBody()) + { + // The loop body node will output braces. + node->getBody()->traverse(this); + } + else + { + // TODO(oetuaho): Check if the semicolon inside is necessary. + // It's there as a result of conservative refactoring of the output. + out << "{;}\n"; + } + + outputLineDirective(out, node->getLine().first_line); + + if (node->getType() == ELoopDoWhile) + { + outputLineDirective(out, node->getCondition()->getLine().first_line); + out << "while ("; + + node->getCondition()->traverse(this); + + out << ");\n"; + } + + out << "}\n"; + + mInsideDiscontinuousLoop = wasDiscontinuous; + mNestedLoopDepth--; + + return false; +} + +bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) +{ + if (visit == PreVisit) + { + TInfoSinkBase &out = getInfoSink(); + + switch (node->getFlowOp()) + { + case EOpKill: + out << "discard"; + break; + case EOpBreak: + if (mNestedLoopDepth > 1) + { + mUsesNestedBreak = true; + } + + if (mExcessiveLoopIndex) + { + out << "{Break"; + mExcessiveLoopIndex->traverse(this); + out << " = true; break;}\n"; + } + else + { + out << "break"; + } + break; + case EOpContinue: + out << "continue"; + break; + case EOpReturn: + if (node->getExpression()) + { + ASSERT(!mInsideMain); + out << "return "; + if (IsInShaderStorageBlock(node->getExpression())) + { + mSSBOOutputHLSL->outputLoadFunctionCall(node->getExpression()); + return false; + } + } + else + { + if (mInsideMain && shaderNeedsGenerateOutput()) + { + out << "return " << generateOutputCall(); + } + else + { + out << "return"; + } + } + break; + default: + UNREACHABLE(); + } + } + + return true; +} + +// Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them +// (The D3D documentation says 255 iterations, but the compiler complains at anything more than +// 254). +bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node) +{ + const int MAX_LOOP_ITERATIONS = 254; + + // Parse loops of the form: + // for(int index = initial; index [comparator] limit; index += increment) + TIntermSymbol *index = nullptr; + TOperator comparator = EOpNull; + int initial = 0; + int limit = 0; + int increment = 0; + + // Parse index name and intial value + if (node->getInit()) + { + TIntermDeclaration *init = node->getInit()->getAsDeclarationNode(); + + if (init) + { + TIntermSequence *sequence = init->getSequence(); + TIntermTyped *variable = (*sequence)[0]->getAsTyped(); + + if (variable && variable->getQualifier() == EvqTemporary) + { + TIntermBinary *assign = variable->getAsBinaryNode(); + + if (assign != nullptr && assign->getOp() == EOpInitialize) + { + TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode(); + TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion(); + + if (symbol && constant) + { + if (constant->getBasicType() == EbtInt && constant->isScalar()) + { + index = symbol; + initial = constant->getIConst(0); + } + } + } + } + } + } + + // Parse comparator and limit value + if (index != nullptr && node->getCondition()) + { + TIntermBinary *test = node->getCondition()->getAsBinaryNode(); + + if (test && test->getLeft()->getAsSymbolNode()->uniqueId() == index->uniqueId()) + { + TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion(); + + if (constant) + { + if (constant->getBasicType() == EbtInt && constant->isScalar()) + { + comparator = test->getOp(); + limit = constant->getIConst(0); + } + } + } + } + + // Parse increment + if (index != nullptr && comparator != EOpNull && node->getExpression()) + { + TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode(); + TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode(); + + if (binaryTerminal) + { + TOperator op = binaryTerminal->getOp(); + TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion(); + + if (constant) + { + if (constant->getBasicType() == EbtInt && constant->isScalar()) + { + int value = constant->getIConst(0); + + switch (op) + { + case EOpAddAssign: + increment = value; + break; + case EOpSubAssign: + increment = -value; + break; + default: + UNIMPLEMENTED(); + } + } + } + } + else if (unaryTerminal) + { + TOperator op = unaryTerminal->getOp(); + + switch (op) + { + case EOpPostIncrement: + increment = 1; + break; + case EOpPostDecrement: + increment = -1; + break; + case EOpPreIncrement: + increment = 1; + break; + case EOpPreDecrement: + increment = -1; + break; + default: + UNIMPLEMENTED(); + } + } + } + + if (index != nullptr && comparator != EOpNull && increment != 0) + { + if (comparator == EOpLessThanEqual) + { + comparator = EOpLessThan; + limit += 1; + } + + if (comparator == EOpLessThan) + { + int iterations = (limit - initial) / increment; + + if (iterations <= MAX_LOOP_ITERATIONS) + { + return false; // Not an excessive loop + } + + TIntermSymbol *restoreIndex = mExcessiveLoopIndex; + mExcessiveLoopIndex = index; + + out << "{int "; + index->traverse(this); + out << ";\n" + "bool Break"; + index->traverse(this); + out << " = false;\n"; + + bool firstLoopFragment = true; + + while (iterations > 0) + { + int clampedLimit = initial + increment * std::min(MAX_LOOP_ITERATIONS, iterations); + + if (!firstLoopFragment) + { + out << "if (!Break"; + index->traverse(this); + out << ") {\n"; + } + + if (iterations <= MAX_LOOP_ITERATIONS) // Last loop fragment + { + mExcessiveLoopIndex = nullptr; // Stops setting the Break flag + } + + // for(int index = initial; index < clampedLimit; index += increment) + const char *unroll = + mCurrentFunctionMetadata->hasGradientInCallGraph(node) ? "LOOP" : ""; + + out << unroll << " for("; + index->traverse(this); + out << " = "; + out << initial; + + out << "; "; + index->traverse(this); + out << " < "; + out << clampedLimit; + + out << "; "; + index->traverse(this); + out << " += "; + out << increment; + out << ")\n"; + + outputLineDirective(out, node->getLine().first_line); + out << "{\n"; + + if (node->getBody()) + { + node->getBody()->traverse(this); + } + + outputLineDirective(out, node->getLine().first_line); + out << ";}\n"; + + if (!firstLoopFragment) + { + out << "}\n"; + } + + firstLoopFragment = false; + + initial += MAX_LOOP_ITERATIONS * increment; + iterations -= MAX_LOOP_ITERATIONS; + } + + out << "}"; + + mExcessiveLoopIndex = restoreIndex; + + return true; + } + else + UNIMPLEMENTED(); + } + + return false; // Not handled as an excessive loop +} + +void OutputHLSL::outputTriplet(TInfoSinkBase &out, + Visit visit, + const char *preString, + const char *inString, + const char *postString) +{ + if (visit == PreVisit) + { + out << preString; + } + else if (visit == InVisit) + { + out << inString; + } + else if (visit == PostVisit) + { + out << postString; + } +} + +void OutputHLSL::outputLineDirective(TInfoSinkBase &out, int line) +{ + if (mCompileOptions.lineDirectives && line > 0) + { + out << "\n"; + out << "#line " << line; + + if (mSourcePath) + { + out << " \"" << mSourcePath << "\""; + } + + out << "\n"; + } +} + +void OutputHLSL::writeParameter(const TVariable *param, TInfoSinkBase &out) +{ + const TType &type = param->getType(); + TQualifier qualifier = type.getQualifier(); + + TString nameStr = DecorateVariableIfNeeded(*param); + ASSERT(nameStr != ""); // HLSL demands named arguments, also for prototypes + + if (IsSampler(type.getBasicType())) + { + if (mOutputType == SH_HLSL_4_1_OUTPUT) + { + // Samplers are passed as indices to the sampler array. + ASSERT(qualifier != EvqParamOut && qualifier != EvqParamInOut); + out << "const uint " << nameStr << ArrayString(type); + return; + } + if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) + { + out << QualifierString(qualifier) << " " << TextureString(type.getBasicType()) + << " texture_" << nameStr << ArrayString(type) << ", " << QualifierString(qualifier) + << " " << SamplerString(type.getBasicType()) << " sampler_" << nameStr + << ArrayString(type); + return; + } + } + + // If the parameter is an atomic counter, we need to add an extra parameter to keep track of the + // buffer offset. + if (IsAtomicCounter(type.getBasicType())) + { + out << QualifierString(qualifier) << " " << TypeString(type) << " " << nameStr << ", int " + << nameStr << "_offset"; + } + else + { + out << QualifierString(qualifier) << " " << TypeString(type) << " " << nameStr + << ArrayString(type); + } + + // If the structure parameter contains samplers, they need to be passed into the function as + // separate parameters. HLSL doesn't natively support samplers in structs. + if (type.isStructureContainingSamplers()) + { + ASSERT(qualifier != EvqParamOut && qualifier != EvqParamInOut); + TVector samplerSymbols; + std::string namePrefix = "angle"; + namePrefix += nameStr.c_str(); + type.createSamplerSymbols(ImmutableString(namePrefix), "", &samplerSymbols, nullptr, + mSymbolTable); + for (const TVariable *sampler : samplerSymbols) + { + const TType &samplerType = sampler->getType(); + if (mOutputType == SH_HLSL_4_1_OUTPUT) + { + out << ", const uint " << sampler->name() << ArrayString(samplerType); + } + else if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) + { + ASSERT(IsSampler(samplerType.getBasicType())); + out << ", " << QualifierString(qualifier) << " " + << TextureString(samplerType.getBasicType()) << " texture_" << sampler->name() + << ArrayString(samplerType) << ", " << QualifierString(qualifier) << " " + << SamplerString(samplerType.getBasicType()) << " sampler_" << sampler->name() + << ArrayString(samplerType); + } + else + { + ASSERT(IsSampler(samplerType.getBasicType())); + out << ", " << QualifierString(qualifier) << " " << TypeString(samplerType) << " " + << sampler->name() << ArrayString(samplerType); + } + } + } +} + +TString OutputHLSL::zeroInitializer(const TType &type) const +{ + TString string; + + size_t size = type.getObjectSize(); + if (size >= kZeroCount) + { + mUseZeroArray = true; + } + string = GetZeroInitializer(size).c_str(); + + return "{" + string + "}"; +} + +void OutputHLSL::outputConstructor(TInfoSinkBase &out, Visit visit, TIntermAggregate *node) +{ + // Array constructors should have been already pruned from the code. + ASSERT(!node->getType().isArray()); + + if (visit == PreVisit) + { + TString constructorName; + if (node->getBasicType() == EbtStruct) + { + constructorName = mStructureHLSL->addStructConstructor(*node->getType().getStruct()); + } + else + { + constructorName = + mStructureHLSL->addBuiltInConstructor(node->getType(), node->getSequence()); + } + out << constructorName << "("; + } + else if (visit == InVisit) + { + out << ", "; + } + else if (visit == PostVisit) + { + out << ")"; + } +} + +const TConstantUnion *OutputHLSL::writeConstantUnion(TInfoSinkBase &out, + const TType &type, + const TConstantUnion *const constUnion) +{ + ASSERT(!type.isArray()); + + const TConstantUnion *constUnionIterated = constUnion; + + const TStructure *structure = type.getStruct(); + if (structure) + { + out << mStructureHLSL->addStructConstructor(*structure) << "("; + + const TFieldList &fields = structure->fields(); + + for (size_t i = 0; i < fields.size(); i++) + { + const TType *fieldType = fields[i]->type(); + constUnionIterated = writeConstantUnion(out, *fieldType, constUnionIterated); + + if (i != fields.size() - 1) + { + out << ", "; + } + } + + out << ")"; + } + else + { + size_t size = type.getObjectSize(); + bool writeType = size > 1; + + if (writeType) + { + out << TypeString(type) << "("; + } + constUnionIterated = writeConstantUnionArray(out, constUnionIterated, size); + if (writeType) + { + out << ")"; + } + } + + return constUnionIterated; +} + +void OutputHLSL::writeEmulatedFunctionTriplet(TInfoSinkBase &out, + Visit visit, + const TFunction *function) +{ + if (visit == PreVisit) + { + ASSERT(function != nullptr); + BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, function->name().data()); + out << "("; + } + else + { + outputTriplet(out, visit, nullptr, ", ", ")"); + } +} + +bool OutputHLSL::writeSameSymbolInitializer(TInfoSinkBase &out, + TIntermSymbol *symbolNode, + TIntermTyped *expression) +{ + ASSERT(symbolNode->variable().symbolType() != SymbolType::Empty); + const TIntermSymbol *symbolInInitializer = FindSymbolNode(expression, symbolNode->getName()); + + if (symbolInInitializer) + { + // Type already printed + out << "t" + str(mUniqueIndex) + " = "; + expression->traverse(this); + out << ", "; + symbolNode->traverse(this); + out << " = t" + str(mUniqueIndex); + + mUniqueIndex++; + return true; + } + + return false; +} + +bool OutputHLSL::writeConstantInitialization(TInfoSinkBase &out, + TIntermSymbol *symbolNode, + TIntermTyped *initializer) +{ + if (initializer->hasConstantValue()) + { + symbolNode->traverse(this); + out << ArrayString(symbolNode->getType()); + out << " = {"; + writeConstantUnionArray(out, initializer->getConstantValue(), + initializer->getType().getObjectSize()); + out << "}"; + return true; + } + return false; +} + +TString OutputHLSL::addStructEqualityFunction(const TStructure &structure) +{ + const TFieldList &fields = structure.fields(); + + for (const auto &eqFunction : mStructEqualityFunctions) + { + if (eqFunction->structure == &structure) + { + return eqFunction->functionName; + } + } + + const TString &structNameString = StructNameString(structure); + + StructEqualityFunction *function = new StructEqualityFunction(); + function->structure = &structure; + function->functionName = "angle_eq_" + structNameString; + + TInfoSinkBase fnOut; + + fnOut << "bool " << function->functionName << "(" << structNameString << " a, " + << structNameString + " b)\n" + << "{\n" + " return "; + + for (size_t i = 0; i < fields.size(); i++) + { + const TField *field = fields[i]; + const TType *fieldType = field->type(); + + const TString &fieldNameA = "a." + Decorate(field->name()); + const TString &fieldNameB = "b." + Decorate(field->name()); + + if (i > 0) + { + fnOut << " && "; + } + + fnOut << "("; + outputEqual(PreVisit, *fieldType, EOpEqual, fnOut); + fnOut << fieldNameA; + outputEqual(InVisit, *fieldType, EOpEqual, fnOut); + fnOut << fieldNameB; + outputEqual(PostVisit, *fieldType, EOpEqual, fnOut); + fnOut << ")"; + } + + fnOut << ";\n" + << "}\n"; + + function->functionDefinition = fnOut.c_str(); + + mStructEqualityFunctions.push_back(function); + mEqualityFunctions.push_back(function); + + return function->functionName; +} + +TString OutputHLSL::addArrayEqualityFunction(const TType &type) +{ + for (const auto &eqFunction : mArrayEqualityFunctions) + { + if (eqFunction->type == type) + { + return eqFunction->functionName; + } + } + + TType elementType(type); + elementType.toArrayElementType(); + + ArrayHelperFunction *function = new ArrayHelperFunction(); + function->type = type; + + function->functionName = ArrayHelperFunctionName("angle_eq", type); + + TInfoSinkBase fnOut; + + const TString &typeName = TypeString(type); + fnOut << "bool " << function->functionName << "(" << typeName << " a" << ArrayString(type) + << ", " << typeName << " b" << ArrayString(type) << ")\n" + << "{\n" + " for (int i = 0; i < " + << type.getOutermostArraySize() + << "; ++i)\n" + " {\n" + " if ("; + + outputEqual(PreVisit, elementType, EOpNotEqual, fnOut); + fnOut << "a[i]"; + outputEqual(InVisit, elementType, EOpNotEqual, fnOut); + fnOut << "b[i]"; + outputEqual(PostVisit, elementType, EOpNotEqual, fnOut); + + fnOut << ") { return false; }\n" + " }\n" + " return true;\n" + "}\n"; + + function->functionDefinition = fnOut.c_str(); + + mArrayEqualityFunctions.push_back(function); + mEqualityFunctions.push_back(function); + + return function->functionName; +} + +TString OutputHLSL::addArrayAssignmentFunction(const TType &type) +{ + for (const auto &assignFunction : mArrayAssignmentFunctions) + { + if (assignFunction.type == type) + { + return assignFunction.functionName; + } + } + + TType elementType(type); + elementType.toArrayElementType(); + + ArrayHelperFunction function; + function.type = type; + + function.functionName = ArrayHelperFunctionName("angle_assign", type); + + TInfoSinkBase fnOut; + + const TString &typeName = TypeString(type); + fnOut << "void " << function.functionName << "(out " << typeName << " a" << ArrayString(type) + << ", " << typeName << " b" << ArrayString(type) << ")\n" + << "{\n" + " for (int i = 0; i < " + << type.getOutermostArraySize() + << "; ++i)\n" + " {\n" + " "; + + outputAssign(PreVisit, elementType, fnOut); + fnOut << "a[i]"; + outputAssign(InVisit, elementType, fnOut); + fnOut << "b[i]"; + outputAssign(PostVisit, elementType, fnOut); + + fnOut << ";\n" + " }\n" + "}\n"; + + function.functionDefinition = fnOut.c_str(); + + mArrayAssignmentFunctions.push_back(function); + + return function.functionName; +} + +TString OutputHLSL::addArrayConstructIntoFunction(const TType &type) +{ + for (const auto &constructIntoFunction : mArrayConstructIntoFunctions) + { + if (constructIntoFunction.type == type) + { + return constructIntoFunction.functionName; + } + } + + TType elementType(type); + elementType.toArrayElementType(); + + ArrayHelperFunction function; + function.type = type; + + function.functionName = ArrayHelperFunctionName("angle_construct_into", type); + + TInfoSinkBase fnOut; + + const TString &typeName = TypeString(type); + fnOut << "void " << function.functionName << "(out " << typeName << " a" << ArrayString(type); + for (unsigned int i = 0u; i < type.getOutermostArraySize(); ++i) + { + fnOut << ", " << typeName << " b" << i << ArrayString(elementType); + } + fnOut << ")\n" + "{\n"; + + for (unsigned int i = 0u; i < type.getOutermostArraySize(); ++i) + { + fnOut << " "; + outputAssign(PreVisit, elementType, fnOut); + fnOut << "a[" << i << "]"; + outputAssign(InVisit, elementType, fnOut); + fnOut << "b" << i; + outputAssign(PostVisit, elementType, fnOut); + fnOut << ";\n"; + } + fnOut << "}\n"; + + function.functionDefinition = fnOut.c_str(); + + mArrayConstructIntoFunctions.push_back(function); + + return function.functionName; +} + +void OutputHLSL::ensureStructDefined(const TType &type) +{ + const TStructure *structure = type.getStruct(); + if (structure) + { + ASSERT(type.getBasicType() == EbtStruct); + mStructureHLSL->ensureStructDefined(*structure); + } +} + +bool OutputHLSL::shaderNeedsGenerateOutput() const +{ + return mShaderType == GL_VERTEX_SHADER || mShaderType == GL_FRAGMENT_SHADER; +} + +const char *OutputHLSL::generateOutputCall() const +{ + if (mShaderType == GL_VERTEX_SHADER) + { + return "generateOutput(input)"; + } + else + { + return "generateOutput()"; + } +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/OutputHLSL.h b/gfx/angle/checkout/src/compiler/translator/OutputHLSL.h new file mode 100644 index 0000000000..06cc22d486 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/OutputHLSL.h @@ -0,0 +1,289 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_OUTPUTHLSL_H_ +#define COMPILER_TRANSLATOR_OUTPUTHLSL_H_ + +#include +#include +#include + +#include "angle_gl.h" +#include "compiler/translator/ASTMetadataHLSL.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/FlagStd140Structs.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/ShaderStorageBlockOutputHLSL.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +class BuiltInFunctionEmulator; + +namespace sh +{ +class AtomicCounterFunctionHLSL; +class ImageFunctionHLSL; +class ResourcesHLSL; +class StructureHLSL; +class TextureFunctionHLSL; +class TSymbolTable; +class TVariable; +class UnfoldShortCircuit; + +using ReferencedVariables = std::map; + +class OutputHLSL : public TIntermTraverser +{ + public: + OutputHLSL(sh::GLenum shaderType, + ShShaderSpec shaderSpec, + int shaderVersion, + const TExtensionBehavior &extensionBehavior, + const char *sourcePath, + ShShaderOutput outputType, + int numRenderTargets, + int maxDualSourceDrawBuffers, + const std::vector &uniforms, + const ShCompileOptions &compileOptions, + sh::WorkGroupSize workGroupSize, + TSymbolTable *symbolTable, + PerformanceDiagnostics *perfDiagnostics, + const std::map &uniformBlockOptimizedMap, + const std::vector &shaderStorageBlocks, + bool isEarlyFragmentTestsSpecified); + + ~OutputHLSL() override; + + void output(TIntermNode *treeRoot, TInfoSinkBase &objSink); + + const std::map &getShaderStorageBlockRegisterMap() const; + const std::map &getUniformBlockRegisterMap() const; + const std::map &getUniformBlockUseStructuredBufferMap() const; + const std::map &getUniformRegisterMap() const; + unsigned int getReadonlyImage2DRegisterIndex() const; + unsigned int getImage2DRegisterIndex() const; + const std::set &getUsedImage2DFunctionNames() const; + + TInfoSinkBase &getInfoSink() + { + ASSERT(!mInfoSinkStack.empty()); + return *mInfoSinkStack.top(); + } + + protected: + friend class ShaderStorageBlockOutputHLSL; + + TString zeroInitializer(const TType &type) const; + + void writeReferencedAttributes(TInfoSinkBase &out) const; + void writeReferencedVaryings(TInfoSinkBase &out) const; + void header(TInfoSinkBase &out, + const std::vector &std140Structs, + const BuiltInFunctionEmulator *builtInFunctionEmulator) const; + + void writeFloat(TInfoSinkBase &out, float f); + void writeSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion); + const TConstantUnion *writeConstantUnionArray(TInfoSinkBase &out, + const TConstantUnion *const constUnion, + const size_t size); + + // Visit AST nodes and output their code to the body stream + void visitSymbol(TIntermSymbol *) override; + void visitConstantUnion(TIntermConstantUnion *) override; + bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; + bool visitBinary(Visit visit, TIntermBinary *) override; + bool visitUnary(Visit visit, TIntermUnary *) override; + bool visitTernary(Visit visit, TIntermTernary *) override; + bool visitIfElse(Visit visit, TIntermIfElse *) override; + bool visitSwitch(Visit visit, TIntermSwitch *) override; + bool visitCase(Visit visit, TIntermCase *) override; + void visitFunctionPrototype(TIntermFunctionPrototype *node) override; + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *) override; + bool visitBlock(Visit visit, TIntermBlock *node) override; + bool visitGlobalQualifierDeclaration(Visit visit, + TIntermGlobalQualifierDeclaration *node) override; + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; + bool visitLoop(Visit visit, TIntermLoop *) override; + bool visitBranch(Visit visit, TIntermBranch *) override; + + bool handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node); + + // Emit one of three strings depending on traverse phase. Called with literal strings so using + // const char* instead of TString. + void outputTriplet(TInfoSinkBase &out, + Visit visit, + const char *preString, + const char *inString, + const char *postString); + void outputLineDirective(TInfoSinkBase &out, int line); + void writeParameter(const TVariable *param, TInfoSinkBase &out); + + void outputConstructor(TInfoSinkBase &out, Visit visit, TIntermAggregate *node); + const TConstantUnion *writeConstantUnion(TInfoSinkBase &out, + const TType &type, + const TConstantUnion *constUnion); + + void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out); + void outputAssign(Visit visit, const TType &type, TInfoSinkBase &out); + + void writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, const TFunction *function); + + // Returns true if it found a 'same symbol' initializer (initializer that references the + // variable it's initting) + bool writeSameSymbolInitializer(TInfoSinkBase &out, + TIntermSymbol *symbolNode, + TIntermTyped *expression); + // Returns true if variable initializer could be written using literal {} notation. + bool writeConstantInitialization(TInfoSinkBase &out, + TIntermSymbol *symbolNode, + TIntermTyped *expression); + + void writeIfElse(TInfoSinkBase &out, TIntermIfElse *node); + + // Returns the function name + TString addStructEqualityFunction(const TStructure &structure); + TString addArrayEqualityFunction(const TType &type); + TString addArrayAssignmentFunction(const TType &type); + TString addArrayConstructIntoFunction(const TType &type); + + // Ensures if the type is a struct, the struct is defined + void ensureStructDefined(const TType &type); + + bool shaderNeedsGenerateOutput() const; + const char *generateOutputCall() const; + + sh::GLenum mShaderType; + ShShaderSpec mShaderSpec; + int mShaderVersion; + const TExtensionBehavior &mExtensionBehavior; + const char *mSourcePath; + const ShShaderOutput mOutputType; + const ShCompileOptions &mCompileOptions; + + bool mInsideFunction; + bool mInsideMain; + + // Output streams + TInfoSinkBase mHeader; + TInfoSinkBase mBody; + TInfoSinkBase mFooter; + + // A stack is useful when we want to traverse in the header, or in helper functions, but not + // always write to the body. Instead use an InfoSink stack to keep our current state intact. + // TODO (jmadill): Just passing an InfoSink in function parameters would be simpler. + std::stack mInfoSinkStack; + + ReferencedVariables mReferencedUniforms; + + // Indexed by block id, not instance id. + ReferencedInterfaceBlocks mReferencedUniformBlocks; + + std::map mUniformBlockOptimizedMap; + + ReferencedVariables mReferencedAttributes; + ReferencedVariables mReferencedVaryings; + ReferencedVariables mReferencedOutputVariables; + + StructureHLSL *mStructureHLSL; + ResourcesHLSL *mResourcesHLSL; + TextureFunctionHLSL *mTextureFunctionHLSL; + ImageFunctionHLSL *mImageFunctionHLSL; + AtomicCounterFunctionHLSL *mAtomicCounterFunctionHLSL; + + // Parameters determining what goes in the header output + bool mUsesFragColor; + bool mUsesFragData; + bool mUsesDepthRange; + bool mUsesFragCoord; + bool mUsesPointCoord; + bool mUsesFrontFacing; + bool mUsesHelperInvocation; + bool mUsesPointSize; + bool mUsesInstanceID; + bool mHasMultiviewExtensionEnabled; + bool mUsesViewID; + bool mUsesVertexID; + bool mUsesFragDepth; + bool mUsesNumWorkGroups; + bool mUsesWorkGroupID; + bool mUsesLocalInvocationID; + bool mUsesGlobalInvocationID; + bool mUsesLocalInvocationIndex; + bool mUsesXor; + bool mUsesDiscardRewriting; + bool mUsesNestedBreak; + bool mRequiresIEEEStrictCompiling; + mutable bool mUseZeroArray; + bool mUsesSecondaryColor; + + int mNumRenderTargets; + int mMaxDualSourceDrawBuffers; + + int mUniqueIndex; // For creating unique names + + CallDAG mCallDag; + MetadataList mASTMetadataList; + ASTMetadataHLSL *mCurrentFunctionMetadata; + bool mOutputLod0Function; + bool mInsideDiscontinuousLoop; + int mNestedLoopDepth; + + TIntermSymbol *mExcessiveLoopIndex; + + TString structInitializerString(int indent, const TType &type, const TString &name) const; + + struct HelperFunction + { + TString functionName; + TString functionDefinition; + + virtual ~HelperFunction() {} + }; + + // A list of all equality comparison functions. It's important to preserve the order at + // which we add the functions, since nested structures call each other recursively, and + // structure equality functions may need to call array equality functions and vice versa. + // The ownership of the pointers is maintained by the type-specific arrays. + std::vector mEqualityFunctions; + + struct StructEqualityFunction : public HelperFunction + { + const TStructure *structure; + }; + std::vector mStructEqualityFunctions; + + struct ArrayHelperFunction : public HelperFunction + { + TType type; + }; + std::vector mArrayEqualityFunctions; + + std::vector mArrayAssignmentFunctions; + + // The construct-into functions are functions that fill an N-element array passed as an out + // parameter with the other N parameters of the function. This is used to work around that + // arrays can't be return values in HLSL. + std::vector mArrayConstructIntoFunctions; + + sh::WorkGroupSize mWorkGroupSize; + + PerformanceDiagnostics *mPerfDiagnostics; + + private: + TString generateStructMapping(const std::vector &std140Structs) const; + ImmutableString samplerNamePrefixFromStruct(TIntermTyped *node); + bool ancestorEvaluatesToSamplerInStruct(); + // We need to do struct mapping when pass the struct to a function or copy the struct via + // assignment. + bool needStructMapping(TIntermTyped *node); + + ShaderStorageBlockOutputHLSL *mSSBOOutputHLSL; + bool mIsEarlyFragmentTestsSpecified; + bool mNeedStructMapping; +}; +} // namespace sh + +#endif // COMPILER_TRANSLATOR_OUTPUTHLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/OutputTree.cpp b/gfx/angle/checkout/src/compiler/translator/OutputTree.cpp new file mode 100644 index 0000000000..f51e891ce8 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/OutputTree.cpp @@ -0,0 +1,723 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +void OutputFunction(TInfoSinkBase &out, const char *str, const TFunction *func) +{ + const char *internal = + (func->symbolType() == SymbolType::AngleInternal) ? " (internal function)" : ""; + out << str << internal << ": " << func->name() << " (symbol id " << func->uniqueId().get() + << ")"; +} + +// Two purposes: +// 1. Show an example of how to iterate tree. Functions can also directly call traverse() on +// children themselves to have finer grained control over the process than shown here, though +// that's not recommended if it can be avoided. +// 2. Print out a text based description of the tree. + +// The traverser subclass is used to carry along data from node to node in the traversal. +class TOutputTraverser : public TIntermTraverser +{ + public: + TOutputTraverser(TInfoSinkBase &out) + : TIntermTraverser(true, false, false), mOut(out), mIndentDepth(0) + {} + + protected: + void visitSymbol(TIntermSymbol *) override; + void visitConstantUnion(TIntermConstantUnion *) override; + bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; + bool visitBinary(Visit visit, TIntermBinary *) override; + bool visitUnary(Visit visit, TIntermUnary *) override; + bool visitTernary(Visit visit, TIntermTernary *node) override; + bool visitIfElse(Visit visit, TIntermIfElse *node) override; + bool visitSwitch(Visit visit, TIntermSwitch *node) override; + bool visitCase(Visit visit, TIntermCase *node) override; + void visitFunctionPrototype(TIntermFunctionPrototype *node) override; + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *) override; + bool visitBlock(Visit visit, TIntermBlock *) override; + bool visitGlobalQualifierDeclaration(Visit visit, + TIntermGlobalQualifierDeclaration *node) override; + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; + bool visitLoop(Visit visit, TIntermLoop *) override; + bool visitBranch(Visit visit, TIntermBranch *) override; + + int getCurrentIndentDepth() const { return mIndentDepth + getCurrentTraversalDepth(); } + + TInfoSinkBase &mOut; + int mIndentDepth; +}; + +// +// Helper functions for printing, not part of traversing. +// +void OutputTreeText(TInfoSinkBase &out, TIntermNode *node, const int depth) +{ + int i; + + out.location(node->getLine().first_file, node->getLine().first_line); + + for (i = 0; i < depth; ++i) + out << " "; +} + +// +// The rest of the file are the traversal functions. The last one +// is the one that starts the traversal. +// +// Return true from interior nodes to have the external traversal +// continue on to children. If you process children yourself, +// return false. +// + +void TOutputTraverser::visitSymbol(TIntermSymbol *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + + if (node->variable().symbolType() == SymbolType::Empty) + { + mOut << "''"; + } + else + { + mOut << "'" << node->getName() << "' "; + } + mOut << "(symbol id " << node->uniqueId().get() << ") "; + mOut << "(" << node->getType() << ")"; + mOut << "\n"; +} + +bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + mOut << "vector swizzle ("; + node->writeOffsetsAsXYZW(&mOut); + mOut << ")"; + + mOut << " (" << node->getType() << ")"; + mOut << "\n"; + return true; +} + +bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + + switch (node->getOp()) + { + case EOpComma: + mOut << "comma"; + break; + case EOpAssign: + mOut << "move second child to first child"; + break; + case EOpInitialize: + mOut << "initialize first child with second child"; + break; + case EOpAddAssign: + mOut << "add second child into first child"; + break; + case EOpSubAssign: + mOut << "subtract second child into first child"; + break; + case EOpMulAssign: + mOut << "multiply second child into first child"; + break; + case EOpVectorTimesMatrixAssign: + mOut << "matrix mult second child into first child"; + break; + case EOpVectorTimesScalarAssign: + mOut << "vector scale second child into first child"; + break; + case EOpMatrixTimesScalarAssign: + mOut << "matrix scale second child into first child"; + break; + case EOpMatrixTimesMatrixAssign: + mOut << "matrix mult second child into first child"; + break; + case EOpDivAssign: + mOut << "divide second child into first child"; + break; + case EOpIModAssign: + mOut << "modulo second child into first child"; + break; + case EOpBitShiftLeftAssign: + mOut << "bit-wise shift first child left by second child"; + break; + case EOpBitShiftRightAssign: + mOut << "bit-wise shift first child right by second child"; + break; + case EOpBitwiseAndAssign: + mOut << "bit-wise and second child into first child"; + break; + case EOpBitwiseXorAssign: + mOut << "bit-wise xor second child into first child"; + break; + case EOpBitwiseOrAssign: + mOut << "bit-wise or second child into first child"; + break; + + case EOpIndexDirect: + mOut << "direct index"; + break; + case EOpIndexIndirect: + mOut << "indirect index"; + break; + case EOpIndexDirectStruct: + mOut << "direct index for structure"; + break; + case EOpIndexDirectInterfaceBlock: + mOut << "direct index for interface block"; + break; + + case EOpAdd: + mOut << "add"; + break; + case EOpSub: + mOut << "subtract"; + break; + case EOpMul: + mOut << "component-wise multiply"; + break; + case EOpDiv: + mOut << "divide"; + break; + case EOpIMod: + mOut << "modulo"; + break; + case EOpBitShiftLeft: + mOut << "bit-wise shift left"; + break; + case EOpBitShiftRight: + mOut << "bit-wise shift right"; + break; + case EOpBitwiseAnd: + mOut << "bit-wise and"; + break; + case EOpBitwiseXor: + mOut << "bit-wise xor"; + break; + case EOpBitwiseOr: + mOut << "bit-wise or"; + break; + + case EOpEqual: + mOut << "Compare Equal"; + break; + case EOpNotEqual: + mOut << "Compare Not Equal"; + break; + case EOpLessThan: + mOut << "Compare Less Than"; + break; + case EOpGreaterThan: + mOut << "Compare Greater Than"; + break; + case EOpLessThanEqual: + mOut << "Compare Less Than or Equal"; + break; + case EOpGreaterThanEqual: + mOut << "Compare Greater Than or Equal"; + break; + + case EOpVectorTimesScalar: + mOut << "vector-scale"; + break; + case EOpVectorTimesMatrix: + mOut << "vector-times-matrix"; + break; + case EOpMatrixTimesVector: + mOut << "matrix-times-vector"; + break; + case EOpMatrixTimesScalar: + mOut << "matrix-scale"; + break; + case EOpMatrixTimesMatrix: + mOut << "matrix-multiply"; + break; + + case EOpLogicalOr: + mOut << "logical-or"; + break; + case EOpLogicalXor: + mOut << "logical-xor"; + break; + case EOpLogicalAnd: + mOut << "logical-and"; + break; + default: + mOut << ""; + } + + mOut << " (" << node->getType() << ")"; + + mOut << "\n"; + + // Special handling for direct indexes. Because constant + // unions are not aware they are struct indexes, treat them + // here where we have that contextual knowledge. + if (node->getOp() == EOpIndexDirectStruct || node->getOp() == EOpIndexDirectInterfaceBlock) + { + node->getLeft()->traverse(this); + + TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion(); + ASSERT(intermConstantUnion); + + OutputTreeText(mOut, intermConstantUnion, getCurrentIndentDepth() + 1); + + // The following code finds the field name from the constant union + const TConstantUnion *constantUnion = intermConstantUnion->getConstantValue(); + const TStructure *structure = node->getLeft()->getType().getStruct(); + const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock(); + ASSERT(structure || interfaceBlock); + + const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields(); + + const TField *field = fields[constantUnion->getIConst()]; + + mOut << constantUnion->getIConst() << " (field '" << field->name() << "')"; + + mOut << "\n"; + + return false; + } + + return true; +} + +bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + + const TOperator op = node->getOp(); + + switch (op) + { + // Give verbose names for ops that have special syntax and some built-in functions that are + // easy to confuse with others, but mostly use GLSL names for functions. + case EOpNegative: + mOut << "Negate value"; + break; + case EOpPositive: + mOut << "Positive sign"; + break; + case EOpLogicalNot: + mOut << "negation"; + break; + case EOpBitwiseNot: + mOut << "bit-wise not"; + break; + + case EOpPostIncrement: + mOut << "Post-Increment"; + break; + case EOpPostDecrement: + mOut << "Post-Decrement"; + break; + case EOpPreIncrement: + mOut << "Pre-Increment"; + break; + case EOpPreDecrement: + mOut << "Pre-Decrement"; + break; + + case EOpArrayLength: + mOut << "Array length"; + break; + + case EOpNotComponentWise: + mOut << "component-wise not"; + break; + + default: + if (BuiltInGroup::IsBuiltIn(op)) + { + OutputFunction(mOut, "Call a built-in function", node->getFunction()); + } + else + { + mOut << GetOperatorString(node->getOp()); + } + break; + } + + mOut << " (" << node->getType() << ")"; + + mOut << "\n"; + + return true; +} + +bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + mOut << "Function Definition:\n"; + return true; +} + +bool TOutputTraverser::visitGlobalQualifierDeclaration(Visit visit, + TIntermGlobalQualifierDeclaration *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + if (node->isPrecise()) + { + mOut << "Precise Declaration:\n"; + } + else + { + mOut << "Invariant Declaration:\n"; + } + return true; +} + +void TOutputTraverser::visitFunctionPrototype(TIntermFunctionPrototype *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + OutputFunction(mOut, "Function Prototype", node->getFunction()); + mOut << " (" << node->getType() << ")"; + mOut << "\n"; + size_t paramCount = node->getFunction()->getParamCount(); + for (size_t i = 0; i < paramCount; ++i) + { + const TVariable *param = node->getFunction()->getParam(i); + OutputTreeText(mOut, node, getCurrentIndentDepth() + 1); + mOut << "parameter: " << param->name() << " (" << param->getType() << ")\n"; + } +} + +bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + + const TOperator op = node->getOp(); + + if (op == EOpNull) + { + mOut.prefix(SH_ERROR); + mOut << "node is still EOpNull!\n"; + return true; + } + + // Give verbose names for some built-in functions that are easy to confuse with others, but + // mostly use GLSL names for functions. + switch (op) + { + case EOpCallFunctionInAST: + OutputFunction(mOut, "Call a user-defined function", node->getFunction()); + break; + case EOpCallInternalRawFunction: + OutputFunction(mOut, "Call an internal function with raw implementation", + node->getFunction()); + break; + + case EOpConstruct: + // The type of the constructor will be printed below. + mOut << "Construct"; + break; + + case EOpEqualComponentWise: + mOut << "component-wise equal"; + break; + case EOpNotEqualComponentWise: + mOut << "component-wise not equal"; + break; + case EOpLessThanComponentWise: + mOut << "component-wise less than"; + break; + case EOpGreaterThanComponentWise: + mOut << "component-wise greater than"; + break; + case EOpLessThanEqualComponentWise: + mOut << "component-wise less than or equal"; + break; + case EOpGreaterThanEqualComponentWise: + mOut << "component-wise greater than or equal"; + break; + + case EOpDot: + mOut << "dot product"; + break; + case EOpCross: + mOut << "cross product"; + break; + case EOpMatrixCompMult: + mOut << "component-wise multiply"; + break; + + default: + if (BuiltInGroup::IsBuiltIn(op)) + { + OutputFunction(mOut, "Call a built-in function", node->getFunction()); + } + else + { + mOut << GetOperatorString(node->getOp()); + } + break; + } + + mOut << " (" << node->getType() << ")"; + + mOut << "\n"; + + return true; +} + +bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + mOut << "Code block\n"; + + return true; +} + +bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + mOut << "Declaration\n"; + + return true; +} + +bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + + mOut << "Ternary selection"; + mOut << " (" << node->getType() << ")\n"; + + ++mIndentDepth; + + OutputTreeText(mOut, node, getCurrentIndentDepth()); + mOut << "Condition\n"; + node->getCondition()->traverse(this); + + OutputTreeText(mOut, node, getCurrentIndentDepth()); + if (node->getTrueExpression()) + { + mOut << "true case\n"; + node->getTrueExpression()->traverse(this); + } + if (node->getFalseExpression()) + { + OutputTreeText(mOut, node, getCurrentIndentDepth()); + mOut << "false case\n"; + node->getFalseExpression()->traverse(this); + } + + --mIndentDepth; + + return false; +} + +bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + + mOut << "If test\n"; + + ++mIndentDepth; + + OutputTreeText(mOut, node, getCurrentIndentDepth()); + mOut << "Condition\n"; + node->getCondition()->traverse(this); + + OutputTreeText(mOut, node, getCurrentIndentDepth()); + if (node->getTrueBlock()) + { + mOut << "true case\n"; + node->getTrueBlock()->traverse(this); + } + else + { + mOut << "true case is null\n"; + } + + if (node->getFalseBlock()) + { + OutputTreeText(mOut, node, getCurrentIndentDepth()); + mOut << "false case\n"; + node->getFalseBlock()->traverse(this); + } + + --mIndentDepth; + + return false; +} + +bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + + mOut << "Switch\n"; + + return true; +} + +bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + + if (node->getCondition() == nullptr) + { + mOut << "Default\n"; + } + else + { + mOut << "Case\n"; + } + + return true; +} + +void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node) +{ + size_t size = node->getType().getObjectSize(); + + for (size_t i = 0; i < size; i++) + { + OutputTreeText(mOut, node, getCurrentIndentDepth()); + switch (node->getConstantValue()[i].getType()) + { + case EbtBool: + if (node->getConstantValue()[i].getBConst()) + mOut << "true"; + else + mOut << "false"; + + mOut << " (" + << "const bool" + << ")"; + mOut << "\n"; + break; + case EbtFloat: + mOut << node->getConstantValue()[i].getFConst(); + mOut << " (const float)\n"; + break; + case EbtInt: + mOut << node->getConstantValue()[i].getIConst(); + mOut << " (const int)\n"; + break; + case EbtUInt: + mOut << node->getConstantValue()[i].getUConst(); + mOut << " (const uint)\n"; + break; + case EbtYuvCscStandardEXT: + mOut << getYuvCscStandardEXTString( + node->getConstantValue()[i].getYuvCscStandardEXTConst()); + mOut << " (const yuvCscStandardEXT)\n"; + break; + default: + mOut.prefix(SH_ERROR); + mOut << "Unknown constant\n"; + break; + } + } +} + +bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + + mOut << "Loop with condition "; + if (node->getType() == ELoopDoWhile) + mOut << "not "; + mOut << "tested first\n"; + + ++mIndentDepth; + + OutputTreeText(mOut, node, getCurrentIndentDepth()); + if (node->getCondition()) + { + mOut << "Loop Condition\n"; + node->getCondition()->traverse(this); + } + else + { + mOut << "No loop condition\n"; + } + + OutputTreeText(mOut, node, getCurrentIndentDepth()); + if (node->getBody()) + { + mOut << "Loop Body\n"; + node->getBody()->traverse(this); + } + else + { + mOut << "No loop body\n"; + } + + if (node->getExpression()) + { + OutputTreeText(mOut, node, getCurrentIndentDepth()); + mOut << "Loop Terminal Expression\n"; + node->getExpression()->traverse(this); + } + + --mIndentDepth; + + return false; +} + +bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node) +{ + OutputTreeText(mOut, node, getCurrentIndentDepth()); + + switch (node->getFlowOp()) + { + case EOpKill: + mOut << "Branch: Kill"; + break; + case EOpBreak: + mOut << "Branch: Break"; + break; + case EOpContinue: + mOut << "Branch: Continue"; + break; + case EOpReturn: + mOut << "Branch: Return"; + break; + default: + mOut << "Branch: Unknown Branch"; + break; + } + + if (node->getExpression()) + { + mOut << " with expression\n"; + ++mIndentDepth; + node->getExpression()->traverse(this); + --mIndentDepth; + } + else + { + mOut << "\n"; + } + + return false; +} + +} // anonymous namespace + +void OutputTree(TIntermNode *root, TInfoSinkBase &out) +{ + TOutputTraverser it(out); + ASSERT(root); + root->traverse(&it); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/OutputTree.h b/gfx/angle/checkout/src/compiler/translator/OutputTree.h new file mode 100644 index 0000000000..29bca65642 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/OutputTree.h @@ -0,0 +1,22 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Output the AST intermediate representation of the GLSL code. + +#ifndef COMPILER_TRANSLATOR_OUTPUTTREE_H_ +#define COMPILER_TRANSLATOR_OUTPUTTREE_H_ + +namespace sh +{ + +class TIntermNode; +class TInfoSinkBase; + +// Output the AST along with metadata. +void OutputTree(TIntermNode *root, TInfoSinkBase &out); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_OUTPUTTREE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ParseContext.cpp b/gfx/angle/checkout/src/compiler/translator/ParseContext.cpp new file mode 100644 index 0000000000..4312c2c966 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ParseContext.cpp @@ -0,0 +1,7538 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/ParseContext.h" + +#include +#include + +#include "common/mathutil.h" +#include "common/utilities.h" +#include "compiler/preprocessor/SourceLocation.h" +#include "compiler/translator/Declarator.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/ValidateGlobalInitializer.h" +#include "compiler/translator/ValidateSwitch.h" +#include "compiler/translator/glslang.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +/////////////////////////////////////////////////////////////////////// +// +// Sub- vector and matrix fields +// +//////////////////////////////////////////////////////////////////////// + +namespace +{ + +const int kWebGLMaxStructNesting = 4; + +bool ContainsSampler(const TStructure *structType); + +bool ContainsSampler(const TType &type) +{ + if (IsSampler(type.getBasicType())) + { + return true; + } + if (type.getBasicType() == EbtStruct) + { + return ContainsSampler(type.getStruct()); + } + + return false; +} + +bool ContainsSampler(const TStructure *structType) +{ + for (const auto &field : structType->fields()) + { + if (ContainsSampler(*field->type())) + return true; + } + return false; +} + +// Get a token from an image argument to use as an error message token. +const char *GetImageArgumentToken(TIntermTyped *imageNode) +{ + ASSERT(IsImage(imageNode->getBasicType())); + while (imageNode->getAsBinaryNode() && + (imageNode->getAsBinaryNode()->getOp() == EOpIndexIndirect || + imageNode->getAsBinaryNode()->getOp() == EOpIndexDirect)) + { + imageNode = imageNode->getAsBinaryNode()->getLeft(); + } + TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode(); + if (imageSymbol) + { + return imageSymbol->getName().data(); + } + return "image"; +} + +bool CanSetDefaultPrecisionOnType(const TPublicType &type) +{ + if (!SupportsPrecision(type.getBasicType())) + { + return false; + } + if (type.getBasicType() == EbtUInt) + { + // ESSL 3.00.4 section 4.5.4 + return false; + } + if (type.isAggregate()) + { + // Not allowed to set for aggregate types + return false; + } + return true; +} + +// Map input primitive types to input array sizes in a geometry shader. +GLuint GetGeometryShaderInputArraySize(TLayoutPrimitiveType primitiveType) +{ + switch (primitiveType) + { + case EptPoints: + return 1u; + case EptLines: + return 2u; + case EptTriangles: + return 3u; + case EptLinesAdjacency: + return 4u; + case EptTrianglesAdjacency: + return 6u; + default: + UNREACHABLE(); + return 0u; + } +} + +bool IsBufferOrSharedVariable(TIntermTyped *var) +{ + if (var->isInterfaceBlock() || var->getQualifier() == EvqBuffer || + var->getQualifier() == EvqShared) + { + return true; + } + return false; +} + +TIntermTyped *FindLValueBase(TIntermTyped *node) +{ + do + { + const TIntermBinary *binary = node->getAsBinaryNode(); + if (binary == nullptr) + { + return node; + } + + TOperator op = binary->getOp(); + if (op != EOpIndexDirect && op != EOpIndexIndirect) + { + return static_cast(nullptr); + } + + node = binary->getLeft(); + } while (true); +} + +void AddAdvancedBlendEquation(gl::BlendEquationType eq, TLayoutQualifier *qualifier) +{ + qualifier->advancedBlendEquations.set(static_cast(eq)); +} + +constexpr bool IsValidWithPixelLocalStorage(TLayoutImageInternalFormat internalFormat) +{ + switch (internalFormat) + { + case EiifRGBA8: + case EiifRGBA8I: + case EiifRGBA8UI: + case EiifR32F: + case EiifR32UI: + return true; + default: + return false; + } +} +} // namespace + +// This tracks each binding point's current default offset for inheritance of subsequent +// variables using the same binding, and keeps offsets unique and non overlapping. +// See GLSL ES 3.1, section 4.4.6. +class TParseContext::AtomicCounterBindingState +{ + public: + AtomicCounterBindingState() : mDefaultOffset(0) {} + // Inserts a new span and returns -1 if overlapping, else returns the starting offset of + // newly inserted span. + int insertSpan(int start, size_t length) + { + gl::RangeI newSpan(start, start + static_cast(length)); + for (const auto &span : mSpans) + { + if (newSpan.intersects(span)) + { + return -1; + } + } + mSpans.push_back(newSpan); + mDefaultOffset = newSpan.high(); + return start; + } + // Inserts a new span starting from the default offset. + int appendSpan(size_t length) { return insertSpan(mDefaultOffset, length); } + void setDefaultOffset(int offset) { mDefaultOffset = offset; } + + private: + int mDefaultOffset; + std::vector mSpans; +}; + +TParseContext::TParseContext(TSymbolTable &symt, + TExtensionBehavior &ext, + sh::GLenum type, + ShShaderSpec spec, + const ShCompileOptions &options, + bool checksPrecErrors, + TDiagnostics *diagnostics, + const ShBuiltInResources &resources, + ShShaderOutput outputType) + : symbolTable(symt), + mDeferredNonEmptyDeclarationErrorCheck(false), + mShaderType(type), + mShaderSpec(spec), + mCompileOptions(options), + mShaderVersion(100), + mTreeRoot(nullptr), + mLoopNestingLevel(0), + mStructNestingLevel(0), + mSwitchNestingLevel(0), + mCurrentFunctionType(nullptr), + mFunctionReturnsValue(false), + mChecksPrecisionErrors(checksPrecErrors), + mFragmentPrecisionHighOnESSL1(false), + mEarlyFragmentTestsSpecified(false), + mHasDiscard(false), + mSampleQualifierSpecified(false), + mDefaultUniformMatrixPacking(EmpColumnMajor), + mDefaultUniformBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared), + mDefaultBufferMatrixPacking(EmpColumnMajor), + mDefaultBufferBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared), + mDiagnostics(diagnostics), + mDirectiveHandler(ext, *mDiagnostics, mShaderVersion, mShaderType), + mPreprocessor(mDiagnostics, &mDirectiveHandler, angle::pp::PreprocessorSettings(spec)), + mScanner(nullptr), + mMinProgramTexelOffset(resources.MinProgramTexelOffset), + mMaxProgramTexelOffset(resources.MaxProgramTexelOffset), + mMinProgramTextureGatherOffset(resources.MinProgramTextureGatherOffset), + mMaxProgramTextureGatherOffset(resources.MaxProgramTextureGatherOffset), + mComputeShaderLocalSizeDeclared(false), + mComputeShaderLocalSize(-1), + mNumViews(-1), + mMaxNumViews(resources.MaxViewsOVR), + mMaxImageUnits(resources.MaxImageUnits), + mMaxCombinedTextureImageUnits(resources.MaxCombinedTextureImageUnits), + mMaxUniformLocations(resources.MaxUniformLocations), + mMaxUniformBufferBindings(resources.MaxUniformBufferBindings), + mMaxVertexAttribs(resources.MaxVertexAttribs), + mMaxAtomicCounterBindings(resources.MaxAtomicCounterBindings), + mMaxShaderStorageBufferBindings(resources.MaxShaderStorageBufferBindings), + mDeclaringFunction(false), + mGeometryShaderInputPrimitiveType(EptUndefined), + mGeometryShaderOutputPrimitiveType(EptUndefined), + mGeometryShaderInvocations(0), + mGeometryShaderMaxVertices(-1), + mMaxGeometryShaderInvocations(resources.MaxGeometryShaderInvocations), + mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices), + mGeometryInputArraySize(0), + mMaxPatchVertices(resources.MaxPatchVertices), + mTessControlShaderOutputVertices(0), + mTessEvaluationShaderInputPrimitiveType(EtetUndefined), + mTessEvaluationShaderInputVertexSpacingType(EtetUndefined), + mTessEvaluationShaderInputOrderingType(EtetUndefined), + mTessEvaluationShaderInputPointType(EtetUndefined), + mHasAnyPreciseType(false), + mAdvancedBlendEquations(0), + mFunctionBodyNewScope(false), + mOutputType(outputType) +{} + +TParseContext::~TParseContext() {} + +bool TParseContext::anyMultiviewExtensionAvailable() +{ + return isExtensionEnabled(TExtension::OVR_multiview) || + isExtensionEnabled(TExtension::OVR_multiview2); +} + +bool TParseContext::parseVectorFields(const TSourceLoc &line, + const ImmutableString &compString, + int vecSize, + TVector *fieldOffsets) +{ + ASSERT(fieldOffsets); + size_t fieldCount = compString.length(); + if (fieldCount > 4u) + { + error(line, "illegal vector field selection", compString); + return false; + } + fieldOffsets->resize(fieldCount); + + enum + { + exyzw, + ergba, + estpq + } fieldSet[4]; + + for (unsigned int i = 0u; i < fieldOffsets->size(); ++i) + { + switch (compString[i]) + { + case 'x': + (*fieldOffsets)[i] = 0; + fieldSet[i] = exyzw; + break; + case 'r': + (*fieldOffsets)[i] = 0; + fieldSet[i] = ergba; + break; + case 's': + (*fieldOffsets)[i] = 0; + fieldSet[i] = estpq; + break; + case 'y': + (*fieldOffsets)[i] = 1; + fieldSet[i] = exyzw; + break; + case 'g': + (*fieldOffsets)[i] = 1; + fieldSet[i] = ergba; + break; + case 't': + (*fieldOffsets)[i] = 1; + fieldSet[i] = estpq; + break; + case 'z': + (*fieldOffsets)[i] = 2; + fieldSet[i] = exyzw; + break; + case 'b': + (*fieldOffsets)[i] = 2; + fieldSet[i] = ergba; + break; + case 'p': + (*fieldOffsets)[i] = 2; + fieldSet[i] = estpq; + break; + + case 'w': + (*fieldOffsets)[i] = 3; + fieldSet[i] = exyzw; + break; + case 'a': + (*fieldOffsets)[i] = 3; + fieldSet[i] = ergba; + break; + case 'q': + (*fieldOffsets)[i] = 3; + fieldSet[i] = estpq; + break; + default: + error(line, "illegal vector field selection", compString); + return false; + } + } + + for (unsigned int i = 0u; i < fieldOffsets->size(); ++i) + { + if ((*fieldOffsets)[i] >= vecSize) + { + error(line, "vector field selection out of range", compString); + return false; + } + + if (i > 0) + { + if (fieldSet[i] != fieldSet[i - 1]) + { + error(line, "illegal - vector component fields not from the same set", compString); + return false; + } + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////// +// +// Errors +// +//////////////////////////////////////////////////////////////////////// + +// +// Used by flex/bison to output all syntax and parsing errors. +// +void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token) +{ + mDiagnostics->error(loc, reason, token); +} + +void TParseContext::error(const TSourceLoc &loc, const char *reason, const ImmutableString &token) +{ + mDiagnostics->error(loc, reason, token.data()); +} + +void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token) +{ + mDiagnostics->warning(loc, reason, token); +} + +void TParseContext::errorIfPLSDeclared(const TSourceLoc &loc, PLSIllegalOperations op) +{ + if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage)) + { + return; + } + if (mPLSBindings.empty()) + { + // No pixel local storage uniforms have been declared yet. Remember this potential error in + // case PLS gets declared later. + mPLSPotentialErrors.emplace_back(loc, op); + return; + } + switch (op) + { + case PLSIllegalOperations::Discard: + error(loc, "illegal discard when pixel local storage is declared", "discard"); + break; + case PLSIllegalOperations::ReturnFromMain: + error(loc, "illegal return from main when pixel local storage is declared", "return"); + break; + case PLSIllegalOperations::AssignFragDepth: + error(loc, "value not assignable when pixel local storage is declared", "gl_FragDepth"); + break; + case PLSIllegalOperations::AssignSampleMask: + error(loc, "value not assignable when pixel local storage is declared", + "gl_SampleMask"); + break; + } +} + +void TParseContext::outOfRangeError(bool isError, + const TSourceLoc &loc, + const char *reason, + const char *token) +{ + if (isError) + { + error(loc, reason, token); + } + else + { + warning(loc, reason, token); + } +} + +void TParseContext::setTreeRoot(TIntermBlock *treeRoot) +{ + mTreeRoot = treeRoot; + mTreeRoot->setIsTreeRoot(); +} + +// +// Same error message for all places assignments don't work. +// +void TParseContext::assignError(const TSourceLoc &line, + const char *op, + const TType &left, + const TType &right) +{ + TInfoSinkBase reasonStream; + reasonStream << "cannot convert from '" << right << "' to '" << left << "'"; + error(line, reasonStream.c_str(), op); +} + +// +// Same error message for all places unary operations don't work. +// +void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, const TType &operand) +{ + TInfoSinkBase reasonStream; + reasonStream << "wrong operand type - no operation '" << op + << "' exists that takes an operand of type " << operand + << " (or there is no acceptable conversion)"; + error(line, reasonStream.c_str(), op); +} + +// +// Same error message for all binary operations don't work. +// +void TParseContext::binaryOpError(const TSourceLoc &line, + const char *op, + const TType &left, + const TType &right) +{ + TInfoSinkBase reasonStream; + reasonStream << "wrong operand types - no operation '" << op + << "' exists that takes a left-hand operand of type '" << left + << "' and a right operand of type '" << right + << "' (or there is no acceptable conversion)"; + error(line, reasonStream.c_str(), op); +} + +void TParseContext::checkPrecisionSpecified(const TSourceLoc &line, + TPrecision precision, + TBasicType type) +{ + if (!mChecksPrecisionErrors) + return; + + if (precision != EbpUndefined && !SupportsPrecision(type)) + { + error(line, "illegal type for precision qualifier", getBasicString(type)); + } + + if (precision == EbpUndefined) + { + switch (type) + { + case EbtFloat: + error(line, "No precision specified for (float)", ""); + return; + case EbtInt: + case EbtUInt: + UNREACHABLE(); // there's always a predeclared qualifier + error(line, "No precision specified (int)", ""); + return; + default: + if (IsOpaqueType(type)) + { + error(line, "No precision specified", getBasicString(type)); + return; + } + } + } +} + +void TParseContext::markStaticReadIfSymbol(TIntermNode *node) +{ + TIntermSwizzle *swizzleNode = node->getAsSwizzleNode(); + if (swizzleNode) + { + markStaticReadIfSymbol(swizzleNode->getOperand()); + return; + } + TIntermBinary *binaryNode = node->getAsBinaryNode(); + if (binaryNode) + { + switch (binaryNode->getOp()) + { + case EOpIndexDirect: + case EOpIndexIndirect: + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: + markStaticReadIfSymbol(binaryNode->getLeft()); + return; + default: + return; + } + } + TIntermSymbol *symbolNode = node->getAsSymbolNode(); + if (symbolNode) + { + symbolTable.markStaticRead(symbolNode->variable()); + } +} + +// Both test and if necessary, spit out an error, to see if the node is really +// an l-value that can be operated on this way. +bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node) +{ + TIntermSwizzle *swizzleNode = node->getAsSwizzleNode(); + if (swizzleNode) + { + bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand()); + if (ok && swizzleNode->hasDuplicateOffsets()) + { + error(line, " l-value of swizzle cannot have duplicate components", op); + return false; + } + return ok; + } + + TIntermBinary *binaryNode = node->getAsBinaryNode(); + if (binaryNode) + { + switch (binaryNode->getOp()) + { + case EOpIndexDirect: + case EOpIndexIndirect: + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: + if (node->getMemoryQualifier().readonly) + { + error(line, "can't modify a readonly variable", op); + return false; + } + return checkCanBeLValue(line, op, binaryNode->getLeft()); + default: + break; + } + error(line, " l-value required", op); + return false; + } + + std::string message; + switch (node->getQualifier()) + { + case EvqConst: + message = "can't modify a const"; + break; + case EvqParamConst: + message = "can't modify a const"; + break; + case EvqAttribute: + message = "can't modify an attribute"; + break; + case EvqFragmentIn: + case EvqVertexIn: + case EvqGeometryIn: + case EvqTessControlIn: + case EvqTessEvaluationIn: + case EvqFlatIn: + case EvqNoPerspectiveIn: + case EvqSmoothIn: + case EvqCentroidIn: + case EvqSampleIn: + message = "can't modify an input"; + break; + case EvqUniform: + message = "can't modify a uniform"; + break; + case EvqVaryingIn: + message = "can't modify a varying"; + break; + case EvqFragCoord: + message = "can't modify gl_FragCoord"; + break; + case EvqFrontFacing: + message = "can't modify gl_FrontFacing"; + break; + case EvqHelperInvocation: + message = "can't modify gl_HelperInvocation"; + break; + case EvqPointCoord: + message = "can't modify gl_PointCoord"; + break; + case EvqNumWorkGroups: + message = "can't modify gl_NumWorkGroups"; + break; + case EvqWorkGroupSize: + message = "can't modify gl_WorkGroupSize"; + break; + case EvqWorkGroupID: + message = "can't modify gl_WorkGroupID"; + break; + case EvqLocalInvocationID: + message = "can't modify gl_LocalInvocationID"; + break; + case EvqGlobalInvocationID: + message = "can't modify gl_GlobalInvocationID"; + break; + case EvqLocalInvocationIndex: + message = "can't modify gl_LocalInvocationIndex"; + break; + case EvqViewIDOVR: + message = "can't modify gl_ViewID_OVR"; + break; + case EvqComputeIn: + message = "can't modify work group size variable"; + break; + case EvqPerVertexIn: + message = "can't modify any member in gl_in"; + break; + case EvqPrimitiveIDIn: + message = "can't modify gl_PrimitiveIDIn"; + break; + case EvqInvocationID: + message = "can't modify gl_InvocationID"; + break; + case EvqPrimitiveID: + if (mShaderType == GL_FRAGMENT_SHADER) + { + message = "can't modify gl_PrimitiveID in a fragment shader"; + } + break; + case EvqLayerIn: + message = "can't modify gl_Layer in a fragment shader"; + break; + case EvqSampleID: + message = "can't modify gl_SampleID"; + break; + case EvqSampleMaskIn: + message = "can't modify gl_SampleMaskIn"; + break; + case EvqSamplePosition: + message = "can't modify gl_SamplePosition"; + break; + case EvqClipDistance: + if (mShaderType == GL_FRAGMENT_SHADER) + { + message = "can't modify gl_ClipDistance in a fragment shader"; + } + break; + case EvqCullDistance: + if (mShaderType == GL_FRAGMENT_SHADER) + { + message = "can't modify gl_CullDistance in a fragment shader"; + } + break; + case EvqFragDepth: + errorIfPLSDeclared(line, PLSIllegalOperations::AssignFragDepth); + break; + case EvqSampleMask: + errorIfPLSDeclared(line, PLSIllegalOperations::AssignSampleMask); + break; + default: + // + // Type that can't be written to? + // + if (node->getBasicType() == EbtVoid) + { + message = "can't modify void"; + } + if (IsOpaqueType(node->getBasicType())) + { + message = "can't modify a variable with type "; + message += getBasicString(node->getBasicType()); + } + else if (node->getMemoryQualifier().readonly) + { + message = "can't modify a readonly variable"; + } + } + + ASSERT(binaryNode == nullptr && swizzleNode == nullptr); + TIntermSymbol *symNode = node->getAsSymbolNode(); + if (message.empty() && symNode != nullptr) + { + symbolTable.markStaticWrite(symNode->variable()); + return true; + } + + std::stringstream reasonStream = sh::InitializeStream(); + reasonStream << "l-value required"; + if (!message.empty()) + { + if (symNode) + { + // Symbol inside an expression can't be nameless. + ASSERT(symNode->variable().symbolType() != SymbolType::Empty); + const ImmutableString &symbol = symNode->getName(); + reasonStream << " (" << message << " \"" << symbol << "\")"; + } + else + { + reasonStream << " (" << message << ")"; + } + } + std::string reason = reasonStream.str(); + error(line, reason.c_str(), op); + + return false; +} + +// Both test, and if necessary spit out an error, to see if the node is really +// a constant. +void TParseContext::checkIsConst(TIntermTyped *node) +{ + if (node->getQualifier() != EvqConst) + { + error(node->getLine(), "constant expression required", ""); + } +} + +// Both test, and if necessary spit out an error, to see if the node is really +// an integer. +void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token) +{ + if (!node->isScalarInt()) + { + error(node->getLine(), "integer expression required", token); + } +} + +// Both test, and if necessary spit out an error, to see if we are currently +// globally scoped. +bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token) +{ + if (!symbolTable.atGlobalLevel()) + { + error(line, "only allowed at global scope", token); + return false; + } + return true; +} + +// ESSL 3.00.5 sections 3.8 and 3.9. +// If it starts "gl_" or contains two consecutive underscores, it's reserved. +// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a webgl shader. +bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const ImmutableString &identifier) +{ + static const char *reservedErrMsg = "reserved built-in name"; + if (gl::IsBuiltInName(identifier.data())) + { + error(line, reservedErrMsg, "gl_"); + return false; + } + if (sh::IsWebGLBasedSpec(mShaderSpec)) + { + if (identifier.beginsWith("webgl_")) + { + error(line, reservedErrMsg, "webgl_"); + return false; + } + if (identifier.beginsWith("_webgl_")) + { + error(line, reservedErrMsg, "_webgl_"); + return false; + } + } + if (identifier.contains("__")) + { + if (sh::IsWebGLBasedSpec(mShaderSpec)) + { + error(line, + "identifiers containing two consecutive underscores (__) are reserved as " + "possible future keywords", + identifier); + return false; + } + else + { + // Using double underscores is allowed, but may result in unintended behaviors, so a + // warning is issued. + // OpenGL ES Shader Language 3.2 specification: + // > 3.7. Keywords + // > ... + // > In addition, all identifiers containing two consecutive underscores (__) are + // > reserved for use by underlying software layers. Defining such a name in a shader + // > does not itself result in an error, but may result in unintended behaviors that + // > stem from having multiple definitions of the same name. + warning(line, + "all identifiers containing two consecutive underscores (__) are reserved - " + "unintented behaviors are possible", + identifier.data()); + } + } + return true; +} + +// Make sure the argument types are correct for constructing a specific type. +bool TParseContext::checkConstructorArguments(const TSourceLoc &line, + const TIntermSequence &arguments, + const TType &type) +{ + if (arguments.empty()) + { + error(line, "constructor does not have any arguments", "constructor"); + return false; + } + + for (TIntermNode *arg : arguments) + { + markStaticReadIfSymbol(arg); + const TIntermTyped *argTyped = arg->getAsTyped(); + ASSERT(argTyped != nullptr); + if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType())) + { + std::string reason("cannot convert a variable with type "); + reason += getBasicString(argTyped->getBasicType()); + error(line, reason.c_str(), "constructor"); + return false; + } + else if (argTyped->getMemoryQualifier().writeonly) + { + error(line, "cannot convert a variable with writeonly", "constructor"); + return false; + } + if (argTyped->getBasicType() == EbtVoid) + { + error(line, "cannot convert a void", "constructor"); + return false; + } + } + + if (type.isArray()) + { + // The size of an unsized constructor should already have been determined. + ASSERT(!type.isUnsizedArray()); + if (static_cast(type.getOutermostArraySize()) != arguments.size()) + { + error(line, "array constructor needs one argument per array element", "constructor"); + return false; + } + // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of + // the array. + for (TIntermNode *const &argNode : arguments) + { + const TType &argType = argNode->getAsTyped()->getType(); + if (mShaderVersion < 310 && argType.isArray()) + { + error(line, "constructing from a non-dereferenced array", "constructor"); + return false; + } + if (!argType.isElementTypeOf(type)) + { + error(line, "Array constructor argument has an incorrect type", "constructor"); + return false; + } + } + } + else if (type.getBasicType() == EbtStruct) + { + const TFieldList &fields = type.getStruct()->fields(); + if (fields.size() != arguments.size()) + { + error(line, + "Number of constructor parameters does not match the number of structure fields", + "constructor"); + return false; + } + + for (size_t i = 0; i < fields.size(); i++) + { + if (i >= arguments.size() || + arguments[i]->getAsTyped()->getType() != *fields[i]->type()) + { + error(line, "Structure constructor arguments do not match structure fields", + "constructor"); + return false; + } + } + } + else + { + // We're constructing a scalar, vector, or matrix. + + // Note: It's okay to have too many components available, but not okay to have unused + // arguments. 'full' will go to true when enough args have been seen. If we loop again, + // there is an extra argument, so 'overFull' will become true. + + size_t size = 0; + bool full = false; + bool overFull = false; + bool matrixArg = false; + for (TIntermNode *arg : arguments) + { + const TIntermTyped *argTyped = arg->getAsTyped(); + ASSERT(argTyped != nullptr); + + if (argTyped->getBasicType() == EbtStruct) + { + error(line, "a struct cannot be used as a constructor argument for this type", + "constructor"); + return false; + } + if (argTyped->getType().isArray()) + { + error(line, "constructing from a non-dereferenced array", "constructor"); + return false; + } + if (argTyped->getType().isMatrix()) + { + matrixArg = true; + } + + size += argTyped->getType().getObjectSize(); + if (full) + { + overFull = true; + } + if (size >= type.getObjectSize()) + { + full = true; + } + } + + if (type.isMatrix() && matrixArg) + { + if (arguments.size() != 1) + { + error(line, "constructing matrix from matrix can only take one argument", + "constructor"); + return false; + } + } + else + { + if (size != 1 && size < type.getObjectSize()) + { + error(line, "not enough data provided for construction", "constructor"); + return false; + } + if (overFull) + { + error(line, "too many arguments", "constructor"); + return false; + } + } + } + + return true; +} + +// This function checks to see if a void variable has been declared and raise an error message for +// such a case +// +// returns true in case of an error +// +bool TParseContext::checkIsNonVoid(const TSourceLoc &line, + const ImmutableString &identifier, + const TBasicType &type) +{ + if (type == EbtVoid) + { + error(line, "illegal use of type 'void'", identifier); + return false; + } + + return true; +} + +// This function checks to see if the node (for the expression) contains a scalar boolean expression +// or not. +bool TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type) +{ + if (type->getBasicType() != EbtBool || !type->isScalar()) + { + error(line, "boolean expression expected", ""); + return false; + } + return true; +} + +// This function checks to see if the node (for the expression) contains a scalar boolean expression +// or not. +void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType) +{ + if (pType.getBasicType() != EbtBool || pType.isAggregate()) + { + error(line, "boolean expression expected", ""); + } +} + +bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line, + const TTypeSpecifierNonArray &pType, + const char *reason) +{ + if (pType.type == EbtStruct) + { + if (ContainsSampler(pType.userDef)) + { + std::stringstream reasonStream = sh::InitializeStream(); + reasonStream << reason << " (structure contains a sampler)"; + std::string reasonStr = reasonStream.str(); + error(line, reasonStr.c_str(), getBasicString(pType.type)); + return false; + } + // only samplers need to be checked from structs, since other opaque types can't be struct + // members. + return true; + } + else if (IsOpaqueType(pType.type)) + { + error(line, reason, getBasicString(pType.type)); + return false; + } + + return true; +} + +void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line, + const TPublicType &pType) +{ + if (pType.layoutQualifier.location != -1) + { + error(line, "location must only be specified for a single input or output variable", + "location"); + } +} + +void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location, + const TLayoutQualifier &layoutQualifier) +{ + if (layoutQualifier.location != -1) + { + const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs"; + if (mShaderVersion >= 310) + { + errorMsg = + "invalid layout qualifier: only valid on shader inputs, outputs, and uniforms"; + } + error(location, errorMsg, "location"); + } +} + +void TParseContext::checkStd430IsForShaderStorageBlock(const TSourceLoc &location, + const TLayoutBlockStorage &blockStorage, + const TQualifier &qualifier) +{ + if (blockStorage == EbsStd430 && qualifier != EvqBuffer) + { + error(location, "The std430 layout is supported only for shader storage blocks.", "std430"); + } +} + +void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line, + TQualifier qualifier, + const TType &type) +{ + ASSERT(qualifier == EvqParamOut || qualifier == EvqParamInOut); + if (IsOpaqueType(type.getBasicType())) + { + error(line, "opaque types cannot be output parameters", type.getBasicString()); + } +} + +// Do size checking for an array type's size. +unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr) +{ + TIntermConstantUnion *constant = expr->getAsConstantUnion(); + + // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be + // safe against corner cases we still check for constant folding. Some interpretations of the + // spec have allowed constant expressions with side effects - like array length() method on a + // non-constant array. + if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt()) + { + error(line, "array size must be a constant integer expression", ""); + return 1u; + } + + unsigned int size = 0u; + + if (constant->getBasicType() == EbtUInt) + { + size = constant->getUConst(0); + } + else + { + int signedSize = constant->getIConst(0); + + if (signedSize < 0) + { + error(line, "array size must be non-negative", ""); + return 1u; + } + + size = static_cast(signedSize); + } + + if (size == 0u) + { + error(line, "array size must be greater than zero", ""); + return 1u; + } + + if (IsOutputHLSL(getOutputType())) + { + // The size of arrays is restricted here to prevent issues further down the + // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to + // 4096 registers so this should be reasonable even for aggressively optimizable code. + const unsigned int sizeLimit = 65536; + + if (size > sizeLimit) + { + error(line, "array size too large", ""); + return 1u; + } + } + + return size; +} + +// See if this qualifier can be an array. +bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line, + const TPublicType &elementQualifier) +{ + if ((elementQualifier.qualifier == EvqAttribute) || + (elementQualifier.qualifier == EvqVertexIn) || + (elementQualifier.qualifier == EvqConst && mShaderVersion < 300)) + { + error(line, "cannot declare arrays of this qualifier", + TType(elementQualifier).getQualifierString()); + return false; + } + + return true; +} + +// See if this element type can be formed into an array. +bool TParseContext::checkArrayElementIsNotArray(const TSourceLoc &line, + const TPublicType &elementType) +{ + if (mShaderVersion < 310 && elementType.isArray()) + { + TInfoSinkBase typeString; + typeString << TType(elementType); + error(line, "cannot declare arrays of arrays", typeString.c_str()); + return false; + } + return true; +} + +// Check for array-of-arrays being used as non-allowed shader inputs/outputs. +bool TParseContext::checkArrayOfArraysInOut(const TSourceLoc &line, + const TPublicType &elementType, + const TType &arrayType) +{ + if (arrayType.isArrayOfArrays()) + { + if (elementType.qualifier == EvqVertexOut) + { + error(line, "vertex shader output cannot be an array of arrays", + TType(elementType).getQualifierString()); + return false; + } + if (elementType.qualifier == EvqFragmentIn) + { + error(line, "fragment shader input cannot be an array of arrays", + TType(elementType).getQualifierString()); + return false; + } + if (elementType.qualifier == EvqFragmentOut || elementType.qualifier == EvqFragmentInOut) + { + error(line, "fragment shader output cannot be an array of arrays", + TType(elementType).getQualifierString()); + return false; + } + } + return true; +} + +// Check if this qualified element type can be formed into an array. This is only called when array +// brackets are associated with an identifier in a declaration, like this: +// float a[2]; +// Similar checks are done in addFullySpecifiedType for array declarations where the array brackets +// are associated with the type, like this: +// float[2] a; +bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation, + const TPublicType &elementType) +{ + if (!checkArrayElementIsNotArray(indexLocation, elementType)) + { + return false; + } + // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere. + // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section + // 4.3.4). + // Geometry shader requires each user-defined input be declared as arrays or inside input + // blocks declared as arrays (GL_EXT_geometry_shader section 11.1gs.4.3). For the purposes of + // interface matching, such variables and blocks are treated as though they were not declared + // as arrays (GL_EXT_geometry_shader section 7.4.1). + if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct && + sh::IsVarying(elementType.qualifier) && + !IsGeometryShaderInput(mShaderType, elementType.qualifier) && + !IsTessellationControlShaderInput(mShaderType, elementType.qualifier) && + !IsTessellationEvaluationShaderInput(mShaderType, elementType.qualifier) && + !IsTessellationControlShaderOutput(mShaderType, elementType.qualifier)) + { + TInfoSinkBase typeString; + typeString << TType(elementType); + error(indexLocation, "cannot declare arrays of structs of this qualifier", + typeString.c_str()); + return false; + } + return checkIsValidQualifierForArray(indexLocation, elementType); +} + +// Enforce non-initializer type/qualifier rules. +void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line, + const ImmutableString &identifier, + TType *type) +{ + ASSERT(type != nullptr); + if (type->getQualifier() == EvqConst) + { + // Make the qualifier make sense. + type->setQualifier(EvqTemporary); + + // Generate informative error messages for ESSL1. + // In ESSL3 arrays and structures containing arrays can be constant. + if (mShaderVersion < 300 && type->isStructureContainingArrays()) + { + error(line, + "structures containing arrays may not be declared constant since they cannot be " + "initialized", + identifier); + } + else + { + error(line, "variables with qualifier 'const' must be initialized", identifier); + } + } + + // Implicitly declared arrays are only allowed with tessellation or geometry shader inputs + if (type->isArray() && + ((mShaderType != GL_TESS_CONTROL_SHADER && mShaderType != GL_TESS_EVALUATION_SHADER && + mShaderType != GL_GEOMETRY_SHADER) || + (mShaderType == GL_GEOMETRY_SHADER && type->getQualifier() == EvqGeometryOut))) + { + const TSpan &arraySizes = type->getArraySizes(); + for (unsigned int size : arraySizes) + { + if (size == 0) + { + error(line, + "implicitly sized arrays only allowed for tessellation shaders " + "or geometry shader inputs", + identifier); + } + } + } +} + +// Do some simple checks that are shared between all variable declarations, +// and update the symbol table. +// +// Returns true if declaring the variable succeeded. +// +bool TParseContext::declareVariable(const TSourceLoc &line, + const ImmutableString &identifier, + const TType *type, + TVariable **variable) +{ + ASSERT((*variable) == nullptr); + + SymbolType symbolType = SymbolType::UserDefined; + switch (type->getQualifier()) + { + case EvqClipDistance: + case EvqCullDistance: + case EvqLastFragData: + symbolType = SymbolType::BuiltIn; + break; + default: + break; + } + + (*variable) = new TVariable(&symbolTable, identifier, type, symbolType); + + ASSERT(type->getLayoutQualifier().index == -1 || + (isExtensionEnabled(TExtension::EXT_blend_func_extended) && + mShaderType == GL_FRAGMENT_SHADER && mShaderVersion >= 300)); + if (type->getQualifier() == EvqFragmentOut) + { + if (type->getLayoutQualifier().index != -1 && type->getLayoutQualifier().location == -1) + { + error(line, + "If index layout qualifier is specified for a fragment output, location must " + "also be specified.", + "index"); + return false; + } + } + else + { + checkIndexIsNotSpecified(line, type->getLayoutQualifier().index); + } + + if (!((identifier.beginsWith("gl_LastFragData") || type->getQualifier() == EvqFragmentInOut) && + (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) || + isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent)))) + { + checkNoncoherentIsNotSpecified(line, type->getLayoutQualifier().noncoherent); + } + else if (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent) && + !isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch)) + { + checkNoncoherentIsSpecified(line, type->getLayoutQualifier().noncoherent); + } + + checkBindingIsValid(line, *type); + + bool needsReservedCheck = true; + + // gl_LastFragData may be redeclared with a new precision qualifier + if (type->isArray() && identifier.beginsWith("gl_LastFragData")) + { + const TVariable *maxDrawBuffers = static_cast( + symbolTable.findBuiltIn(ImmutableString("gl_MaxDrawBuffers"), mShaderVersion)); + if (type->isArrayOfArrays()) + { + error(line, "redeclaration of gl_LastFragData as an array of arrays", identifier); + return false; + } + else if (static_cast(type->getOutermostArraySize()) == + maxDrawBuffers->getConstPointer()->getIConst()) + { + if (const TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion)) + { + needsReservedCheck = !checkCanUseOneOfExtensions(line, builtInSymbol->extensions()); + } + } + else + { + error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers", + identifier); + return false; + } + } + else if (type->isArray() && identifier == "gl_ClipDistance") + { + // gl_ClipDistance can be redeclared with smaller size than gl_MaxClipDistances + const TVariable *maxClipDistances = static_cast( + symbolTable.findBuiltIn(ImmutableString("gl_MaxClipDistances"), mShaderVersion)); + if (!maxClipDistances) + { + // Unsupported extension + needsReservedCheck = true; + } + else if (type->isArrayOfArrays()) + { + error(line, "redeclaration of gl_ClipDistance as an array of arrays", identifier); + return false; + } + else if (static_cast(type->getOutermostArraySize()) <= + maxClipDistances->getConstPointer()->getIConst()) + { + const TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion); + if (builtInSymbol) + { + needsReservedCheck = !checkCanUseOneOfExtensions(line, builtInSymbol->extensions()); + } + } + else + { + error(line, "redeclaration of gl_ClipDistance with size > gl_MaxClipDistances", + identifier); + return false; + } + } + else if (type->isArray() && identifier == "gl_CullDistance") + { + // gl_CullDistance can be redeclared with smaller size than gl_MaxCullDistances + const TVariable *maxCullDistances = static_cast( + symbolTable.findBuiltIn(ImmutableString("gl_MaxCullDistances"), mShaderVersion)); + if (!maxCullDistances) + { + // Unsupported extension + needsReservedCheck = true; + } + else if (type->isArrayOfArrays()) + { + error(line, "redeclaration of gl_CullDistance as an array of arrays", identifier); + return false; + } + else if (static_cast(type->getOutermostArraySize()) <= + maxCullDistances->getConstPointer()->getIConst()) + { + if (const TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion)) + { + needsReservedCheck = !checkCanUseOneOfExtensions(line, builtInSymbol->extensions()); + } + } + else + { + error(line, "redeclaration of gl_CullDistance with size > gl_MaxCullDistances", + identifier); + return false; + } + } + + if (needsReservedCheck && !checkIsNotReserved(line, identifier)) + return false; + + if (!symbolTable.declare(*variable)) + { + error(line, "redefinition", identifier); + return false; + } + + if (!checkIsNonVoid(line, identifier, type->getBasicType())) + return false; + + return true; +} + +void TParseContext::checkIsParameterQualifierValid( + const TSourceLoc &line, + const TTypeQualifierBuilder &typeQualifierBuilder, + TType *type) +{ + // The only parameter qualifiers a parameter can have are in, out, inout or const. + TTypeQualifier typeQualifier = + typeQualifierBuilder.getParameterTypeQualifier(type->getBasicType(), mDiagnostics); + + if (typeQualifier.qualifier == EvqParamOut || typeQualifier.qualifier == EvqParamInOut) + { + checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type); + } + + if (!IsImage(type->getBasicType())) + { + checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line); + } + else + { + type->setMemoryQualifier(typeQualifier.memoryQualifier); + } + + type->setQualifier(typeQualifier.qualifier); + + if (typeQualifier.precision != EbpUndefined) + { + type->setPrecision(typeQualifier.precision); + } + + if (typeQualifier.precise) + { + type->setPrecise(true); + } +} + +template +bool TParseContext::checkCanUseOneOfExtensions(const TSourceLoc &line, + const std::array &extensions) +{ + ASSERT(!extensions.empty()); + const TExtensionBehavior &extBehavior = extensionBehavior(); + + bool canUseWithWarning = false; + bool canUseWithoutWarning = false; + + const char *errorMsgString = ""; + TExtension errorMsgExtension = TExtension::UNDEFINED; + + for (TExtension extension : extensions) + { + auto extIter = extBehavior.find(extension); + if (canUseWithWarning) + { + // We already have an extension that we can use, but with a warning. + // See if we can use the alternative extension without a warning. + if (extIter == extBehavior.end()) + { + continue; + } + if (extIter->second == EBhEnable || extIter->second == EBhRequire) + { + canUseWithoutWarning = true; + break; + } + continue; + } + if (extension == TExtension::UNDEFINED) + { + continue; + } + else if (extIter == extBehavior.end()) + { + errorMsgString = "extension is not supported"; + errorMsgExtension = extension; + } + else if (extIter->second == EBhUndefined || extIter->second == EBhDisable) + { + errorMsgString = "extension is disabled"; + errorMsgExtension = extension; + } + else if (extIter->second == EBhWarn) + { + errorMsgExtension = extension; + canUseWithWarning = true; + } + else + { + ASSERT(extIter->second == EBhEnable || extIter->second == EBhRequire); + canUseWithoutWarning = true; + break; + } + } + + if (canUseWithoutWarning) + { + return true; + } + if (canUseWithWarning) + { + warning(line, "extension is being used", GetExtensionNameString(errorMsgExtension)); + return true; + } + error(line, errorMsgString, GetExtensionNameString(errorMsgExtension)); + return false; +} + +template bool TParseContext::checkCanUseOneOfExtensions( + const TSourceLoc &line, + const std::array &extensions); +template bool TParseContext::checkCanUseOneOfExtensions( + const TSourceLoc &line, + const std::array &extensions); +template bool TParseContext::checkCanUseOneOfExtensions( + const TSourceLoc &line, + const std::array &extensions); + +bool TParseContext::checkCanUseExtension(const TSourceLoc &line, TExtension extension) +{ + ASSERT(extension != TExtension::UNDEFINED); + return checkCanUseOneOfExtensions(line, std::array{{extension}}); +} + +// ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause +// compile-time or link-time errors are the same whether or not the declaration is empty". +// This function implements all the checks that are done on qualifiers regardless of if the +// declaration is empty. +void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier, + const sh::TLayoutQualifier &layoutQualifier, + const TSourceLoc &location) +{ + if (qualifier == EvqShared && !layoutQualifier.isEmpty()) + { + error(location, "Shared memory declarations cannot have layout specified", "layout"); + } + + if (layoutQualifier.matrixPacking != EmpUnspecified) + { + error(location, "layout qualifier only valid for interface blocks", + getMatrixPackingString(layoutQualifier.matrixPacking)); + return; + } + + if (layoutQualifier.blockStorage != EbsUnspecified) + { + error(location, "layout qualifier only valid for interface blocks", + getBlockStorageString(layoutQualifier.blockStorage)); + return; + } + + if (qualifier == EvqFragmentOut) + { + if (layoutQualifier.location != -1 && layoutQualifier.yuv == true) + { + error(location, "invalid layout qualifier combination", "yuv"); + return; + } + } + else + { + checkYuvIsNotSpecified(location, layoutQualifier.yuv); + } + + if (qualifier != EvqFragmentIn) + { + checkEarlyFragmentTestsIsNotSpecified(location, layoutQualifier.earlyFragmentTests); + } + + // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous + // parsing steps. So it needs to be checked here. + if (anyMultiviewExtensionAvailable() && mShaderVersion < 300 && qualifier == EvqVertexIn) + { + error(location, "storage qualifier supported in GLSL ES 3.00 and above only", "in"); + } + + bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut; + if (mShaderVersion >= 300 && + (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) || + isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent))) + { + // In the case of EXT_shader_framebuffer_fetch or EXT_shader_framebuffer_fetch_non_coherent + // extension, the location of inout qualifier is used to set the input attachment index + canHaveLocation = canHaveLocation || qualifier == EvqFragmentInOut; + } + if (mShaderVersion >= 310) + { + canHaveLocation = canHaveLocation || qualifier == EvqUniform || IsVarying(qualifier); + // We're not checking whether the uniform location is in range here since that depends on + // the type of the variable. + // The type can only be fully determined for non-empty declarations. + } + if (!canHaveLocation) + { + checkLocationIsNotSpecified(location, layoutQualifier); + } +} + +void TParseContext::atomicCounterQualifierErrorCheck(const TPublicType &publicType, + const TSourceLoc &location) +{ + if (publicType.precision != EbpHigh) + { + error(location, "Can only be highp", "atomic counter"); + } + // dEQP enforces compile error if location is specified. See uniform_location.test. + if (publicType.layoutQualifier.location != -1) + { + error(location, "location must not be set for atomic_uint", "layout"); + } + if (publicType.layoutQualifier.binding == -1) + { + error(location, "no binding specified", "atomic counter"); + } +} + +void TParseContext::emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location) +{ + if (type.isUnsizedArray()) + { + // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an + // error. It is assumed that this applies to empty declarations as well. + error(location, "empty array declaration needs to specify a size", ""); + } + + if (type.getQualifier() != EvqFragmentOut) + { + checkIndexIsNotSpecified(location, type.getLayoutQualifier().index); + } +} + +// These checks are done for all declarations that are non-empty. They're done for non-empty +// declarations starting a declarator list, and declarators that follow an empty declaration. +void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType, + const TSourceLoc &identifierLocation) +{ + switch (publicType.qualifier) + { + case EvqVaryingIn: + case EvqVaryingOut: + case EvqAttribute: + case EvqVertexIn: + case EvqFragmentOut: + case EvqFragmentInOut: + case EvqComputeIn: + if (publicType.getBasicType() == EbtStruct) + { + error(identifierLocation, "cannot be used with a structure", + getQualifierString(publicType.qualifier)); + return; + } + break; + case EvqBuffer: + if (publicType.getBasicType() != EbtInterfaceBlock) + { + error(identifierLocation, + "cannot declare buffer variables at global scope(outside a block)", + getQualifierString(publicType.qualifier)); + return; + } + break; + default: + break; + } + std::string reason(getBasicString(publicType.getBasicType())); + reason += "s must be uniform"; + if (publicType.qualifier != EvqUniform && + !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str())) + { + return; + } + + if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal && + publicType.qualifier != EvqConst) && + publicType.getBasicType() == EbtYuvCscStandardEXT) + { + error(identifierLocation, "cannot be used with a yuvCscStandardEXT", + getQualifierString(publicType.qualifier)); + return; + } + + if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform) + { + // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized. + // But invalid shaders may still reach here with an unsized array declaration. + TType type(publicType); + if (!type.isUnsizedArray()) + { + checkUniformLocationInRange(identifierLocation, type.getLocationCount(), + publicType.layoutQualifier); + } + } + + if (mShaderVersion >= 300 && publicType.qualifier == EvqVertexIn) + { + // Valid vertex input declarations can't be unsized arrays since they can't be initialized. + // But invalid shaders may still reach here with an unsized array declaration. + TType type(publicType); + if (!type.isUnsizedArray()) + { + checkAttributeLocationInRange(identifierLocation, type.getLocationCount(), + publicType.layoutQualifier); + } + } + + // check for layout qualifier issues + const TLayoutQualifier layoutQualifier = publicType.layoutQualifier; + + if (IsImage(publicType.getBasicType())) + { + + switch (layoutQualifier.imageInternalFormat) + { + case EiifRGBA32F: + case EiifRGBA16F: + case EiifR32F: + case EiifRGBA8: + case EiifRGBA8_SNORM: + if (!IsFloatImage(publicType.getBasicType())) + { + error(identifierLocation, + "internal image format requires a floating image type", + getBasicString(publicType.getBasicType())); + return; + } + break; + case EiifRGBA32I: + case EiifRGBA16I: + case EiifRGBA8I: + case EiifR32I: + if (!IsIntegerImage(publicType.getBasicType())) + { + error(identifierLocation, + "internal image format requires an integer image type", + getBasicString(publicType.getBasicType())); + return; + } + break; + case EiifRGBA32UI: + case EiifRGBA16UI: + case EiifRGBA8UI: + case EiifR32UI: + if (!IsUnsignedImage(publicType.getBasicType())) + { + error(identifierLocation, + "internal image format requires an unsigned image type", + getBasicString(publicType.getBasicType())); + return; + } + break; + case EiifUnspecified: + error(identifierLocation, "layout qualifier", "No image internal format specified"); + return; + default: + error(identifierLocation, "layout qualifier", "unrecognized token"); + return; + } + + // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers + switch (layoutQualifier.imageInternalFormat) + { + case EiifR32F: + case EiifR32I: + case EiifR32UI: + break; + default: + if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly) + { + error(identifierLocation, "layout qualifier", + "Except for images with the r32f, r32i and r32ui format qualifiers, " + "image variables must be qualified readonly and/or writeonly"); + return; + } + break; + } + } + else if (IsPixelLocal(publicType.getBasicType())) + { + if (getShaderType() != GL_FRAGMENT_SHADER) + { + error(identifierLocation, + "undefined use of pixel local storage outside a fragment shader", + getBasicString(publicType.getBasicType())); + return; + } + switch (layoutQualifier.imageInternalFormat) + { + case EiifR32F: + case EiifRGBA8: + if (publicType.getBasicType() != EbtPixelLocalANGLE) + { + error(identifierLocation, "pixel local storage format requires pixelLocalANGLE", + getImageInternalFormatString(layoutQualifier.imageInternalFormat)); + } + break; + case EiifRGBA8I: + if (publicType.getBasicType() != EbtIPixelLocalANGLE) + { + error(identifierLocation, + "pixel local storage format requires ipixelLocalANGLE", + getImageInternalFormatString(layoutQualifier.imageInternalFormat)); + } + break; + case EiifR32UI: + case EiifRGBA8UI: + if (publicType.getBasicType() != EbtUPixelLocalANGLE) + { + error(identifierLocation, + "pixel local storage format requires upixelLocalANGLE", + getImageInternalFormatString(layoutQualifier.imageInternalFormat)); + } + break; + case EiifR32I: + case EiifRGBA8_SNORM: + case EiifRGBA16F: + case EiifRGBA32F: + case EiifRGBA16I: + case EiifRGBA32I: + case EiifRGBA16UI: + case EiifRGBA32UI: + default: + ASSERT(!IsValidWithPixelLocalStorage(layoutQualifier.imageInternalFormat)); + error(identifierLocation, "illegal pixel local storage format", + getImageInternalFormatString(layoutQualifier.imageInternalFormat)); + break; + case EiifUnspecified: + error(identifierLocation, "pixel local storage requires a format specifier", + "layout qualifier"); + break; + } + checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation); + checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType); + } + else + { + checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat); + checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation); + } + + if (IsAtomicCounter(publicType.getBasicType())) + { + atomicCounterQualifierErrorCheck(publicType, identifierLocation); + } + else + { + checkOffsetIsNotSpecified(identifierLocation, layoutQualifier.offset); + } +} + +void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type) +{ + TLayoutQualifier layoutQualifier = type.getLayoutQualifier(); + // Note that the ESSL 3.10 section 4.4.5 is not particularly clear on how the binding qualifier + // on arrays of arrays should be handled. We interpret the spec so that the binding value is + // incremented for each element of the innermost nested arrays. This is in line with how arrays + // of arrays of blocks are specified to behave in GLSL 4.50 and a conservative interpretation + // when it comes to which shaders are accepted by the compiler. + int arrayTotalElementCount = type.getArraySizeProduct(); + if (IsPixelLocal(type.getBasicType())) + { + checkPixelLocalStorageBindingIsValid(identifierLocation, type); + } + else if (mShaderVersion < 310) + { + checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding); + } + else if (IsImage(type.getBasicType())) + { + checkImageBindingIsValid(identifierLocation, layoutQualifier.binding, + arrayTotalElementCount); + } + else if (IsSampler(type.getBasicType())) + { + checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding, + arrayTotalElementCount); + } + else if (IsAtomicCounter(type.getBasicType())) + { + checkAtomicCounterBindingIsValid(identifierLocation, layoutQualifier.binding); + } + else + { + ASSERT(!IsOpaqueType(type.getBasicType())); + checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding); + } +} + +void TParseContext::checkCanUseLayoutQualifier(const TSourceLoc &location) +{ + constexpr std::array extensions{ + {TExtension::EXT_shader_framebuffer_fetch, + TExtension::EXT_shader_framebuffer_fetch_non_coherent, + TExtension::KHR_blend_equation_advanced, TExtension::ANGLE_shader_pixel_local_storage}}; + if (getShaderVersion() < 300 && !checkCanUseOneOfExtensions(location, extensions)) + { + error(location, "qualifier supported in GLSL ES 3.00 and above only", "layout"); + } +} + +bool TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location, + const ImmutableString &layoutQualifierName, + int versionRequired) +{ + + if (mShaderVersion < versionRequired) + { + error(location, "invalid layout qualifier: not supported", layoutQualifierName); + return false; + } + return true; +} + +bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location, + const TLayoutQualifier &layoutQualifier) +{ + const sh::WorkGroupSize &localSize = layoutQualifier.localSize; + for (size_t i = 0u; i < localSize.size(); ++i) + { + if (localSize[i] != -1) + { + error(location, + "invalid layout qualifier: only valid when used with 'in' in a compute shader " + "global layout declaration", + getWorkGroupSizeString(i)); + return false; + } + } + + return true; +} + +void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location, + TLayoutImageInternalFormat internalFormat) +{ + if (internalFormat != EiifUnspecified) + { + if (mShaderVersion < 310) + { + if (IsValidWithPixelLocalStorage(internalFormat)) + { + error(location, + "invalid layout qualifier: not supported before GLSL ES 3.10, except pixel " + "local storage", + getImageInternalFormatString(internalFormat)); + } + else + { + error(location, "invalid layout qualifier: not supported before GLSL ES 3.10", + getImageInternalFormatString(internalFormat)); + } + } + else + { + if (IsValidWithPixelLocalStorage(internalFormat)) + { + error(location, + "invalid layout qualifier: only valid when used with images or pixel local " + "storage ", + getImageInternalFormatString(internalFormat)); + } + else + { + error(location, "invalid layout qualifier: only valid when used with images", + getImageInternalFormatString(internalFormat)); + } + } + } +} + +void TParseContext::checkIndexIsNotSpecified(const TSourceLoc &location, int index) +{ + if (index != -1) + { + error(location, + "invalid layout qualifier: only valid when used with a fragment shader output in " + "ESSL version >= 3.00 and EXT_blend_func_extended is enabled", + "index"); + } +} + +void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding) +{ + if (binding != -1) + { + if (mShaderVersion < 310) + { + error(location, + "invalid layout qualifier: only valid when used with pixel local storage", + "binding"); + } + else + { + error(location, + "invalid layout qualifier: only valid when used with opaque types or blocks", + "binding"); + } + } +} + +void TParseContext::checkOffsetIsNotSpecified(const TSourceLoc &location, int offset) +{ + if (offset != -1) + { + error(location, "invalid layout qualifier: only valid when used with atomic counters", + "offset"); + } +} + +void TParseContext::checkImageBindingIsValid(const TSourceLoc &location, + int binding, + int arrayTotalElementCount) +{ + // Expects arraySize to be 1 when setting binding for only a single variable. + if (binding >= 0 && binding + arrayTotalElementCount > mMaxImageUnits) + { + error(location, "image binding greater than gl_MaxImageUnits", "binding"); + } +} + +void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location, + int binding, + int arrayTotalElementCount) +{ + // Expects arraySize to be 1 when setting binding for only a single variable. + if (binding >= 0 && binding + arrayTotalElementCount > mMaxCombinedTextureImageUnits) + { + error(location, "sampler binding greater than maximum texture units", "binding"); + } +} + +void TParseContext::checkBlockBindingIsValid(const TSourceLoc &location, + const TQualifier &qualifier, + int binding, + int arraySize) +{ + int size = (arraySize == 0 ? 1 : arraySize); + if (qualifier == EvqUniform) + { + if (binding + size > mMaxUniformBufferBindings) + { + error(location, "uniform block binding greater than MAX_UNIFORM_BUFFER_BINDINGS", + "binding"); + } + } + else if (qualifier == EvqBuffer) + { + if (binding + size > mMaxShaderStorageBufferBindings) + { + error(location, + "shader storage block binding greater than MAX_SHADER_STORAGE_BUFFER_BINDINGS", + "binding"); + } + } +} +void TParseContext::checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding) +{ + if (binding >= mMaxAtomicCounterBindings) + { + error(location, "atomic counter binding greater than gl_MaxAtomicCounterBindings", + "binding"); + } +} + +void TParseContext::checkPixelLocalStorageBindingIsValid(const TSourceLoc &location, + const TType &type) +{ + TLayoutQualifier layoutQualifier = type.getLayoutQualifier(); + if (type.isArray()) + { + // PLS is not allowed in arrays. + // TODO(anglebug.com/7279): Consider allowing this once more backends are implemented. + error(location, "pixel local storage handles cannot be aggregated in arrays", "array"); + } + else if (layoutQualifier.binding < 0) + { + error(location, "pixel local storage requires a binding index", "layout qualifier"); + } + // TODO(anglebug.com/7279): + // else if (binding >= GL_MAX_LOCAL_STORAGE_PLANES_ANGLE) + // { + // } + else if (mPLSBindings.find(layoutQualifier.binding) != mPLSBindings.end()) + { + error(location, "duplicate pixel local storage binding index", + std::to_string(layoutQualifier.binding).c_str()); + } + else + { + mPLSBindings[layoutQualifier.binding] = layoutQualifier.imageInternalFormat; + // "mPLSBindings" is how we know whether pixel local storage uniforms have been declared, so + // flush the queue of potential errors once mPLSBindings isn't empty. + if (!mPLSPotentialErrors.empty()) + { + for (const auto &[loc, op] : mPLSPotentialErrors) + { + errorIfPLSDeclared(loc, op); + } + mPLSPotentialErrors.clear(); + } + } +} + +void TParseContext::checkUniformLocationInRange(const TSourceLoc &location, + int objectLocationCount, + const TLayoutQualifier &layoutQualifier) +{ + int loc = layoutQualifier.location; + if (loc >= 0) // Shader-specified location + { + if (loc >= mMaxUniformLocations || objectLocationCount > mMaxUniformLocations || + static_cast(loc) + static_cast(objectLocationCount) > + static_cast(mMaxUniformLocations)) + { + error(location, "Uniform location out of range", "location"); + } + } +} + +void TParseContext::checkAttributeLocationInRange(const TSourceLoc &location, + int objectLocationCount, + const TLayoutQualifier &layoutQualifier) +{ + int loc = layoutQualifier.location; + if (loc >= 0) // Shader-specified location + { + if (loc >= mMaxVertexAttribs || objectLocationCount > mMaxVertexAttribs || + static_cast(loc) + static_cast(objectLocationCount) > + static_cast(mMaxVertexAttribs)) + { + error(location, "Attribute location out of range", "location"); + } + } +} + +void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv) +{ + if (yuv != false) + { + error(location, "invalid layout qualifier: only valid on program outputs", "yuv"); + } +} + +void TParseContext::checkEarlyFragmentTestsIsNotSpecified(const TSourceLoc &location, + bool earlyFragmentTests) +{ + if (earlyFragmentTests != false) + { + error(location, + "invalid layout qualifier: only valid when used with 'in' in a fragment shader", + "early_fragment_tests"); + } +} + +void TParseContext::checkNoncoherentIsSpecified(const TSourceLoc &location, bool noncoherent) +{ + if (noncoherent == false) + { + error(location, + "'noncoherent' qualifier must be used when " + "GL_EXT_shader_framebuffer_fetch_non_coherent extension is used", + "noncoherent"); + } +} + +void TParseContext::checkNoncoherentIsNotSpecified(const TSourceLoc &location, bool noncoherent) +{ + if (noncoherent != false) + { + error(location, + "invalid layout qualifier: only valid when used with 'gl_LastFragData' or the " + "variable decorated with 'inout' in a fragment shader", + "noncoherent"); + } +} + +void TParseContext::checkTCSOutVarIndexIsValid(TIntermBinary *binaryExpression, + const TSourceLoc &location) +{ + ASSERT(binaryExpression->getOp() == EOpIndexIndirect || + binaryExpression->getOp() == EOpIndexDirect); + const TIntermSymbol *intermSymbol = binaryExpression->getRight()->getAsSymbolNode(); + if ((intermSymbol == nullptr) || (intermSymbol->getName() != "gl_InvocationID")) + { + error(location, + "tessellation-control per-vertex output l-value must be indexed with " + "gl_InvocationID", + "["); + } +} + +void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandidate, + TIntermAggregate *fnCall) +{ + for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) + { + TQualifier qual = fnCandidate->getParam(i)->getType().getQualifier(); + TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped(); + bool argumentIsRead = (IsQualifierUnspecified(qual) || qual == EvqParamIn || + qual == EvqParamInOut || qual == EvqParamConst); + if (argumentIsRead) + { + markStaticReadIfSymbol(argument); + if (!IsImage(argument->getBasicType())) + { + if (argument->getMemoryQualifier().writeonly) + { + error(argument->getLine(), + "Writeonly value cannot be passed for 'in' or 'inout' parameters.", + fnCall->functionName()); + return; + } + } + } + if (qual == EvqParamOut || qual == EvqParamInOut) + { + if (!checkCanBeLValue(argument->getLine(), "assign", argument)) + { + error(argument->getLine(), + "Constant value cannot be passed for 'out' or 'inout' parameters.", + fnCall->functionName()); + return; + } + } + } +} + +void TParseContext::checkInvariantVariableQualifier(bool invariant, + const TQualifier qualifier, + const TSourceLoc &invariantLocation) +{ + if (!invariant) + return; + + if (mShaderVersion < 300) + { + // input variables in the fragment shader can be also qualified as invariant + if (!sh::CanBeInvariantESSL1(qualifier)) + { + error(invariantLocation, "Cannot be qualified as invariant.", "invariant"); + } + } + else + { + if (!sh::CanBeInvariantESSL3OrGreater(qualifier)) + { + error(invariantLocation, "Cannot be qualified as invariant.", "invariant"); + } + } +} + +void TParseContext::checkAdvancedBlendEquationsNotSpecified( + const TSourceLoc &location, + const AdvancedBlendEquations &advancedBlendEquations, + const TQualifier &qualifier) +{ + if (advancedBlendEquations.any() && qualifier != EvqFragmentOut) + { + error(location, + "invalid layout qualifier: blending equation qualifiers are only permitted on the " + "fragment 'out' qualifier ", + "blend_support_qualifier"); + } +} + +bool TParseContext::isExtensionEnabled(TExtension extension) const +{ + return IsExtensionEnabled(extensionBehavior(), extension); +} + +void TParseContext::handleExtensionDirective(const TSourceLoc &loc, + const char *extName, + const char *behavior) +{ + angle::pp::SourceLocation srcLoc; + srcLoc.file = loc.first_file; + srcLoc.line = loc.first_line; + mDirectiveHandler.handleExtension(srcLoc, extName, behavior); +} + +void TParseContext::handlePragmaDirective(const TSourceLoc &loc, + const char *name, + const char *value, + bool stdgl) +{ + angle::pp::SourceLocation srcLoc; + srcLoc.file = loc.first_file; + srcLoc.line = loc.first_line; + mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl); +} + +sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const +{ + sh::WorkGroupSize result(-1); + for (size_t i = 0u; i < result.size(); ++i) + { + if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1) + { + result[i] = 1; + } + else + { + result[i] = mComputeShaderLocalSize[i]; + } + } + return result; +} + +TIntermConstantUnion *TParseContext::addScalarLiteral(const TConstantUnion *constantUnion, + const TSourceLoc &line) +{ + TIntermConstantUnion *node = new TIntermConstantUnion( + constantUnion, TType(constantUnion->getType(), EbpUndefined, EvqConst)); + node->setLine(line); + return node; +} + +///////////////////////////////////////////////////////////////////////////////// +// +// Non-Errors. +// +///////////////////////////////////////////////////////////////////////////////// + +const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location, + const ImmutableString &name, + const TSymbol *symbol) +{ + if (!symbol) + { + error(location, "undeclared identifier", name); + return nullptr; + } + + if (!symbol->isVariable()) + { + error(location, "variable expected", name); + return nullptr; + } + + const TVariable *variable = static_cast(symbol); + + if (!variable->extensions().empty() && variable->extensions()[0] != TExtension::UNDEFINED) + { + checkCanUseOneOfExtensions(location, variable->extensions()); + } + + // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables + if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared && + variable->getType().getQualifier() == EvqWorkGroupSize) + { + error(location, + "It is an error to use gl_WorkGroupSize before declaring the local group size", + "gl_WorkGroupSize"); + } + + // If EXT_shader_framebuffer_fetch_non_coherent is used, gl_LastFragData should be decorated + // with 'layout(noncoherent)' EXT_shader_framebuffer_fetch_non_coherent spec: "Unless the + // GL_EXT_shader_framebuffer_fetch extension has been enabled in addition, it's an error to use + // gl_LastFragData if it hasn't been explicitly redeclared with layout(noncoherent)." + if (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent) && + !isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) && + variable->getType().getQualifier() == EvqLastFragData) + { + checkNoncoherentIsSpecified(location, variable->getType().getLayoutQualifier().noncoherent); + } + return variable; +} + +TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location, + const ImmutableString &name, + const TSymbol *symbol) +{ + const TVariable *variable = getNamedVariable(location, name, symbol); + + if (!variable) + { + TIntermTyped *node = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); + node->setLine(location); + return node; + } + + const TType &variableType = variable->getType(); + TIntermTyped *node = nullptr; + + if (variable->getConstPointer() && variableType.canReplaceWithConstantUnion()) + { + const TConstantUnion *constArray = variable->getConstPointer(); + node = new TIntermConstantUnion(constArray, variableType); + } + else if (variableType.getQualifier() == EvqWorkGroupSize && mComputeShaderLocalSizeDeclared) + { + // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it + // needs to be added to the AST as a constant and not as a symbol. + sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize(); + TConstantUnion *constArray = new TConstantUnion[3]; + for (size_t i = 0; i < 3; ++i) + { + constArray[i].setUConst(static_cast(workGroupSize[i])); + } + + ASSERT(variableType.getBasicType() == EbtUInt); + ASSERT(variableType.getObjectSize() == 3); + + TType type(variableType); + type.setQualifier(EvqConst); + node = new TIntermConstantUnion(constArray, type); + } + else if ((mGeometryShaderInputPrimitiveType != EptUndefined) && + (variableType.getQualifier() == EvqPerVertexIn)) + { + ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr); + node = new TIntermSymbol(symbolTable.getGlInVariableWithArraySize()); + } + else + { + node = new TIntermSymbol(variable); + } + ASSERT(node != nullptr); + node->setLine(location); + return node; +} + +void TParseContext::adjustRedeclaredBuiltInType(const ImmutableString &identifier, TType *type) +{ + if (identifier == "gl_ClipDistance") + { + type->setQualifier(EvqClipDistance); + } + else if (identifier == "gl_CullDistance") + { + type->setQualifier(EvqCullDistance); + } + else if (identifier == "gl_LastFragData") + { + type->setQualifier(EvqLastFragData); + } +} + +// Initializers show up in several places in the grammar. Have one set of +// code to handle them here. +// +// Returns true on success. +bool TParseContext::executeInitializer(const TSourceLoc &line, + const ImmutableString &identifier, + TType *type, + TIntermTyped *initializer, + TIntermBinary **initNode) +{ + ASSERT(initNode != nullptr); + ASSERT(*initNode == nullptr); + + if (type->isUnsizedArray()) + { + // In case initializer is not an array or type has more dimensions than initializer, this + // will default to setting array sizes to 1. We have not checked yet whether the initializer + // actually is an array or not. Having a non-array initializer for an unsized array will + // result in an error later, so we don't generate an error message here. + type->sizeUnsizedArrays(initializer->getType().getArraySizes()); + } + + const TQualifier qualifier = type->getQualifier(); + + bool constError = false; + if (qualifier == EvqConst) + { + if (EvqConst != initializer->getType().getQualifier()) + { + TInfoSinkBase reasonStream; + reasonStream << "assigning non-constant to '" << *type << "'"; + error(line, reasonStream.c_str(), "="); + + // We're still going to declare the variable to avoid extra error messages. + type->setQualifier(EvqTemporary); + constError = true; + } + } + + TVariable *variable = nullptr; + if (!declareVariable(line, identifier, type, &variable)) + { + return false; + } + + if (constError) + { + return false; + } + + bool nonConstGlobalInitializers = + IsExtensionEnabled(mDirectiveHandler.extensionBehavior(), + TExtension::EXT_shader_non_constant_global_initializers); + bool globalInitWarning = false; + if (symbolTable.atGlobalLevel() && + !ValidateGlobalInitializer(initializer, mShaderVersion, sh::IsWebGLBasedSpec(mShaderSpec), + nonConstGlobalInitializers, &globalInitWarning)) + { + // Error message does not completely match behavior with ESSL 1.00, but + // we want to steer developers towards only using constant expressions. + error(line, "global variable initializers must be constant expressions", "="); + return false; + } + if (globalInitWarning) + { + warning( + line, + "global variable initializers should be constant expressions " + "(uniforms and globals are allowed in global initializers for legacy compatibility)", + "="); + } + + // identifier must be of type constant, a global, or a temporary + if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) + { + error(line, " cannot initialize this type of qualifier ", + variable->getType().getQualifierString()); + return false; + } + + TIntermSymbol *intermSymbol = new TIntermSymbol(variable); + intermSymbol->setLine(line); + + if (!binaryOpCommonCheck(EOpInitialize, intermSymbol, initializer, line)) + { + assignError(line, "=", variable->getType(), initializer->getType()); + return false; + } + + if (qualifier == EvqConst) + { + // Save the constant folded value to the variable if possible. + const TConstantUnion *constArray = initializer->getConstantValue(); + if (constArray) + { + variable->shareConstPointer(constArray); + if (initializer->getType().canReplaceWithConstantUnion()) + { + ASSERT(*initNode == nullptr); + return true; + } + } + } + + *initNode = new TIntermBinary(EOpInitialize, intermSymbol, initializer); + markStaticReadIfSymbol(initializer); + (*initNode)->setLine(line); + return true; +} + +TIntermNode *TParseContext::addConditionInitializer(const TPublicType &pType, + const ImmutableString &identifier, + TIntermTyped *initializer, + const TSourceLoc &loc) +{ + checkIsScalarBool(loc, pType); + TIntermBinary *initNode = nullptr; + TType *type = new TType(pType); + if (executeInitializer(loc, identifier, type, initializer, &initNode)) + { + // The initializer is valid. The init condition needs to have a node - either the + // initializer node, or a constant node in case the initialized variable is const and won't + // be recorded in the AST. + if (initNode == nullptr) + { + return initializer; + } + else + { + TIntermDeclaration *declaration = new TIntermDeclaration(); + declaration->appendDeclarator(initNode); + return declaration; + } + } + return nullptr; +} + +TIntermNode *TParseContext::addLoop(TLoopType type, + TIntermNode *init, + TIntermNode *cond, + TIntermTyped *expr, + TIntermNode *body, + const TSourceLoc &line) +{ + TIntermNode *node = nullptr; + TIntermTyped *typedCond = nullptr; + if (cond) + { + markStaticReadIfSymbol(cond); + typedCond = cond->getAsTyped(); + } + if (expr) + { + markStaticReadIfSymbol(expr); + } + // In case the loop body was not parsed as a block and contains a statement that simply refers + // to a variable, we need to mark it as statically used. + if (body) + { + markStaticReadIfSymbol(body); + } + if (cond == nullptr || typedCond) + { + if (type == ELoopDoWhile && typedCond) + { + checkIsScalarBool(line, typedCond); + } + // In the case of other loops, it was checked before that the condition is a scalar boolean. + ASSERT(mDiagnostics->numErrors() > 0 || typedCond == nullptr || + (typedCond->getBasicType() == EbtBool && !typedCond->isArray() && + !typedCond->isVector())); + + node = new TIntermLoop(type, init, typedCond, expr, EnsureBlock(body)); + node->setLine(line); + return node; + } + + ASSERT(type != ELoopDoWhile); + + TIntermDeclaration *declaration = cond->getAsDeclarationNode(); + ASSERT(declaration); + TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode(); + ASSERT(declarator->getLeft()->getAsSymbolNode()); + + // The condition is a declaration. In the AST representation we don't support declarations as + // loop conditions. Wrap the loop to a block that declares the condition variable and contains + // the loop. + TIntermBlock *block = new TIntermBlock(); + + TIntermDeclaration *declareCondition = new TIntermDeclaration(); + declareCondition->appendDeclarator(declarator->getLeft()->deepCopy()); + block->appendStatement(declareCondition); + + TIntermBinary *conditionInit = new TIntermBinary(EOpAssign, declarator->getLeft()->deepCopy(), + declarator->getRight()->deepCopy()); + TIntermLoop *loop = new TIntermLoop(type, init, conditionInit, expr, EnsureBlock(body)); + block->appendStatement(loop); + loop->setLine(line); + block->setLine(line); + return block; +} + +TIntermNode *TParseContext::addIfElse(TIntermTyped *cond, + TIntermNodePair code, + const TSourceLoc &loc) +{ + bool isScalarBool = checkIsScalarBool(loc, cond); + // In case the conditional statements were not parsed as blocks and contain a statement that + // simply refers to a variable, we need to mark them as statically used. + if (code.node1) + { + markStaticReadIfSymbol(code.node1); + } + if (code.node2) + { + markStaticReadIfSymbol(code.node2); + } + + // For compile time constant conditions, prune the code now. + if (isScalarBool && cond->getAsConstantUnion()) + { + if (cond->getAsConstantUnion()->getBConst(0) == true) + { + return EnsureBlock(code.node1); + } + else + { + return EnsureBlock(code.node2); + } + } + + TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2)); + markStaticReadIfSymbol(cond); + node->setLine(loc); + + return node; +} + +void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier) +{ + checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision, + typeSpecifier->getBasicType()); + + if (mShaderVersion < 300 && typeSpecifier->isArray()) + { + error(typeSpecifier->getLine(), "not supported", "first-class array"); + typeSpecifier->clearArrayness(); + } +} + +TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder, + const TPublicType &typeSpecifier) +{ + TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); + + TPublicType returnType = typeSpecifier; + returnType.qualifier = typeQualifier.qualifier; + returnType.invariant = typeQualifier.invariant; + returnType.precise = typeQualifier.precise; + returnType.layoutQualifier = typeQualifier.layoutQualifier; + returnType.memoryQualifier = typeQualifier.memoryQualifier; + returnType.precision = typeSpecifier.precision; + + if (typeQualifier.precision != EbpUndefined) + { + returnType.precision = typeQualifier.precision; + } + + checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision, + typeSpecifier.getBasicType()); + + checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier, + typeSpecifier.getLine()); + + checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier); + + checkEarlyFragmentTestsIsNotSpecified(typeSpecifier.getLine(), + returnType.layoutQualifier.earlyFragmentTests); + + if (returnType.qualifier == EvqSampleIn || returnType.qualifier == EvqSampleOut) + { + mSampleQualifierSpecified = true; + } + + if (mShaderVersion < 300) + { + if (typeSpecifier.isArray()) + { + error(typeSpecifier.getLine(), "not supported", "first-class array"); + returnType.clearArrayness(); + } + + if (returnType.qualifier == EvqAttribute && + (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt)) + { + error(typeSpecifier.getLine(), "cannot be bool or int", + getQualifierString(returnType.qualifier)); + } + + if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) && + (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt)) + { + error(typeSpecifier.getLine(), "cannot be bool or int", + getQualifierString(returnType.qualifier)); + } + } + else + { + if (!returnType.layoutQualifier.isEmpty()) + { + checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout"); + } + if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn || + returnType.qualifier == EvqFragmentOut || returnType.qualifier == EvqFragmentInOut) + { + checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier, + typeSpecifier.getLine()); + } + if (returnType.qualifier == EvqComputeIn) + { + error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size", + "in"); + } + } + + return returnType; +} + +void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier, + const TPublicType &type, + const TSourceLoc &qualifierLocation) +{ + // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere. + if (type.getBasicType() == EbtBool) + { + error(qualifierLocation, "cannot be bool", getQualifierString(qualifier)); + } + + // Specific restrictions apply for vertex shader inputs and fragment shader outputs. + switch (qualifier) + { + case EvqVertexIn: + // ESSL 3.00 section 4.3.4 + if (type.isArray()) + { + error(qualifierLocation, "cannot be array", getQualifierString(qualifier)); + } + // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck + return; + case EvqFragmentOut: + case EvqFragmentInOut: + // ESSL 3.00 section 4.3.6 + if (type.typeSpecifierNonArray.isMatrix()) + { + error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier)); + } + // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck + return; + default: + break; + } + + // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of + // restrictions. + bool typeContainsIntegers = + (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt || + type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt)); + bool extendedShaderTypes = mShaderVersion >= 320 || + isExtensionEnabled(TExtension::EXT_geometry_shader) || + isExtensionEnabled(TExtension::OES_geometry_shader) || + isExtensionEnabled(TExtension::EXT_tessellation_shader); + if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut && + (!extendedShaderTypes || mShaderType == GL_FRAGMENT_SHADER)) + { + error(qualifierLocation, "must use 'flat' interpolation here", + getQualifierString(qualifier)); + } + + if (type.getBasicType() == EbtStruct) + { + // ESSL 3.00 sections 4.3.4 and 4.3.6. + // These restrictions are only implied by the ESSL 3.00 spec, but + // the ESSL 3.10 spec lists these restrictions explicitly. + if (type.isArray()) + { + error(qualifierLocation, "cannot be an array of structures", + getQualifierString(qualifier)); + } + if (type.isStructureContainingArrays()) + { + error(qualifierLocation, "cannot be a structure containing an array", + getQualifierString(qualifier)); + } + if (type.isStructureContainingType(EbtStruct)) + { + error(qualifierLocation, "cannot be a structure containing a structure", + getQualifierString(qualifier)); + } + if (type.isStructureContainingType(EbtBool)) + { + error(qualifierLocation, "cannot be a structure containing a bool", + getQualifierString(qualifier)); + } + } +} + +void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier) +{ + if (qualifier.getType() == QtStorage) + { + const TStorageQualifierWrapper &storageQualifier = + static_cast(qualifier); + if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst && + !symbolTable.atGlobalLevel()) + { + error(storageQualifier.getLine(), + "Local variables can only use the const storage qualifier.", + storageQualifier.getQualifierString()); + } + } +} + +void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier, + const TSourceLoc &location) +{ + const std::string reason( + "Only allowed with shader storage blocks, variables declared within shader storage blocks " + "and variables declared as image types."); + if (memoryQualifier.readonly) + { + error(location, reason.c_str(), "readonly"); + } + if (memoryQualifier.writeonly) + { + error(location, reason.c_str(), "writeonly"); + } + if (memoryQualifier.coherent) + { + error(location, reason.c_str(), "coherent"); + } + if (memoryQualifier.restrictQualifier) + { + error(location, reason.c_str(), "restrict"); + } + if (memoryQualifier.volatileQualifier) + { + error(location, reason.c_str(), "volatile"); + } +} + +// Make sure there is no offset overlapping, and store the newly assigned offset to "type" in +// intermediate tree. +void TParseContext::checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend, + const TSourceLoc &loc, + TType *type) +{ + const size_t size = type->isArray() ? kAtomicCounterArrayStride * type->getArraySizeProduct() + : kAtomicCounterSize; + TLayoutQualifier layoutQualifier = type->getLayoutQualifier(); + auto &bindingState = mAtomicCounterBindingStates[layoutQualifier.binding]; + int offset; + if (layoutQualifier.offset == -1 || forceAppend) + { + offset = bindingState.appendSpan(size); + } + else + { + offset = bindingState.insertSpan(layoutQualifier.offset, size); + } + if (offset == -1) + { + error(loc, "Offset overlapping", "atomic counter"); + return; + } + layoutQualifier.offset = offset; + type->setLayoutQualifier(layoutQualifier); +} + +void TParseContext::checkAtomicCounterOffsetAlignment(const TSourceLoc &location, const TType &type) +{ + TLayoutQualifier layoutQualifier = type.getLayoutQualifier(); + + // OpenGL ES 3.1 Table 6.5, Atomic counter offset must be a multiple of 4 + if (layoutQualifier.offset % 4 != 0) + { + error(location, "Offset must be multiple of 4", "atomic counter"); + } +} + +void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location, + const ImmutableString &token, + TType *type) +{ + if (IsGeometryShaderInput(mShaderType, type->getQualifier())) + { + if (type->isArray() && type->getOutermostArraySize() == 0u) + { + // Set size for the unsized geometry shader inputs if they are declared after a valid + // input primitive declaration. + if (mGeometryShaderInputPrimitiveType != EptUndefined) + { + ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr); + type->sizeOutermostUnsizedArray( + symbolTable.getGlInVariableWithArraySize()->getType().getOutermostArraySize()); + } + else + { + // [GLSL ES 3.2 SPEC Chapter 4.4.1.2] + // An input can be declared without an array size if there is a previous layout + // which specifies the size. + warning(location, + "Missing a valid input primitive declaration before declaring an unsized " + "array input", + "Deferred"); + mDeferredArrayTypesToSize.push_back(type); + } + } + else if (type->isArray()) + { + setGeometryShaderInputArraySize(type->getOutermostArraySize(), location); + } + else + { + error(location, "Geometry shader input variable must be declared as an array", token); + } + } +} + +void TParseContext::checkTessellationShaderUnsizedArraysAndSetSize(const TSourceLoc &location, + const ImmutableString &token, + TType *type) +{ + TQualifier qualifier = type->getQualifier(); + if (!IsTessellationControlShaderOutput(mShaderType, qualifier) && + !IsTessellationControlShaderInput(mShaderType, qualifier) && + !IsTessellationEvaluationShaderInput(mShaderType, qualifier)) + { + return; + } + + // Such variables must be declared as arrays or inside output blocks declared as arrays. + if (!type->isArray()) + { + error(location, "Tessellation interface variables must be declared as an array", token); + return; + } + + // If a size is specified, it must match the maximum patch size. + unsigned int outermostSize = type->getOutermostArraySize(); + if (outermostSize == 0u) + { + switch (qualifier) + { + case EvqTessControlIn: + case EvqTessEvaluationIn: + case EvqFlatIn: + case EvqCentroidIn: + case EvqSmoothIn: + case EvqSampleIn: + // Declaring an array size is optional. If no size is specified, it will be taken + // from the implementation-dependent maximum patch size (gl_MaxPatchVertices). + ASSERT(mMaxPatchVertices > 0); + type->sizeOutermostUnsizedArray(mMaxPatchVertices); + break; + case EvqTessControlOut: + case EvqFlatOut: + case EvqCentroidOut: + case EvqSmoothOut: + case EvqSampleOut: + // Declaring an array size is optional. If no size is specified, it will be taken + // from output patch size declared in the shader. If the patch size is not yet + // declared, this is deferred until such time as it does. + if (mTessControlShaderOutputVertices == 0) + { + mDeferredArrayTypesToSize.push_back(type); + } + else + { + type->sizeOutermostUnsizedArray(mTessControlShaderOutputVertices); + } + break; + default: + UNREACHABLE(); + break; + } + return; + } + + if (IsTessellationControlShaderInput(mShaderType, qualifier) || + IsTessellationEvaluationShaderInput(mShaderType, qualifier)) + { + if (outermostSize != static_cast(mMaxPatchVertices)) + { + error(location, + "If a size is specified for a tessellation control or evaluation user-defined " + "input variable, it must match the maximum patch size (gl_MaxPatchVertices).", + token); + } + } + else if (IsTessellationControlShaderOutput(mShaderType, qualifier)) + { + if (outermostSize != static_cast(mTessControlShaderOutputVertices) && + mTessControlShaderOutputVertices != 0) + { + error(location, + "If a size is specified for a tessellation control user-defined per-vertex " + "output variable, it must match the the number of vertices in the output " + "patch.", + token); + } + } +} + +TIntermDeclaration *TParseContext::parseSingleDeclaration( + TPublicType &publicType, + const TSourceLoc &identifierOrTypeLocation, + const ImmutableString &identifier) +{ + TType *type = new TType(publicType); + if (mCompileOptions.flattenPragmaSTDGLInvariantAll && + mDirectiveHandler.pragma().stdgl.invariantAll) + { + TQualifier qualifier = type->getQualifier(); + + // The directive handler has already taken care of rejecting invalid uses of this pragma + // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all + // affected variable declarations: + // + // 1. Built-in special variables which are inputs to the fragment shader. (These are handled + // elsewhere, in TranslatorGLSL.) + // + // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It + // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but + // the way this is currently implemented we have to enable this compiler option before + // parsing the shader and determining the shading language version it uses. If this were + // implemented as a post-pass, the workaround could be more targeted. + if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut) + { + type->setInvariant(true); + } + } + + checkGeometryShaderInputAndSetArraySize(identifierOrTypeLocation, identifier, type); + checkTessellationShaderUnsizedArraysAndSetSize(identifierOrTypeLocation, identifier, type); + + declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier, + identifierOrTypeLocation); + + bool emptyDeclaration = (identifier == ""); + mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration; + + TIntermSymbol *symbol = nullptr; + if (emptyDeclaration) + { + emptyDeclarationErrorCheck(*type, identifierOrTypeLocation); + // In most cases we don't need to create a symbol node for an empty declaration. + // But if the empty declaration is declaring a struct type, the symbol node will store that. + if (type->getBasicType() == EbtStruct) + { + TVariable *emptyVariable = + new TVariable(&symbolTable, kEmptyImmutableString, type, SymbolType::Empty); + symbol = new TIntermSymbol(emptyVariable); + } + else if (IsAtomicCounter(publicType.getBasicType())) + { + setAtomicCounterBindingDefaultOffset(publicType, identifierOrTypeLocation); + } + } + else + { + nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation); + + checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, type); + + if (IsAtomicCounter(type->getBasicType())) + { + checkAtomicCounterOffsetDoesNotOverlap(false, identifierOrTypeLocation, type); + + checkAtomicCounterOffsetAlignment(identifierOrTypeLocation, *type); + } + + TVariable *variable = nullptr; + if (declareVariable(identifierOrTypeLocation, identifier, type, &variable)) + { + symbol = new TIntermSymbol(variable); + } + } + + TIntermDeclaration *declaration = new TIntermDeclaration(); + declaration->setLine(identifierOrTypeLocation); + if (symbol) + { + symbol->setLine(identifierOrTypeLocation); + declaration->appendDeclarator(symbol); + } + return declaration; +} + +TIntermDeclaration *TParseContext::parseSingleArrayDeclaration( + TPublicType &elementType, + const TSourceLoc &identifierLocation, + const ImmutableString &identifier, + const TSourceLoc &indexLocation, + const TVector &arraySizes) +{ + mDeferredNonEmptyDeclarationErrorCheck = false; + + declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier, + identifierLocation); + + nonEmptyDeclarationErrorCheck(elementType, identifierLocation); + + checkIsValidTypeAndQualifierForArray(indexLocation, elementType); + + TType *arrayType = new TType(elementType); + arrayType->makeArrays(arraySizes); + + checkArrayOfArraysInOut(indexLocation, elementType, *arrayType); + + checkGeometryShaderInputAndSetArraySize(indexLocation, identifier, arrayType); + checkTessellationShaderUnsizedArraysAndSetSize(indexLocation, identifier, arrayType); + + checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, arrayType); + + if (IsAtomicCounter(arrayType->getBasicType())) + { + checkAtomicCounterOffsetDoesNotOverlap(false, identifierLocation, arrayType); + + checkAtomicCounterOffsetAlignment(identifierLocation, *arrayType); + } + + adjustRedeclaredBuiltInType(identifier, arrayType); + + TIntermDeclaration *declaration = new TIntermDeclaration(); + declaration->setLine(identifierLocation); + + TVariable *variable = nullptr; + if (declareVariable(identifierLocation, identifier, arrayType, &variable)) + { + TIntermSymbol *symbol = new TIntermSymbol(variable); + symbol->setLine(identifierLocation); + declaration->appendDeclarator(symbol); + } + + return declaration; +} + +TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType, + const TSourceLoc &identifierLocation, + const ImmutableString &identifier, + const TSourceLoc &initLocation, + TIntermTyped *initializer) +{ + mDeferredNonEmptyDeclarationErrorCheck = false; + + declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier, + identifierLocation); + + nonEmptyDeclarationErrorCheck(publicType, identifierLocation); + + TIntermDeclaration *declaration = new TIntermDeclaration(); + declaration->setLine(identifierLocation); + + TIntermBinary *initNode = nullptr; + TType *type = new TType(publicType); + if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode)) + { + if (initNode) + { + declaration->appendDeclarator(initNode); + } + else if (publicType.isStructSpecifier()) + { + // The initialization got constant folded. If it's a struct, declare the struct anyway. + TVariable *emptyVariable = + new TVariable(&symbolTable, kEmptyImmutableString, type, SymbolType::Empty); + TIntermSymbol *symbol = new TIntermSymbol(emptyVariable); + symbol->setLine(publicType.getLine()); + declaration->appendDeclarator(symbol); + } + } + return declaration; +} + +TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration( + TPublicType &elementType, + const TSourceLoc &identifierLocation, + const ImmutableString &identifier, + const TSourceLoc &indexLocation, + const TVector &arraySizes, + const TSourceLoc &initLocation, + TIntermTyped *initializer) +{ + mDeferredNonEmptyDeclarationErrorCheck = false; + + declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier, + identifierLocation); + + nonEmptyDeclarationErrorCheck(elementType, identifierLocation); + + checkIsValidTypeAndQualifierForArray(indexLocation, elementType); + + TType *arrayType = new TType(elementType); + arrayType->makeArrays(arraySizes); + + TIntermDeclaration *declaration = new TIntermDeclaration(); + declaration->setLine(identifierLocation); + + // initNode will correspond to the whole of "type b[n] = initializer". + TIntermBinary *initNode = nullptr; + if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode)) + { + if (initNode) + { + declaration->appendDeclarator(initNode); + } + } + + return declaration; +} + +TIntermGlobalQualifierDeclaration *TParseContext::parseGlobalQualifierDeclaration( + const TTypeQualifierBuilder &typeQualifierBuilder, + const TSourceLoc &identifierLoc, + const ImmutableString &identifier, + const TSymbol *symbol) +{ + TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); + + if (!typeQualifier.invariant && !typeQualifier.precise) + { + error(identifierLoc, "Expected invariant or precise", identifier); + return nullptr; + } + if (typeQualifier.invariant && !checkIsAtGlobalLevel(identifierLoc, "invariant varying")) + { + return nullptr; + } + if (!symbol) + { + error(identifierLoc, "undeclared identifier declared as invariant or precise", identifier); + return nullptr; + } + if (!IsQualifierUnspecified(typeQualifier.qualifier)) + { + error(identifierLoc, "invariant or precise declaration specifies qualifier", + getQualifierString(typeQualifier.qualifier)); + } + if (typeQualifier.precision != EbpUndefined) + { + error(identifierLoc, "invariant or precise declaration specifies precision", + getPrecisionString(typeQualifier.precision)); + } + if (!typeQualifier.layoutQualifier.isEmpty()) + { + error(identifierLoc, "invariant or precise declaration specifies layout", "'layout'"); + } + + const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); + if (!variable) + { + return nullptr; + } + const TType &type = variable->getType(); + + checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(), + typeQualifier.line); + checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line); + + symbolTable.addInvariantVarying(*variable); + + TIntermSymbol *intermSymbol = new TIntermSymbol(variable); + intermSymbol->setLine(identifierLoc); + + return new TIntermGlobalQualifierDeclaration(intermSymbol, typeQualifier.precise, + identifierLoc); +} + +void TParseContext::parseDeclarator(TPublicType &publicType, + const TSourceLoc &identifierLocation, + const ImmutableString &identifier, + TIntermDeclaration *declarationOut) +{ + // If the declaration starting this declarator list was empty (example: int,), some checks were + // not performed. + if (mDeferredNonEmptyDeclarationErrorCheck) + { + nonEmptyDeclarationErrorCheck(publicType, identifierLocation); + mDeferredNonEmptyDeclarationErrorCheck = false; + } + + checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType); + + TType *type = new TType(publicType); + + checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, type); + checkTessellationShaderUnsizedArraysAndSetSize(identifierLocation, identifier, type); + + checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, type); + + if (IsAtomicCounter(type->getBasicType())) + { + checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, type); + + checkAtomicCounterOffsetAlignment(identifierLocation, *type); + } + + adjustRedeclaredBuiltInType(identifier, type); + + TVariable *variable = nullptr; + if (declareVariable(identifierLocation, identifier, type, &variable)) + { + TIntermSymbol *symbol = new TIntermSymbol(variable); + symbol->setLine(identifierLocation); + declarationOut->appendDeclarator(symbol); + } +} + +void TParseContext::parseArrayDeclarator(TPublicType &elementType, + const TSourceLoc &identifierLocation, + const ImmutableString &identifier, + const TSourceLoc &arrayLocation, + const TVector &arraySizes, + TIntermDeclaration *declarationOut) +{ + // If the declaration starting this declarator list was empty (example: int,), some checks were + // not performed. + if (mDeferredNonEmptyDeclarationErrorCheck) + { + nonEmptyDeclarationErrorCheck(elementType, identifierLocation); + mDeferredNonEmptyDeclarationErrorCheck = false; + } + + checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType); + + if (checkIsValidTypeAndQualifierForArray(arrayLocation, elementType)) + { + TType *arrayType = new TType(elementType); + arrayType->makeArrays(arraySizes); + + checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, arrayType); + checkTessellationShaderUnsizedArraysAndSetSize(identifierLocation, identifier, arrayType); + + checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, arrayType); + + if (IsAtomicCounter(arrayType->getBasicType())) + { + checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, arrayType); + + checkAtomicCounterOffsetAlignment(identifierLocation, *arrayType); + } + + adjustRedeclaredBuiltInType(identifier, arrayType); + + TVariable *variable = nullptr; + if (declareVariable(identifierLocation, identifier, arrayType, &variable)) + { + TIntermSymbol *symbol = new TIntermSymbol(variable); + symbol->setLine(identifierLocation); + declarationOut->appendDeclarator(symbol); + } + } +} + +void TParseContext::parseInitDeclarator(const TPublicType &publicType, + const TSourceLoc &identifierLocation, + const ImmutableString &identifier, + const TSourceLoc &initLocation, + TIntermTyped *initializer, + TIntermDeclaration *declarationOut) +{ + // If the declaration starting this declarator list was empty (example: int,), some checks were + // not performed. + if (mDeferredNonEmptyDeclarationErrorCheck) + { + nonEmptyDeclarationErrorCheck(publicType, identifierLocation); + mDeferredNonEmptyDeclarationErrorCheck = false; + } + + checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType); + + TIntermBinary *initNode = nullptr; + TType *type = new TType(publicType); + if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode)) + { + // + // build the intermediate representation + // + if (initNode) + { + declarationOut->appendDeclarator(initNode); + } + } +} + +void TParseContext::parseArrayInitDeclarator(const TPublicType &elementType, + const TSourceLoc &identifierLocation, + const ImmutableString &identifier, + const TSourceLoc &indexLocation, + const TVector &arraySizes, + const TSourceLoc &initLocation, + TIntermTyped *initializer, + TIntermDeclaration *declarationOut) +{ + // If the declaration starting this declarator list was empty (example: int,), some checks were + // not performed. + if (mDeferredNonEmptyDeclarationErrorCheck) + { + nonEmptyDeclarationErrorCheck(elementType, identifierLocation); + mDeferredNonEmptyDeclarationErrorCheck = false; + } + + checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType); + + checkIsValidTypeAndQualifierForArray(indexLocation, elementType); + + TType *arrayType = new TType(elementType); + arrayType->makeArrays(arraySizes); + + // initNode will correspond to the whole of "b[n] = initializer". + TIntermBinary *initNode = nullptr; + if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode)) + { + if (initNode) + { + declarationOut->appendDeclarator(initNode); + } + } +} + +TIntermNode *TParseContext::addEmptyStatement(const TSourceLoc &location) +{ + // It's simpler to parse an empty statement as a constant expression rather than having a + // different type of node just for empty statements, that will be pruned from the AST anyway. + TIntermNode *node = CreateZeroNode(TType(EbtInt, EbpMedium)); + node->setLine(location); + return node; +} + +void TParseContext::setAtomicCounterBindingDefaultOffset(const TPublicType &publicType, + const TSourceLoc &location) +{ + const TLayoutQualifier &layoutQualifier = publicType.layoutQualifier; + checkAtomicCounterBindingIsValid(location, layoutQualifier.binding); + if (layoutQualifier.binding == -1 || layoutQualifier.offset == -1) + { + error(location, "Requires both binding and offset", "layout"); + return; + } + mAtomicCounterBindingStates[layoutQualifier.binding].setDefaultOffset(layoutQualifier.offset); +} + +void TParseContext::parseDefaultPrecisionQualifier(const TPrecision precision, + const TPublicType &type, + const TSourceLoc &loc) +{ + if ((precision == EbpHigh) && (getShaderType() == GL_FRAGMENT_SHADER) && + !getFragmentPrecisionHigh()) + { + error(loc, "precision is not supported in fragment shader", "highp"); + } + + if (!CanSetDefaultPrecisionOnType(type)) + { + error(loc, "illegal type argument for default precision qualifier", + getBasicString(type.getBasicType())); + return; + } + symbolTable.setDefaultPrecision(type.getBasicType(), precision); +} + +bool TParseContext::checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier) +{ + switch (typeQualifier.layoutQualifier.primitiveType) + { + case EptLines: + case EptLinesAdjacency: + case EptTriangles: + case EptTrianglesAdjacency: + return typeQualifier.qualifier == EvqGeometryIn; + + case EptLineStrip: + case EptTriangleStrip: + return typeQualifier.qualifier == EvqGeometryOut; + + case EptPoints: + return true; + + default: + UNREACHABLE(); + return false; + } +} + +void TParseContext::setGeometryShaderInputArraySize(unsigned int inputArraySize, + const TSourceLoc &line) +{ + if (!symbolTable.setGlInArraySize(inputArraySize)) + { + error(line, + "Array size or input primitive declaration doesn't match the size of earlier sized " + "array inputs.", + "layout"); + } + mGeometryInputArraySize = inputArraySize; +} + +bool TParseContext::parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier) +{ + ASSERT(typeQualifier.qualifier == EvqGeometryIn); + + const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier; + + if (layoutQualifier.maxVertices != -1) + { + error(typeQualifier.line, + "max_vertices can only be declared in 'out' layout in a geometry shader", "layout"); + return false; + } + + // Set mGeometryInputPrimitiveType if exists + if (layoutQualifier.primitiveType != EptUndefined) + { + if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier)) + { + error(typeQualifier.line, "invalid primitive type for 'in' layout", "layout"); + return false; + } + + if (mGeometryShaderInputPrimitiveType == EptUndefined) + { + mGeometryShaderInputPrimitiveType = layoutQualifier.primitiveType; + setGeometryShaderInputArraySize( + GetGeometryShaderInputArraySize(mGeometryShaderInputPrimitiveType), + typeQualifier.line); + } + else if (mGeometryShaderInputPrimitiveType != layoutQualifier.primitiveType) + { + error(typeQualifier.line, "primitive doesn't match earlier input primitive declaration", + "layout"); + return false; + } + + // Size any implicitly sized arrays that have already been declared. + for (TType *type : mDeferredArrayTypesToSize) + { + type->sizeOutermostUnsizedArray( + symbolTable.getGlInVariableWithArraySize()->getType().getOutermostArraySize()); + } + mDeferredArrayTypesToSize.clear(); + } + + // Set mGeometryInvocations if exists + if (layoutQualifier.invocations > 0) + { + if (mGeometryShaderInvocations == 0) + { + mGeometryShaderInvocations = layoutQualifier.invocations; + } + else if (mGeometryShaderInvocations != layoutQualifier.invocations) + { + error(typeQualifier.line, "invocations contradicts to the earlier declaration", + "layout"); + return false; + } + } + + return true; +} + +bool TParseContext::parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier) +{ + ASSERT(typeQualifier.qualifier == EvqGeometryOut); + + const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier; + + if (layoutQualifier.invocations > 0) + { + error(typeQualifier.line, + "invocations can only be declared in 'in' layout in a geometry shader", "layout"); + return false; + } + + // Set mGeometryOutputPrimitiveType if exists + if (layoutQualifier.primitiveType != EptUndefined) + { + if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier)) + { + error(typeQualifier.line, "invalid primitive type for 'out' layout", "layout"); + return false; + } + + if (mGeometryShaderOutputPrimitiveType == EptUndefined) + { + mGeometryShaderOutputPrimitiveType = layoutQualifier.primitiveType; + } + else if (mGeometryShaderOutputPrimitiveType != layoutQualifier.primitiveType) + { + error(typeQualifier.line, + "primitive doesn't match earlier output primitive declaration", "layout"); + return false; + } + } + + // Set mGeometryMaxVertices if exists + if (layoutQualifier.maxVertices > -1) + { + if (mGeometryShaderMaxVertices == -1) + { + mGeometryShaderMaxVertices = layoutQualifier.maxVertices; + } + else if (mGeometryShaderMaxVertices != layoutQualifier.maxVertices) + { + error(typeQualifier.line, "max_vertices contradicts to the earlier declaration", + "layout"); + return false; + } + } + + return true; +} + +bool TParseContext::parseTessControlShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier) +{ + ASSERT(typeQualifier.qualifier == EvqTessControlOut); + + const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier; + + if (layoutQualifier.vertices == 0) + { + error(typeQualifier.line, "No vertices specified", "layout"); + return false; + } + + // Set mTessControlShaderOutputVertices if exists + if (mTessControlShaderOutputVertices == 0) + { + mTessControlShaderOutputVertices = layoutQualifier.vertices; + + // Size any implicitly sized arrays that have already been declared. + for (TType *type : mDeferredArrayTypesToSize) + { + type->sizeOutermostUnsizedArray(mTessControlShaderOutputVertices); + } + mDeferredArrayTypesToSize.clear(); + } + else + { + error(typeQualifier.line, "Duplicated vertices specified", "layout"); + } + return true; +} + +bool TParseContext::parseTessEvaluationShaderInputLayoutQualifier( + const TTypeQualifier &typeQualifier) +{ + ASSERT(typeQualifier.qualifier == EvqTessEvaluationIn); + + const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier; + + // Set mTessEvaluationShaderInputPrimitiveType if exists + if (layoutQualifier.tesPrimitiveType != EtetUndefined) + { + if (mTessEvaluationShaderInputPrimitiveType == EtetUndefined) + { + mTessEvaluationShaderInputPrimitiveType = layoutQualifier.tesPrimitiveType; + } + else + { + error(typeQualifier.line, "Duplicated primitive type declaration", "layout"); + } + } + // Set mTessEvaluationShaderVertexSpacingType if exists + if (layoutQualifier.tesVertexSpacingType != EtetUndefined) + { + if (mTessEvaluationShaderInputVertexSpacingType == EtetUndefined) + { + mTessEvaluationShaderInputVertexSpacingType = layoutQualifier.tesVertexSpacingType; + } + else + { + error(typeQualifier.line, "Duplicated vertex spacing declaration", "layout"); + } + } + // Set mTessEvaluationShaderInputOrderingType if exists + if (layoutQualifier.tesOrderingType != EtetUndefined) + { + if (mTessEvaluationShaderInputOrderingType == EtetUndefined) + { + mTessEvaluationShaderInputOrderingType = layoutQualifier.tesOrderingType; + } + else + { + error(typeQualifier.line, "Duplicated ordering declaration", "layout"); + } + } + // Set mTessEvaluationShaderInputPointType if exists + if (layoutQualifier.tesPointType != EtetUndefined) + { + if (mTessEvaluationShaderInputPointType == EtetUndefined) + { + mTessEvaluationShaderInputPointType = layoutQualifier.tesPointType; + } + else + { + error(typeQualifier.line, "Duplicated point type declaration", "layout"); + } + } + + return true; +} + +void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder) +{ + TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); + const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier; + + checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier, + typeQualifier.line); + + // It should never be the case, but some strange parser errors can send us here. + if (layoutQualifier.isEmpty()) + { + error(typeQualifier.line, "Error during layout qualifier parsing.", "?"); + return; + } + + if (!layoutQualifier.isCombinationValid()) + { + error(typeQualifier.line, "invalid layout qualifier combination", "layout"); + return; + } + + checkIndexIsNotSpecified(typeQualifier.line, layoutQualifier.index); + + checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding); + + checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line); + + checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat); + + checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv); + + checkOffsetIsNotSpecified(typeQualifier.line, layoutQualifier.offset); + + checkStd430IsForShaderStorageBlock(typeQualifier.line, layoutQualifier.blockStorage, + typeQualifier.qualifier); + + checkAdvancedBlendEquationsNotSpecified( + typeQualifier.line, layoutQualifier.advancedBlendEquations, typeQualifier.qualifier); + + if (typeQualifier.qualifier != EvqFragmentIn) + { + checkEarlyFragmentTestsIsNotSpecified(typeQualifier.line, + layoutQualifier.earlyFragmentTests); + } + + if (typeQualifier.qualifier == EvqComputeIn) + { + if (mComputeShaderLocalSizeDeclared && + !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize)) + { + error(typeQualifier.line, "Work group size does not match the previous declaration", + "layout"); + return; + } + + if (mShaderVersion < 310) + { + error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout"); + return; + } + + if (!layoutQualifier.localSize.isAnyValueSet()) + { + error(typeQualifier.line, "No local work group size specified", "layout"); + return; + } + + const TVariable *maxComputeWorkGroupSize = static_cast( + symbolTable.findBuiltIn(ImmutableString("gl_MaxComputeWorkGroupSize"), mShaderVersion)); + + const TConstantUnion *maxComputeWorkGroupSizeData = + maxComputeWorkGroupSize->getConstPointer(); + + for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i) + { + if (layoutQualifier.localSize[i] != -1) + { + mComputeShaderLocalSize[i] = layoutQualifier.localSize[i]; + const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst(); + if (mComputeShaderLocalSize[i] < 1 || + mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue) + { + std::stringstream reasonStream = sh::InitializeStream(); + reasonStream << "invalid value: Value must be at least 1 and no greater than " + << maxComputeWorkGroupSizeValue; + const std::string &reason = reasonStream.str(); + + error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i)); + return; + } + } + } + + mComputeShaderLocalSizeDeclared = true; + } + else if (typeQualifier.qualifier == EvqGeometryIn) + { + if (mShaderVersion < 310) + { + error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout"); + return; + } + + if (!parseGeometryShaderInputLayoutQualifier(typeQualifier)) + { + return; + } + } + else if (typeQualifier.qualifier == EvqGeometryOut) + { + if (mShaderVersion < 310) + { + error(typeQualifier.line, "out type qualifier supported in GLSL ES 3.10 only", + "layout"); + return; + } + + if (!parseGeometryShaderOutputLayoutQualifier(typeQualifier)) + { + return; + } + } + else if (anyMultiviewExtensionAvailable() && typeQualifier.qualifier == EvqVertexIn) + { + // This error is only specified in WebGL, but tightens unspecified behavior in the native + // specification. + if (mNumViews != -1 && layoutQualifier.numViews != mNumViews) + { + error(typeQualifier.line, "Number of views does not match the previous declaration", + "layout"); + return; + } + + if (layoutQualifier.numViews == -1) + { + error(typeQualifier.line, "No num_views specified", "layout"); + return; + } + + if (layoutQualifier.numViews > mMaxNumViews) + { + error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR", + "layout"); + return; + } + + mNumViews = layoutQualifier.numViews; + } + else if (typeQualifier.qualifier == EvqFragmentIn) + { + if (mShaderVersion < 310) + { + error(typeQualifier.line, + "in type qualifier without variable declaration supported in GLSL ES 3.10 and " + "after", + "layout"); + return; + } + + if (!layoutQualifier.earlyFragmentTests) + { + error(typeQualifier.line, + "only early_fragment_tests is allowed as layout qualifier when not declaring a " + "variable", + "layout"); + return; + } + + mEarlyFragmentTestsSpecified = true; + } + else if (typeQualifier.qualifier == EvqFragmentOut) + { + if (mShaderVersion < 320 && !isExtensionEnabled(TExtension::KHR_blend_equation_advanced)) + { + error(typeQualifier.line, + "out type qualifier without variable declaration is supported in GLSL ES 3.20," + " or if GL_KHR_blend_equation_advanced is enabled", + "layout"); + return; + } + + if (!layoutQualifier.advancedBlendEquations.any()) + { + error(typeQualifier.line, + "only blend equations are allowed as layout qualifier when not declaring a " + "variable", + "layout"); + return; + } + + mAdvancedBlendEquations |= layoutQualifier.advancedBlendEquations; + } + else if (typeQualifier.qualifier == EvqTessControlOut) + { + if (mShaderVersion < 310) + { + error(typeQualifier.line, "out type qualifier supported in GLSL ES 3.10 and after", + "layout"); + return; + } + + if (!parseTessControlShaderOutputLayoutQualifier(typeQualifier)) + { + return; + } + } + else if (typeQualifier.qualifier == EvqTessEvaluationIn) + { + if (mShaderVersion < 310) + { + error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 and after", + "layout"); + return; + } + + if (!parseTessEvaluationShaderInputLayoutQualifier(typeQualifier)) + { + return; + } + } + else + { + if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier)) + { + return; + } + + if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer) + { + error(typeQualifier.line, "invalid qualifier: global layout can only be set for blocks", + getQualifierString(typeQualifier.qualifier)); + return; + } + + if (mShaderVersion < 300) + { + error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and after", + "layout"); + return; + } + + checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier); + + if (layoutQualifier.matrixPacking != EmpUnspecified) + { + if (typeQualifier.qualifier == EvqUniform) + { + mDefaultUniformMatrixPacking = layoutQualifier.matrixPacking; + } + else if (typeQualifier.qualifier == EvqBuffer) + { + mDefaultBufferMatrixPacking = layoutQualifier.matrixPacking; + } + } + + if (layoutQualifier.blockStorage != EbsUnspecified) + { + if (typeQualifier.qualifier == EvqUniform) + { + mDefaultUniformBlockStorage = layoutQualifier.blockStorage; + } + else if (typeQualifier.qualifier == EvqBuffer) + { + mDefaultBufferBlockStorage = layoutQualifier.blockStorage; + } + } + } +} + +TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction( + const TFunction &function, + const TSourceLoc &location, + bool insertParametersToSymbolTable) +{ + checkIsNotReserved(location, function.name()); + + TIntermFunctionPrototype *prototype = new TIntermFunctionPrototype(&function); + prototype->setLine(location); + + for (size_t i = 0; i < function.getParamCount(); i++) + { + const TVariable *param = function.getParam(i); + + // If the parameter has no name, it's not an error, just don't add it to symbol table (could + // be used for unused args). + if (param->symbolType() != SymbolType::Empty) + { + if (insertParametersToSymbolTable) + { + if (!symbolTable.declare(const_cast(param))) + { + error(location, "redefinition", param->name()); + } + } + // Unsized type of a named parameter should have already been checked and sanitized. + ASSERT(!param->getType().isUnsizedArray()); + } + else + { + if (param->getType().isUnsizedArray()) + { + error(location, "function parameter array must be sized at compile time", "[]"); + // We don't need to size the arrays since the parameter is unnamed and hence + // inaccessible. + } + } + } + return prototype; +} + +TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration( + const TFunction &parsedFunction, + const TSourceLoc &location) +{ + // Note: function found from the symbol table could be the same as parsedFunction if this is the + // first declaration. Either way the instance in the symbol table is used to track whether the + // function is declared multiple times. + bool hadPrototypeDeclaration = false; + const TFunction *function = symbolTable.markFunctionHasPrototypeDeclaration( + parsedFunction.getMangledName(), &hadPrototypeDeclaration); + + if (hadPrototypeDeclaration && mShaderVersion == 100) + { + // ESSL 1.00.17 section 4.2.7. + // Doesn't apply to ESSL 3.00.4: see section 4.2.3. + error(location, "duplicate function prototype declarations are not allowed", "function"); + } + + TIntermFunctionPrototype *prototype = + createPrototypeNodeFromFunction(*function, location, false); + + symbolTable.pop(); + + if (!symbolTable.atGlobalLevel()) + { + // ESSL 3.00.4 section 4.2.4. + error(location, "local function prototype declarations are not allowed", "function"); + } + + return prototype; +} + +TIntermFunctionDefinition *TParseContext::addFunctionDefinition( + TIntermFunctionPrototype *functionPrototype, + TIntermBlock *functionBody, + const TSourceLoc &location) +{ + // Undo push at end of parseFunctionDefinitionHeader() below for ESSL1.00 case + if (mFunctionBodyNewScope) + { + mFunctionBodyNewScope = false; + symbolTable.pop(); + } + + // Check that non-void functions have at least one return statement. + if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue) + { + error(location, + "function does not return a value:", functionPrototype->getFunction()->name()); + } + + if (functionBody == nullptr) + { + functionBody = new TIntermBlock(); + functionBody->setLine(location); + } + TIntermFunctionDefinition *functionNode = + new TIntermFunctionDefinition(functionPrototype, functionBody); + functionNode->setLine(location); + + symbolTable.pop(); + return functionNode; +} + +void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location, + const TFunction *function, + TIntermFunctionPrototype **prototypeOut) +{ + ASSERT(function); + + bool wasDefined = false; + function = symbolTable.setFunctionParameterNamesFromDefinition(function, &wasDefined); + if (wasDefined) + { + error(location, "function already has a body", function->name()); + } + + // Remember the return type for later checking for return statements. + mCurrentFunctionType = &(function->getReturnType()); + mFunctionReturnsValue = false; + + *prototypeOut = createPrototypeNodeFromFunction(*function, location, true); + setLoopNestingLevel(0); + + // ESSL 1.00 spec allows for variable in function body to redefine parameter + if (IsSpecWithFunctionBodyNewScope(mShaderSpec, mShaderVersion)) + { + mFunctionBodyNewScope = true; + symbolTable.push(); + } +} + +TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function) +{ + // + // We don't know at this point whether this is a function definition or a prototype. + // The definition production code will check for redefinitions. + // In the case of ESSL 1.00 the prototype production code will also check for redeclarations. + // + + for (size_t i = 0u; i < function->getParamCount(); ++i) + { + const TVariable *param = function->getParam(i); + const TType ¶mType = param->getType(); + + if (paramType.isStructSpecifier()) + { + // ESSL 3.00.6 section 12.10. + error(location, "Function parameter type cannot be a structure definition", + function->name()); + } + + checkPrecisionSpecified(location, paramType.getPrecision(), paramType.getBasicType()); + } + + if (getShaderVersion() >= 300) + { + if (symbolTable.isUnmangledBuiltInName(function->name(), getShaderVersion(), + extensionBehavior())) + { + // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as + // functions. Therefore overloading or redefining builtin functions is an error. + error(location, "Name of a built-in function cannot be redeclared as function", + function->name()); + } + } + else + { + // ESSL 1.00.17 section 4.2.6: built-ins can be overloaded but not redefined. We assume that + // this applies to redeclarations as well. + const TSymbol *builtIn = + symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion()); + if (builtIn) + { + error(location, "built-in functions cannot be redefined", function->name()); + } + } + + // Return types and parameter qualifiers must match in all redeclarations, so those are checked + // here. + const TFunction *prevDec = + static_cast(symbolTable.findGlobal(function->getMangledName())); + if (prevDec) + { + if (prevDec->getReturnType() != function->getReturnType()) + { + error(location, "function must have the same return type in all of its declarations", + function->getReturnType().getBasicString()); + } + for (size_t i = 0; i < prevDec->getParamCount(); ++i) + { + if (prevDec->getParam(i)->getType().getQualifier() != + function->getParam(i)->getType().getQualifier()) + { + error(location, + "function must have the same parameter qualifiers in all of its declarations", + function->getParam(i)->getType().getQualifierString()); + } + } + } + + // Check for previously declared variables using the same name. + const TSymbol *prevSym = symbolTable.find(function->name(), getShaderVersion()); + bool insertUnmangledName = true; + if (prevSym) + { + if (!prevSym->isFunction()) + { + error(location, "redefinition of a function", function->name()); + } + insertUnmangledName = false; + } + // Parsing is at the inner scope level of the function's arguments and body statement at this + // point, but declareUserDefinedFunction takes care of declaring the function at the global + // scope. + symbolTable.declareUserDefinedFunction(function, insertUnmangledName); + + // Raise error message if main function takes any parameters or return anything other than void + if (function->isMain()) + { + if (function->getParamCount() > 0) + { + error(location, "function cannot take any parameter(s)", "main"); + } + if (function->getReturnType().getBasicType() != EbtVoid) + { + error(location, "main function cannot return a value", + function->getReturnType().getBasicString()); + } + } + + mDeclaringMain = function->isMain(); + + // + // If this is a redeclaration, it could also be a definition, in which case, we want to use the + // variable names from this one, and not the one that's + // being redeclared. So, pass back up this declaration, not the one in the symbol table. + // + return function; +} + +TFunction *TParseContext::parseFunctionHeader(const TPublicType &type, + const ImmutableString &name, + const TSourceLoc &location) +{ + if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary) + { + error(location, "no qualifiers allowed for function return", + getQualifierString(type.qualifier)); + } + if (!type.layoutQualifier.isEmpty()) + { + error(location, "no qualifiers allowed for function return", "layout"); + } + // make sure an opaque type is not involved as well... + std::string reason(getBasicString(type.getBasicType())); + reason += "s can't be function return values"; + checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str()); + if (mShaderVersion < 300) + { + // Array return values are forbidden, but there's also no valid syntax for declaring array + // return values in ESSL 1.00. + ASSERT(!type.isArray() || mDiagnostics->numErrors() > 0); + + if (type.isStructureContainingArrays()) + { + // ESSL 1.00.17 section 6.1 Function Definitions + TInfoSinkBase typeString; + typeString << TType(type); + error(location, "structures containing arrays can't be function return values", + typeString.c_str()); + } + } + + // Add the function as a prototype after parsing it (we do not support recursion) + return new TFunction(&symbolTable, name, SymbolType::UserDefined, new TType(type), false); +} + +TFunctionLookup *TParseContext::addNonConstructorFunc(const ImmutableString &name, + const TSymbol *symbol) +{ + return TFunctionLookup::CreateFunctionCall(name, symbol); +} + +TFunctionLookup *TParseContext::addConstructorFunc(const TPublicType &publicType) +{ + if (mShaderVersion < 300 && publicType.isArray()) + { + error(publicType.getLine(), "array constructor supported in GLSL ES 3.00 and above only", + "[]"); + } + if (publicType.isStructSpecifier()) + { + error(publicType.getLine(), "constructor can't be a structure definition", + getBasicString(publicType.getBasicType())); + } + + TType *type = new TType(publicType); + if (!type->canBeConstructed()) + { + error(publicType.getLine(), "cannot construct this type", + getBasicString(publicType.getBasicType())); + type->setBasicType(EbtFloat); + } + return TFunctionLookup::CreateConstructor(type); +} + +void TParseContext::checkIsNotUnsizedArray(const TSourceLoc &line, + const char *errorMessage, + const ImmutableString &token, + TType *arrayType) +{ + if (arrayType->isUnsizedArray()) + { + error(line, errorMessage, token); + arrayType->sizeUnsizedArrays(TSpan()); + } +} + +TParameter TParseContext::parseParameterDeclarator(TType *type, + const ImmutableString &name, + const TSourceLoc &nameLoc) +{ + ASSERT(type); + checkIsNotUnsizedArray(nameLoc, "function parameter array must specify a size", name, type); + if (type->getBasicType() == EbtVoid) + { + error(nameLoc, "illegal use of type 'void'", name); + } + checkIsNotReserved(nameLoc, name); + TParameter param = {name.data(), type}; + return param; +} + +TParameter TParseContext::parseParameterDeclarator(const TPublicType &publicType, + const ImmutableString &name, + const TSourceLoc &nameLoc) +{ + TType *type = new TType(publicType); + return parseParameterDeclarator(type, name, nameLoc); +} + +TParameter TParseContext::parseParameterArrayDeclarator(const ImmutableString &name, + const TSourceLoc &nameLoc, + const TVector &arraySizes, + const TSourceLoc &arrayLoc, + TPublicType *elementType) +{ + checkArrayElementIsNotArray(arrayLoc, *elementType); + TType *arrayType = new TType(*elementType); + arrayType->makeArrays(arraySizes); + return parseParameterDeclarator(arrayType, name, nameLoc); +} + +bool TParseContext::checkUnsizedArrayConstructorArgumentDimensionality( + const TIntermSequence &arguments, + TType type, + const TSourceLoc &line) +{ + if (arguments.empty()) + { + error(line, "implicitly sized array constructor must have at least one argument", "[]"); + return false; + } + for (TIntermNode *arg : arguments) + { + const TIntermTyped *element = arg->getAsTyped(); + ASSERT(element); + size_t dimensionalityFromElement = element->getType().getNumArraySizes() + 1u; + if (dimensionalityFromElement > type.getNumArraySizes()) + { + error(line, "constructing from a non-dereferenced array", "constructor"); + return false; + } + else if (dimensionalityFromElement < type.getNumArraySizes()) + { + if (dimensionalityFromElement == 1u) + { + error(line, "implicitly sized array of arrays constructor argument is not an array", + "constructor"); + } + else + { + error(line, + "implicitly sized array of arrays constructor argument dimensionality is too " + "low", + "constructor"); + } + return false; + } + } + return true; +} + +// This function is used to test for the correctness of the parameters passed to various constructor +// functions and also convert them to the right datatype if it is allowed and required. +// +// Returns a node to add to the tree regardless of if an error was generated or not. +// +TIntermTyped *TParseContext::addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line) +{ + TType type = fnCall->constructorType(); + TIntermSequence &arguments = fnCall->arguments(); + if (type.isUnsizedArray()) + { + if (!checkUnsizedArrayConstructorArgumentDimensionality(arguments, type, line)) + { + type.sizeUnsizedArrays(TSpan()); + return CreateZeroNode(type); + } + TIntermTyped *firstElement = arguments.at(0)->getAsTyped(); + ASSERT(firstElement); + if (type.getOutermostArraySize() == 0u) + { + type.sizeOutermostUnsizedArray(static_cast(arguments.size())); + } + for (size_t i = 0; i < firstElement->getType().getNumArraySizes(); ++i) + { + if (type.getArraySizes()[i] == 0u) + { + type.setArraySize(i, firstElement->getType().getArraySizes()[i]); + } + } + ASSERT(!type.isUnsizedArray()); + } + + if (!checkConstructorArguments(line, arguments, type)) + { + return CreateZeroNode(type); + } + + TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, &arguments); + constructorNode->setLine(line); + + return constructorNode->fold(mDiagnostics); +} + +// +// Interface/uniform blocks +TIntermDeclaration *TParseContext::addInterfaceBlock( + const TTypeQualifierBuilder &typeQualifierBuilder, + const TSourceLoc &nameLine, + const ImmutableString &blockName, + TFieldList *fieldList, + const ImmutableString &instanceName, + const TSourceLoc &instanceLine, + const TVector *arraySizes, + const TSourceLoc &arraySizesLine) +{ + const bool isGLPerVertex = blockName == "gl_PerVertex"; + // gl_PerVertex is allowed to be redefined and therefore not reserved + if (!isGLPerVertex) + { + checkIsNotReserved(nameLine, blockName); + } + + TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); + + const bool isUniformOrBuffer = + typeQualifier.qualifier == EvqUniform || typeQualifier.qualifier == EvqBuffer; + const bool isShaderIoBlock = IsShaderIoBlock(typeQualifier.qualifier); + + if (mShaderVersion < 310 && typeQualifier.qualifier != EvqUniform) + { + error(typeQualifier.line, + "invalid qualifier: interface blocks must be uniform in version lower than GLSL ES " + "3.10", + getQualifierString(typeQualifier.qualifier)); + } + else if (typeQualifier.qualifier == EvqPatchOut) + { + if ((!isExtensionEnabled(TExtension::EXT_tessellation_shader) && mShaderVersion < 320) || + mShaderType != GL_TESS_CONTROL_SHADER) + { + error(typeQualifier.line, + "invalid qualifier: 'patch out' requires a tessellation control shader", + getQualifierString(typeQualifier.qualifier)); + } + } + else if (typeQualifier.qualifier == EvqPatchIn) + { + if ((!isExtensionEnabled(TExtension::EXT_tessellation_shader) && mShaderVersion < 320) || + mShaderType != GL_TESS_EVALUATION_SHADER) + { + error(typeQualifier.line, + "invalid qualifier: 'patch in' requires a tessellation evaluation shader", + getQualifierString(typeQualifier.qualifier)); + } + } + else if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer) + { + if (isShaderIoBlock) + { + if (!isExtensionEnabled(TExtension::OES_shader_io_blocks) && + !isExtensionEnabled(TExtension::EXT_shader_io_blocks) && + !isExtensionEnabled(TExtension::OES_geometry_shader) && + !isExtensionEnabled(TExtension::EXT_geometry_shader) && mShaderVersion < 320) + { + error(typeQualifier.line, + "invalid qualifier: shader IO blocks need shader io block extension", + getQualifierString(typeQualifier.qualifier)); + } + + // Both inputs and outputs of tessellation control shaders must be arrays. + // For tessellation evaluation shaders, only inputs must necessarily be arrays. + const bool isTCS = mShaderType == GL_TESS_CONTROL_SHADER; + const bool isTESIn = + mShaderType == GL_TESS_EVALUATION_SHADER && IsShaderIn(typeQualifier.qualifier); + if (arraySizes == nullptr && (isTCS || isTESIn)) + { + error(typeQualifier.line, "type must be an array", blockName); + } + } + else + { + error(typeQualifier.line, + "invalid qualifier: interface blocks must be uniform or buffer", + getQualifierString(typeQualifier.qualifier)); + } + } + + if (typeQualifier.invariant) + { + error(typeQualifier.line, "invalid qualifier on interface block", "invariant"); + } + + if (typeQualifier.qualifier != EvqBuffer) + { + checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line); + } + + // Verify array sizes + if (arraySizes) + { + if (isUniformOrBuffer) + { + if (arraySizes->size() == 0) + { + error(arraySizesLine, "unsized arrays are not allowed with interface blocks", ""); + } + if (arraySizes->size() > 1) + { + error(arraySizesLine, "array of arrays are not allowed with interface blocks", ""); + } + } + else if (isShaderIoBlock) + { + size_t arrayDimensions = arraySizes->size(); + + // Geometry shader inputs have a level arrayness that must be ignored. + if (mShaderType == GL_GEOMETRY_SHADER_EXT && IsVaryingIn(typeQualifier.qualifier)) + { + ASSERT(arrayDimensions > 0); + --arrayDimensions; + + // Validate that the array size of input matches the geometry layout + // declaration, if not automatic (specified as []). + const unsigned int geometryDim = arraySizes->back(); + if (geometryDim > 0 && geometryDim != mGeometryInputArraySize) + { + error(arraySizesLine, + "geometry shader input block array size inconsistent " + "with primitive", + ""); + } + } + + if (arrayDimensions > 1) + { + error(arraySizesLine, "array of arrays are not allowed with I/O blocks", ""); + } + } + } + else if (isShaderIoBlock && mShaderType == GL_GEOMETRY_SHADER_EXT && + IsVaryingIn(typeQualifier.qualifier)) + { + error(arraySizesLine, "geometry shader input blocks must be an array", ""); + } + + checkIndexIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.index); + + if (mShaderVersion < 310) + { + checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding); + } + else + { + unsigned int arraySize = + arraySizes == nullptr || arraySizes->empty() ? 0 : (*arraySizes)[0]; + checkBlockBindingIsValid(typeQualifier.line, typeQualifier.qualifier, + typeQualifier.layoutQualifier.binding, arraySize); + } + + checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv); + checkEarlyFragmentTestsIsNotSpecified(typeQualifier.line, + typeQualifier.layoutQualifier.earlyFragmentTests); + checkNoncoherentIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.noncoherent); + + TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier; + if (!IsShaderIoBlock(typeQualifier.qualifier) && typeQualifier.qualifier != EvqPatchIn && + typeQualifier.qualifier != EvqPatchOut) + { + checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier); + } + checkStd430IsForShaderStorageBlock(typeQualifier.line, blockLayoutQualifier.blockStorage, + typeQualifier.qualifier); + + if (blockLayoutQualifier.matrixPacking == EmpUnspecified) + { + if (typeQualifier.qualifier == EvqUniform) + { + blockLayoutQualifier.matrixPacking = mDefaultUniformMatrixPacking; + } + else if (typeQualifier.qualifier == EvqBuffer) + { + blockLayoutQualifier.matrixPacking = mDefaultBufferMatrixPacking; + } + } + + if (blockLayoutQualifier.blockStorage == EbsUnspecified) + { + if (typeQualifier.qualifier == EvqUniform) + { + blockLayoutQualifier.blockStorage = mDefaultUniformBlockStorage; + } + else if (typeQualifier.qualifier == EvqBuffer) + { + blockLayoutQualifier.blockStorage = mDefaultBufferBlockStorage; + } + } + + checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier); + + checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat); + + // check for sampler types and apply layout qualifiers + for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) + { + TField *field = (*fieldList)[memberIndex]; + TType *fieldType = field->type(); + if (IsOpaqueType(fieldType->getBasicType())) + { + std::string reason("unsupported type - "); + reason += fieldType->getBasicString(); + reason += " types are not allowed in interface blocks"; + error(field->line(), reason.c_str(), fieldType->getBasicString()); + } + + const TQualifier qualifier = fieldType->getQualifier(); + switch (qualifier) + { + case EvqGlobal: + break; + case EvqUniform: + if (typeQualifier.qualifier == EvqBuffer) + { + error(field->line(), "invalid qualifier on shader storage block member", + getQualifierString(qualifier)); + } + break; + case EvqBuffer: + if (typeQualifier.qualifier == EvqUniform) + { + error(field->line(), "invalid qualifier on uniform block member", + getQualifierString(qualifier)); + } + break; + // a member variable in io block may have different interpolation. + case EvqFlatIn: + case EvqFlatOut: + case EvqNoPerspectiveIn: + case EvqNoPerspectiveOut: + case EvqSmoothIn: + case EvqSmoothOut: + case EvqCentroidIn: + case EvqCentroidOut: + break; + // a member variable can have an incomplete qualifier because shader io block has either + // in or out. + case EvqSmooth: + case EvqFlat: + case EvqNoPerspective: + case EvqCentroid: + case EvqGeometryIn: + case EvqGeometryOut: + if (!IsShaderIoBlock(typeQualifier.qualifier) && + typeQualifier.qualifier != EvqPatchIn && + typeQualifier.qualifier != EvqPatchOut && + typeQualifier.qualifier != EvqGeometryIn && + typeQualifier.qualifier != EvqGeometryOut) + { + error(field->line(), "invalid qualifier on interface block member", + getQualifierString(qualifier)); + } + break; + default: + error(field->line(), "invalid qualifier on interface block member", + getQualifierString(qualifier)); + break; + } + + // On interface block members, invariant is only applicable to output I/O blocks. + const bool isOutputShaderIoBlock = isShaderIoBlock && IsShaderOut(typeQualifier.qualifier); + if (fieldType->isInvariant() && !isOutputShaderIoBlock) + { + error(field->line(), "invalid qualifier on interface block member", "invariant"); + } + + // check layout qualifiers + TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier(); + checkIndexIsNotSpecified(field->line(), fieldLayoutQualifier.index); + checkBindingIsNotSpecified(field->line(), fieldLayoutQualifier.binding); + + if (fieldLayoutQualifier.blockStorage != EbsUnspecified) + { + error(field->line(), "invalid layout qualifier: cannot be used here", + getBlockStorageString(fieldLayoutQualifier.blockStorage)); + } + + if (fieldLayoutQualifier.matrixPacking == EmpUnspecified) + { + fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking; + } + else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct) + { + warning(field->line(), + "extraneous layout qualifier: only has an effect on matrix types", + getMatrixPackingString(fieldLayoutQualifier.matrixPacking)); + } + + fieldType->setLayoutQualifier(fieldLayoutQualifier); + + if (mShaderVersion < 310 || memberIndex != fieldList->size() - 1u || + typeQualifier.qualifier != EvqBuffer) + { + // ESSL 3.10 spec section 4.1.9 allows for runtime-sized arrays. + checkIsNotUnsizedArray(field->line(), + "array members of interface blocks must specify a size", + field->name(), field->type()); + } + + if (typeQualifier.qualifier == EvqBuffer) + { + // set memory qualifiers + // GLSL ES 3.10 session 4.9 [Memory Access Qualifiers]. When a block declaration is + // qualified with a memory qualifier, it is as if all of its members were declared with + // the same memory qualifier. + const TMemoryQualifier &blockMemoryQualifier = typeQualifier.memoryQualifier; + TMemoryQualifier fieldMemoryQualifier = fieldType->getMemoryQualifier(); + fieldMemoryQualifier.readonly |= blockMemoryQualifier.readonly; + fieldMemoryQualifier.writeonly |= blockMemoryQualifier.writeonly; + fieldMemoryQualifier.coherent |= blockMemoryQualifier.coherent; + fieldMemoryQualifier.restrictQualifier |= blockMemoryQualifier.restrictQualifier; + fieldMemoryQualifier.volatileQualifier |= blockMemoryQualifier.volatileQualifier; + // TODO(jiajia.qin@intel.com): Decide whether if readonly and writeonly buffer variable + // is legal. See bug https://github.com/KhronosGroup/OpenGL-API/issues/7 + fieldType->setMemoryQualifier(fieldMemoryQualifier); + } + } + + SymbolType instanceSymbolType = SymbolType::UserDefined; + if (isGLPerVertex) + { + instanceSymbolType = SymbolType::BuiltIn; + } + TInterfaceBlock *interfaceBlock = new TInterfaceBlock(&symbolTable, blockName, fieldList, + blockLayoutQualifier, instanceSymbolType); + if (!symbolTable.declare(interfaceBlock) && isUniformOrBuffer) + { + error(nameLine, "redefinition of an interface block name", blockName); + } + + TType *interfaceBlockType = + new TType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier); + if (arraySizes) + { + interfaceBlockType->makeArrays(*arraySizes); + + checkGeometryShaderInputAndSetArraySize(instanceLine, instanceName, interfaceBlockType); + checkTessellationShaderUnsizedArraysAndSetSize(instanceLine, instanceName, + interfaceBlockType); + } + + // The instance variable gets created to refer to the interface block type from the AST + // regardless of if there's an instance name. It's created as an empty symbol if there is no + // instance name. + TVariable *instanceVariable = + new TVariable(&symbolTable, instanceName, interfaceBlockType, + instanceName.empty() ? SymbolType::Empty : SymbolType::UserDefined); + + if (instanceVariable->symbolType() == SymbolType::Empty) + { + // define symbols for the members of the interface block + for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) + { + TField *field = (*fieldList)[memberIndex]; + TType *fieldType = new TType(*field->type()); + + // set parent pointer of the field variable + fieldType->setInterfaceBlockField(interfaceBlock, memberIndex); + + fieldType->setQualifier(typeQualifier.qualifier); + + SymbolType symbolType = SymbolType::UserDefined; + if (field->name() == "gl_Position" || field->name() == "gl_PointSize" || + field->name() == "gl_ClipDistance" || field->name() == "gl_CullDistance") + { + // These builtins can be redifined only when used within a redefiend gl_PerVertex + // block + if (interfaceBlock->name() != "gl_PerVertex") + { + error(field->line(), "redefinition in an invalid interface block", + field->name()); + } + symbolType = SymbolType::BuiltIn; + } + TVariable *fieldVariable = + new TVariable(&symbolTable, field->name(), fieldType, symbolType); + if (!symbolTable.declare(fieldVariable)) + { + error(field->line(), "redefinition of an interface block member name", + field->name()); + } + } + } + else + { + checkIsNotReserved(instanceLine, instanceName); + + // add a symbol for this interface block + if (!symbolTable.declare(instanceVariable)) + { + error(instanceLine, "redefinition of an interface block instance name", instanceName); + } + } + + TIntermSymbol *blockSymbol = new TIntermSymbol(instanceVariable); + blockSymbol->setLine(typeQualifier.line); + TIntermDeclaration *declaration = new TIntermDeclaration(); + declaration->appendDeclarator(blockSymbol); + declaration->setLine(nameLine); + + exitStructDeclaration(); + return declaration; +} + +void TParseContext::enterStructDeclaration(const TSourceLoc &line, + const ImmutableString &identifier) +{ + ++mStructNestingLevel; + + // Embedded structure definitions are not supported per GLSL ES spec. + // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11. + if (mStructNestingLevel > 1) + { + error(line, "Embedded struct definitions are not allowed", "struct"); + } +} + +void TParseContext::exitStructDeclaration() +{ + --mStructNestingLevel; +} + +void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field) +{ + if (!sh::IsWebGLBasedSpec(mShaderSpec)) + { + return; + } + + if (field.type()->getBasicType() != EbtStruct) + { + return; + } + + // We're already inside a structure definition at this point, so add + // one to the field's struct nesting. + if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) + { + std::stringstream reasonStream = sh::InitializeStream(); + if (field.type()->getStruct()->symbolType() == SymbolType::Empty) + { + // This may happen in case there are nested struct definitions. While they are also + // invalid GLSL, they don't cause a syntax error. + reasonStream << "Struct nesting"; + } + else + { + reasonStream << "Reference of struct type " << field.type()->getStruct()->name(); + } + reasonStream << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting; + std::string reason = reasonStream.str(); + error(line, reason.c_str(), field.name()); + return; + } +} + +// +// Parse an array index expression +// +TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, + const TSourceLoc &location, + TIntermTyped *indexExpression) +{ + if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector()) + { + if (baseExpression->getAsSymbolNode()) + { + error(location, " left of '[' is not of type array, matrix, or vector ", + baseExpression->getAsSymbolNode()->getName()); + } + else + { + error(location, " left of '[' is not of type array, matrix, or vector ", "expression"); + } + + return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); + } + + if (baseExpression->getQualifier() == EvqPerVertexIn) + { + if (mGeometryShaderInputPrimitiveType == EptUndefined && + mShaderType == GL_GEOMETRY_SHADER_EXT) + { + error(location, "missing input primitive declaration before indexing gl_in.", "["); + return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); + } + } + + TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion(); + + // ES3.2 or ES3.1's EXT_gpu_shader5 allow dynamically uniform expressions to be used as indices + // of opaque types (samplers and atomic counters) as well as UBOs, but not SSBOs and images. + bool allowUniformIndices = + mShaderVersion >= 320 || isExtensionEnabled(TExtension::EXT_gpu_shader5); + + // ANGLE should be able to fold any constant expressions resulting in an integer - but to be + // safe we don't treat "EvqConst" that's evaluated according to the spec as being sufficient + // for constness. Some interpretations of the spec have allowed constant expressions with side + // effects - like array length() method on a non-constant array. + if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr) + { + if (baseExpression->isInterfaceBlock()) + { + switch (baseExpression->getQualifier()) + { + case EvqPerVertexIn: + break; + case EvqUniform: + if (!allowUniformIndices) + { + error(location, + "array indexes for uniform block arrays must be constant integral " + "expressions", + "["); + } + break; + case EvqBuffer: + error(location, + "array indexes for shader storage block arrays must be constant integral " + "expressions", + "["); + break; + default: + // It's ok for shader I/O blocks to be dynamically indexed + if (!IsShaderIoBlock(baseExpression->getQualifier()) && + baseExpression->getQualifier() != EvqPatchIn && + baseExpression->getQualifier() != EvqPatchOut) + { + // We can reach here only in error cases. + ASSERT(mDiagnostics->numErrors() > 0); + } + break; + } + } + else if (baseExpression->getQualifier() == EvqFragmentOut) + { + error(location, + "array indexes for fragment outputs must be constant integral expressions", "["); + } + else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData) + { + error(location, "array index for gl_FragData must be constant zero", "["); + } + else if (baseExpression->isArray()) + { + TBasicType elementType = baseExpression->getType().getBasicType(); + + // Note: In Section 12.30 of the ESSL 3.00 spec on p143-144: + // + // Indexing of arrays of samplers by constant-index-expressions is + // supported in GLSL ES 1.00. A constant-index-expression is an + // expression formed from constant-expressions and certain loop indices, + // defined for a subset of loop constructs. Should this functionality be + // included in GLSL ES 3.00? + // + // RESOLUTION: No. Arrays of samplers may only be indexed by constant- + // integral-expressions. + if (IsSampler(elementType) && !allowUniformIndices && mShaderVersion > 100) + { + error(location, "array index for samplers must be constant integral expressions", + "["); + } + else if (IsImage(elementType)) + { + error(location, + "array indexes for image arrays must be constant integral expressions", "["); + } + } + } + + if (indexConstantUnion) + { + // If an out-of-range index is not qualified as constant, the behavior in the spec is + // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may + // constant fold expressions that are not constant expressions). The most compatible way to + // handle this case is to report a warning instead of an error and force the index to be in + // the correct range. + bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst; + int index = 0; + if (indexConstantUnion->getBasicType() == EbtInt) + { + index = indexConstantUnion->getIConst(0); + } + else if (indexConstantUnion->getBasicType() == EbtUInt) + { + index = static_cast(indexConstantUnion->getUConst(0)); + } + + int safeIndex = -1; + + if (index < 0) + { + outOfRangeError(outOfRangeIndexIsError, location, "index expression is negative", "[]"); + safeIndex = 0; + } + + if (!baseExpression->getType().isUnsizedArray()) + { + if (baseExpression->isArray()) + { + if (baseExpression->getQualifier() == EvqFragData && index > 0) + { + if (!isExtensionEnabled(TExtension::EXT_draw_buffers)) + { + outOfRangeError(outOfRangeIndexIsError, location, + "array index for gl_FragData must be zero when " + "GL_EXT_draw_buffers is disabled", + "[]"); + safeIndex = 0; + } + } + } + // Only do generic out-of-range check if similar error hasn't already been reported. + if (safeIndex < 0) + { + if (baseExpression->isArray()) + { + safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index, + baseExpression->getOutermostArraySize(), + "array index out of range"); + } + else if (baseExpression->isMatrix()) + { + safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index, + baseExpression->getType().getCols(), + "matrix field selection out of range"); + } + else + { + ASSERT(baseExpression->isVector()); + safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index, + baseExpression->getType().getNominalSize(), + "vector field selection out of range"); + } + } + + ASSERT(safeIndex >= 0); + // Data of constant unions can't be changed, because it may be shared with other + // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new + // sanitized object. + if (safeIndex != index || indexConstantUnion->getBasicType() != EbtInt) + { + TConstantUnion *safeConstantUnion = new TConstantUnion(); + safeConstantUnion->setIConst(safeIndex); + indexExpression = + new TIntermConstantUnion(safeConstantUnion, TType(indexExpression->getType())); + } + + TIntermBinary *node = + new TIntermBinary(EOpIndexDirect, baseExpression, indexExpression); + node->setLine(location); + return expressionOrFoldedResult(node); + } + } + + markStaticReadIfSymbol(indexExpression); + TIntermBinary *node = new TIntermBinary(EOpIndexIndirect, baseExpression, indexExpression); + node->setLine(location); + // Indirect indexing can never be constant folded. + return node; +} + +int TParseContext::checkIndexLessThan(bool outOfRangeIndexIsError, + const TSourceLoc &location, + int index, + int arraySize, + const char *reason) +{ + // Should not reach here with an unsized / runtime-sized array. + ASSERT(arraySize > 0); + // A negative index should already have been checked. + ASSERT(index >= 0); + if (index >= arraySize) + { + std::stringstream reasonStream = sh::InitializeStream(); + reasonStream << reason << " '" << index << "'"; + std::string token = reasonStream.str(); + outOfRangeError(outOfRangeIndexIsError, location, reason, "[]"); + return arraySize - 1; + } + return index; +} + +TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression, + const TSourceLoc &dotLocation, + const ImmutableString &fieldString, + const TSourceLoc &fieldLocation) +{ + if (baseExpression->isArray()) + { + error(fieldLocation, "cannot apply dot operator to an array", "."); + return baseExpression; + } + + if (baseExpression->isVector()) + { + TVector fieldOffsets; + if (!parseVectorFields(fieldLocation, fieldString, baseExpression->getNominalSize(), + &fieldOffsets)) + { + fieldOffsets.resize(1); + fieldOffsets[0] = 0; + } + TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldOffsets); + node->setLine(dotLocation); + + return node->fold(mDiagnostics); + } + else if (baseExpression->getBasicType() == EbtStruct) + { + const TFieldList &fields = baseExpression->getType().getStruct()->fields(); + if (fields.empty()) + { + error(dotLocation, "structure has no fields", "Internal Error"); + return baseExpression; + } + else + { + bool fieldFound = false; + unsigned int i; + for (i = 0; i < fields.size(); ++i) + { + if (fields[i]->name() == fieldString) + { + fieldFound = true; + break; + } + } + if (fieldFound) + { + TIntermTyped *index = CreateIndexNode(i); + index->setLine(fieldLocation); + TIntermBinary *node = + new TIntermBinary(EOpIndexDirectStruct, baseExpression, index); + node->setLine(dotLocation); + return expressionOrFoldedResult(node); + } + else + { + error(dotLocation, " no such field in structure", fieldString); + return baseExpression; + } + } + } + else if (baseExpression->isInterfaceBlock()) + { + const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields(); + if (fields.empty()) + { + error(dotLocation, "interface block has no fields", "Internal Error"); + return baseExpression; + } + else + { + bool fieldFound = false; + unsigned int i; + for (i = 0; i < fields.size(); ++i) + { + if (fields[i]->name() == fieldString) + { + fieldFound = true; + break; + } + } + if (fieldFound) + { + TIntermTyped *index = CreateIndexNode(i); + index->setLine(fieldLocation); + TIntermBinary *node = + new TIntermBinary(EOpIndexDirectInterfaceBlock, baseExpression, index); + node->setLine(dotLocation); + // Indexing interface blocks can never be constant folded. + return node; + } + else + { + error(dotLocation, " no such field in interface block", fieldString); + return baseExpression; + } + } + } + else + { + if (mShaderVersion < 300) + { + error(dotLocation, " field selection requires structure or vector on left hand side", + fieldString); + } + else + { + error(dotLocation, + " field selection requires structure, vector, or interface block on left hand " + "side", + fieldString); + } + return baseExpression; + } +} + +TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qualifierType, + const TSourceLoc &qualifierTypeLine) +{ + TLayoutQualifier qualifier = TLayoutQualifier::Create(); + + if (qualifierType == "shared") + { + if (sh::IsWebGLBasedSpec(mShaderSpec)) + { + error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared"); + } + qualifier.blockStorage = EbsShared; + } + else if (qualifierType == "packed") + { + if (sh::IsWebGLBasedSpec(mShaderSpec)) + { + error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed"); + } + qualifier.blockStorage = EbsPacked; + } + else if (qualifierType == "std430") + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + qualifier.blockStorage = EbsStd430; + } + else if (qualifierType == "std140") + { + qualifier.blockStorage = EbsStd140; + } + else if (qualifierType == "row_major") + { + qualifier.matrixPacking = EmpRowMajor; + } + else if (qualifierType == "column_major") + { + qualifier.matrixPacking = EmpColumnMajor; + } + else if (qualifierType == "location") + { + error(qualifierTypeLine, "invalid layout qualifier: location requires an argument", + qualifierType); + } + else if (qualifierType == "yuv" && mShaderType == GL_FRAGMENT_SHADER) + { + if (checkCanUseExtension(qualifierTypeLine, TExtension::EXT_YUV_target)) + { + qualifier.yuv = true; + } + } + else if (qualifierType == "early_fragment_tests") + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + qualifier.earlyFragmentTests = true; + } + else if (qualifierType == "rgba32f") + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + qualifier.imageInternalFormat = EiifRGBA32F; + } + else if (qualifierType == "rgba16f") + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + qualifier.imageInternalFormat = EiifRGBA16F; + } + else if (qualifierType == "r32f") + { + if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage)) + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + } + qualifier.imageInternalFormat = EiifR32F; + } + else if (qualifierType == "rgba8") + { + if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage)) + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + } + qualifier.imageInternalFormat = EiifRGBA8; + } + else if (qualifierType == "rgba8_snorm") + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + qualifier.imageInternalFormat = EiifRGBA8_SNORM; + } + else if (qualifierType == "rgba32i") + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + qualifier.imageInternalFormat = EiifRGBA32I; + } + else if (qualifierType == "rgba16i") + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + qualifier.imageInternalFormat = EiifRGBA16I; + } + else if (qualifierType == "rgba8i") + { + if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage)) + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + } + qualifier.imageInternalFormat = EiifRGBA8I; + } + else if (qualifierType == "r32i") + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + qualifier.imageInternalFormat = EiifR32I; + } + else if (qualifierType == "rgba32ui") + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + qualifier.imageInternalFormat = EiifRGBA32UI; + } + else if (qualifierType == "rgba16ui") + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + qualifier.imageInternalFormat = EiifRGBA16UI; + } + else if (qualifierType == "rgba8ui") + { + if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage)) + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + } + qualifier.imageInternalFormat = EiifRGBA8UI; + } + else if (qualifierType == "r32ui") + { + if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage)) + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + } + qualifier.imageInternalFormat = EiifR32UI; + } + else if (mShaderType == GL_GEOMETRY_SHADER_EXT && + (mShaderVersion >= 320 || + (checkCanUseOneOfExtensions( + qualifierTypeLine, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}) && + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310)))) + { + if (qualifierType == "points") + { + qualifier.primitiveType = EptPoints; + } + else if (qualifierType == "lines") + { + qualifier.primitiveType = EptLines; + } + else if (qualifierType == "lines_adjacency") + { + qualifier.primitiveType = EptLinesAdjacency; + } + else if (qualifierType == "triangles") + { + qualifier.primitiveType = EptTriangles; + } + else if (qualifierType == "triangles_adjacency") + { + qualifier.primitiveType = EptTrianglesAdjacency; + } + else if (qualifierType == "line_strip") + { + qualifier.primitiveType = EptLineStrip; + } + else if (qualifierType == "triangle_strip") + { + qualifier.primitiveType = EptTriangleStrip; + } + else + { + error(qualifierTypeLine, "invalid layout qualifier", qualifierType); + } + } + else if (mShaderType == GL_TESS_EVALUATION_SHADER_EXT && + (mShaderVersion >= 320 || + (checkCanUseExtension(qualifierTypeLine, TExtension::EXT_tessellation_shader) && + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310)))) + { + if (qualifierType == "triangles") + { + qualifier.tesPrimitiveType = EtetTriangles; + } + else if (qualifierType == "quads") + { + qualifier.tesPrimitiveType = EtetQuads; + } + else if (qualifierType == "isolines") + { + qualifier.tesPrimitiveType = EtetIsolines; + } + else if (qualifierType == "equal_spacing") + { + qualifier.tesVertexSpacingType = EtetEqualSpacing; + } + else if (qualifierType == "fractional_even_spacing") + { + qualifier.tesVertexSpacingType = EtetFractionalEvenSpacing; + } + else if (qualifierType == "fractional_odd_spacing") + { + qualifier.tesVertexSpacingType = EtetFractionalOddSpacing; + } + else if (qualifierType == "cw") + { + qualifier.tesOrderingType = EtetCw; + } + else if (qualifierType == "ccw") + { + qualifier.tesOrderingType = EtetCcw; + } + else if (qualifierType == "point_mode") + { + qualifier.tesPointType = EtetPointMode; + } + else + { + error(qualifierTypeLine, "invalid layout qualifier", qualifierType); + } + } + else if (mShaderType == GL_FRAGMENT_SHADER) + { + if (qualifierType == "noncoherent") + { + if (checkCanUseOneOfExtensions( + qualifierTypeLine, + std::array{ + {TExtension::EXT_shader_framebuffer_fetch, + TExtension::EXT_shader_framebuffer_fetch_non_coherent}})) + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 100); + qualifier.noncoherent = true; + } + } + else if (qualifierType == "blend_support_multiply") + { + AddAdvancedBlendEquation(gl::BlendEquationType::Multiply, &qualifier); + } + else if (qualifierType == "blend_support_screen") + { + AddAdvancedBlendEquation(gl::BlendEquationType::Screen, &qualifier); + } + else if (qualifierType == "blend_support_overlay") + { + AddAdvancedBlendEquation(gl::BlendEquationType::Overlay, &qualifier); + } + else if (qualifierType == "blend_support_darken") + { + AddAdvancedBlendEquation(gl::BlendEquationType::Darken, &qualifier); + } + else if (qualifierType == "blend_support_lighten") + { + AddAdvancedBlendEquation(gl::BlendEquationType::Lighten, &qualifier); + } + else if (qualifierType == "blend_support_colordodge") + { + AddAdvancedBlendEquation(gl::BlendEquationType::Colordodge, &qualifier); + } + else if (qualifierType == "blend_support_colorburn") + { + AddAdvancedBlendEquation(gl::BlendEquationType::Colorburn, &qualifier); + } + else if (qualifierType == "blend_support_hardlight") + { + AddAdvancedBlendEquation(gl::BlendEquationType::Hardlight, &qualifier); + } + else if (qualifierType == "blend_support_softlight") + { + AddAdvancedBlendEquation(gl::BlendEquationType::Softlight, &qualifier); + } + else if (qualifierType == "blend_support_difference") + { + AddAdvancedBlendEquation(gl::BlendEquationType::Difference, &qualifier); + } + else if (qualifierType == "blend_support_exclusion") + { + AddAdvancedBlendEquation(gl::BlendEquationType::Exclusion, &qualifier); + } + else if (qualifierType == "blend_support_hsl_hue") + { + AddAdvancedBlendEquation(gl::BlendEquationType::HslHue, &qualifier); + } + else if (qualifierType == "blend_support_hsl_saturation") + { + AddAdvancedBlendEquation(gl::BlendEquationType::HslSaturation, &qualifier); + } + else if (qualifierType == "blend_support_hsl_color") + { + AddAdvancedBlendEquation(gl::BlendEquationType::HslColor, &qualifier); + } + else if (qualifierType == "blend_support_hsl_luminosity") + { + AddAdvancedBlendEquation(gl::BlendEquationType::HslLuminosity, &qualifier); + } + else if (qualifierType == "blend_support_all_equations") + { + qualifier.advancedBlendEquations.setAll(); + } + else + { + error(qualifierTypeLine, "invalid layout qualifier", qualifierType); + } + + if (qualifier.advancedBlendEquations.any() && mShaderVersion < 320) + { + if (!checkCanUseExtension(qualifierTypeLine, TExtension::KHR_blend_equation_advanced)) + { + qualifier.advancedBlendEquations.reset(); + } + } + } + else + { + error(qualifierTypeLine, "invalid layout qualifier", qualifierType); + } + + return qualifier; +} + +void TParseContext::parseLocalSize(const ImmutableString &qualifierType, + const TSourceLoc &qualifierTypeLine, + int intValue, + const TSourceLoc &intValueLine, + const std::string &intValueString, + size_t index, + sh::WorkGroupSize *localSize) +{ + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + if (intValue < 1) + { + std::stringstream reasonStream = sh::InitializeStream(); + reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive"; + std::string reason = reasonStream.str(); + error(intValueLine, reason.c_str(), intValueString.c_str()); + } + (*localSize)[index] = intValue; +} + +void TParseContext::parseNumViews(int intValue, + const TSourceLoc &intValueLine, + const std::string &intValueString, + int *numViews) +{ + // This error is only specified in WebGL, but tightens unspecified behavior in the native + // specification. + if (intValue < 1) + { + error(intValueLine, "out of range: num_views must be positive", intValueString.c_str()); + } + *numViews = intValue; +} + +void TParseContext::parseInvocations(int intValue, + const TSourceLoc &intValueLine, + const std::string &intValueString, + int *numInvocations) +{ + // Although SPEC isn't clear whether invocations can be less than 1, we add this limit because + // it doesn't make sense to accept invocations <= 0. + if (intValue < 1 || intValue > mMaxGeometryShaderInvocations) + { + error(intValueLine, + "out of range: invocations must be in the range of [1, " + "MAX_GEOMETRY_SHADER_INVOCATIONS_OES]", + intValueString.c_str()); + } + else + { + *numInvocations = intValue; + } +} + +void TParseContext::parseMaxVertices(int intValue, + const TSourceLoc &intValueLine, + const std::string &intValueString, + int *maxVertices) +{ + // Although SPEC isn't clear whether max_vertices can be less than 0, we add this limit because + // it doesn't make sense to accept max_vertices < 0. + if (intValue < 0 || intValue > mMaxGeometryShaderMaxVertices) + { + error( + intValueLine, + "out of range: max_vertices must be in the range of [0, gl_MaxGeometryOutputVertices]", + intValueString.c_str()); + } + else + { + *maxVertices = intValue; + } +} + +void TParseContext::parseVertices(int intValue, + const TSourceLoc &intValueLine, + const std::string &intValueString, + int *vertices) +{ + if (intValue < 1 || intValue > mMaxPatchVertices) + { + error(intValueLine, + "out of range : vertices must be in the range of [1, gl_MaxPatchVertices]", + intValueString.c_str()); + } + else + { + *vertices = intValue; + } +} + +void TParseContext::parseIndexLayoutQualifier(int intValue, + const TSourceLoc &intValueLine, + const std::string &intValueString, + int *index) +{ + // EXT_blend_func_extended specifies that most validation should happen at link time, but since + // we're validating output variable locations at compile time, it makes sense to validate that + // index is 0 or 1 also at compile time. Also since we use "-1" as a placeholder for unspecified + // index, we can't accept it here. + if (intValue < 0 || intValue > 1) + { + error(intValueLine, "out of range: index layout qualifier can only be 0 or 1", + intValueString.c_str()); + } + else + { + *index = intValue; + } +} + +TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qualifierType, + const TSourceLoc &qualifierTypeLine, + int intValue, + const TSourceLoc &intValueLine) +{ + TLayoutQualifier qualifier = TLayoutQualifier::Create(); + + std::string intValueString = Str(intValue); + + if (qualifierType == "location") + { + // must check that location is non-negative + if (intValue < 0) + { + error(intValueLine, "out of range: location must be non-negative", + intValueString.c_str()); + } + else + { + qualifier.location = intValue; + qualifier.locationsSpecified = 1; + } + } + else if (qualifierType == "binding") + { + if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage)) + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + } + if (intValue < 0) + { + error(intValueLine, "out of range: binding must be non-negative", + intValueString.c_str()); + } + else + { + qualifier.binding = intValue; + } + } + else if (qualifierType == "offset") + { + checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); + if (intValue < 0) + { + error(intValueLine, "out of range: offset must be non-negative", + intValueString.c_str()); + } + else + { + qualifier.offset = intValue; + } + } + else if (qualifierType == "local_size_x") + { + parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u, + &qualifier.localSize); + } + else if (qualifierType == "local_size_y") + { + parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u, + &qualifier.localSize); + } + else if (qualifierType == "local_size_z") + { + parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u, + &qualifier.localSize); + } + else if (qualifierType == "num_views" && mShaderType == GL_VERTEX_SHADER) + { + if (checkCanUseOneOfExtensions( + qualifierTypeLine, std::array{ + {TExtension::OVR_multiview, TExtension::OVR_multiview2}})) + { + parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews); + } + } + else if (qualifierType == "invocations" && mShaderType == GL_GEOMETRY_SHADER_EXT && + (mShaderVersion >= 320 || + checkCanUseOneOfExtensions( + qualifierTypeLine, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}))) + { + parseInvocations(intValue, intValueLine, intValueString, &qualifier.invocations); + } + else if (qualifierType == "max_vertices" && mShaderType == GL_GEOMETRY_SHADER_EXT && + (mShaderVersion >= 320 || + checkCanUseOneOfExtensions( + qualifierTypeLine, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}))) + { + parseMaxVertices(intValue, intValueLine, intValueString, &qualifier.maxVertices); + } + else if (qualifierType == "index" && mShaderType == GL_FRAGMENT_SHADER && + checkCanUseExtension(qualifierTypeLine, TExtension::EXT_blend_func_extended)) + { + parseIndexLayoutQualifier(intValue, intValueLine, intValueString, &qualifier.index); + } + else if (qualifierType == "vertices" && mShaderType == GL_TESS_CONTROL_SHADER_EXT && + (mShaderVersion >= 320 || + checkCanUseExtension(qualifierTypeLine, TExtension::EXT_tessellation_shader))) + { + parseVertices(intValue, intValueLine, intValueString, &qualifier.vertices); + } + else + { + error(qualifierTypeLine, "invalid layout qualifier", qualifierType); + } + + return qualifier; +} + +TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc) +{ + return new TTypeQualifierBuilder( + new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc), + mShaderVersion); +} + +TStorageQualifierWrapper *TParseContext::parseGlobalStorageQualifier(TQualifier qualifier, + const TSourceLoc &loc) +{ + checkIsAtGlobalLevel(loc, getQualifierString(qualifier)); + return new TStorageQualifierWrapper(qualifier, loc); +} + +TStorageQualifierWrapper *TParseContext::parseVaryingQualifier(const TSourceLoc &loc) +{ + if (getShaderType() == GL_VERTEX_SHADER) + { + return parseGlobalStorageQualifier(EvqVaryingOut, loc); + } + return parseGlobalStorageQualifier(EvqVaryingIn, loc); +} + +TStorageQualifierWrapper *TParseContext::parseInQualifier(const TSourceLoc &loc) +{ + if (declaringFunction()) + { + return new TStorageQualifierWrapper(EvqParamIn, loc); + } + + switch (getShaderType()) + { + case GL_VERTEX_SHADER: + { + if (mShaderVersion < 300 && !anyMultiviewExtensionAvailable() && + !IsDesktopGLSpec(mShaderSpec)) + { + error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in"); + } + return new TStorageQualifierWrapper(EvqVertexIn, loc); + } + case GL_FRAGMENT_SHADER: + { + if (mShaderVersion < 300 && !IsDesktopGLSpec(mShaderSpec)) + { + error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in"); + } + return new TStorageQualifierWrapper(EvqFragmentIn, loc); + } + case GL_COMPUTE_SHADER: + { + return new TStorageQualifierWrapper(EvqComputeIn, loc); + } + case GL_GEOMETRY_SHADER: + { + return new TStorageQualifierWrapper(EvqGeometryIn, loc); + } + case GL_TESS_CONTROL_SHADER: + { + return new TStorageQualifierWrapper(EvqTessControlIn, loc); + } + case GL_TESS_EVALUATION_SHADER: + { + return new TStorageQualifierWrapper(EvqTessEvaluationIn, loc); + } + default: + { + UNREACHABLE(); + return new TStorageQualifierWrapper(EvqLast, loc); + } + } +} + +TStorageQualifierWrapper *TParseContext::parseOutQualifier(const TSourceLoc &loc) +{ + if (declaringFunction()) + { + return new TStorageQualifierWrapper(EvqParamOut, loc); + } + switch (getShaderType()) + { + case GL_VERTEX_SHADER: + { + if (mShaderVersion < 300 && !IsDesktopGLSpec(mShaderSpec)) + { + error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out"); + } + return new TStorageQualifierWrapper(EvqVertexOut, loc); + } + case GL_FRAGMENT_SHADER: + { + if (mShaderVersion < 300 && !IsDesktopGLSpec(mShaderSpec)) + { + error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out"); + } + return new TStorageQualifierWrapper(EvqFragmentOut, loc); + } + case GL_COMPUTE_SHADER: + { + error(loc, "storage qualifier isn't supported in compute shaders", "out"); + return new TStorageQualifierWrapper(EvqParamOut, loc); + } + case GL_GEOMETRY_SHADER_EXT: + { + return new TStorageQualifierWrapper(EvqGeometryOut, loc); + } + case GL_TESS_CONTROL_SHADER_EXT: + { + return new TStorageQualifierWrapper(EvqTessControlOut, loc); + } + case GL_TESS_EVALUATION_SHADER_EXT: + { + return new TStorageQualifierWrapper(EvqTessEvaluationOut, loc); + } + default: + { + UNREACHABLE(); + return new TStorageQualifierWrapper(EvqLast, loc); + } + } +} + +TStorageQualifierWrapper *TParseContext::parseInOutQualifier(const TSourceLoc &loc) +{ + if (!declaringFunction()) + { + if (mShaderVersion < 300 && !IsDesktopGLSpec(mShaderSpec)) + { + error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "inout"); + } + + if (getShaderType() != GL_FRAGMENT_SHADER) + { + error(loc, "storage qualifier isn't supported in non-fragment shaders", "inout"); + } + + if (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) || + isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent)) + { + return new TStorageQualifierWrapper(EvqFragmentInOut, loc); + } + + error(loc, + "invalid qualifier: can be used with either function parameters or the variables for " + "fetching input attachment data", + "inout"); + } + return new TStorageQualifierWrapper(EvqParamInOut, loc); +} + +TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, + TLayoutQualifier rightQualifier, + const TSourceLoc &rightQualifierLocation) +{ + return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation, + mDiagnostics); +} + +TDeclarator *TParseContext::parseStructDeclarator(const ImmutableString &identifier, + const TSourceLoc &loc) +{ + return new TDeclarator(identifier, loc); +} + +TDeclarator *TParseContext::parseStructArrayDeclarator(const ImmutableString &identifier, + const TSourceLoc &loc, + const TVector *arraySizes) +{ + return new TDeclarator(identifier, arraySizes, loc); +} + +void TParseContext::checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin, + const TFieldList::const_iterator end, + const ImmutableString &name, + const TSourceLoc &location) +{ + for (auto fieldIter = begin; fieldIter != end; ++fieldIter) + { + if ((*fieldIter)->name() == name) + { + error(location, "duplicate field name in structure", name); + } + } +} + +TFieldList *TParseContext::addStructFieldList(TFieldList *fields, const TSourceLoc &location) +{ + for (TFieldList::const_iterator fieldIter = fields->begin(); fieldIter != fields->end(); + ++fieldIter) + { + checkDoesNotHaveDuplicateFieldName(fields->begin(), fieldIter, (*fieldIter)->name(), + location); + } + return fields; +} + +TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields, + const TFieldList *newlyAddedFields, + const TSourceLoc &location) +{ + for (TField *field : *newlyAddedFields) + { + checkDoesNotHaveDuplicateFieldName(processedFields->begin(), processedFields->end(), + field->name(), location); + processedFields->push_back(field); + } + return processedFields; +} + +TFieldList *TParseContext::addStructDeclaratorListWithQualifiers( + const TTypeQualifierBuilder &typeQualifierBuilder, + TPublicType *typeSpecifier, + const TDeclaratorList *declaratorList) +{ + TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); + + typeSpecifier->qualifier = typeQualifier.qualifier; + typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier; + typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier; + typeSpecifier->invariant = typeQualifier.invariant; + typeSpecifier->precise = typeQualifier.precise; + if (typeQualifier.precision != EbpUndefined) + { + typeSpecifier->precision = typeQualifier.precision; + } + return addStructDeclaratorList(*typeSpecifier, declaratorList); +} + +TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier, + const TDeclaratorList *declaratorList) +{ + checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision, + typeSpecifier.getBasicType()); + + checkIsNonVoid(typeSpecifier.getLine(), (*declaratorList)[0]->name(), + typeSpecifier.getBasicType()); + + checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier); + checkEarlyFragmentTestsIsNotSpecified(typeSpecifier.getLine(), + typeSpecifier.layoutQualifier.earlyFragmentTests); + checkNoncoherentIsNotSpecified(typeSpecifier.getLine(), + typeSpecifier.layoutQualifier.noncoherent); + + TFieldList *fieldList = new TFieldList(); + + for (const TDeclarator *declarator : *declaratorList) + { + TType *type = new TType(typeSpecifier); + if (declarator->isArray()) + { + // Don't allow arrays of arrays in ESSL < 3.10. + checkArrayElementIsNotArray(typeSpecifier.getLine(), typeSpecifier); + type->makeArrays(*declarator->arraySizes()); + } + + SymbolType symbolType = SymbolType::UserDefined; + if (declarator->name() == "gl_Position" || declarator->name() == "gl_PointSize" || + declarator->name() == "gl_ClipDistance" || declarator->name() == "gl_CullDistance") + { + symbolType = SymbolType::BuiltIn; + } + else + { + checkIsNotReserved(typeSpecifier.getLine(), declarator->name()); + } + TField *field = new TField(type, declarator->name(), declarator->line(), symbolType); + checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *field); + fieldList->push_back(field); + } + + return fieldList; +} + +TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine, + const TSourceLoc &nameLine, + const ImmutableString &structName, + TFieldList *fieldList) +{ + SymbolType structSymbolType = SymbolType::UserDefined; + if (structName.empty()) + { + structSymbolType = SymbolType::Empty; + } + TStructure *structure = new TStructure(&symbolTable, structName, fieldList, structSymbolType); + + // Store a bool in the struct if we're at global scope, to allow us to + // skip the local struct scoping workaround in HLSL. + structure->setAtGlobalScope(symbolTable.atGlobalLevel()); + + if (structSymbolType != SymbolType::Empty) + { + checkIsNotReserved(nameLine, structName); + if (!symbolTable.declare(structure)) + { + error(nameLine, "redefinition of a struct", structName); + } + } + + // ensure we do not specify any storage qualifiers on the struct members + for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++) + { + TField &field = *(*fieldList)[typeListIndex]; + const TQualifier qualifier = field.type()->getQualifier(); + switch (qualifier) + { + case EvqGlobal: + case EvqTemporary: + break; + default: + error(field.line(), "invalid qualifier on struct member", + getQualifierString(qualifier)); + break; + } + if (field.type()->isInvariant()) + { + error(field.line(), "invalid qualifier on struct member", "invariant"); + } + // ESSL 3.10 section 4.1.8 -- atomic_uint or images are not allowed as structure member. + // ANGLE_shader_pixel_local_storage also disallows PLS as struct members. + if (IsImage(field.type()->getBasicType()) || + IsAtomicCounter(field.type()->getBasicType()) || + IsPixelLocal(field.type()->getBasicType())) + { + error(field.line(), "disallowed type in struct", field.type()->getBasicString()); + } + + checkIsNotUnsizedArray(field.line(), "array members of structs must specify a size", + field.name(), field.type()); + + checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line()); + + checkIndexIsNotSpecified(field.line(), field.type()->getLayoutQualifier().index); + + checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding); + + checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier()); + } + + TTypeSpecifierNonArray typeSpecifierNonArray; + typeSpecifierNonArray.initializeStruct(structure, true, structLine); + exitStructDeclaration(); + + return typeSpecifierNonArray; +} + +TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, + TIntermBlock *statementList, + const TSourceLoc &loc) +{ + TBasicType switchType = init->getBasicType(); + if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() || + init->isVector()) + { + error(init->getLine(), "init-expression in a switch statement must be a scalar integer", + "switch"); + return nullptr; + } + + ASSERT(statementList); + if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc)) + { + ASSERT(mDiagnostics->numErrors() > 0); + return nullptr; + } + + markStaticReadIfSymbol(init); + TIntermSwitch *node = new TIntermSwitch(init, statementList); + node->setLine(loc); + return node; +} + +TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc) +{ + if (mSwitchNestingLevel == 0) + { + error(loc, "case labels need to be inside switch statements", "case"); + return nullptr; + } + if (condition == nullptr) + { + error(loc, "case label must have a condition", "case"); + return nullptr; + } + if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) || + condition->isMatrix() || condition->isArray() || condition->isVector()) + { + error(condition->getLine(), "case label must be a scalar integer", "case"); + } + TIntermConstantUnion *conditionConst = condition->getAsConstantUnion(); + // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be + // safe against corner cases we still check for conditionConst. Some interpretations of the + // spec have allowed constant expressions with side effects - like array length() method on a + // non-constant array. + if (condition->getQualifier() != EvqConst || conditionConst == nullptr) + { + error(condition->getLine(), "case label must be constant", "case"); + } + TIntermCase *node = new TIntermCase(condition); + node->setLine(loc); + return node; +} + +TIntermCase *TParseContext::addDefault(const TSourceLoc &loc) +{ + if (mSwitchNestingLevel == 0) + { + error(loc, "default labels need to be inside switch statements", "default"); + return nullptr; + } + TIntermCase *node = new TIntermCase(nullptr); + node->setLine(loc); + return node; +} + +TIntermTyped *TParseContext::createUnaryMath(TOperator op, + TIntermTyped *child, + const TSourceLoc &loc, + const TFunction *func) +{ + ASSERT(child != nullptr); + + switch (op) + { + case EOpLogicalNot: + if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() || + child->isVector()) + { + unaryOpError(loc, GetOperatorString(op), child->getType()); + return nullptr; + } + break; + case EOpBitwiseNot: + if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) || + child->isMatrix() || child->isArray()) + { + unaryOpError(loc, GetOperatorString(op), child->getType()); + return nullptr; + } + break; + case EOpPostIncrement: + case EOpPreIncrement: + case EOpPostDecrement: + case EOpPreDecrement: + case EOpNegative: + case EOpPositive: + if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() || + child->getBasicType() == EbtBool || child->isArray() || + child->getBasicType() == EbtVoid || IsOpaqueType(child->getBasicType())) + { + unaryOpError(loc, GetOperatorString(op), child->getType()); + return nullptr; + } + break; + // Operators for math built-ins are already type checked against their prototype. + default: + break; + } + + if (child->getMemoryQualifier().writeonly) + { + const char *opStr = + BuiltInGroup::IsBuiltIn(op) ? func->name().data() : GetOperatorString(op); + unaryOpError(loc, opStr, child->getType()); + return nullptr; + } + + markStaticReadIfSymbol(child); + TIntermUnary *node = new TIntermUnary(op, child, func); + node->setLine(loc); + + return node->fold(mDiagnostics); +} + +TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc) +{ + ASSERT(op != EOpNull); + TIntermTyped *node = createUnaryMath(op, child, loc, nullptr); + if (node == nullptr) + { + return child; + } + return node; +} + +TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op, + TIntermTyped *child, + const TSourceLoc &loc) +{ + checkCanBeLValue(loc, GetOperatorString(op), child); + return addUnaryMath(op, child, loc); +} + +TIntermTyped *TParseContext::expressionOrFoldedResult(TIntermTyped *expression) +{ + // If we can, we should return the folded version of the expression for subsequent parsing. This + // enables folding the containing expression during parsing as well, instead of the separate + // FoldExpressions() step where folding nested expressions requires multiple full AST + // traversals. + + // Even if folding fails the fold() functions return some node representing the expression, + // typically the original node. So "folded" can be assumed to be non-null. + TIntermTyped *folded = expression->fold(mDiagnostics); + ASSERT(folded != nullptr); + if (folded->getQualifier() == expression->getQualifier()) + { + // We need this expression to have the correct qualifier when validating the consuming + // expression. So we can only return the folded node from here in case it has the same + // qualifier as the original expression. In this kind of a cases the qualifier of the folded + // node is EvqConst, whereas the qualifier of the expression is EvqTemporary: + // 1. (true ? 1.0 : non_constant) + // 2. (non_constant, 1.0) + return folded; + } + return expression; +} + +bool TParseContext::binaryOpCommonCheck(TOperator op, + TIntermTyped *left, + TIntermTyped *right, + const TSourceLoc &loc) +{ + // Check opaque types are not allowed to be operands in expressions other than array indexing + // and structure member selection. + if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType())) + { + switch (op) + { + case EOpIndexDirect: + case EOpIndexIndirect: + break; + + default: + ASSERT(op != EOpIndexDirectStruct); + error(loc, "Invalid operation for variables with an opaque type", + GetOperatorString(op)); + return false; + } + } + + if (right->getMemoryQualifier().writeonly) + { + error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op)); + return false; + } + + if (left->getMemoryQualifier().writeonly) + { + switch (op) + { + case EOpAssign: + case EOpInitialize: + case EOpIndexDirect: + case EOpIndexIndirect: + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: + break; + default: + error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op)); + return false; + } + } + + if (left->getType().getStruct() || right->getType().getStruct()) + { + switch (op) + { + case EOpIndexDirectStruct: + ASSERT(left->getType().getStruct()); + break; + case EOpEqual: + case EOpNotEqual: + case EOpAssign: + case EOpInitialize: + if (left->getType() != right->getType()) + { + return false; + } + break; + default: + error(loc, "Invalid operation for structs", GetOperatorString(op)); + return false; + } + } + + if (left->isInterfaceBlock() || right->isInterfaceBlock()) + { + switch (op) + { + case EOpIndexDirectInterfaceBlock: + ASSERT(left->getType().getInterfaceBlock()); + break; + default: + error(loc, "Invalid operation for interface blocks", GetOperatorString(op)); + return false; + } + } + + if (left->isArray() != right->isArray()) + { + error(loc, "array / non-array mismatch", GetOperatorString(op)); + return false; + } + + if (left->isArray()) + { + ASSERT(right->isArray()); + if (mShaderVersion < 300) + { + error(loc, "Invalid operation for arrays", GetOperatorString(op)); + return false; + } + + switch (op) + { + case EOpEqual: + case EOpNotEqual: + case EOpAssign: + case EOpInitialize: + break; + default: + error(loc, "Invalid operation for arrays", GetOperatorString(op)); + return false; + } + // At this point, size of implicitly sized arrays should be resolved. + if (left->getType().getArraySizes() != right->getType().getArraySizes()) + { + error(loc, "array size mismatch", GetOperatorString(op)); + return false; + } + } + + // Check ops which require integer / ivec parameters + bool isBitShift = false; + switch (op) + { + case EOpBitShiftLeft: + case EOpBitShiftRight: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + // Unsigned can be bit-shifted by signed and vice versa, but we need to + // check that the basic type is an integer type. + isBitShift = true; + if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType())) + { + return false; + } + break; + case EOpBitwiseAnd: + case EOpBitwiseXor: + case EOpBitwiseOr: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: + // It is enough to check the type of only one operand, since later it + // is checked that the operand types match. + if (!IsInteger(left->getBasicType())) + { + return false; + } + break; + default: + break; + } + + ImplicitTypeConversion conversion = GetConversion(left->getBasicType(), right->getBasicType()); + + // Implicit type casting only supported for GL shaders + if (!isBitShift && conversion != ImplicitTypeConversion::Same && + (!IsDesktopGLSpec(mShaderSpec) || !IsValidImplicitConversion(conversion, op))) + { + return false; + } + + // Check that: + // 1. Type sizes match exactly on ops that require that. + // 2. Restrictions for structs that contain arrays or samplers are respected. + // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected. + switch (op) + { + case EOpAssign: + case EOpInitialize: + case EOpEqual: + case EOpNotEqual: + // ESSL 1.00 sections 5.7, 5.8, 5.9 + if (mShaderVersion < 300 && left->getType().isStructureContainingArrays()) + { + error(loc, "undefined operation for structs containing arrays", + GetOperatorString(op)); + return false; + } + // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7, + // we interpret the spec so that this extends to structs containing samplers, + // similarly to ESSL 1.00 spec. + if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) && + left->getType().isStructureContainingSamplers()) + { + error(loc, "undefined operation for structs containing samplers", + GetOperatorString(op)); + return false; + } + + if ((left->getNominalSize() != right->getNominalSize()) || + (left->getSecondarySize() != right->getSecondarySize())) + { + error(loc, "dimension mismatch", GetOperatorString(op)); + return false; + } + break; + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if (!left->isScalar() || !right->isScalar()) + { + error(loc, "comparison operator only defined for scalars", GetOperatorString(op)); + return false; + } + break; + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpIMod: + case EOpBitShiftLeft: + case EOpBitShiftRight: + case EOpBitwiseAnd: + case EOpBitwiseXor: + case EOpBitwiseOr: + case EOpAddAssign: + case EOpSubAssign: + case EOpDivAssign: + case EOpIModAssign: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: + if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix())) + { + return false; + } + + // Are the sizes compatible? + if (left->getNominalSize() != right->getNominalSize() || + left->getSecondarySize() != right->getSecondarySize()) + { + // If the nominal sizes of operands do not match: + // One of them must be a scalar. + if (!left->isScalar() && !right->isScalar()) + return false; + + // In the case of compound assignment other than multiply-assign, + // the right side needs to be a scalar. Otherwise a vector/matrix + // would be assigned to a scalar. A scalar can't be shifted by a + // vector either. + if (!right->isScalar() && + (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight)) + return false; + } + break; + default: + break; + } + + return true; +} + +bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op, + const TType &left, + const TType &right) +{ + switch (op) + { + case EOpMul: + case EOpMulAssign: + return left.getNominalSize() == right.getNominalSize() && + left.getSecondarySize() == right.getSecondarySize(); + case EOpVectorTimesScalar: + return true; + case EOpVectorTimesScalarAssign: + ASSERT(!left.isMatrix() && !right.isMatrix()); + return left.isVector() && !right.isVector(); + case EOpVectorTimesMatrix: + return left.getNominalSize() == right.getRows(); + case EOpVectorTimesMatrixAssign: + ASSERT(!left.isMatrix() && right.isMatrix()); + return left.isVector() && left.getNominalSize() == right.getRows() && + left.getNominalSize() == right.getCols(); + case EOpMatrixTimesVector: + return left.getCols() == right.getNominalSize(); + case EOpMatrixTimesScalar: + return true; + case EOpMatrixTimesScalarAssign: + ASSERT(left.isMatrix() && !right.isMatrix()); + return !right.isVector(); + case EOpMatrixTimesMatrix: + return left.getCols() == right.getRows(); + case EOpMatrixTimesMatrixAssign: + ASSERT(left.isMatrix() && right.isMatrix()); + // We need to check two things: + // 1. The matrix multiplication step is valid. + // 2. The result will have the same number of columns as the lvalue. + return left.getCols() == right.getRows() && left.getCols() == right.getCols(); + + default: + UNREACHABLE(); + return false; + } +} + +TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op, + TIntermTyped *left, + TIntermTyped *right, + const TSourceLoc &loc) +{ + if (!binaryOpCommonCheck(op, left, right, loc)) + return nullptr; + + switch (op) + { + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + break; + case EOpLogicalOr: + case EOpLogicalXor: + case EOpLogicalAnd: + ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() && + !right->getType().getStruct()); + if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar()) + { + return nullptr; + } + // Basic types matching should have been already checked. + ASSERT(right->getBasicType() == EbtBool); + break; + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpMul: + ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() && + !right->getType().getStruct()); + if (left->getBasicType() == EbtBool) + { + return nullptr; + } + break; + case EOpIMod: + ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() && + !right->getType().getStruct()); + // Note that this is only for the % operator, not for mod() + if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat) + { + return nullptr; + } + break; + default: + break; + } + + if (op == EOpMul) + { + op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType()); + if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType())) + { + return nullptr; + } + } + + TIntermBinary *node = new TIntermBinary(op, left, right); + ASSERT(op != EOpAssign); + markStaticReadIfSymbol(left); + markStaticReadIfSymbol(right); + node->setLine(loc); + return expressionOrFoldedResult(node); +} + +TIntermTyped *TParseContext::addBinaryMath(TOperator op, + TIntermTyped *left, + TIntermTyped *right, + const TSourceLoc &loc) +{ + TIntermTyped *node = addBinaryMathInternal(op, left, right, loc); + if (node == 0) + { + binaryOpError(loc, GetOperatorString(op), left->getType(), right->getType()); + return left; + } + return node; +} + +TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op, + TIntermTyped *left, + TIntermTyped *right, + const TSourceLoc &loc) +{ + TIntermTyped *node = addBinaryMathInternal(op, left, right, loc); + if (node == nullptr) + { + binaryOpError(loc, GetOperatorString(op), left->getType(), right->getType()); + node = CreateBoolNode(false); + node->setLine(loc); + } + return node; +} + +TIntermTyped *TParseContext::addAssign(TOperator op, + TIntermTyped *left, + TIntermTyped *right, + const TSourceLoc &loc) +{ + checkCanBeLValue(loc, "assign", left); + TIntermBinary *node = nullptr; + if (binaryOpCommonCheck(op, left, right, loc)) + { + TIntermBinary *lValue = left->getAsBinaryNode(); + if ((lValue != nullptr) && + (lValue->getOp() == EOpIndexIndirect || lValue->getOp() == EOpIndexDirect) && + IsTessellationControlShaderOutput(mShaderType, lValue->getLeft()->getQualifier())) + { + checkTCSOutVarIndexIsValid(lValue, loc); + } + + if (op == EOpMulAssign) + { + op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType()); + if (isMultiplicationTypeCombinationValid(op, left->getType(), right->getType())) + { + node = new TIntermBinary(op, left, right); + } + } + else + { + node = new TIntermBinary(op, left, right); + } + } + if (node == nullptr) + { + assignError(loc, "assign", left->getType(), right->getType()); + return left; + } + if (op != EOpAssign) + { + markStaticReadIfSymbol(left); + } + markStaticReadIfSymbol(right); + node->setLine(loc); + return node; +} + +TIntermTyped *TParseContext::addComma(TIntermTyped *left, + TIntermTyped *right, + const TSourceLoc &loc) +{ + // WebGL2 section 5.26, the following results in an error: + // "Sequence operator applied to void, arrays, or structs containing arrays" + if (mShaderSpec == SH_WEBGL2_SPEC && + (left->isArray() || left->getBasicType() == EbtVoid || + left->getType().isStructureContainingArrays() || right->isArray() || + right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays())) + { + error(loc, + "sequence operator is not allowed for void, arrays, or structs containing arrays", + ","); + } + + TIntermBinary *commaNode = TIntermBinary::CreateComma(left, right, mShaderVersion); + markStaticReadIfSymbol(left); + markStaticReadIfSymbol(right); + commaNode->setLine(loc); + + return expressionOrFoldedResult(commaNode); +} + +TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc) +{ + switch (op) + { + case EOpContinue: + if (mLoopNestingLevel <= 0) + { + error(loc, "continue statement only allowed in loops", ""); + } + break; + case EOpBreak: + if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0) + { + error(loc, "break statement only allowed in loops and switch statements", ""); + } + break; + case EOpReturn: + if (mCurrentFunctionType->getBasicType() != EbtVoid) + { + error(loc, "non-void function must return a value", "return"); + } + if (mDeclaringMain) + { + errorIfPLSDeclared(loc, PLSIllegalOperations::ReturnFromMain); + } + break; + case EOpKill: + if (mShaderType != GL_FRAGMENT_SHADER) + { + error(loc, "discard supported in fragment shaders only", "discard"); + } + else + { + errorIfPLSDeclared(loc, PLSIllegalOperations::Discard); + } + mHasDiscard = true; + break; + default: + UNREACHABLE(); + break; + } + return addBranch(op, nullptr, loc); +} + +TIntermBranch *TParseContext::addBranch(TOperator op, + TIntermTyped *expression, + const TSourceLoc &loc) +{ + if (expression != nullptr) + { + markStaticReadIfSymbol(expression); + ASSERT(op == EOpReturn); + mFunctionReturnsValue = true; + if (mCurrentFunctionType->getBasicType() == EbtVoid) + { + error(loc, "void function cannot return a value", "return"); + } + else if (*mCurrentFunctionType != expression->getType()) + { + error(loc, "function return is not matching type:", "return"); + } + } + TIntermBranch *node = new TIntermBranch(op, expression); + node->setLine(loc); + return node; +} + +void TParseContext::appendStatement(TIntermBlock *block, TIntermNode *statement) +{ + if (statement != nullptr) + { + markStaticReadIfSymbol(statement); + block->appendStatement(statement); + } +} + +void TParseContext::checkTextureGather(TIntermAggregate *functionCall) +{ + const TOperator op = functionCall->getOp(); + const TFunction *func = functionCall->getFunction(); + if (BuiltInGroup::IsTextureGather(op)) + { + bool isTextureGatherOffsetOrOffsets = + BuiltInGroup::IsTextureGatherOffset(op) || BuiltInGroup::IsTextureGatherOffsets(op); + TIntermNode *componentNode = nullptr; + TIntermSequence *arguments = functionCall->getSequence(); + ASSERT(arguments->size() >= 2u && arguments->size() <= 4u); + const TIntermTyped *sampler = arguments->front()->getAsTyped(); + ASSERT(sampler != nullptr); + switch (sampler->getBasicType()) + { + case EbtSampler2D: + case EbtISampler2D: + case EbtUSampler2D: + case EbtSampler2DArray: + case EbtISampler2DArray: + case EbtUSampler2DArray: + if ((!isTextureGatherOffsetOrOffsets && arguments->size() == 3u) || + (isTextureGatherOffsetOrOffsets && arguments->size() == 4u)) + { + componentNode = arguments->back(); + } + break; + case EbtSamplerCube: + case EbtISamplerCube: + case EbtUSamplerCube: + case EbtSamplerCubeArray: + case EbtISamplerCubeArray: + case EbtUSamplerCubeArray: + ASSERT(!isTextureGatherOffsetOrOffsets); + if (arguments->size() == 3u) + { + componentNode = arguments->back(); + } + break; + case EbtSampler2DShadow: + case EbtSampler2DArrayShadow: + case EbtSamplerCubeShadow: + case EbtSamplerCubeArrayShadow: + break; + default: + UNREACHABLE(); + break; + } + if (componentNode) + { + const TIntermConstantUnion *componentConstantUnion = + componentNode->getAsConstantUnion(); + if (componentNode->getAsTyped()->getQualifier() != EvqConst || !componentConstantUnion) + { + error(functionCall->getLine(), "Texture component must be a constant expression", + func->name()); + } + else + { + int component = componentConstantUnion->getIConst(0); + if (component < 0 || component > 3) + { + error(functionCall->getLine(), "Component must be in the range [0;3]", + func->name()); + } + } + } + } +} + +void TParseContext::checkTextureOffset(TIntermAggregate *functionCall) +{ + const TOperator op = functionCall->getOp(); + const TFunction *func = functionCall->getFunction(); + TIntermNode *offset = nullptr; + TIntermSequence *arguments = functionCall->getSequence(); + + if (BuiltInGroup::IsTextureOffsetNoBias(op) || BuiltInGroup::IsTextureGatherOffsetNoComp(op) || + BuiltInGroup::IsTextureGatherOffsetsNoComp(op)) + { + offset = arguments->back(); + } + else if (BuiltInGroup::IsTextureOffsetBias(op) || BuiltInGroup::IsTextureGatherOffsetComp(op) || + BuiltInGroup::IsTextureGatherOffsetsComp(op)) + { + // A bias or comp parameter follows the offset parameter. + ASSERT(arguments->size() >= 3); + offset = (*arguments)[2]; + } + + // If not one of the above built-ins, there's nothing to do here. + if (offset == nullptr) + { + return; + } + + bool isTextureGatherOffset = BuiltInGroup::IsTextureGatherOffset(op); + bool isTextureGatherOffsets = BuiltInGroup::IsTextureGatherOffsets(op); + bool useTextureGatherOffsetConstraints = isTextureGatherOffset || isTextureGatherOffsets; + + int minOffsetValue = + useTextureGatherOffsetConstraints ? mMinProgramTextureGatherOffset : mMinProgramTexelOffset; + int maxOffsetValue = + useTextureGatherOffsetConstraints ? mMaxProgramTextureGatherOffset : mMaxProgramTexelOffset; + + if (isTextureGatherOffsets) + { + // If textureGatherOffsets, the offsets parameter is an array, which is expected as an + // aggregate constructor node or as a symbol node with a constant value. + TIntermAggregate *offsetAggregate = offset->getAsAggregate(); + TIntermSymbol *offsetSymbol = offset->getAsSymbolNode(); + + const TConstantUnion *offsetValues = offsetAggregate ? offsetAggregate->getConstantValue() + : offsetSymbol ? offsetSymbol->getConstantValue() + : nullptr; + + if (offsetValues == nullptr) + { + error(functionCall->getLine(), "Texture offsets must be a constant expression", + func->name()); + return; + } + + constexpr unsigned int kOffsetsCount = 4; + const TType &offsetType = + offsetAggregate != nullptr ? offsetAggregate->getType() : offsetSymbol->getType(); + if (offsetType.getNumArraySizes() != 1 || offsetType.getArraySizes()[0] != kOffsetsCount) + { + error(functionCall->getLine(), "Texture offsets must be an array of 4 elements", + func->name()); + return; + } + + size_t size = offsetType.getObjectSize() / kOffsetsCount; + for (unsigned int i = 0; i < kOffsetsCount; ++i) + { + checkSingleTextureOffset(offset->getLine(), &offsetValues[i * size], size, + minOffsetValue, maxOffsetValue); + } + } + else + { + // If textureOffset or textureGatherOffset, the offset is expected to be found as a constant + // union. + TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion(); + + // ES3.2 or ES3.1's EXT_gpu_shader5 allow non-const offsets to be passed to + // textureGatherOffset. + bool textureGatherOffsetMustBeConst = + mShaderVersion <= 310 && !isExtensionEnabled(TExtension::EXT_gpu_shader5); + + bool isOffsetConst = + offset->getAsTyped()->getQualifier() == EvqConst && offsetConstantUnion != nullptr; + bool offsetMustBeConst = !isTextureGatherOffset || textureGatherOffsetMustBeConst; + + if (!isOffsetConst && offsetMustBeConst) + { + error(functionCall->getLine(), "Texture offset must be a constant expression", + func->name()); + return; + } + + // We cannot verify non-constant offsets to textureGatherOffset. + if (offsetConstantUnion == nullptr) + { + ASSERT(!offsetMustBeConst); + return; + } + + size_t size = offsetConstantUnion->getType().getObjectSize(); + const TConstantUnion *values = offsetConstantUnion->getConstantValue(); + checkSingleTextureOffset(offset->getLine(), values, size, minOffsetValue, maxOffsetValue); + } +} + +void TParseContext::checkSingleTextureOffset(const TSourceLoc &line, + const TConstantUnion *values, + size_t size, + int minOffsetValue, + int maxOffsetValue) +{ + for (size_t i = 0u; i < size; ++i) + { + ASSERT(values[i].getType() == EbtInt); + int offsetValue = values[i].getIConst(); + if (offsetValue > maxOffsetValue || offsetValue < minOffsetValue) + { + std::stringstream tokenStream = sh::InitializeStream(); + tokenStream << offsetValue; + std::string token = tokenStream.str(); + error(line, "Texture offset value out of valid range", token.c_str()); + } + } +} + +void TParseContext::checkInterpolationFS(TIntermAggregate *functionCall) +{ + const TFunction *func = functionCall->getFunction(); + if (!BuiltInGroup::IsInterpolationFS(functionCall->getOp())) + { + return; + } + + TIntermTyped *arg0 = nullptr; + + if (functionCall->getAsAggregate()) + { + const TIntermSequence *argp = functionCall->getSequence(); + if (argp->size() > 0) + arg0 = (*argp)[0]->getAsTyped(); + } + else + { + assert(functionCall->getAsUnaryNode()); + arg0 = functionCall->getAsUnaryNode()->getOperand(); + } + + // Make sure the first argument is an interpolant, or an array element of an interpolant + if (!IsVaryingIn(arg0->getType().getQualifier())) + { + // It might still be an array element. + const TIntermTyped *base = FindLValueBase(arg0); + + if (base == nullptr || (!IsVaryingIn(base->getType().getQualifier()))) + error(arg0->getLine(), + "first argument must be an interpolant, or interpolant-array element", + func->name()); + } +} + +void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall) +{ + const TFunction *func = functionCall->getFunction(); + if (BuiltInGroup::IsAtomicMemory(functionCall->getOp())) + { + TIntermSequence *arguments = functionCall->getSequence(); + TIntermTyped *memNode = (*arguments)[0]->getAsTyped(); + + if (IsBufferOrSharedVariable(memNode)) + { + return; + } + + while (memNode->getAsBinaryNode() || memNode->getAsSwizzleNode()) + { + // Child 0 is "left" if binary, and the expression being swizzled if swizzle. + // Note: we don't need to check that the binary operation is one of EOp*Index*, as any + // other operation will result in a temp value which cannot be passed to this + // out/inout parameter anyway. + memNode = memNode->getChildNode(0)->getAsTyped(); + if (IsBufferOrSharedVariable(memNode)) + { + return; + } + } + + error(memNode->getLine(), + "The value passed to the mem argument of an atomic memory function does not " + "correspond to a buffer or shared variable.", + func->name()); + } +} + +// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers +void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall) +{ + const TOperator op = functionCall->getOp(); + + if (BuiltInGroup::IsImage(op)) + { + TIntermSequence *arguments = functionCall->getSequence(); + TIntermTyped *imageNode = (*arguments)[0]->getAsTyped(); + + const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier(); + + if (BuiltInGroup::IsImageStore(op)) + { + if (memoryQualifier.readonly) + { + error(imageNode->getLine(), + "'imageStore' cannot be used with images qualified as 'readonly'", + GetImageArgumentToken(imageNode)); + } + } + else if (BuiltInGroup::IsImageLoad(op)) + { + if (memoryQualifier.writeonly) + { + error(imageNode->getLine(), + "'imageLoad' cannot be used with images qualified as 'writeonly'", + GetImageArgumentToken(imageNode)); + } + } + else if (BuiltInGroup::IsImageAtomic(op)) + { + if (memoryQualifier.readonly) + { + error(imageNode->getLine(), + "'imageAtomic' cannot be used with images qualified as 'readonly'", + GetImageArgumentToken(imageNode)); + } + if (memoryQualifier.writeonly) + { + error(imageNode->getLine(), + "'imageAtomic' cannot be used with images qualified as 'writeonly'", + GetImageArgumentToken(imageNode)); + } + } + } +} + +// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters +void TParseContext::checkImageMemoryAccessForUserDefinedFunctions( + const TFunction *functionDefinition, + const TIntermAggregate *functionCall) +{ + ASSERT(functionCall->getOp() == EOpCallFunctionInAST); + + const TIntermSequence &arguments = *functionCall->getSequence(); + + ASSERT(functionDefinition->getParamCount() == arguments.size()); + + for (size_t i = 0; i < arguments.size(); ++i) + { + TIntermTyped *typedArgument = arguments[i]->getAsTyped(); + const TType &functionArgumentType = typedArgument->getType(); + const TType &functionParameterType = functionDefinition->getParam(i)->getType(); + ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType()); + + if (IsImage(functionArgumentType.getBasicType())) + { + const TMemoryQualifier &functionArgumentMemoryQualifier = + functionArgumentType.getMemoryQualifier(); + const TMemoryQualifier &functionParameterMemoryQualifier = + functionParameterType.getMemoryQualifier(); + if (functionArgumentMemoryQualifier.readonly && + !functionParameterMemoryQualifier.readonly) + { + error(functionCall->getLine(), + "Function call discards the 'readonly' qualifier from image", + GetImageArgumentToken(typedArgument)); + } + + if (functionArgumentMemoryQualifier.writeonly && + !functionParameterMemoryQualifier.writeonly) + { + error(functionCall->getLine(), + "Function call discards the 'writeonly' qualifier from image", + GetImageArgumentToken(typedArgument)); + } + + if (functionArgumentMemoryQualifier.coherent && + !functionParameterMemoryQualifier.coherent) + { + error(functionCall->getLine(), + "Function call discards the 'coherent' qualifier from image", + GetImageArgumentToken(typedArgument)); + } + + if (functionArgumentMemoryQualifier.volatileQualifier && + !functionParameterMemoryQualifier.volatileQualifier) + { + error(functionCall->getLine(), + "Function call discards the 'volatile' qualifier from image", + GetImageArgumentToken(typedArgument)); + } + } + } +} + +TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunctionLookup *fnCall, const TSourceLoc &loc) +{ + if (fnCall->thisNode() != nullptr) + { + return addMethod(fnCall, loc); + } + if (fnCall->isConstructor()) + { + return addConstructor(fnCall, loc); + } + return addNonConstructorFunctionCall(fnCall, loc); +} + +TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc) +{ + TIntermTyped *thisNode = fnCall->thisNode(); + // It's possible for the name pointer in the TFunction to be null in case it gets parsed as + // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS + // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead. + // So accessing fnCall->name() below is safe. + if (fnCall->name() != "length") + { + error(loc, "invalid method", fnCall->name()); + } + else if (!fnCall->arguments().empty()) + { + error(loc, "method takes no parameters", "length"); + } + else if (!thisNode->isArray()) + { + error(loc, "length can only be called on arrays", "length"); + } + else if (thisNode->getQualifier() == EvqPerVertexIn && + mGeometryShaderInputPrimitiveType == EptUndefined) + { + ASSERT(mShaderType == GL_GEOMETRY_SHADER_EXT); + error(loc, "missing input primitive declaration before calling length on gl_in", "length"); + } + else + { + TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode, nullptr); + markStaticReadIfSymbol(thisNode); + node->setLine(loc); + return node->fold(mDiagnostics); + } + return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst)); +} + +TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCall, + const TSourceLoc &loc) +{ + // First check whether the function has been hidden by a variable name or struct typename by + // using the symbol looked up in the lexical phase. If the function is not hidden, look for one + // with a matching argument list. + if (fnCall->symbol() != nullptr && !fnCall->symbol()->isFunction()) + { + error(loc, "function name expected", fnCall->name()); + } + else + { + // There are no inner functions, so it's enough to look for user-defined functions in the + // global scope. + const TSymbol *symbol = symbolTable.findGlobal(fnCall->getMangledName()); + + if (symbol == nullptr && IsDesktopGLSpec(mShaderSpec)) + { + // If using Desktop GL spec, need to check for implicit conversion + symbol = symbolTable.findGlobalWithConversion( + fnCall->getMangledNamesForImplicitConversions()); + } + + if (symbol != nullptr) + { + // A user-defined function - could be an overloaded built-in as well. + ASSERT(symbol->symbolType() == SymbolType::UserDefined); + const TFunction *fnCandidate = static_cast(symbol); + TIntermAggregate *callNode = + TIntermAggregate::CreateFunctionCall(*fnCandidate, &fnCall->arguments()); + callNode->setLine(loc); + checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode); + functionCallRValueLValueErrorCheck(fnCandidate, callNode); + return callNode; + } + + symbol = symbolTable.findBuiltIn(fnCall->getMangledName(), mShaderVersion); + + if (symbol == nullptr && IsDesktopGLSpec(mShaderSpec)) + { + // If using Desktop GL spec, need to check for implicit conversion + symbol = symbolTable.findBuiltInWithConversion( + fnCall->getMangledNamesForImplicitConversions(), mShaderVersion); + } + + if (symbol != nullptr) + { + // A built-in function. + ASSERT(symbol->symbolType() == SymbolType::BuiltIn); + const TFunction *fnCandidate = static_cast(symbol); + + if (!fnCandidate->extensions().empty() && + fnCandidate->extensions()[0] != TExtension::UNDEFINED) + { + checkCanUseOneOfExtensions(loc, fnCandidate->extensions()); + } + + // All function calls are mapped to a built-in operation. + TOperator op = fnCandidate->getBuiltInOp(); + if (BuiltInGroup::IsMath(op) && fnCandidate->getParamCount() == 1) + { + // Treat it like a built-in unary operator. + TIntermNode *unaryParamNode = fnCall->arguments().front(); + TIntermTyped *callNode = + createUnaryMath(op, unaryParamNode->getAsTyped(), loc, fnCandidate); + ASSERT(callNode != nullptr); + return callNode; + } + + TIntermAggregate *callNode = + TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, &fnCall->arguments()); + callNode->setLine(loc); + + checkAtomicMemoryBuiltinFunctions(callNode); + checkTextureOffset(callNode); + checkTextureGather(callNode); + checkInterpolationFS(callNode); + checkImageMemoryAccessForBuiltinFunctions(callNode); + + // Some built-in functions have out parameters too. + functionCallRValueLValueErrorCheck(fnCandidate, callNode); + + // See if we can constant fold a built-in. Note that this may be possible + // even if it is not const-qualified. + return callNode->fold(mDiagnostics); + } + else + { + error(loc, "no matching overloaded function found", fnCall->name()); + } + } + + // Error message was already written. Put on an unused node for error recovery. + return CreateZeroNode(TType(EbtFloat, EbpMedium, EvqConst)); +} + +TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond, + TIntermTyped *trueExpression, + TIntermTyped *falseExpression, + const TSourceLoc &loc) +{ + if (!checkIsScalarBool(loc, cond)) + { + return falseExpression; + } + + if (trueExpression->getType() != falseExpression->getType()) + { + TInfoSinkBase reasonStream; + reasonStream << "mismatching ternary operator operand types '" << trueExpression->getType() + << " and '" << falseExpression->getType() << "'"; + error(loc, reasonStream.c_str(), "?:"); + return falseExpression; + } + if (IsOpaqueType(trueExpression->getBasicType())) + { + // ESSL 1.00 section 4.1.7 + // ESSL 3.00.6 section 4.1.7 + // Opaque/sampler types are not allowed in most types of expressions, including ternary. + // Note that structs containing opaque types don't need to be checked as structs are + // forbidden below. + error(loc, "ternary operator is not allowed for opaque types", "?:"); + return falseExpression; + } + + if (cond->getMemoryQualifier().writeonly || trueExpression->getMemoryQualifier().writeonly || + falseExpression->getMemoryQualifier().writeonly) + { + error(loc, "ternary operator is not allowed for variables with writeonly", "?:"); + return falseExpression; + } + + // ESSL 1.00.17 sections 5.2 and 5.7: + // Ternary operator is not among the operators allowed for structures/arrays. + // ESSL 3.00.6 section 5.7: + // Ternary operator support is optional for arrays. No certainty that it works across all + // devices with struct either, so we err on the side of caution here. TODO (oetuaho@nvidia.com): + // Would be nice to make the spec and implementation agree completely here. + if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct) + { + error(loc, "ternary operator is not allowed for structures or arrays", "?:"); + return falseExpression; + } + if (trueExpression->getBasicType() == EbtInterfaceBlock) + { + error(loc, "ternary operator is not allowed for interface blocks", "?:"); + return falseExpression; + } + + // WebGL2 section 5.26, the following results in an error: + // "Ternary operator applied to void, arrays, or structs containing arrays" + if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid) + { + error(loc, "ternary operator is not allowed for void", "?:"); + return falseExpression; + } + + TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression); + markStaticReadIfSymbol(cond); + markStaticReadIfSymbol(trueExpression); + markStaticReadIfSymbol(falseExpression); + node->setLine(loc); + return expressionOrFoldedResult(node); +} + +// +// Parse an array of strings using yyparse. +// +// Returns 0 for success. +// +int PaParseStrings(size_t count, + const char *const string[], + const int length[], + TParseContext *context) +{ + if ((count == 0) || (string == nullptr)) + return 1; + + if (glslang_initialize(context)) + return 1; + + int error = glslang_scan(count, string, length, context); + if (!error) + error = glslang_parse(context); + + glslang_finalize(context); + + return (error == 0) && (context->numErrors() == 0) ? 0 : 1; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ParseContext.h b/gfx/angle/checkout/src/compiler/translator/ParseContext.h new file mode 100644 index 0000000000..666f5e3851 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ParseContext.h @@ -0,0 +1,818 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +#ifndef COMPILER_TRANSLATOR_PARSECONTEXT_H_ +#define COMPILER_TRANSLATOR_PARSECONTEXT_H_ + +#include "compiler/preprocessor/Preprocessor.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/Declarator.h" +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/DirectiveHandler.h" +#include "compiler/translator/FunctionLookup.h" +#include "compiler/translator/QualifierTypes.h" +#include "compiler/translator/SymbolTable.h" + +namespace sh +{ + +struct TMatrixFields +{ + bool wholeRow; + bool wholeCol; + int row; + int col; +}; + +// +// The following are extra variables needed during parsing, grouped together so +// they can be passed to the parser without needing a global. +// +class TParseContext : angle::NonCopyable +{ + public: + TParseContext(TSymbolTable &symt, + TExtensionBehavior &ext, + sh::GLenum type, + ShShaderSpec spec, + const ShCompileOptions &options, + bool checksPrecErrors, + TDiagnostics *diagnostics, + const ShBuiltInResources &resources, + ShShaderOutput outputType); + ~TParseContext(); + + bool anyMultiviewExtensionAvailable(); + const angle::pp::Preprocessor &getPreprocessor() const { return mPreprocessor; } + angle::pp::Preprocessor &getPreprocessor() { return mPreprocessor; } + void *getScanner() const { return mScanner; } + void setScanner(void *scanner) { mScanner = scanner; } + int getShaderVersion() const { return mShaderVersion; } + sh::GLenum getShaderType() const { return mShaderType; } + ShShaderSpec getShaderSpec() const { return mShaderSpec; } + int numErrors() const { return mDiagnostics->numErrors(); } + void error(const TSourceLoc &loc, const char *reason, const char *token); + void error(const TSourceLoc &loc, const char *reason, const ImmutableString &token); + void warning(const TSourceLoc &loc, const char *reason, const char *token); + + // If isError is false, a warning will be reported instead. + void outOfRangeError(bool isError, + const TSourceLoc &loc, + const char *reason, + const char *token); + + TIntermBlock *getTreeRoot() const { return mTreeRoot; } + void setTreeRoot(TIntermBlock *treeRoot); + + bool getFragmentPrecisionHigh() const + { + return mFragmentPrecisionHighOnESSL1 || mShaderVersion >= 300; + } + void setFragmentPrecisionHighOnESSL1(bool fragmentPrecisionHigh) + { + mFragmentPrecisionHighOnESSL1 = fragmentPrecisionHigh; + } + + bool isEarlyFragmentTestsSpecified() const { return mEarlyFragmentTestsSpecified; } + bool hasDiscard() const { return mHasDiscard; } + bool isSampleQualifierSpecified() const { return mSampleQualifierSpecified; } + + void setLoopNestingLevel(int loopNestintLevel) { mLoopNestingLevel = loopNestintLevel; } + + void incrLoopNestingLevel() { ++mLoopNestingLevel; } + void decrLoopNestingLevel() { --mLoopNestingLevel; } + + void incrSwitchNestingLevel() { ++mSwitchNestingLevel; } + void decrSwitchNestingLevel() { --mSwitchNestingLevel; } + + bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; } + sh::WorkGroupSize getComputeShaderLocalSize() const; + + int getNumViews() const { return mNumViews; } + + const std::map &pixelLocalStorageBindings() const + { + return mPLSBindings; + } + + void enterFunctionDeclaration() { mDeclaringFunction = true; } + + void exitFunctionDeclaration() { mDeclaringFunction = false; } + + bool declaringFunction() const { return mDeclaringFunction; } + + TIntermConstantUnion *addScalarLiteral(const TConstantUnion *constantUnion, + const TSourceLoc &line); + + // This method is guaranteed to succeed, even if no variable with 'name' exists. + const TVariable *getNamedVariable(const TSourceLoc &location, + const ImmutableString &name, + const TSymbol *symbol); + TIntermTyped *parseVariableIdentifier(const TSourceLoc &location, + const ImmutableString &name, + const TSymbol *symbol); + + // Look at a '.' field selector string and change it into offsets for a vector. + bool parseVectorFields(const TSourceLoc &line, + const ImmutableString &compString, + int vecSize, + TVector *fieldOffsets); + + void assignError(const TSourceLoc &line, const char *op, const TType &left, const TType &right); + void unaryOpError(const TSourceLoc &line, const char *op, const TType &operand); + void binaryOpError(const TSourceLoc &line, + const char *op, + const TType &left, + const TType &right); + + // Check functions - the ones that return bool return false if an error was generated. + + bool checkIsNotReserved(const TSourceLoc &line, const ImmutableString &identifier); + void checkPrecisionSpecified(const TSourceLoc &line, TPrecision precision, TBasicType type); + bool checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node); + void checkIsConst(TIntermTyped *node); + void checkIsScalarInteger(TIntermTyped *node, const char *token); + bool checkIsAtGlobalLevel(const TSourceLoc &line, const char *token); + bool checkConstructorArguments(const TSourceLoc &line, + const TIntermSequence &arguments, + const TType &type); + + // Returns a sanitized array size to use (the size is at least 1). + unsigned int checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr); + bool checkIsValidQualifierForArray(const TSourceLoc &line, const TPublicType &elementQualifier); + bool checkArrayElementIsNotArray(const TSourceLoc &line, const TPublicType &elementType); + bool checkArrayOfArraysInOut(const TSourceLoc &line, + const TPublicType &elementType, + const TType &arrayType); + bool checkIsNonVoid(const TSourceLoc &line, + const ImmutableString &identifier, + const TBasicType &type); + bool checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type); + void checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType); + bool checkIsNotOpaqueType(const TSourceLoc &line, + const TTypeSpecifierNonArray &pType, + const char *reason); + void checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line, const TPublicType &pType); + void checkLocationIsNotSpecified(const TSourceLoc &location, + const TLayoutQualifier &layoutQualifier); + void checkStd430IsForShaderStorageBlock(const TSourceLoc &location, + const TLayoutBlockStorage &blockStorage, + const TQualifier &qualifier); + void checkIsParameterQualifierValid(const TSourceLoc &line, + const TTypeQualifierBuilder &typeQualifierBuilder, + TType *type); + + // Check if at least one of the specified extensions can be used, and generate error/warning as + // appropriate according to the spec. + // This function is only needed for a few different small constant sizes of extension array, and + // we want to avoid unnecessary dynamic allocations. That's why checkCanUseOneOfExtensions is a + // template function rather than one taking a vector. + template + bool checkCanUseOneOfExtensions(const TSourceLoc &line, + const std::array &extensions); + bool checkCanUseExtension(const TSourceLoc &line, TExtension extension); + + // Done for all declarations, whether empty or not. + void declarationQualifierErrorCheck(const sh::TQualifier qualifier, + const sh::TLayoutQualifier &layoutQualifier, + const TSourceLoc &location); + // Done for the first non-empty declarator in a declaration. + void nonEmptyDeclarationErrorCheck(const TPublicType &publicType, + const TSourceLoc &identifierLocation); + // Done only for empty declarations. + void emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location); + + void checkCanUseLayoutQualifier(const TSourceLoc &location); + bool checkLayoutQualifierSupported(const TSourceLoc &location, + const ImmutableString &layoutQualifierName, + int versionRequired); + bool checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location, + const TLayoutQualifier &layoutQualifier); + void functionCallRValueLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *fnCall); + void checkInvariantVariableQualifier(bool invariant, + const TQualifier qualifier, + const TSourceLoc &invariantLocation); + void checkInputOutputTypeIsValidES3(const TQualifier qualifier, + const TPublicType &type, + const TSourceLoc &qualifierLocation); + void checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier); + void checkTCSOutVarIndexIsValid(TIntermBinary *binaryExpression, const TSourceLoc &location); + + void checkAdvancedBlendEquationsNotSpecified( + const TSourceLoc &location, + const AdvancedBlendEquations &advancedBlendEquations, + const TQualifier &qualifier); + + const TPragma &pragma() const { return mDirectiveHandler.pragma(); } + const TExtensionBehavior &extensionBehavior() const + { + return mDirectiveHandler.extensionBehavior(); + } + + bool isExtensionEnabled(TExtension extension) const; + void handleExtensionDirective(const TSourceLoc &loc, const char *extName, const char *behavior); + void handlePragmaDirective(const TSourceLoc &loc, + const char *name, + const char *value, + bool stdgl); + + // For built-ins that can be redeclared, adjusts the type qualifier so transformations can + // identify them correctly. + void adjustRedeclaredBuiltInType(const ImmutableString &identifier, TType *type); + + // Returns true on success. *initNode may still be nullptr on success in case the initialization + // is not needed in the AST. + bool executeInitializer(const TSourceLoc &line, + const ImmutableString &identifier, + TType *type, + TIntermTyped *initializer, + TIntermBinary **initNode); + TIntermNode *addConditionInitializer(const TPublicType &pType, + const ImmutableString &identifier, + TIntermTyped *initializer, + const TSourceLoc &loc); + TIntermNode *addLoop(TLoopType type, + TIntermNode *init, + TIntermNode *cond, + TIntermTyped *expr, + TIntermNode *body, + const TSourceLoc &loc); + + // For "if" test nodes. There are three children: a condition, a true path, and a false path. + // The two paths are in TIntermNodePair code. + TIntermNode *addIfElse(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &loc); + + void addFullySpecifiedType(TPublicType *typeSpecifier); + TPublicType addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder, + const TPublicType &typeSpecifier); + + TIntermDeclaration *parseSingleDeclaration(TPublicType &publicType, + const TSourceLoc &identifierOrTypeLocation, + const ImmutableString &identifier); + TIntermDeclaration *parseSingleArrayDeclaration(TPublicType &elementType, + const TSourceLoc &identifierLocation, + const ImmutableString &identifier, + const TSourceLoc &indexLocation, + const TVector &arraySizes); + TIntermDeclaration *parseSingleInitDeclaration(const TPublicType &publicType, + const TSourceLoc &identifierLocation, + const ImmutableString &identifier, + const TSourceLoc &initLocation, + TIntermTyped *initializer); + + // Parse a declaration like "type a[n] = initializer" + // Note that this does not apply to declarations like "type[n] a = initializer" + TIntermDeclaration *parseSingleArrayInitDeclaration(TPublicType &elementType, + const TSourceLoc &identifierLocation, + const ImmutableString &identifier, + const TSourceLoc &indexLocation, + const TVector &arraySizes, + const TSourceLoc &initLocation, + TIntermTyped *initializer); + + TIntermGlobalQualifierDeclaration *parseGlobalQualifierDeclaration( + const TTypeQualifierBuilder &typeQualifierBuilder, + const TSourceLoc &identifierLoc, + const ImmutableString &identifier, + const TSymbol *symbol); + + void parseDeclarator(TPublicType &publicType, + const TSourceLoc &identifierLocation, + const ImmutableString &identifier, + TIntermDeclaration *declarationOut); + void parseArrayDeclarator(TPublicType &elementType, + const TSourceLoc &identifierLocation, + const ImmutableString &identifier, + const TSourceLoc &arrayLocation, + const TVector &arraySizes, + TIntermDeclaration *declarationOut); + void parseInitDeclarator(const TPublicType &publicType, + const TSourceLoc &identifierLocation, + const ImmutableString &identifier, + const TSourceLoc &initLocation, + TIntermTyped *initializer, + TIntermDeclaration *declarationOut); + + // Parse a declarator like "a[n] = initializer" + void parseArrayInitDeclarator(const TPublicType &elementType, + const TSourceLoc &identifierLocation, + const ImmutableString &identifier, + const TSourceLoc &indexLocation, + const TVector &arraySizes, + const TSourceLoc &initLocation, + TIntermTyped *initializer, + TIntermDeclaration *declarationOut); + + TIntermNode *addEmptyStatement(const TSourceLoc &location); + + void parseDefaultPrecisionQualifier(const TPrecision precision, + const TPublicType &type, + const TSourceLoc &loc); + void parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder); + + TIntermFunctionPrototype *addFunctionPrototypeDeclaration(const TFunction &parsedFunction, + const TSourceLoc &location); + TIntermFunctionDefinition *addFunctionDefinition(TIntermFunctionPrototype *functionPrototype, + TIntermBlock *functionBody, + const TSourceLoc &location); + void parseFunctionDefinitionHeader(const TSourceLoc &location, + const TFunction *function, + TIntermFunctionPrototype **prototypeOut); + TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function); + TFunction *parseFunctionHeader(const TPublicType &type, + const ImmutableString &name, + const TSourceLoc &location); + + TFunctionLookup *addNonConstructorFunc(const ImmutableString &name, const TSymbol *symbol); + TFunctionLookup *addConstructorFunc(const TPublicType &publicType); + + TParameter parseParameterDeclarator(const TPublicType &publicType, + const ImmutableString &name, + const TSourceLoc &nameLoc); + + TParameter parseParameterArrayDeclarator(const ImmutableString &name, + const TSourceLoc &nameLoc, + const TVector &arraySizes, + const TSourceLoc &arrayLoc, + TPublicType *elementType); + + TIntermTyped *addIndexExpression(TIntermTyped *baseExpression, + const TSourceLoc &location, + TIntermTyped *indexExpression); + TIntermTyped *addFieldSelectionExpression(TIntermTyped *baseExpression, + const TSourceLoc &dotLocation, + const ImmutableString &fieldString, + const TSourceLoc &fieldLocation); + + // Parse declarator for a single field + TDeclarator *parseStructDeclarator(const ImmutableString &identifier, const TSourceLoc &loc); + TDeclarator *parseStructArrayDeclarator(const ImmutableString &identifier, + const TSourceLoc &loc, + const TVector *arraySizes); + + void checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin, + const TFieldList::const_iterator end, + const ImmutableString &name, + const TSourceLoc &location); + TFieldList *addStructFieldList(TFieldList *fields, const TSourceLoc &location); + TFieldList *combineStructFieldLists(TFieldList *processedFields, + const TFieldList *newlyAddedFields, + const TSourceLoc &location); + TFieldList *addStructDeclaratorListWithQualifiers( + const TTypeQualifierBuilder &typeQualifierBuilder, + TPublicType *typeSpecifier, + const TDeclaratorList *declaratorList); + TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, + const TDeclaratorList *declaratorList); + TTypeSpecifierNonArray addStructure(const TSourceLoc &structLine, + const TSourceLoc &nameLine, + const ImmutableString &structName, + TFieldList *fieldList); + + TIntermDeclaration *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder, + const TSourceLoc &nameLine, + const ImmutableString &blockName, + TFieldList *fieldList, + const ImmutableString &instanceName, + const TSourceLoc &instanceLine, + const TVector *arraySizes, + const TSourceLoc &arraySizesLine); + + void parseLocalSize(const ImmutableString &qualifierType, + const TSourceLoc &qualifierTypeLine, + int intValue, + const TSourceLoc &intValueLine, + const std::string &intValueString, + size_t index, + sh::WorkGroupSize *localSize); + void parseNumViews(int intValue, + const TSourceLoc &intValueLine, + const std::string &intValueString, + int *numViews); + void parseInvocations(int intValue, + const TSourceLoc &intValueLine, + const std::string &intValueString, + int *numInvocations); + void parseMaxVertices(int intValue, + const TSourceLoc &intValueLine, + const std::string &intValueString, + int *numMaxVertices); + void parseVertices(int intValue, + const TSourceLoc &intValueLine, + const std::string &intValueString, + int *numVertices); + void parseIndexLayoutQualifier(int intValue, + const TSourceLoc &intValueLine, + const std::string &intValueString, + int *index); + TLayoutQualifier parseLayoutQualifier(const ImmutableString &qualifierType, + const TSourceLoc &qualifierTypeLine); + TLayoutQualifier parseLayoutQualifier(const ImmutableString &qualifierType, + const TSourceLoc &qualifierTypeLine, + int intValue, + const TSourceLoc &intValueLine); + TTypeQualifierBuilder *createTypeQualifierBuilder(const TSourceLoc &loc); + TStorageQualifierWrapper *parseGlobalStorageQualifier(TQualifier qualifier, + const TSourceLoc &loc); + TStorageQualifierWrapper *parseVaryingQualifier(const TSourceLoc &loc); + TStorageQualifierWrapper *parseInQualifier(const TSourceLoc &loc); + TStorageQualifierWrapper *parseOutQualifier(const TSourceLoc &loc); + TStorageQualifierWrapper *parseInOutQualifier(const TSourceLoc &loc); + TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, + TLayoutQualifier rightQualifier, + const TSourceLoc &rightQualifierLocation); + + // Performs an error check for embedded struct declarations. + void enterStructDeclaration(const TSourceLoc &line, const ImmutableString &identifier); + void exitStructDeclaration(); + + void checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field); + + TIntermSwitch *addSwitch(TIntermTyped *init, + TIntermBlock *statementList, + const TSourceLoc &loc); + TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc); + TIntermCase *addDefault(const TSourceLoc &loc); + + TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc); + TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc); + TIntermTyped *addBinaryMath(TOperator op, + TIntermTyped *left, + TIntermTyped *right, + const TSourceLoc &loc); + TIntermTyped *addBinaryMathBooleanResult(TOperator op, + TIntermTyped *left, + TIntermTyped *right, + const TSourceLoc &loc); + TIntermTyped *addAssign(TOperator op, + TIntermTyped *left, + TIntermTyped *right, + const TSourceLoc &loc); + + TIntermTyped *addComma(TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); + + TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc); + TIntermBranch *addBranch(TOperator op, TIntermTyped *expression, const TSourceLoc &loc); + + void appendStatement(TIntermBlock *block, TIntermNode *statement); + + void checkTextureGather(TIntermAggregate *functionCall); + void checkTextureOffset(TIntermAggregate *functionCall); + void checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall); + void checkImageMemoryAccessForUserDefinedFunctions(const TFunction *functionDefinition, + const TIntermAggregate *functionCall); + void checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall); + void checkInterpolationFS(TIntermAggregate *functionCall); + + // fnCall is only storing the built-in op, and function name or constructor type. arguments + // has the arguments. + TIntermTyped *addFunctionCallOrMethod(TFunctionLookup *fnCall, const TSourceLoc &loc); + + TIntermTyped *addTernarySelection(TIntermTyped *cond, + TIntermTyped *trueExpression, + TIntermTyped *falseExpression, + const TSourceLoc &line); + + int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; } + int getGeometryShaderInvocations() const + { + return (mGeometryShaderInvocations > 0) ? mGeometryShaderInvocations : 1; + } + TLayoutPrimitiveType getGeometryShaderInputPrimitiveType() const + { + return mGeometryShaderInputPrimitiveType; + } + TLayoutPrimitiveType getGeometryShaderOutputPrimitiveType() const + { + return mGeometryShaderOutputPrimitiveType; + } + int getTessControlShaderOutputVertices() const { return mTessControlShaderOutputVertices; } + TLayoutTessEvaluationType getTessEvaluationShaderInputPrimitiveType() const + { + return mTessEvaluationShaderInputPrimitiveType; + } + TLayoutTessEvaluationType getTessEvaluationShaderInputVertexSpacingType() const + { + return mTessEvaluationShaderInputVertexSpacingType; + } + TLayoutTessEvaluationType getTessEvaluationShaderInputOrderingType() const + { + return mTessEvaluationShaderInputOrderingType; + } + TLayoutTessEvaluationType getTessEvaluationShaderInputPointType() const + { + return mTessEvaluationShaderInputPointType; + } + + const TVector &getDeferredArrayTypesToSize() const + { + return mDeferredArrayTypesToSize; + } + + void markShaderHasPrecise() { mHasAnyPreciseType = true; } + bool hasAnyPreciseType() const { return mHasAnyPreciseType; } + AdvancedBlendEquations getAdvancedBlendEquations() const { return mAdvancedBlendEquations; } + + ShShaderOutput getOutputType() const { return mOutputType; } + + // TODO(jmadill): make this private + TSymbolTable &symbolTable; // symbol table that goes with the language currently being parsed + + private: + class AtomicCounterBindingState; + constexpr static size_t kAtomicCounterSize = 4; + // UNIFORM_ARRAY_STRIDE for atomic counter arrays is an implementation-dependent value which + // can be queried after a program is linked according to ES 3.10 section 7.7.1. This is + // controversial with the offset inheritance as described in ESSL 3.10 section 4.4.6. Currently + // we treat it as always 4 in favour of the original interpretation in + // "ARB_shader_atomic_counters". + // TODO(jie.a.chen@intel.com): Double check this once the spec vagueness is resolved. + // Note that there may be tests in AtomicCounter_test that will need to be updated as well. + constexpr static size_t kAtomicCounterArrayStride = 4; + + void markStaticReadIfSymbol(TIntermNode *node); + + // Returns a clamped index. If it prints out an error message, the token is "[]". + int checkIndexLessThan(bool outOfRangeIndexIsError, + const TSourceLoc &location, + int index, + int arraySize, + const char *reason); + + bool declareVariable(const TSourceLoc &line, + const ImmutableString &identifier, + const TType *type, + TVariable **variable); + + void checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line, + const ImmutableString &identifier, + TType *type); + + TParameter parseParameterDeclarator(TType *type, + const ImmutableString &name, + const TSourceLoc &nameLoc); + + bool checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation, + const TPublicType &elementType); + // Done for all atomic counter declarations, whether empty or not. + void atomicCounterQualifierErrorCheck(const TPublicType &publicType, + const TSourceLoc &location); + + // Assumes that multiplication op has already been set based on the types. + bool isMultiplicationTypeCombinationValid(TOperator op, const TType &left, const TType &right); + + void checkOutParameterIsNotOpaqueType(const TSourceLoc &line, + TQualifier qualifier, + const TType &type); + + void checkInternalFormatIsNotSpecified(const TSourceLoc &location, + TLayoutImageInternalFormat internalFormat); + void checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier, + const TSourceLoc &location); + void checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend, + const TSourceLoc &loc, + TType *type); + void checkAtomicCounterOffsetAlignment(const TSourceLoc &location, const TType &type); + + void checkIndexIsNotSpecified(const TSourceLoc &location, int index); + void checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type); + void checkBindingIsNotSpecified(const TSourceLoc &location, int binding); + void checkOffsetIsNotSpecified(const TSourceLoc &location, int offset); + void checkImageBindingIsValid(const TSourceLoc &location, + int binding, + int arrayTotalElementCount); + void checkSamplerBindingIsValid(const TSourceLoc &location, + int binding, + int arrayTotalElementCount); + void checkBlockBindingIsValid(const TSourceLoc &location, + const TQualifier &qualifier, + int binding, + int arraySize); + void checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding); + void checkPixelLocalStorageBindingIsValid(const TSourceLoc &, const TType &); + + void checkUniformLocationInRange(const TSourceLoc &location, + int objectLocationCount, + const TLayoutQualifier &layoutQualifier); + void checkAttributeLocationInRange(const TSourceLoc &location, + int objectLocationCount, + const TLayoutQualifier &layoutQualifier); + + void checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv); + + void checkEarlyFragmentTestsIsNotSpecified(const TSourceLoc &location, bool earlyFragmentTests); + + void checkNoncoherentIsSpecified(const TSourceLoc &location, bool noncoherent); + + void checkNoncoherentIsNotSpecified(const TSourceLoc &location, bool noncoherent); + + bool checkUnsizedArrayConstructorArgumentDimensionality(const TIntermSequence &arguments, + TType type, + const TSourceLoc &line); + + void checkCombinedClipCullDistanceIsValid(const TSourceLoc &line, + const ImmutableString &identifier, + const int arraySize); + + // Check texture offset is within range. + void checkSingleTextureOffset(const TSourceLoc &line, + const TConstantUnion *values, + size_t size, + int minOffsetValue, + int maxOffsetValue); + + // Will set the size of the outermost array according to geometry shader input layout. + void checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location, + const ImmutableString &token, + TType *type); + + // Similar, for tessellation shaders. + void checkTessellationShaderUnsizedArraysAndSetSize(const TSourceLoc &location, + const ImmutableString &token, + TType *type); + + // Will size any unsized array type so unsized arrays won't need to be taken into account + // further along the line in parsing. + void checkIsNotUnsizedArray(const TSourceLoc &line, + const char *errorMessage, + const ImmutableString &token, + TType *arrayType); + + TIntermTyped *addBinaryMathInternal(TOperator op, + TIntermTyped *left, + TIntermTyped *right, + const TSourceLoc &loc); + TIntermTyped *createUnaryMath(TOperator op, + TIntermTyped *child, + const TSourceLoc &loc, + const TFunction *func); + + TIntermTyped *addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc); + TIntermTyped *addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line); + TIntermTyped *addNonConstructorFunctionCall(TFunctionLookup *fnCall, const TSourceLoc &loc); + + // Return either the original expression or the folded version of the expression in case the + // folded node will validate the same way during subsequent parsing. + TIntermTyped *expressionOrFoldedResult(TIntermTyped *expression); + + // Return true if the checks pass + bool binaryOpCommonCheck(TOperator op, + TIntermTyped *left, + TIntermTyped *right, + const TSourceLoc &loc); + + TIntermFunctionPrototype *createPrototypeNodeFromFunction(const TFunction &function, + const TSourceLoc &location, + bool insertParametersToSymbolTable); + + void setAtomicCounterBindingDefaultOffset(const TPublicType &declaration, + const TSourceLoc &location); + + bool checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier); + bool parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier); + bool parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier); + void setGeometryShaderInputArraySize(unsigned int inputArraySize, const TSourceLoc &line); + + bool parseTessControlShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier); + bool parseTessEvaluationShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier); + + // Certain operations become illegal only iff the shader declares pixel local storage uniforms. + enum class PLSIllegalOperations + { + // When polyfilled with shader images, pixel local storage requires early_fragment_tests, + // which causes discard to interact differently with the depth and stencil tests. + // + // To ensure identical behavior across all backends (some of which may not have access to + // early_fragment_tests), we disallow discard if pixel local storage uniforms have been + // declared. + Discard, + + // ARB_fragment_shader_interlock functions cannot be called within flow control, which + // includes any code that might execute after a return statement. To keep things simple, and + // since these "interlock" calls are automatically injected by the compiler inside of + // main(), we disallow return from main() if pixel local storage uniforms have been + // declared. + ReturnFromMain, + + // When polyfilled with shader images, pixel local storage requires early_fragment_tests, + // which causes assignments to gl_FragDepth(EXT) and gl_SampleMask to be ignored. + // + // To ensure identical behavior across all backends, we disallow assignment to these values + // if pixel local storage uniforms have been declared. + AssignFragDepth, + AssignSampleMask + }; + + // Generates an error if any pixel local storage uniforms have been declared (more specifically, + // if mPLSBindings is not empty). + // + // If no pixel local storage uniforms have been declared, and if the PLS extension is enabled, + // saves the potential error to mPLSPotentialErrors in case we encounter a PLS uniform later. + void errorIfPLSDeclared(const TSourceLoc &, PLSIllegalOperations); + + // Set to true when the last/current declarator list was started with an empty declaration. The + // non-empty declaration error check will need to be performed if the empty declaration is + // followed by a declarator. + bool mDeferredNonEmptyDeclarationErrorCheck; + + sh::GLenum mShaderType; // vertex/fragment/geometry/etc shader + ShShaderSpec mShaderSpec; // The language specification compiler conforms to - GLES/WebGL/etc. + ShCompileOptions mCompileOptions; // Options passed to TCompiler + int mShaderVersion; + TIntermBlock *mTreeRoot; // root of parse tree being created + int mLoopNestingLevel; // 0 if outside all loops + int mStructNestingLevel; // incremented while parsing a struct declaration + int mSwitchNestingLevel; // 0 if outside all switch statements + const TType + *mCurrentFunctionType; // the return type of the function that's currently being parsed + bool mFunctionReturnsValue; // true if a non-void function has a return + bool mChecksPrecisionErrors; // true if an error will be generated when a variable is declared + // without precision, explicit or implicit. + bool mFragmentPrecisionHighOnESSL1; // true if highp precision is supported when compiling + // ESSL1. + bool mEarlyFragmentTestsSpecified; // true if |layout(early_fragment_tests) in| is specified. + bool mHasDiscard; // true if |discard| is encountered in the shader. + bool mSampleQualifierSpecified; // true if the |sample| qualifier is used. + TLayoutMatrixPacking mDefaultUniformMatrixPacking; + TLayoutBlockStorage mDefaultUniformBlockStorage; + TLayoutMatrixPacking mDefaultBufferMatrixPacking; + TLayoutBlockStorage mDefaultBufferBlockStorage; + TString mHashErrMsg; + TDiagnostics *mDiagnostics; + TDirectiveHandler mDirectiveHandler; + angle::pp::Preprocessor mPreprocessor; + void *mScanner; + int mMinProgramTexelOffset; + int mMaxProgramTexelOffset; + + int mMinProgramTextureGatherOffset; + int mMaxProgramTextureGatherOffset; + + // keep track of local group size declared in layout. It should be declared only once. + bool mComputeShaderLocalSizeDeclared; + sh::WorkGroupSize mComputeShaderLocalSize; + // keep track of number of views declared in layout. + int mNumViews; + int mMaxNumViews; + int mMaxImageUnits; + int mMaxCombinedTextureImageUnits; + int mMaxUniformLocations; + int mMaxUniformBufferBindings; + int mMaxVertexAttribs; + int mMaxAtomicCounterBindings; + int mMaxShaderStorageBufferBindings; + + // keeps track whether we are declaring / defining a function + bool mDeclaringFunction; + + // keeps track whether we are declaring / defining the function main(). + bool mDeclaringMain; + + // Track the state of each atomic counter binding. + std::map mAtomicCounterBindingStates; + + // Track the format of each pixel local storage binding. + std::map mPLSBindings; + + // Potential errors to generate immediately upon encountering a pixel local storage uniform. + std::vector> mPLSPotentialErrors; + + // Track the geometry shader global parameters declared in layout. + TLayoutPrimitiveType mGeometryShaderInputPrimitiveType; + TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType; + int mGeometryShaderInvocations; + int mGeometryShaderMaxVertices; + int mMaxGeometryShaderInvocations; + int mMaxGeometryShaderMaxVertices; + unsigned int mGeometryInputArraySize; + + int mMaxPatchVertices; + int mTessControlShaderOutputVertices; + TLayoutTessEvaluationType mTessEvaluationShaderInputPrimitiveType; + TLayoutTessEvaluationType mTessEvaluationShaderInputVertexSpacingType; + TLayoutTessEvaluationType mTessEvaluationShaderInputOrderingType; + TLayoutTessEvaluationType mTessEvaluationShaderInputPointType; + // List of array declarations without an explicit size that have come before layout(vertices=N). + // Once the vertex count is specified, these arrays are sized. + TVector mDeferredArrayTypesToSize; + // Whether the |precise| keyword has been seen in the shader. + bool mHasAnyPreciseType; + + AdvancedBlendEquations mAdvancedBlendEquations; + + // Track when we add new scope for func body in ESSL 1.00 spec + bool mFunctionBodyNewScope; + + ShShaderOutput mOutputType; +}; + +int PaParseStrings(size_t count, + const char *const string[], + const int length[], + TParseContext *context); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_PARSECONTEXT_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/PoolAlloc.cpp b/gfx/angle/checkout/src/compiler/translator/PoolAlloc.cpp new file mode 100644 index 0000000000..1d770c6229 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/PoolAlloc.cpp @@ -0,0 +1,40 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/PoolAlloc.h" + +#include "common/debug.h" +#include "common/tls.h" + +TLSIndex PoolIndex = TLS_INVALID_INDEX; + +bool InitializePoolIndex() +{ + ASSERT(PoolIndex == TLS_INVALID_INDEX); + + PoolIndex = CreateTLSIndex(nullptr); + return PoolIndex != TLS_INVALID_INDEX; +} + +void FreePoolIndex() +{ + ASSERT(PoolIndex != TLS_INVALID_INDEX); + + DestroyTLSIndex(PoolIndex); + PoolIndex = TLS_INVALID_INDEX; +} + +angle::PoolAllocator *GetGlobalPoolAllocator() +{ + ASSERT(PoolIndex != TLS_INVALID_INDEX); + return static_cast(GetTLSValue(PoolIndex)); +} + +void SetGlobalPoolAllocator(angle::PoolAllocator *poolAllocator) +{ + ASSERT(PoolIndex != TLS_INVALID_INDEX); + SetTLSValue(PoolIndex, poolAllocator); +} diff --git a/gfx/angle/checkout/src/compiler/translator/PoolAlloc.h b/gfx/angle/checkout/src/compiler/translator/PoolAlloc.h new file mode 100644 index 0000000000..98f549b179 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/PoolAlloc.h @@ -0,0 +1,102 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_POOLALLOC_H_ +#define COMPILER_TRANSLATOR_POOLALLOC_H_ + +// +// This header defines the pool_allocator class that allows STL containers +// to use the angle::PoolAllocator class by using the pool_allocator +// class as the allocator (second) template argument. +// +// It also defines functions for managing the GlobalPoolAllocator used by the compiler. +// + +#include +#include +#include + +#include "common/PoolAlloc.h" + +// +// There could potentially be many pools with pops happening at +// different times. But a simple use is to have a global pop +// with everyone using the same global allocator. +// +extern angle::PoolAllocator *GetGlobalPoolAllocator(); +extern void SetGlobalPoolAllocator(angle::PoolAllocator *poolAllocator); + +// +// This STL compatible allocator is intended to be used as the allocator +// parameter to templatized STL containers, like vector and map. +// +// It will use the pools for allocation, and not +// do any deallocation, but will still do destruction. +// +template +class pool_allocator +{ + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T *pointer; + typedef const T *const_pointer; + typedef T &reference; + typedef const T &const_reference; + typedef T value_type; + + template + struct rebind + { + typedef pool_allocator other; + }; + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + + pool_allocator() {} + + template + pool_allocator(const pool_allocator &p) + {} + + template + pool_allocator &operator=(const pool_allocator &p) + { + return *this; + } + +#if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR) + // libCStd on some platforms have a different allocate/deallocate interface. + // Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be + // allocated, not the number of elements. + void *allocate(size_type n) { return getAllocator().allocate(n); } + void *allocate(size_type n, const void *) { return getAllocator().allocate(n); } + void deallocate(void *, size_type) {} +#else + pointer allocate(size_type n) + { + return static_cast(getAllocator().allocate(n * sizeof(T))); + } + pointer allocate(size_type n, const void *) + { + return static_cast(getAllocator().allocate(n * sizeof(T))); + } + void deallocate(pointer, size_type) {} +#endif // _RWSTD_ALLOCATOR + + void construct(pointer p, const T &val) { new ((void *)p) T(val); } + void destroy(pointer p) { p->T::~T(); } + + bool operator==(const pool_allocator &rhs) const { return true; } + bool operator!=(const pool_allocator &rhs) const { return false; } + + size_type max_size() const { return static_cast(-1) / sizeof(T); } + size_type max_size(int size) const { return static_cast(-1) / size; } + + angle::PoolAllocator &getAllocator() const { return *GetGlobalPoolAllocator(); } +}; + +#endif // COMPILER_TRANSLATOR_POOLALLOC_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/Pragma.h b/gfx/angle/checkout/src/compiler/translator/Pragma.h new file mode 100644 index 0000000000..c3f5ca2f46 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Pragma.h @@ -0,0 +1,28 @@ +// +// Copyright 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_PRAGMA_H_ +#define COMPILER_TRANSLATOR_PRAGMA_H_ + +struct TPragma +{ + struct STDGL + { + STDGL() : invariantAll(false) {} + + bool invariantAll; + }; + + // By default optimization is turned on and debug is turned off. + TPragma() : optimize(true), debug(false) {} + TPragma(bool o, bool d) : optimize(o), debug(d) {} + + bool optimize; + bool debug; + STDGL stdgl; +}; + +#endif // COMPILER_TRANSLATOR_PRAGMA_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/QualifierTypes.cpp b/gfx/angle/checkout/src/compiler/translator/QualifierTypes.cpp new file mode 100644 index 0000000000..e524146cd3 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/QualifierTypes.cpp @@ -0,0 +1,1007 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/QualifierTypes.h" + +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/ImmutableStringBuilder.h" + +#include + +namespace sh +{ + +namespace +{ + +constexpr const ImmutableString kSpecifiedMultipleTimes(" specified multiple times"); +constexpr const ImmutableString kInvariantMultipleTimes( + "The invariant qualifier specified multiple times."); +constexpr const ImmutableString kPreciseMultipleTimes( + "The precise qualifier specified multiple times."); +constexpr const ImmutableString kPrecisionMultipleTimes( + "The precision qualifier specified multiple times."); +constexpr const ImmutableString kLayoutMultipleTimes( + "The layout qualifier specified multiple times."); +constexpr const ImmutableString kLayoutAndInvariantDisallowed( + "The layout qualifier and invariant qualifier cannot coexist in the same " + "declaration according to the grammar."); +constexpr const ImmutableString kInterpolationMultipleTimes( + "The interpolation qualifier specified multiple times."); +constexpr const ImmutableString kOutputLayoutMultipleTimes( + "Output layout location specified multiple times."); +constexpr const ImmutableString kInvariantQualifierFirst( + "The invariant qualifier has to be first in the expression."); +constexpr const ImmutableString kStorageAfterInterpolation( + "Storage qualifiers have to be after interpolation qualifiers."); +constexpr const ImmutableString kPrecisionAfterInterpolation( + "Precision qualifiers have to be after interpolation qualifiers."); +constexpr const ImmutableString kStorageAfterLayout( + "Storage qualifiers have to be after layout qualifiers."); +constexpr const ImmutableString kPrecisionAfterLayout( + "Precision qualifiers have to be after layout qualifiers."); +constexpr const ImmutableString kPrecisionAfterStorage( + "Precision qualifiers have to be after storage qualifiers."); +constexpr const ImmutableString kPrecisionAfterMemory( + "Precision qualifiers have to be after memory qualifiers."); + +// GLSL ES 3.10 does not impose a strict order on type qualifiers and allows multiple layout +// declarations. +// GLSL ES 3.10 Revision 4, 4.10 Order of Qualification +bool AreTypeQualifierChecksRelaxed(int shaderVersion) +{ + return shaderVersion >= 310; +} + +bool IsScopeQualifier(TQualifier qualifier) +{ + return qualifier == EvqGlobal || qualifier == EvqTemporary; +} + +bool IsScopeQualifierWrapper(const TQualifierWrapperBase *qualifier) +{ + if (qualifier->getType() != QtStorage) + return false; + const TStorageQualifierWrapper *storageQualifier = + static_cast(qualifier); + TQualifier q = storageQualifier->getQualifier(); + return IsScopeQualifier(q); +} + +// Returns true if the invariant/precise for the qualifier sequence holds +bool IsInvariantCorrect(const TTypeQualifierBuilder::QualifierSequence &qualifiers) +{ + // We should have at least one qualifier. + // The first qualifier always tells the scope. + return qualifiers.size() >= 1 && IsScopeQualifierWrapper(qualifiers[0]); +} + +ImmutableString QualifierSpecifiedMultipleTimesErrorMessage(const ImmutableString &qualifierString) +{ + ImmutableStringBuilder errorMsg(qualifierString.length() + kSpecifiedMultipleTimes.length()); + errorMsg << qualifierString << kSpecifiedMultipleTimes; + return errorMsg; +} + +// Returns true if there are qualifiers which have been specified multiple times +// If areQualifierChecksRelaxed is set to true, then layout qualifier repetition is allowed. +bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qualifiers, + bool areQualifierChecksRelaxed, + ImmutableString *errorMessage) +{ + bool invariantFound = false; + bool preciseFound = false; + bool precisionFound = false; + bool layoutFound = false; + bool interpolationFound = false; + + unsigned int locationsSpecified = 0; + bool isOut = false; + + // The iteration starts from one since the first qualifier only reveals the scope of the + // expression. It is inserted first whenever the sequence gets created. + for (size_t i = 1; i < qualifiers.size(); ++i) + { + switch (qualifiers[i]->getType()) + { + case QtInvariant: + { + if (invariantFound) + { + *errorMessage = kInvariantMultipleTimes; + return true; + } + invariantFound = true; + break; + } + case QtPrecise: + { + if (preciseFound) + { + *errorMessage = kPreciseMultipleTimes; + return true; + } + preciseFound = true; + break; + } + case QtPrecision: + { + if (precisionFound) + { + *errorMessage = kPrecisionMultipleTimes; + return true; + } + precisionFound = true; + break; + } + case QtLayout: + { + if (layoutFound && !areQualifierChecksRelaxed) + { + *errorMessage = kLayoutMultipleTimes; + return true; + } + if (invariantFound && !areQualifierChecksRelaxed) + { + // This combination is not correct according to the syntax specified in the + // formal grammar in the ESSL 3.00 spec. In ESSL 3.10 the grammar does not have + // a similar restriction. + *errorMessage = kLayoutAndInvariantDisallowed; + return true; + } + layoutFound = true; + const TLayoutQualifier ¤tQualifier = + static_cast(qualifiers[i])->getQualifier(); + locationsSpecified += currentQualifier.locationsSpecified; + break; + } + case QtInterpolation: + { + // 'centroid' is treated as a storage qualifier + // 'flat centroid' will be squashed to 'flat' + // 'smooth centroid' will be squashed to 'centroid' + if (interpolationFound) + { + *errorMessage = kInterpolationMultipleTimes; + return true; + } + interpolationFound = true; + break; + } + case QtStorage: + { + // Go over all of the storage qualifiers up until the current one and check for + // repetitions. + TQualifier currentQualifier = + static_cast(qualifiers[i])->getQualifier(); + if (currentQualifier == EvqVertexOut || currentQualifier == EvqFragmentOut || + currentQualifier == EvqFragmentInOut) + { + isOut = true; + } + for (size_t j = 1; j < i; ++j) + { + if (qualifiers[j]->getType() == QtStorage) + { + const TStorageQualifierWrapper *previousQualifierWrapper = + static_cast(qualifiers[j]); + TQualifier previousQualifier = previousQualifierWrapper->getQualifier(); + if (currentQualifier == previousQualifier) + { + *errorMessage = QualifierSpecifiedMultipleTimesErrorMessage( + previousQualifierWrapper->getQualifierString()); + return true; + } + } + } + break; + } + case QtMemory: + { + // Go over all of the memory qualifiers up until the current one and check for + // repetitions. + // Having both readonly and writeonly in a sequence is valid. + // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers + TQualifier currentQualifier = + static_cast(qualifiers[i])->getQualifier(); + for (size_t j = 1; j < i; ++j) + { + if (qualifiers[j]->getType() == QtMemory) + { + const TMemoryQualifierWrapper *previousQualifierWrapper = + static_cast(qualifiers[j]); + TQualifier previousQualifier = previousQualifierWrapper->getQualifier(); + if (currentQualifier == previousQualifier) + { + *errorMessage = QualifierSpecifiedMultipleTimesErrorMessage( + previousQualifierWrapper->getQualifierString()); + return true; + } + } + } + break; + } + default: + UNREACHABLE(); + } + } + + if (locationsSpecified > 1 && isOut) + { + // GLSL ES 3.00.6 section 4.3.8.2 Output Layout Qualifiers + // GLSL ES 3.10 section 4.4.2 Output Layout Qualifiers + // "The qualifier may appear at most once within a declaration." + *errorMessage = kOutputLayoutMultipleTimes; + return true; + } + + return false; +} + +// GLSL ES 3.00_6, 4.7 Order of Qualification +// The correct order of qualifiers is: +// invariant-qualifier interpolation-qualifier storage-qualifier precision-qualifier +// layout-qualifier has to be before storage-qualifier. +// +// GLSL ES 3.1 relaxes the order of qualification: +// When multiple qualifiers are present in a declaration, they may appear in any order, but they +// must all appear before the type. +bool AreQualifiersInOrder(const TTypeQualifierBuilder::QualifierSequence &qualifiers, + int shaderVersion, + ImmutableString *errorMessage) +{ + if (shaderVersion >= 310) + { + return true; + } + + bool foundInterpolation = false; + bool foundStorage = false; + bool foundPrecision = false; + for (size_t i = 1; i < qualifiers.size(); ++i) + { + switch (qualifiers[i]->getType()) + { + case QtInvariant: + if (foundInterpolation || foundStorage || foundPrecision) + { + *errorMessage = kInvariantQualifierFirst; + return false; + } + break; + case QtInterpolation: + if (foundStorage) + { + *errorMessage = kStorageAfterInterpolation; + return false; + } + else if (foundPrecision) + { + *errorMessage = kPrecisionAfterInterpolation; + return false; + } + foundInterpolation = true; + break; + case QtLayout: + if (foundStorage) + { + *errorMessage = kStorageAfterLayout; + return false; + } + else if (foundPrecision) + { + *errorMessage = kPrecisionAfterLayout; + return false; + } + break; + case QtStorage: + if (foundPrecision) + { + *errorMessage = kPrecisionAfterStorage; + return false; + } + foundStorage = true; + break; + case QtMemory: + if (foundPrecision) + { + *errorMessage = kPrecisionAfterMemory; + return false; + } + break; + case QtPrecision: + foundPrecision = true; + break; + case QtPrecise: + // This keyword is available in ES3.1 (with extension) or in ES3.2, but the function + // should early-out in such a case as the spec doesn't require a particular order to + // the qualifiers. + UNREACHABLE(); + break; + default: + UNREACHABLE(); + } + } + return true; +} + +struct QualifierComparator +{ + bool operator()(const TQualifierWrapperBase *q1, const TQualifierWrapperBase *q2) + { + return q1->getRank() < q2->getRank(); + } +}; + +void SortSequence(TTypeQualifierBuilder::QualifierSequence &qualifiers) +{ + // We need a stable sorting algorithm since the order of layout-qualifier declarations matter. + // The sorting starts from index 1, instead of 0, since the element at index 0 tells the scope + // and we always want it to be first. + std::stable_sort(qualifiers.begin() + 1, qualifiers.end(), QualifierComparator()); +} + +// Handles the joining of storage qualifiers for variables. +bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier) +{ + switch (*joinedQualifier) + { + case EvqGlobal: + *joinedQualifier = storageQualifier; + break; + case EvqTemporary: + { + switch (storageQualifier) + { + case EvqConst: + *joinedQualifier = storageQualifier; + break; + default: + return false; + } + break; + } + case EvqSmooth: + { + switch (storageQualifier) + { + case EvqCentroid: + *joinedQualifier = EvqCentroid; + break; + case EvqVertexOut: + case EvqGeometryOut: + case EvqTessControlOut: + case EvqTessEvaluationOut: + *joinedQualifier = EvqSmoothOut; + break; + case EvqFragmentIn: + case EvqGeometryIn: + case EvqTessControlIn: + case EvqTessEvaluationIn: + *joinedQualifier = EvqSmoothIn; + break; + default: + return false; + } + break; + } + case EvqFlat: + { + switch (storageQualifier) + { + case EvqCentroid: + *joinedQualifier = EvqFlat; + break; + case EvqVertexOut: + case EvqGeometryOut: + case EvqTessControlOut: + case EvqTessEvaluationOut: + *joinedQualifier = EvqFlatOut; + break; + case EvqFragmentIn: + case EvqGeometryIn: + case EvqTessControlIn: + case EvqTessEvaluationIn: + *joinedQualifier = EvqFlatIn; + break; + default: + return false; + } + break; + } + case EvqNoPerspective: + { + switch (storageQualifier) + { + case EvqCentroid: + *joinedQualifier = EvqNoPerspective; + break; + case EvqVertexOut: + case EvqGeometryOut: + case EvqTessControlOut: + case EvqTessEvaluationOut: + *joinedQualifier = EvqNoPerspectiveOut; + break; + case EvqFragmentIn: + case EvqGeometryIn: + case EvqTessControlIn: + case EvqTessEvaluationIn: + *joinedQualifier = EvqNoPerspectiveIn; + break; + default: + return false; + } + break; + } + case EvqCentroid: + { + switch (storageQualifier) + { + case EvqVertexOut: + case EvqGeometryOut: + case EvqTessControlOut: + case EvqTessEvaluationOut: + *joinedQualifier = EvqCentroidOut; + break; + case EvqFragmentIn: + case EvqGeometryIn: + case EvqTessControlIn: + case EvqTessEvaluationIn: + *joinedQualifier = EvqCentroidIn; + break; + default: + return false; + } + break; + } + case EvqSample: + { + switch (storageQualifier) + { + case EvqVertexOut: + case EvqGeometryOut: + case EvqTessControlOut: + case EvqTessEvaluationOut: + *joinedQualifier = EvqSampleOut; + break; + case EvqFragmentIn: + case EvqGeometryIn: + case EvqTessControlIn: + case EvqTessEvaluationIn: + *joinedQualifier = EvqSampleIn; + break; + default: + return false; + } + break; + } + case EvqPatch: + { + switch (storageQualifier) + { + case EvqTessControlOut: + *joinedQualifier = EvqPatchOut; + break; + case EvqTessEvaluationIn: + *joinedQualifier = EvqPatchIn; + break; + default: + return false; + } + break; + } + default: + return false; + } + return true; +} + +// Handles the joining of storage qualifiers for a parameter in a function. +bool JoinParameterStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier) +{ + switch (*joinedQualifier) + { + case EvqTemporary: + *joinedQualifier = storageQualifier; + break; + case EvqConst: + { + switch (storageQualifier) + { + case EvqParamIn: + *joinedQualifier = EvqParamConst; + break; + default: + return false; + } + break; + } + default: + return false; + } + return true; +} + +bool JoinMemoryQualifier(TMemoryQualifier *joinedMemoryQualifier, TQualifier memoryQualifier) +{ + switch (memoryQualifier) + { + case EvqReadOnly: + joinedMemoryQualifier->readonly = true; + break; + case EvqWriteOnly: + joinedMemoryQualifier->writeonly = true; + break; + case EvqCoherent: + joinedMemoryQualifier->coherent = true; + break; + case EvqRestrict: + joinedMemoryQualifier->restrictQualifier = true; + break; + case EvqVolatile: + // Variables having the volatile qualifier are automatcally treated as coherent as well. + // GLSL ES 3.10, Revision 4, 4.9 Memory Access Qualifiers + joinedMemoryQualifier->volatileQualifier = true; + joinedMemoryQualifier->coherent = true; + break; + default: + UNREACHABLE(); + } + return true; +} + +TTypeQualifier GetVariableTypeQualifierFromSortedSequence( + const TTypeQualifierBuilder::QualifierSequence &sortedSequence, + TDiagnostics *diagnostics) +{ + TTypeQualifier typeQualifier( + static_cast(sortedSequence[0])->getQualifier(), + sortedSequence[0]->getLine()); + for (size_t i = 1; i < sortedSequence.size(); ++i) + { + const TQualifierWrapperBase *qualifier = sortedSequence[i]; + bool isQualifierValid = false; + switch (qualifier->getType()) + { + case QtInvariant: + isQualifierValid = true; + typeQualifier.invariant = true; + break; + case QtPrecise: + isQualifierValid = true; + typeQualifier.precise = true; + break; + case QtInterpolation: + { + switch (typeQualifier.qualifier) + { + case EvqGlobal: + isQualifierValid = true; + typeQualifier.qualifier = + static_cast(qualifier) + ->getQualifier(); + break; + default: + isQualifierValid = false; + } + break; + } + case QtLayout: + { + const TLayoutQualifierWrapper *layoutQualifierWrapper = + static_cast(qualifier); + isQualifierValid = true; + typeQualifier.layoutQualifier = sh::JoinLayoutQualifiers( + typeQualifier.layoutQualifier, layoutQualifierWrapper->getQualifier(), + layoutQualifierWrapper->getLine(), diagnostics); + break; + } + case QtStorage: + isQualifierValid = JoinVariableStorageQualifier( + &typeQualifier.qualifier, + static_cast(qualifier)->getQualifier()); + break; + case QtPrecision: + isQualifierValid = true; + typeQualifier.precision = + static_cast(qualifier)->getQualifier(); + ASSERT(typeQualifier.precision != EbpUndefined); + break; + case QtMemory: + isQualifierValid = JoinMemoryQualifier( + &typeQualifier.memoryQualifier, + static_cast(qualifier)->getQualifier()); + break; + default: + UNREACHABLE(); + } + if (!isQualifierValid) + { + const ImmutableString &qualifierString = qualifier->getQualifierString(); + diagnostics->error(qualifier->getLine(), "invalid qualifier combination", + qualifierString.data()); + break; + } + } + return typeQualifier; +} + +TTypeQualifier GetParameterTypeQualifierFromSortedSequence( + TBasicType parameterBasicType, + const TTypeQualifierBuilder::QualifierSequence &sortedSequence, + TDiagnostics *diagnostics) +{ + TTypeQualifier typeQualifier(EvqTemporary, sortedSequence[0]->getLine()); + for (size_t i = 1; i < sortedSequence.size(); ++i) + { + const TQualifierWrapperBase *qualifier = sortedSequence[i]; + bool isQualifierValid = false; + switch (qualifier->getType()) + { + case QtInvariant: + case QtInterpolation: + case QtLayout: + break; + case QtMemory: + isQualifierValid = JoinMemoryQualifier( + &typeQualifier.memoryQualifier, + static_cast(qualifier)->getQualifier()); + break; + case QtStorage: + isQualifierValid = JoinParameterStorageQualifier( + &typeQualifier.qualifier, + static_cast(qualifier)->getQualifier()); + break; + case QtPrecision: + isQualifierValid = true; + typeQualifier.precision = + static_cast(qualifier)->getQualifier(); + ASSERT(typeQualifier.precision != EbpUndefined); + break; + case QtPrecise: + isQualifierValid = true; + typeQualifier.precise = true; + break; + default: + UNREACHABLE(); + } + if (!isQualifierValid) + { + const ImmutableString &qualifierString = qualifier->getQualifierString(); + diagnostics->error(qualifier->getLine(), "invalid parameter qualifier", + qualifierString.data()); + break; + } + } + + switch (typeQualifier.qualifier) + { + case EvqParamIn: + case EvqParamConst: // const in + case EvqParamOut: + case EvqParamInOut: + break; + case EvqConst: + // Opaque parameters can only be |in|. |const| is allowed, but is meaningless and is + // dropped. + typeQualifier.qualifier = IsOpaqueType(parameterBasicType) ? EvqParamIn : EvqParamConst; + break; + case EvqTemporary: + // no qualifier has been specified, set it to EvqParamIn which is the default + typeQualifier.qualifier = EvqParamIn; + break; + default: + diagnostics->error(sortedSequence[0]->getLine(), "Invalid parameter qualifier ", + getQualifierString(typeQualifier.qualifier)); + } + return typeQualifier; +} +} // namespace + +TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier, + TLayoutQualifier rightQualifier, + const TSourceLoc &rightQualifierLocation, + TDiagnostics *diagnostics) +{ + TLayoutQualifier joinedQualifier = leftQualifier; + + if (rightQualifier.location != -1) + { + joinedQualifier.location = rightQualifier.location; + ++joinedQualifier.locationsSpecified; + } + if (rightQualifier.yuv != false) + { + joinedQualifier.yuv = rightQualifier.yuv; + } + if (rightQualifier.earlyFragmentTests != false) + { + joinedQualifier.earlyFragmentTests = rightQualifier.earlyFragmentTests; + } + if (rightQualifier.binding != -1) + { + joinedQualifier.binding = rightQualifier.binding; + } + if (rightQualifier.offset != -1) + { + joinedQualifier.offset = rightQualifier.offset; + } + if (rightQualifier.matrixPacking != EmpUnspecified) + { + joinedQualifier.matrixPacking = rightQualifier.matrixPacking; + } + if (rightQualifier.blockStorage != EbsUnspecified) + { + joinedQualifier.blockStorage = rightQualifier.blockStorage; + } + if (rightQualifier.noncoherent != false) + { + joinedQualifier.noncoherent = rightQualifier.noncoherent; + } + + for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i) + { + if (rightQualifier.localSize[i] != -1) + { + if (joinedQualifier.localSize[i] != -1 && + joinedQualifier.localSize[i] != rightQualifier.localSize[i]) + { + diagnostics->error(rightQualifierLocation, + "Cannot have multiple different work group size specifiers", + getWorkGroupSizeString(i)); + } + joinedQualifier.localSize[i] = rightQualifier.localSize[i]; + } + } + + if (rightQualifier.numViews != -1) + { + joinedQualifier.numViews = rightQualifier.numViews; + } + + if (rightQualifier.imageInternalFormat != EiifUnspecified) + { + joinedQualifier.imageInternalFormat = rightQualifier.imageInternalFormat; + } + + if (rightQualifier.primitiveType != EptUndefined) + { + if (joinedQualifier.primitiveType != EptUndefined && + joinedQualifier.primitiveType != rightQualifier.primitiveType) + { + diagnostics->error(rightQualifierLocation, + "Cannot have multiple different primitive specifiers", + getGeometryShaderPrimitiveTypeString(rightQualifier.primitiveType)); + } + joinedQualifier.primitiveType = rightQualifier.primitiveType; + } + + if (rightQualifier.invocations != 0) + { + if (joinedQualifier.invocations != 0 && + joinedQualifier.invocations != rightQualifier.invocations) + { + diagnostics->error(rightQualifierLocation, + "Cannot have multiple different invocations specifiers", + "invocations"); + } + joinedQualifier.invocations = rightQualifier.invocations; + } + + if (rightQualifier.maxVertices != -1) + { + if (joinedQualifier.maxVertices != -1 && + joinedQualifier.maxVertices != rightQualifier.maxVertices) + { + diagnostics->error(rightQualifierLocation, + "Cannot have multiple different max_vertices specifiers", + "max_vertices"); + } + joinedQualifier.maxVertices = rightQualifier.maxVertices; + } + + if (rightQualifier.tesPrimitiveType != EtetUndefined) + { + if (joinedQualifier.tesPrimitiveType == EtetUndefined) + { + joinedQualifier.tesPrimitiveType = rightQualifier.tesPrimitiveType; + } + } + + if (rightQualifier.tesVertexSpacingType != EtetUndefined) + { + if (joinedQualifier.tesVertexSpacingType == EtetUndefined) + { + joinedQualifier.tesVertexSpacingType = rightQualifier.tesVertexSpacingType; + } + } + + if (rightQualifier.tesOrderingType != EtetUndefined) + { + if (joinedQualifier.tesOrderingType == EtetUndefined) + { + joinedQualifier.tesOrderingType = rightQualifier.tesOrderingType; + } + } + + if (rightQualifier.tesPointType != EtetUndefined) + { + if (joinedQualifier.tesPointType == EtetUndefined) + { + joinedQualifier.tesPointType = rightQualifier.tesPointType; + } + } + + if (rightQualifier.vertices != 0) + { + if (joinedQualifier.vertices != 0 && joinedQualifier.vertices != rightQualifier.vertices) + { + diagnostics->error(rightQualifierLocation, + "Cannot have multiple different vertices specifiers", "vertices"); + } + joinedQualifier.vertices = rightQualifier.vertices; + } + + if (rightQualifier.index != -1) + { + if (joinedQualifier.index != -1) + { + // EXT_blend_func_extended spec: "Each of these qualifiers may appear at most once" + diagnostics->error(rightQualifierLocation, "Cannot have multiple index specifiers", + "index"); + } + joinedQualifier.index = rightQualifier.index; + } + + if (rightQualifier.advancedBlendEquations.any()) + { + joinedQualifier.advancedBlendEquations |= rightQualifier.advancedBlendEquations; + } + + return joinedQualifier; +} + +unsigned int TInvariantQualifierWrapper::getRank() const +{ + return 0u; +} + +unsigned int TPreciseQualifierWrapper::getRank() const +{ + return 1u; +} + +unsigned int TInterpolationQualifierWrapper::getRank() const +{ + return 2u; +} + +unsigned int TLayoutQualifierWrapper::getRank() const +{ + return 3u; +} + +unsigned int TStorageQualifierWrapper::getRank() const +{ + // Force the 'centroid' auxilary storage qualifier to be always first among all storage + // qualifiers. + if (mStorageQualifier == EvqCentroid) + { + return 4u; + } + else + { + return 5u; + } +} + +unsigned int TMemoryQualifierWrapper::getRank() const +{ + return 5u; +} + +unsigned int TPrecisionQualifierWrapper::getRank() const +{ + return 6u; +} + +TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc) + : layoutQualifier(TLayoutQualifier::Create()), + memoryQualifier(TMemoryQualifier::Create()), + precision(EbpUndefined), + qualifier(scope), + invariant(false), + precise(false), + line(loc) +{ + ASSERT(IsScopeQualifier(qualifier)); +} + +TTypeQualifierBuilder::TTypeQualifierBuilder(const TStorageQualifierWrapper *scope, + int shaderVersion) + : mShaderVersion(shaderVersion) +{ + ASSERT(IsScopeQualifier(scope->getQualifier())); + mQualifiers.push_back(scope); +} + +void TTypeQualifierBuilder::appendQualifier(const TQualifierWrapperBase *qualifier) +{ + mQualifiers.push_back(qualifier); +} + +bool TTypeQualifierBuilder::checkSequenceIsValid(TDiagnostics *diagnostics) const +{ + bool areQualifierChecksRelaxed = AreTypeQualifierChecksRelaxed(mShaderVersion); + ImmutableString errorMessage(""); + if (HasRepeatingQualifiers(mQualifiers, areQualifierChecksRelaxed, &errorMessage)) + { + diagnostics->error(mQualifiers[0]->getLine(), errorMessage.data(), "qualifier sequence"); + return false; + } + + if (!areQualifierChecksRelaxed && + !AreQualifiersInOrder(mQualifiers, mShaderVersion, &errorMessage)) + { + diagnostics->error(mQualifiers[0]->getLine(), errorMessage.data(), "qualifier sequence"); + return false; + } + + return true; +} + +TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier(TBasicType parameterBasicType, + TDiagnostics *diagnostics) const +{ + ASSERT(IsInvariantCorrect(mQualifiers)); + ASSERT(static_cast(mQualifiers[0])->getQualifier() == + EvqTemporary); + + if (!checkSequenceIsValid(diagnostics)) + { + return TTypeQualifier(EvqTemporary, mQualifiers[0]->getLine()); + } + + // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so + // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to + // combine the qualifiers. + if (AreTypeQualifierChecksRelaxed(mShaderVersion)) + { + // Copy the qualifier sequence so that we can sort them. + QualifierSequence sortedQualifierSequence = mQualifiers; + SortSequence(sortedQualifierSequence); + return GetParameterTypeQualifierFromSortedSequence(parameterBasicType, + sortedQualifierSequence, diagnostics); + } + return GetParameterTypeQualifierFromSortedSequence(parameterBasicType, mQualifiers, + diagnostics); +} + +TTypeQualifier TTypeQualifierBuilder::getVariableTypeQualifier(TDiagnostics *diagnostics) const +{ + ASSERT(IsInvariantCorrect(mQualifiers)); + + if (!checkSequenceIsValid(diagnostics)) + { + return TTypeQualifier( + static_cast(mQualifiers[0])->getQualifier(), + mQualifiers[0]->getLine()); + } + + // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so + // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to + // combine the qualifiers. + if (AreTypeQualifierChecksRelaxed(mShaderVersion)) + { + // Copy the qualifier sequence so that we can sort them. + QualifierSequence sortedQualifierSequence = mQualifiers; + SortSequence(sortedQualifierSequence); + return GetVariableTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics); + } + return GetVariableTypeQualifierFromSortedSequence(mQualifiers, diagnostics); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/QualifierTypes.h b/gfx/angle/checkout/src/compiler/translator/QualifierTypes.h new file mode 100644 index 0000000000..b98f300ce8 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/QualifierTypes.h @@ -0,0 +1,214 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_ +#define COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_ + +#include "common/angleutils.h" +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/Types.h" + +namespace sh +{ +class TDiagnostics; + +TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier, + TLayoutQualifier rightQualifier, + const TSourceLoc &rightQualifierLocation, + TDiagnostics *diagnostics); + +enum TQualifierType +{ + QtInvariant, + QtPrecise, + QtInterpolation, + QtLayout, + QtStorage, + QtPrecision, + QtMemory +}; + +class TQualifierWrapperBase : angle::NonCopyable +{ + public: + POOL_ALLOCATOR_NEW_DELETE + TQualifierWrapperBase(const TSourceLoc &line) : mLine(line) {} + virtual ~TQualifierWrapperBase() {} + virtual TQualifierType getType() const = 0; + virtual ImmutableString getQualifierString() const = 0; + virtual unsigned int getRank() const = 0; + const TSourceLoc &getLine() const { return mLine; } + + private: + TSourceLoc mLine; +}; + +class TInvariantQualifierWrapper final : public TQualifierWrapperBase +{ + public: + TInvariantQualifierWrapper(const TSourceLoc &line) : TQualifierWrapperBase(line) {} + ~TInvariantQualifierWrapper() override {} + + TQualifierType getType() const override { return QtInvariant; } + ImmutableString getQualifierString() const override { return ImmutableString("invariant"); } + unsigned int getRank() const override; +}; + +class TPreciseQualifierWrapper final : public TQualifierWrapperBase +{ + public: + TPreciseQualifierWrapper(const TSourceLoc &line) : TQualifierWrapperBase(line) {} + ~TPreciseQualifierWrapper() override {} + + TQualifierType getType() const override { return QtPrecise; } + ImmutableString getQualifierString() const override { return ImmutableString("precise"); } + unsigned int getRank() const override; +}; + +class TInterpolationQualifierWrapper final : public TQualifierWrapperBase +{ + public: + TInterpolationQualifierWrapper(TQualifier interpolationQualifier, const TSourceLoc &line) + : TQualifierWrapperBase(line), mInterpolationQualifier(interpolationQualifier) + {} + ~TInterpolationQualifierWrapper() override {} + + TQualifierType getType() const override { return QtInterpolation; } + ImmutableString getQualifierString() const override + { + return ImmutableString(sh::getQualifierString(mInterpolationQualifier)); + } + TQualifier getQualifier() const { return mInterpolationQualifier; } + unsigned int getRank() const override; + + private: + TQualifier mInterpolationQualifier; +}; + +class TLayoutQualifierWrapper final : public TQualifierWrapperBase +{ + public: + TLayoutQualifierWrapper(TLayoutQualifier layoutQualifier, const TSourceLoc &line) + : TQualifierWrapperBase(line), mLayoutQualifier(layoutQualifier) + {} + ~TLayoutQualifierWrapper() override {} + + TQualifierType getType() const override { return QtLayout; } + ImmutableString getQualifierString() const override { return ImmutableString("layout"); } + const TLayoutQualifier &getQualifier() const { return mLayoutQualifier; } + unsigned int getRank() const override; + + private: + TLayoutQualifier mLayoutQualifier; +}; + +class TStorageQualifierWrapper final : public TQualifierWrapperBase +{ + public: + TStorageQualifierWrapper(TQualifier storageQualifier, const TSourceLoc &line) + : TQualifierWrapperBase(line), mStorageQualifier(storageQualifier) + {} + ~TStorageQualifierWrapper() override {} + + TQualifierType getType() const override { return QtStorage; } + ImmutableString getQualifierString() const override + { + return ImmutableString(sh::getQualifierString(mStorageQualifier)); + } + TQualifier getQualifier() const { return mStorageQualifier; } + unsigned int getRank() const override; + + private: + TQualifier mStorageQualifier; +}; + +class TPrecisionQualifierWrapper final : public TQualifierWrapperBase +{ + public: + TPrecisionQualifierWrapper(TPrecision precisionQualifier, const TSourceLoc &line) + : TQualifierWrapperBase(line), mPrecisionQualifier(precisionQualifier) + {} + ~TPrecisionQualifierWrapper() override {} + + TQualifierType getType() const override { return QtPrecision; } + ImmutableString getQualifierString() const override + { + return ImmutableString(sh::getPrecisionString(mPrecisionQualifier)); + } + TPrecision getQualifier() const { return mPrecisionQualifier; } + unsigned int getRank() const override; + + private: + TPrecision mPrecisionQualifier; +}; + +class TMemoryQualifierWrapper final : public TQualifierWrapperBase +{ + public: + TMemoryQualifierWrapper(TQualifier memoryQualifier, const TSourceLoc &line) + : TQualifierWrapperBase(line), mMemoryQualifier(memoryQualifier) + {} + ~TMemoryQualifierWrapper() override {} + + TQualifierType getType() const override { return QtMemory; } + ImmutableString getQualifierString() const override + { + return ImmutableString(sh::getQualifierString(mMemoryQualifier)); + } + TQualifier getQualifier() const { return mMemoryQualifier; } + unsigned int getRank() const override; + + private: + TQualifier mMemoryQualifier; +}; + +// TTypeQualifier tightly covers type_qualifier from the grammar +struct TTypeQualifier +{ + // initializes all of the qualifiers and sets the scope + TTypeQualifier(TQualifier scope, const TSourceLoc &loc); + + TLayoutQualifier layoutQualifier; + TMemoryQualifier memoryQualifier; + TPrecision precision; + TQualifier qualifier; + bool invariant; + bool precise; + TSourceLoc line; +}; + +// TTypeQualifierBuilder contains all of the qualifiers when type_qualifier gets parsed. +// It is to be used to validate the qualifier sequence and build a TTypeQualifier from it. +class TTypeQualifierBuilder : angle::NonCopyable +{ + public: + using QualifierSequence = TVector; + + public: + POOL_ALLOCATOR_NEW_DELETE + TTypeQualifierBuilder(const TStorageQualifierWrapper *scope, int shaderVersion); + // Adds the passed qualifier to the end of the sequence. + void appendQualifier(const TQualifierWrapperBase *qualifier); + // Checks for the order of qualification and repeating qualifiers. + bool checkSequenceIsValid(TDiagnostics *diagnostics) const; + // Goes over the qualifier sequence and parses it to form a type qualifier for a function + // parameter. + // The returned object is initialized even if the parsing fails. + TTypeQualifier getParameterTypeQualifier(TBasicType parameterBasicType, + TDiagnostics *diagnostics) const; + // Goes over the qualifier sequence and parses it to form a type qualifier for a variable. + // The returned object is initialized even if the parsing fails. + TTypeQualifier getVariableTypeQualifier(TDiagnostics *diagnostics) const; + + private: + QualifierSequence mQualifiers; + int mShaderVersion; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ResourcesHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/ResourcesHLSL.cpp new file mode 100644 index 0000000000..e43bd44d4a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ResourcesHLSL.cpp @@ -0,0 +1,989 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ResourcesHLSL.cpp: +// Methods for GLSL to HLSL translation for uniforms and interface blocks. +// + +#include "compiler/translator/ResourcesHLSL.h" + +#include "common/utilities.h" +#include "compiler/translator/AtomicCounterFunctionHLSL.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/StructureHLSL.h" +#include "compiler/translator/UtilsHLSL.h" +#include "compiler/translator/blocklayoutHLSL.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +constexpr const ImmutableString kAngleDecorString("angle_"); + +static const char *UniformRegisterPrefix(const TType &type) +{ + if (IsSampler(type.getBasicType())) + { + return "s"; + } + else + { + return "c"; + } +} + +static TString InterfaceBlockFieldTypeString(const TField &field, + TLayoutBlockStorage blockStorage, + bool usedStructuredbuffer) +{ + const TType &fieldType = *field.type(); + const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking; + ASSERT(matrixPacking != EmpUnspecified); + const TStructure *structure = fieldType.getStruct(); + + if (fieldType.isMatrix()) + { + // Use HLSL row-major packing for GLSL column-major matrices + const TString &matrixPackString = + (matrixPacking == EmpRowMajor ? "column_major" : "row_major"); + return matrixPackString + " " + TypeString(fieldType); + } + else if (structure) + { + // If uniform block's layout is std140 and translating it to StructuredBuffer, + // should pack structure in the end, in order to fit API buffer. + bool forcePackingEnd = usedStructuredbuffer && (blockStorage == EbsStd140); + // Use HLSL row-major packing for GLSL column-major matrices + return QualifiedStructNameString(*structure, matrixPacking == EmpColumnMajor, + blockStorage == EbsStd140, forcePackingEnd); + } + else + { + return TypeString(fieldType); + } +} + +static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock) +{ + return DecoratePrivate(interfaceBlock.name()) + "_type"; +} + +void OutputUniformIndexArrayInitializer(TInfoSinkBase &out, + const TType &type, + unsigned int startIndex) +{ + out << "{"; + TType elementType(type); + elementType.toArrayElementType(); + for (unsigned int i = 0u; i < type.getOutermostArraySize(); ++i) + { + if (i > 0u) + { + out << ", "; + } + if (elementType.isArray()) + { + OutputUniformIndexArrayInitializer(out, elementType, + startIndex + i * elementType.getArraySizeProduct()); + } + else + { + out << (startIndex + i); + } + } + out << "}"; +} + +static TString InterfaceBlockScalarVectorFieldPaddingString(const TType &type) +{ + switch (type.getBasicType()) + { + case EbtFloat: + switch (type.getNominalSize()) + { + case 1: + return "float3 padding;"; + case 2: + return "float2 padding;"; + case 3: + return "float padding;"; + default: + break; + } + break; + case EbtInt: + switch (type.getNominalSize()) + { + case 1: + return "int3 padding;"; + case 2: + return "int2 padding;"; + case 3: + return "int padding"; + default: + break; + } + break; + case EbtUInt: + switch (type.getNominalSize()) + { + case 1: + return "uint3 padding;"; + case 2: + return "uint2 padding;"; + case 3: + return "uint padding;"; + default: + break; + } + break; + case EbtBool: + switch (type.getNominalSize()) + { + case 1: + return "bool3 padding;"; + case 2: + return "bool2 padding;"; + case 3: + return "bool padding;"; + default: + break; + } + break; + default: + break; + } + return ""; +} + +static bool IsAnyRasterOrdered(const TVector &imageVars) +{ + for (const TVariable *imageVar : imageVars) + { + if (imageVar->getType().getLayoutQualifier().rasterOrdered) + { + return true; + } + } + return false; +} + +} // anonymous namespace + +ResourcesHLSL::ResourcesHLSL(StructureHLSL *structureHLSL, + ShShaderOutput outputType, + const std::vector &uniforms, + unsigned int firstUniformRegister) + : mUniformRegister(firstUniformRegister), + mUniformBlockRegister(0), + mSRVRegister(0), + mUAVRegister(0), + mSamplerCount(0), + mStructureHLSL(structureHLSL), + mOutputType(outputType), + mUniforms(uniforms) +{} + +void ResourcesHLSL::reserveUniformRegisters(unsigned int registerCount) +{ + mUniformRegister = registerCount; +} + +void ResourcesHLSL::reserveUniformBlockRegisters(unsigned int registerCount) +{ + mUniformBlockRegister = registerCount; +} + +const ShaderVariable *ResourcesHLSL::findUniformByName(const ImmutableString &name) const +{ + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex) + { + if (name == mUniforms[uniformIndex].name) + { + return &mUniforms[uniformIndex]; + } + } + + return nullptr; +} + +unsigned int ResourcesHLSL::assignUniformRegister(const TType &type, + const ImmutableString &name, + unsigned int *outRegisterCount) +{ + unsigned int registerIndex; + const ShaderVariable *uniform = findUniformByName(name); + ASSERT(uniform); + + if (IsSampler(type.getBasicType()) || + (IsImage(type.getBasicType()) && type.getMemoryQualifier().readonly)) + { + registerIndex = mSRVRegister; + } + else if (IsImage(type.getBasicType())) + { + registerIndex = mUAVRegister; + } + else + { + registerIndex = mUniformRegister; + } + + if (uniform->name == "angle_DrawID" && uniform->mappedName == "angle_DrawID") + { + mUniformRegisterMap["gl_DrawID"] = registerIndex; + } + else + { + mUniformRegisterMap[uniform->name] = registerIndex; + } + + if (uniform->name == "angle_BaseVertex" && uniform->mappedName == "angle_BaseVertex") + { + mUniformRegisterMap["gl_BaseVertex"] = registerIndex; + } + else + { + mUniformRegisterMap[uniform->name] = registerIndex; + } + + if (uniform->name == "angle_BaseInstance" && uniform->mappedName == "angle_BaseInstance") + { + mUniformRegisterMap["gl_BaseInstance"] = registerIndex; + } + else + { + mUniformRegisterMap[uniform->name] = registerIndex; + } + + unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType); + + if (IsSampler(type.getBasicType()) || + (IsImage(type.getBasicType()) && type.getMemoryQualifier().readonly)) + { + mSRVRegister += registerCount; + } + else if (IsImage(type.getBasicType())) + { + mUAVRegister += registerCount; + } + else + { + mUniformRegister += registerCount; + } + if (outRegisterCount) + { + *outRegisterCount = registerCount; + } + return registerIndex; +} + +unsigned int ResourcesHLSL::assignSamplerInStructUniformRegister(const TType &type, + const TString &name, + unsigned int *outRegisterCount) +{ + // Sampler that is a field of a uniform structure. + ASSERT(IsSampler(type.getBasicType())); + unsigned int registerIndex = mSRVRegister; + mUniformRegisterMap[std::string(name.c_str())] = registerIndex; + unsigned int registerCount = type.isArray() ? type.getArraySizeProduct() : 1u; + mSRVRegister += registerCount; + if (outRegisterCount) + { + *outRegisterCount = registerCount; + } + return registerIndex; +} + +void ResourcesHLSL::outputHLSLSamplerUniformGroup( + TInfoSinkBase &out, + const HLSLTextureGroup textureGroup, + const TVector &group, + const TMap &samplerInStructSymbolsToAPINames, + unsigned int *groupTextureRegisterIndex) +{ + if (group.empty()) + { + return; + } + unsigned int groupRegisterCount = 0; + for (const TVariable *uniform : group) + { + const TType &type = uniform->getType(); + const ImmutableString &name = uniform->name(); + unsigned int registerCount; + + // The uniform might be just a regular sampler or one extracted from a struct. + unsigned int samplerArrayIndex = 0u; + const ShaderVariable *uniformByName = findUniformByName(name); + if (uniformByName) + { + samplerArrayIndex = assignUniformRegister(type, name, ®isterCount); + } + else + { + ASSERT(samplerInStructSymbolsToAPINames.find(uniform) != + samplerInStructSymbolsToAPINames.end()); + samplerArrayIndex = assignSamplerInStructUniformRegister( + type, samplerInStructSymbolsToAPINames.at(uniform), ®isterCount); + } + groupRegisterCount += registerCount; + + if (type.isArray()) + { + out << "static const uint " << DecorateVariableIfNeeded(*uniform) << ArrayString(type) + << " = "; + OutputUniformIndexArrayInitializer(out, type, samplerArrayIndex); + out << ";\n"; + } + else + { + out << "static const uint " << DecorateVariableIfNeeded(*uniform) << " = " + << samplerArrayIndex << ";\n"; + } + } + TString suffix = TextureGroupSuffix(textureGroup); + // Since HLSL_TEXTURE_2D is the first group, it has a fixed offset of zero. + if (textureGroup != HLSL_TEXTURE_2D) + { + out << "static const uint textureIndexOffset" << suffix << " = " + << (*groupTextureRegisterIndex) << ";\n"; + out << "static const uint samplerIndexOffset" << suffix << " = " + << (*groupTextureRegisterIndex) << ";\n"; + } + out << "uniform " << TextureString(textureGroup) << " textures" << suffix << "[" + << groupRegisterCount << "]" + << " : register(t" << (*groupTextureRegisterIndex) << ");\n"; + out << "uniform " << SamplerString(textureGroup) << " samplers" << suffix << "[" + << groupRegisterCount << "]" + << " : register(s" << (*groupTextureRegisterIndex) << ");\n"; + *groupTextureRegisterIndex += groupRegisterCount; +} + +void ResourcesHLSL::outputHLSLImageUniformIndices(TInfoSinkBase &out, + const TVector &group, + unsigned int imageArrayIndex, + unsigned int *groupRegisterCount) +{ + for (const TVariable *uniform : group) + { + const TType &type = uniform->getType(); + const ImmutableString &name = uniform->name(); + unsigned int registerCount = 0; + + assignUniformRegister(type, name, ®isterCount); + *groupRegisterCount += registerCount; + + if (type.isArray()) + { + out << "static const uint " << DecorateVariableIfNeeded(*uniform) << ArrayString(type) + << " = "; + OutputUniformIndexArrayInitializer(out, type, imageArrayIndex); + out << ";\n"; + } + else + { + out << "static const uint " << DecorateVariableIfNeeded(*uniform) << " = " + << imageArrayIndex << ";\n"; + } + + imageArrayIndex += registerCount; + } +} + +void ResourcesHLSL::outputHLSLReadonlyImageUniformGroup(TInfoSinkBase &out, + const HLSLTextureGroup textureGroup, + const TVector &group, + unsigned int *groupTextureRegisterIndex) +{ + if (group.empty()) + { + return; + } + + unsigned int groupRegisterCount = 0; + outputHLSLImageUniformIndices(out, group, *groupTextureRegisterIndex, &groupRegisterCount); + + TString suffix = TextureGroupSuffix(textureGroup); + out << "static const uint readonlyImageIndexOffset" << suffix << " = " + << (*groupTextureRegisterIndex) << ";\n"; + out << "uniform " << TextureString(textureGroup) << " readonlyImages" << suffix << "[" + << groupRegisterCount << "]" + << " : register(t" << (*groupTextureRegisterIndex) << ");\n"; + *groupTextureRegisterIndex += groupRegisterCount; +} + +void ResourcesHLSL::outputHLSLImageUniformGroup(TInfoSinkBase &out, + const HLSLRWTextureGroup textureGroup, + const TVector &group, + unsigned int *groupTextureRegisterIndex) +{ + if (group.empty()) + { + return; + } + + // ROVs should all be written out in DynamicImage2DHLSL.cpp. + ASSERT(!IsAnyRasterOrdered(group)); + + unsigned int groupRegisterCount = 0; + outputHLSLImageUniformIndices(out, group, *groupTextureRegisterIndex, &groupRegisterCount); + + TString suffix = RWTextureGroupSuffix(textureGroup); + out << "static const uint imageIndexOffset" << suffix << " = " << (*groupTextureRegisterIndex) + << ";\n"; + out << "uniform " << RWTextureString(textureGroup) << " images" << suffix << "[" + << groupRegisterCount << "]" + << " : register(u" << (*groupTextureRegisterIndex) << ");\n"; + *groupTextureRegisterIndex += groupRegisterCount; +} + +void ResourcesHLSL::outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out, + const TType &type, + const TVariable &variable, + const unsigned int registerIndex) +{ + out << "uniform " << SamplerString(type.getBasicType()) << " sampler_" + << DecorateVariableIfNeeded(variable) << ArrayString(type) << " : register(s" + << str(registerIndex) << ");\n"; + out << "uniform " << TextureString(type.getBasicType()) << " texture_" + << DecorateVariableIfNeeded(variable) << ArrayString(type) << " : register(t" + << str(registerIndex) << ");\n"; +} + +void ResourcesHLSL::outputUniform(TInfoSinkBase &out, + const TType &type, + const TVariable &variable, + const unsigned int registerIndex) +{ + const TStructure *structure = type.getStruct(); + // If this is a nameless struct, we need to use its full definition, rather than its (empty) + // name. + // TypeString() will invoke defineNameless in this case; qualifier prefixes are unnecessary for + // nameless structs in ES, as nameless structs cannot be used anywhere that layout qualifiers + // are permitted. + const TString &typeName = ((structure && structure->symbolType() != SymbolType::Empty) + ? QualifiedStructNameString(*structure, false, false, false) + : TypeString(type)); + + const TString ®isterString = + TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")"; + + out << "uniform " << typeName << " "; + + out << DecorateVariableIfNeeded(variable); + + out << ArrayString(type) << " : " << registerString << ";\n"; +} + +void ResourcesHLSL::outputAtomicCounterBuffer(TInfoSinkBase &out, + const int binding, + const unsigned int registerIndex) +{ + // Atomic counter memory access is not incoherent + out << "uniform globallycoherent RWByteAddressBuffer " + << getAtomicCounterNameForBinding(binding) << " : register(u" << registerIndex << ");\n"; +} + +void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out, + ShShaderOutput outputType, + const ReferencedVariables &referencedUniforms, + TSymbolTable *symbolTable) +{ + if (!referencedUniforms.empty()) + { + out << "// Uniforms\n\n"; + } + // In the case of HLSL 4, sampler uniforms need to be grouped by type before the code is + // written. They are grouped based on the combination of the HLSL texture type and + // HLSL sampler type, enumerated in HLSLTextureSamplerGroup. + TVector> groupedSamplerUniforms(HLSL_TEXTURE_MAX + 1); + TMap samplerInStructSymbolsToAPINames; + TVector> groupedReadonlyImageUniforms(HLSL_TEXTURE_MAX + 1); + TVector> groupedImageUniforms(HLSL_RWTEXTURE_MAX + 1); + + TUnorderedMap assignedAtomicCounterBindings; + unsigned int reservedReadonlyImageRegisterCount = 0, reservedImageRegisterCount = 0; + for (auto &uniformIt : referencedUniforms) + { + // Output regular uniforms. Group sampler uniforms by type. + const TVariable &variable = *uniformIt.second; + const TType &type = variable.getType(); + + if (outputType == SH_HLSL_4_1_OUTPUT && IsSampler(type.getBasicType())) + { + HLSLTextureGroup group = TextureGroup(type.getBasicType()); + groupedSamplerUniforms[group].push_back(&variable); + } + else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(type.getBasicType())) + { + unsigned int registerIndex = assignUniformRegister(type, variable.name(), nullptr); + outputHLSL4_0_FL9_3Sampler(out, type, variable, registerIndex); + } + else if (outputType == SH_HLSL_4_1_OUTPUT && IsImage(type.getBasicType())) + { + if (IsImage2D(type.getBasicType())) + { + const ShaderVariable *uniform = findUniformByName(variable.name()); + if (type.getMemoryQualifier().readonly) + { + reservedReadonlyImageRegisterCount += + HLSLVariableRegisterCount(*uniform, mOutputType); + } + else + { + reservedImageRegisterCount += HLSLVariableRegisterCount(*uniform, mOutputType); + } + continue; + } + if (type.getMemoryQualifier().readonly) + { + HLSLTextureGroup group = TextureGroup( + type.getBasicType(), type.getLayoutQualifier().imageInternalFormat); + groupedReadonlyImageUniforms[group].push_back(&variable); + } + else + { + HLSLRWTextureGroup group = RWTextureGroup( + type.getBasicType(), type.getLayoutQualifier().imageInternalFormat); + groupedImageUniforms[group].push_back(&variable); + } + } + else if (outputType == SH_HLSL_4_1_OUTPUT && IsAtomicCounter(type.getBasicType())) + { + TLayoutQualifier layout = type.getLayoutQualifier(); + int binding = layout.binding; + unsigned int registerIndex; + if (assignedAtomicCounterBindings.find(binding) == assignedAtomicCounterBindings.end()) + { + registerIndex = mUAVRegister++; + assignedAtomicCounterBindings[binding] = registerIndex; + outputAtomicCounterBuffer(out, binding, registerIndex); + } + else + { + registerIndex = assignedAtomicCounterBindings[binding]; + } + const ShaderVariable *uniform = findUniformByName(variable.name()); + mUniformRegisterMap[uniform->name] = registerIndex; + } + else + { + if (type.isStructureContainingSamplers()) + { + TVector samplerSymbols; + TMap symbolsToAPINames; + ImmutableStringBuilder namePrefix(kAngleDecorString.length() + + variable.name().length()); + namePrefix << kAngleDecorString; + namePrefix << variable.name(); + type.createSamplerSymbols(namePrefix, TString(variable.name().data()), + &samplerSymbols, &symbolsToAPINames, symbolTable); + for (const TVariable *sampler : samplerSymbols) + { + const TType &samplerType = sampler->getType(); + + if (outputType == SH_HLSL_4_1_OUTPUT) + { + HLSLTextureGroup group = TextureGroup(samplerType.getBasicType()); + groupedSamplerUniforms[group].push_back(sampler); + samplerInStructSymbolsToAPINames[sampler] = symbolsToAPINames[sampler]; + } + else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT) + { + unsigned int registerIndex = assignSamplerInStructUniformRegister( + samplerType, symbolsToAPINames[sampler], nullptr); + outputHLSL4_0_FL9_3Sampler(out, samplerType, *sampler, registerIndex); + } + else + { + ASSERT(outputType == SH_HLSL_3_0_OUTPUT); + unsigned int registerIndex = assignSamplerInStructUniformRegister( + samplerType, symbolsToAPINames[sampler], nullptr); + outputUniform(out, samplerType, *sampler, registerIndex); + } + } + } + unsigned int registerIndex = assignUniformRegister(type, variable.name(), nullptr); + outputUniform(out, type, variable, registerIndex); + } + } + + if (outputType == SH_HLSL_4_1_OUTPUT) + { + unsigned int groupTextureRegisterIndex = 0; + // Atomic counters and RW texture share the same resources. Therefore, RW texture need to + // start counting after the last atomic counter. + unsigned int groupRWTextureRegisterIndex = mUAVRegister; + // TEXTURE_2D is special, index offset is assumed to be 0 and omitted in that case. + ASSERT(HLSL_TEXTURE_MIN == HLSL_TEXTURE_2D); + for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId) + { + outputHLSLSamplerUniformGroup( + out, HLSLTextureGroup(groupId), groupedSamplerUniforms[groupId], + samplerInStructSymbolsToAPINames, &groupTextureRegisterIndex); + } + mSamplerCount = groupTextureRegisterIndex; + + // Reserve t type register for readonly image2D variables. + mReadonlyImage2DRegisterIndex = mSRVRegister; + groupTextureRegisterIndex += reservedReadonlyImageRegisterCount; + mSRVRegister += reservedReadonlyImageRegisterCount; + + for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId) + { + outputHLSLReadonlyImageUniformGroup(out, HLSLTextureGroup(groupId), + groupedReadonlyImageUniforms[groupId], + &groupTextureRegisterIndex); + } + mReadonlyImageCount = groupTextureRegisterIndex - mReadonlyImage2DRegisterIndex; + if (mReadonlyImageCount) + { + out << "static const uint readonlyImageIndexStart = " << mReadonlyImage2DRegisterIndex + << ";\n"; + } + + // Reserve u type register for writable image2D variables. + mImage2DRegisterIndex = mUAVRegister; + groupRWTextureRegisterIndex += reservedImageRegisterCount; + mUAVRegister += reservedImageRegisterCount; + + for (int groupId = HLSL_RWTEXTURE_MIN; groupId < HLSL_RWTEXTURE_MAX; ++groupId) + { + outputHLSLImageUniformGroup(out, HLSLRWTextureGroup(groupId), + groupedImageUniforms[groupId], + &groupRWTextureRegisterIndex); + } + mImageCount = groupRWTextureRegisterIndex - mImage2DRegisterIndex; + if (mImageCount) + { + out << "static const uint imageIndexStart = " << mImage2DRegisterIndex << ";\n"; + } + } +} + +void ResourcesHLSL::samplerMetadataUniforms(TInfoSinkBase &out, unsigned int regIndex) +{ + // If mSamplerCount is 0 the shader doesn't use any textures for samplers. + if (mSamplerCount > 0) + { + out << " struct SamplerMetadata\n" + " {\n" + " int baseLevel;\n" + " int internalFormatBits;\n" + " int wrapModes;\n" + " int padding;\n" + " int4 intBorderColor;\n" + " };\n" + " SamplerMetadata samplerMetadata[" + << mSamplerCount << "] : packoffset(c" << regIndex << ");\n"; + } +} + +void ResourcesHLSL::imageMetadataUniforms(TInfoSinkBase &out, unsigned int regIndex) +{ + if (mReadonlyImageCount > 0 || mImageCount > 0) + { + out << " struct ImageMetadata\n" + " {\n" + " int layer;\n" + " uint level;\n" + " int2 padding;\n" + " };\n"; + + if (mReadonlyImageCount > 0) + { + out << " ImageMetadata readonlyImageMetadata[" << mReadonlyImageCount + << "] : packoffset(c" << regIndex << ");\n"; + } + + if (mImageCount > 0) + { + out << " ImageMetadata imageMetadata[" << mImageCount << "] : packoffset(c" + << regIndex + mReadonlyImageCount << ");\n"; + } + } +} + +TString ResourcesHLSL::uniformBlocksHeader( + const ReferencedInterfaceBlocks &referencedInterfaceBlocks, + const std::map &uniformBlockOptimizedMap) +{ + TString interfaceBlocks; + + for (const auto &blockReference : referencedInterfaceBlocks) + { + const TInterfaceBlock &interfaceBlock = *blockReference.second->block; + const TVariable *instanceVariable = blockReference.second->instanceVariable; + if (instanceVariable != nullptr) + { + interfaceBlocks += uniformBlockStructString(interfaceBlock); + } + + // In order to avoid compile performance issue, translate uniform block to structured + // buffer. anglebug.com/3682. + if (uniformBlockOptimizedMap.count(interfaceBlock.uniqueId().get()) != 0) + { + unsigned int structuredBufferRegister = mSRVRegister; + if (instanceVariable != nullptr && instanceVariable->getType().isArray()) + { + unsigned int instanceArraySize = + instanceVariable->getType().getOutermostArraySize(); + for (unsigned int arrayIndex = 0; arrayIndex < instanceArraySize; arrayIndex++) + { + interfaceBlocks += uniformBlockWithOneLargeArrayMemberString( + interfaceBlock, instanceVariable, structuredBufferRegister + arrayIndex, + arrayIndex); + } + mSRVRegister += instanceArraySize; + } + else + { + interfaceBlocks += uniformBlockWithOneLargeArrayMemberString( + interfaceBlock, instanceVariable, structuredBufferRegister, GL_INVALID_INDEX); + mSRVRegister += 1u; + } + mUniformBlockRegisterMap[interfaceBlock.name().data()] = structuredBufferRegister; + mUniformBlockUseStructuredBufferMap[interfaceBlock.name().data()] = true; + continue; + } + + unsigned int activeRegister = mUniformBlockRegister; + mUniformBlockRegisterMap[interfaceBlock.name().data()] = activeRegister; + + if (instanceVariable != nullptr && instanceVariable->getType().isArray()) + { + unsigned int instanceArraySize = instanceVariable->getType().getOutermostArraySize(); + for (unsigned int arrayIndex = 0; arrayIndex < instanceArraySize; arrayIndex++) + { + interfaceBlocks += uniformBlockString(interfaceBlock, instanceVariable, + activeRegister + arrayIndex, arrayIndex); + } + mUniformBlockRegister += instanceArraySize; + } + else + { + interfaceBlocks += uniformBlockString(interfaceBlock, instanceVariable, activeRegister, + GL_INVALID_INDEX); + mUniformBlockRegister += 1u; + } + } + + return (interfaceBlocks.empty() ? "" : ("// Uniform Blocks\n\n" + interfaceBlocks)); +} + +void ResourcesHLSL::allocateShaderStorageBlockRegisters( + const ReferencedInterfaceBlocks &referencedInterfaceBlocks) +{ + for (const auto &interfaceBlockReference : referencedInterfaceBlocks) + { + const TInterfaceBlock &interfaceBlock = *interfaceBlockReference.second->block; + const TVariable *instanceVariable = interfaceBlockReference.second->instanceVariable; + + mShaderStorageBlockRegisterMap[interfaceBlock.name().data()] = mUAVRegister; + + if (instanceVariable != nullptr && instanceVariable->getType().isArray()) + { + mUAVRegister += instanceVariable->getType().getOutermostArraySize(); + } + else + { + mUAVRegister += 1u; + } + } +} + +TString ResourcesHLSL::shaderStorageBlocksHeader( + const ReferencedInterfaceBlocks &referencedInterfaceBlocks) +{ + TString interfaceBlocks; + + for (const auto &interfaceBlockReference : referencedInterfaceBlocks) + { + const TInterfaceBlock &interfaceBlock = *interfaceBlockReference.second->block; + const TVariable *instanceVariable = interfaceBlockReference.second->instanceVariable; + + unsigned int activeRegister = mShaderStorageBlockRegisterMap[interfaceBlock.name().data()]; + + if (instanceVariable != nullptr && instanceVariable->getType().isArray()) + { + unsigned int instanceArraySize = instanceVariable->getType().getOutermostArraySize(); + for (unsigned int arrayIndex = 0; arrayIndex < instanceArraySize; arrayIndex++) + { + interfaceBlocks += shaderStorageBlockString( + interfaceBlock, instanceVariable, activeRegister + arrayIndex, arrayIndex); + } + } + else + { + interfaceBlocks += shaderStorageBlockString(interfaceBlock, instanceVariable, + activeRegister, GL_INVALID_INDEX); + } + } + + return interfaceBlocks; +} + +TString ResourcesHLSL::uniformBlockString(const TInterfaceBlock &interfaceBlock, + const TVariable *instanceVariable, + unsigned int registerIndex, + unsigned int arrayIndex) +{ + const TString &arrayIndexString = (arrayIndex != GL_INVALID_INDEX ? str(arrayIndex) : ""); + const TString &blockName = TString(interfaceBlock.name().data()) + arrayIndexString; + TString hlsl; + + hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + + ")\n" + "{\n"; + + if (instanceVariable != nullptr) + { + hlsl += " " + InterfaceBlockStructName(interfaceBlock) + " " + + InterfaceBlockInstanceString(instanceVariable->name(), arrayIndex) + ";\n"; + } + else + { + const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage(); + hlsl += uniformBlockMembersString(interfaceBlock, blockStorage); + } + + hlsl += "};\n\n"; + + return hlsl; +} + +TString ResourcesHLSL::uniformBlockWithOneLargeArrayMemberString( + const TInterfaceBlock &interfaceBlock, + const TVariable *instanceVariable, + unsigned int registerIndex, + unsigned int arrayIndex) +{ + TString hlsl, typeString; + + const TField &field = *interfaceBlock.fields()[0]; + const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage(); + typeString = InterfaceBlockFieldTypeString(field, blockStorage, true); + const TType &fieldType = *field.type(); + if (fieldType.isMatrix()) + { + if (arrayIndex == GL_INVALID_INDEX || arrayIndex == 0) + { + hlsl += "struct pack" + Decorate(interfaceBlock.name()) + " { " + typeString + " " + + Decorate(field.name()) + "; };\n"; + } + typeString = "pack" + Decorate(interfaceBlock.name()); + } + else if (fieldType.isVectorArray() || fieldType.isScalarArray()) + { + // If the member is an array of scalars or vectors, std140 rules require the base array + // stride are rounded up to the base alignment of a vec4. + if (arrayIndex == GL_INVALID_INDEX || arrayIndex == 0) + { + hlsl += "struct pack" + Decorate(interfaceBlock.name()) + " { " + typeString + " " + + Decorate(field.name()) + ";\n"; + hlsl += InterfaceBlockScalarVectorFieldPaddingString(fieldType) + " };\n"; + } + typeString = "pack" + Decorate(interfaceBlock.name()); + } + + if (instanceVariable != nullptr) + { + + hlsl += "StructuredBuffer <" + typeString + "> " + + InterfaceBlockInstanceString(instanceVariable->name(), arrayIndex) + "_" + + Decorate(field.name()) + +" : register(t" + str(registerIndex) + ");\n"; + } + else + { + hlsl += "StructuredBuffer <" + typeString + "> " + Decorate(field.name()) + + " : register(t" + str(registerIndex) + ");\n"; + } + + return hlsl; +} + +TString ResourcesHLSL::shaderStorageBlockString(const TInterfaceBlock &interfaceBlock, + const TVariable *instanceVariable, + unsigned int registerIndex, + unsigned int arrayIndex) +{ + TString hlsl; + if (instanceVariable != nullptr) + { + hlsl += "RWByteAddressBuffer " + + InterfaceBlockInstanceString(instanceVariable->name(), arrayIndex) + + ": register(u" + str(registerIndex) + ");\n"; + } + else + { + hlsl += "RWByteAddressBuffer " + Decorate(interfaceBlock.name()) + ": register(u" + + str(registerIndex) + ");\n"; + } + return hlsl; +} + +TString ResourcesHLSL::InterfaceBlockInstanceString(const ImmutableString &instanceName, + unsigned int arrayIndex) +{ + if (arrayIndex != GL_INVALID_INDEX) + { + return DecoratePrivate(instanceName) + "_" + str(arrayIndex); + } + else + { + return Decorate(instanceName); + } +} + +TString ResourcesHLSL::uniformBlockMembersString(const TInterfaceBlock &interfaceBlock, + TLayoutBlockStorage blockStorage) +{ + TString hlsl; + + Std140PaddingHelper padHelper = mStructureHLSL->getPaddingHelper(); + + const unsigned int fieldCount = static_cast(interfaceBlock.fields().size()); + for (unsigned int typeIndex = 0; typeIndex < fieldCount; typeIndex++) + { + const TField &field = *interfaceBlock.fields()[typeIndex]; + const TType &fieldType = *field.type(); + + if (blockStorage == EbsStd140) + { + // 2 and 3 component vector types in some cases need pre-padding + hlsl += padHelper.prePaddingString(fieldType, false); + } + + hlsl += " " + InterfaceBlockFieldTypeString(field, blockStorage, false) + " " + + Decorate(field.name()) + ArrayString(fieldType).data() + ";\n"; + + // must pad out after matrices and arrays, where HLSL usually allows itself room to pack + // stuff + if (blockStorage == EbsStd140) + { + const bool useHLSLRowMajorPacking = + (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor); + hlsl += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking, + typeIndex == fieldCount - 1, false); + } + } + + return hlsl; +} + +TString ResourcesHLSL::uniformBlockStructString(const TInterfaceBlock &interfaceBlock) +{ + const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage(); + + return "struct " + InterfaceBlockStructName(interfaceBlock) + + "\n" + "{\n" + + uniformBlockMembersString(interfaceBlock, blockStorage) + "};\n\n"; +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ResourcesHLSL.h b/gfx/angle/checkout/src/compiler/translator/ResourcesHLSL.h new file mode 100644 index 0000000000..a13ba036eb --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ResourcesHLSL.h @@ -0,0 +1,155 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ResourcesHLSL.h: +// Methods for GLSL to HLSL translation for uniforms and interface blocks. +// + +#ifndef COMPILER_TRANSLATOR_RESOURCESHLSL_H_ +#define COMPILER_TRANSLATOR_RESOURCESHLSL_H_ + +#include "compiler/translator/OutputHLSL.h" +#include "compiler/translator/UtilsHLSL.h" + +namespace sh +{ +class ImmutableString; +class StructureHLSL; +class TSymbolTable; + +class ResourcesHLSL : angle::NonCopyable +{ + public: + ResourcesHLSL(StructureHLSL *structureHLSL, + ShShaderOutput outputType, + const std::vector &uniforms, + unsigned int firstUniformRegister); + + void reserveUniformRegisters(unsigned int registerCount); + void reserveUniformBlockRegisters(unsigned int registerCount); + void uniformsHeader(TInfoSinkBase &out, + ShShaderOutput outputType, + const ReferencedVariables &referencedUniforms, + TSymbolTable *symbolTable); + + // Must be called after uniformsHeader + void samplerMetadataUniforms(TInfoSinkBase &out, unsigned int regIndex); + unsigned int getSamplerCount() const { return mSamplerCount; } + void imageMetadataUniforms(TInfoSinkBase &out, unsigned int regIndex); + TString uniformBlocksHeader( + const ReferencedInterfaceBlocks &referencedInterfaceBlocks, + const std::map &uniformBlockOptimizedMap); + void allocateShaderStorageBlockRegisters( + const ReferencedInterfaceBlocks &referencedInterfaceBlocks); + TString shaderStorageBlocksHeader(const ReferencedInterfaceBlocks &referencedInterfaceBlocks); + + // Used for direct index references + static TString InterfaceBlockInstanceString(const ImmutableString &instanceName, + unsigned int arrayIndex); + + const std::map &getShaderStorageBlockRegisterMap() const + { + return mShaderStorageBlockRegisterMap; + } + + const std::map &getUniformBlockRegisterMap() const + { + return mUniformBlockRegisterMap; + } + + const std::map &getUniformBlockUseStructuredBufferMap() const + { + return mUniformBlockUseStructuredBufferMap; + } + + const std::map &getUniformRegisterMap() const + { + return mUniformRegisterMap; + } + + unsigned int getReadonlyImage2DRegisterIndex() const { return mReadonlyImage2DRegisterIndex; } + unsigned int getImage2DRegisterIndex() const { return mImage2DRegisterIndex; } + bool hasImages() const { return mReadonlyImageCount > 0 || mImageCount > 0; } + + private: + TString uniformBlockString(const TInterfaceBlock &interfaceBlock, + const TVariable *instanceVariable, + unsigned int registerIndex, + unsigned int arrayIndex); + TString uniformBlockWithOneLargeArrayMemberString(const TInterfaceBlock &interfaceBlock, + const TVariable *instanceVariable, + unsigned int registerIndex, + unsigned int arrayIndex); + + TString shaderStorageBlockString(const TInterfaceBlock &interfaceBlock, + const TVariable *instanceVariable, + unsigned int registerIndex, + unsigned int arrayIndex); + TString uniformBlockMembersString(const TInterfaceBlock &interfaceBlock, + TLayoutBlockStorage blockStorage); + TString uniformBlockStructString(const TInterfaceBlock &interfaceBlock); + const ShaderVariable *findUniformByName(const ImmutableString &name) const; + + void outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out, + const TType &type, + const TVariable &variable, + const unsigned int registerIndex); + void outputUniform(TInfoSinkBase &out, + const TType &type, + const TVariable &variable, + const unsigned int registerIndex); + void outputAtomicCounterBuffer(TInfoSinkBase &out, + const int binding, + const unsigned int registerIndex); + + // Returns the uniform's register index + unsigned int assignUniformRegister(const TType &type, + const ImmutableString &name, + unsigned int *outRegisterCount); + unsigned int assignSamplerInStructUniformRegister(const TType &type, + const TString &name, + unsigned int *outRegisterCount); + + void outputHLSLSamplerUniformGroup( + TInfoSinkBase &out, + const HLSLTextureGroup textureGroup, + const TVector &group, + const TMap &samplerInStructSymbolsToAPINames, + unsigned int *groupTextureRegisterIndex); + + void outputHLSLImageUniformIndices(TInfoSinkBase &out, + const TVector &group, + unsigned int imageArrayIndex, + unsigned int *groupRegisterCount); + void outputHLSLReadonlyImageUniformGroup(TInfoSinkBase &out, + const HLSLTextureGroup textureGroup, + const TVector &group, + unsigned int *groupTextureRegisterIndex); + void outputHLSLImageUniformGroup(TInfoSinkBase &out, + const HLSLRWTextureGroup textureGroup, + const TVector &group, + unsigned int *groupTextureRegisterIndex); + + unsigned int mUniformRegister; + unsigned int mUniformBlockRegister; + unsigned int mSRVRegister; + unsigned int mUAVRegister; + unsigned int mSamplerCount; + unsigned int mReadonlyImageCount = 0; + unsigned int mImageCount = 0; + StructureHLSL *mStructureHLSL; + ShShaderOutput mOutputType; + + const std::vector &mUniforms; + std::map mUniformBlockRegisterMap; + std::map mShaderStorageBlockRegisterMap; + std::map mUniformRegisterMap; + std::map mUniformBlockUseStructuredBufferMap; + unsigned int mReadonlyImage2DRegisterIndex; + unsigned int mImage2DRegisterIndex; +}; +} // namespace sh + +#endif // COMPILER_TRANSLATOR_RESOURCESHLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/Severity.h b/gfx/angle/checkout/src/compiler/translator/Severity.h new file mode 100644 index 0000000000..dccd45375d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Severity.h @@ -0,0 +1,22 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_SEVERITY_H_ +#define COMPILER_TRANSLATOR_SEVERITY_H_ + +namespace sh +{ + +// Severity is used to classify info log messages. +enum Severity +{ + SH_WARNING, + SH_ERROR +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_SEVERITY_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ShaderLang.cpp b/gfx/angle/checkout/src/compiler/translator/ShaderLang.cpp new file mode 100644 index 0000000000..abc680656a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ShaderLang.cpp @@ -0,0 +1,1091 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// Implement the top-level of interface to the compiler, +// as defined in ShaderLang.h +// + +#include "GLSLANG/ShaderLang.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/InitializeDll.h" +#include "compiler/translator/glslang_wrapper.h" +#include "compiler/translator/length_limits.h" +#ifdef ANGLE_ENABLE_HLSL +# include "compiler/translator/TranslatorHLSL.h" +#endif // ANGLE_ENABLE_HLSL +#include "angle_gl.h" +#include "compiler/translator/VariablePacker.h" + +namespace sh +{ + +namespace +{ + +bool isInitialized = false; + +// glslang can only be initialized/finalized once per process. Otherwise, the following EGL commands +// will call GlslangFinalize() without ever being able to GlslangInitialize() again, leading to +// crashes since GlslangFinalize() cleans up glslang for the entire process. +// dpy1 = eglGetPlatformDisplay() | +// eglInitialize(dpy1) | GlslangInitialize() +// dpy2 = eglGetPlatformDisplay() | +// eglInitialize(dpy2) | GlslangInitialize() +// eglTerminate(dpy2) | GlslangFinalize() +// eglInitialize(dpy1) | Display::isInitialized() == true, no GlslangInitialize() +int initializeGlslangRefCount = 0; + +// +// This is the platform independent interface between an OGL driver +// and the shading language compiler. +// + +template +const std::vector *GetVariableList(const TCompiler *compiler); + +template <> +const std::vector *GetVariableList(const TCompiler *compiler) +{ + return &compiler->getInterfaceBlocks(); +} + +TCompiler *GetCompilerFromHandle(ShHandle handle) +{ + if (!handle) + { + return nullptr; + } + + TShHandleBase *base = static_cast(handle); + return base->getAsCompiler(); +} + +template +const std::vector *GetShaderVariables(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + if (!compiler) + { + return nullptr; + } + + return GetVariableList(compiler); +} + +#ifdef ANGLE_ENABLE_HLSL +TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle) +{ + if (!handle) + return nullptr; + TShHandleBase *base = static_cast(handle); + return base->getAsTranslatorHLSL(); +} +#endif // ANGLE_ENABLE_HLSL + +GLenum GetGeometryShaderPrimitiveTypeEnum(sh::TLayoutPrimitiveType primitiveType) +{ + switch (primitiveType) + { + case EptPoints: + return GL_POINTS; + case EptLines: + return GL_LINES; + case EptLinesAdjacency: + return GL_LINES_ADJACENCY_EXT; + case EptTriangles: + return GL_TRIANGLES; + case EptTrianglesAdjacency: + return GL_TRIANGLES_ADJACENCY_EXT; + + case EptLineStrip: + return GL_LINE_STRIP; + case EptTriangleStrip: + return GL_TRIANGLE_STRIP; + + case EptUndefined: + default: + UNREACHABLE(); + return GL_INVALID_VALUE; + } +} + +GLenum GetTessellationShaderTypeEnum(sh::TLayoutTessEvaluationType type) +{ + switch (type) + { + case EtetTriangles: + return GL_TRIANGLES; + case EtetQuads: + return GL_QUADS; + case EtetIsolines: + return GL_ISOLINES; + case EtetEqualSpacing: + return GL_EQUAL; + case EtetFractionalEvenSpacing: + return GL_FRACTIONAL_EVEN; + case EtetFractionalOddSpacing: + return GL_FRACTIONAL_ODD; + case EtetCw: + return GL_CW; + case EtetCcw: + return GL_CCW; + case EtetPointMode: + return GL_TESS_GEN_POINT_MODE; + + case EtetUndefined: + default: + UNREACHABLE(); + return GL_INVALID_VALUE; + } +} + +} // anonymous namespace + +// +// Driver must call this first, once, before doing any other compiler operations. +// Subsequent calls to this function are no-op. +// +bool Initialize() +{ + if (!isInitialized) + { + isInitialized = InitProcess(); + } + return isInitialized; +} + +// +// Cleanup symbol tables +// +bool Finalize() +{ + if (isInitialized) + { + DetachProcess(); + isInitialized = false; + } + return true; +} + +// +// Initialize built-in resources with minimum expected values. +// +void InitBuiltInResources(ShBuiltInResources *resources) +{ + // Make comparable. + memset(resources, 0, sizeof(*resources)); + + // Constants. + resources->MaxVertexAttribs = 8; + resources->MaxVertexUniformVectors = 128; + resources->MaxVaryingVectors = 8; + resources->MaxVertexTextureImageUnits = 0; + resources->MaxCombinedTextureImageUnits = 8; + resources->MaxTextureImageUnits = 8; + resources->MaxFragmentUniformVectors = 16; + resources->MaxDrawBuffers = 1; + + // Extensions. + resources->OES_standard_derivatives = 0; + resources->OES_EGL_image_external = 0; + resources->OES_EGL_image_external_essl3 = 0; + resources->NV_EGL_stream_consumer_external = 0; + resources->ARB_texture_rectangle = 0; + resources->EXT_blend_func_extended = 0; + resources->EXT_draw_buffers = 0; + resources->EXT_frag_depth = 0; + resources->EXT_shader_texture_lod = 0; + resources->EXT_shader_framebuffer_fetch = 0; + resources->EXT_shader_framebuffer_fetch_non_coherent = 0; + resources->NV_shader_framebuffer_fetch = 0; + resources->ARM_shader_framebuffer_fetch = 0; + resources->OVR_multiview = 0; + resources->OVR_multiview2 = 0; + resources->EXT_YUV_target = 0; + resources->EXT_geometry_shader = 0; + resources->OES_geometry_shader = 0; + resources->EXT_gpu_shader5 = 0; + resources->OES_shader_io_blocks = 0; + resources->EXT_shader_io_blocks = 0; + resources->EXT_shader_non_constant_global_initializers = 0; + resources->NV_shader_noperspective_interpolation = 0; + resources->OES_texture_storage_multisample_2d_array = 0; + resources->OES_texture_3D = 0; + resources->ANGLE_shader_pixel_local_storage = 0; + resources->ANGLE_texture_multisample = 0; + resources->ANGLE_multi_draw = 0; + resources->ANGLE_base_vertex_base_instance = 0; + resources->ANGLE_base_vertex_base_instance_shader_builtin = 0; + resources->WEBGL_video_texture = 0; + resources->APPLE_clip_distance = 0; + resources->OES_texture_cube_map_array = 0; + resources->EXT_texture_cube_map_array = 0; + resources->EXT_shadow_samplers = 0; + resources->OES_shader_multisample_interpolation = 0; + resources->NV_draw_buffers = 0; + resources->OES_shader_image_atomic = 0; + resources->EXT_tessellation_shader = 0; + resources->OES_texture_buffer = 0; + resources->EXT_texture_buffer = 0; + resources->OES_sample_variables = 0; + resources->EXT_clip_cull_distance = 0; + resources->KHR_blend_equation_advanced = 0; + + resources->MaxClipDistances = 8; + resources->MaxCullDistances = 8; + resources->MaxCombinedClipAndCullDistances = 8; + + // Disable highp precision in fragment shader by default. + resources->FragmentPrecisionHigh = 0; + + // GLSL ES 3.0 constants. + resources->MaxVertexOutputVectors = 16; + resources->MaxFragmentInputVectors = 15; + resources->MinProgramTexelOffset = -8; + resources->MaxProgramTexelOffset = 7; + + // Extensions constants. + resources->MaxDualSourceDrawBuffers = 0; + + resources->MaxViewsOVR = 4; + + // Disable name hashing by default. + resources->HashFunction = nullptr; + + resources->MaxExpressionComplexity = 256; + resources->MaxCallStackDepth = 256; + resources->MaxFunctionParameters = 1024; + + // ES 3.1 Revision 4, 7.2 Built-in Constants + + // ES 3.1, Revision 4, 8.13 Texture minification + // "The value of MIN_PROGRAM_TEXTURE_GATHER_OFFSET must be less than or equal to the value of + // MIN_PROGRAM_TEXEL_OFFSET. The value of MAX_PROGRAM_TEXTURE_GATHER_OFFSET must be greater than + // or equal to the value of MAX_PROGRAM_TEXEL_OFFSET" + resources->MinProgramTextureGatherOffset = -8; + resources->MaxProgramTextureGatherOffset = 7; + + resources->MaxImageUnits = 4; + resources->MaxVertexImageUniforms = 0; + resources->MaxFragmentImageUniforms = 0; + resources->MaxComputeImageUniforms = 4; + resources->MaxCombinedImageUniforms = 4; + + resources->MaxUniformLocations = 1024; + + resources->MaxCombinedShaderOutputResources = 4; + + resources->MaxComputeWorkGroupCount[0] = 65535; + resources->MaxComputeWorkGroupCount[1] = 65535; + resources->MaxComputeWorkGroupCount[2] = 65535; + resources->MaxComputeWorkGroupSize[0] = 128; + resources->MaxComputeWorkGroupSize[1] = 128; + resources->MaxComputeWorkGroupSize[2] = 64; + resources->MaxComputeUniformComponents = 512; + resources->MaxComputeTextureImageUnits = 16; + + resources->MaxComputeAtomicCounters = 8; + resources->MaxComputeAtomicCounterBuffers = 1; + + resources->MaxVertexAtomicCounters = 0; + resources->MaxFragmentAtomicCounters = 0; + resources->MaxCombinedAtomicCounters = 8; + resources->MaxAtomicCounterBindings = 1; + + resources->MaxVertexAtomicCounterBuffers = 0; + resources->MaxFragmentAtomicCounterBuffers = 0; + resources->MaxCombinedAtomicCounterBuffers = 1; + resources->MaxAtomicCounterBufferSize = 32; + + resources->MaxUniformBufferBindings = 32; + resources->MaxShaderStorageBufferBindings = 4; + + resources->MaxGeometryUniformComponents = 1024; + resources->MaxGeometryUniformBlocks = 12; + resources->MaxGeometryInputComponents = 64; + resources->MaxGeometryOutputComponents = 64; + resources->MaxGeometryOutputVertices = 256; + resources->MaxGeometryTotalOutputComponents = 1024; + resources->MaxGeometryTextureImageUnits = 16; + resources->MaxGeometryAtomicCounterBuffers = 0; + resources->MaxGeometryAtomicCounters = 0; + resources->MaxGeometryShaderStorageBlocks = 0; + resources->MaxGeometryShaderInvocations = 32; + resources->MaxGeometryImageUniforms = 0; + + resources->MaxTessControlInputComponents = 64; + resources->MaxTessControlOutputComponents = 64; + resources->MaxTessControlTextureImageUnits = 16; + resources->MaxTessControlUniformComponents = 1024; + resources->MaxTessControlTotalOutputComponents = 2048; + resources->MaxTessControlImageUniforms = 0; + resources->MaxTessControlAtomicCounters = 0; + resources->MaxTessControlAtomicCounterBuffers = 0; + + resources->MaxTessPatchComponents = 120; + resources->MaxPatchVertices = 32; + resources->MaxTessGenLevel = 64; + + resources->MaxTessEvaluationInputComponents = 64; + resources->MaxTessEvaluationOutputComponents = 64; + resources->MaxTessEvaluationTextureImageUnits = 16; + resources->MaxTessEvaluationUniformComponents = 1024; + resources->MaxTessEvaluationImageUniforms = 0; + resources->MaxTessEvaluationAtomicCounters = 0; + resources->MaxTessEvaluationAtomicCounterBuffers = 0; + + resources->SubPixelBits = 8; + + resources->MaxSamples = 4; +} + +// +// Driver calls these to create and destroy compiler objects. +// +ShHandle ConstructCompiler(sh::GLenum type, + ShShaderSpec spec, + ShShaderOutput output, + const ShBuiltInResources *resources) +{ + TShHandleBase *base = static_cast(ConstructCompiler(type, spec, output)); + if (base == nullptr) + { + return 0; + } + + TCompiler *compiler = base->getAsCompiler(); + if (compiler == nullptr) + { + return 0; + } + + // Generate built-in symbol table. + if (!compiler->Init(*resources)) + { + Destruct(base); + return 0; + } + + return base; +} + +void Destruct(ShHandle handle) +{ + if (handle == 0) + return; + + TShHandleBase *base = static_cast(handle); + + if (base->getAsCompiler()) + DeleteCompiler(base->getAsCompiler()); +} + +ShBuiltInResources GetBuiltInResources(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + return compiler->getBuiltInResources(); +} + +const std::string &GetBuiltInResourcesString(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + return compiler->getBuiltInResourcesString(); +} + +// +// Do an actual compile on the given strings. The result is left +// in the given compile object. +// +// Return: The return value of ShCompile is really boolean, indicating +// success or failure. +// +bool Compile(const ShHandle handle, + const char *const shaderStrings[], + size_t numStrings, + const ShCompileOptions &compileOptions) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + + return compiler->compile(shaderStrings, numStrings, compileOptions); +} + +void ClearResults(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + compiler->clearResults(); +} + +int GetShaderVersion(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + return compiler->getShaderVersion(); +} + +ShShaderOutput GetShaderOutputType(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + return compiler->getOutputType(); +} + +// +// Return any compiler log of messages for the application. +// +const std::string &GetInfoLog(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + + TInfoSink &infoSink = compiler->getInfoSink(); + return infoSink.info.str(); +} + +// +// Return any object code. +// +const std::string &GetObjectCode(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + + TInfoSink &infoSink = compiler->getInfoSink(); + return infoSink.obj.str(); +} + +// +// Return any object binary code. +// +const BinaryBlob &GetObjectBinaryBlob(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + + TInfoSink &infoSink = compiler->getInfoSink(); + return infoSink.obj.getBinary(); +} + +const std::map *GetNameHashingMap(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + return &(compiler->getNameMap()); +} + +const std::vector *GetUniforms(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + if (!compiler) + { + return nullptr; + } + return &compiler->getUniforms(); +} + +const std::vector *GetInputVaryings(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + if (compiler == nullptr) + { + return nullptr; + } + return &compiler->getInputVaryings(); +} + +const std::vector *GetOutputVaryings(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + if (compiler == nullptr) + { + return nullptr; + } + return &compiler->getOutputVaryings(); +} + +const std::vector *GetVaryings(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + if (compiler == nullptr) + { + return nullptr; + } + + switch (compiler->getShaderType()) + { + case GL_VERTEX_SHADER: + return &compiler->getOutputVaryings(); + case GL_FRAGMENT_SHADER: + return &compiler->getInputVaryings(); + case GL_COMPUTE_SHADER: + ASSERT(compiler->getOutputVaryings().empty() && compiler->getInputVaryings().empty()); + return &compiler->getOutputVaryings(); + // Since geometry shaders have both input and output varyings, we shouldn't call GetVaryings + // on a geometry shader. + default: + return nullptr; + } +} + +const std::vector *GetAttributes(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + if (!compiler) + { + return nullptr; + } + return &compiler->getAttributes(); +} + +const std::vector *GetOutputVariables(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + if (!compiler) + { + return nullptr; + } + return &compiler->getOutputVariables(); +} + +const std::vector *GetInterfaceBlocks(const ShHandle handle) +{ + return GetShaderVariables(handle); +} + +const std::vector *GetUniformBlocks(const ShHandle handle) +{ + ASSERT(handle); + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return &compiler->getUniformBlocks(); +} + +const std::vector *GetShaderStorageBlocks(const ShHandle handle) +{ + ASSERT(handle); + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return &compiler->getShaderStorageBlocks(); +} + +WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return compiler->getComputeShaderLocalSize(); +} + +int GetVertexShaderNumViews(const ShHandle handle) +{ + ASSERT(handle); + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return compiler->getNumViews(); +} + +bool EnablesPerSampleShading(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + if (compiler == nullptr) + { + return false; + } + return compiler->enablesPerSampleShading(); +} + +uint32_t GetShaderSpecConstUsageBits(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + if (compiler == nullptr) + { + return 0; + } + return compiler->getSpecConstUsageBits().bits(); +} + +bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector &variables) +{ + return CheckVariablesInPackingLimits(maxVectors, variables); +} + +bool GetShaderStorageBlockRegister(const ShHandle handle, + const std::string &shaderStorageBlockName, + unsigned int *indexOut) +{ +#ifdef ANGLE_ENABLE_HLSL + ASSERT(indexOut); + + TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); + ASSERT(translator); + + if (!translator->hasShaderStorageBlock(shaderStorageBlockName)) + { + return false; + } + + *indexOut = translator->getShaderStorageBlockRegister(shaderStorageBlockName); + return true; +#else + return false; +#endif // ANGLE_ENABLE_HLSL +} + +bool GetUniformBlockRegister(const ShHandle handle, + const std::string &uniformBlockName, + unsigned int *indexOut) +{ +#ifdef ANGLE_ENABLE_HLSL + ASSERT(indexOut); + + TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); + ASSERT(translator); + + if (!translator->hasUniformBlock(uniformBlockName)) + { + return false; + } + + *indexOut = translator->getUniformBlockRegister(uniformBlockName); + return true; +#else + return false; +#endif // ANGLE_ENABLE_HLSL +} + +bool ShouldUniformBlockUseStructuredBuffer(const ShHandle handle, + const std::string &uniformBlockName) +{ +#ifdef ANGLE_ENABLE_HLSL + TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); + ASSERT(translator); + + return translator->shouldUniformBlockUseStructuredBuffer(uniformBlockName); +#else + return false; +#endif // ANGLE_ENABLE_HLSL +} + +const std::map *GetUniformRegisterMap(const ShHandle handle) +{ +#ifdef ANGLE_ENABLE_HLSL + TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); + ASSERT(translator); + + return translator->getUniformRegisterMap(); +#else + return nullptr; +#endif // ANGLE_ENABLE_HLSL +} + +const std::set *GetSlowCompilingUniformBlockSet(const ShHandle handle) +{ +#ifdef ANGLE_ENABLE_HLSL + TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); + ASSERT(translator); + + return translator->getSlowCompilingUniformBlockSet(); +#else + return nullptr; +#endif // ANGLE_ENABLE_HLSL +} + +unsigned int GetReadonlyImage2DRegisterIndex(const ShHandle handle) +{ +#ifdef ANGLE_ENABLE_HLSL + TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); + ASSERT(translator); + + return translator->getReadonlyImage2DRegisterIndex(); +#else + return 0; +#endif // ANGLE_ENABLE_HLSL +} + +unsigned int GetImage2DRegisterIndex(const ShHandle handle) +{ +#ifdef ANGLE_ENABLE_HLSL + TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); + ASSERT(translator); + + return translator->getImage2DRegisterIndex(); +#else + return 0; +#endif // ANGLE_ENABLE_HLSL +} + +const std::set *GetUsedImage2DFunctionNames(const ShHandle handle) +{ +#ifdef ANGLE_ENABLE_HLSL + TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); + ASSERT(translator); + + return translator->getUsedImage2DFunctionNames(); +#else + return nullptr; +#endif // ANGLE_ENABLE_HLSL +} + +bool HasDiscardInFragmentShader(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return compiler->getShaderType() == GL_FRAGMENT_SHADER && compiler->hasDiscard(); +} + +bool HasValidGeometryShaderInputPrimitiveType(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return compiler->getGeometryShaderInputPrimitiveType() != EptUndefined; +} + +bool HasValidGeometryShaderOutputPrimitiveType(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return compiler->getGeometryShaderOutputPrimitiveType() != EptUndefined; +} + +bool HasValidGeometryShaderMaxVertices(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return compiler->getGeometryShaderMaxVertices() >= 0; +} + +bool HasValidTessGenMode(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return compiler->getTessEvaluationShaderInputPrimitiveType() != EtetUndefined; +} + +bool HasValidTessGenSpacing(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return compiler->getTessEvaluationShaderInputVertexSpacingType() != EtetUndefined; +} + +bool HasValidTessGenVertexOrder(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return compiler->getTessEvaluationShaderInputOrderingType() != EtetUndefined; +} + +bool HasValidTessGenPointMode(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return compiler->getTessEvaluationShaderInputPointType() != EtetUndefined; +} + +GLenum GetGeometryShaderInputPrimitiveType(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderInputPrimitiveType()); +} + +GLenum GetGeometryShaderOutputPrimitiveType(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderOutputPrimitiveType()); +} + +int GetGeometryShaderInvocations(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return compiler->getGeometryShaderInvocations(); +} + +int GetGeometryShaderMaxVertices(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + int maxVertices = compiler->getGeometryShaderMaxVertices(); + ASSERT(maxVertices >= 0); + return maxVertices; +} + +int GetTessControlShaderVertices(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + int vertices = compiler->getTessControlShaderOutputVertices(); + return vertices; +} + +GLenum GetTessGenMode(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return GetTessellationShaderTypeEnum(compiler->getTessEvaluationShaderInputPrimitiveType()); +} + +GLenum GetTessGenSpacing(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return GetTessellationShaderTypeEnum(compiler->getTessEvaluationShaderInputVertexSpacingType()); +} + +GLenum GetTessGenVertexOrder(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return GetTessellationShaderTypeEnum(compiler->getTessEvaluationShaderInputOrderingType()); +} + +GLenum GetTessGenPointMode(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + return GetTessellationShaderTypeEnum(compiler->getTessEvaluationShaderInputPointType()); +} + +unsigned int GetShaderSharedMemorySize(const ShHandle handle) +{ + ASSERT(handle); + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + ASSERT(compiler); + + unsigned int sharedMemorySize = compiler->getSharedMemorySize(); + return sharedMemorySize; +} + +uint32_t GetAdvancedBlendEquations(const ShHandle handle) +{ + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + + return compiler->getAdvancedBlendEquations().bits(); +} + +void InitializeGlslang() +{ + if (initializeGlslangRefCount == 0) + { + GlslangInitialize(); + } + ++initializeGlslangRefCount; + ASSERT(initializeGlslangRefCount < std::numeric_limits::max()); +} + +void FinalizeGlslang() +{ + --initializeGlslangRefCount; + ASSERT(initializeGlslangRefCount >= 0); + if (initializeGlslangRefCount == 0) + { + GlslangFinalize(); + } +} + +// Can't prefix with just _ because then we might introduce a double underscore, which is not safe +// in GLSL (ESSL 3.00.6 section 3.8: All identifiers containing a double underscore are reserved for +// use by the underlying implementation). u is short for user-defined. +const char kUserDefinedNamePrefix[] = "_u"; + +namespace vk +{ +// Interface block name containing the aggregate default uniforms +const char kDefaultUniformsNameVS[] = "defaultUniformsVS"; +const char kDefaultUniformsNameTCS[] = "defaultUniformsTCS"; +const char kDefaultUniformsNameTES[] = "defaultUniformsTES"; +const char kDefaultUniformsNameGS[] = "defaultUniformsGS"; +const char kDefaultUniformsNameFS[] = "defaultUniformsFS"; +const char kDefaultUniformsNameCS[] = "defaultUniformsCS"; + +// Interface block and variable names containing driver uniforms +const char kDriverUniformsBlockName[] = "ANGLEUniformBlock"; +const char kDriverUniformsVarName[] = "ANGLEUniforms"; + +// Interface block array name used for atomic counter emulation +const char kAtomicCountersBlockName[] = "ANGLEAtomicCounters"; + +const char kXfbEmulationGetOffsetsFunctionName[] = "ANGLEGetXfbOffsets"; +const char kXfbEmulationCaptureFunctionName[] = "ANGLECaptureXfb"; +const char kXfbEmulationBufferBlockName[] = "ANGLEXfbBuffer"; +const char kXfbEmulationBufferName[] = "ANGLEXfb"; +const char kXfbEmulationBufferFieldName[] = "xfbOut"; + +const char kTransformPositionFunctionName[] = "ANGLETransformPosition"; + +const char kXfbExtensionPositionOutName[] = "ANGLEXfbPosition"; + +// EXT_shader_framebuffer_fetch / EXT_shader_framebuffer_fetch_non_coherent +const char kInputAttachmentName[] = "ANGLEInputAttachment"; + +} // namespace vk + +const char *BlockLayoutTypeToString(BlockLayoutType type) +{ + switch (type) + { + case BlockLayoutType::BLOCKLAYOUT_STD140: + return "std140"; + case BlockLayoutType::BLOCKLAYOUT_STD430: + return "std430"; + case BlockLayoutType::BLOCKLAYOUT_PACKED: + return "packed"; + case BlockLayoutType::BLOCKLAYOUT_SHARED: + return "shared"; + default: + return "invalid"; + } +} + +const char *BlockTypeToString(BlockType type) +{ + switch (type) + { + case BlockType::BLOCK_BUFFER: + return "buffer"; + case BlockType::BLOCK_UNIFORM: + return "uniform"; + default: + return "invalid"; + } +} + +const char *InterpolationTypeToString(InterpolationType type) +{ + switch (type) + { + case InterpolationType::INTERPOLATION_SMOOTH: + return "smooth"; + case InterpolationType::INTERPOLATION_CENTROID: + return "centroid"; + case InterpolationType::INTERPOLATION_SAMPLE: + return "sample"; + case InterpolationType::INTERPOLATION_FLAT: + return "flat"; + case InterpolationType::INTERPOLATION_NOPERSPECTIVE: + return "noperspective"; + default: + return "invalid"; + } +} +} // namespace sh + +ShCompileOptions::ShCompileOptions() +{ + memset(this, 0, sizeof(*this)); +} + +ShCompileOptions::ShCompileOptions(const ShCompileOptions &other) +{ + memcpy(this, &other, sizeof(*this)); +} +ShCompileOptions &ShCompileOptions::operator=(const ShCompileOptions &other) +{ + memcpy(this, &other, sizeof(*this)); + return *this; +} + +ShBuiltInResources::ShBuiltInResources() +{ + memset(this, 0, sizeof(*this)); +} + +ShBuiltInResources::ShBuiltInResources(const ShBuiltInResources &other) +{ + memcpy(this, &other, sizeof(*this)); +} +ShBuiltInResources &ShBuiltInResources::operator=(const ShBuiltInResources &other) +{ + memcpy(this, &other, sizeof(*this)); + return *this; +} diff --git a/gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockFunctionHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockFunctionHLSL.cpp new file mode 100644 index 0000000000..f4eeab5ab9 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockFunctionHLSL.cpp @@ -0,0 +1,439 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ShaderStorageBlockFunctionHLSL: Wrapper functions for RWByteAddressBuffer Load/Store functions. +// + +#include "compiler/translator/ShaderStorageBlockFunctionHLSL.h" + +#include "common/utilities.h" +#include "compiler/translator/UtilsHLSL.h" +#include "compiler/translator/blocklayout.h" +#include "compiler/translator/blocklayoutHLSL.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +// static +void ShaderStorageBlockFunctionHLSL::OutputSSBOLoadFunctionBody( + TInfoSinkBase &out, + const ShaderStorageBlockFunction &ssboFunction) +{ + const char *convertString; + switch (ssboFunction.type.getBasicType()) + { + case EbtFloat: + convertString = "asfloat("; + break; + case EbtInt: + convertString = "asint("; + break; + case EbtUInt: + convertString = "asuint("; + break; + case EbtBool: + convertString = "asint("; + break; + default: + UNREACHABLE(); + return; + } + + size_t bytesPerComponent = + gl::VariableComponentSize(gl::VariableComponentType(GLVariableType(ssboFunction.type))); + out << " " << ssboFunction.typeString << " result"; + if (ssboFunction.type.isScalar()) + { + size_t offset = ssboFunction.swizzleOffsets[0] * bytesPerComponent; + out << " = " << convertString << "buffer.Load(loc + " << offset << "));\n "; + } + else if (ssboFunction.type.isVector()) + { + if (ssboFunction.rowMajor || !ssboFunction.isDefaultSwizzle) + { + size_t componentStride = bytesPerComponent; + if (ssboFunction.rowMajor) + { + componentStride = ssboFunction.matrixStride; + } + + out << " = {"; + for (const int offset : ssboFunction.swizzleOffsets) + { + size_t offsetInBytes = offset * componentStride; + out << convertString << "buffer.Load(loc + " << offsetInBytes << ")),"; + } + out << "};\n"; + } + else + { + out << " = " << convertString << "buffer.Load" + << static_cast(ssboFunction.type.getNominalSize()) << "(loc));\n"; + } + } + else if (ssboFunction.type.isMatrix()) + { + if (ssboFunction.rowMajor) + { + out << ";"; + out << " float" << static_cast(ssboFunction.type.getRows()) << "x" + << static_cast(ssboFunction.type.getCols()) << " tmp_ = {"; + for (uint8_t rowIndex = 0; rowIndex < ssboFunction.type.getRows(); rowIndex++) + { + out << "asfloat(buffer.Load" << static_cast(ssboFunction.type.getCols()) + << "(loc + " << rowIndex * ssboFunction.matrixStride << ")), "; + } + out << "};\n"; + out << " result = transpose(tmp_);\n"; + } + else + { + out << " = {"; + for (uint8_t columnIndex = 0; columnIndex < ssboFunction.type.getCols(); columnIndex++) + { + out << "asfloat(buffer.Load" << static_cast(ssboFunction.type.getRows()) + << "(loc + " << columnIndex * ssboFunction.matrixStride << ")), "; + } + out << "};\n"; + } + } + else + { + // TODO(jiajia.qin@intel.com): Process all possible return types. http://anglebug.com/1951 + out << ";\n"; + } + + out << " return result;\n"; + return; +} + +// static +void ShaderStorageBlockFunctionHLSL::OutputSSBOStoreFunctionBody( + TInfoSinkBase &out, + const ShaderStorageBlockFunction &ssboFunction) +{ + size_t bytesPerComponent = + gl::VariableComponentSize(gl::VariableComponentType(GLVariableType(ssboFunction.type))); + if (ssboFunction.type.isScalar()) + { + size_t offset = ssboFunction.swizzleOffsets[0] * bytesPerComponent; + if (ssboFunction.type.getBasicType() == EbtBool) + { + out << " buffer.Store(loc + " << offset << ", uint(value));\n"; + } + else + { + out << " buffer.Store(loc + " << offset << ", asuint(value));\n"; + } + } + else if (ssboFunction.type.isVector()) + { + out << " uint" << static_cast(ssboFunction.type.getNominalSize()) + << " _value;\n"; + if (ssboFunction.type.getBasicType() == EbtBool) + { + out << " _value = uint" << static_cast(ssboFunction.type.getNominalSize()) + << "(value);\n"; + } + else + { + out << " _value = asuint(value);\n"; + } + + if (ssboFunction.rowMajor || !ssboFunction.isDefaultSwizzle) + { + size_t componentStride = bytesPerComponent; + if (ssboFunction.rowMajor) + { + componentStride = ssboFunction.matrixStride; + } + const TVector &swizzleOffsets = ssboFunction.swizzleOffsets; + for (int index = 0; index < static_cast(swizzleOffsets.size()); index++) + { + size_t offsetInBytes = swizzleOffsets[index] * componentStride; + out << "buffer.Store(loc + " << offsetInBytes << ", _value[" << index << "]);\n"; + } + } + else + { + out << " buffer.Store" << static_cast(ssboFunction.type.getNominalSize()) + << "(loc, _value);\n"; + } + } + else if (ssboFunction.type.isMatrix()) + { + if (ssboFunction.rowMajor) + { + out << " float" << static_cast(ssboFunction.type.getRows()) << "x" + << static_cast(ssboFunction.type.getCols()) + << " tmp_ = transpose(value);\n"; + for (uint8_t rowIndex = 0; rowIndex < ssboFunction.type.getRows(); rowIndex++) + { + out << " buffer.Store" << static_cast(ssboFunction.type.getCols()) + << "(loc + " << rowIndex * ssboFunction.matrixStride << ", asuint(tmp_[" + << static_cast(rowIndex) << "]));\n"; + } + } + else + { + for (uint8_t columnIndex = 0; columnIndex < ssboFunction.type.getCols(); columnIndex++) + { + out << " buffer.Store" << static_cast(ssboFunction.type.getRows()) + << "(loc + " << columnIndex * ssboFunction.matrixStride << ", asuint(value[" + << static_cast(columnIndex) << "]));\n"; + } + } + } + else + { + // TODO(jiajia.qin@intel.com): Process all possible return types. http://anglebug.com/1951 + } +} + +// static +void ShaderStorageBlockFunctionHLSL::OutputSSBOLengthFunctionBody(TInfoSinkBase &out, + int unsizedArrayStride) +{ + out << " uint dim = 0;\n"; + out << " buffer.GetDimensions(dim);\n"; + out << " return int((dim - loc)/uint(" << unsizedArrayStride << "));\n"; +} + +// static +void ShaderStorageBlockFunctionHLSL::OutputSSBOAtomicMemoryFunctionBody( + TInfoSinkBase &out, + const ShaderStorageBlockFunction &ssboFunction) +{ + out << " " << ssboFunction.typeString << " original_value;\n"; + switch (ssboFunction.method) + { + case SSBOMethod::ATOMIC_ADD: + out << " buffer.InterlockedAdd(loc, value, original_value);\n"; + break; + case SSBOMethod::ATOMIC_MIN: + out << " buffer.InterlockedMin(loc, value, original_value);\n"; + break; + case SSBOMethod::ATOMIC_MAX: + out << " buffer.InterlockedMax(loc, value, original_value);\n"; + break; + case SSBOMethod::ATOMIC_AND: + out << " buffer.InterlockedAnd(loc, value, original_value);\n"; + break; + case SSBOMethod::ATOMIC_OR: + out << " buffer.InterlockedOr(loc, value, original_value);\n"; + break; + case SSBOMethod::ATOMIC_XOR: + out << " buffer.InterlockedXor(loc, value, original_value);\n"; + break; + case SSBOMethod::ATOMIC_EXCHANGE: + out << " buffer.InterlockedExchange(loc, value, original_value);\n"; + break; + case SSBOMethod::ATOMIC_COMPSWAP: + out << " buffer.InterlockedCompareExchange(loc, compare_value, value, " + "original_value);\n"; + break; + default: + UNREACHABLE(); + } + out << " return original_value;\n"; +} + +bool ShaderStorageBlockFunctionHLSL::ShaderStorageBlockFunction::operator<( + const ShaderStorageBlockFunction &rhs) const +{ + return functionName < rhs.functionName; +} + +TString ShaderStorageBlockFunctionHLSL::registerShaderStorageBlockFunction( + const TType &type, + SSBOMethod method, + TLayoutBlockStorage storage, + bool rowMajor, + int matrixStride, + int unsizedArrayStride, + TIntermSwizzle *swizzleNode) +{ + ShaderStorageBlockFunction ssboFunction; + ssboFunction.typeString = TypeString(type); + ssboFunction.method = method; + switch (method) + { + case SSBOMethod::LOAD: + ssboFunction.functionName = "_Load_"; + break; + case SSBOMethod::STORE: + ssboFunction.functionName = "_Store_"; + break; + case SSBOMethod::LENGTH: + ssboFunction.unsizedArrayStride = unsizedArrayStride; + ssboFunction.functionName = "_Length_" + str(unsizedArrayStride); + mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); + return ssboFunction.functionName; + case SSBOMethod::ATOMIC_ADD: + ssboFunction.functionName = "_ssbo_atomicAdd_" + ssboFunction.typeString; + mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); + return ssboFunction.functionName; + case SSBOMethod::ATOMIC_MIN: + ssboFunction.functionName = "_ssbo_atomicMin_" + ssboFunction.typeString; + mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); + return ssboFunction.functionName; + case SSBOMethod::ATOMIC_MAX: + ssboFunction.functionName = "_ssbo_atomicMax_" + ssboFunction.typeString; + mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); + return ssboFunction.functionName; + case SSBOMethod::ATOMIC_AND: + ssboFunction.functionName = "_ssbo_atomicAnd_" + ssboFunction.typeString; + mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); + return ssboFunction.functionName; + case SSBOMethod::ATOMIC_OR: + ssboFunction.functionName = "_ssbo_atomicOr_" + ssboFunction.typeString; + mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); + return ssboFunction.functionName; + case SSBOMethod::ATOMIC_XOR: + ssboFunction.functionName = "_ssbo_atomicXor_" + ssboFunction.typeString; + mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); + return ssboFunction.functionName; + case SSBOMethod::ATOMIC_EXCHANGE: + ssboFunction.functionName = "_ssbo_atomicExchange_" + ssboFunction.typeString; + mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); + return ssboFunction.functionName; + case SSBOMethod::ATOMIC_COMPSWAP: + ssboFunction.functionName = "_ssbo_atomicCompSwap_" + ssboFunction.typeString; + mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); + return ssboFunction.functionName; + default: + UNREACHABLE(); + } + + ssboFunction.functionName += ssboFunction.typeString; + ssboFunction.type = type; + if (swizzleNode != nullptr) + { + ssboFunction.swizzleOffsets = swizzleNode->getSwizzleOffsets(); + ssboFunction.isDefaultSwizzle = false; + } + else + { + if (ssboFunction.type.getNominalSize() > 1) + { + for (uint8_t index = 0; index < ssboFunction.type.getNominalSize(); index++) + { + ssboFunction.swizzleOffsets.push_back(index); + } + } + else + { + ssboFunction.swizzleOffsets.push_back(0); + } + + ssboFunction.isDefaultSwizzle = true; + } + ssboFunction.rowMajor = rowMajor; + ssboFunction.matrixStride = matrixStride; + ssboFunction.functionName += "_" + TString(getBlockStorageString(storage)); + + if (rowMajor) + { + ssboFunction.functionName += "_rm_"; + } + else + { + ssboFunction.functionName += "_cm_"; + } + + for (const int offset : ssboFunction.swizzleOffsets) + { + switch (offset) + { + case 0: + ssboFunction.functionName += "x"; + break; + case 1: + ssboFunction.functionName += "y"; + break; + case 2: + ssboFunction.functionName += "z"; + break; + case 3: + ssboFunction.functionName += "w"; + break; + default: + UNREACHABLE(); + } + } + + mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); + return ssboFunction.functionName; +} + +void ShaderStorageBlockFunctionHLSL::shaderStorageBlockFunctionHeader(TInfoSinkBase &out) +{ + for (const ShaderStorageBlockFunction &ssboFunction : mRegisteredShaderStorageBlockFunctions) + { + switch (ssboFunction.method) + { + case SSBOMethod::LOAD: + { + // Function header + out << ssboFunction.typeString << " " << ssboFunction.functionName + << "(RWByteAddressBuffer buffer, uint loc)\n"; + out << "{\n"; + OutputSSBOLoadFunctionBody(out, ssboFunction); + break; + } + case SSBOMethod::STORE: + { + // Function header + out << "void " << ssboFunction.functionName + << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString + << " value)\n"; + out << "{\n"; + OutputSSBOStoreFunctionBody(out, ssboFunction); + break; + } + case SSBOMethod::LENGTH: + { + out << "int " << ssboFunction.functionName + << "(RWByteAddressBuffer buffer, uint loc)\n"; + out << "{\n"; + OutputSSBOLengthFunctionBody(out, ssboFunction.unsizedArrayStride); + break; + } + case SSBOMethod::ATOMIC_ADD: + case SSBOMethod::ATOMIC_MIN: + case SSBOMethod::ATOMIC_MAX: + case SSBOMethod::ATOMIC_AND: + case SSBOMethod::ATOMIC_OR: + case SSBOMethod::ATOMIC_XOR: + case SSBOMethod::ATOMIC_EXCHANGE: + { + out << ssboFunction.typeString << " " << ssboFunction.functionName + << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString + << " value)\n"; + out << "{\n"; + + OutputSSBOAtomicMemoryFunctionBody(out, ssboFunction); + break; + } + case SSBOMethod::ATOMIC_COMPSWAP: + { + out << ssboFunction.typeString << " " << ssboFunction.functionName + << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString + << " compare_value, " << ssboFunction.typeString << " value)\n"; + out << "{\n"; + OutputSSBOAtomicMemoryFunctionBody(out, ssboFunction); + break; + } + default: + UNREACHABLE(); + } + + out << "}\n" + "\n"; + } +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockFunctionHLSL.h b/gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockFunctionHLSL.h new file mode 100644 index 0000000000..0d3cd0291b --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockFunctionHLSL.h @@ -0,0 +1,94 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ShaderStorageBlockOutputHLSL: A traverser to translate a ssbo_access_chain to an offset of +// RWByteAddressBuffer. +// //EOpIndexDirectInterfaceBlock +// ssbo_variable := +// | the name of the SSBO +// | the name of a variable in an SSBO backed interface block + +// // EOpIndexInDirect +// // EOpIndexDirect +// ssbo_array_indexing := ssbo_access_chain[expr_no_ssbo] + +// // EOpIndexDirectStruct +// ssbo_structure_access := ssbo_access_chain.identifier + +// ssbo_access_chain := +// | ssbo_variable +// | ssbo_array_indexing +// | ssbo_structure_access +// + +#ifndef COMPILER_TRANSLATOR_SHADERSTORAGEBLOCKFUNCTIONHLSL_H_ +#define COMPILER_TRANSLATOR_SHADERSTORAGEBLOCKFUNCTIONHLSL_H_ + +#include + +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/Types.h" + +namespace sh +{ + +class TIntermSwizzle; +enum class SSBOMethod +{ + LOAD, + STORE, + LENGTH, + ATOMIC_ADD, + ATOMIC_MIN, + ATOMIC_MAX, + ATOMIC_AND, + ATOMIC_OR, + ATOMIC_XOR, + ATOMIC_EXCHANGE, + ATOMIC_COMPSWAP +}; + +class ShaderStorageBlockFunctionHLSL final : angle::NonCopyable +{ + public: + TString registerShaderStorageBlockFunction(const TType &type, + SSBOMethod method, + TLayoutBlockStorage storage, + bool rowMajor, + int matrixStride, + int unsizedArrayStride, + TIntermSwizzle *node); + + void shaderStorageBlockFunctionHeader(TInfoSinkBase &out); + + private: + struct ShaderStorageBlockFunction + { + bool operator<(const ShaderStorageBlockFunction &rhs) const; + TString functionName; + TString typeString; + SSBOMethod method; + TType type; + bool rowMajor; + int matrixStride; + int unsizedArrayStride; + TVector swizzleOffsets; + bool isDefaultSwizzle; + }; + + static void OutputSSBOLoadFunctionBody(TInfoSinkBase &out, + const ShaderStorageBlockFunction &ssboFunction); + static void OutputSSBOStoreFunctionBody(TInfoSinkBase &out, + const ShaderStorageBlockFunction &ssboFunction); + static void OutputSSBOLengthFunctionBody(TInfoSinkBase &out, int unsizedArrayStride); + static void OutputSSBOAtomicMemoryFunctionBody(TInfoSinkBase &out, + const ShaderStorageBlockFunction &ssboFunction); + using ShaderStorageBlockFunctionSet = std::set; + ShaderStorageBlockFunctionSet mRegisteredShaderStorageBlockFunctions; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_SHADERSTORAGEBLOCKFUNCTIONHLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockOutputHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockOutputHLSL.cpp new file mode 100644 index 0000000000..2ff01e439e --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockOutputHLSL.cpp @@ -0,0 +1,667 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ShaderStorageBlockOutputHLSL: A traverser to translate a ssbo_access_chain to an offset of +// RWByteAddressBuffer. +// //EOpIndexDirectInterfaceBlock +// ssbo_variable := +// | the name of the SSBO +// | the name of a variable in an SSBO backed interface block + +// // EOpIndexInDirect +// // EOpIndexDirect +// ssbo_array_indexing := ssbo_access_chain[expr_no_ssbo] + +// // EOpIndexDirectStruct +// ssbo_structure_access := ssbo_access_chain.identifier + +// ssbo_access_chain := +// | ssbo_variable +// | ssbo_array_indexing +// | ssbo_structure_access +// + +#include "compiler/translator/ShaderStorageBlockOutputHLSL.h" + +#include "compiler/translator/ResourcesHLSL.h" +#include "compiler/translator/blocklayoutHLSL.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +constexpr const char kShaderStorageDeclarationString[] = + "// @@ SHADER STORAGE DECLARATION STRING @@"; + +void GetBlockLayoutInfo(TIntermTyped *node, + bool rowMajorAlreadyAssigned, + TLayoutBlockStorage *storage, + bool *rowMajor) +{ + TIntermSwizzle *swizzleNode = node->getAsSwizzleNode(); + if (swizzleNode) + { + return GetBlockLayoutInfo(swizzleNode->getOperand(), rowMajorAlreadyAssigned, storage, + rowMajor); + } + + TIntermBinary *binaryNode = node->getAsBinaryNode(); + if (binaryNode) + { + switch (binaryNode->getOp()) + { + case EOpIndexDirectInterfaceBlock: + { + // The column_major/row_major qualifier of a field member overrides the interface + // block's row_major/column_major. So we can assign rowMajor here and don't need to + // assign it again. But we still need to call recursively to get the storage's + // value. + const TType &type = node->getType(); + *rowMajor = type.getLayoutQualifier().matrixPacking == EmpRowMajor; + return GetBlockLayoutInfo(binaryNode->getLeft(), true, storage, rowMajor); + } + case EOpIndexIndirect: + case EOpIndexDirect: + case EOpIndexDirectStruct: + return GetBlockLayoutInfo(binaryNode->getLeft(), rowMajorAlreadyAssigned, storage, + rowMajor); + default: + UNREACHABLE(); + return; + } + } + + const TType &type = node->getType(); + ASSERT(type.getQualifier() == EvqBuffer); + const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + ASSERT(interfaceBlock); + *storage = interfaceBlock->blockStorage(); + // If the block doesn't have an instance name, rowMajorAlreadyAssigned will be false. In + // this situation, we still need to set rowMajor's value. + if (!rowMajorAlreadyAssigned) + { + *rowMajor = type.getLayoutQualifier().matrixPacking == EmpRowMajor; + } +} + +// It's possible that the current type has lost the original layout information. So we should pass +// the right layout information to GetBlockMemberInfoByType. +const BlockMemberInfo GetBlockMemberInfoByType(const TType &type, + TLayoutBlockStorage storage, + bool rowMajor) +{ + sh::Std140BlockEncoder std140Encoder; + sh::Std430BlockEncoder std430Encoder; + sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED, false); + sh::BlockLayoutEncoder *encoder = nullptr; + + if (storage == EbsStd140) + { + encoder = &std140Encoder; + } + else if (storage == EbsStd430) + { + encoder = &std430Encoder; + } + else + { + encoder = &hlslEncoder; + } + + std::vector arraySizes; + const TSpan &typeArraySizes = type.getArraySizes(); + if (!typeArraySizes.empty()) + { + arraySizes.assign(typeArraySizes.begin(), typeArraySizes.end()); + } + return encoder->encodeType(GLVariableType(type), arraySizes, rowMajor); +} + +const TField *GetFieldMemberInShaderStorageBlock(const TInterfaceBlock *interfaceBlock, + const ImmutableString &variableName) +{ + for (const TField *field : interfaceBlock->fields()) + { + if (field->name() == variableName) + { + return field; + } + } + return nullptr; +} + +const InterfaceBlock *FindInterfaceBlock(const TInterfaceBlock *needle, + const std::vector &haystack) +{ + for (const InterfaceBlock &block : haystack) + { + if (strcmp(block.name.c_str(), needle->name().data()) == 0) + { + ASSERT(block.fields.size() == needle->fields().size()); + return █ + } + } + + UNREACHABLE(); + return nullptr; +} + +std::string StripArrayIndices(const std::string &nameIn) +{ + std::string name = nameIn; + size_t pos = name.find('['); + while (pos != std::string::npos) + { + size_t closePos = name.find(']', pos); + ASSERT(closePos != std::string::npos); + name.erase(pos, closePos - pos + 1); + pos = name.find('[', pos); + } + ASSERT(name.find(']') == std::string::npos); + return name; +} + +// Does not include any array indices. +void MapVariableToField(const ShaderVariable &variable, + const TField *field, + std::string currentName, + ShaderVarToFieldMap *shaderVarToFieldMap) +{ + ASSERT((field->type()->getStruct() == nullptr) == variable.fields.empty()); + (*shaderVarToFieldMap)[currentName] = field; + + if (!variable.fields.empty()) + { + const TStructure *subStruct = field->type()->getStruct(); + ASSERT(variable.fields.size() == subStruct->fields().size()); + + for (size_t index = 0; index < variable.fields.size(); ++index) + { + const TField *subField = subStruct->fields()[index]; + const ShaderVariable &subVariable = variable.fields[index]; + std::string subName = currentName + "." + subVariable.name; + MapVariableToField(subVariable, subField, subName, shaderVarToFieldMap); + } + } +} + +class BlockInfoVisitor final : public BlockEncoderVisitor +{ + public: + BlockInfoVisitor(const std::string &prefix, + TLayoutBlockStorage storage, + const ShaderVarToFieldMap &shaderVarToFieldMap, + BlockMemberInfoMap *blockInfoOut) + : BlockEncoderVisitor(prefix, "", getEncoder(storage)), + mShaderVarToFieldMap(shaderVarToFieldMap), + mBlockInfoOut(blockInfoOut), + mHLSLEncoder(HLSLBlockEncoder::ENCODE_PACKED, false), + mStorage(storage) + {} + + BlockLayoutEncoder *getEncoder(TLayoutBlockStorage storage) + { + switch (storage) + { + case EbsStd140: + return &mStd140Encoder; + case EbsStd430: + return &mStd430Encoder; + default: + return &mHLSLEncoder; + } + } + + void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override + { + BlockEncoderVisitor::enterStructAccess(structVar, isRowMajor); + + std::string variableName = StripArrayIndices(collapseNameStack()); + + // Remove the trailing "." + variableName.pop_back(); + + BlockInfoVisitor childVisitor(variableName, mStorage, mShaderVarToFieldMap, mBlockInfoOut); + childVisitor.getEncoder(mStorage)->enterAggregateType(structVar); + TraverseShaderVariables(structVar.fields, isRowMajor, &childVisitor); + childVisitor.getEncoder(mStorage)->exitAggregateType(structVar); + + int offset = static_cast(getEncoder(mStorage)->getCurrentOffset()); + int arrayStride = static_cast(childVisitor.getEncoder(mStorage)->getCurrentOffset()); + + auto iter = mShaderVarToFieldMap.find(variableName); + if (iter == mShaderVarToFieldMap.end()) + return; + + const TField *structField = iter->second; + if (mBlockInfoOut->count(structField) == 0) + { + mBlockInfoOut->emplace(structField, BlockMemberInfo(offset, arrayStride, -1, false)); + } + } + + void encodeVariable(const ShaderVariable &variable, + const BlockMemberInfo &variableInfo, + const std::string &name, + const std::string &mappedName) override + { + auto iter = mShaderVarToFieldMap.find(StripArrayIndices(name)); + if (iter == mShaderVarToFieldMap.end()) + return; + + const TField *field = iter->second; + if (mBlockInfoOut->count(field) == 0) + { + mBlockInfoOut->emplace(field, variableInfo); + } + } + + private: + const ShaderVarToFieldMap &mShaderVarToFieldMap; + BlockMemberInfoMap *mBlockInfoOut; + Std140BlockEncoder mStd140Encoder; + Std430BlockEncoder mStd430Encoder; + HLSLBlockEncoder mHLSLEncoder; + TLayoutBlockStorage mStorage; +}; + +void GetShaderStorageBlockMembersInfo(const TInterfaceBlock *interfaceBlock, + const std::vector &shaderStorageBlocks, + BlockMemberInfoMap *blockInfoOut) +{ + // Find the sh::InterfaceBlock. + const InterfaceBlock *block = FindInterfaceBlock(interfaceBlock, shaderStorageBlocks); + ASSERT(block); + + // Map ShaderVariable to TField. + ShaderVarToFieldMap shaderVarToFieldMap; + for (size_t index = 0; index < block->fields.size(); ++index) + { + const TField *field = interfaceBlock->fields()[index]; + const ShaderVariable &variable = block->fields[index]; + MapVariableToField(variable, field, variable.name, &shaderVarToFieldMap); + } + + BlockInfoVisitor visitor("", interfaceBlock->blockStorage(), shaderVarToFieldMap, blockInfoOut); + TraverseShaderVariables(block->fields, false, &visitor); +} + +TIntermTyped *Mul(TIntermTyped *left, TIntermTyped *right) +{ + return left && right ? new TIntermBinary(EOpMul, left, right) : nullptr; +} + +TIntermTyped *Add(TIntermTyped *left, TIntermTyped *right) +{ + return left ? right ? new TIntermBinary(EOpAdd, left, right) : left : right; +} + +} // anonymous namespace + +ShaderStorageBlockOutputHLSL::ShaderStorageBlockOutputHLSL( + OutputHLSL *outputHLSL, + ResourcesHLSL *resourcesHLSL, + const std::vector &shaderStorageBlocks) + : mOutputHLSL(outputHLSL), + mResourcesHLSL(resourcesHLSL), + mShaderStorageBlocks(shaderStorageBlocks) +{ + mSSBOFunctionHLSL = new ShaderStorageBlockFunctionHLSL; +} + +ShaderStorageBlockOutputHLSL::~ShaderStorageBlockOutputHLSL() +{ + SafeDelete(mSSBOFunctionHLSL); +} + +void ShaderStorageBlockOutputHLSL::outputStoreFunctionCallPrefix(TIntermTyped *node) +{ + traverseSSBOAccess(node, SSBOMethod::STORE); +} + +void ShaderStorageBlockOutputHLSL::outputLoadFunctionCall(TIntermTyped *node) +{ + traverseSSBOAccess(node, SSBOMethod::LOAD); + mOutputHLSL->getInfoSink() << ")"; +} + +void ShaderStorageBlockOutputHLSL::outputLengthFunctionCall(TIntermTyped *node) +{ + traverseSSBOAccess(node, SSBOMethod::LENGTH); + mOutputHLSL->getInfoSink() << ")"; +} + +void ShaderStorageBlockOutputHLSL::outputAtomicMemoryFunctionCallPrefix(TIntermTyped *node, + TOperator op) +{ + switch (op) + { + case EOpAtomicAdd: + traverseSSBOAccess(node, SSBOMethod::ATOMIC_ADD); + break; + case EOpAtomicMin: + traverseSSBOAccess(node, SSBOMethod::ATOMIC_MIN); + break; + case EOpAtomicMax: + traverseSSBOAccess(node, SSBOMethod::ATOMIC_MAX); + break; + case EOpAtomicAnd: + traverseSSBOAccess(node, SSBOMethod::ATOMIC_AND); + break; + case EOpAtomicOr: + traverseSSBOAccess(node, SSBOMethod::ATOMIC_OR); + break; + case EOpAtomicXor: + traverseSSBOAccess(node, SSBOMethod::ATOMIC_XOR); + break; + case EOpAtomicExchange: + traverseSSBOAccess(node, SSBOMethod::ATOMIC_EXCHANGE); + break; + case EOpAtomicCompSwap: + traverseSSBOAccess(node, SSBOMethod::ATOMIC_COMPSWAP); + break; + default: + UNREACHABLE(); + break; + } +} + +// Note that we must calculate the matrix stride here instead of ShaderStorageBlockFunctionHLSL. +// It's because that if the current node's type is a vector which comes from a matrix, we will +// lose the matrix type info once we enter ShaderStorageBlockFunctionHLSL. +int ShaderStorageBlockOutputHLSL::getMatrixStride(TIntermTyped *node, + TLayoutBlockStorage storage, + bool rowMajor, + bool *isRowMajorMatrix) const +{ + if (node->getType().isMatrix()) + { + *isRowMajorMatrix = rowMajor; + return GetBlockMemberInfoByType(node->getType(), storage, rowMajor).matrixStride; + } + + if (node->getType().isVector()) + { + TIntermBinary *binaryNode = node->getAsBinaryNode(); + if (binaryNode) + { + return getMatrixStride(binaryNode->getLeft(), storage, rowMajor, isRowMajorMatrix); + } + else + { + TIntermSwizzle *swizzleNode = node->getAsSwizzleNode(); + if (swizzleNode) + { + return getMatrixStride(swizzleNode->getOperand(), storage, rowMajor, + isRowMajorMatrix); + } + } + } + return 0; +} + +void ShaderStorageBlockOutputHLSL::collectShaderStorageBlocks(TIntermTyped *node) +{ + TIntermSwizzle *swizzleNode = node->getAsSwizzleNode(); + if (swizzleNode) + { + return collectShaderStorageBlocks(swizzleNode->getOperand()); + } + + TIntermBinary *binaryNode = node->getAsBinaryNode(); + if (binaryNode) + { + switch (binaryNode->getOp()) + { + case EOpIndexDirectInterfaceBlock: + case EOpIndexIndirect: + case EOpIndexDirect: + case EOpIndexDirectStruct: + return collectShaderStorageBlocks(binaryNode->getLeft()); + default: + UNREACHABLE(); + return; + } + } + + const TIntermSymbol *symbolNode = node->getAsSymbolNode(); + const TType &type = symbolNode->getType(); + ASSERT(type.getQualifier() == EvqBuffer); + const TVariable &variable = symbolNode->variable(); + + const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + ASSERT(interfaceBlock); + if (mReferencedShaderStorageBlocks.count(interfaceBlock->uniqueId().get()) == 0) + { + const TVariable *instanceVariable = nullptr; + if (type.isInterfaceBlock()) + { + instanceVariable = &variable; + } + mReferencedShaderStorageBlocks[interfaceBlock->uniqueId().get()] = + new TReferencedBlock(interfaceBlock, instanceVariable); + GetShaderStorageBlockMembersInfo(interfaceBlock, mShaderStorageBlocks, + &mBlockMemberInfoMap); + } +} + +void ShaderStorageBlockOutputHLSL::traverseSSBOAccess(TIntermTyped *node, SSBOMethod method) +{ + // TODO: Merge collectShaderStorageBlocks and GetBlockLayoutInfo to simplify the code. + collectShaderStorageBlocks(node); + + // Note that we don't have correct BlockMemberInfo from mBlockMemberInfoMap at the current + // point. But we must use those information to generate the right function name. So here we have + // to calculate them again. + TLayoutBlockStorage storage; + bool rowMajor; + GetBlockLayoutInfo(node, false, &storage, &rowMajor); + int unsizedArrayStride = 0; + if (node->getType().isUnsizedArray()) + { + // The unsized array member must be the last member of a shader storage block. + TIntermBinary *binaryNode = node->getAsBinaryNode(); + if (binaryNode) + { + const TInterfaceBlock *interfaceBlock = + binaryNode->getLeft()->getType().getInterfaceBlock(); + ASSERT(interfaceBlock); + const TIntermConstantUnion *index = binaryNode->getRight()->getAsConstantUnion(); + const TField *field = interfaceBlock->fields()[index->getIConst(0)]; + auto fieldInfoIter = mBlockMemberInfoMap.find(field); + ASSERT(fieldInfoIter != mBlockMemberInfoMap.end()); + unsizedArrayStride = fieldInfoIter->second.arrayStride; + } + else + { + const TIntermSymbol *symbolNode = node->getAsSymbolNode(); + const TVariable &variable = symbolNode->variable(); + const TInterfaceBlock *interfaceBlock = symbolNode->getType().getInterfaceBlock(); + ASSERT(interfaceBlock); + const TField *field = + GetFieldMemberInShaderStorageBlock(interfaceBlock, variable.name()); + auto fieldInfoIter = mBlockMemberInfoMap.find(field); + ASSERT(fieldInfoIter != mBlockMemberInfoMap.end()); + unsizedArrayStride = fieldInfoIter->second.arrayStride; + } + } + bool isRowMajorMatrix = false; + int matrixStride = getMatrixStride(node, storage, rowMajor, &isRowMajorMatrix); + + const TString &functionName = mSSBOFunctionHLSL->registerShaderStorageBlockFunction( + node->getType(), method, storage, isRowMajorMatrix, matrixStride, unsizedArrayStride, + node->getAsSwizzleNode()); + TInfoSinkBase &out = mOutputHLSL->getInfoSink(); + out << functionName; + out << "("; + BlockMemberInfo blockMemberInfo; + TIntermNode *loc = traverseNode(out, node, &blockMemberInfo); + out << ", "; + loc->traverse(mOutputHLSL); +} + +void ShaderStorageBlockOutputHLSL::writeShaderStorageBlocksHeader(GLenum shaderType, + TInfoSinkBase &out) const +{ + if (mReferencedShaderStorageBlocks.empty()) + { + return; + } + + mResourcesHLSL->allocateShaderStorageBlockRegisters(mReferencedShaderStorageBlocks); + out << "// Shader Storage Blocks\n\n"; + if (shaderType == GL_COMPUTE_SHADER) + { + out << mResourcesHLSL->shaderStorageBlocksHeader(mReferencedShaderStorageBlocks); + } + else + { + out << kShaderStorageDeclarationString << "\n"; + } + mSSBOFunctionHLSL->shaderStorageBlockFunctionHeader(out); +} + +TIntermTyped *ShaderStorageBlockOutputHLSL::traverseNode(TInfoSinkBase &out, + TIntermTyped *node, + BlockMemberInfo *blockMemberInfo) +{ + if (TIntermSymbol *symbolNode = node->getAsSymbolNode()) + { + const TVariable &variable = symbolNode->variable(); + const TType &type = variable.getType(); + if (type.isInterfaceBlock()) + { + out << DecorateVariableIfNeeded(variable); + } + else + { + const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + out << Decorate(interfaceBlock->name()); + const TField *field = + GetFieldMemberInShaderStorageBlock(interfaceBlock, variable.name()); + return createFieldOffset(field, blockMemberInfo); + } + } + else if (TIntermSwizzle *swizzleNode = node->getAsSwizzleNode()) + { + return traverseNode(out, swizzleNode->getOperand(), blockMemberInfo); + } + else if (TIntermBinary *binaryNode = node->getAsBinaryNode()) + { + switch (binaryNode->getOp()) + { + case EOpIndexDirect: + { + const TType &leftType = binaryNode->getLeft()->getType(); + if (leftType.isInterfaceBlock()) + { + ASSERT(leftType.getQualifier() == EvqBuffer); + TIntermSymbol *instanceArraySymbol = binaryNode->getLeft()->getAsSymbolNode(); + + const int arrayIndex = + binaryNode->getRight()->getAsConstantUnion()->getIConst(0); + out << mResourcesHLSL->InterfaceBlockInstanceString( + instanceArraySymbol->getName(), arrayIndex); + } + else + { + return writeEOpIndexDirectOrIndirectOutput(out, binaryNode, blockMemberInfo); + } + break; + } + case EOpIndexIndirect: + { + // We do not currently support indirect references to interface blocks + ASSERT(binaryNode->getLeft()->getBasicType() != EbtInterfaceBlock); + return writeEOpIndexDirectOrIndirectOutput(out, binaryNode, blockMemberInfo); + } + case EOpIndexDirectStruct: + { + // We do not currently support direct references to interface blocks + ASSERT(binaryNode->getLeft()->getBasicType() != EbtInterfaceBlock); + TIntermTyped *left = traverseNode(out, binaryNode->getLeft(), blockMemberInfo); + const TStructure *structure = binaryNode->getLeft()->getType().getStruct(); + const TIntermConstantUnion *index = binaryNode->getRight()->getAsConstantUnion(); + const TField *field = structure->fields()[index->getIConst(0)]; + return Add(createFieldOffset(field, blockMemberInfo), left); + } + case EOpIndexDirectInterfaceBlock: + { + ASSERT(IsInShaderStorageBlock(binaryNode->getLeft())); + traverseNode(out, binaryNode->getLeft(), blockMemberInfo); + const TInterfaceBlock *interfaceBlock = + binaryNode->getLeft()->getType().getInterfaceBlock(); + const TIntermConstantUnion *index = binaryNode->getRight()->getAsConstantUnion(); + const TField *field = interfaceBlock->fields()[index->getIConst(0)]; + return createFieldOffset(field, blockMemberInfo); + } + default: + return nullptr; + } + } + return nullptr; +} + +TIntermTyped *ShaderStorageBlockOutputHLSL::writeEOpIndexDirectOrIndirectOutput( + TInfoSinkBase &out, + TIntermBinary *node, + BlockMemberInfo *blockMemberInfo) +{ + ASSERT(IsInShaderStorageBlock(node->getLeft())); + TIntermTyped *left = traverseNode(out, node->getLeft(), blockMemberInfo); + TIntermTyped *right = node->getRight()->deepCopy(); + const TType &type = node->getLeft()->getType(); + TLayoutBlockStorage storage; + bool rowMajor; + GetBlockLayoutInfo(node, false, &storage, &rowMajor); + + if (type.isArray()) + { + const TSpan &arraySizes = type.getArraySizes(); + for (unsigned int i = 0; i < arraySizes.size() - 1; i++) + { + right = Mul(CreateUIntNode(arraySizes[i]), right); + } + right = Mul(CreateUIntNode(blockMemberInfo->arrayStride), right); + } + else if (type.isMatrix()) + { + if (rowMajor) + { + right = Mul(CreateUIntNode(BlockLayoutEncoder::kBytesPerComponent), right); + } + else + { + right = Mul(CreateUIntNode(blockMemberInfo->matrixStride), right); + } + } + else if (type.isVector()) + { + if (blockMemberInfo->isRowMajorMatrix) + { + right = Mul(CreateUIntNode(blockMemberInfo->matrixStride), right); + } + else + { + right = Mul(CreateUIntNode(BlockLayoutEncoder::kBytesPerComponent), right); + } + } + return Add(left, right); +} + +TIntermTyped *ShaderStorageBlockOutputHLSL::createFieldOffset(const TField *field, + BlockMemberInfo *blockMemberInfo) +{ + auto fieldInfoIter = mBlockMemberInfoMap.find(field); + ASSERT(fieldInfoIter != mBlockMemberInfoMap.end()); + *blockMemberInfo = fieldInfoIter->second; + return CreateUIntNode(blockMemberInfo->offset); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockOutputHLSL.h b/gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockOutputHLSL.h new file mode 100644 index 0000000000..2acf06a0ea --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ShaderStorageBlockOutputHLSL.h @@ -0,0 +1,86 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ShaderStorageBlockOutputHLSL: A traverser to translate a buffer variable of shader storage block +// to an offset of RWByteAddressBuffer. +// + +#ifndef COMPILER_TRANSLATOR_SHADERSTORAGEBLOCKOUTPUTHLSL_H_ +#define COMPILER_TRANSLATOR_SHADERSTORAGEBLOCKOUTPUTHLSL_H_ + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/ShaderStorageBlockFunctionHLSL.h" +#include "compiler/translator/blocklayout.h" + +namespace sh +{ +class ResourcesHLSL; +class OutputHLSL; +class TSymbolTable; + +struct TReferencedBlock : angle::NonCopyable +{ + POOL_ALLOCATOR_NEW_DELETE + TReferencedBlock(const TInterfaceBlock *block, const TVariable *instanceVariable); + const TInterfaceBlock *block; + const TVariable *instanceVariable; // May be nullptr if the block is not instanced. +}; + +// Maps from uniqueId to a variable. +using ReferencedInterfaceBlocks = std::map; + +// Used to save shader storage block field member information. +using BlockMemberInfoMap = std::map; + +using ShaderVarToFieldMap = std::map; + +class ShaderStorageBlockOutputHLSL +{ + public: + ShaderStorageBlockOutputHLSL(OutputHLSL *outputHLSL, + ResourcesHLSL *resourcesHLSL, + const std::vector &shaderStorageBlocks); + + ~ShaderStorageBlockOutputHLSL(); + + // This writes part of the function call to store a value to a SSBO to the output stream. After + // calling this, ", )" should be written to the output stream to complete the + // function call. + void outputStoreFunctionCallPrefix(TIntermTyped *node); + // This writes the function call to load a SSBO value to the output stream. + void outputLoadFunctionCall(TIntermTyped *node); + // This writes the function call to get the lengh of unsized array member of SSBO. + void outputLengthFunctionCall(TIntermTyped *node); + // Writes the atomic memory function calls for SSBO. + void outputAtomicMemoryFunctionCallPrefix(TIntermTyped *node, TOperator op); + + void writeShaderStorageBlocksHeader(GLenum shaderType, TInfoSinkBase &out) const; + + private: + void traverseSSBOAccess(TIntermTyped *node, SSBOMethod method); + TIntermTyped *traverseNode(TInfoSinkBase &out, + TIntermTyped *node, + BlockMemberInfo *blockMemberInfo); + int getMatrixStride(TIntermTyped *node, + TLayoutBlockStorage storage, + bool rowMajor, + bool *isRowMajor) const; + TIntermTyped *writeEOpIndexDirectOrIndirectOutput(TInfoSinkBase &out, + TIntermBinary *node, + BlockMemberInfo *blockMemberInfo); + // Common part in dot operations. + TIntermTyped *createFieldOffset(const TField *field, BlockMemberInfo *blockMemberInfo); + void collectShaderStorageBlocks(TIntermTyped *node); + OutputHLSL *mOutputHLSL; + ShaderStorageBlockFunctionHLSL *mSSBOFunctionHLSL; + ResourcesHLSL *mResourcesHLSL; + ReferencedInterfaceBlocks mReferencedShaderStorageBlocks; + + BlockMemberInfoMap mBlockMemberInfoMap; + const std::vector &mShaderStorageBlocks; +}; +} // namespace sh + +#endif // COMPILER_TRANSLATOR_SHADERSTORAGEBLOCKOUTPUTHLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ShaderVars.cpp b/gfx/angle/checkout/src/compiler/translator/ShaderVars.cpp new file mode 100644 index 0000000000..85d87e2be4 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ShaderVars.cpp @@ -0,0 +1,625 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ShaderVars.cpp: +// Methods for GL variable types (varyings, uniforms, etc) +// + +#include + +#include "common/debug.h" +#include "common/utilities.h" + +namespace sh +{ + +namespace +{ + +InterpolationType GetNonAuxiliaryInterpolationType(InterpolationType interpolation) +{ + return (interpolation == INTERPOLATION_CENTROID ? INTERPOLATION_SMOOTH : interpolation); +} +} // namespace +// The ES 3.0 spec is not clear on this point, but the ES 3.1 spec, and discussion +// on Khronos.org, clarifies that a smooth/flat mismatch produces a link error, +// but auxiliary qualifier mismatch (centroid) does not. +bool InterpolationTypesMatch(InterpolationType a, InterpolationType b) +{ + return (GetNonAuxiliaryInterpolationType(a) == GetNonAuxiliaryInterpolationType(b)); +} + +ShaderVariable::ShaderVariable() : ShaderVariable(GL_NONE) {} + +ShaderVariable::ShaderVariable(GLenum typeIn) + : type(typeIn), + precision(0), + staticUse(false), + active(false), + isRowMajorLayout(false), + location(-1), + hasImplicitLocation(false), + binding(-1), + imageUnitFormat(GL_NONE), + offset(-1), + rasterOrdered(false), + readonly(false), + writeonly(false), + isFragmentInOut(false), + index(-1), + yuv(false), + interpolation(INTERPOLATION_SMOOTH), + isInvariant(false), + isShaderIOBlock(false), + isPatch(false), + texelFetchStaticUse(false), + flattenedOffsetInParentArrays(-1) +{} + +ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn) : ShaderVariable(typeIn) +{ + ASSERT(arraySizeIn != 0); + arraySizes.push_back(arraySizeIn); +} + +ShaderVariable::~ShaderVariable() {} + +ShaderVariable::ShaderVariable(const ShaderVariable &other) + : type(other.type), + precision(other.precision), + name(other.name), + mappedName(other.mappedName), + arraySizes(other.arraySizes), + staticUse(other.staticUse), + active(other.active), + fields(other.fields), + structOrBlockName(other.structOrBlockName), + mappedStructOrBlockName(other.mappedStructOrBlockName), + isRowMajorLayout(other.isRowMajorLayout), + location(other.location), + hasImplicitLocation(other.hasImplicitLocation), + binding(other.binding), + imageUnitFormat(other.imageUnitFormat), + offset(other.offset), + rasterOrdered(other.rasterOrdered), + readonly(other.readonly), + writeonly(other.writeonly), + isFragmentInOut(other.isFragmentInOut), + index(other.index), + yuv(other.yuv), + interpolation(other.interpolation), + isInvariant(other.isInvariant), + isShaderIOBlock(other.isShaderIOBlock), + isPatch(other.isPatch), + texelFetchStaticUse(other.texelFetchStaticUse), + flattenedOffsetInParentArrays(other.flattenedOffsetInParentArrays) +{} + +ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other) +{ + type = other.type; + precision = other.precision; + name = other.name; + mappedName = other.mappedName; + arraySizes = other.arraySizes; + staticUse = other.staticUse; + active = other.active; + fields = other.fields; + structOrBlockName = other.structOrBlockName; + mappedStructOrBlockName = other.mappedStructOrBlockName; + isRowMajorLayout = other.isRowMajorLayout; + flattenedOffsetInParentArrays = other.flattenedOffsetInParentArrays; + location = other.location; + hasImplicitLocation = other.hasImplicitLocation; + binding = other.binding; + imageUnitFormat = other.imageUnitFormat; + offset = other.offset; + rasterOrdered = other.rasterOrdered; + readonly = other.readonly; + writeonly = other.writeonly; + isFragmentInOut = other.isFragmentInOut; + index = other.index; + yuv = other.yuv; + interpolation = other.interpolation; + isInvariant = other.isInvariant; + isShaderIOBlock = other.isShaderIOBlock; + isPatch = other.isPatch; + texelFetchStaticUse = other.texelFetchStaticUse; + return *this; +} + +bool ShaderVariable::operator==(const ShaderVariable &other) const +{ + if (type != other.type || precision != other.precision || name != other.name || + mappedName != other.mappedName || arraySizes != other.arraySizes || + staticUse != other.staticUse || active != other.active || + fields.size() != other.fields.size() || structOrBlockName != other.structOrBlockName || + mappedStructOrBlockName != other.mappedStructOrBlockName || + isRowMajorLayout != other.isRowMajorLayout || location != other.location || + hasImplicitLocation != other.hasImplicitLocation || binding != other.binding || + imageUnitFormat != other.imageUnitFormat || offset != other.offset || + rasterOrdered != other.rasterOrdered || readonly != other.readonly || + writeonly != other.writeonly || index != other.index || yuv != other.yuv || + interpolation != other.interpolation || isInvariant != other.isInvariant || + isShaderIOBlock != other.isShaderIOBlock || isPatch != other.isPatch || + texelFetchStaticUse != other.texelFetchStaticUse || + isFragmentInOut != other.isFragmentInOut) + { + return false; + } + for (size_t ii = 0; ii < fields.size(); ++ii) + { + if (fields[ii] != other.fields[ii]) + return false; + } + return true; +} + +void ShaderVariable::setArraySize(unsigned int size) +{ + arraySizes.clear(); + if (size != 0) + { + arraySizes.push_back(size); + } +} + +unsigned int ShaderVariable::getInnerArraySizeProduct() const +{ + return gl::InnerArraySizeProduct(arraySizes); +} + +unsigned int ShaderVariable::getArraySizeProduct() const +{ + return gl::ArraySizeProduct(arraySizes); +} + +void ShaderVariable::indexIntoArray(unsigned int arrayIndex) +{ + ASSERT(isArray()); + flattenedOffsetInParentArrays = arrayIndex + getOutermostArraySize() * parentArrayIndex(); + arraySizes.pop_back(); +} + +unsigned int ShaderVariable::getNestedArraySize(unsigned int arrayNestingIndex) const +{ + ASSERT(arraySizes.size() > arrayNestingIndex); + unsigned int arraySize = arraySizes[arraySizes.size() - 1u - arrayNestingIndex]; + + if (arraySize == 0) + { + // Unsized array, so give it at least 1 entry + arraySize = 1; + } + + return arraySize; +} + +unsigned int ShaderVariable::getBasicTypeElementCount() const +{ + // GLES 3.1 Nov 2016 section 7.3.1.1 page 77 specifies that a separate entry should be generated + // for each array element when dealing with an array of arrays or an array of structs. + ASSERT(!isArrayOfArrays()); + ASSERT(!isStruct() || !isArray()); + + // GLES 3.1 Nov 2016 page 82. + if (isArray()) + { + return getOutermostArraySize(); + } + return 1u; +} + +unsigned int ShaderVariable::getExternalSize() const +{ + unsigned int memorySize = 0; + + if (isStruct()) + { + // Have a structure, need to compute the structure size. + for (const auto &field : fields) + { + memorySize += field.getExternalSize(); + } + } + else + { + memorySize += gl::VariableExternalSize(type); + } + + // multiply by array size to get total memory size of this variable / struct. + memorySize *= getArraySizeProduct(); + + return memorySize; +} + +bool ShaderVariable::findInfoByMappedName(const std::string &mappedFullName, + const ShaderVariable **leafVar, + std::string *originalFullName) const +{ + ASSERT(leafVar && originalFullName); + // There are three cases: + // 1) the top variable is of struct type; + // 2) the top variable is an array; + // 3) otherwise. + size_t pos = mappedFullName.find_first_of(".["); + + if (pos == std::string::npos) + { + // Case 3. + if (mappedFullName != this->mappedName) + return false; + *originalFullName = this->name; + *leafVar = this; + return true; + } + else + { + std::string topName = mappedFullName.substr(0, pos); + if (topName != this->mappedName) + return false; + std::string originalName = this->name; + std::string remaining; + if (mappedFullName[pos] == '[') + { + // Case 2. + size_t closePos = mappedFullName.find_first_of(']'); + if (closePos < pos || closePos == std::string::npos) + return false; + // Append '[index]'. + originalName += mappedFullName.substr(pos, closePos - pos + 1); + if (closePos + 1 == mappedFullName.size()) + { + *originalFullName = originalName; + *leafVar = this; + return true; + } + else + { + // In the form of 'a[0].b', so after ']', '.' is expected. + if (mappedFullName[closePos + 1] != '.') + return false; + remaining = mappedFullName.substr(closePos + 2); // Skip "]." + } + } + else + { + // Case 1. + remaining = mappedFullName.substr(pos + 1); // Skip "." + } + for (size_t ii = 0; ii < this->fields.size(); ++ii) + { + const ShaderVariable *fieldVar = nullptr; + std::string originalFieldName; + bool found = fields[ii].findInfoByMappedName(remaining, &fieldVar, &originalFieldName); + if (found) + { + *originalFullName = originalName + "." + originalFieldName; + *leafVar = fieldVar; + return true; + } + } + return false; + } +} + +const sh::ShaderVariable *ShaderVariable::findField(const std::string &fullName, + uint32_t *fieldIndexOut) const +{ + if (fields.empty()) + { + return nullptr; + } + size_t pos = fullName.find_first_of("."); + std::string topName, fieldName; + if (pos == std::string::npos) + { + // If this is a shader I/O block without an instance name, return the field given only the + // field name. + if (!isShaderIOBlock || !name.empty()) + { + return nullptr; + } + + fieldName = fullName; + } + else + { + std::string baseName = isShaderIOBlock ? structOrBlockName : name; + topName = fullName.substr(0, pos); + if (topName != baseName) + { + return nullptr; + } + fieldName = fullName.substr(pos + 1); + } + if (fieldName.empty()) + { + return nullptr; + } + for (size_t field = 0; field < fields.size(); ++field) + { + if (fields[field].name == fieldName) + { + *fieldIndexOut = static_cast(field); + return &fields[field]; + } + } + return nullptr; +} + +bool ShaderVariable::isBuiltIn() const +{ + return gl::IsBuiltInName(name); +} + +bool ShaderVariable::isEmulatedBuiltIn() const +{ + return isBuiltIn() && name != mappedName; +} + +bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other, + bool matchPrecision, + bool matchName) const +{ + if (type != other.type) + return false; + if (matchPrecision && precision != other.precision) + return false; + if (matchName && name != other.name) + return false; + ASSERT(!matchName || mappedName == other.mappedName); + if (arraySizes != other.arraySizes) + return false; + if (isRowMajorLayout != other.isRowMajorLayout) + return false; + if (fields.size() != other.fields.size()) + return false; + + // [OpenGL ES 3.1 SPEC Chapter 7.4.1] + // Variables declared as structures are considered to match in type if and only if structure + // members match in name, type, qualification, and declaration order. + for (size_t ii = 0; ii < fields.size(); ++ii) + { + if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii], matchPrecision, true)) + { + return false; + } + } + if (structOrBlockName != other.structOrBlockName || + mappedStructOrBlockName != other.mappedStructOrBlockName) + return false; + return true; +} + +void ShaderVariable::updateEffectiveLocation(const sh::ShaderVariable &parent) +{ + if ((location < 0 || hasImplicitLocation) && !parent.hasImplicitLocation) + { + location = parent.location; + } +} + +void ShaderVariable::resetEffectiveLocation() +{ + if (hasImplicitLocation) + { + location = -1; + } +} + +bool ShaderVariable::isSameUniformAtLinkTime(const ShaderVariable &other) const +{ + // Enforce a consistent match. + // https://cvs.khronos.org/bugzilla/show_bug.cgi?id=16261 + if (binding != -1 && other.binding != -1 && binding != other.binding) + { + return false; + } + if (imageUnitFormat != other.imageUnitFormat) + { + return false; + } + if (location != -1 && other.location != -1 && location != other.location) + { + return false; + } + if (offset != other.offset) + { + return false; + } + if (rasterOrdered != other.rasterOrdered) + { + return false; + } + if (readonly != other.readonly || writeonly != other.writeonly) + { + return false; + } + return ShaderVariable::isSameVariableAtLinkTime(other, true, true); +} + +bool ShaderVariable::isSameInterfaceBlockFieldAtLinkTime(const ShaderVariable &other) const +{ + return (ShaderVariable::isSameVariableAtLinkTime(other, true, true)); +} + +bool ShaderVariable::isSameVaryingAtLinkTime(const ShaderVariable &other) const +{ + return isSameVaryingAtLinkTime(other, 100); +} + +bool ShaderVariable::isSameVaryingAtLinkTime(const ShaderVariable &other, int shaderVersion) const +{ + return ShaderVariable::isSameVariableAtLinkTime(other, false, false) && + InterpolationTypesMatch(interpolation, other.interpolation) && + (shaderVersion >= 300 || isInvariant == other.isInvariant) && + (isPatch == other.isPatch) && location == other.location && + (isSameNameAtLinkTime(other) || (shaderVersion >= 310 && location >= 0)); +} + +bool ShaderVariable::isSameNameAtLinkTime(const ShaderVariable &other) const +{ + if (isShaderIOBlock != other.isShaderIOBlock) + { + return false; + } + + if (isShaderIOBlock) + { + // Shader I/O blocks match by block name. + return structOrBlockName == other.structOrBlockName; + } + + // Otherwise match by name. + return name == other.name; +} + +InterfaceBlock::InterfaceBlock() + : arraySize(0), + layout(BLOCKLAYOUT_PACKED), + isRowMajorLayout(false), + binding(-1), + staticUse(false), + active(false), + blockType(BlockType::BLOCK_UNIFORM) +{} + +InterfaceBlock::~InterfaceBlock() {} + +InterfaceBlock::InterfaceBlock(const InterfaceBlock &other) + : name(other.name), + mappedName(other.mappedName), + instanceName(other.instanceName), + arraySize(other.arraySize), + layout(other.layout), + isRowMajorLayout(other.isRowMajorLayout), + binding(other.binding), + staticUse(other.staticUse), + active(other.active), + blockType(other.blockType), + fields(other.fields) +{} + +InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other) +{ + name = other.name; + mappedName = other.mappedName; + instanceName = other.instanceName; + arraySize = other.arraySize; + layout = other.layout; + isRowMajorLayout = other.isRowMajorLayout; + binding = other.binding; + staticUse = other.staticUse; + active = other.active; + blockType = other.blockType; + fields = other.fields; + return *this; +} + +std::string InterfaceBlock::fieldPrefix() const +{ + return instanceName.empty() ? "" : name; +} + +std::string InterfaceBlock::fieldMappedPrefix() const +{ + return instanceName.empty() ? "" : mappedName; +} + +bool InterfaceBlock::isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const +{ + if (name != other.name || mappedName != other.mappedName || arraySize != other.arraySize || + layout != other.layout || isRowMajorLayout != other.isRowMajorLayout || + binding != other.binding || blockType != other.blockType || + fields.size() != other.fields.size()) + { + return false; + } + + for (size_t fieldIndex = 0; fieldIndex < fields.size(); ++fieldIndex) + { + if (!fields[fieldIndex].isSameInterfaceBlockFieldAtLinkTime(other.fields[fieldIndex])) + { + return false; + } + } + + return true; +} + +bool InterfaceBlock::isBuiltIn() const +{ + return gl::IsBuiltInName(name); +} + +void WorkGroupSize::fill(int fillValue) +{ + localSizeQualifiers[0] = fillValue; + localSizeQualifiers[1] = fillValue; + localSizeQualifiers[2] = fillValue; +} + +void WorkGroupSize::setLocalSize(int localSizeX, int localSizeY, int localSizeZ) +{ + localSizeQualifiers[0] = localSizeX; + localSizeQualifiers[1] = localSizeY; + localSizeQualifiers[2] = localSizeZ; +} + +// check that if one of them is less than 1, then all of them are. +// Or if one is positive, then all of them are positive. +bool WorkGroupSize::isLocalSizeValid() const +{ + return ( + (localSizeQualifiers[0] < 1 && localSizeQualifiers[1] < 1 && localSizeQualifiers[2] < 1) || + (localSizeQualifiers[0] > 0 && localSizeQualifiers[1] > 0 && localSizeQualifiers[2] > 0)); +} + +bool WorkGroupSize::isAnyValueSet() const +{ + return localSizeQualifiers[0] > 0 || localSizeQualifiers[1] > 0 || localSizeQualifiers[2] > 0; +} + +bool WorkGroupSize::isDeclared() const +{ + bool localSizeDeclared = localSizeQualifiers[0] > 0; + ASSERT(isLocalSizeValid()); + return localSizeDeclared; +} + +bool WorkGroupSize::isWorkGroupSizeMatching(const WorkGroupSize &right) const +{ + for (size_t i = 0u; i < size(); ++i) + { + bool result = (localSizeQualifiers[i] == right.localSizeQualifiers[i] || + (localSizeQualifiers[i] == 1 && right.localSizeQualifiers[i] == -1) || + (localSizeQualifiers[i] == -1 && right.localSizeQualifiers[i] == 1)); + if (!result) + { + return false; + } + } + return true; +} + +int &WorkGroupSize::operator[](size_t index) +{ + ASSERT(index < size()); + return localSizeQualifiers[index]; +} + +int WorkGroupSize::operator[](size_t index) const +{ + ASSERT(index < size()); + return localSizeQualifiers[index]; +} + +size_t WorkGroupSize::size() const +{ + return 3u; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/StaticType.h b/gfx/angle/checkout/src/compiler/translator/StaticType.h new file mode 100644 index 0000000000..641daadebd --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/StaticType.h @@ -0,0 +1,296 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Compile-time instances of many common TType values. These are looked up +// (statically or dynamically) through the methods defined in the namespace. +// + +#ifndef COMPILER_TRANSLATOR_STATIC_TYPE_H_ +#define COMPILER_TRANSLATOR_STATIC_TYPE_H_ + +#include "compiler/translator/Types.h" + +namespace sh +{ + +namespace StaticType +{ + +namespace Helpers +{ + +// +// Generation and static allocation of type mangled name values. +// + +// Size of the constexpr-generated mangled name. +// If this value is too small, the compiler will produce errors. +static constexpr size_t kStaticMangledNameLength = TBasicMangledName::mangledNameSize + 1; + +// Type which holds the mangled names for constexpr-generated TTypes. +// This simple struct is needed so that a char array can be returned by value. +struct StaticMangledName +{ + // If this array is too small, the compiler will produce errors. + char name[kStaticMangledNameLength + 1] = {}; +}; + +// Generates a mangled name for a TType given its parameters. +constexpr StaticMangledName BuildStaticMangledName(TBasicType basicType, + TPrecision precision, + TQualifier qualifier, + uint8_t primarySize, + uint8_t secondarySize) +{ + StaticMangledName name = {}; + name.name[0] = TType::GetSizeMangledName(primarySize, secondarySize); + TBasicMangledName typeName(basicType); + char *mangledName = typeName.getName(); + static_assert(TBasicMangledName::mangledNameSize == 2, "Mangled name size is not 2"); + name.name[1] = mangledName[0]; + name.name[2] = mangledName[1]; + name.name[3] = '\0'; + return name; +} + +// Similar mangled name builder but for array types. Currently, only single-dimension arrays of +// single-digit size are necessary and supported. +static constexpr size_t kStaticArrayMangledNameLength = kStaticMangledNameLength + 2; +struct StaticArrayMangledName +{ + char name[kStaticArrayMangledNameLength + 1] = {}; +}; +constexpr StaticArrayMangledName BuildStaticArrayMangledName(TBasicType basicType, + TPrecision precision, + TQualifier qualifier, + uint8_t primarySize, + uint8_t secondarySize, + const unsigned int *arraySizes, + size_t numArraySizes) +{ + StaticMangledName nonArrayName = + BuildStaticMangledName(basicType, precision, qualifier, primarySize, secondarySize); + + StaticArrayMangledName arrayName = {}; + static_assert(kStaticMangledNameLength == 3, "Static mangled name size is not 3"); + + arrayName.name[0] = nonArrayName.name[0]; + arrayName.name[1] = nonArrayName.name[1]; + arrayName.name[2] = nonArrayName.name[2]; + arrayName.name[3] = 'x'; + arrayName.name[4] = static_cast('0' + arraySizes[0]); + arrayName.name[5] = '\0'; + return arrayName; +} + +// This "variable" contains the mangled names for every constexpr-generated TType. +// If kMangledNameInstance is used anywhere (specifally +// in instance, below), this is where the appropriate type will be stored. +template +static constexpr StaticMangledName kMangledNameInstance = + BuildStaticMangledName(basicType, precision, qualifier, primarySize, secondarySize); + +// Same as kMangledNameInstance, but for array types. +template +static constexpr StaticArrayMangledName kMangledNameArrayInstance = + BuildStaticArrayMangledName(basicType, + precision, + qualifier, + primarySize, + secondarySize, + arraySizes, + numArraySizes); + +// +// Generation and static allocation of TType values. +// + +// This "variable" contains every constexpr-generated TType. +// If instance is used anywhere (specifally +// in Get, below), this is where the appropriate type will be stored. +// +// TODO(crbug.com/981610): This is constexpr but doesn't follow the kConstant naming convention +// because TType has a mutable member that prevents it from being in .data.rel.ro and makes the +// Android Binary Size builder complain when ANGLE is rolled in Chromium. +template +static constexpr TType instance = + TType(basicType, + precision, + qualifier, + primarySize, + secondarySize, + TSpan(), + kMangledNameInstance.name); + +// Same as instance, but for array types. +template +static constexpr TType arrayInstance = + TType(basicType, + precision, + qualifier, + primarySize, + secondarySize, + TSpan(arraySizes, numArraySizes), + kMangledNameArrayInstance.name); + +} // namespace Helpers + +// +// Fully-qualified type lookup. +// + +template +constexpr const TType *Get() +{ + static_assert(1 <= primarySize && primarySize <= 4, "primarySize out of bounds"); + static_assert(1 <= secondarySize && secondarySize <= 4, "secondarySize out of bounds"); + return &Helpers::instance; +} + +template +constexpr const TType *GetArray() +{ + static_assert(1 <= primarySize && primarySize <= 4, "primarySize out of bounds"); + static_assert(1 <= secondarySize && secondarySize <= 4, "secondarySize out of bounds"); + static_assert(numArraySizes == 1, "only single-dimension static types are supported"); + static_assert(arraySizes[0] < 10, "only single-digit dimensions are supported in static types"); + return &Helpers::arrayInstance; +} + +// +// Overloads +// + +template +constexpr const TType *GetBasic() +{ + return Get(); +} + +template +constexpr const TType *GetTemporary() +{ + return Get(); +} + +template +const TType *GetQualified() +{ + return Get(); +} + +// Dynamic lookup methods (convert runtime values to template args) + +namespace Helpers +{ + +// Helper which takes secondarySize statically but primarySize dynamically. +template +constexpr const TType *GetForVecMatHelper(uint8_t primarySize) +{ + static_assert(basicType == EbtFloat || basicType == EbtInt || basicType == EbtUInt || + basicType == EbtBool, + "unsupported basicType"); + switch (primarySize) + { + case 1: + return Get(); + case 2: + return Get(); + case 3: + return Get(); + case 4: + return Get(); + default: + UNREACHABLE(); + return GetBasic(); + } +} + +} // namespace Helpers + +template +constexpr const TType *GetForVecMat(uint8_t primarySize, uint8_t secondarySize = 1) +{ + static_assert(basicType == EbtFloat || basicType == EbtInt || basicType == EbtUInt || + basicType == EbtBool, + "unsupported basicType"); + switch (secondarySize) + { + case 1: + return Helpers::GetForVecMatHelper(primarySize); + case 2: + return Helpers::GetForVecMatHelper(primarySize); + case 3: + return Helpers::GetForVecMatHelper(primarySize); + case 4: + return Helpers::GetForVecMatHelper(primarySize); + default: + UNREACHABLE(); + return GetBasic(); + } +} + +template +constexpr const TType *GetForVec(TQualifier qualifier, uint8_t size) +{ + switch (qualifier) + { + case EvqGlobal: + return Helpers::GetForVecMatHelper(size); + case EvqParamOut: + return Helpers::GetForVecMatHelper(size); + default: + UNREACHABLE(); + return GetBasic(); + } +} + +} // namespace StaticType + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_STATIC_TYPE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/StructureHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/StructureHLSL.cpp new file mode 100644 index 0000000000..eae602f5ea --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/StructureHLSL.cpp @@ -0,0 +1,668 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// StructureHLSL.cpp: +// HLSL translation of GLSL constructors and structures. +// + +#include "compiler/translator/StructureHLSL.h" +#include "common/utilities.h" +#include "compiler/translator/OutputHLSL.h" +#include "compiler/translator/Types.h" +#include "compiler/translator/UtilsHLSL.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +TString Define(const TStructure &structure, + bool useHLSLRowMajorPacking, + bool useStd140Packing, + bool forcePadding, + Std140PaddingHelper *padHelper) +{ + const TFieldList &fields = structure.fields(); + const bool isNameless = (structure.symbolType() == SymbolType::Empty); + const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking, + useStd140Packing, forcePadding); + const TString declareString = (isNameless ? "struct" : "struct " + structName); + + TString string; + string += declareString + + "\n" + "{\n"; + + size_t memberSize = fields.size(); + for (const TField *field : fields) + { + memberSize--; + const TType &fieldType = *field->type(); + if (!IsSampler(fieldType.getBasicType())) + { + const TStructure *fieldStruct = fieldType.getStruct(); + const TString &fieldTypeString = + fieldStruct ? QualifiedStructNameString(*fieldStruct, useHLSLRowMajorPacking, + useStd140Packing, false) + : TypeString(fieldType); + + if (padHelper) + { + string += padHelper->prePaddingString( + fieldType, (memberSize != fields.size() - 1) && forcePadding); + } + + string += " " + fieldTypeString + " " + DecorateField(field->name(), structure) + + ArrayString(fieldType).data() + ";\n"; + + if (padHelper) + { + string += padHelper->postPaddingString(fieldType, useHLSLRowMajorPacking, + memberSize == 0, forcePadding); + } + } + } + + // Nameless structs do not finish with a semicolon and newline, to leave room for an instance + // variable + string += (isNameless ? "} " : "};\n"); + + return string; +} + +TString WriteParameterList(const std::vector ¶meters) +{ + TString parameterList; + for (size_t parameter = 0u; parameter < parameters.size(); parameter++) + { + const TType ¶mType = parameters[parameter]; + + parameterList += + TypeString(paramType) + " x" + str(parameter) + ArrayString(paramType).data(); + + if (parameter < parameters.size() - 1u) + { + parameterList += ", "; + } + } + return parameterList; +} + +int GetElementPadding(int elementIndex, int alignment) +{ + const int paddingOffset = elementIndex % alignment; + return paddingOffset != 0 ? (alignment - paddingOffset) : 0; +} + +} // anonymous namespace + +Std140PaddingHelper::Std140PaddingHelper(const std::map &structElementIndexes, + unsigned *uniqueCounter) + : mPaddingCounter(uniqueCounter), mElementIndex(0), mStructElementIndexes(&structElementIndexes) +{} + +Std140PaddingHelper::Std140PaddingHelper(const Std140PaddingHelper &other) + : mPaddingCounter(other.mPaddingCounter), + mElementIndex(other.mElementIndex), + mStructElementIndexes(other.mStructElementIndexes) +{} + +Std140PaddingHelper &Std140PaddingHelper::operator=(const Std140PaddingHelper &other) +{ + mPaddingCounter = other.mPaddingCounter; + mElementIndex = other.mElementIndex; + mStructElementIndexes = other.mStructElementIndexes; + return *this; +} + +TString Std140PaddingHelper::next() +{ + unsigned value = (*mPaddingCounter)++; + return str(value); +} + +int Std140PaddingHelper::prePadding(const TType &type, bool forcePadding) +{ + if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray()) + { + if (forcePadding) + { + // Add padding between the structure's members to follow the std140 rules manually. + const int forcePaddingCount = GetElementPadding(mElementIndex, 4); + mElementIndex = 0; + return forcePaddingCount; + } + else + { + // no padding needed, HLSL will align the field to a new register + mElementIndex = 0; + return 0; + } + } + + const GLenum glType = GLVariableType(type); + const int numComponents = gl::VariableComponentCount(glType); + + if (numComponents >= 4) + { + if (forcePadding) + { + // Add padding between the structure's members to follow the std140 rules manually. + const int forcePaddingCount = GetElementPadding(mElementIndex, 4); + mElementIndex = numComponents % 4; + return forcePaddingCount; + } + else + { + // no padding needed, HLSL will align the field to a new register + mElementIndex = 0; + return 0; + } + } + + if (mElementIndex + numComponents > 4) + { + if (forcePadding) + { + // Add padding between the structure's members to follow the std140 rules manually. + const int forcePaddingCount = GetElementPadding(mElementIndex, 4); + mElementIndex = numComponents; + return forcePaddingCount; + } + else + { + // no padding needed, HLSL will align the field to a new register + mElementIndex = numComponents; + return 0; + } + } + + const int alignment = numComponents == 3 ? 4 : numComponents; + const int paddingCount = GetElementPadding(mElementIndex, alignment); + + mElementIndex += paddingCount; + mElementIndex += numComponents; + mElementIndex %= 4; + + return paddingCount; +} + +TString Std140PaddingHelper::prePaddingString(const TType &type, bool forcePadding) +{ + int paddingCount = prePadding(type, forcePadding); + + TString padding; + + for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++) + { + padding += " float pad_" + next() + ";\n"; + } + + return padding; +} + +TString Std140PaddingHelper::postPaddingString(const TType &type, + bool useHLSLRowMajorPacking, + bool isLastElement, + bool forcePadding) +{ + if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct) + { + if (forcePadding) + { + const GLenum glType = GLVariableType(type); + const int numComponents = gl::VariableComponentCount(glType); + if (isLastElement || (numComponents >= 4)) + { + // If this structure will be used as HLSL StructuredBuffer member's type, in + // order to follow the std140 rules, add padding at the end of the structure + // if necessary. Or if the current element straddles a vec4 boundary, add + // padding to round up the base offset of the next element to the base + // alignment of a vec4. + TString forcePaddingStr; + const int paddingCount = GetElementPadding(mElementIndex, 4); + for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++) + { + forcePaddingStr += " float pad_" + next() + ";\n"; + } + mElementIndex = 0; + return forcePaddingStr; + } + } + + return ""; + } + + int numComponents = 0; + const TStructure *structure = type.getStruct(); + + if (type.isMatrix()) + { + // This method can also be called from structureString, which does not use layout + // qualifiers. + // Thus, use the method parameter for determining the matrix packing. + // + // Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we + // wish to always transpose GL matrices to play well with HLSL's matrix array indexing. + // + const bool isRowMajorMatrix = !useHLSLRowMajorPacking; + const GLenum glType = GLVariableType(type); + numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix); + } + else if (structure) + { + const TString &structName = + QualifiedStructNameString(*structure, useHLSLRowMajorPacking, true, false); + numComponents = mStructElementIndexes->find(structName)->second; + + if (numComponents == 0) + { + return ""; + } + } + else + { + const GLenum glType = GLVariableType(type); + numComponents = gl::VariableComponentCount(glType); + } + + TString padding; + for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++) + { + padding += " float pad_" + next() + ";\n"; + } + return padding; +} + +StructureHLSL::StructureHLSL() : mUniquePaddingCounter(0) {} + +Std140PaddingHelper StructureHLSL::getPaddingHelper() +{ + return Std140PaddingHelper(mStd140StructElementIndexes, &mUniquePaddingCounter); +} + +TString StructureHLSL::defineQualified(const TStructure &structure, + bool useHLSLRowMajorPacking, + bool useStd140Packing, + bool forcePadding) +{ + if (useStd140Packing) + { + Std140PaddingHelper padHelper = getPaddingHelper(); + return Define(structure, useHLSLRowMajorPacking, useStd140Packing, forcePadding, + &padHelper); + } + else + { + return Define(structure, useHLSLRowMajorPacking, useStd140Packing, false, nullptr); + } +} + +TString StructureHLSL::defineNameless(const TStructure &structure) +{ + return Define(structure, false, false, false, nullptr); +} + +StructureHLSL::DefinedStructs::iterator StructureHLSL::defineVariants(const TStructure &structure, + const TString &name) +{ + ASSERT(mDefinedStructs.find(name) == mDefinedStructs.end()); + + for (const TField *field : structure.fields()) + { + const TType *fieldType = field->type(); + if (fieldType->getBasicType() == EbtStruct) + { + ensureStructDefined(*fieldType->getStruct()); + } + } + + DefinedStructs::iterator addedStruct = + mDefinedStructs.insert(std::make_pair(name, new TStructProperties())).first; + // Add element index + storeStd140ElementIndex(structure, false); + storeStd140ElementIndex(structure, true); + + const TString &structString = defineQualified(structure, false, false, false); + + ASSERT(std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) == + mStructDeclarations.end()); + // Add row-major packed struct for interface blocks + TString rowMajorString = "#pragma pack_matrix(row_major)\n" + + defineQualified(structure, true, false, false) + + "#pragma pack_matrix(column_major)\n"; + + TString std140String = defineQualified(structure, false, true, false); + TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" + + defineQualified(structure, true, true, false) + + "#pragma pack_matrix(column_major)\n"; + + // Must force to pad the structure's elements for StructuredBuffer's element type, if qualifier + // of structure is std140. + TString std140ForcePaddingString = defineQualified(structure, false, true, true); + TString std140RowMajorForcePaddingString = "#pragma pack_matrix(row_major)\n" + + defineQualified(structure, true, true, true) + + "#pragma pack_matrix(column_major)\n"; + + mStructDeclarations.push_back(structString); + mStructDeclarations.push_back(rowMajorString); + mStructDeclarations.push_back(std140String); + mStructDeclarations.push_back(std140RowMajorString); + mStructDeclarations.push_back(std140ForcePaddingString); + mStructDeclarations.push_back(std140RowMajorForcePaddingString); + return addedStruct; +} + +void StructureHLSL::ensureStructDefined(const TStructure &structure) +{ + const TString name = StructNameString(structure); + if (name == "") + { + return; // Nameless structures are not defined + } + if (mDefinedStructs.find(name) == mDefinedStructs.end()) + { + defineVariants(structure, name); + } +} + +TString StructureHLSL::addStructConstructor(const TStructure &structure) +{ + const TString name = StructNameString(structure); + + if (name == "") + { + return TString(); // Nameless structures don't have constructors + } + + auto definedStruct = mDefinedStructs.find(name); + if (definedStruct == mDefinedStructs.end()) + { + definedStruct = defineVariants(structure, name); + } + const TString constructorFunctionName = TString(name) + "_ctor"; + TString *constructor = &definedStruct->second->constructor; + if (!constructor->empty()) + { + return constructorFunctionName; // Already added + } + *constructor += name + " " + constructorFunctionName + "("; + + std::vector ctorParameters; + const TFieldList &fields = structure.fields(); + for (const TField *field : fields) + { + const TType *fieldType = field->type(); + if (!IsSampler(fieldType->getBasicType())) + { + ctorParameters.push_back(*fieldType); + } + } + // Structs that have sampler members should not have constructor calls, and otherwise structs + // are guaranteed to be non-empty by the grammar. Structs can't contain empty declarations + // either. + ASSERT(!ctorParameters.empty()); + + *constructor += WriteParameterList(ctorParameters); + + *constructor += + ")\n" + "{\n" + " " + + name + " structure = { "; + + for (size_t parameterIndex = 0u; parameterIndex < ctorParameters.size(); ++parameterIndex) + { + *constructor += "x" + str(parameterIndex); + if (parameterIndex < ctorParameters.size() - 1u) + { + *constructor += ", "; + } + } + *constructor += + "};\n" + " return structure;\n" + "}\n"; + + return constructorFunctionName; +} + +TString StructureHLSL::addBuiltInConstructor(const TType &type, const TIntermSequence *parameters) +{ + ASSERT(!type.isArray()); + ASSERT(type.getStruct() == nullptr); + ASSERT(parameters); + + TType ctorType = type; + ctorType.setPrecision(EbpHigh); + ctorType.setQualifier(EvqTemporary); + + const TString constructorFunctionName = + TString(type.getBuiltInTypeNameString()) + "_ctor" + DisambiguateFunctionName(parameters); + TString constructor = TypeString(ctorType) + " " + constructorFunctionName + "("; + + std::vector ctorParameters; + for (auto parameter : *parameters) + { + const TType ¶mType = parameter->getAsTyped()->getType(); + ASSERT(!paramType.isArray()); + ctorParameters.push_back(paramType); + } + constructor += WriteParameterList(ctorParameters); + + constructor += + ")\n" + "{\n" + " return " + + TypeString(ctorType) + "("; + + if (ctorType.isMatrix() && ctorParameters.size() == 1) + { + uint8_t rows = ctorType.getRows(); + uint8_t cols = ctorType.getCols(); + const TType ¶meter = ctorParameters[0]; + + if (parameter.isScalar()) + { + for (uint8_t col = 0; col < cols; col++) + { + for (uint8_t row = 0; row < rows; row++) + { + constructor += TString((row == col) ? "x0" : "0.0"); + + if (row < rows - 1 || col < cols - 1) + { + constructor += ", "; + } + } + } + } + else if (parameter.isMatrix()) + { + for (uint8_t col = 0; col < cols; col++) + { + for (uint8_t row = 0; row < rows; row++) + { + if (row < parameter.getRows() && col < parameter.getCols()) + { + constructor += TString("x0") + "[" + str(col) + "][" + str(row) + "]"; + } + else + { + constructor += TString((row == col) ? "1.0" : "0.0"); + } + + if (row < rows - 1 || col < cols - 1) + { + constructor += ", "; + } + } + } + } + else + { + ASSERT(rows == 2 && cols == 2 && parameter.isVector() && + parameter.getNominalSize() == 4); + + constructor += "x0"; + } + } + else + { + size_t remainingComponents = ctorType.getObjectSize(); + size_t parameterIndex = 0; + + while (remainingComponents > 0) + { + const TType ¶meter = ctorParameters[parameterIndex]; + const size_t parameterSize = parameter.getObjectSize(); + bool moreParameters = parameterIndex + 1 < ctorParameters.size(); + + constructor += "x" + str(parameterIndex); + + if (parameter.isScalar()) + { + remainingComponents -= parameter.getObjectSize(); + } + else if (parameter.isVector()) + { + if (remainingComponents == parameterSize || moreParameters) + { + ASSERT(parameterSize <= remainingComponents); + remainingComponents -= parameterSize; + } + else if (remainingComponents < static_cast(parameter.getNominalSize())) + { + switch (remainingComponents) + { + case 1: + constructor += ".x"; + break; + case 2: + constructor += ".xy"; + break; + case 3: + constructor += ".xyz"; + break; + case 4: + constructor += ".xyzw"; + break; + default: + UNREACHABLE(); + } + + remainingComponents = 0; + } + else + UNREACHABLE(); + } + else if (parameter.isMatrix()) + { + uint8_t column = 0; + while (remainingComponents > 0 && column < parameter.getCols()) + { + constructor += "[" + str(column) + "]"; + + if (remainingComponents < static_cast(parameter.getRows())) + { + switch (remainingComponents) + { + case 1: + constructor += ".x"; + break; + case 2: + constructor += ".xy"; + break; + case 3: + constructor += ".xyz"; + break; + default: + UNREACHABLE(); + } + + remainingComponents = 0; + } + else + { + remainingComponents -= parameter.getRows(); + + if (remainingComponents > 0) + { + constructor += ", x" + str(parameterIndex); + } + } + + column++; + } + } + else + { + UNREACHABLE(); + } + + if (moreParameters) + { + parameterIndex++; + } + + if (remainingComponents) + { + constructor += ", "; + } + } + } + + constructor += + ");\n" + "}\n"; + + mBuiltInConstructors.insert(constructor); + + return constructorFunctionName; +} + +std::string StructureHLSL::structsHeader() const +{ + TInfoSinkBase out; + + for (auto &declaration : mStructDeclarations) + { + out << declaration; + } + + for (auto &structure : mDefinedStructs) + { + out << structure.second->constructor; + } + + for (auto &constructor : mBuiltInConstructors) + { + out << constructor; + } + + return out.str(); +} + +void StructureHLSL::storeStd140ElementIndex(const TStructure &structure, + bool useHLSLRowMajorPacking) +{ + Std140PaddingHelper padHelper = getPaddingHelper(); + const TFieldList &fields = structure.fields(); + + for (const TField *field : fields) + { + padHelper.prePadding(*field->type(), false); + } + + // Add remaining element index to the global map, for use with nested structs in standard + // layouts + const TString &structName = + QualifiedStructNameString(structure, useHLSLRowMajorPacking, true, false); + mStd140StructElementIndexes[structName] = padHelper.elementIndex(); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/StructureHLSL.h b/gfx/angle/checkout/src/compiler/translator/StructureHLSL.h new file mode 100644 index 0000000000..7f3b0356f7 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/StructureHLSL.h @@ -0,0 +1,102 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// StructureHLSL.h: +// HLSL translation of GLSL constructors and structures. +// + +#ifndef COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ +#define COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ + +#include "compiler/translator/Common.h" +#include "compiler/translator/IntermNode.h" + +#include + +class TInfoSinkBase; +class TScopeBracket; + +namespace sh +{ + +// This helper class assists structure and interface block definitions in determining +// how to pack std140 structs within HLSL's packing rules. +class Std140PaddingHelper +{ + public: + explicit Std140PaddingHelper(const std::map &structElementIndexes, + unsigned int *uniqueCounter); + Std140PaddingHelper(const Std140PaddingHelper &other); + Std140PaddingHelper &operator=(const Std140PaddingHelper &other); + + int elementIndex() const { return mElementIndex; } + int prePadding(const TType &type, bool forcePadding); + TString prePaddingString(const TType &type, bool forcePadding); + TString postPaddingString(const TType &type, + bool useHLSLRowMajorPacking, + bool isLastElement, + bool forcePadding); + + private: + TString next(); + + unsigned *mPaddingCounter; + int mElementIndex; + const std::map *mStructElementIndexes; +}; + +class StructureHLSL : angle::NonCopyable +{ + public: + StructureHLSL(); + + // Returns the name of the constructor function. + TString addStructConstructor(const TStructure &structure); + TString addBuiltInConstructor(const TType &type, const TIntermSequence *parameters); + + static TString defineNameless(const TStructure &structure); + void ensureStructDefined(const TStructure &structure); + + std::string structsHeader() const; + + Std140PaddingHelper getPaddingHelper(); + + private: + unsigned mUniquePaddingCounter; + + std::map mStd140StructElementIndexes; + + struct TStructProperties : public angle::NonCopyable + { + POOL_ALLOCATOR_NEW_DELETE + + TStructProperties() {} + + // Constructor is an empty string in case the struct doesn't have a constructor yet. + TString constructor; + }; + + // Map from struct name to struct properties. + typedef std::map DefinedStructs; + DefinedStructs mDefinedStructs; + + // Struct declarations need to be kept in a vector instead of having them inside mDefinedStructs + // since maintaining the original order is necessary for nested structs. + typedef std::vector StructDeclarations; + StructDeclarations mStructDeclarations; + + typedef std::set BuiltInConstructors; + BuiltInConstructors mBuiltInConstructors; + + void storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking); + TString defineQualified(const TStructure &structure, + bool useHLSLRowMajorPacking, + bool useStd140Packing, + bool forcePackingEnd); + DefinedStructs::iterator defineVariants(const TStructure &structure, const TString &name); +}; +} // namespace sh + +#endif // COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/Symbol.cpp b/gfx/angle/checkout/src/compiler/translator/Symbol.cpp new file mode 100644 index 0000000000..dddf770715 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Symbol.cpp @@ -0,0 +1,254 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Symbol.cpp: Symbols representing variables, functions, structures and interface blocks. +// + +#if defined(_MSC_VER) +# pragma warning(disable : 4718) +#endif + +#include "compiler/translator/Symbol.h" + +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/SymbolTable.h" + +namespace sh +{ + +namespace +{ + +constexpr const ImmutableString kMainName("main"); +constexpr const ImmutableString kImageLoadName("imageLoad"); +constexpr const ImmutableString kImageStoreName("imageStore"); +constexpr const ImmutableString kImageSizeName("imageSize"); +constexpr const ImmutableString kImageAtomicExchangeName("imageAtomicExchange"); +constexpr const ImmutableString kAtomicCounterName("atomicCounter"); + +static const char kFunctionMangledNameSeparator = '('; + +} // anonymous namespace + +TSymbol::TSymbol(TSymbolTable *symbolTable, + const ImmutableString &name, + SymbolType symbolType, + SymbolClass symbolClass, + TExtension extension) + : mName(name), + mUniqueId(symbolTable->nextUniqueId()), + mExtensions( + std::array{{extension, TExtension::UNDEFINED, TExtension::UNDEFINED}}), + mSymbolType(symbolType), + mSymbolClass(symbolClass) +{ + ASSERT(mSymbolType == SymbolType::BuiltIn || extension == TExtension::UNDEFINED); + ASSERT(mName != "" || mSymbolType == SymbolType::AngleInternal || + mSymbolType == SymbolType::Empty); +} + +TSymbol::TSymbol(TSymbolTable *symbolTable, + const ImmutableString &name, + SymbolType symbolType, + SymbolClass symbolClass, + const std::array &extensions) + : mName(name), + mUniqueId(symbolTable->nextUniqueId()), + mExtensions(extensions), + mSymbolType(symbolType), + mSymbolClass(symbolClass) +{ + ASSERT(mSymbolType == SymbolType::BuiltIn || extensions[0] == TExtension::UNDEFINED); + ASSERT(mName != "" || mSymbolType == SymbolType::AngleInternal || + mSymbolType == SymbolType::Empty); +} + +ImmutableString TSymbol::name() const +{ + if (!mName.empty()) + { + return mName; + } + // This can be called for nameless function parameters in HLSL. + ASSERT(mSymbolType == SymbolType::AngleInternal || + (mSymbolType == SymbolType::Empty && isVariable())); + int uniqueId = mUniqueId.get(); + ImmutableStringBuilder symbolNameOut(sizeof(uniqueId) * 2u + 1u); + symbolNameOut << 's'; + symbolNameOut.appendHex(mUniqueId.get()); + return symbolNameOut; +} + +ImmutableString TSymbol::getMangledName() const +{ + if (mSymbolClass == SymbolClass::Function) + { + // We do this instead of using proper virtual functions so that we can better support + // constexpr symbols. + return static_cast(this)->getFunctionMangledName(); + } + ASSERT(mSymbolType != SymbolType::Empty); + return name(); +} + +TVariable::TVariable(TSymbolTable *symbolTable, + const ImmutableString &name, + const TType *type, + SymbolType symbolType, + TExtension extension) + : TSymbol(symbolTable, name, symbolType, SymbolClass::Variable, extension), + mType(type), + unionArray(nullptr) +{ + ASSERT(mType); + ASSERT(name.empty() || symbolType != SymbolType::Empty); +} + +TVariable::TVariable(TSymbolTable *symbolTable, + const ImmutableString &name, + const TType *type, + SymbolType symbolType, + const std::array &extensions) + : TSymbol(symbolTable, name, symbolType, SymbolClass::Variable, extensions), + mType(type), + unionArray(nullptr) +{ + ASSERT(mType); + ASSERT(name.empty() || symbolType != SymbolType::Empty); +} + +TStructure::TStructure(TSymbolTable *symbolTable, + const ImmutableString &name, + const TFieldList *fields, + SymbolType symbolType) + : TSymbol(symbolTable, name, symbolType, SymbolClass::Struct), TFieldListCollection(fields) +{} + +void TStructure::createSamplerSymbols(const char *namePrefix, + const TString &apiNamePrefix, + TVector *outputSymbols, + TMap *outputSymbolsToAPINames, + TSymbolTable *symbolTable) const +{ + ASSERT(containsSamplers()); + for (const auto *field : *mFields) + { + const TType *fieldType = field->type(); + if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers()) + { + std::stringstream fieldName = sh::InitializeStream(); + fieldName << namePrefix << "_" << field->name(); + TString fieldApiName = apiNamePrefix + "."; + fieldApiName += field->name().data(); + fieldType->createSamplerSymbols(ImmutableString(fieldName.str()), fieldApiName, + outputSymbols, outputSymbolsToAPINames, symbolTable); + } + } +} + +void TStructure::setName(const ImmutableString &name) +{ + ImmutableString *mutableName = const_cast(&mName); + *mutableName = name; +} + +TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable, + const ImmutableString &name, + const TFieldList *fields, + const TLayoutQualifier &layoutQualifier, + SymbolType symbolType, + TExtension extension) + : TSymbol(symbolTable, name, symbolType, SymbolClass::InterfaceBlock, extension), + TFieldListCollection(fields), + mBlockStorage(layoutQualifier.blockStorage), + mBinding(layoutQualifier.binding) +{ + ASSERT(name != nullptr); +} + +TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable, + const ImmutableString &name, + const TFieldList *fields, + const TLayoutQualifier &layoutQualifier, + SymbolType symbolType, + const std::array &extensions) + : TSymbol(symbolTable, name, symbolType, SymbolClass::InterfaceBlock, extensions), + TFieldListCollection(fields), + mBlockStorage(layoutQualifier.blockStorage), + mBinding(layoutQualifier.binding) +{ + ASSERT(name != nullptr); +} + +TFunction::TFunction(TSymbolTable *symbolTable, + const ImmutableString &name, + SymbolType symbolType, + const TType *retType, + bool knownToNotHaveSideEffects) + : TSymbol(symbolTable, name, symbolType, SymbolClass::Function, TExtension::UNDEFINED), + mParametersVector(new TParamVector()), + mParameters(nullptr), + returnType(retType), + mMangledName(""), + mParamCount(0u), + mOp(EOpNull), + defined(false), + mHasPrototypeDeclaration(false), + mKnownToNotHaveSideEffects(knownToNotHaveSideEffects), + mHasVoidParameter(false) +{ + // Functions with an empty name are not allowed. + ASSERT(symbolType != SymbolType::Empty); + ASSERT(name != nullptr || symbolType == SymbolType::AngleInternal); +} + +void TFunction::addParameter(const TVariable *p) +{ + ASSERT(mParametersVector); + mParametersVector->push_back(p); + mParameters = mParametersVector->data(); + mParamCount = mParametersVector->size(); + mMangledName = kEmptyImmutableString; +} + +void TFunction::shareParameters(const TFunction ¶metersSource) +{ + mParametersVector = nullptr; + mParameters = parametersSource.mParameters; + mParamCount = parametersSource.mParamCount; + ASSERT(parametersSource.name() == name()); + mMangledName = parametersSource.mMangledName; +} + +ImmutableString TFunction::buildMangledName() const +{ + ImmutableString name = this->name(); + std::string newName(name.data(), name.length()); + newName += kFunctionMangledNameSeparator; + + for (size_t i = 0u; i < mParamCount; ++i) + { + newName += mParameters[i]->getType().getMangledName(); + } + return ImmutableString(newName); +} + +bool TFunction::isMain() const +{ + return symbolType() == SymbolType::UserDefined && name() == kMainName; +} + +bool TFunction::isImageFunction() const +{ + return symbolType() == SymbolType::BuiltIn && + (name() == kImageSizeName || name() == kImageLoadName || name() == kImageStoreName || + name() == kImageAtomicExchangeName); +} + +bool TFunction::isAtomicCounterFunction() const +{ + return SymbolType() == SymbolType::BuiltIn && name().beginsWith(kAtomicCounterName); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/Symbol.h b/gfx/angle/checkout/src/compiler/translator/Symbol.h new file mode 100644 index 0000000000..cb34306be8 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Symbol.h @@ -0,0 +1,402 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Symbol.h: Symbols representing variables, functions, structures and interface blocks. +// + +#ifndef COMPILER_TRANSLATOR_SYMBOL_H_ +#define COMPILER_TRANSLATOR_SYMBOL_H_ + +#include "common/angleutils.h" +#include "compiler/translator/ExtensionBehavior.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/SymbolUniqueId.h" + +namespace sh +{ + +class TSymbolTable; + +// Symbol base class. (Can build functions or variables out of these...) +class TSymbol : angle::NonCopyable +{ + public: + POOL_ALLOCATOR_NEW_DELETE + TSymbol(TSymbolTable *symbolTable, + const ImmutableString &name, + SymbolType symbolType, + SymbolClass symbolClass, + TExtension extension = TExtension::UNDEFINED); + + TSymbol(TSymbolTable *symbolTable, + const ImmutableString &name, + SymbolType symbolType, + SymbolClass symbolClass, + const std::array &extensions); + + // Note that we can't have a virtual destructor in order to support constexpr symbols. Data is + // either statically allocated or pool allocated. + ~TSymbol() = default; + + // Calling name() for empty symbols (symbolType == SymbolType::Empty) generates a similar name + // as for internal variables. + ImmutableString name() const; + // Don't call getMangledName() for empty symbols (symbolType == SymbolType::Empty). + ImmutableString getMangledName() const; + + bool isFunction() const { return mSymbolClass == SymbolClass::Function; } + bool isVariable() const { return mSymbolClass == SymbolClass::Variable; } + bool isStruct() const { return mSymbolClass == SymbolClass::Struct; } + bool isInterfaceBlock() const { return mSymbolClass == SymbolClass::InterfaceBlock; } + + const TSymbolUniqueId &uniqueId() const { return mUniqueId; } + SymbolType symbolType() const { return mSymbolType; } + const std::array extensions() const { return mExtensions; } + + template + constexpr const std::array CreateExtensionList( + const std::array &extensions) + { + switch (extensions.size()) + { + case 1: + return std::array{ + {extensions[0], TExtension::UNDEFINED, TExtension::UNDEFINED}}; + case 2: + return std::array{ + {extensions[0], extensions[1], TExtension::UNDEFINED}}; + case 3: + return std::array{{extensions[0], extensions[1], extensions[2]}}; + default: + UNREACHABLE(); + return std::array{ + {TExtension::UNDEFINED, TExtension::UNDEFINED, TExtension::UNDEFINED}}; + } + } + + protected: + template + constexpr TSymbol(const TSymbolUniqueId &id, + const ImmutableString &name, + SymbolType symbolType, + const std::array &extensions, + SymbolClass symbolClass) + : mName(name), + mUniqueId(id), + mExtensions(CreateExtensionList(extensions)), + mSymbolType(symbolType), + mSymbolClass(symbolClass) + {} + + const ImmutableString mName; + + private: + const TSymbolUniqueId mUniqueId; + const std::array mExtensions; + const SymbolType mSymbolType : 4; + + // We use this instead of having virtual functions for querying the class in order to support + // constexpr symbols. + const SymbolClass mSymbolClass : 4; +}; + +static_assert(sizeof(TSymbol) <= 24, "Size check failed"); + +// Variable. +// May store the value of a constant variable of any type (float, int, bool or struct). +class TVariable : public TSymbol +{ + public: + TVariable(TSymbolTable *symbolTable, + const ImmutableString &name, + const TType *type, + SymbolType symbolType, + TExtension ext = TExtension::UNDEFINED); + + TVariable(TSymbolTable *symbolTable, + const ImmutableString &name, + const TType *type, + SymbolType symbolType, + const std::array &extensions); + + const TType &getType() const { return *mType; } + + const TConstantUnion *getConstPointer() const { return unionArray; } + + void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; } + + // Note: only to be used for built-in variables with autogenerated ids! + constexpr TVariable(const TSymbolUniqueId &id, + const ImmutableString &name, + SymbolType symbolType, + TExtension extension, + const TType *type) + : TSymbol(id, + name, + symbolType, + std::array{{extension}}, + SymbolClass::Variable), + mType(type), + unionArray(nullptr) + {} + + template + constexpr TVariable(const TSymbolUniqueId &id, + const ImmutableString &name, + SymbolType symbolType, + const std::array &extensions, + const TType *type) + : TSymbol(id, name, symbolType, extensions, SymbolClass::Variable), + mType(type), + unionArray(nullptr) + {} + + private: + const TType *mType; + const TConstantUnion *unionArray; +}; + +// Struct type. +class TStructure : public TSymbol, public TFieldListCollection +{ + public: + TStructure(TSymbolTable *symbolTable, + const ImmutableString &name, + const TFieldList *fields, + SymbolType symbolType); + + // The char arrays passed in must be pool allocated or static. + void createSamplerSymbols(const char *namePrefix, + const TString &apiNamePrefix, + TVector *outputSymbols, + TMap *outputSymbolsToAPINames, + TSymbolTable *symbolTable) const; + + void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; } + bool atGlobalScope() const { return mAtGlobalScope; } + + private: + friend class TSymbolTable; + // For creating built-in structs. + TStructure(const TSymbolUniqueId &id, + const ImmutableString &name, + TExtension extension, + const TFieldList *fields) + : TSymbol(id, + name, + SymbolType::BuiltIn, + std::array{{extension}}, + SymbolClass::Struct), + TFieldListCollection(fields) + {} + + template + TStructure(const TSymbolUniqueId &id, + const ImmutableString &name, + const std::array &extensions, + const TFieldList *fields) + : TSymbol(id, name, SymbolType::BuiltIn, extensions, SymbolClass::Struct), + TFieldListCollection(fields) + {} + + // TODO(zmo): Find a way to get rid of the const_cast in function + // setName(). At the moment keep this function private so only + // friend class RegenerateStructNames may call it. + friend class RegenerateStructNamesTraverser; + void setName(const ImmutableString &name); + + bool mAtGlobalScope; +}; + +// Interface block. Note that this contains the block name, not the instance name. Interface block +// instances are stored as TVariable. +class TInterfaceBlock : public TSymbol, public TFieldListCollection +{ + public: + TInterfaceBlock(TSymbolTable *symbolTable, + const ImmutableString &name, + const TFieldList *fields, + const TLayoutQualifier &layoutQualifier, + SymbolType symbolType, + TExtension extension = TExtension::UNDEFINED); + + TInterfaceBlock(TSymbolTable *symbolTable, + const ImmutableString &name, + const TFieldList *fields, + const TLayoutQualifier &layoutQualifier, + SymbolType symbolType, + const std::array &extensions); + + TLayoutBlockStorage blockStorage() const { return mBlockStorage; } + int blockBinding() const { return mBinding; } + + private: + friend class TSymbolTable; + // For creating built-in interface blocks. + TInterfaceBlock(const TSymbolUniqueId &id, + const ImmutableString &name, + TExtension extension, + const TFieldList *fields) + : TSymbol(id, + name, + SymbolType::BuiltIn, + std::array{{extension}}, + SymbolClass::InterfaceBlock), + TFieldListCollection(fields), + mBlockStorage(EbsUnspecified), + mBinding(0) + {} + + template + TInterfaceBlock(const TSymbolUniqueId &id, + const ImmutableString &name, + const std::array &extensions, + const TFieldList *fields) + : TSymbol(id, name, SymbolType::BuiltIn, extensions, SymbolClass::InterfaceBlock), + TFieldListCollection(fields), + mBlockStorage(EbsUnspecified), + mBinding(0) + {} + + TLayoutBlockStorage mBlockStorage; + int mBinding; + + // Note that we only record matrix packing on a per-field granularity. +}; + +// Parameter class used for parsing user-defined function parameters. +struct TParameter +{ + // Destructively converts to TVariable. + // This method resets name and type to nullptrs to make sure + // their content cannot be modified after the call. + const TVariable *createVariable(TSymbolTable *symbolTable) + { + const ImmutableString constName(name); + const TType *constType = type; + name = nullptr; + type = nullptr; + return new TVariable(symbolTable, constName, constType, + constName.empty() ? SymbolType::Empty : SymbolType::UserDefined); + } + + const char *name; // either pool allocated or static. + TType *type; +}; + +// The function sub-class of a symbol. +class TFunction : public TSymbol +{ + public: + // User-defined function + TFunction(TSymbolTable *symbolTable, + const ImmutableString &name, + SymbolType symbolType, + const TType *retType, + bool knownToNotHaveSideEffects); + + void addParameter(const TVariable *p); + void shareParameters(const TFunction ¶metersSource); + + ImmutableString getFunctionMangledName() const + { + ASSERT(symbolType() != SymbolType::BuiltIn); + if (mMangledName.empty()) + { + mMangledName = buildMangledName(); + } + return mMangledName; + } + + const TType &getReturnType() const { return *returnType; } + + TOperator getBuiltInOp() const { return mOp; } + + void setDefined() { defined = true; } + bool isDefined() const { return defined; } + void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; } + bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; } + void setHasVoidParameter() { mHasVoidParameter = true; } + bool hasVoidParameter() const { return mHasVoidParameter; } + + size_t getParamCount() const { return mParamCount; } + const TVariable *getParam(size_t i) const { return mParameters[i]; } + + bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; } + + bool isMain() const; + bool isImageFunction() const; + bool isAtomicCounterFunction() const; + + // Note: Only to be used for static built-in functions! + constexpr TFunction(const TSymbolUniqueId &id, + const ImmutableString &name, + TExtension extension, + const TVariable *const *parameters, + size_t paramCount, + const TType *retType, + TOperator op, + bool knownToNotHaveSideEffects) + : TSymbol(id, + name, + SymbolType::BuiltIn, + std::array{{extension}}, + SymbolClass::Function), + mParametersVector(nullptr), + mParameters(parameters), + returnType(retType), + mMangledName(nullptr), + mParamCount(paramCount), + mOp(op), + defined(false), + mHasPrototypeDeclaration(false), + mKnownToNotHaveSideEffects(knownToNotHaveSideEffects), + mHasVoidParameter(false) + {} + + template + constexpr TFunction(const TSymbolUniqueId &id, + const ImmutableString &name, + const std::array &extensions, + const TVariable *const *parameters, + size_t paramCount, + const TType *retType, + TOperator op, + bool knownToNotHaveSideEffects) + : TSymbol(id, name, SymbolType::BuiltIn, extensions, SymbolClass::Function), + mParametersVector(nullptr), + mParameters(parameters), + returnType(retType), + mMangledName(nullptr), + mParamCount(paramCount), + mOp(op), + defined(false), + mHasPrototypeDeclaration(false), + mKnownToNotHaveSideEffects(knownToNotHaveSideEffects), + mHasVoidParameter(false) + {} + + private: + ImmutableString buildMangledName() const; + + typedef TVector TParamVector; + TParamVector *mParametersVector; + const TVariable *const *mParameters; + const TType *const returnType; + mutable ImmutableString mMangledName; + size_t mParamCount : 32; + const TOperator mOp; // Only set for built-ins + bool defined : 1; + bool mHasPrototypeDeclaration : 1; + bool mKnownToNotHaveSideEffects : 1; + // Whether the parameter list of the function starts with void. This is used to generate an + // error if any other parameter follows. + bool mHasVoidParameter : 1; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_SYMBOL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/SymbolTable.cpp b/gfx/angle/checkout/src/compiler/translator/SymbolTable.cpp new file mode 100644 index 0000000000..8424f474f7 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/SymbolTable.cpp @@ -0,0 +1,559 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Symbol table for parsing. The design principles and most of the functionality are documented in +// the header file. +// + +#if defined(_MSC_VER) +# pragma warning(disable : 4718) +#endif + +#include "compiler/translator/SymbolTable.h" + +#include "angle_gl.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/util.h" + +namespace sh +{ +namespace +{ +bool CheckShaderType(Shader expected, GLenum actual) +{ + switch (expected) + { + case Shader::ALL: + return true; + case Shader::FRAGMENT: + return actual == GL_FRAGMENT_SHADER; + case Shader::VERTEX: + return actual == GL_VERTEX_SHADER; + case Shader::COMPUTE: + return actual == GL_COMPUTE_SHADER; + case Shader::GEOMETRY: + return actual == GL_GEOMETRY_SHADER; + case Shader::GEOMETRY_EXT: + return actual == GL_GEOMETRY_SHADER_EXT; + case Shader::TESS_CONTROL_EXT: + return actual == GL_TESS_CONTROL_SHADER_EXT; + case Shader::TESS_EVALUATION_EXT: + return actual == GL_TESS_EVALUATION_SHADER_EXT; + case Shader::NOT_COMPUTE: + return actual != GL_COMPUTE_SHADER; + default: + UNREACHABLE(); + return false; + } +} + +bool CheckExtension(uint32_t extensionIndex, const ShBuiltInResources &resources) +{ + const int *resourcePtr = reinterpret_cast(&resources); + return resourcePtr[extensionIndex] > 0; +} +} // namespace + +class TSymbolTable::TSymbolTableLevel +{ + public: + TSymbolTableLevel() = default; + + bool insert(TSymbol *symbol); + + // Insert a function using its unmangled name as the key. + void insertUnmangled(TFunction *function); + + TSymbol *find(const ImmutableString &name) const; + + private: + using tLevel = TUnorderedMap>; + using tLevelPair = const tLevel::value_type; + using tInsertResult = std::pair; + + tLevel level; +}; + +bool TSymbolTable::TSymbolTableLevel::insert(TSymbol *symbol) +{ + // returning true means symbol was added to the table + tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol)); + return result.second; +} + +void TSymbolTable::TSymbolTableLevel::insertUnmangled(TFunction *function) +{ + level.insert(tLevelPair(function->name(), function)); +} + +TSymbol *TSymbolTable::TSymbolTableLevel::find(const ImmutableString &name) const +{ + tLevel::const_iterator it = level.find(name); + if (it == level.end()) + return nullptr; + else + return (*it).second; +} + +TSymbolTable::TSymbolTable() + : mGlobalInvariant(false), + mUniqueIdCounter(0), + mShaderType(GL_FRAGMENT_SHADER), + mShaderSpec(SH_GLES2_SPEC), + mGlInVariableWithArraySize(nullptr) +{} + +TSymbolTable::~TSymbolTable() = default; + +bool TSymbolTable::isEmpty() const +{ + return mTable.empty(); +} + +bool TSymbolTable::atGlobalLevel() const +{ + return mTable.size() == 1u; +} + +void TSymbolTable::push() +{ + mTable.emplace_back(new TSymbolTableLevel); + mPrecisionStack.emplace_back(new PrecisionStackLevel); +} + +void TSymbolTable::pop() +{ + mTable.pop_back(); + mPrecisionStack.pop_back(); +} + +const TFunction *TSymbolTable::markFunctionHasPrototypeDeclaration( + const ImmutableString &mangledName, + bool *hadPrototypeDeclarationOut) const +{ + TFunction *function = findUserDefinedFunction(mangledName); + *hadPrototypeDeclarationOut = function->hasPrototypeDeclaration(); + function->setHasPrototypeDeclaration(); + return function; +} + +const TFunction *TSymbolTable::setFunctionParameterNamesFromDefinition(const TFunction *function, + bool *wasDefinedOut) const +{ + TFunction *firstDeclaration = findUserDefinedFunction(function->getMangledName()); + ASSERT(firstDeclaration); + // Note: 'firstDeclaration' could be 'function' if this is the first time we've seen function as + // it would have just been put in the symbol table. Otherwise, we're looking up an earlier + // occurance. + if (function != firstDeclaration) + { + // The previous declaration should have the same parameters as the function definition + // (parameter names may differ). + firstDeclaration->shareParameters(*function); + } + + *wasDefinedOut = firstDeclaration->isDefined(); + firstDeclaration->setDefined(); + return firstDeclaration; +} + +bool TSymbolTable::setGlInArraySize(unsigned int inputArraySize) +{ + if (mGlInVariableWithArraySize) + { + return mGlInVariableWithArraySize->getType().getOutermostArraySize() == inputArraySize; + } + const TInterfaceBlock *glPerVertex = static_cast(m_gl_PerVertex); + TType *glInType = new TType(glPerVertex, EvqPerVertexIn, TLayoutQualifier::Create()); + glInType->makeArray(inputArraySize); + mGlInVariableWithArraySize = + new TVariable(this, ImmutableString("gl_in"), glInType, SymbolType::BuiltIn, + TExtension::EXT_geometry_shader); + return true; +} + +TVariable *TSymbolTable::getGlInVariableWithArraySize() const +{ + return mGlInVariableWithArraySize; +} + +const TVariable *TSymbolTable::gl_FragData() const +{ + return static_cast(m_gl_FragData); +} + +const TVariable *TSymbolTable::gl_SecondaryFragDataEXT() const +{ + return static_cast(m_gl_SecondaryFragDataEXT); +} + +TSymbolTable::VariableMetadata *TSymbolTable::getOrCreateVariableMetadata(const TVariable &variable) +{ + int id = variable.uniqueId().get(); + auto iter = mVariableMetadata.find(id); + if (iter == mVariableMetadata.end()) + { + iter = mVariableMetadata.insert(std::make_pair(id, VariableMetadata())).first; + } + return &iter->second; +} + +void TSymbolTable::markStaticWrite(const TVariable &variable) +{ + auto metadata = getOrCreateVariableMetadata(variable); + metadata->staticWrite = true; +} + +void TSymbolTable::markStaticRead(const TVariable &variable) +{ + auto metadata = getOrCreateVariableMetadata(variable); + metadata->staticRead = true; +} + +bool TSymbolTable::isStaticallyUsed(const TVariable &variable) const +{ + ASSERT(!variable.getConstPointer()); + int id = variable.uniqueId().get(); + auto iter = mVariableMetadata.find(id); + return iter != mVariableMetadata.end() && (iter->second.staticRead || iter->second.staticWrite); +} + +void TSymbolTable::addInvariantVarying(const TVariable &variable) +{ + ASSERT(atGlobalLevel()); + auto metadata = getOrCreateVariableMetadata(variable); + metadata->invariant = true; +} + +bool TSymbolTable::isVaryingInvariant(const TVariable &variable) const +{ + ASSERT(atGlobalLevel()); + if (mGlobalInvariant && (IsShaderOutput(variable.getType().getQualifier()))) + { + return true; + } + int id = variable.uniqueId().get(); + auto iter = mVariableMetadata.find(id); + return iter != mVariableMetadata.end() && iter->second.invariant; +} + +void TSymbolTable::setGlobalInvariant(bool invariant) +{ + ASSERT(atGlobalLevel()); + mGlobalInvariant = invariant; +} + +const TSymbol *TSymbolTable::find(const ImmutableString &name, int shaderVersion) const +{ + const TSymbol *userSymbol = findUserDefined(name); + if (userSymbol) + { + return userSymbol; + } + + return findBuiltIn(name, shaderVersion); +} + +const TSymbol *TSymbolTable::findUserDefined(const ImmutableString &name) const +{ + int userDefinedLevel = static_cast(mTable.size()) - 1; + while (userDefinedLevel >= 0) + { + const TSymbol *symbol = mTable[userDefinedLevel]->find(name); + if (symbol) + { + return symbol; + } + userDefinedLevel--; + } + + return nullptr; +} + +TFunction *TSymbolTable::findUserDefinedFunction(const ImmutableString &name) const +{ + // User-defined functions are always declared at the global level. + ASSERT(!mTable.empty()); + return static_cast(mTable[0]->find(name)); +} + +const TSymbol *TSymbolTable::findGlobal(const ImmutableString &name) const +{ + ASSERT(!mTable.empty()); + return mTable[0]->find(name); +} + +const TSymbol *TSymbolTable::findGlobalWithConversion( + const std::vector &names) const +{ + for (const ImmutableString &name : names) + { + const TSymbol *target = findGlobal(name); + if (target != nullptr) + return target; + } + return nullptr; +} + +const TSymbol *TSymbolTable::findBuiltInWithConversion(const std::vector &names, + int shaderVersion) const +{ + for (const ImmutableString &name : names) + { + const TSymbol *target = findBuiltIn(name, shaderVersion); + if (target != nullptr) + return target; + } + return nullptr; +} + +bool TSymbolTable::declare(TSymbol *symbol) +{ + ASSERT(!mTable.empty()); + // The following built-ins may be redeclared by the shader: gl_ClipDistance, gl_CullDistance and + // gl_LastFragData. + ASSERT(symbol->symbolType() == SymbolType::UserDefined || + (symbol->symbolType() == SymbolType::BuiltIn && IsRedeclarableBuiltIn(symbol->name()))); + ASSERT(!symbol->isFunction()); + return mTable.back()->insert(symbol); +} + +bool TSymbolTable::declareInternal(TSymbol *symbol) +{ + ASSERT(!mTable.empty()); + ASSERT(symbol->symbolType() == SymbolType::AngleInternal); + ASSERT(!symbol->isFunction()); + return mTable.back()->insert(symbol); +} + +void TSymbolTable::declareUserDefinedFunction(TFunction *function, bool insertUnmangledName) +{ + ASSERT(!mTable.empty()); + if (insertUnmangledName) + { + // Insert the unmangled name to detect potential future redefinition as a variable. + mTable[0]->insertUnmangled(function); + } + mTable[0]->insert(function); +} + +void TSymbolTable::setDefaultPrecision(TBasicType type, TPrecision prec) +{ + int indexOfLastElement = static_cast(mPrecisionStack.size()) - 1; + // Uses map operator [], overwrites the current value + (*mPrecisionStack[indexOfLastElement])[type] = prec; +} + +TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const +{ + if (!SupportsPrecision(type)) + return EbpUndefined; + + // unsigned integers use the same precision as signed + TBasicType baseType = (type == EbtUInt) ? EbtInt : type; + + int level = static_cast(mPrecisionStack.size()) - 1; + ASSERT(level >= 0); // Just to be safe. Should not happen. + // If we dont find anything we return this. Some types don't have predefined default precision. + TPrecision prec = EbpUndefined; + while (level >= 0) + { + PrecisionStackLevel::iterator it = mPrecisionStack[level]->find(baseType); + if (it != mPrecisionStack[level]->end()) + { + prec = (*it).second; + break; + } + level--; + } + return prec; +} + +void TSymbolTable::clearCompilationResults() +{ + mGlobalInvariant = false; + mUniqueIdCounter = kLastBuiltInId + 1; + mVariableMetadata.clear(); + mGlInVariableWithArraySize = nullptr; + + // User-defined scopes should have already been cleared when the compilation finished. + ASSERT(mTable.empty()); +} + +int TSymbolTable::nextUniqueIdValue() +{ + ASSERT(mUniqueIdCounter < std::numeric_limits::max()); + return ++mUniqueIdCounter; +} + +void TSymbolTable::initializeBuiltIns(sh::GLenum type, + ShShaderSpec spec, + const ShBuiltInResources &resources) +{ + mShaderType = type; + mShaderSpec = spec; + mResources = resources; + + // We need just one precision stack level for predefined precisions. + mPrecisionStack.emplace_back(new PrecisionStackLevel); + + if (IsDesktopGLSpec(spec)) + { + setDefaultPrecision(EbtInt, EbpUndefined); + setDefaultPrecision(EbtFloat, EbpUndefined); + } + else + { + switch (type) + { + case GL_FRAGMENT_SHADER: + setDefaultPrecision(EbtInt, EbpMedium); + break; + case GL_VERTEX_SHADER: + case GL_COMPUTE_SHADER: + case GL_GEOMETRY_SHADER_EXT: + case GL_TESS_CONTROL_SHADER_EXT: + case GL_TESS_EVALUATION_SHADER_EXT: + setDefaultPrecision(EbtInt, EbpHigh); + setDefaultPrecision(EbtFloat, EbpHigh); + break; + default: + UNREACHABLE(); + } + } + + // Set defaults for sampler types that have default precision, even those that are + // only available if an extension exists. + // New sampler types in ESSL3 don't have default precision. ESSL1 types do. + initSamplerDefaultPrecision(EbtSampler2D); + initSamplerDefaultPrecision(EbtSamplerCube); + // SamplerExternalOES is specified in the extension to have default precision. + initSamplerDefaultPrecision(EbtSamplerExternalOES); + // SamplerExternal2DY2YEXT is specified in the extension to have default precision. + initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT); + // It isn't specified whether Sampler2DRect has default precision. + initSamplerDefaultPrecision(EbtSampler2DRect); + + if (spec < SH_GLES3_SPEC) + { + // Only set the default precision of shadow samplers in ESLL1. They become core in ESSL3 + // where they do not have a defalut precision. + initSamplerDefaultPrecision(EbtSampler2DShadow); + } + + setDefaultPrecision(EbtAtomicCounter, EbpHigh); + + initializeBuiltInVariables(type, spec, resources); + mUniqueIdCounter = kLastBuiltInId + 1; +} + +void TSymbolTable::initSamplerDefaultPrecision(TBasicType samplerType) +{ + ASSERT(samplerType >= EbtGuardSamplerBegin && samplerType <= EbtGuardSamplerEnd); + setDefaultPrecision(samplerType, EbpLow); +} + +TSymbolTable::VariableMetadata::VariableMetadata() + : staticRead(false), staticWrite(false), invariant(false) +{} + +const TSymbol *SymbolRule::get(ShShaderSpec shaderSpec, + int shaderVersion, + sh::GLenum shaderType, + const ShBuiltInResources &resources, + const TSymbolTableBase &symbolTable) const +{ + if (IsDesktopGLSpec(shaderSpec) != (mIsDesktop == 1)) + return nullptr; + + if (mVersion == kESSL1Only && shaderVersion != static_cast(kESSL1Only)) + return nullptr; + + if (mVersion > shaderVersion) + return nullptr; + + if (!CheckShaderType(static_cast(mShaders), shaderType)) + return nullptr; + + if (mExtensionIndex != 0 && !CheckExtension(mExtensionIndex, resources)) + return nullptr; + + return mIsVar > 0 ? symbolTable.*(mSymbolOrVar.var) : mSymbolOrVar.symbol; +} + +const TSymbol *FindMangledBuiltIn(ShShaderSpec shaderSpec, + int shaderVersion, + sh::GLenum shaderType, + const ShBuiltInResources &resources, + const TSymbolTableBase &symbolTable, + const SymbolRule *rules, + uint16_t startIndex, + uint16_t endIndex) +{ + for (uint32_t ruleIndex = startIndex; ruleIndex < endIndex; ++ruleIndex) + { + const TSymbol *symbol = + rules[ruleIndex].get(shaderSpec, shaderVersion, shaderType, resources, symbolTable); + if (symbol) + { + return symbol; + } + } + + return nullptr; +} + +bool UnmangledEntry::matches(const ImmutableString &name, + ShShaderSpec shaderSpec, + int shaderVersion, + sh::GLenum shaderType, + const TExtensionBehavior &extensions) const +{ + if (name != mName) + return false; + + if (!CheckShaderType(static_cast(mShaderType), shaderType)) + return false; + + if (IsDesktopGLSpec(shaderSpec)) + { + if (mGLSLVersion > shaderVersion) + return false; + + if (mGLSLExtension == TExtension::UNDEFINED) + return true; + + return IsExtensionEnabled(extensions, mGLSLExtension); + } + else + { + if (mESSLVersion == kESSL1Only && shaderVersion != static_cast(kESSL1Only)) + return false; + + if (mESSLVersion > shaderVersion) + return false; + + bool anyExtension = false; + bool anyExtensionEnabled = false; + for (TExtension ext : mESSLExtensions) + { + if (ext != TExtension::UNDEFINED) + { + anyExtension = true; + anyExtensionEnabled = anyExtensionEnabled || IsExtensionEnabled(extensions, ext); + } + } + + if (!anyExtension) + return true; + + return anyExtensionEnabled; + } +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/SymbolTable.h b/gfx/angle/checkout/src/compiler/translator/SymbolTable.h new file mode 100644 index 0000000000..fb05729981 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/SymbolTable.h @@ -0,0 +1,363 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_H_ +#define COMPILER_TRANSLATOR_SYMBOLTABLE_H_ + +// +// Symbol table for parsing. Has these design characteristics: +// +// * Same symbol table can be used to compile many shaders, to preserve +// effort of creating and loading with the large numbers of built-in +// symbols. +// +// * Name mangling will be used to give each function a unique name +// so that symbol table lookups are never ambiguous. This allows +// a simpler symbol table structure. +// +// * Pushing and popping of scope, so symbol table will really be a stack +// of symbol tables. Searched from the top, with new inserts going into +// the top. +// +// * Constants: Compile time constant symbols will keep their values +// in the symbol table. The parser can substitute constants at parse +// time, including doing constant folding and constant propagation. +// +// * No temporaries: Temporaries made from operations (+, --, .xy, etc.) +// are tracked in the intermediate representation, not the symbol table. +// + +#include +#include +#include + +#include "common/angleutils.h" +#include "compiler/translator/ExtensionBehavior.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/SymbolTable_autogen.h" + +enum class Shader : uint8_t +{ + ALL, + FRAGMENT, // GL_FRAGMENT_SHADER + VERTEX, // GL_VERTEX_SHADER + COMPUTE, // GL_COMPUTE_SHADER + GEOMETRY, // GL_GEOMETRY_SHADER + GEOMETRY_EXT, // GL_GEOMETRY_SHADER_EXT + TESS_CONTROL_EXT, // GL_TESS_CONTROL_SHADER_EXT + TESS_EVALUATION_EXT, // GL_TESS_EVALUATION_SHADER_EXT + NOT_COMPUTE +}; + +namespace sh +{ + +struct UnmangledBuiltIn +{ + constexpr UnmangledBuiltIn(TExtension extension) : extension(extension) {} + + TExtension extension; +}; + +using VarPointer = TSymbol *(TSymbolTableBase::*); +using ValidateExtension = int ShBuiltInResources::*; + +enum class Spec : uint8_t +{ + GLSL, + ESSL +}; + +constexpr uint16_t kESSL1Only = 100; +// Some built-ins from backend shader languages are made available internally to ESSL for use in +// tree transformations. This (invalid) shader version is used to select those built-ins. This +// value needs to be larger than all other shader versions. +constexpr uint16_t kESSLInternalBackendBuiltIns = 0x3FFF; + +// The version assigned to |kESSLInternalBackendBuiltIns| should be good until OpenGL 20.0! +static_assert(kESSLInternalBackendBuiltIns > 2000, + "Accidentally exposing internal backend built-ins in OpenGL"); + +static_assert(offsetof(ShBuiltInResources, OES_standard_derivatives) != 0, + "Update SymbolTable extension logic"); + +#define EXT_INDEX(Ext) (offsetof(ShBuiltInResources, Ext) / sizeof(int)) + +class SymbolRule +{ + public: + const TSymbol *get(ShShaderSpec shaderSpec, + int shaderVersion, + sh::GLenum shaderType, + const ShBuiltInResources &resources, + const TSymbolTableBase &symbolTable) const; + + template + constexpr static SymbolRule Get(T value); + + private: + constexpr SymbolRule(Spec spec, + int version, + Shader shaders, + size_t extensionIndex, + const TSymbol *symbol); + + constexpr SymbolRule(Spec spec, + int version, + Shader shaders, + size_t extensionIndex, + VarPointer resourceVar); + + union SymbolOrVar + { + constexpr SymbolOrVar(const TSymbol *symbolIn) : symbol(symbolIn) {} + constexpr SymbolOrVar(VarPointer varIn) : var(varIn) {} + + const TSymbol *symbol; + VarPointer var; + }; + + uint16_t mIsDesktop : 1; + uint16_t mIsVar : 1; + uint16_t mVersion : 14; + uint8_t mShaders; + uint8_t mExtensionIndex; + SymbolOrVar mSymbolOrVar; +}; + +constexpr SymbolRule::SymbolRule(Spec spec, + int version, + Shader shaders, + size_t extensionIndex, + const TSymbol *symbol) + : mIsDesktop(spec == Spec::GLSL ? 1u : 0u), + mIsVar(0u), + mVersion(static_cast(version)), + mShaders(static_cast(shaders)), + mExtensionIndex(extensionIndex), + mSymbolOrVar(symbol) +{} + +constexpr SymbolRule::SymbolRule(Spec spec, + int version, + Shader shaders, + size_t extensionIndex, + VarPointer resourceVar) + : mIsDesktop(spec == Spec::GLSL ? 1u : 0u), + mIsVar(1u), + mVersion(static_cast(version)), + mShaders(static_cast(shaders)), + mExtensionIndex(extensionIndex), + mSymbolOrVar(resourceVar) +{} + +template +// static +constexpr SymbolRule SymbolRule::Get(T value) +{ + static_assert(version < 0x4000u, "version OOR"); + static_assert(static_cast(shaders) < 0xFFu, "shaders OOR"); + static_assert(static_cast(extensionIndex) < 0xFF, "extensionIndex OOR"); + return SymbolRule(spec, version, shaders, extensionIndex, value); +} + +const TSymbol *FindMangledBuiltIn(ShShaderSpec shaderSpec, + int shaderVersion, + sh::GLenum shaderType, + const ShBuiltInResources &resources, + const TSymbolTableBase &symbolTable, + const SymbolRule *rules, + uint16_t startIndex, + uint16_t endIndex); + +class UnmangledEntry +{ + public: + template + constexpr UnmangledEntry(const char *name, + const std::array &esslExtensions, + TExtension glslExtension, + int esslVersion, + int glslVersion, + Shader shaderType); + + bool matches(const ImmutableString &name, + ShShaderSpec shaderSpec, + int shaderVersion, + sh::GLenum shaderType, + const TExtensionBehavior &extensions) const; + + private: + const char *mName; + std::array mESSLExtensions; + TExtension mGLSLExtension; + uint8_t mShaderType; + uint16_t mESSLVersion; + uint16_t mGLSLVersion; +}; + +template +constexpr UnmangledEntry::UnmangledEntry(const char *name, + const std::array &esslExtensions, + TExtension glslExtension, + int esslVersion, + int glslVersion, + Shader shaderType) + : mName(name), + mESSLExtensions{(ESSLExtCount >= 1) ? esslExtensions[0] : TExtension::UNDEFINED, + (ESSLExtCount >= 2) ? esslExtensions[1] : TExtension::UNDEFINED}, + mGLSLExtension(glslExtension), + mShaderType(static_cast(shaderType)), + mESSLVersion(esslVersion < 0 ? std::numeric_limits::max() + : static_cast(esslVersion)), + mGLSLVersion(glslVersion < 0 ? std::numeric_limits::max() + : static_cast(glslVersion)) +{} + +class TSymbolTable : angle::NonCopyable, TSymbolTableBase +{ + public: + TSymbolTable(); + // To start using the symbol table after construction: + // * initializeBuiltIns() needs to be called. + // * push() needs to be called to push the global level. + + ~TSymbolTable(); + + bool isEmpty() const; + bool atGlobalLevel() const; + + void push(); + void pop(); + + // Declare a non-function symbol at the current scope. Return true in case the declaration was + // successful, and false if the declaration failed due to redefinition. + bool declare(TSymbol *symbol); + + // Only used to declare internal variables. + bool declareInternal(TSymbol *symbol); + + // Functions are always declared at global scope. + void declareUserDefinedFunction(TFunction *function, bool insertUnmangledName); + + // These return the TFunction pointer to keep using to refer to this function. + const TFunction *markFunctionHasPrototypeDeclaration(const ImmutableString &mangledName, + bool *hadPrototypeDeclarationOut) const; + const TFunction *setFunctionParameterNamesFromDefinition(const TFunction *function, + bool *wasDefinedOut) const; + + // Return false if the gl_in array size has already been initialized with a mismatching value. + bool setGlInArraySize(unsigned int inputArraySize); + TVariable *getGlInVariableWithArraySize() const; + + const TVariable *gl_FragData() const; + const TVariable *gl_SecondaryFragDataEXT() const; + + void markStaticRead(const TVariable &variable); + void markStaticWrite(const TVariable &variable); + + // Note: Should not call this for constant variables. + bool isStaticallyUsed(const TVariable &variable) const; + + // find() is guaranteed not to retain a reference to the ImmutableString, so an ImmutableString + // with a reference to a short-lived char * is fine to pass here. + const TSymbol *find(const ImmutableString &name, int shaderVersion) const; + + const TSymbol *findUserDefined(const ImmutableString &name) const; + + TFunction *findUserDefinedFunction(const ImmutableString &name) const; + + const TSymbol *findGlobal(const ImmutableString &name) const; + const TSymbol *findGlobalWithConversion(const std::vector &names) const; + + const TSymbol *findBuiltIn(const ImmutableString &name, int shaderVersion) const; + const TSymbol *findBuiltInWithConversion(const std::vector &names, + int shaderVersion) const; + + void setDefaultPrecision(TBasicType type, TPrecision prec); + + // Searches down the precisionStack for a precision qualifier + // for the specified TBasicType + TPrecision getDefaultPrecision(TBasicType type) const; + + // This records invariant varyings declared through "invariant varying_name;". + void addInvariantVarying(const TVariable &variable); + + // If this returns false, the varying could still be invariant if it is set as invariant during + // the varying variable declaration - this piece of information is stored in the variable's + // type, not here. + bool isVaryingInvariant(const TVariable &variable) const; + + void setGlobalInvariant(bool invariant); + + const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); } + + // Gets the built-in accessible by a shader with the specified version, if any. + bool isUnmangledBuiltInName(const ImmutableString &name, + int shaderVersion, + const TExtensionBehavior &extensions) const; + + void initializeBuiltIns(sh::GLenum type, + ShShaderSpec spec, + const ShBuiltInResources &resources); + void clearCompilationResults(); + + ShShaderSpec getShaderSpec() const { return mShaderSpec; } + + private: + friend class TSymbolUniqueId; + + struct VariableMetadata + { + VariableMetadata(); + bool staticRead; + bool staticWrite; + bool invariant; + }; + + int nextUniqueIdValue(); + + class TSymbolTableLevel; + + void initSamplerDefaultPrecision(TBasicType samplerType); + + void initializeBuiltInVariables(sh::GLenum shaderType, + ShShaderSpec spec, + const ShBuiltInResources &resources); + + VariableMetadata *getOrCreateVariableMetadata(const TVariable &variable); + + std::vector> mTable; + + // There's one precision stack level for predefined precisions and then one level for each scope + // in table. + typedef TMap PrecisionStackLevel; + std::vector> mPrecisionStack; + + bool mGlobalInvariant; + + int mUniqueIdCounter; + + static const int kLastBuiltInId; + + sh::GLenum mShaderType; + ShShaderSpec mShaderSpec; + ShBuiltInResources mResources; + + // Indexed by unique id. Map instead of vector since the variables are fairly sparse. + std::map mVariableMetadata; + + // Store gl_in variable with its array size once the array size can be determined. The array + // size can also be checked against latter input primitive type declaration. + TVariable *mGlInVariableWithArraySize; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/SymbolTable_ESSL_autogen.cpp b/gfx/angle/checkout/src/compiler/translator/SymbolTable_ESSL_autogen.cpp new file mode 100644 index 0000000000..483e9b4748 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/SymbolTable_ESSL_autogen.cpp @@ -0,0 +1,30071 @@ +// GENERATED FILE - DO NOT EDIT. +// Generated by gen_builtin_symbols.py using data from builtin_variables.json and +// builtin_function_declarations.txt. +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SymbolTable_ESSL_autogen.cpp: +// Compile-time initialized built-ins. + +#include + +#include "compiler/translator/SymbolTable.h" + +#include "angle_gl.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/BuiltIn.h" + +namespace sh +{ +using Resources = ShBuiltInResources; +using TableBase = TSymbolTableBase; + +const int TSymbolTable::kLastBuiltInId = 5603; + +namespace BuiltInName +{ + +constexpr const ImmutableString _empty(""); +constexpr const ImmutableString EmitVertex("EmitVertex"); +constexpr const ImmutableString EmitVertexES3_2("EmitVertex"); +constexpr const ImmutableString EndPrimitive("EndPrimitive"); +constexpr const ImmutableString EndPrimitiveES3_2("EndPrimitive"); +constexpr const ImmutableString abs("abs"); +constexpr const ImmutableString acos("acos"); +constexpr const ImmutableString acosh("acosh"); +constexpr const ImmutableString all("all"); +constexpr const ImmutableString angle_BaseInstance("angle_BaseInstance"); +constexpr const ImmutableString angle_BaseVertex("angle_BaseVertex"); +constexpr const ImmutableString any("any"); +constexpr const ImmutableString asin("asin"); +constexpr const ImmutableString asinh("asinh"); +constexpr const ImmutableString atan("atan"); +constexpr const ImmutableString atanh("atanh"); +constexpr const ImmutableString atomicAdd("atomicAdd"); +constexpr const ImmutableString atomicAnd("atomicAnd"); +constexpr const ImmutableString atomicCompSwap("atomicCompSwap"); +constexpr const ImmutableString atomicCounter("atomicCounter"); +constexpr const ImmutableString atomicCounterDecrement("atomicCounterDecrement"); +constexpr const ImmutableString atomicCounterIncrement("atomicCounterIncrement"); +constexpr const ImmutableString atomicExchange("atomicExchange"); +constexpr const ImmutableString atomicMax("atomicMax"); +constexpr const ImmutableString atomicMin("atomicMin"); +constexpr const ImmutableString atomicOr("atomicOr"); +constexpr const ImmutableString atomicXor("atomicXor"); +constexpr const ImmutableString barrier("barrier"); +constexpr const ImmutableString barrierTCS("barrier"); +constexpr const ImmutableString barrierTCSES3_2("barrier"); +constexpr const ImmutableString beginFragmentShaderOrderingINTEL( + "beginFragmentShaderOrderingINTEL"); +constexpr const ImmutableString beginInvocationInterlockARB("beginInvocationInterlockARB"); +constexpr const ImmutableString beginInvocationInterlockNV("beginInvocationInterlockNV"); +constexpr const ImmutableString bitCount("bitCount"); +constexpr const ImmutableString bitfieldExtract("bitfieldExtract"); +constexpr const ImmutableString bitfieldInsert("bitfieldInsert"); +constexpr const ImmutableString bitfieldReverse("bitfieldReverse"); +constexpr const ImmutableString ceil("ceil"); +constexpr const ImmutableString clamp("clamp"); +constexpr const ImmutableString cos("cos"); +constexpr const ImmutableString cosh("cosh"); +constexpr const ImmutableString cross("cross"); +constexpr const ImmutableString dFdx("dFdx"); +constexpr const ImmutableString dFdxExt("dFdx"); +constexpr const ImmutableString dFdy("dFdy"); +constexpr const ImmutableString dFdyExt("dFdy"); +constexpr const ImmutableString degrees("degrees"); +constexpr const ImmutableString determinant("determinant"); +constexpr const ImmutableString diff("diff"); +constexpr const ImmutableString distance("distance"); +constexpr const ImmutableString dot("dot"); +constexpr const ImmutableString endInvocationInterlockARB("endInvocationInterlockARB"); +constexpr const ImmutableString endInvocationInterlockNV("endInvocationInterlockNV"); +constexpr const ImmutableString equal("equal"); +constexpr const ImmutableString exp("exp"); +constexpr const ImmutableString exp2("exp2"); +constexpr const ImmutableString faceforward("faceforward"); +constexpr const ImmutableString far("far"); +constexpr const ImmutableString findLSB("findLSB"); +constexpr const ImmutableString findMSB("findMSB"); +constexpr const ImmutableString floatBitsToInt("floatBitsToInt"); +constexpr const ImmutableString floatBitsToUint("floatBitsToUint"); +constexpr const ImmutableString floor("floor"); +constexpr const ImmutableString fma("fma"); +constexpr const ImmutableString fmaExt("fma"); +constexpr const ImmutableString fract("fract"); +constexpr const ImmutableString frexp("frexp"); +constexpr const ImmutableString fwidth("fwidth"); +constexpr const ImmutableString fwidthExt("fwidth"); +constexpr const ImmutableString gl_BaseInstance("gl_BaseInstance"); +constexpr const ImmutableString gl_BaseVertex("gl_BaseVertex"); +constexpr const ImmutableString gl_BoundingBox("gl_BoundingBox"); +constexpr const ImmutableString gl_BoundingBoxEXT("gl_BoundingBoxEXT"); +constexpr const ImmutableString gl_BoundingBoxOES("gl_BoundingBoxOES"); +constexpr const ImmutableString gl_ClipDistance("gl_ClipDistance"); +constexpr const ImmutableString gl_CullDistance("gl_CullDistance"); +constexpr const ImmutableString gl_DepthRange("gl_DepthRange"); +constexpr const ImmutableString gl_DepthRangeParameters("gl_DepthRangeParameters"); +constexpr const ImmutableString gl_DrawID("gl_DrawID"); +constexpr const ImmutableString gl_FragColor("gl_FragColor"); +constexpr const ImmutableString gl_FragCoord("gl_FragCoord"); +constexpr const ImmutableString gl_FragData("gl_FragData"); +constexpr const ImmutableString gl_FragDepth("gl_FragDepth"); +constexpr const ImmutableString gl_FragDepthEXT("gl_FragDepthEXT"); +constexpr const ImmutableString gl_FrontFacing("gl_FrontFacing"); +constexpr const ImmutableString gl_GlobalInvocationID("gl_GlobalInvocationID"); +constexpr const ImmutableString gl_HelperInvocation("gl_HelperInvocation"); +constexpr const ImmutableString gl_InstanceID("gl_InstanceID"); +constexpr const ImmutableString gl_InstanceIndex("gl_InstanceIndex"); +constexpr const ImmutableString gl_InvocationID("gl_InvocationID"); +constexpr const ImmutableString gl_LastFragColor("gl_LastFragColor"); +constexpr const ImmutableString gl_LastFragColorARM("gl_LastFragColorARM"); +constexpr const ImmutableString gl_LastFragData("gl_LastFragData"); +constexpr const ImmutableString gl_Layer("gl_Layer"); +constexpr const ImmutableString gl_LocalInvocationID("gl_LocalInvocationID"); +constexpr const ImmutableString gl_LocalInvocationIndex("gl_LocalInvocationIndex"); +constexpr const ImmutableString gl_MaxAtomicCounterBindings("gl_MaxAtomicCounterBindings"); +constexpr const ImmutableString gl_MaxAtomicCounterBufferSize("gl_MaxAtomicCounterBufferSize"); +constexpr const ImmutableString gl_MaxClipDistances("gl_MaxClipDistances"); +constexpr const ImmutableString gl_MaxCombinedAtomicCounterBuffers( + "gl_MaxCombinedAtomicCounterBuffers"); +constexpr const ImmutableString gl_MaxCombinedAtomicCounters("gl_MaxCombinedAtomicCounters"); +constexpr const ImmutableString gl_MaxCombinedClipAndCullDistances( + "gl_MaxCombinedClipAndCullDistances"); +constexpr const ImmutableString gl_MaxCombinedImageUniforms("gl_MaxCombinedImageUniforms"); +constexpr const ImmutableString gl_MaxCombinedShaderOutputResources( + "gl_MaxCombinedShaderOutputResources"); +constexpr const ImmutableString gl_MaxCombinedTextureImageUnits("gl_MaxCombinedTextureImageUnits"); +constexpr const ImmutableString gl_MaxComputeAtomicCounterBuffers( + "gl_MaxComputeAtomicCounterBuffers"); +constexpr const ImmutableString gl_MaxComputeAtomicCounters("gl_MaxComputeAtomicCounters"); +constexpr const ImmutableString gl_MaxComputeImageUniforms("gl_MaxComputeImageUniforms"); +constexpr const ImmutableString gl_MaxComputeTextureImageUnits("gl_MaxComputeTextureImageUnits"); +constexpr const ImmutableString gl_MaxComputeUniformComponents("gl_MaxComputeUniformComponents"); +constexpr const ImmutableString gl_MaxComputeWorkGroupCount("gl_MaxComputeWorkGroupCount"); +constexpr const ImmutableString gl_MaxComputeWorkGroupSize("gl_MaxComputeWorkGroupSize"); +constexpr const ImmutableString gl_MaxCullDistances("gl_MaxCullDistances"); +constexpr const ImmutableString gl_MaxDrawBuffers("gl_MaxDrawBuffers"); +constexpr const ImmutableString gl_MaxDualSourceDrawBuffersEXT("gl_MaxDualSourceDrawBuffersEXT"); +constexpr const ImmutableString gl_MaxFragmentAtomicCounterBuffers( + "gl_MaxFragmentAtomicCounterBuffers"); +constexpr const ImmutableString gl_MaxFragmentAtomicCounters("gl_MaxFragmentAtomicCounters"); +constexpr const ImmutableString gl_MaxFragmentImageUniforms("gl_MaxFragmentImageUniforms"); +constexpr const ImmutableString gl_MaxFragmentInputVectors("gl_MaxFragmentInputVectors"); +constexpr const ImmutableString gl_MaxFragmentUniformVectors("gl_MaxFragmentUniformVectors"); +constexpr const ImmutableString gl_MaxGeometryAtomicCounterBuffers( + "gl_MaxGeometryAtomicCounterBuffers"); +constexpr const ImmutableString gl_MaxGeometryAtomicCounters("gl_MaxGeometryAtomicCounters"); +constexpr const ImmutableString gl_MaxGeometryImageUniforms("gl_MaxGeometryImageUniforms"); +constexpr const ImmutableString gl_MaxGeometryInputComponents("gl_MaxGeometryInputComponents"); +constexpr const ImmutableString gl_MaxGeometryOutputComponents("gl_MaxGeometryOutputComponents"); +constexpr const ImmutableString gl_MaxGeometryOutputVertices("gl_MaxGeometryOutputVertices"); +constexpr const ImmutableString gl_MaxGeometryTextureImageUnits("gl_MaxGeometryTextureImageUnits"); +constexpr const ImmutableString gl_MaxGeometryTotalOutputComponents( + "gl_MaxGeometryTotalOutputComponents"); +constexpr const ImmutableString gl_MaxGeometryUniformComponents("gl_MaxGeometryUniformComponents"); +constexpr const ImmutableString gl_MaxImageUnits("gl_MaxImageUnits"); +constexpr const ImmutableString gl_MaxPatchVertices("gl_MaxPatchVertices"); +constexpr const ImmutableString gl_MaxProgramTexelOffset("gl_MaxProgramTexelOffset"); +constexpr const ImmutableString gl_MaxSamples("gl_MaxSamples"); +constexpr const ImmutableString gl_MaxTessControlAtomicCounterBuffers( + "gl_MaxTessControlAtomicCounterBuffers"); +constexpr const ImmutableString gl_MaxTessControlAtomicCounters("gl_MaxTessControlAtomicCounters"); +constexpr const ImmutableString gl_MaxTessControlImageUniforms("gl_MaxTessControlImageUniforms"); +constexpr const ImmutableString gl_MaxTessControlInputComponents( + "gl_MaxTessControlInputComponents"); +constexpr const ImmutableString gl_MaxTessControlOutputComponents( + "gl_MaxTessControlOutputComponents"); +constexpr const ImmutableString gl_MaxTessControlTextureImageUnits( + "gl_MaxTessControlTextureImageUnits"); +constexpr const ImmutableString gl_MaxTessControlTotalOutputComponents( + "gl_MaxTessControlTotalOutputComponents"); +constexpr const ImmutableString gl_MaxTessControlUniformComponents( + "gl_MaxTessControlUniformComponents"); +constexpr const ImmutableString gl_MaxTessEvaluationAtomicCounterBuffers( + "gl_MaxTessEvaluationAtomicCounterBuffers"); +constexpr const ImmutableString gl_MaxTessEvaluationAtomicCounters( + "gl_MaxTessEvaluationAtomicCounters"); +constexpr const ImmutableString gl_MaxTessEvaluationImageUniforms( + "gl_MaxTessEvaluationImageUniforms"); +constexpr const ImmutableString gl_MaxTessEvaluationInputComponents( + "gl_MaxTessEvaluationInputComponents"); +constexpr const ImmutableString gl_MaxTessEvaluationOutputComponents( + "gl_MaxTessEvaluationOutputComponents"); +constexpr const ImmutableString gl_MaxTessEvaluationTextureImageUnits( + "gl_MaxTessEvaluationTextureImageUnits"); +constexpr const ImmutableString gl_MaxTessEvaluationUniformComponents( + "gl_MaxTessEvaluationUniformComponents"); +constexpr const ImmutableString gl_MaxTessGenLevel("gl_MaxTessGenLevel"); +constexpr const ImmutableString gl_MaxTessPatchComponents("gl_MaxTessPatchComponents"); +constexpr const ImmutableString gl_MaxTextureImageUnits("gl_MaxTextureImageUnits"); +constexpr const ImmutableString gl_MaxVaryingVectors("gl_MaxVaryingVectors"); +constexpr const ImmutableString gl_MaxVertexAtomicCounterBuffers( + "gl_MaxVertexAtomicCounterBuffers"); +constexpr const ImmutableString gl_MaxVertexAtomicCounters("gl_MaxVertexAtomicCounters"); +constexpr const ImmutableString gl_MaxVertexAttribs("gl_MaxVertexAttribs"); +constexpr const ImmutableString gl_MaxVertexImageUniforms("gl_MaxVertexImageUniforms"); +constexpr const ImmutableString gl_MaxVertexOutputVectors("gl_MaxVertexOutputVectors"); +constexpr const ImmutableString gl_MaxVertexTextureImageUnits("gl_MaxVertexTextureImageUnits"); +constexpr const ImmutableString gl_MaxVertexUniformVectors("gl_MaxVertexUniformVectors"); +constexpr const ImmutableString gl_MinProgramTexelOffset("gl_MinProgramTexelOffset"); +constexpr const ImmutableString gl_NumSamples("gl_NumSamples"); +constexpr const ImmutableString gl_NumWorkGroups("gl_NumWorkGroups"); +constexpr const ImmutableString gl_PatchVerticesIn("gl_PatchVerticesIn"); +constexpr const ImmutableString gl_PerVertex("gl_PerVertex"); +constexpr const ImmutableString gl_PointCoord("gl_PointCoord"); +constexpr const ImmutableString gl_PointSize("gl_PointSize"); +constexpr const ImmutableString gl_Position("gl_Position"); +constexpr const ImmutableString gl_PrimitiveID("gl_PrimitiveID"); +constexpr const ImmutableString gl_PrimitiveIDIn("gl_PrimitiveIDIn"); +constexpr const ImmutableString gl_SampleID("gl_SampleID"); +constexpr const ImmutableString gl_SampleMask("gl_SampleMask"); +constexpr const ImmutableString gl_SampleMaskIn("gl_SampleMaskIn"); +constexpr const ImmutableString gl_SamplePosition("gl_SamplePosition"); +constexpr const ImmutableString gl_SecondaryFragColorEXT("gl_SecondaryFragColorEXT"); +constexpr const ImmutableString gl_SecondaryFragDataEXT("gl_SecondaryFragDataEXT"); +constexpr const ImmutableString gl_TessCoord("gl_TessCoord"); +constexpr const ImmutableString gl_TessLevelInner("gl_TessLevelInner"); +constexpr const ImmutableString gl_TessLevelOuter("gl_TessLevelOuter"); +constexpr const ImmutableString gl_VertexID("gl_VertexID"); +constexpr const ImmutableString gl_VertexIndex("gl_VertexIndex"); +constexpr const ImmutableString gl_ViewID_OVR("gl_ViewID_OVR"); +constexpr const ImmutableString gl_ViewportIndex("gl_ViewportIndex"); +constexpr const ImmutableString gl_WorkGroupID("gl_WorkGroupID"); +constexpr const ImmutableString gl_WorkGroupSize("gl_WorkGroupSize"); +constexpr const ImmutableString gl_in("gl_in"); +constexpr const ImmutableString gl_out("gl_out"); +constexpr const ImmutableString greaterThan("greaterThan"); +constexpr const ImmutableString greaterThanEqual("greaterThanEqual"); +constexpr const ImmutableString groupMemoryBarrier("groupMemoryBarrier"); +constexpr const ImmutableString imageAtomicAdd("imageAtomicAdd"); +constexpr const ImmutableString imageAtomicAddExt("imageAtomicAdd"); +constexpr const ImmutableString imageAtomicAnd("imageAtomicAnd"); +constexpr const ImmutableString imageAtomicAndExt("imageAtomicAnd"); +constexpr const ImmutableString imageAtomicCompSwap("imageAtomicCompSwap"); +constexpr const ImmutableString imageAtomicCompSwapExt("imageAtomicCompSwap"); +constexpr const ImmutableString imageAtomicExchange("imageAtomicExchange"); +constexpr const ImmutableString imageAtomicExchangeExt("imageAtomicExchange"); +constexpr const ImmutableString imageAtomicMax("imageAtomicMax"); +constexpr const ImmutableString imageAtomicMaxExt("imageAtomicMax"); +constexpr const ImmutableString imageAtomicMin("imageAtomicMin"); +constexpr const ImmutableString imageAtomicMinExt("imageAtomicMin"); +constexpr const ImmutableString imageAtomicOr("imageAtomicOr"); +constexpr const ImmutableString imageAtomicOrExt("imageAtomicOr"); +constexpr const ImmutableString imageAtomicXor("imageAtomicXor"); +constexpr const ImmutableString imageAtomicXorExt("imageAtomicXor"); +constexpr const ImmutableString imageLoad("imageLoad"); +constexpr const ImmutableString imageLoadExt("imageLoad"); +constexpr const ImmutableString imageSize("imageSize"); +constexpr const ImmutableString imageSizeExt("imageSize"); +constexpr const ImmutableString imageStore("imageStore"); +constexpr const ImmutableString imageStoreExt("imageStore"); +constexpr const ImmutableString imulExtended("imulExtended"); +constexpr const ImmutableString intBitsToFloat("intBitsToFloat"); +constexpr const ImmutableString interpolateAtCentroid("interpolateAtCentroid"); +constexpr const ImmutableString interpolateAtCentroidExt("interpolateAtCentroid"); +constexpr const ImmutableString interpolateAtOffset("interpolateAtOffset"); +constexpr const ImmutableString interpolateAtOffsetExt("interpolateAtOffset"); +constexpr const ImmutableString interpolateAtSample("interpolateAtSample"); +constexpr const ImmutableString interpolateAtSampleExt("interpolateAtSample"); +constexpr const ImmutableString inverse("inverse"); +constexpr const ImmutableString inversesqrt("inversesqrt"); +constexpr const ImmutableString isinf("isinf"); +constexpr const ImmutableString isnan("isnan"); +constexpr const ImmutableString ldexp("ldexp"); +constexpr const ImmutableString length("length"); +constexpr const ImmutableString lessThan("lessThan"); +constexpr const ImmutableString lessThanEqual("lessThanEqual"); +constexpr const ImmutableString log("log"); +constexpr const ImmutableString log2("log2"); +constexpr const ImmutableString matrixCompMult("matrixCompMult"); +constexpr const ImmutableString max("max"); +constexpr const ImmutableString memoryBarrier("memoryBarrier"); +constexpr const ImmutableString memoryBarrierAtomicCounter("memoryBarrierAtomicCounter"); +constexpr const ImmutableString memoryBarrierBuffer("memoryBarrierBuffer"); +constexpr const ImmutableString memoryBarrierImage("memoryBarrierImage"); +constexpr const ImmutableString memoryBarrierShared("memoryBarrierShared"); +constexpr const ImmutableString min("min"); +constexpr const ImmutableString mix("mix"); +constexpr const ImmutableString mod("mod"); +constexpr const ImmutableString modf("modf"); +constexpr const ImmutableString near("near"); +constexpr const ImmutableString normalize("normalize"); +constexpr const ImmutableString notEqual("notEqual"); +constexpr const ImmutableString notFunc("not"); +constexpr const ImmutableString outerProduct("outerProduct"); +constexpr const ImmutableString packHalf2x16("packHalf2x16"); +constexpr const ImmutableString packSnorm2x16("packSnorm2x16"); +constexpr const ImmutableString packSnorm4x8("packSnorm4x8"); +constexpr const ImmutableString packUnorm2x16("packUnorm2x16"); +constexpr const ImmutableString packUnorm4x8("packUnorm4x8"); +constexpr const ImmutableString pixelLocalLoadANGLE("pixelLocalLoadANGLE"); +constexpr const ImmutableString pixelLocalStoreANGLE("pixelLocalStoreANGLE"); +constexpr const ImmutableString pow("pow"); +constexpr const ImmutableString radians("radians"); +constexpr const ImmutableString reflect("reflect"); +constexpr const ImmutableString refract("refract"); +constexpr const ImmutableString rgb_2_yuv("rgb_2_yuv"); +constexpr const ImmutableString round("round"); +constexpr const ImmutableString roundEven("roundEven"); +constexpr const ImmutableString shadow2DEXT("shadow2DEXT"); +constexpr const ImmutableString shadow2DProjEXT("shadow2DProjEXT"); +constexpr const ImmutableString sign("sign"); +constexpr const ImmutableString sin("sin"); +constexpr const ImmutableString sinh("sinh"); +constexpr const ImmutableString smoothstep("smoothstep"); +constexpr const ImmutableString sqrt("sqrt"); +constexpr const ImmutableString step("step"); +constexpr const ImmutableString subpassLoad("subpassLoad"); +constexpr const ImmutableString tan("tan"); +constexpr const ImmutableString tanh("tanh"); +constexpr const ImmutableString texelFetch("texelFetch"); +constexpr const ImmutableString texelFetchExt("texelFetch"); +constexpr const ImmutableString texelFetchOffset("texelFetchOffset"); +constexpr const ImmutableString texture("texture"); +constexpr const ImmutableString texture2D("texture2D"); +constexpr const ImmutableString texture2DGradEXT("texture2DGradEXT"); +constexpr const ImmutableString texture2DLod("texture2DLod"); +constexpr const ImmutableString texture2DLodEXT("texture2DLodEXT"); +constexpr const ImmutableString texture2DProj("texture2DProj"); +constexpr const ImmutableString texture2DProjGradEXT("texture2DProjGradEXT"); +constexpr const ImmutableString texture2DProjLod("texture2DProjLod"); +constexpr const ImmutableString texture2DProjLodEXT("texture2DProjLodEXT"); +constexpr const ImmutableString texture2DRect("texture2DRect"); +constexpr const ImmutableString texture2DRectProj("texture2DRectProj"); +constexpr const ImmutableString texture3D("texture3D"); +constexpr const ImmutableString texture3DLod("texture3DLod"); +constexpr const ImmutableString texture3DProj("texture3DProj"); +constexpr const ImmutableString texture3DProjLod("texture3DProjLod"); +constexpr const ImmutableString textureCube("textureCube"); +constexpr const ImmutableString textureCubeGradEXT("textureCubeGradEXT"); +constexpr const ImmutableString textureCubeLod("textureCubeLod"); +constexpr const ImmutableString textureCubeLodEXT("textureCubeLodEXT"); +constexpr const ImmutableString textureExt("texture"); +constexpr const ImmutableString textureGather("textureGather"); +constexpr const ImmutableString textureGatherExt("textureGather"); +constexpr const ImmutableString textureGatherOffset("textureGatherOffset"); +constexpr const ImmutableString textureGatherOffsets("textureGatherOffsets"); +constexpr const ImmutableString textureGatherOffsetsExt("textureGatherOffsets"); +constexpr const ImmutableString textureGrad("textureGrad"); +constexpr const ImmutableString textureGradExt("textureGrad"); +constexpr const ImmutableString textureGradOffset("textureGradOffset"); +constexpr const ImmutableString textureLod("textureLod"); +constexpr const ImmutableString textureLodExt("textureLod"); +constexpr const ImmutableString textureLodOffset("textureLodOffset"); +constexpr const ImmutableString textureOffset("textureOffset"); +constexpr const ImmutableString textureProj("textureProj"); +constexpr const ImmutableString textureProjGrad("textureProjGrad"); +constexpr const ImmutableString textureProjGradOffset("textureProjGradOffset"); +constexpr const ImmutableString textureProjLod("textureProjLod"); +constexpr const ImmutableString textureProjLodOffset("textureProjLodOffset"); +constexpr const ImmutableString textureProjOffset("textureProjOffset"); +constexpr const ImmutableString textureSize("textureSize"); +constexpr const ImmutableString textureSizeExt("textureSize"); +constexpr const ImmutableString textureVideoWEBGL("textureVideoWEBGL"); +constexpr const ImmutableString transpose("transpose"); +constexpr const ImmutableString trunc("trunc"); +constexpr const ImmutableString uaddCarry("uaddCarry"); +constexpr const ImmutableString uintBitsToFloat("uintBitsToFloat"); +constexpr const ImmutableString umulExtended("umulExtended"); +constexpr const ImmutableString unpackHalf2x16("unpackHalf2x16"); +constexpr const ImmutableString unpackSnorm2x16("unpackSnorm2x16"); +constexpr const ImmutableString unpackSnorm4x8("unpackSnorm4x8"); +constexpr const ImmutableString unpackUnorm2x16("unpackUnorm2x16"); +constexpr const ImmutableString unpackUnorm4x8("unpackUnorm4x8"); +constexpr const ImmutableString usubBorrow("usubBorrow"); +constexpr const ImmutableString yuv_2_rgb("yuv_2_rgb"); + +} // namespace BuiltInName + +// TODO(oetuaho): Would be nice to make this a class instead of a namespace so that we could friend +// this from TVariable. Now symbol constructors taking an id have to be public even though they're +// not supposed to be accessible from outside of here. http://anglebug.com/2390 +namespace BuiltInVariable +{ + +constexpr const unsigned int kArraySize4[1] = {4}; + +constexpr const TVariable kangle_BaseInstance( + BuiltInId::angle_BaseInstance, + BuiltInName::angle_BaseInstance, + SymbolType::BuiltIn, + std::array{{TExtension::ANGLE_base_vertex_base_instance_shader_builtin}}, + StaticType::Get()); +constexpr const TVariable kangle_BaseVertex( + BuiltInId::angle_BaseVertex, + BuiltInName::angle_BaseVertex, + SymbolType::BuiltIn, + std::array{{TExtension::ANGLE_base_vertex_base_instance_shader_builtin}}, + StaticType::Get()); +constexpr const TVariable kgl_BaseInstance( + BuiltInId::gl_BaseInstance, + BuiltInName::gl_BaseInstance, + SymbolType::BuiltIn, + std::array{{TExtension::ANGLE_base_vertex_base_instance_shader_builtin}}, + StaticType::Get()); +constexpr const TVariable kgl_BaseVertex( + BuiltInId::gl_BaseVertex, + BuiltInName::gl_BaseVertex, + SymbolType::BuiltIn, + std::array{{TExtension::ANGLE_base_vertex_base_instance_shader_builtin}}, + StaticType::Get()); +constexpr const TVariable kgl_DrawID(BuiltInId::gl_DrawID, + BuiltInName::gl_DrawID, + SymbolType::BuiltIn, + std::array{{TExtension::ANGLE_multi_draw}}, + StaticType::Get()); +constexpr const TVariable kgl_FragColor(BuiltInId::gl_FragColor, + BuiltInName::gl_FragColor, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_FragCoord(BuiltInId::gl_FragCoord, + BuiltInName::gl_FragCoord, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_FragCoord300( + BuiltInId::gl_FragCoord300, + BuiltInName::gl_FragCoord, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_FragDepth(BuiltInId::gl_FragDepth, + BuiltInName::gl_FragDepth, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_FrontFacing( + BuiltInId::gl_FrontFacing, + BuiltInName::gl_FrontFacing, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_GlobalInvocationID( + BuiltInId::gl_GlobalInvocationID, + BuiltInName::gl_GlobalInvocationID, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_HelperInvocation( + BuiltInId::gl_HelperInvocation, + BuiltInName::gl_HelperInvocation, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_InstanceID(BuiltInId::gl_InstanceID, + BuiltInName::gl_InstanceID, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_InstanceIndex( + BuiltInId::gl_InstanceIndex, + BuiltInName::gl_InstanceIndex, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_InvocationID( + BuiltInId::gl_InvocationID, + BuiltInName::gl_InvocationID, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + StaticType::Get()); +constexpr const TVariable kgl_InvocationIDES3_2( + BuiltInId::gl_InvocationIDES3_2, + BuiltInName::gl_InvocationID, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_InvocationIDTCS( + BuiltInId::gl_InvocationIDTCS, + BuiltInName::gl_InvocationID, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); +constexpr const TVariable kgl_InvocationIDTCSES3_2( + BuiltInId::gl_InvocationIDTCSES3_2, + BuiltInName::gl_InvocationID, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_LastFragColor( + BuiltInId::gl_LastFragColor, + BuiltInName::gl_LastFragColor, + SymbolType::BuiltIn, + std::array{{TExtension::NV_shader_framebuffer_fetch}}, + StaticType::Get()); +constexpr const TVariable kgl_LastFragColorARM( + BuiltInId::gl_LastFragColorARM, + BuiltInName::gl_LastFragColorARM, + SymbolType::BuiltIn, + std::array{{TExtension::ARM_shader_framebuffer_fetch}}, + StaticType::Get()); +constexpr const TVariable kgl_Layer(BuiltInId::gl_Layer, + BuiltInName::gl_Layer, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_geometry_shader, + TExtension::OES_geometry_shader}}, + StaticType::Get()); +constexpr const TVariable kgl_LayerES3_2(BuiltInId::gl_LayerES3_2, + BuiltInName::gl_Layer, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_LayerGS(BuiltInId::gl_LayerGS, + BuiltInName::gl_Layer, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_geometry_shader, + TExtension::OES_geometry_shader}}, + StaticType::Get()); +constexpr const TVariable kgl_LayerGSES3_2(BuiltInId::gl_LayerGSES3_2, + BuiltInName::gl_Layer, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_LayerVS(BuiltInId::gl_LayerVS, + BuiltInName::gl_Layer, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_LocalInvocationID( + BuiltInId::gl_LocalInvocationID, + BuiltInName::gl_LocalInvocationID, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_LocalInvocationIndex( + BuiltInId::gl_LocalInvocationIndex, + BuiltInName::gl_LocalInvocationIndex, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_NumSamples(BuiltInId::gl_NumSamples, + BuiltInName::gl_NumSamples, + SymbolType::BuiltIn, + std::array{ + {TExtension::OES_sample_variables}}, + StaticType::Get()); +constexpr const TVariable kgl_NumSamplesES3_2(BuiltInId::gl_NumSamplesES3_2, + BuiltInName::gl_NumSamples, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_NumWorkGroups( + BuiltInId::gl_NumWorkGroups, + BuiltInName::gl_NumWorkGroups, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_PatchVerticesInTCS( + BuiltInId::gl_PatchVerticesInTCS, + BuiltInName::gl_PatchVerticesIn, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); +constexpr const TVariable kgl_PatchVerticesInTCSES3_2( + BuiltInId::gl_PatchVerticesInTCSES3_2, + BuiltInName::gl_PatchVerticesIn, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_PatchVerticesInTES( + BuiltInId::gl_PatchVerticesInTES, + BuiltInName::gl_PatchVerticesIn, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); +constexpr const TVariable kgl_PatchVerticesInTESES3_2( + BuiltInId::gl_PatchVerticesInTESES3_2, + BuiltInName::gl_PatchVerticesIn, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_PointCoord( + BuiltInId::gl_PointCoord, + BuiltInName::gl_PointCoord, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_PointSize(BuiltInId::gl_PointSize, + BuiltInName::gl_PointSize, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_PointSize300( + BuiltInId::gl_PointSize300, + BuiltInName::gl_PointSize, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_Position(BuiltInId::gl_Position, + BuiltInName::gl_Position, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_PrimitiveID( + BuiltInId::gl_PrimitiveID, + BuiltInName::gl_PrimitiveID, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + StaticType::Get()); +constexpr const TVariable kgl_PrimitiveIDES3_2( + BuiltInId::gl_PrimitiveIDES3_2, + BuiltInName::gl_PrimitiveID, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_PrimitiveIDGS( + BuiltInId::gl_PrimitiveIDGS, + BuiltInName::gl_PrimitiveID, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + StaticType::Get()); +constexpr const TVariable kgl_PrimitiveIDGSES3_2( + BuiltInId::gl_PrimitiveIDGSES3_2, + BuiltInName::gl_PrimitiveID, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_PrimitiveIDIn( + BuiltInId::gl_PrimitiveIDIn, + BuiltInName::gl_PrimitiveIDIn, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + StaticType::Get()); +constexpr const TVariable kgl_PrimitiveIDInES3_2( + BuiltInId::gl_PrimitiveIDInES3_2, + BuiltInName::gl_PrimitiveIDIn, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_PrimitiveIDTCS( + BuiltInId::gl_PrimitiveIDTCS, + BuiltInName::gl_PrimitiveID, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); +constexpr const TVariable kgl_PrimitiveIDTCSES3_2( + BuiltInId::gl_PrimitiveIDTCSES3_2, + BuiltInName::gl_PrimitiveID, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_PrimitiveIDTES( + BuiltInId::gl_PrimitiveIDTES, + BuiltInName::gl_PrimitiveID, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); +constexpr const TVariable kgl_PrimitiveIDTESES3_2( + BuiltInId::gl_PrimitiveIDTESES3_2, + BuiltInName::gl_PrimitiveID, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_SampleID(BuiltInId::gl_SampleID, + BuiltInName::gl_SampleID, + SymbolType::BuiltIn, + std::array{ + {TExtension::OES_sample_variables}}, + StaticType::Get()); +constexpr const TVariable kgl_SampleIDES3_2(BuiltInId::gl_SampleIDES3_2, + BuiltInName::gl_SampleID, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_SamplePosition( + BuiltInId::gl_SamplePosition, + BuiltInName::gl_SamplePosition, + SymbolType::BuiltIn, + std::array{{TExtension::OES_sample_variables}}, + StaticType::Get()); +constexpr const TVariable kgl_SamplePositionES3_2( + BuiltInId::gl_SamplePositionES3_2, + BuiltInName::gl_SamplePosition, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_SecondaryFragColorEXT( + BuiltInId::gl_SecondaryFragColorEXT, + BuiltInName::gl_SecondaryFragColorEXT, + SymbolType::BuiltIn, + std::array{{TExtension::EXT_blend_func_extended}}, + StaticType::Get()); +constexpr const TVariable kgl_TessCoord(BuiltInId::gl_TessCoord, + BuiltInName::gl_TessCoord, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_VertexID(BuiltInId::gl_VertexID, + BuiltInName::gl_VertexID, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_VertexIndex(BuiltInId::gl_VertexIndex, + BuiltInName::gl_VertexIndex, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_ViewID_OVR(BuiltInId::gl_ViewID_OVR, + BuiltInName::gl_ViewID_OVR, + SymbolType::BuiltIn, + std::array{{TExtension::OVR_multiview}}, + StaticType::Get()); +constexpr const TVariable kgl_ViewportIndex( + BuiltInId::gl_ViewportIndex, + BuiltInName::gl_ViewportIndex, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_WorkGroupID( + BuiltInId::gl_WorkGroupID, + BuiltInName::gl_WorkGroupID, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kgl_WorkGroupSize( + BuiltInId::gl_WorkGroupSize, + BuiltInName::gl_WorkGroupSize, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00B(BuiltInId::pt00B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00D(BuiltInId::pt00D, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00E(BuiltInId::pt00E, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00F(BuiltInId::pt00F, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00G( + BuiltInId::pt00G, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00H( + BuiltInId::pt00H, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00I(BuiltInId::pt00I, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00J(BuiltInId::pt00J, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00K(BuiltInId::pt00K, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00L( + BuiltInId::pt00L, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00M( + BuiltInId::pt00M, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00N( + BuiltInId::pt00N, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00O( + BuiltInId::pt00O, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00P(BuiltInId::pt00P, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00Q( + BuiltInId::pt00Q, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00R(BuiltInId::pt00R, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00S(BuiltInId::pt00S, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00T(BuiltInId::pt00T, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00U( + BuiltInId::pt00U, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00V(BuiltInId::pt00V, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00W( + BuiltInId::pt00W, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00X(BuiltInId::pt00X, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00Y(BuiltInId::pt00Y, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00Z(BuiltInId::pt00Z, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00a( + BuiltInId::pt00a, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00b(BuiltInId::pt00b, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00c( + BuiltInId::pt00c, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00d( + BuiltInId::pt00d, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00e( + BuiltInId::pt00e, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00f( + BuiltInId::pt00f, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00j( + BuiltInId::pt00j, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00k( + BuiltInId::pt00k, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00l( + BuiltInId::pt00l, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00r( + BuiltInId::pt00r, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00s( + BuiltInId::pt00s, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00w( + BuiltInId::pt00w, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00x( + BuiltInId::pt00x, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00y( + BuiltInId::pt00y, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt00z(BuiltInId::pt00z, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01A(BuiltInId::pt01A, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01B(BuiltInId::pt01B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01C(BuiltInId::pt01C, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01D(BuiltInId::pt01D, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01E(BuiltInId::pt01E, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01F(BuiltInId::pt01F, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01G( + BuiltInId::pt01G, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01H( + BuiltInId::pt01H, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01I(BuiltInId::pt01I, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01J(BuiltInId::pt01J, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01K(BuiltInId::pt01K, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01L(BuiltInId::pt01L, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01M( + BuiltInId::pt01M, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01N(BuiltInId::pt01N, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01O(BuiltInId::pt01O, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01P( + BuiltInId::pt01P, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01Q(BuiltInId::pt01Q, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01R( + BuiltInId::pt01R, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01S( + BuiltInId::pt01S, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01T(BuiltInId::pt01T, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01U(BuiltInId::pt01U, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01V(BuiltInId::pt01V, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01W(BuiltInId::pt01W, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01X( + BuiltInId::pt01X, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01Y(BuiltInId::pt01Y, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01Z(BuiltInId::pt01Z, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01a( + BuiltInId::pt01a, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01b(BuiltInId::pt01b, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01c( + BuiltInId::pt01c, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01d( + BuiltInId::pt01d, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01e(BuiltInId::pt01e, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01f(BuiltInId::pt01f, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01g( + BuiltInId::pt01g, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01h( + BuiltInId::pt01h, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01i( + BuiltInId::pt01i, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01j(BuiltInId::pt01j, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01k( + BuiltInId::pt01k, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01l( + BuiltInId::pt01l, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01m( + BuiltInId::pt01m, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01n( + BuiltInId::pt01n, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt01o( + BuiltInId::pt01o, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt10B(BuiltInId::pt10B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt10D(BuiltInId::pt10D, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt10Dx4( + BuiltInId::pt10Dx4, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::GetArray()); +constexpr const TVariable kpt10E(BuiltInId::pt10E, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt10F(BuiltInId::pt10F, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt20B(BuiltInId::pt20B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt20D(BuiltInId::pt20D, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt20E(BuiltInId::pt20E, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt20F(BuiltInId::pt20F, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt30B(BuiltInId::pt30B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt30D(BuiltInId::pt30D, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt30E(BuiltInId::pt30E, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt30F(BuiltInId::pt30F, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt50B(BuiltInId::pt50B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt60B(BuiltInId::pt60B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt70B(BuiltInId::pt70B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt90B(BuiltInId::pt90B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kptA0B(BuiltInId::ptA0B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kptB0B(BuiltInId::ptB0B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kptD0B(BuiltInId::ptD0B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kptE0B(BuiltInId::ptE0B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kptF0B(BuiltInId::ptF0B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt_io_00D(BuiltInId::pt_io_00D, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt_io_00E(BuiltInId::pt_io_00E, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt_o_00B(BuiltInId::pt_o_00B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt_o_00D(BuiltInId::pt_o_00D, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt_o_00E(BuiltInId::pt_o_00E, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt_o_10B(BuiltInId::pt_o_10B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt_o_10D(BuiltInId::pt_o_10D, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt_o_10E(BuiltInId::pt_o_10E, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt_o_20B(BuiltInId::pt_o_20B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt_o_20D(BuiltInId::pt_o_20D, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt_o_20E(BuiltInId::pt_o_20E, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt_o_30B(BuiltInId::pt_o_30B, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt_o_30D(BuiltInId::pt_o_30D, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); +constexpr const TVariable kpt_o_30E(BuiltInId::pt_o_30E, + BuiltInName::_empty, + SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + +const TVariable *angle_BaseInstance() +{ + return &kangle_BaseInstance; +} + +const TVariable *angle_BaseVertex() +{ + return &kangle_BaseVertex; +} + +const TVariable *gl_BaseInstance() +{ + return &kgl_BaseInstance; +} + +const TVariable *gl_BaseVertex() +{ + return &kgl_BaseVertex; +} + +const TVariable *gl_DrawID() +{ + return &kgl_DrawID; +} + +const TVariable *gl_FragColor() +{ + return &kgl_FragColor; +} + +const TVariable *gl_FragCoord() +{ + return &kgl_FragCoord; +} + +const TVariable *gl_FragCoord300() +{ + return &kgl_FragCoord300; +} + +const TVariable *gl_FragDepth() +{ + return &kgl_FragDepth; +} + +const TVariable *gl_FrontFacing() +{ + return &kgl_FrontFacing; +} + +const TVariable *gl_GlobalInvocationID() +{ + return &kgl_GlobalInvocationID; +} + +const TVariable *gl_HelperInvocation() +{ + return &kgl_HelperInvocation; +} + +const TVariable *gl_InstanceID() +{ + return &kgl_InstanceID; +} + +const TVariable *gl_InstanceIndex() +{ + return &kgl_InstanceIndex; +} + +const TVariable *gl_InvocationID() +{ + return &kgl_InvocationID; +} + +const TVariable *gl_InvocationIDES3_2() +{ + return &kgl_InvocationIDES3_2; +} + +const TVariable *gl_InvocationIDTCS() +{ + return &kgl_InvocationIDTCS; +} + +const TVariable *gl_InvocationIDTCSES3_2() +{ + return &kgl_InvocationIDTCSES3_2; +} + +const TVariable *gl_LastFragColor() +{ + return &kgl_LastFragColor; +} + +const TVariable *gl_LastFragColorARM() +{ + return &kgl_LastFragColorARM; +} + +const TVariable *gl_Layer() +{ + return &kgl_Layer; +} + +const TVariable *gl_LayerES3_2() +{ + return &kgl_LayerES3_2; +} + +const TVariable *gl_LayerGS() +{ + return &kgl_LayerGS; +} + +const TVariable *gl_LayerGSES3_2() +{ + return &kgl_LayerGSES3_2; +} + +const TVariable *gl_LayerVS() +{ + return &kgl_LayerVS; +} + +const TVariable *gl_LocalInvocationID() +{ + return &kgl_LocalInvocationID; +} + +const TVariable *gl_LocalInvocationIndex() +{ + return &kgl_LocalInvocationIndex; +} + +const TVariable *gl_NumSamples() +{ + return &kgl_NumSamples; +} + +const TVariable *gl_NumSamplesES3_2() +{ + return &kgl_NumSamplesES3_2; +} + +const TVariable *gl_NumWorkGroups() +{ + return &kgl_NumWorkGroups; +} + +const TVariable *gl_PatchVerticesInTCS() +{ + return &kgl_PatchVerticesInTCS; +} + +const TVariable *gl_PatchVerticesInTCSES3_2() +{ + return &kgl_PatchVerticesInTCSES3_2; +} + +const TVariable *gl_PatchVerticesInTES() +{ + return &kgl_PatchVerticesInTES; +} + +const TVariable *gl_PatchVerticesInTESES3_2() +{ + return &kgl_PatchVerticesInTESES3_2; +} + +const TVariable *gl_PointCoord() +{ + return &kgl_PointCoord; +} + +const TVariable *gl_PointSize() +{ + return &kgl_PointSize; +} + +const TVariable *gl_PointSize300() +{ + return &kgl_PointSize300; +} + +const TVariable *gl_Position() +{ + return &kgl_Position; +} + +const TVariable *gl_PrimitiveID() +{ + return &kgl_PrimitiveID; +} + +const TVariable *gl_PrimitiveIDES3_2() +{ + return &kgl_PrimitiveIDES3_2; +} + +const TVariable *gl_PrimitiveIDGS() +{ + return &kgl_PrimitiveIDGS; +} + +const TVariable *gl_PrimitiveIDGSES3_2() +{ + return &kgl_PrimitiveIDGSES3_2; +} + +const TVariable *gl_PrimitiveIDIn() +{ + return &kgl_PrimitiveIDIn; +} + +const TVariable *gl_PrimitiveIDInES3_2() +{ + return &kgl_PrimitiveIDInES3_2; +} + +const TVariable *gl_PrimitiveIDTCS() +{ + return &kgl_PrimitiveIDTCS; +} + +const TVariable *gl_PrimitiveIDTCSES3_2() +{ + return &kgl_PrimitiveIDTCSES3_2; +} + +const TVariable *gl_PrimitiveIDTES() +{ + return &kgl_PrimitiveIDTES; +} + +const TVariable *gl_PrimitiveIDTESES3_2() +{ + return &kgl_PrimitiveIDTESES3_2; +} + +const TVariable *gl_SampleID() +{ + return &kgl_SampleID; +} + +const TVariable *gl_SampleIDES3_2() +{ + return &kgl_SampleIDES3_2; +} + +const TVariable *gl_SamplePosition() +{ + return &kgl_SamplePosition; +} + +const TVariable *gl_SamplePositionES3_2() +{ + return &kgl_SamplePositionES3_2; +} + +const TVariable *gl_SecondaryFragColorEXT() +{ + return &kgl_SecondaryFragColorEXT; +} + +const TVariable *gl_TessCoord() +{ + return &kgl_TessCoord; +} + +const TVariable *gl_VertexID() +{ + return &kgl_VertexID; +} + +const TVariable *gl_VertexIndex() +{ + return &kgl_VertexIndex; +} + +const TVariable *gl_ViewID_OVR() +{ + return &kgl_ViewID_OVR; +} + +const TVariable *gl_ViewportIndex() +{ + return &kgl_ViewportIndex; +} + +const TVariable *gl_WorkGroupID() +{ + return &kgl_WorkGroupID; +} + +const TVariable *gl_WorkGroupSize() +{ + return &kgl_WorkGroupSize; +} + +} // namespace BuiltInVariable + +namespace BuiltInParameters +{ + +constexpr const TVariable **empty = nullptr; +constexpr const TVariable *p00B00B00B[3] = {&BuiltInVariable::kpt00B, &BuiltInVariable::kpt00B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00B00B00F[3] = {&BuiltInVariable::kpt00B, &BuiltInVariable::kpt00B, + &BuiltInVariable::kpt00F}; +constexpr const TVariable *p00B00B10B[3] = {&BuiltInVariable::kpt00B, &BuiltInVariable::kpt00B, + &BuiltInVariable::kpt10B}; +constexpr const TVariable *p00B00B20B[3] = {&BuiltInVariable::kpt00B, &BuiltInVariable::kpt00B, + &BuiltInVariable::kpt20B}; +constexpr const TVariable *p00B00B30B[3] = {&BuiltInVariable::kpt00B, &BuiltInVariable::kpt00B, + &BuiltInVariable::kpt30B}; +constexpr const TVariable *p00B00D[2] = {&BuiltInVariable::kpt00B, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00B10B[2] = {&BuiltInVariable::kpt00B, &BuiltInVariable::kpt10B}; +constexpr const TVariable *p00B20B[2] = {&BuiltInVariable::kpt00B, &BuiltInVariable::kpt20B}; +constexpr const TVariable *p00B30B[2] = {&BuiltInVariable::kpt00B, &BuiltInVariable::kpt30B}; +constexpr const TVariable *p00B_o_00B[2] = {&BuiltInVariable::kpt00B, &BuiltInVariable::kpt_o_00B}; +constexpr const TVariable *p00B_o_00D[2] = {&BuiltInVariable::kpt00B, &BuiltInVariable::kpt_o_00D}; +constexpr const TVariable *p00D00D00D00D[4] = {&BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00D00D00F[3] = {&BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00F}; +constexpr const TVariable *p00D00D_o_00D_o_00D[4] = { + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D, &BuiltInVariable::kpt_o_00D, + &BuiltInVariable::kpt_o_00D}; +constexpr const TVariable *p00E00D00D[3] = {&BuiltInVariable::kpt00E, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00E00E00D00D[4] = {&BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00E00E00E[3] = {&BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E, + &BuiltInVariable::kpt00E}; +constexpr const TVariable *p00E00E00F[3] = {&BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E, + &BuiltInVariable::kpt00F}; +constexpr const TVariable *p00E00E_o_00E_o_00E[4] = { + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E, &BuiltInVariable::kpt_o_00E, + &BuiltInVariable::kpt_o_00E}; +constexpr const TVariable *p00F00F00F[3] = {&BuiltInVariable::kpt00F, &BuiltInVariable::kpt00F, + &BuiltInVariable::kpt00F}; +constexpr const TVariable *p00G[1] = {&BuiltInVariable::kpt00G}; +constexpr const TVariable *p00I00D[2] = {&BuiltInVariable::kpt00I, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00I10B00B10D[4] = {&BuiltInVariable::kpt00I, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00I10B00D[3] = {&BuiltInVariable::kpt00I, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00I10B10B10B10D[5] = { + &BuiltInVariable::kpt00I, &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00I10B10D00B[4] = {&BuiltInVariable::kpt00I, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00I10B10D00D[4] = {&BuiltInVariable::kpt00I, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00I10B10Dx400D[4] = {&BuiltInVariable::kpt00I, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10Dx4, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00I10D00D10D[4] = {&BuiltInVariable::kpt00I, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00I20B00B10D[4] = {&BuiltInVariable::kpt00I, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00I20B10B10B10D[5] = { + &BuiltInVariable::kpt00I, &BuiltInVariable::kpt20B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00I20B10D00B[4] = {&BuiltInVariable::kpt00I, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00I30B00B10D[4] = {&BuiltInVariable::kpt00I, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00I30B10B10B10D[5] = { + &BuiltInVariable::kpt00I, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00I30B10D00B[4] = {&BuiltInVariable::kpt00I, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00J00D[2] = {&BuiltInVariable::kpt00J, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00J20B00B20D[4] = {&BuiltInVariable::kpt00J, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00J20B20B20B20D[5] = { + &BuiltInVariable::kpt00J, &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00J20B20D00B[4] = {&BuiltInVariable::kpt00J, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt20D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00J20D00D20D[4] = {&BuiltInVariable::kpt00J, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00J30B00B20D[4] = {&BuiltInVariable::kpt00J, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00J30B20B20B20D[5] = { + &BuiltInVariable::kpt00J, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00J30B20D00B[4] = {&BuiltInVariable::kpt00J, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt20D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00K00D[2] = {&BuiltInVariable::kpt00K, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00K20B00B[3] = {&BuiltInVariable::kpt00K, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00K20B00D[3] = {&BuiltInVariable::kpt00K, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00K20B20B20B[4] = {&BuiltInVariable::kpt00K, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B}; +constexpr const TVariable *p00L00D[2] = {&BuiltInVariable::kpt00L, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00L20B00B10D[4] = {&BuiltInVariable::kpt00L, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00L20B00D[3] = {&BuiltInVariable::kpt00L, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00L20B10B10B10D[5] = { + &BuiltInVariable::kpt00L, &BuiltInVariable::kpt20B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00L20B10D00B[4] = {&BuiltInVariable::kpt00L, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00L20B10D00D[4] = {&BuiltInVariable::kpt00L, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00L20B10Dx400D[4] = {&BuiltInVariable::kpt00L, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt10Dx4, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00L20D00D10D[4] = {&BuiltInVariable::kpt00L, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00M00D[2] = {&BuiltInVariable::kpt00M, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00M10B00B[3] = {&BuiltInVariable::kpt00M, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00M10D00D[3] = {&BuiltInVariable::kpt00M, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00M20B00B[3] = {&BuiltInVariable::kpt00M, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00M30B00B[3] = {&BuiltInVariable::kpt00M, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00N00D[2] = {&BuiltInVariable::kpt00N, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00N10B00B[3] = {&BuiltInVariable::kpt00N, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00N10D00D[3] = {&BuiltInVariable::kpt00N, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00N20B00B[3] = {&BuiltInVariable::kpt00N, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00N30B00B[3] = {&BuiltInVariable::kpt00N, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00O10B[2] = {&BuiltInVariable::kpt00O, &BuiltInVariable::kpt10B}; +constexpr const TVariable *p00O20B[2] = {&BuiltInVariable::kpt00O, &BuiltInVariable::kpt20B}; +constexpr const TVariable *p00O30B[2] = {&BuiltInVariable::kpt00O, &BuiltInVariable::kpt30B}; +constexpr const TVariable *p00P10D00D[3] = {&BuiltInVariable::kpt00P, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00Q20D00D[3] = {&BuiltInVariable::kpt00Q, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00R00D[2] = {&BuiltInVariable::kpt00R, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00R10B00B10D[4] = {&BuiltInVariable::kpt00R, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00R10B00D[3] = {&BuiltInVariable::kpt00R, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00R10B10B10B10D[5] = { + &BuiltInVariable::kpt00R, &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00R10B10D00B[4] = {&BuiltInVariable::kpt00R, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00R10B10D00D[4] = {&BuiltInVariable::kpt00R, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00R10B10Dx400D[4] = {&BuiltInVariable::kpt00R, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10Dx4, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00R10D00D10D[4] = {&BuiltInVariable::kpt00R, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00R20B00B10D[4] = {&BuiltInVariable::kpt00R, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00R20B10B10B10D[5] = { + &BuiltInVariable::kpt00R, &BuiltInVariable::kpt20B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00R20B10D00B[4] = {&BuiltInVariable::kpt00R, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00R30B00B10D[4] = {&BuiltInVariable::kpt00R, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00R30B10B10B10D[5] = { + &BuiltInVariable::kpt00R, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00R30B10D00B[4] = {&BuiltInVariable::kpt00R, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00S00D[2] = {&BuiltInVariable::kpt00S, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00S20B00B20D[4] = {&BuiltInVariable::kpt00S, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00S20B20B20B20D[5] = { + &BuiltInVariable::kpt00S, &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00S20B20D00B[4] = {&BuiltInVariable::kpt00S, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt20D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00S20D00D20D[4] = {&BuiltInVariable::kpt00S, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00S30B00B20D[4] = {&BuiltInVariable::kpt00S, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00S30B20B20B20D[5] = { + &BuiltInVariable::kpt00S, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00S30B20D00B[4] = {&BuiltInVariable::kpt00S, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt20D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00T00D[2] = {&BuiltInVariable::kpt00T, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00T20B00B[3] = {&BuiltInVariable::kpt00T, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00T20B00D[3] = {&BuiltInVariable::kpt00T, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00T20B20B20B[4] = {&BuiltInVariable::kpt00T, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B}; +constexpr const TVariable *p00U00D[2] = {&BuiltInVariable::kpt00U, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00U20B00B10D[4] = {&BuiltInVariable::kpt00U, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00U20B00D[3] = {&BuiltInVariable::kpt00U, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00U20B10B10B10D[5] = { + &BuiltInVariable::kpt00U, &BuiltInVariable::kpt20B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00U20B10D00B[4] = {&BuiltInVariable::kpt00U, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00U20B10D00D[4] = {&BuiltInVariable::kpt00U, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00U20B10Dx400D[4] = {&BuiltInVariable::kpt00U, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt10Dx4, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00U20D00D10D[4] = {&BuiltInVariable::kpt00U, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00V10D00D[3] = {&BuiltInVariable::kpt00V, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00W20D00D[3] = {&BuiltInVariable::kpt00W, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00X00D[2] = {&BuiltInVariable::kpt00X, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00X10B00B10D[4] = {&BuiltInVariable::kpt00X, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00X10B00D[3] = {&BuiltInVariable::kpt00X, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00X10B10B10B10D[5] = { + &BuiltInVariable::kpt00X, &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00X10B10D00B[4] = {&BuiltInVariable::kpt00X, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00X10B10D00D[4] = {&BuiltInVariable::kpt00X, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00X10B10Dx400D[4] = {&BuiltInVariable::kpt00X, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10Dx4, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00X10D00D10D[4] = {&BuiltInVariable::kpt00X, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00X20B00B10D[4] = {&BuiltInVariable::kpt00X, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00X20B10B10B10D[5] = { + &BuiltInVariable::kpt00X, &BuiltInVariable::kpt20B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00X20B10D00B[4] = {&BuiltInVariable::kpt00X, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00X30B00B10D[4] = {&BuiltInVariable::kpt00X, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00X30B10B10B10D[5] = { + &BuiltInVariable::kpt00X, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00X30B10D00B[4] = {&BuiltInVariable::kpt00X, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00Y00D[2] = {&BuiltInVariable::kpt00Y, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00Y20B00B20D[4] = {&BuiltInVariable::kpt00Y, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00Y20B20B20B20D[5] = { + &BuiltInVariable::kpt00Y, &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00Y20B20D00B[4] = {&BuiltInVariable::kpt00Y, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt20D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00Y20D00D20D[4] = {&BuiltInVariable::kpt00Y, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00Y30B00B20D[4] = {&BuiltInVariable::kpt00Y, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00Y30B20B20B20D[5] = { + &BuiltInVariable::kpt00Y, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p00Y30B20D00B[4] = {&BuiltInVariable::kpt00Y, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt20D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00Z00D[2] = {&BuiltInVariable::kpt00Z, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00Z20B00B[3] = {&BuiltInVariable::kpt00Z, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00Z20B00D[3] = {&BuiltInVariable::kpt00Z, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00Z20B20B20B[4] = {&BuiltInVariable::kpt00Z, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B}; +constexpr const TVariable *p00a00D[2] = {&BuiltInVariable::kpt00a, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00a20B00B10D[4] = {&BuiltInVariable::kpt00a, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00a20B00D[3] = {&BuiltInVariable::kpt00a, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00a20B10B10B10D[5] = { + &BuiltInVariable::kpt00a, &BuiltInVariable::kpt20B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00a20B10D00B[4] = {&BuiltInVariable::kpt00a, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00a20B10D00D[4] = {&BuiltInVariable::kpt00a, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00a20B10Dx400D[4] = {&BuiltInVariable::kpt00a, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt10Dx4, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00a20D00D10D[4] = {&BuiltInVariable::kpt00a, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00b10D00D[3] = {&BuiltInVariable::kpt00b, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00c20D00D[3] = {&BuiltInVariable::kpt00c, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00d00D[2] = {&BuiltInVariable::kpt00d, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00d10B00B10Dx4[4] = {&BuiltInVariable::kpt00d, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt00B, + &BuiltInVariable::kpt10Dx4}; +constexpr const TVariable *p00d20B00B10D[4] = {&BuiltInVariable::kpt00d, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00d20B10B10B10D[5] = { + &BuiltInVariable::kpt00d, &BuiltInVariable::kpt20B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00d20B10D00B[4] = {&BuiltInVariable::kpt00d, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00d30B00B10D[4] = {&BuiltInVariable::kpt00d, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00d30B10B10B10D[5] = { + &BuiltInVariable::kpt00d, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00d30B10D00B[4] = {&BuiltInVariable::kpt00d, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00e00D[2] = {&BuiltInVariable::kpt00e, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00e20B00B[3] = {&BuiltInVariable::kpt00e, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00e30B00B[3] = {&BuiltInVariable::kpt00e, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00e30B20B20B[4] = {&BuiltInVariable::kpt00e, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B}; +constexpr const TVariable *p00f00D[2] = {&BuiltInVariable::kpt00f, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00f20B00B10Dx4[4] = {&BuiltInVariable::kpt00f, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B, + &BuiltInVariable::kpt10Dx4}; +constexpr const TVariable *p00f30B10B10B10D[5] = { + &BuiltInVariable::kpt00f, &BuiltInVariable::kpt30B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p00j00D[2] = {&BuiltInVariable::kpt00j, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00k00D[2] = {&BuiltInVariable::kpt00k, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00k30B00B[3] = {&BuiltInVariable::kpt00k, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00k30B00D[3] = {&BuiltInVariable::kpt00k, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00k30B20B20B[4] = {&BuiltInVariable::kpt00k, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B}; +constexpr const TVariable *p00l00D[2] = {&BuiltInVariable::kpt00l, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00l30B00B[3] = {&BuiltInVariable::kpt00l, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00r00D[2] = {&BuiltInVariable::kpt00r, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00s00D[2] = {&BuiltInVariable::kpt00s, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00s30B00B[3] = {&BuiltInVariable::kpt00s, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00s30B00D[3] = {&BuiltInVariable::kpt00s, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00s30B20B20B[4] = {&BuiltInVariable::kpt00s, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B}; +constexpr const TVariable *p00w00D[2] = {&BuiltInVariable::kpt00w, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00x00D[2] = {&BuiltInVariable::kpt00x, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00x30B00B[3] = {&BuiltInVariable::kpt00x, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00x30B00D[3] = {&BuiltInVariable::kpt00x, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00x30B20B20B[4] = {&BuiltInVariable::kpt00x, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B}; +constexpr const TVariable *p00y10B[2] = {&BuiltInVariable::kpt00y, &BuiltInVariable::kpt10B}; +constexpr const TVariable *p00z10D00B[3] = {&BuiltInVariable::kpt00z, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p00z10D00D00D[4] = {&BuiltInVariable::kpt00z, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p00z10D00E00E[4] = {&BuiltInVariable::kpt00z, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p00z10D30B[3] = {&BuiltInVariable::kpt00z, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt30B}; +constexpr const TVariable *p01A20D00B[3] = {&BuiltInVariable::kpt01A, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01A20D00D00D[4] = {&BuiltInVariable::kpt01A, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01A20D00E00E[4] = {&BuiltInVariable::kpt01A, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01A20D30B[3] = {&BuiltInVariable::kpt01A, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt30B}; +constexpr const TVariable *p01B20D00B[3] = {&BuiltInVariable::kpt01B, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01B20D00D00D[4] = {&BuiltInVariable::kpt01B, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01B20D00E00E[4] = {&BuiltInVariable::kpt01B, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01B20D30B[3] = {&BuiltInVariable::kpt01B, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt30B}; +constexpr const TVariable *p01C20D00B[3] = {&BuiltInVariable::kpt01C, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01C20D00D00D[4] = {&BuiltInVariable::kpt01C, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01C20D00E00E[4] = {&BuiltInVariable::kpt01C, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01C20D30B[3] = {&BuiltInVariable::kpt01C, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt30B}; +constexpr const TVariable *p01D00D00B[3] = {&BuiltInVariable::kpt01D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01D00D00D00D[4] = {&BuiltInVariable::kpt01D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01D00D00E00E[4] = {&BuiltInVariable::kpt01D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01E10D00B[3] = {&BuiltInVariable::kpt01E, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01E10D00D00D[4] = {&BuiltInVariable::kpt01E, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01E10D00E00E[4] = {&BuiltInVariable::kpt01E, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01F10D00D00B[4] = {&BuiltInVariable::kpt01F, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01F10D00D00D00D[5] = { + &BuiltInVariable::kpt01F, &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01F10D00D00E00E[5] = { + &BuiltInVariable::kpt01F, &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01G20D00D00B[4] = {&BuiltInVariable::kpt01G, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01G20D00D00D00D[5] = { + &BuiltInVariable::kpt01G, &BuiltInVariable::kpt20D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01G20D00D00E00E[5] = { + &BuiltInVariable::kpt01G, &BuiltInVariable::kpt20D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01H20D00B[3] = {&BuiltInVariable::kpt01H, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01H20D00D00D[4] = {&BuiltInVariable::kpt01H, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01H20D00E00E[4] = {&BuiltInVariable::kpt01H, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01H20D30B[3] = {&BuiltInVariable::kpt01H, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt30B}; +constexpr const TVariable *p01I10D00B[3] = {&BuiltInVariable::kpt01I, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01I10D00D00D[4] = {&BuiltInVariable::kpt01I, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01I10D00E00E[4] = {&BuiltInVariable::kpt01I, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01J00D00B[3] = {&BuiltInVariable::kpt01J, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01J00D00D00D[4] = {&BuiltInVariable::kpt01J, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01J00D00E00E[4] = {&BuiltInVariable::kpt01J, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01J00D30B[3] = {&BuiltInVariable::kpt01J, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt30B}; +constexpr const TVariable *p01K10D00B[3] = {&BuiltInVariable::kpt01K, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01K10D00D00D[4] = {&BuiltInVariable::kpt01K, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01K10D00E00E[4] = {&BuiltInVariable::kpt01K, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01K10D30D[3] = {&BuiltInVariable::kpt01K, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt30D}; +constexpr const TVariable *p01L20D00B[3] = {&BuiltInVariable::kpt01L, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01L20D00D00D[4] = {&BuiltInVariable::kpt01L, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01L20D00E00E[4] = {&BuiltInVariable::kpt01L, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01L20D30D[3] = {&BuiltInVariable::kpt01L, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt30D}; +constexpr const TVariable *p01M20D00B[3] = {&BuiltInVariable::kpt01M, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01M20D00D00D[4] = {&BuiltInVariable::kpt01M, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01M20D00E00E[4] = {&BuiltInVariable::kpt01M, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01M20D30D[3] = {&BuiltInVariable::kpt01M, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt30D}; +constexpr const TVariable *p01N20D00B[3] = {&BuiltInVariable::kpt01N, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01N20D00D00D[4] = {&BuiltInVariable::kpt01N, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01N20D00E00E[4] = {&BuiltInVariable::kpt01N, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01N20D30D[3] = {&BuiltInVariable::kpt01N, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt30D}; +constexpr const TVariable *p01O00D00B[3] = {&BuiltInVariable::kpt01O, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01O00D00D00D[4] = {&BuiltInVariable::kpt01O, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01O00D00E00E[4] = {&BuiltInVariable::kpt01O, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01P10D00B[3] = {&BuiltInVariable::kpt01P, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01P10D00D00D[4] = {&BuiltInVariable::kpt01P, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01P10D00E00E[4] = {&BuiltInVariable::kpt01P, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01Q10D00D00B[4] = {&BuiltInVariable::kpt01Q, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01Q10D00D00D00D[5] = { + &BuiltInVariable::kpt01Q, &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01Q10D00D00E00E[5] = { + &BuiltInVariable::kpt01Q, &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01R20D00D00B[4] = {&BuiltInVariable::kpt01R, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01R20D00D00D00D[5] = { + &BuiltInVariable::kpt01R, &BuiltInVariable::kpt20D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01R20D00D00E00E[5] = { + &BuiltInVariable::kpt01R, &BuiltInVariable::kpt20D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01S20D00B[3] = {&BuiltInVariable::kpt01S, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01S20D00D00D[4] = {&BuiltInVariable::kpt01S, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01S20D00E00E[4] = {&BuiltInVariable::kpt01S, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01S20D30D[3] = {&BuiltInVariable::kpt01S, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt30D}; +constexpr const TVariable *p01T10D00B[3] = {&BuiltInVariable::kpt01T, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01T10D00D00D[4] = {&BuiltInVariable::kpt01T, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01T10D00E00E[4] = {&BuiltInVariable::kpt01T, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01U00D00B[3] = {&BuiltInVariable::kpt01U, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01U00D00D00D[4] = {&BuiltInVariable::kpt01U, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01U00D00E00E[4] = {&BuiltInVariable::kpt01U, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01U00D30D[3] = {&BuiltInVariable::kpt01U, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt30D}; +constexpr const TVariable *p01V10D00B[3] = {&BuiltInVariable::kpt01V, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01V10D00D00D[4] = {&BuiltInVariable::kpt01V, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01V10D00E00E[4] = {&BuiltInVariable::kpt01V, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01V10D30E[3] = {&BuiltInVariable::kpt01V, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt30E}; +constexpr const TVariable *p01W20D00B[3] = {&BuiltInVariable::kpt01W, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01W20D00D00D[4] = {&BuiltInVariable::kpt01W, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01W20D00E00E[4] = {&BuiltInVariable::kpt01W, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01W20D30E[3] = {&BuiltInVariable::kpt01W, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt30E}; +constexpr const TVariable *p01X20D00B[3] = {&BuiltInVariable::kpt01X, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01X20D00D00D[4] = {&BuiltInVariable::kpt01X, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01X20D00E00E[4] = {&BuiltInVariable::kpt01X, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01X20D30E[3] = {&BuiltInVariable::kpt01X, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt30E}; +constexpr const TVariable *p01Y20D00B[3] = {&BuiltInVariable::kpt01Y, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01Y20D00D00D[4] = {&BuiltInVariable::kpt01Y, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01Y20D00E00E[4] = {&BuiltInVariable::kpt01Y, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01Y20D30E[3] = {&BuiltInVariable::kpt01Y, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt30E}; +constexpr const TVariable *p01Z00D00B[3] = {&BuiltInVariable::kpt01Z, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01Z00D00D00D[4] = {&BuiltInVariable::kpt01Z, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01Z00D00E00E[4] = {&BuiltInVariable::kpt01Z, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01a10D00B[3] = {&BuiltInVariable::kpt01a, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01a10D00D00D[4] = {&BuiltInVariable::kpt01a, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01a10D00E00E[4] = {&BuiltInVariable::kpt01a, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01b10D00D00B[4] = {&BuiltInVariable::kpt01b, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01b10D00D00D00D[5] = { + &BuiltInVariable::kpt01b, &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01b10D00D00E00E[5] = { + &BuiltInVariable::kpt01b, &BuiltInVariable::kpt10D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01c20D00D00B[4] = {&BuiltInVariable::kpt01c, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01c20D00D00D00D[5] = { + &BuiltInVariable::kpt01c, &BuiltInVariable::kpt20D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01c20D00D00E00E[5] = { + &BuiltInVariable::kpt01c, &BuiltInVariable::kpt20D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01d20D00B[3] = {&BuiltInVariable::kpt01d, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01d20D00D00D[4] = {&BuiltInVariable::kpt01d, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01d20D00E00E[4] = {&BuiltInVariable::kpt01d, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01d20D30E[3] = {&BuiltInVariable::kpt01d, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt30E}; +constexpr const TVariable *p01e10D00B[3] = {&BuiltInVariable::kpt01e, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01e10D00D00D[4] = {&BuiltInVariable::kpt01e, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01e10D00E00E[4] = {&BuiltInVariable::kpt01e, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01f00D00B[3] = {&BuiltInVariable::kpt01f, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p01f00D00D00D[4] = {&BuiltInVariable::kpt01f, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01f00D00E00E[4] = {&BuiltInVariable::kpt01f, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; +constexpr const TVariable *p01f00D30E[3] = {&BuiltInVariable::kpt01f, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt30E}; +constexpr const TVariable *p01g30B[2] = {&BuiltInVariable::kpt01g, &BuiltInVariable::kpt30B}; +constexpr const TVariable *p01h30D[2] = {&BuiltInVariable::kpt01h, &BuiltInVariable::kpt30D}; +constexpr const TVariable *p01i30E[2] = {&BuiltInVariable::kpt01i, &BuiltInVariable::kpt30E}; +constexpr const TVariable *p01j[1] = {&BuiltInVariable::kpt01j}; +constexpr const TVariable *p01k[1] = {&BuiltInVariable::kpt01k}; +constexpr const TVariable *p01l[1] = {&BuiltInVariable::kpt01l}; +constexpr const TVariable *p01m00D[2] = {&BuiltInVariable::kpt01m, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01n00D[2] = {&BuiltInVariable::kpt01n, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p01o00D[2] = {&BuiltInVariable::kpt01o, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p10B00B00B[3] = {&BuiltInVariable::kpt10B, &BuiltInVariable::kpt00B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p10B00D[2] = {&BuiltInVariable::kpt10B, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p10B10B00B[3] = {&BuiltInVariable::kpt10B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p10B10B10B[3] = {&BuiltInVariable::kpt10B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10B}; +constexpr const TVariable *p10B10B10F[3] = {&BuiltInVariable::kpt10B, &BuiltInVariable::kpt10B, + &BuiltInVariable::kpt10F}; +constexpr const TVariable *p10B10D[2] = {&BuiltInVariable::kpt10B, &BuiltInVariable::kpt10D}; +constexpr const TVariable *p10B20B[2] = {&BuiltInVariable::kpt10B, &BuiltInVariable::kpt20B}; +constexpr const TVariable *p10B30B[2] = {&BuiltInVariable::kpt10B, &BuiltInVariable::kpt30B}; +constexpr const TVariable *p10B_o_10B[2] = {&BuiltInVariable::kpt10B, &BuiltInVariable::kpt_o_10B}; +constexpr const TVariable *p10B_o_10D[2] = {&BuiltInVariable::kpt10B, &BuiltInVariable::kpt_o_10D}; +constexpr const TVariable *p10D00D00D[3] = {&BuiltInVariable::kpt10D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p10D10D00D00D[4] = {&BuiltInVariable::kpt10D, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p10D10D10D[3] = {&BuiltInVariable::kpt10D, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt10D}; +constexpr const TVariable *p10D10D10F[3] = {&BuiltInVariable::kpt10D, &BuiltInVariable::kpt10D, + &BuiltInVariable::kpt10F}; +constexpr const TVariable *p10D10D_o_10D_o_10D[4] = { + &BuiltInVariable::kpt10D, &BuiltInVariable::kpt10D, &BuiltInVariable::kpt_o_10D, + &BuiltInVariable::kpt_o_10D}; +constexpr const TVariable *p10E00D00D[3] = {&BuiltInVariable::kpt10E, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p10E00E00E[3] = {&BuiltInVariable::kpt10E, &BuiltInVariable::kpt00E, + &BuiltInVariable::kpt00E}; +constexpr const TVariable *p10E10E00D00D[4] = {&BuiltInVariable::kpt10E, &BuiltInVariable::kpt10E, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p10E10E10E[3] = {&BuiltInVariable::kpt10E, &BuiltInVariable::kpt10E, + &BuiltInVariable::kpt10E}; +constexpr const TVariable *p10E10E10F[3] = {&BuiltInVariable::kpt10E, &BuiltInVariable::kpt10E, + &BuiltInVariable::kpt10F}; +constexpr const TVariable *p10E10E_o_10E_o_10E[4] = { + &BuiltInVariable::kpt10E, &BuiltInVariable::kpt10E, &BuiltInVariable::kpt_o_10E, + &BuiltInVariable::kpt_o_10E}; +constexpr const TVariable *p10F10F10F[3] = {&BuiltInVariable::kpt10F, &BuiltInVariable::kpt10F, + &BuiltInVariable::kpt10F}; +constexpr const TVariable *p20B00B00B[3] = {&BuiltInVariable::kpt20B, &BuiltInVariable::kpt00B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p20B00D[2] = {&BuiltInVariable::kpt20B, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p20B00H[2] = {&BuiltInVariable::kpt20B, &BuiltInVariable::kpt00H}; +constexpr const TVariable *p20B10B[2] = {&BuiltInVariable::kpt20B, &BuiltInVariable::kpt10B}; +constexpr const TVariable *p20B20B00B[3] = {&BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p20B20B20B[3] = {&BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt20B}; +constexpr const TVariable *p20B20B20F[3] = {&BuiltInVariable::kpt20B, &BuiltInVariable::kpt20B, + &BuiltInVariable::kpt20F}; +constexpr const TVariable *p20B20D[2] = {&BuiltInVariable::kpt20B, &BuiltInVariable::kpt20D}; +constexpr const TVariable *p20B30B[2] = {&BuiltInVariable::kpt20B, &BuiltInVariable::kpt30B}; +constexpr const TVariable *p20B_o_20B[2] = {&BuiltInVariable::kpt20B, &BuiltInVariable::kpt_o_20B}; +constexpr const TVariable *p20B_o_20D[2] = {&BuiltInVariable::kpt20B, &BuiltInVariable::kpt_o_20D}; +constexpr const TVariable *p20D00D00D[3] = {&BuiltInVariable::kpt20D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p20D20D00D00D[4] = {&BuiltInVariable::kpt20D, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p20D20D20D[3] = {&BuiltInVariable::kpt20D, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt20D}; +constexpr const TVariable *p20D20D20F[3] = {&BuiltInVariable::kpt20D, &BuiltInVariable::kpt20D, + &BuiltInVariable::kpt20F}; +constexpr const TVariable *p20D20D_o_20D_o_20D[4] = { + &BuiltInVariable::kpt20D, &BuiltInVariable::kpt20D, &BuiltInVariable::kpt_o_20D, + &BuiltInVariable::kpt_o_20D}; +constexpr const TVariable *p20E00D00D[3] = {&BuiltInVariable::kpt20E, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p20E00E00E[3] = {&BuiltInVariable::kpt20E, &BuiltInVariable::kpt00E, + &BuiltInVariable::kpt00E}; +constexpr const TVariable *p20E20E00D00D[4] = {&BuiltInVariable::kpt20E, &BuiltInVariable::kpt20E, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p20E20E20E[3] = {&BuiltInVariable::kpt20E, &BuiltInVariable::kpt20E, + &BuiltInVariable::kpt20E}; +constexpr const TVariable *p20E20E20F[3] = {&BuiltInVariable::kpt20E, &BuiltInVariable::kpt20E, + &BuiltInVariable::kpt20F}; +constexpr const TVariable *p20E20E_o_20E_o_20E[4] = { + &BuiltInVariable::kpt20E, &BuiltInVariable::kpt20E, &BuiltInVariable::kpt_o_20E, + &BuiltInVariable::kpt_o_20E}; +constexpr const TVariable *p20F20F20F[3] = {&BuiltInVariable::kpt20F, &BuiltInVariable::kpt20F, + &BuiltInVariable::kpt20F}; +constexpr const TVariable *p30B00B00B[3] = {&BuiltInVariable::kpt30B, &BuiltInVariable::kpt00B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p30B00D[2] = {&BuiltInVariable::kpt30B, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p30B10B[2] = {&BuiltInVariable::kpt30B, &BuiltInVariable::kpt10B}; +constexpr const TVariable *p30B20B[2] = {&BuiltInVariable::kpt30B, &BuiltInVariable::kpt20B}; +constexpr const TVariable *p30B30B00B[3] = {&BuiltInVariable::kpt30B, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt00B}; +constexpr const TVariable *p30B30B30B[3] = {&BuiltInVariable::kpt30B, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt30B}; +constexpr const TVariable *p30B30B30F[3] = {&BuiltInVariable::kpt30B, &BuiltInVariable::kpt30B, + &BuiltInVariable::kpt30F}; +constexpr const TVariable *p30B30D[2] = {&BuiltInVariable::kpt30B, &BuiltInVariable::kpt30D}; +constexpr const TVariable *p30B_o_30B[2] = {&BuiltInVariable::kpt30B, &BuiltInVariable::kpt_o_30B}; +constexpr const TVariable *p30B_o_30D[2] = {&BuiltInVariable::kpt30B, &BuiltInVariable::kpt_o_30D}; +constexpr const TVariable *p30D00D00D[3] = {&BuiltInVariable::kpt30D, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p30D30D00D00D[4] = {&BuiltInVariable::kpt30D, &BuiltInVariable::kpt30D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p30D30D30D[3] = {&BuiltInVariable::kpt30D, &BuiltInVariable::kpt30D, + &BuiltInVariable::kpt30D}; +constexpr const TVariable *p30D30D30F[3] = {&BuiltInVariable::kpt30D, &BuiltInVariable::kpt30D, + &BuiltInVariable::kpt30F}; +constexpr const TVariable *p30D30D_o_30D_o_30D[4] = { + &BuiltInVariable::kpt30D, &BuiltInVariable::kpt30D, &BuiltInVariable::kpt_o_30D, + &BuiltInVariable::kpt_o_30D}; +constexpr const TVariable *p30E00D00D[3] = {&BuiltInVariable::kpt30E, &BuiltInVariable::kpt00D, + &BuiltInVariable::kpt00D}; +constexpr const TVariable *p30E00E00E[3] = {&BuiltInVariable::kpt30E, &BuiltInVariable::kpt00E, + &BuiltInVariable::kpt00E}; +constexpr const TVariable *p30E30E00D00D[4] = {&BuiltInVariable::kpt30E, &BuiltInVariable::kpt30E, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p30E30E30E[3] = {&BuiltInVariable::kpt30E, &BuiltInVariable::kpt30E, + &BuiltInVariable::kpt30E}; +constexpr const TVariable *p30E30E30F[3] = {&BuiltInVariable::kpt30E, &BuiltInVariable::kpt30E, + &BuiltInVariable::kpt30F}; +constexpr const TVariable *p30E30E_o_30E_o_30E[4] = { + &BuiltInVariable::kpt30E, &BuiltInVariable::kpt30E, &BuiltInVariable::kpt_o_30E, + &BuiltInVariable::kpt_o_30E}; +constexpr const TVariable *p30F30F30F[3] = {&BuiltInVariable::kpt30F, &BuiltInVariable::kpt30F, + &BuiltInVariable::kpt30F}; +constexpr const TVariable *p50B50B[2] = {&BuiltInVariable::kpt50B, &BuiltInVariable::kpt50B}; +constexpr const TVariable *p60B60B[2] = {&BuiltInVariable::kpt60B, &BuiltInVariable::kpt60B}; +constexpr const TVariable *p70B70B[2] = {&BuiltInVariable::kpt70B, &BuiltInVariable::kpt70B}; +constexpr const TVariable *p90B90B[2] = {&BuiltInVariable::kpt90B, &BuiltInVariable::kpt90B}; +constexpr const TVariable *pA0BA0B[2] = {&BuiltInVariable::kptA0B, &BuiltInVariable::kptA0B}; +constexpr const TVariable *pB0BB0B[2] = {&BuiltInVariable::kptB0B, &BuiltInVariable::kptB0B}; +constexpr const TVariable *pD0BD0B[2] = {&BuiltInVariable::kptD0B, &BuiltInVariable::kptD0B}; +constexpr const TVariable *pE0BE0B[2] = {&BuiltInVariable::kptE0B, &BuiltInVariable::kptE0B}; +constexpr const TVariable *pF0BF0B[2] = {&BuiltInVariable::kptF0B, &BuiltInVariable::kptF0B}; +constexpr const TVariable *p_io_00D00D00D[3] = {&BuiltInVariable::kpt_io_00D, + &BuiltInVariable::kpt00D, &BuiltInVariable::kpt00D}; +constexpr const TVariable *p_io_00E00E00E[3] = {&BuiltInVariable::kpt_io_00E, + &BuiltInVariable::kpt00E, &BuiltInVariable::kpt00E}; + +} // namespace BuiltInParameters + +// TODO(oetuaho): Would be nice to make this a class instead of a namespace so that we could friend +// this from TFunction. Now symbol constructors taking an id have to be public even though they're +// not supposed to be accessible from outside of here. http://anglebug.com/2390 +namespace Func +{ + +constexpr const TFunction radians_00B(BuiltInId::radians_Float1, + BuiltInName::radians, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpRadians, + true); +constexpr const TFunction radians_10B(BuiltInId::radians_Float2, + BuiltInName::radians, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpRadians, + true); +constexpr const TFunction radians_20B(BuiltInId::radians_Float3, + BuiltInName::radians, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpRadians, + true); +constexpr const TFunction radians_30B(BuiltInId::radians_Float4, + BuiltInName::radians, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpRadians, + true); +constexpr const TFunction degrees_00B(BuiltInId::degrees_Float1, + BuiltInName::degrees, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpDegrees, + true); +constexpr const TFunction degrees_10B(BuiltInId::degrees_Float2, + BuiltInName::degrees, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpDegrees, + true); +constexpr const TFunction degrees_20B(BuiltInId::degrees_Float3, + BuiltInName::degrees, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpDegrees, + true); +constexpr const TFunction degrees_30B(BuiltInId::degrees_Float4, + BuiltInName::degrees, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpDegrees, + true); +constexpr const TFunction sin_00B(BuiltInId::sin_Float1, + BuiltInName::sin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpSin, + true); +constexpr const TFunction sin_10B(BuiltInId::sin_Float2, + BuiltInName::sin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpSin, + true); +constexpr const TFunction sin_20B(BuiltInId::sin_Float3, + BuiltInName::sin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpSin, + true); +constexpr const TFunction sin_30B(BuiltInId::sin_Float4, + BuiltInName::sin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpSin, + true); +constexpr const TFunction cos_00B(BuiltInId::cos_Float1, + BuiltInName::cos, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpCos, + true); +constexpr const TFunction cos_10B(BuiltInId::cos_Float2, + BuiltInName::cos, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpCos, + true); +constexpr const TFunction cos_20B(BuiltInId::cos_Float3, + BuiltInName::cos, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpCos, + true); +constexpr const TFunction cos_30B(BuiltInId::cos_Float4, + BuiltInName::cos, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpCos, + true); +constexpr const TFunction tan_00B(BuiltInId::tan_Float1, + BuiltInName::tan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpTan, + true); +constexpr const TFunction tan_10B(BuiltInId::tan_Float2, + BuiltInName::tan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpTan, + true); +constexpr const TFunction tan_20B(BuiltInId::tan_Float3, + BuiltInName::tan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpTan, + true); +constexpr const TFunction tan_30B(BuiltInId::tan_Float4, + BuiltInName::tan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpTan, + true); +constexpr const TFunction asin_00B(BuiltInId::asin_Float1, + BuiltInName::asin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpAsin, + true); +constexpr const TFunction asin_10B(BuiltInId::asin_Float2, + BuiltInName::asin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpAsin, + true); +constexpr const TFunction asin_20B(BuiltInId::asin_Float3, + BuiltInName::asin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpAsin, + true); +constexpr const TFunction asin_30B(BuiltInId::asin_Float4, + BuiltInName::asin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpAsin, + true); +constexpr const TFunction acos_00B(BuiltInId::acos_Float1, + BuiltInName::acos, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpAcos, + true); +constexpr const TFunction acos_10B(BuiltInId::acos_Float2, + BuiltInName::acos, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpAcos, + true); +constexpr const TFunction acos_20B(BuiltInId::acos_Float3, + BuiltInName::acos, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpAcos, + true); +constexpr const TFunction acos_30B(BuiltInId::acos_Float4, + BuiltInName::acos, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpAcos, + true); +constexpr const TFunction atan_00B00B(BuiltInId::atan_Float1_Float1, + BuiltInName::atan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 2, + StaticType::Get(), + EOpAtan, + true); +constexpr const TFunction atan_10B10B(BuiltInId::atan_Float2_Float2, + BuiltInName::atan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpAtan, + true); +constexpr const TFunction atan_20B20B(BuiltInId::atan_Float3_Float3, + BuiltInName::atan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpAtan, + true); +constexpr const TFunction atan_30B30B(BuiltInId::atan_Float4_Float4, + BuiltInName::atan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpAtan, + true); +constexpr const TFunction atan_00B(BuiltInId::atan_Float1, + BuiltInName::atan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpAtan, + true); +constexpr const TFunction atan_10B(BuiltInId::atan_Float2, + BuiltInName::atan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpAtan, + true); +constexpr const TFunction atan_20B(BuiltInId::atan_Float3, + BuiltInName::atan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpAtan, + true); +constexpr const TFunction atan_30B(BuiltInId::atan_Float4, + BuiltInName::atan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpAtan, + true); +constexpr const TFunction sinh_00B(BuiltInId::sinh_Float1, + BuiltInName::sinh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpSinh, + true); +constexpr const TFunction sinh_10B(BuiltInId::sinh_Float2, + BuiltInName::sinh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpSinh, + true); +constexpr const TFunction sinh_20B(BuiltInId::sinh_Float3, + BuiltInName::sinh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpSinh, + true); +constexpr const TFunction sinh_30B(BuiltInId::sinh_Float4, + BuiltInName::sinh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpSinh, + true); +constexpr const TFunction cosh_00B(BuiltInId::cosh_Float1, + BuiltInName::cosh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpCosh, + true); +constexpr const TFunction cosh_10B(BuiltInId::cosh_Float2, + BuiltInName::cosh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpCosh, + true); +constexpr const TFunction cosh_20B(BuiltInId::cosh_Float3, + BuiltInName::cosh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpCosh, + true); +constexpr const TFunction cosh_30B(BuiltInId::cosh_Float4, + BuiltInName::cosh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpCosh, + true); +constexpr const TFunction tanh_00B(BuiltInId::tanh_Float1, + BuiltInName::tanh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpTanh, + true); +constexpr const TFunction tanh_10B(BuiltInId::tanh_Float2, + BuiltInName::tanh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpTanh, + true); +constexpr const TFunction tanh_20B(BuiltInId::tanh_Float3, + BuiltInName::tanh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpTanh, + true); +constexpr const TFunction tanh_30B(BuiltInId::tanh_Float4, + BuiltInName::tanh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpTanh, + true); +constexpr const TFunction asinh_00B(BuiltInId::asinh_Float1, + BuiltInName::asinh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpAsinh, + true); +constexpr const TFunction asinh_10B(BuiltInId::asinh_Float2, + BuiltInName::asinh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpAsinh, + true); +constexpr const TFunction asinh_20B(BuiltInId::asinh_Float3, + BuiltInName::asinh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpAsinh, + true); +constexpr const TFunction asinh_30B(BuiltInId::asinh_Float4, + BuiltInName::asinh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpAsinh, + true); +constexpr const TFunction acosh_00B(BuiltInId::acosh_Float1, + BuiltInName::acosh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpAcosh, + true); +constexpr const TFunction acosh_10B(BuiltInId::acosh_Float2, + BuiltInName::acosh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpAcosh, + true); +constexpr const TFunction acosh_20B(BuiltInId::acosh_Float3, + BuiltInName::acosh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpAcosh, + true); +constexpr const TFunction acosh_30B(BuiltInId::acosh_Float4, + BuiltInName::acosh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpAcosh, + true); +constexpr const TFunction atanh_00B(BuiltInId::atanh_Float1, + BuiltInName::atanh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpAtanh, + true); +constexpr const TFunction atanh_10B(BuiltInId::atanh_Float2, + BuiltInName::atanh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpAtanh, + true); +constexpr const TFunction atanh_20B(BuiltInId::atanh_Float3, + BuiltInName::atanh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpAtanh, + true); +constexpr const TFunction atanh_30B(BuiltInId::atanh_Float4, + BuiltInName::atanh, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpAtanh, + true); +constexpr const TFunction pow_00B00B(BuiltInId::pow_Float1_Float1, + BuiltInName::pow, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 2, + StaticType::Get(), + EOpPow, + true); +constexpr const TFunction pow_10B10B(BuiltInId::pow_Float2_Float2, + BuiltInName::pow, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpPow, + true); +constexpr const TFunction pow_20B20B(BuiltInId::pow_Float3_Float3, + BuiltInName::pow, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpPow, + true); +constexpr const TFunction pow_30B30B(BuiltInId::pow_Float4_Float4, + BuiltInName::pow, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpPow, + true); +constexpr const TFunction exp_00B(BuiltInId::exp_Float1, + BuiltInName::exp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpExp, + true); +constexpr const TFunction exp_10B(BuiltInId::exp_Float2, + BuiltInName::exp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpExp, + true); +constexpr const TFunction exp_20B(BuiltInId::exp_Float3, + BuiltInName::exp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpExp, + true); +constexpr const TFunction exp_30B(BuiltInId::exp_Float4, + BuiltInName::exp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpExp, + true); +constexpr const TFunction log_00B(BuiltInId::log_Float1, + BuiltInName::log, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpLog, + true); +constexpr const TFunction log_10B(BuiltInId::log_Float2, + BuiltInName::log, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpLog, + true); +constexpr const TFunction log_20B(BuiltInId::log_Float3, + BuiltInName::log, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpLog, + true); +constexpr const TFunction log_30B(BuiltInId::log_Float4, + BuiltInName::log, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpLog, + true); +constexpr const TFunction exp2_00B(BuiltInId::exp2_Float1, + BuiltInName::exp2, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpExp2, + true); +constexpr const TFunction exp2_10B(BuiltInId::exp2_Float2, + BuiltInName::exp2, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpExp2, + true); +constexpr const TFunction exp2_20B(BuiltInId::exp2_Float3, + BuiltInName::exp2, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpExp2, + true); +constexpr const TFunction exp2_30B(BuiltInId::exp2_Float4, + BuiltInName::exp2, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpExp2, + true); +constexpr const TFunction log2_00B(BuiltInId::log2_Float1, + BuiltInName::log2, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpLog2, + true); +constexpr const TFunction log2_10B(BuiltInId::log2_Float2, + BuiltInName::log2, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpLog2, + true); +constexpr const TFunction log2_20B(BuiltInId::log2_Float3, + BuiltInName::log2, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpLog2, + true); +constexpr const TFunction log2_30B(BuiltInId::log2_Float4, + BuiltInName::log2, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpLog2, + true); +constexpr const TFunction sqrt_00B(BuiltInId::sqrt_Float1, + BuiltInName::sqrt, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpSqrt, + true); +constexpr const TFunction sqrt_10B(BuiltInId::sqrt_Float2, + BuiltInName::sqrt, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpSqrt, + true); +constexpr const TFunction sqrt_20B(BuiltInId::sqrt_Float3, + BuiltInName::sqrt, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpSqrt, + true); +constexpr const TFunction sqrt_30B(BuiltInId::sqrt_Float4, + BuiltInName::sqrt, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpSqrt, + true); +constexpr const TFunction inversesqrt_00B( + BuiltInId::inversesqrt_Float1, + BuiltInName::inversesqrt, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpInversesqrt, + true); +constexpr const TFunction inversesqrt_10B( + BuiltInId::inversesqrt_Float2, + BuiltInName::inversesqrt, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpInversesqrt, + true); +constexpr const TFunction inversesqrt_20B( + BuiltInId::inversesqrt_Float3, + BuiltInName::inversesqrt, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpInversesqrt, + true); +constexpr const TFunction inversesqrt_30B( + BuiltInId::inversesqrt_Float4, + BuiltInName::inversesqrt, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpInversesqrt, + true); +constexpr const TFunction abs_00B(BuiltInId::abs_Float1, + BuiltInName::abs, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpAbs, + true); +constexpr const TFunction abs_10B(BuiltInId::abs_Float2, + BuiltInName::abs, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpAbs, + true); +constexpr const TFunction abs_20B(BuiltInId::abs_Float3, + BuiltInName::abs, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpAbs, + true); +constexpr const TFunction abs_30B(BuiltInId::abs_Float4, + BuiltInName::abs, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpAbs, + true); +constexpr const TFunction abs_00D(BuiltInId::abs_Int1, + BuiltInName::abs, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00D00D00D00D, + 1, + StaticType::Get(), + EOpAbs, + true); +constexpr const TFunction abs_10D(BuiltInId::abs_Int2, + BuiltInName::abs, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D00D00D, + 1, + StaticType::Get(), + EOpAbs, + true); +constexpr const TFunction abs_20D(BuiltInId::abs_Int3, + BuiltInName::abs, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D00D00D, + 1, + StaticType::Get(), + EOpAbs, + true); +constexpr const TFunction abs_30D(BuiltInId::abs_Int4, + BuiltInName::abs, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D00D00D, + 1, + StaticType::Get(), + EOpAbs, + true); +constexpr const TFunction sign_00B(BuiltInId::sign_Float1, + BuiltInName::sign, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpSign, + true); +constexpr const TFunction sign_10B(BuiltInId::sign_Float2, + BuiltInName::sign, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpSign, + true); +constexpr const TFunction sign_20B(BuiltInId::sign_Float3, + BuiltInName::sign, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpSign, + true); +constexpr const TFunction sign_30B(BuiltInId::sign_Float4, + BuiltInName::sign, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpSign, + true); +constexpr const TFunction sign_00D(BuiltInId::sign_Int1, + BuiltInName::sign, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00D00D00D00D, + 1, + StaticType::Get(), + EOpSign, + true); +constexpr const TFunction sign_10D(BuiltInId::sign_Int2, + BuiltInName::sign, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D00D00D, + 1, + StaticType::Get(), + EOpSign, + true); +constexpr const TFunction sign_20D(BuiltInId::sign_Int3, + BuiltInName::sign, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D00D00D, + 1, + StaticType::Get(), + EOpSign, + true); +constexpr const TFunction sign_30D(BuiltInId::sign_Int4, + BuiltInName::sign, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D00D00D, + 1, + StaticType::Get(), + EOpSign, + true); +constexpr const TFunction floor_00B(BuiltInId::floor_Float1, + BuiltInName::floor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpFloor, + true); +constexpr const TFunction floor_10B(BuiltInId::floor_Float2, + BuiltInName::floor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpFloor, + true); +constexpr const TFunction floor_20B(BuiltInId::floor_Float3, + BuiltInName::floor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpFloor, + true); +constexpr const TFunction floor_30B(BuiltInId::floor_Float4, + BuiltInName::floor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpFloor, + true); +constexpr const TFunction trunc_00B(BuiltInId::trunc_Float1, + BuiltInName::trunc, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpTrunc, + true); +constexpr const TFunction trunc_10B(BuiltInId::trunc_Float2, + BuiltInName::trunc, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpTrunc, + true); +constexpr const TFunction trunc_20B(BuiltInId::trunc_Float3, + BuiltInName::trunc, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpTrunc, + true); +constexpr const TFunction trunc_30B(BuiltInId::trunc_Float4, + BuiltInName::trunc, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpTrunc, + true); +constexpr const TFunction round_00B(BuiltInId::round_Float1, + BuiltInName::round, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpRound, + true); +constexpr const TFunction round_10B(BuiltInId::round_Float2, + BuiltInName::round, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpRound, + true); +constexpr const TFunction round_20B(BuiltInId::round_Float3, + BuiltInName::round, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpRound, + true); +constexpr const TFunction round_30B(BuiltInId::round_Float4, + BuiltInName::round, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpRound, + true); +constexpr const TFunction roundEven_00B(BuiltInId::roundEven_Float1, + BuiltInName::roundEven, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpRoundEven, + true); +constexpr const TFunction roundEven_10B(BuiltInId::roundEven_Float2, + BuiltInName::roundEven, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpRoundEven, + true); +constexpr const TFunction roundEven_20B(BuiltInId::roundEven_Float3, + BuiltInName::roundEven, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpRoundEven, + true); +constexpr const TFunction roundEven_30B(BuiltInId::roundEven_Float4, + BuiltInName::roundEven, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpRoundEven, + true); +constexpr const TFunction ceil_00B(BuiltInId::ceil_Float1, + BuiltInName::ceil, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpCeil, + true); +constexpr const TFunction ceil_10B(BuiltInId::ceil_Float2, + BuiltInName::ceil, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpCeil, + true); +constexpr const TFunction ceil_20B(BuiltInId::ceil_Float3, + BuiltInName::ceil, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpCeil, + true); +constexpr const TFunction ceil_30B(BuiltInId::ceil_Float4, + BuiltInName::ceil, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpCeil, + true); +constexpr const TFunction fract_00B(BuiltInId::fract_Float1, + BuiltInName::fract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpFract, + true); +constexpr const TFunction fract_10B(BuiltInId::fract_Float2, + BuiltInName::fract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpFract, + true); +constexpr const TFunction fract_20B(BuiltInId::fract_Float3, + BuiltInName::fract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpFract, + true); +constexpr const TFunction fract_30B(BuiltInId::fract_Float4, + BuiltInName::fract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpFract, + true); +constexpr const TFunction mod_00B00B(BuiltInId::mod_Float1_Float1, + BuiltInName::mod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 2, + StaticType::Get(), + EOpMod, + true); +constexpr const TFunction mod_10B00B(BuiltInId::mod_Float2_Float1, + BuiltInName::mod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 2, + StaticType::Get(), + EOpMod, + true); +constexpr const TFunction mod_20B00B(BuiltInId::mod_Float3_Float1, + BuiltInName::mod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 2, + StaticType::Get(), + EOpMod, + true); +constexpr const TFunction mod_30B00B(BuiltInId::mod_Float4_Float1, + BuiltInName::mod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 2, + StaticType::Get(), + EOpMod, + true); +constexpr const TFunction mod_10B10B(BuiltInId::mod_Float2_Float2, + BuiltInName::mod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpMod, + true); +constexpr const TFunction mod_20B20B(BuiltInId::mod_Float3_Float3, + BuiltInName::mod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpMod, + true); +constexpr const TFunction mod_30B30B(BuiltInId::mod_Float4_Float4, + BuiltInName::mod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpMod, + true); +constexpr const TFunction min_00B00B(BuiltInId::min_Float1_Float1, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_10B00B(BuiltInId::min_Float2_Float1, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_20B00B(BuiltInId::min_Float3_Float1, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_30B00B(BuiltInId::min_Float4_Float1, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_10B10B(BuiltInId::min_Float2_Float2, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_20B20B(BuiltInId::min_Float3_Float3, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_30B30B(BuiltInId::min_Float4_Float4, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_00D00D(BuiltInId::min_Int1_Int1, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00D00D00D00D, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_10D10D(BuiltInId::min_Int2_Int2, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D10D00D00D, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_20D20D(BuiltInId::min_Int3_Int3, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D20D00D00D, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_30D30D(BuiltInId::min_Int4_Int4, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D30D00D00D, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_10D00D(BuiltInId::min_Int2_Int1, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D00D00D, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_20D00D(BuiltInId::min_Int3_Int1, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D00D00D, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_30D00D(BuiltInId::min_Int4_Int1, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D00D00D, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_00E00E(BuiltInId::min_UInt1_UInt1, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00E00D00D, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_10E10E(BuiltInId::min_UInt2_UInt2, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E10E00D00D, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_20E20E(BuiltInId::min_UInt3_UInt3, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E20E00D00D, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_30E30E(BuiltInId::min_UInt4_UInt4, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E30E00D00D, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_10E00E(BuiltInId::min_UInt2_UInt1, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E00E00E, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_20E00E(BuiltInId::min_UInt3_UInt1, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E00E00E, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction min_30E00E(BuiltInId::min_UInt4_UInt1, + BuiltInName::min, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E00E00E, + 2, + StaticType::Get(), + EOpMin, + true); +constexpr const TFunction max_00B00B(BuiltInId::max_Float1_Float1, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_10B00B(BuiltInId::max_Float2_Float1, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_20B00B(BuiltInId::max_Float3_Float1, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_30B00B(BuiltInId::max_Float4_Float1, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_10B10B(BuiltInId::max_Float2_Float2, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_20B20B(BuiltInId::max_Float3_Float3, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_30B30B(BuiltInId::max_Float4_Float4, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_00D00D(BuiltInId::max_Int1_Int1, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00D00D00D00D, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_10D10D(BuiltInId::max_Int2_Int2, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D10D00D00D, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_20D20D(BuiltInId::max_Int3_Int3, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D20D00D00D, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_30D30D(BuiltInId::max_Int4_Int4, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D30D00D00D, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_10D00D(BuiltInId::max_Int2_Int1, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D00D00D, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_20D00D(BuiltInId::max_Int3_Int1, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D00D00D, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_30D00D(BuiltInId::max_Int4_Int1, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D00D00D, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_00E00E(BuiltInId::max_UInt1_UInt1, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00E00D00D, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_10E10E(BuiltInId::max_UInt2_UInt2, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E10E00D00D, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_20E20E(BuiltInId::max_UInt3_UInt3, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E20E00D00D, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_30E30E(BuiltInId::max_UInt4_UInt4, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E30E00D00D, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_10E00E(BuiltInId::max_UInt2_UInt1, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E00E00E, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_20E00E(BuiltInId::max_UInt3_UInt1, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E00E00E, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction max_30E00E(BuiltInId::max_UInt4_UInt1, + BuiltInName::max, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E00E00E, + 2, + StaticType::Get(), + EOpMax, + true); +constexpr const TFunction clamp_00B00B00B( + BuiltInId::clamp_Float1_Float1_Float1, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_10B00B00B( + BuiltInId::clamp_Float2_Float1_Float1, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_20B00B00B( + BuiltInId::clamp_Float3_Float1_Float1, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_30B00B00B( + BuiltInId::clamp_Float4_Float1_Float1, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_10B10B10B( + BuiltInId::clamp_Float2_Float2_Float2, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B10B, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_20B20B20B( + BuiltInId::clamp_Float3_Float3_Float3, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B20B, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_30B30B30B( + BuiltInId::clamp_Float4_Float4_Float4, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B30B, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_00D00D00D(BuiltInId::clamp_Int1_Int1_Int1, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00D00D00D00D, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_10D00D00D(BuiltInId::clamp_Int2_Int1_Int1, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D00D00D, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_20D00D00D(BuiltInId::clamp_Int3_Int1_Int1, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D00D00D, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_30D00D00D(BuiltInId::clamp_Int4_Int1_Int1, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D00D00D, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_10D10D10D(BuiltInId::clamp_Int2_Int2_Int2, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D10D10D, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_20D20D20D(BuiltInId::clamp_Int3_Int3_Int3, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D20D20D, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_30D30D30D(BuiltInId::clamp_Int4_Int4_Int4, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D30D30D, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_00E00E00E(BuiltInId::clamp_UInt1_UInt1_UInt1, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00E00E, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_10E00E00E(BuiltInId::clamp_UInt2_UInt1_UInt1, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E00E00E, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_20E00E00E(BuiltInId::clamp_UInt3_UInt1_UInt1, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E00E00E, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_30E00E00E(BuiltInId::clamp_UInt4_UInt1_UInt1, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E00E00E, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_10E10E10E(BuiltInId::clamp_UInt2_UInt2_UInt2, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E10E10E, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_20E20E20E(BuiltInId::clamp_UInt3_UInt3_UInt3, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E20E20E, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction clamp_30E30E30E(BuiltInId::clamp_UInt4_UInt4_UInt4, + BuiltInName::clamp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E30E30E, + 3, + StaticType::Get(), + EOpClamp, + true); +constexpr const TFunction mix_00B00B00B(BuiltInId::mix_Float1_Float1_Float1, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_10B10B00B(BuiltInId::mix_Float2_Float2_Float1, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_20B20B00B(BuiltInId::mix_Float3_Float3_Float1, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_30B30B00B(BuiltInId::mix_Float4_Float4_Float1, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_10B10B10B(BuiltInId::mix_Float2_Float2_Float2, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B10B, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_20B20B20B(BuiltInId::mix_Float3_Float3_Float3, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B20B, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_30B30B30B(BuiltInId::mix_Float4_Float4_Float4, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B30B, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_00B00B00F(BuiltInId::mix_Float1_Float1_Bool1, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_10B10B10F(BuiltInId::mix_Float2_Float2_Bool2, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B10F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_20B20B20F(BuiltInId::mix_Float3_Float3_Bool3, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B20F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_30B30B30F(BuiltInId::mix_Float4_Float4_Bool4, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B30F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_00D00D00F(BuiltInId::mix_Int1_Int1_Bool1, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00D00D00F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_10D10D10F(BuiltInId::mix_Int2_Int2_Bool2, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D10D10F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_20D20D20F(BuiltInId::mix_Int3_Int3_Bool3, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D20D20F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_30D30D30F(BuiltInId::mix_Int4_Int4_Bool4, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D30D30F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_00E00E00F(BuiltInId::mix_UInt1_UInt1_Bool1, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00E00F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_10E10E10F(BuiltInId::mix_UInt2_UInt2_Bool2, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E10E10F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_20E20E20F(BuiltInId::mix_UInt3_UInt3_Bool3, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E20E20F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_30E30E30F(BuiltInId::mix_UInt4_UInt4_Bool4, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E30E30F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_00F00F00F(BuiltInId::mix_Bool1_Bool1_Bool1, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00F00F00F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_10F10F10F(BuiltInId::mix_Bool2_Bool2_Bool2, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10F10F10F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_20F20F20F(BuiltInId::mix_Bool3_Bool3_Bool3, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20F20F20F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction mix_30F30F30F(BuiltInId::mix_Bool4_Bool4_Bool4, + BuiltInName::mix, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30F30F30F, + 3, + StaticType::Get(), + EOpMix, + true); +constexpr const TFunction step_00B00B(BuiltInId::step_Float1_Float1, + BuiltInName::step, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 2, + StaticType::Get(), + EOpStep, + true); +constexpr const TFunction step_10B10B(BuiltInId::step_Float2_Float2, + BuiltInName::step, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpStep, + true); +constexpr const TFunction step_20B20B(BuiltInId::step_Float3_Float3, + BuiltInName::step, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpStep, + true); +constexpr const TFunction step_30B30B(BuiltInId::step_Float4_Float4, + BuiltInName::step, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpStep, + true); +constexpr const TFunction step_00B10B(BuiltInId::step_Float1_Float2, + BuiltInName::step, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B10B, + 2, + StaticType::Get(), + EOpStep, + true); +constexpr const TFunction step_00B20B(BuiltInId::step_Float1_Float3, + BuiltInName::step, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B20B, + 2, + StaticType::Get(), + EOpStep, + true); +constexpr const TFunction step_00B30B(BuiltInId::step_Float1_Float4, + BuiltInName::step, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B30B, + 2, + StaticType::Get(), + EOpStep, + true); +constexpr const TFunction smoothstep_00B00B00B( + BuiltInId::smoothstep_Float1_Float1_Float1, + BuiltInName::smoothstep, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 3, + StaticType::Get(), + EOpSmoothstep, + true); +constexpr const TFunction smoothstep_10B10B10B( + BuiltInId::smoothstep_Float2_Float2_Float2, + BuiltInName::smoothstep, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B10B, + 3, + StaticType::Get(), + EOpSmoothstep, + true); +constexpr const TFunction smoothstep_20B20B20B( + BuiltInId::smoothstep_Float3_Float3_Float3, + BuiltInName::smoothstep, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B20B, + 3, + StaticType::Get(), + EOpSmoothstep, + true); +constexpr const TFunction smoothstep_30B30B30B( + BuiltInId::smoothstep_Float4_Float4_Float4, + BuiltInName::smoothstep, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B30B, + 3, + StaticType::Get(), + EOpSmoothstep, + true); +constexpr const TFunction smoothstep_00B00B10B( + BuiltInId::smoothstep_Float1_Float1_Float2, + BuiltInName::smoothstep, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B10B, + 3, + StaticType::Get(), + EOpSmoothstep, + true); +constexpr const TFunction smoothstep_00B00B20B( + BuiltInId::smoothstep_Float1_Float1_Float3, + BuiltInName::smoothstep, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B20B, + 3, + StaticType::Get(), + EOpSmoothstep, + true); +constexpr const TFunction smoothstep_00B00B30B( + BuiltInId::smoothstep_Float1_Float1_Float4, + BuiltInName::smoothstep, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B30B, + 3, + StaticType::Get(), + EOpSmoothstep, + true); +constexpr const TFunction modf_00B00B(BuiltInId::modf_Float1_Float1, + BuiltInName::modf, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B_o_00B, + 2, + StaticType::Get(), + EOpModf, + false); +constexpr const TFunction modf_10B10B(BuiltInId::modf_Float2_Float2, + BuiltInName::modf, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B_o_10B, + 2, + StaticType::Get(), + EOpModf, + false); +constexpr const TFunction modf_20B20B(BuiltInId::modf_Float3_Float3, + BuiltInName::modf, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B_o_20B, + 2, + StaticType::Get(), + EOpModf, + false); +constexpr const TFunction modf_30B30B(BuiltInId::modf_Float4_Float4, + BuiltInName::modf, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B_o_30B, + 2, + StaticType::Get(), + EOpModf, + false); +constexpr const TFunction isnan_00B(BuiltInId::isnan_Float1, + BuiltInName::isnan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpIsnan, + true); +constexpr const TFunction isnan_10B(BuiltInId::isnan_Float2, + BuiltInName::isnan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpIsnan, + true); +constexpr const TFunction isnan_20B(BuiltInId::isnan_Float3, + BuiltInName::isnan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpIsnan, + true); +constexpr const TFunction isnan_30B(BuiltInId::isnan_Float4, + BuiltInName::isnan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpIsnan, + true); +constexpr const TFunction isinf_00B(BuiltInId::isinf_Float1, + BuiltInName::isinf, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpIsinf, + true); +constexpr const TFunction isinf_10B(BuiltInId::isinf_Float2, + BuiltInName::isinf, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpIsinf, + true); +constexpr const TFunction isinf_20B(BuiltInId::isinf_Float3, + BuiltInName::isinf, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpIsinf, + true); +constexpr const TFunction isinf_30B(BuiltInId::isinf_Float4, + BuiltInName::isinf, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpIsinf, + true); +constexpr const TFunction floatBitsToInt_00B( + BuiltInId::floatBitsToInt_Float1, + BuiltInName::floatBitsToInt, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpFloatBitsToInt, + true); +constexpr const TFunction floatBitsToInt_10B( + BuiltInId::floatBitsToInt_Float2, + BuiltInName::floatBitsToInt, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpFloatBitsToInt, + true); +constexpr const TFunction floatBitsToInt_20B( + BuiltInId::floatBitsToInt_Float3, + BuiltInName::floatBitsToInt, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpFloatBitsToInt, + true); +constexpr const TFunction floatBitsToInt_30B( + BuiltInId::floatBitsToInt_Float4, + BuiltInName::floatBitsToInt, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpFloatBitsToInt, + true); +constexpr const TFunction floatBitsToUint_00B( + BuiltInId::floatBitsToUint_Float1, + BuiltInName::floatBitsToUint, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpFloatBitsToUint, + true); +constexpr const TFunction floatBitsToUint_10B( + BuiltInId::floatBitsToUint_Float2, + BuiltInName::floatBitsToUint, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpFloatBitsToUint, + true); +constexpr const TFunction floatBitsToUint_20B( + BuiltInId::floatBitsToUint_Float3, + BuiltInName::floatBitsToUint, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpFloatBitsToUint, + true); +constexpr const TFunction floatBitsToUint_30B( + BuiltInId::floatBitsToUint_Float4, + BuiltInName::floatBitsToUint, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpFloatBitsToUint, + true); +constexpr const TFunction intBitsToFloat_00D( + BuiltInId::intBitsToFloat_Int1, + BuiltInName::intBitsToFloat, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00D00D00D00D, + 1, + StaticType::Get(), + EOpIntBitsToFloat, + true); +constexpr const TFunction intBitsToFloat_10D( + BuiltInId::intBitsToFloat_Int2, + BuiltInName::intBitsToFloat, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D00D00D, + 1, + StaticType::Get(), + EOpIntBitsToFloat, + true); +constexpr const TFunction intBitsToFloat_20D( + BuiltInId::intBitsToFloat_Int3, + BuiltInName::intBitsToFloat, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D00D00D, + 1, + StaticType::Get(), + EOpIntBitsToFloat, + true); +constexpr const TFunction intBitsToFloat_30D( + BuiltInId::intBitsToFloat_Int4, + BuiltInName::intBitsToFloat, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D00D00D, + 1, + StaticType::Get(), + EOpIntBitsToFloat, + true); +constexpr const TFunction uintBitsToFloat_00E( + BuiltInId::uintBitsToFloat_UInt1, + BuiltInName::uintBitsToFloat, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00D00D, + 1, + StaticType::Get(), + EOpUintBitsToFloat, + true); +constexpr const TFunction uintBitsToFloat_10E( + BuiltInId::uintBitsToFloat_UInt2, + BuiltInName::uintBitsToFloat, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E00D00D, + 1, + StaticType::Get(), + EOpUintBitsToFloat, + true); +constexpr const TFunction uintBitsToFloat_20E( + BuiltInId::uintBitsToFloat_UInt3, + BuiltInName::uintBitsToFloat, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E00D00D, + 1, + StaticType::Get(), + EOpUintBitsToFloat, + true); +constexpr const TFunction uintBitsToFloat_30E( + BuiltInId::uintBitsToFloat_UInt4, + BuiltInName::uintBitsToFloat, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E00D00D, + 1, + StaticType::Get(), + EOpUintBitsToFloat, + true); +constexpr const TFunction fma_00B00B00B(BuiltInId::fma_Float1_Float1_Float1, + BuiltInName::fma, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 3, + StaticType::Get(), + EOpFma, + true); +constexpr const TFunction fma_10B10B10B(BuiltInId::fma_Float2_Float2_Float2, + BuiltInName::fma, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B10B, + 3, + StaticType::Get(), + EOpFma, + true); +constexpr const TFunction fma_20B20B20B(BuiltInId::fma_Float3_Float3_Float3, + BuiltInName::fma, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B20B, + 3, + StaticType::Get(), + EOpFma, + true); +constexpr const TFunction fma_30B30B30B(BuiltInId::fma_Float4_Float4_Float4, + BuiltInName::fma, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B30B, + 3, + StaticType::Get(), + EOpFma, + true); +constexpr const TFunction fmaExt_00B00B00B( + BuiltInId::fmaExt_Float1_Float1_Float1, + BuiltInName::fmaExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00B00B00B, + 3, + StaticType::Get(), + EOpFma, + true); +constexpr const TFunction fmaExt_10B10B10B( + BuiltInId::fmaExt_Float2_Float2_Float2, + BuiltInName::fmaExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p10B10B10B, + 3, + StaticType::Get(), + EOpFma, + true); +constexpr const TFunction fmaExt_20B20B20B( + BuiltInId::fmaExt_Float3_Float3_Float3, + BuiltInName::fmaExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p20B20B20B, + 3, + StaticType::Get(), + EOpFma, + true); +constexpr const TFunction fmaExt_30B30B30B( + BuiltInId::fmaExt_Float4_Float4_Float4, + BuiltInName::fmaExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p30B30B30B, + 3, + StaticType::Get(), + EOpFma, + true); +constexpr const TFunction frexp_00B00D(BuiltInId::frexp_Float1_Int1, + BuiltInName::frexp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B_o_00D, + 2, + StaticType::Get(), + EOpFrexp, + false); +constexpr const TFunction frexp_10B10D(BuiltInId::frexp_Float2_Int2, + BuiltInName::frexp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B_o_10D, + 2, + StaticType::Get(), + EOpFrexp, + false); +constexpr const TFunction frexp_20B20D(BuiltInId::frexp_Float3_Int3, + BuiltInName::frexp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B_o_20D, + 2, + StaticType::Get(), + EOpFrexp, + false); +constexpr const TFunction frexp_30B30D(BuiltInId::frexp_Float4_Int4, + BuiltInName::frexp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B_o_30D, + 2, + StaticType::Get(), + EOpFrexp, + false); +constexpr const TFunction ldexp_00B00D(BuiltInId::ldexp_Float1_Int1, + BuiltInName::ldexp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00D, + 2, + StaticType::Get(), + EOpLdexp, + true); +constexpr const TFunction ldexp_10B10D(BuiltInId::ldexp_Float2_Int2, + BuiltInName::ldexp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10D, + 2, + StaticType::Get(), + EOpLdexp, + true); +constexpr const TFunction ldexp_20B20D(BuiltInId::ldexp_Float3_Int3, + BuiltInName::ldexp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20D, + 2, + StaticType::Get(), + EOpLdexp, + true); +constexpr const TFunction ldexp_30B30D(BuiltInId::ldexp_Float4_Int4, + BuiltInName::ldexp, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30D, + 2, + StaticType::Get(), + EOpLdexp, + true); +constexpr const TFunction packSnorm2x16_10B( + BuiltInId::packSnorm2x16_Float2, + BuiltInName::packSnorm2x16, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpPackSnorm2x16, + true); +constexpr const TFunction packHalf2x16_10B( + BuiltInId::packHalf2x16_Float2, + BuiltInName::packHalf2x16, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpPackHalf2x16, + true); +constexpr const TFunction unpackSnorm2x16_00E( + BuiltInId::unpackSnorm2x16_UInt1, + BuiltInName::unpackSnorm2x16, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00D00D, + 1, + StaticType::Get(), + EOpUnpackSnorm2x16, + true); +constexpr const TFunction unpackHalf2x16_00E( + BuiltInId::unpackHalf2x16_UInt1, + BuiltInName::unpackHalf2x16, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00D00D, + 1, + StaticType::Get(), + EOpUnpackHalf2x16, + true); +constexpr const TFunction packUnorm2x16_10B( + BuiltInId::packUnorm2x16_Float2, + BuiltInName::packUnorm2x16, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpPackUnorm2x16, + true); +constexpr const TFunction unpackUnorm2x16_00E( + BuiltInId::unpackUnorm2x16_UInt1, + BuiltInName::unpackUnorm2x16, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00D00D, + 1, + StaticType::Get(), + EOpUnpackUnorm2x16, + true); +constexpr const TFunction packUnorm4x8_30B( + BuiltInId::packUnorm4x8_Float4, + BuiltInName::packUnorm4x8, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpPackUnorm4x8, + true); +constexpr const TFunction packSnorm4x8_30B( + BuiltInId::packSnorm4x8_Float4, + BuiltInName::packSnorm4x8, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpPackSnorm4x8, + true); +constexpr const TFunction unpackUnorm4x8_00E( + BuiltInId::unpackUnorm4x8_UInt1, + BuiltInName::unpackUnorm4x8, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00D00D, + 1, + StaticType::Get(), + EOpUnpackUnorm4x8, + true); +constexpr const TFunction unpackSnorm4x8_00E( + BuiltInId::unpackSnorm4x8_UInt1, + BuiltInName::unpackSnorm4x8, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00D00D, + 1, + StaticType::Get(), + EOpUnpackSnorm4x8, + true); +constexpr const TFunction length_00B(BuiltInId::length_Float1, + BuiltInName::length, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpLength, + true); +constexpr const TFunction length_10B(BuiltInId::length_Float2, + BuiltInName::length, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpLength, + true); +constexpr const TFunction length_20B(BuiltInId::length_Float3, + BuiltInName::length, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpLength, + true); +constexpr const TFunction length_30B(BuiltInId::length_Float4, + BuiltInName::length, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpLength, + true); +constexpr const TFunction distance_00B00B( + BuiltInId::distance_Float1_Float1, + BuiltInName::distance, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 2, + StaticType::Get(), + EOpDistance, + true); +constexpr const TFunction distance_10B10B( + BuiltInId::distance_Float2_Float2, + BuiltInName::distance, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpDistance, + true); +constexpr const TFunction distance_20B20B( + BuiltInId::distance_Float3_Float3, + BuiltInName::distance, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpDistance, + true); +constexpr const TFunction distance_30B30B( + BuiltInId::distance_Float4_Float4, + BuiltInName::distance, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpDistance, + true); +constexpr const TFunction dot_00B00B(BuiltInId::dot_Float1_Float1, + BuiltInName::dot, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 2, + StaticType::Get(), + EOpDot, + true); +constexpr const TFunction dot_10B10B(BuiltInId::dot_Float2_Float2, + BuiltInName::dot, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpDot, + true); +constexpr const TFunction dot_20B20B(BuiltInId::dot_Float3_Float3, + BuiltInName::dot, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpDot, + true); +constexpr const TFunction dot_30B30B(BuiltInId::dot_Float4_Float4, + BuiltInName::dot, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpDot, + true); +constexpr const TFunction cross_20B20B(BuiltInId::cross_Float3_Float3, + BuiltInName::cross, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpCross, + true); +constexpr const TFunction normalize_00B(BuiltInId::normalize_Float1, + BuiltInName::normalize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpNormalize, + true); +constexpr const TFunction normalize_10B(BuiltInId::normalize_Float2, + BuiltInName::normalize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpNormalize, + true); +constexpr const TFunction normalize_20B(BuiltInId::normalize_Float3, + BuiltInName::normalize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpNormalize, + true); +constexpr const TFunction normalize_30B(BuiltInId::normalize_Float4, + BuiltInName::normalize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpNormalize, + true); +constexpr const TFunction faceforward_00B00B00B( + BuiltInId::faceforward_Float1_Float1_Float1, + BuiltInName::faceforward, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 3, + StaticType::Get(), + EOpFaceforward, + true); +constexpr const TFunction faceforward_10B10B10B( + BuiltInId::faceforward_Float2_Float2_Float2, + BuiltInName::faceforward, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B10B, + 3, + StaticType::Get(), + EOpFaceforward, + true); +constexpr const TFunction faceforward_20B20B20B( + BuiltInId::faceforward_Float3_Float3_Float3, + BuiltInName::faceforward, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B20B, + 3, + StaticType::Get(), + EOpFaceforward, + true); +constexpr const TFunction faceforward_30B30B30B( + BuiltInId::faceforward_Float4_Float4_Float4, + BuiltInName::faceforward, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B30B, + 3, + StaticType::Get(), + EOpFaceforward, + true); +constexpr const TFunction reflect_00B00B(BuiltInId::reflect_Float1_Float1, + BuiltInName::reflect, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 2, + StaticType::Get(), + EOpReflect, + true); +constexpr const TFunction reflect_10B10B(BuiltInId::reflect_Float2_Float2, + BuiltInName::reflect, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpReflect, + true); +constexpr const TFunction reflect_20B20B(BuiltInId::reflect_Float3_Float3, + BuiltInName::reflect, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpReflect, + true); +constexpr const TFunction reflect_30B30B(BuiltInId::reflect_Float4_Float4, + BuiltInName::reflect, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpReflect, + true); +constexpr const TFunction refract_00B00B00B( + BuiltInId::refract_Float1_Float1_Float1, + BuiltInName::refract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 3, + StaticType::Get(), + EOpRefract, + true); +constexpr const TFunction refract_10B10B00B( + BuiltInId::refract_Float2_Float2_Float1, + BuiltInName::refract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 3, + StaticType::Get(), + EOpRefract, + true); +constexpr const TFunction refract_20B20B00B( + BuiltInId::refract_Float3_Float3_Float1, + BuiltInName::refract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 3, + StaticType::Get(), + EOpRefract, + true); +constexpr const TFunction refract_30B30B00B( + BuiltInId::refract_Float4_Float4_Float1, + BuiltInName::refract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 3, + StaticType::Get(), + EOpRefract, + true); +constexpr const TFunction matrixCompMult_50B50B( + BuiltInId::matrixCompMult_Float2x2_Float2x2, + BuiltInName::matrixCompMult, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p50B50B, + 2, + StaticType::Get(), + EOpMatrixCompMult, + true); +constexpr const TFunction matrixCompMult_A0BA0B( + BuiltInId::matrixCompMult_Float3x3_Float3x3, + BuiltInName::matrixCompMult, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::pA0BA0B, + 2, + StaticType::Get(), + EOpMatrixCompMult, + true); +constexpr const TFunction matrixCompMult_F0BF0B( + BuiltInId::matrixCompMult_Float4x4_Float4x4, + BuiltInName::matrixCompMult, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::pF0BF0B, + 2, + StaticType::Get(), + EOpMatrixCompMult, + true); +constexpr const TFunction matrixCompMult_90B90B( + BuiltInId::matrixCompMult_Float2x3_Float2x3, + BuiltInName::matrixCompMult, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p90B90B, + 2, + StaticType::Get(), + EOpMatrixCompMult, + true); +constexpr const TFunction matrixCompMult_60B60B( + BuiltInId::matrixCompMult_Float3x2_Float3x2, + BuiltInName::matrixCompMult, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p60B60B, + 2, + StaticType::Get(), + EOpMatrixCompMult, + true); +constexpr const TFunction matrixCompMult_D0BD0B( + BuiltInId::matrixCompMult_Float2x4_Float2x4, + BuiltInName::matrixCompMult, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::pD0BD0B, + 2, + StaticType::Get(), + EOpMatrixCompMult, + true); +constexpr const TFunction matrixCompMult_70B70B( + BuiltInId::matrixCompMult_Float4x2_Float4x2, + BuiltInName::matrixCompMult, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p70B70B, + 2, + StaticType::Get(), + EOpMatrixCompMult, + true); +constexpr const TFunction matrixCompMult_E0BE0B( + BuiltInId::matrixCompMult_Float3x4_Float3x4, + BuiltInName::matrixCompMult, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::pE0BE0B, + 2, + StaticType::Get(), + EOpMatrixCompMult, + true); +constexpr const TFunction matrixCompMult_B0BB0B( + BuiltInId::matrixCompMult_Float4x3_Float4x3, + BuiltInName::matrixCompMult, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::pB0BB0B, + 2, + StaticType::Get(), + EOpMatrixCompMult, + true); +constexpr const TFunction outerProduct_10B10B( + BuiltInId::outerProduct_Float2_Float2, + BuiltInName::outerProduct, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpOuterProduct, + true); +constexpr const TFunction outerProduct_20B20B( + BuiltInId::outerProduct_Float3_Float3, + BuiltInName::outerProduct, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpOuterProduct, + true); +constexpr const TFunction outerProduct_30B30B( + BuiltInId::outerProduct_Float4_Float4, + BuiltInName::outerProduct, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpOuterProduct, + true); +constexpr const TFunction outerProduct_20B10B( + BuiltInId::outerProduct_Float3_Float2, + BuiltInName::outerProduct, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B10B, + 2, + StaticType::Get(), + EOpOuterProduct, + true); +constexpr const TFunction outerProduct_10B20B( + BuiltInId::outerProduct_Float2_Float3, + BuiltInName::outerProduct, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B20B, + 2, + StaticType::Get(), + EOpOuterProduct, + true); +constexpr const TFunction outerProduct_30B10B( + BuiltInId::outerProduct_Float4_Float2, + BuiltInName::outerProduct, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B10B, + 2, + StaticType::Get(), + EOpOuterProduct, + true); +constexpr const TFunction outerProduct_10B30B( + BuiltInId::outerProduct_Float2_Float4, + BuiltInName::outerProduct, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B30B, + 2, + StaticType::Get(), + EOpOuterProduct, + true); +constexpr const TFunction outerProduct_30B20B( + BuiltInId::outerProduct_Float4_Float3, + BuiltInName::outerProduct, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B20B, + 2, + StaticType::Get(), + EOpOuterProduct, + true); +constexpr const TFunction outerProduct_20B30B( + BuiltInId::outerProduct_Float3_Float4, + BuiltInName::outerProduct, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B30B, + 2, + StaticType::Get(), + EOpOuterProduct, + true); +constexpr const TFunction transpose_50B(BuiltInId::transpose_Float2x2, + BuiltInName::transpose, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p50B50B, + 1, + StaticType::Get(), + EOpTranspose, + true); +constexpr const TFunction transpose_A0B(BuiltInId::transpose_Float3x3, + BuiltInName::transpose, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::pA0BA0B, + 1, + StaticType::Get(), + EOpTranspose, + true); +constexpr const TFunction transpose_F0B(BuiltInId::transpose_Float4x4, + BuiltInName::transpose, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::pF0BF0B, + 1, + StaticType::Get(), + EOpTranspose, + true); +constexpr const TFunction transpose_60B(BuiltInId::transpose_Float3x2, + BuiltInName::transpose, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p60B60B, + 1, + StaticType::Get(), + EOpTranspose, + true); +constexpr const TFunction transpose_90B(BuiltInId::transpose_Float2x3, + BuiltInName::transpose, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p90B90B, + 1, + StaticType::Get(), + EOpTranspose, + true); +constexpr const TFunction transpose_70B(BuiltInId::transpose_Float4x2, + BuiltInName::transpose, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p70B70B, + 1, + StaticType::Get(), + EOpTranspose, + true); +constexpr const TFunction transpose_D0B(BuiltInId::transpose_Float2x4, + BuiltInName::transpose, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::pD0BD0B, + 1, + StaticType::Get(), + EOpTranspose, + true); +constexpr const TFunction transpose_B0B(BuiltInId::transpose_Float4x3, + BuiltInName::transpose, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::pB0BB0B, + 1, + StaticType::Get(), + EOpTranspose, + true); +constexpr const TFunction transpose_E0B(BuiltInId::transpose_Float3x4, + BuiltInName::transpose, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::pE0BE0B, + 1, + StaticType::Get(), + EOpTranspose, + true); +constexpr const TFunction determinant_50B( + BuiltInId::determinant_Float2x2, + BuiltInName::determinant, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p50B50B, + 1, + StaticType::Get(), + EOpDeterminant, + true); +constexpr const TFunction determinant_A0B( + BuiltInId::determinant_Float3x3, + BuiltInName::determinant, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::pA0BA0B, + 1, + StaticType::Get(), + EOpDeterminant, + true); +constexpr const TFunction determinant_F0B( + BuiltInId::determinant_Float4x4, + BuiltInName::determinant, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::pF0BF0B, + 1, + StaticType::Get(), + EOpDeterminant, + true); +constexpr const TFunction inverse_50B(BuiltInId::inverse_Float2x2, + BuiltInName::inverse, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p50B50B, + 1, + StaticType::Get(), + EOpInverse, + true); +constexpr const TFunction inverse_A0B(BuiltInId::inverse_Float3x3, + BuiltInName::inverse, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::pA0BA0B, + 1, + StaticType::Get(), + EOpInverse, + true); +constexpr const TFunction inverse_F0B(BuiltInId::inverse_Float4x4, + BuiltInName::inverse, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::pF0BF0B, + 1, + StaticType::Get(), + EOpInverse, + true); +constexpr const TFunction lessThan_10B10B(BuiltInId::lessThan_Float2_Float2, + BuiltInName::lessThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpLessThanComponentWise, + true); +constexpr const TFunction lessThan_20B20B(BuiltInId::lessThan_Float3_Float3, + BuiltInName::lessThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpLessThanComponentWise, + true); +constexpr const TFunction lessThan_30B30B(BuiltInId::lessThan_Float4_Float4, + BuiltInName::lessThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpLessThanComponentWise, + true); +constexpr const TFunction lessThan_10D10D(BuiltInId::lessThan_Int2_Int2, + BuiltInName::lessThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D10D00D00D, + 2, + StaticType::Get(), + EOpLessThanComponentWise, + true); +constexpr const TFunction lessThan_20D20D(BuiltInId::lessThan_Int3_Int3, + BuiltInName::lessThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D20D00D00D, + 2, + StaticType::Get(), + EOpLessThanComponentWise, + true); +constexpr const TFunction lessThan_30D30D(BuiltInId::lessThan_Int4_Int4, + BuiltInName::lessThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D30D00D00D, + 2, + StaticType::Get(), + EOpLessThanComponentWise, + true); +constexpr const TFunction lessThan_10E10E(BuiltInId::lessThan_UInt2_UInt2, + BuiltInName::lessThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E10E00D00D, + 2, + StaticType::Get(), + EOpLessThanComponentWise, + true); +constexpr const TFunction lessThan_20E20E(BuiltInId::lessThan_UInt3_UInt3, + BuiltInName::lessThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E20E00D00D, + 2, + StaticType::Get(), + EOpLessThanComponentWise, + true); +constexpr const TFunction lessThan_30E30E(BuiltInId::lessThan_UInt4_UInt4, + BuiltInName::lessThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E30E00D00D, + 2, + StaticType::Get(), + EOpLessThanComponentWise, + true); +constexpr const TFunction lessThanEqual_10B10B( + BuiltInId::lessThanEqual_Float2_Float2, + BuiltInName::lessThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpLessThanEqualComponentWise, + true); +constexpr const TFunction lessThanEqual_20B20B( + BuiltInId::lessThanEqual_Float3_Float3, + BuiltInName::lessThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpLessThanEqualComponentWise, + true); +constexpr const TFunction lessThanEqual_30B30B( + BuiltInId::lessThanEqual_Float4_Float4, + BuiltInName::lessThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpLessThanEqualComponentWise, + true); +constexpr const TFunction lessThanEqual_10D10D( + BuiltInId::lessThanEqual_Int2_Int2, + BuiltInName::lessThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D10D00D00D, + 2, + StaticType::Get(), + EOpLessThanEqualComponentWise, + true); +constexpr const TFunction lessThanEqual_20D20D( + BuiltInId::lessThanEqual_Int3_Int3, + BuiltInName::lessThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D20D00D00D, + 2, + StaticType::Get(), + EOpLessThanEqualComponentWise, + true); +constexpr const TFunction lessThanEqual_30D30D( + BuiltInId::lessThanEqual_Int4_Int4, + BuiltInName::lessThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D30D00D00D, + 2, + StaticType::Get(), + EOpLessThanEqualComponentWise, + true); +constexpr const TFunction lessThanEqual_10E10E( + BuiltInId::lessThanEqual_UInt2_UInt2, + BuiltInName::lessThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E10E00D00D, + 2, + StaticType::Get(), + EOpLessThanEqualComponentWise, + true); +constexpr const TFunction lessThanEqual_20E20E( + BuiltInId::lessThanEqual_UInt3_UInt3, + BuiltInName::lessThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E20E00D00D, + 2, + StaticType::Get(), + EOpLessThanEqualComponentWise, + true); +constexpr const TFunction lessThanEqual_30E30E( + BuiltInId::lessThanEqual_UInt4_UInt4, + BuiltInName::lessThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E30E00D00D, + 2, + StaticType::Get(), + EOpLessThanEqualComponentWise, + true); +constexpr const TFunction greaterThan_10B10B( + BuiltInId::greaterThan_Float2_Float2, + BuiltInName::greaterThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpGreaterThanComponentWise, + true); +constexpr const TFunction greaterThan_20B20B( + BuiltInId::greaterThan_Float3_Float3, + BuiltInName::greaterThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpGreaterThanComponentWise, + true); +constexpr const TFunction greaterThan_30B30B( + BuiltInId::greaterThan_Float4_Float4, + BuiltInName::greaterThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpGreaterThanComponentWise, + true); +constexpr const TFunction greaterThan_10D10D( + BuiltInId::greaterThan_Int2_Int2, + BuiltInName::greaterThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D10D00D00D, + 2, + StaticType::Get(), + EOpGreaterThanComponentWise, + true); +constexpr const TFunction greaterThan_20D20D( + BuiltInId::greaterThan_Int3_Int3, + BuiltInName::greaterThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D20D00D00D, + 2, + StaticType::Get(), + EOpGreaterThanComponentWise, + true); +constexpr const TFunction greaterThan_30D30D( + BuiltInId::greaterThan_Int4_Int4, + BuiltInName::greaterThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D30D00D00D, + 2, + StaticType::Get(), + EOpGreaterThanComponentWise, + true); +constexpr const TFunction greaterThan_10E10E( + BuiltInId::greaterThan_UInt2_UInt2, + BuiltInName::greaterThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E10E00D00D, + 2, + StaticType::Get(), + EOpGreaterThanComponentWise, + true); +constexpr const TFunction greaterThan_20E20E( + BuiltInId::greaterThan_UInt3_UInt3, + BuiltInName::greaterThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E20E00D00D, + 2, + StaticType::Get(), + EOpGreaterThanComponentWise, + true); +constexpr const TFunction greaterThan_30E30E( + BuiltInId::greaterThan_UInt4_UInt4, + BuiltInName::greaterThan, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E30E00D00D, + 2, + StaticType::Get(), + EOpGreaterThanComponentWise, + true); +constexpr const TFunction greaterThanEqual_10B10B( + BuiltInId::greaterThanEqual_Float2_Float2, + BuiltInName::greaterThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpGreaterThanEqualComponentWise, + true); +constexpr const TFunction greaterThanEqual_20B20B( + BuiltInId::greaterThanEqual_Float3_Float3, + BuiltInName::greaterThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpGreaterThanEqualComponentWise, + true); +constexpr const TFunction greaterThanEqual_30B30B( + BuiltInId::greaterThanEqual_Float4_Float4, + BuiltInName::greaterThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpGreaterThanEqualComponentWise, + true); +constexpr const TFunction greaterThanEqual_10D10D( + BuiltInId::greaterThanEqual_Int2_Int2, + BuiltInName::greaterThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D10D00D00D, + 2, + StaticType::Get(), + EOpGreaterThanEqualComponentWise, + true); +constexpr const TFunction greaterThanEqual_20D20D( + BuiltInId::greaterThanEqual_Int3_Int3, + BuiltInName::greaterThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D20D00D00D, + 2, + StaticType::Get(), + EOpGreaterThanEqualComponentWise, + true); +constexpr const TFunction greaterThanEqual_30D30D( + BuiltInId::greaterThanEqual_Int4_Int4, + BuiltInName::greaterThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D30D00D00D, + 2, + StaticType::Get(), + EOpGreaterThanEqualComponentWise, + true); +constexpr const TFunction greaterThanEqual_10E10E( + BuiltInId::greaterThanEqual_UInt2_UInt2, + BuiltInName::greaterThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E10E00D00D, + 2, + StaticType::Get(), + EOpGreaterThanEqualComponentWise, + true); +constexpr const TFunction greaterThanEqual_20E20E( + BuiltInId::greaterThanEqual_UInt3_UInt3, + BuiltInName::greaterThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E20E00D00D, + 2, + StaticType::Get(), + EOpGreaterThanEqualComponentWise, + true); +constexpr const TFunction greaterThanEqual_30E30E( + BuiltInId::greaterThanEqual_UInt4_UInt4, + BuiltInName::greaterThanEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E30E00D00D, + 2, + StaticType::Get(), + EOpGreaterThanEqualComponentWise, + true); +constexpr const TFunction equal_10B10B(BuiltInId::equal_Float2_Float2, + BuiltInName::equal, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpEqualComponentWise, + true); +constexpr const TFunction equal_20B20B(BuiltInId::equal_Float3_Float3, + BuiltInName::equal, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpEqualComponentWise, + true); +constexpr const TFunction equal_30B30B(BuiltInId::equal_Float4_Float4, + BuiltInName::equal, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpEqualComponentWise, + true); +constexpr const TFunction equal_10D10D(BuiltInId::equal_Int2_Int2, + BuiltInName::equal, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D10D00D00D, + 2, + StaticType::Get(), + EOpEqualComponentWise, + true); +constexpr const TFunction equal_20D20D(BuiltInId::equal_Int3_Int3, + BuiltInName::equal, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D20D00D00D, + 2, + StaticType::Get(), + EOpEqualComponentWise, + true); +constexpr const TFunction equal_30D30D(BuiltInId::equal_Int4_Int4, + BuiltInName::equal, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D30D00D00D, + 2, + StaticType::Get(), + EOpEqualComponentWise, + true); +constexpr const TFunction equal_10E10E(BuiltInId::equal_UInt2_UInt2, + BuiltInName::equal, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E10E00D00D, + 2, + StaticType::Get(), + EOpEqualComponentWise, + true); +constexpr const TFunction equal_20E20E(BuiltInId::equal_UInt3_UInt3, + BuiltInName::equal, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E20E00D00D, + 2, + StaticType::Get(), + EOpEqualComponentWise, + true); +constexpr const TFunction equal_30E30E(BuiltInId::equal_UInt4_UInt4, + BuiltInName::equal, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E30E00D00D, + 2, + StaticType::Get(), + EOpEqualComponentWise, + true); +constexpr const TFunction equal_10F10F(BuiltInId::equal_Bool2_Bool2, + BuiltInName::equal, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10F10F10F, + 2, + StaticType::Get(), + EOpEqualComponentWise, + true); +constexpr const TFunction equal_20F20F(BuiltInId::equal_Bool3_Bool3, + BuiltInName::equal, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20F20F20F, + 2, + StaticType::Get(), + EOpEqualComponentWise, + true); +constexpr const TFunction equal_30F30F(BuiltInId::equal_Bool4_Bool4, + BuiltInName::equal, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30F30F30F, + 2, + StaticType::Get(), + EOpEqualComponentWise, + true); +constexpr const TFunction notEqual_10B10B(BuiltInId::notEqual_Float2_Float2, + BuiltInName::notEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpNotEqualComponentWise, + true); +constexpr const TFunction notEqual_20B20B(BuiltInId::notEqual_Float3_Float3, + BuiltInName::notEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B20B00B, + 2, + StaticType::Get(), + EOpNotEqualComponentWise, + true); +constexpr const TFunction notEqual_30B30B(BuiltInId::notEqual_Float4_Float4, + BuiltInName::notEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B30B00B, + 2, + StaticType::Get(), + EOpNotEqualComponentWise, + true); +constexpr const TFunction notEqual_10D10D(BuiltInId::notEqual_Int2_Int2, + BuiltInName::notEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D10D00D00D, + 2, + StaticType::Get(), + EOpNotEqualComponentWise, + true); +constexpr const TFunction notEqual_20D20D(BuiltInId::notEqual_Int3_Int3, + BuiltInName::notEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D20D00D00D, + 2, + StaticType::Get(), + EOpNotEqualComponentWise, + true); +constexpr const TFunction notEqual_30D30D(BuiltInId::notEqual_Int4_Int4, + BuiltInName::notEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D30D00D00D, + 2, + StaticType::Get(), + EOpNotEqualComponentWise, + true); +constexpr const TFunction notEqual_10E10E(BuiltInId::notEqual_UInt2_UInt2, + BuiltInName::notEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E10E00D00D, + 2, + StaticType::Get(), + EOpNotEqualComponentWise, + true); +constexpr const TFunction notEqual_20E20E(BuiltInId::notEqual_UInt3_UInt3, + BuiltInName::notEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E20E00D00D, + 2, + StaticType::Get(), + EOpNotEqualComponentWise, + true); +constexpr const TFunction notEqual_30E30E(BuiltInId::notEqual_UInt4_UInt4, + BuiltInName::notEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E30E00D00D, + 2, + StaticType::Get(), + EOpNotEqualComponentWise, + true); +constexpr const TFunction notEqual_10F10F(BuiltInId::notEqual_Bool2_Bool2, + BuiltInName::notEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10F10F10F, + 2, + StaticType::Get(), + EOpNotEqualComponentWise, + true); +constexpr const TFunction notEqual_20F20F(BuiltInId::notEqual_Bool3_Bool3, + BuiltInName::notEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20F20F20F, + 2, + StaticType::Get(), + EOpNotEqualComponentWise, + true); +constexpr const TFunction notEqual_30F30F(BuiltInId::notEqual_Bool4_Bool4, + BuiltInName::notEqual, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30F30F30F, + 2, + StaticType::Get(), + EOpNotEqualComponentWise, + true); +constexpr const TFunction any_10F(BuiltInId::any_Bool2, + BuiltInName::any, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10F10F10F, + 1, + StaticType::Get(), + EOpAny, + true); +constexpr const TFunction any_20F(BuiltInId::any_Bool3, + BuiltInName::any, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20F20F20F, + 1, + StaticType::Get(), + EOpAny, + true); +constexpr const TFunction any_30F(BuiltInId::any_Bool4, + BuiltInName::any, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30F30F30F, + 1, + StaticType::Get(), + EOpAny, + true); +constexpr const TFunction all_10F(BuiltInId::all_Bool2, + BuiltInName::all, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10F10F10F, + 1, + StaticType::Get(), + EOpAll, + true); +constexpr const TFunction all_20F(BuiltInId::all_Bool3, + BuiltInName::all, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20F20F20F, + 1, + StaticType::Get(), + EOpAll, + true); +constexpr const TFunction all_30F(BuiltInId::all_Bool4, + BuiltInName::all, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30F30F30F, + 1, + StaticType::Get(), + EOpAll, + true); +constexpr const TFunction notFunc_10F(BuiltInId::notFunc_Bool2, + BuiltInName::notFunc, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10F10F10F, + 1, + StaticType::Get(), + EOpNotComponentWise, + true); +constexpr const TFunction notFunc_20F(BuiltInId::notFunc_Bool3, + BuiltInName::notFunc, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20F20F20F, + 1, + StaticType::Get(), + EOpNotComponentWise, + true); +constexpr const TFunction notFunc_30F(BuiltInId::notFunc_Bool4, + BuiltInName::notFunc, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30F30F30F, + 1, + StaticType::Get(), + EOpNotComponentWise, + true); +constexpr const TFunction bitfieldExtract_00D00D00D( + BuiltInId::bitfieldExtract_Int1_Int1_Int1, + BuiltInName::bitfieldExtract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00D00D00D00D, + 3, + StaticType::Get(), + EOpBitfieldExtract, + true); +constexpr const TFunction bitfieldExtract_10D00D00D( + BuiltInId::bitfieldExtract_Int2_Int1_Int1, + BuiltInName::bitfieldExtract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D00D00D, + 3, + StaticType::Get(), + EOpBitfieldExtract, + true); +constexpr const TFunction bitfieldExtract_20D00D00D( + BuiltInId::bitfieldExtract_Int3_Int1_Int1, + BuiltInName::bitfieldExtract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D00D00D, + 3, + StaticType::Get(), + EOpBitfieldExtract, + true); +constexpr const TFunction bitfieldExtract_30D00D00D( + BuiltInId::bitfieldExtract_Int4_Int1_Int1, + BuiltInName::bitfieldExtract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D00D00D, + 3, + StaticType::Get(), + EOpBitfieldExtract, + true); +constexpr const TFunction bitfieldExtract_00E00D00D( + BuiltInId::bitfieldExtract_UInt1_Int1_Int1, + BuiltInName::bitfieldExtract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00D00D, + 3, + StaticType::Get(), + EOpBitfieldExtract, + true); +constexpr const TFunction bitfieldExtract_10E00D00D( + BuiltInId::bitfieldExtract_UInt2_Int1_Int1, + BuiltInName::bitfieldExtract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E00D00D, + 3, + StaticType::Get(), + EOpBitfieldExtract, + true); +constexpr const TFunction bitfieldExtract_20E00D00D( + BuiltInId::bitfieldExtract_UInt3_Int1_Int1, + BuiltInName::bitfieldExtract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E00D00D, + 3, + StaticType::Get(), + EOpBitfieldExtract, + true); +constexpr const TFunction bitfieldExtract_30E00D00D( + BuiltInId::bitfieldExtract_UInt4_Int1_Int1, + BuiltInName::bitfieldExtract, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E00D00D, + 3, + StaticType::Get(), + EOpBitfieldExtract, + true); +constexpr const TFunction bitfieldInsert_00D00D00D00D( + BuiltInId::bitfieldInsert_Int1_Int1_Int1_Int1, + BuiltInName::bitfieldInsert, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00D00D00D00D, + 4, + StaticType::Get(), + EOpBitfieldInsert, + true); +constexpr const TFunction bitfieldInsert_10D10D00D00D( + BuiltInId::bitfieldInsert_Int2_Int2_Int1_Int1, + BuiltInName::bitfieldInsert, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D10D00D00D, + 4, + StaticType::Get(), + EOpBitfieldInsert, + true); +constexpr const TFunction bitfieldInsert_20D20D00D00D( + BuiltInId::bitfieldInsert_Int3_Int3_Int1_Int1, + BuiltInName::bitfieldInsert, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D20D00D00D, + 4, + StaticType::Get(), + EOpBitfieldInsert, + true); +constexpr const TFunction bitfieldInsert_30D30D00D00D( + BuiltInId::bitfieldInsert_Int4_Int4_Int1_Int1, + BuiltInName::bitfieldInsert, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D30D00D00D, + 4, + StaticType::Get(), + EOpBitfieldInsert, + true); +constexpr const TFunction bitfieldInsert_00E00E00D00D( + BuiltInId::bitfieldInsert_UInt1_UInt1_Int1_Int1, + BuiltInName::bitfieldInsert, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00E00D00D, + 4, + StaticType::Get(), + EOpBitfieldInsert, + true); +constexpr const TFunction bitfieldInsert_10E10E00D00D( + BuiltInId::bitfieldInsert_UInt2_UInt2_Int1_Int1, + BuiltInName::bitfieldInsert, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E10E00D00D, + 4, + StaticType::Get(), + EOpBitfieldInsert, + true); +constexpr const TFunction bitfieldInsert_20E20E00D00D( + BuiltInId::bitfieldInsert_UInt3_UInt3_Int1_Int1, + BuiltInName::bitfieldInsert, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E20E00D00D, + 4, + StaticType::Get(), + EOpBitfieldInsert, + true); +constexpr const TFunction bitfieldInsert_30E30E00D00D( + BuiltInId::bitfieldInsert_UInt4_UInt4_Int1_Int1, + BuiltInName::bitfieldInsert, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E30E00D00D, + 4, + StaticType::Get(), + EOpBitfieldInsert, + true); +constexpr const TFunction bitfieldReverse_00D( + BuiltInId::bitfieldReverse_Int1, + BuiltInName::bitfieldReverse, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00D00D00D00D, + 1, + StaticType::Get(), + EOpBitfieldReverse, + true); +constexpr const TFunction bitfieldReverse_10D( + BuiltInId::bitfieldReverse_Int2, + BuiltInName::bitfieldReverse, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D00D00D, + 1, + StaticType::Get(), + EOpBitfieldReverse, + true); +constexpr const TFunction bitfieldReverse_20D( + BuiltInId::bitfieldReverse_Int3, + BuiltInName::bitfieldReverse, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D00D00D, + 1, + StaticType::Get(), + EOpBitfieldReverse, + true); +constexpr const TFunction bitfieldReverse_30D( + BuiltInId::bitfieldReverse_Int4, + BuiltInName::bitfieldReverse, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D00D00D, + 1, + StaticType::Get(), + EOpBitfieldReverse, + true); +constexpr const TFunction bitfieldReverse_00E( + BuiltInId::bitfieldReverse_UInt1, + BuiltInName::bitfieldReverse, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00D00D, + 1, + StaticType::Get(), + EOpBitfieldReverse, + true); +constexpr const TFunction bitfieldReverse_10E( + BuiltInId::bitfieldReverse_UInt2, + BuiltInName::bitfieldReverse, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E00D00D, + 1, + StaticType::Get(), + EOpBitfieldReverse, + true); +constexpr const TFunction bitfieldReverse_20E( + BuiltInId::bitfieldReverse_UInt3, + BuiltInName::bitfieldReverse, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E00D00D, + 1, + StaticType::Get(), + EOpBitfieldReverse, + true); +constexpr const TFunction bitfieldReverse_30E( + BuiltInId::bitfieldReverse_UInt4, + BuiltInName::bitfieldReverse, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E00D00D, + 1, + StaticType::Get(), + EOpBitfieldReverse, + true); +constexpr const TFunction bitCount_00D(BuiltInId::bitCount_Int1, + BuiltInName::bitCount, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00D00D00D00D, + 1, + StaticType::Get(), + EOpBitCount, + true); +constexpr const TFunction bitCount_10D(BuiltInId::bitCount_Int2, + BuiltInName::bitCount, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D00D00D, + 1, + StaticType::Get(), + EOpBitCount, + true); +constexpr const TFunction bitCount_20D(BuiltInId::bitCount_Int3, + BuiltInName::bitCount, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D00D00D, + 1, + StaticType::Get(), + EOpBitCount, + true); +constexpr const TFunction bitCount_30D(BuiltInId::bitCount_Int4, + BuiltInName::bitCount, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D00D00D, + 1, + StaticType::Get(), + EOpBitCount, + true); +constexpr const TFunction bitCount_00E(BuiltInId::bitCount_UInt1, + BuiltInName::bitCount, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00D00D, + 1, + StaticType::Get(), + EOpBitCount, + true); +constexpr const TFunction bitCount_10E(BuiltInId::bitCount_UInt2, + BuiltInName::bitCount, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E00D00D, + 1, + StaticType::Get(), + EOpBitCount, + true); +constexpr const TFunction bitCount_20E(BuiltInId::bitCount_UInt3, + BuiltInName::bitCount, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E00D00D, + 1, + StaticType::Get(), + EOpBitCount, + true); +constexpr const TFunction bitCount_30E(BuiltInId::bitCount_UInt4, + BuiltInName::bitCount, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E00D00D, + 1, + StaticType::Get(), + EOpBitCount, + true); +constexpr const TFunction findLSB_00D(BuiltInId::findLSB_Int1, + BuiltInName::findLSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00D00D00D00D, + 1, + StaticType::Get(), + EOpFindLSB, + true); +constexpr const TFunction findLSB_10D(BuiltInId::findLSB_Int2, + BuiltInName::findLSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D00D00D, + 1, + StaticType::Get(), + EOpFindLSB, + true); +constexpr const TFunction findLSB_20D(BuiltInId::findLSB_Int3, + BuiltInName::findLSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D00D00D, + 1, + StaticType::Get(), + EOpFindLSB, + true); +constexpr const TFunction findLSB_30D(BuiltInId::findLSB_Int4, + BuiltInName::findLSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D00D00D, + 1, + StaticType::Get(), + EOpFindLSB, + true); +constexpr const TFunction findLSB_00E(BuiltInId::findLSB_UInt1, + BuiltInName::findLSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00D00D, + 1, + StaticType::Get(), + EOpFindLSB, + true); +constexpr const TFunction findLSB_10E(BuiltInId::findLSB_UInt2, + BuiltInName::findLSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E00D00D, + 1, + StaticType::Get(), + EOpFindLSB, + true); +constexpr const TFunction findLSB_20E(BuiltInId::findLSB_UInt3, + BuiltInName::findLSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E00D00D, + 1, + StaticType::Get(), + EOpFindLSB, + true); +constexpr const TFunction findLSB_30E(BuiltInId::findLSB_UInt4, + BuiltInName::findLSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E00D00D, + 1, + StaticType::Get(), + EOpFindLSB, + true); +constexpr const TFunction findMSB_00D(BuiltInId::findMSB_Int1, + BuiltInName::findMSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00D00D00D00D, + 1, + StaticType::Get(), + EOpFindMSB, + true); +constexpr const TFunction findMSB_10D(BuiltInId::findMSB_Int2, + BuiltInName::findMSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D00D00D, + 1, + StaticType::Get(), + EOpFindMSB, + true); +constexpr const TFunction findMSB_20D(BuiltInId::findMSB_Int3, + BuiltInName::findMSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D00D00D, + 1, + StaticType::Get(), + EOpFindMSB, + true); +constexpr const TFunction findMSB_30D(BuiltInId::findMSB_Int4, + BuiltInName::findMSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D00D00D, + 1, + StaticType::Get(), + EOpFindMSB, + true); +constexpr const TFunction findMSB_00E(BuiltInId::findMSB_UInt1, + BuiltInName::findMSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00D00D, + 1, + StaticType::Get(), + EOpFindMSB, + true); +constexpr const TFunction findMSB_10E(BuiltInId::findMSB_UInt2, + BuiltInName::findMSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E00D00D, + 1, + StaticType::Get(), + EOpFindMSB, + true); +constexpr const TFunction findMSB_20E(BuiltInId::findMSB_UInt3, + BuiltInName::findMSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E00D00D, + 1, + StaticType::Get(), + EOpFindMSB, + true); +constexpr const TFunction findMSB_30E(BuiltInId::findMSB_UInt4, + BuiltInName::findMSB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E00D00D, + 1, + StaticType::Get(), + EOpFindMSB, + true); +constexpr const TFunction uaddCarry_00E00E00E( + BuiltInId::uaddCarry_UInt1_UInt1_UInt1, + BuiltInName::uaddCarry, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00E_o_00E_o_00E, + 3, + StaticType::Get(), + EOpUaddCarry, + false); +constexpr const TFunction uaddCarry_10E10E10E( + BuiltInId::uaddCarry_UInt2_UInt2_UInt2, + BuiltInName::uaddCarry, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E10E_o_10E_o_10E, + 3, + StaticType::Get(), + EOpUaddCarry, + false); +constexpr const TFunction uaddCarry_20E20E20E( + BuiltInId::uaddCarry_UInt3_UInt3_UInt3, + BuiltInName::uaddCarry, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E20E_o_20E_o_20E, + 3, + StaticType::Get(), + EOpUaddCarry, + false); +constexpr const TFunction uaddCarry_30E30E30E( + BuiltInId::uaddCarry_UInt4_UInt4_UInt4, + BuiltInName::uaddCarry, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E30E_o_30E_o_30E, + 3, + StaticType::Get(), + EOpUaddCarry, + false); +constexpr const TFunction usubBorrow_00E00E00E( + BuiltInId::usubBorrow_UInt1_UInt1_UInt1, + BuiltInName::usubBorrow, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00E_o_00E_o_00E, + 3, + StaticType::Get(), + EOpUsubBorrow, + false); +constexpr const TFunction usubBorrow_10E10E10E( + BuiltInId::usubBorrow_UInt2_UInt2_UInt2, + BuiltInName::usubBorrow, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E10E_o_10E_o_10E, + 3, + StaticType::Get(), + EOpUsubBorrow, + false); +constexpr const TFunction usubBorrow_20E20E20E( + BuiltInId::usubBorrow_UInt3_UInt3_UInt3, + BuiltInName::usubBorrow, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E20E_o_20E_o_20E, + 3, + StaticType::Get(), + EOpUsubBorrow, + false); +constexpr const TFunction usubBorrow_30E30E30E( + BuiltInId::usubBorrow_UInt4_UInt4_UInt4, + BuiltInName::usubBorrow, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E30E_o_30E_o_30E, + 3, + StaticType::Get(), + EOpUsubBorrow, + false); +constexpr const TFunction umulExtended_00E00E00E00E( + BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1, + BuiltInName::umulExtended, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00E00E_o_00E_o_00E, + 4, + StaticType::Get(), + EOpUmulExtended, + false); +constexpr const TFunction umulExtended_10E10E10E10E( + BuiltInId::umulExtended_UInt2_UInt2_UInt2_UInt2, + BuiltInName::umulExtended, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10E10E_o_10E_o_10E, + 4, + StaticType::Get(), + EOpUmulExtended, + false); +constexpr const TFunction umulExtended_20E20E20E20E( + BuiltInId::umulExtended_UInt3_UInt3_UInt3_UInt3, + BuiltInName::umulExtended, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20E20E_o_20E_o_20E, + 4, + StaticType::Get(), + EOpUmulExtended, + false); +constexpr const TFunction umulExtended_30E30E30E30E( + BuiltInId::umulExtended_UInt4_UInt4_UInt4_UInt4, + BuiltInName::umulExtended, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30E30E_o_30E_o_30E, + 4, + StaticType::Get(), + EOpUmulExtended, + false); +constexpr const TFunction imulExtended_00D00D00D00D( + BuiltInId::imulExtended_Int1_Int1_Int1_Int1, + BuiltInName::imulExtended, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00D00D_o_00D_o_00D, + 4, + StaticType::Get(), + EOpImulExtended, + false); +constexpr const TFunction imulExtended_10D10D10D10D( + BuiltInId::imulExtended_Int2_Int2_Int2_Int2, + BuiltInName::imulExtended, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10D10D_o_10D_o_10D, + 4, + StaticType::Get(), + EOpImulExtended, + false); +constexpr const TFunction imulExtended_20D20D20D20D( + BuiltInId::imulExtended_Int3_Int3_Int3_Int3, + BuiltInName::imulExtended, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20D20D_o_20D_o_20D, + 4, + StaticType::Get(), + EOpImulExtended, + false); +constexpr const TFunction imulExtended_30D30D30D30D( + BuiltInId::imulExtended_Int4_Int4_Int4_Int4, + BuiltInName::imulExtended, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30D30D_o_30D_o_30D, + 4, + StaticType::Get(), + EOpImulExtended, + false); +constexpr const TFunction texture2D_00I10B( + BuiltInId::texture2D_Sampler2D1_Float2, + BuiltInName::texture2D, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B00B10D, + 2, + StaticType::Get(), + EOpTexture2D, + false); +constexpr const TFunction texture2DProj_00I20B( + BuiltInId::texture2DProj_Sampler2D1_Float3, + BuiltInName::texture2DProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I20B00B10D, + 2, + StaticType::Get(), + EOpTexture2DProj, + false); +constexpr const TFunction texture2DProj_00I30B( + BuiltInId::texture2DProj_Sampler2D1_Float4, + BuiltInName::texture2DProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I30B00B10D, + 2, + StaticType::Get(), + EOpTexture2DProj, + false); +constexpr const TFunction textureCube_00K20B( + BuiltInId::textureCube_SamplerCube1_Float3, + BuiltInName::textureCube, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00K20B00B, + 2, + StaticType::Get(), + EOpTextureCube, + false); +constexpr const TFunction texture3D_00J20B( + BuiltInId::texture3D_Sampler3D1_Float3, + BuiltInName::texture3D, + std::array{{TExtension::OES_texture_3D}}, + BuiltInParameters::p00J20B00B20D, + 2, + StaticType::Get(), + EOpTexture3D, + false); +constexpr const TFunction texture3DProj_00J30B( + BuiltInId::texture3DProj_Sampler3D1_Float4, + BuiltInName::texture3DProj, + std::array{{TExtension::OES_texture_3D}}, + BuiltInParameters::p00J30B00B20D, + 2, + StaticType::Get(), + EOpTexture3DProj, + false); +constexpr const TFunction shadow2DEXT_00d20B( + BuiltInId::shadow2DEXT_Sampler2DShadow1_Float3, + BuiltInName::shadow2DEXT, + std::array{{TExtension::EXT_shadow_samplers}}, + BuiltInParameters::p00d20B00B10D, + 2, + StaticType::Get(), + EOpShadow2DEXT, + false); +constexpr const TFunction shadow2DProjEXT_00d30B( + BuiltInId::shadow2DProjEXT_Sampler2DShadow1_Float4, + BuiltInName::shadow2DProjEXT, + std::array{{TExtension::EXT_shadow_samplers}}, + BuiltInParameters::p00d30B00B10D, + 2, + StaticType::Get(), + EOpShadow2DProjEXT, + false); +constexpr const TFunction texture2D_00M10B( + BuiltInId::texture2D_SamplerExternalOES1_Float2, + BuiltInName::texture2D, + std::array{ + {TExtension::OES_EGL_image_external, TExtension::NV_EGL_stream_consumer_external}}, + BuiltInParameters::p00M10B00B, + 2, + StaticType::Get(), + EOpTexture2D, + false); +constexpr const TFunction texture2DProj_00M20B( + BuiltInId::texture2DProj_SamplerExternalOES1_Float3, + BuiltInName::texture2DProj, + std::array{ + {TExtension::OES_EGL_image_external, TExtension::NV_EGL_stream_consumer_external}}, + BuiltInParameters::p00M20B00B, + 2, + StaticType::Get(), + EOpTexture2DProj, + false); +constexpr const TFunction texture2DProj_00M30B( + BuiltInId::texture2DProj_SamplerExternalOES1_Float4, + BuiltInName::texture2DProj, + std::array{ + {TExtension::OES_EGL_image_external, TExtension::NV_EGL_stream_consumer_external}}, + BuiltInParameters::p00M30B00B, + 2, + StaticType::Get(), + EOpTexture2DProj, + false); +constexpr const TFunction texture2DRect_00O10B( + BuiltInId::texture2DRect_Sampler2DRect1_Float2, + BuiltInName::texture2DRect, + std::array{{TExtension::ARB_texture_rectangle}}, + BuiltInParameters::p00O10B, + 2, + StaticType::Get(), + EOpTexture2DRect, + false); +constexpr const TFunction texture2DRectProj_00O20B( + BuiltInId::texture2DRectProj_Sampler2DRect1_Float3, + BuiltInName::texture2DRectProj, + std::array{{TExtension::ARB_texture_rectangle}}, + BuiltInParameters::p00O20B, + 2, + StaticType::Get(), + EOpTexture2DRectProj, + false); +constexpr const TFunction texture2DRectProj_00O30B( + BuiltInId::texture2DRectProj_Sampler2DRect1_Float4, + BuiltInName::texture2DRectProj, + std::array{{TExtension::ARB_texture_rectangle}}, + BuiltInParameters::p00O30B, + 2, + StaticType::Get(), + EOpTexture2DRectProj, + false); +constexpr const TFunction texture2DGradEXT_00I10B10B10B( + BuiltInId::texture2DGradEXT_Sampler2D1_Float2_Float2_Float2, + BuiltInName::texture2DGradEXT, + std::array{{TExtension::EXT_shader_texture_lod}}, + BuiltInParameters::p00I10B10B10B10D, + 4, + StaticType::Get(), + EOpTexture2DGradEXT, + false); +constexpr const TFunction texture2DProjGradEXT_00I20B10B10B( + BuiltInId::texture2DProjGradEXT_Sampler2D1_Float3_Float2_Float2, + BuiltInName::texture2DProjGradEXT, + std::array{{TExtension::EXT_shader_texture_lod}}, + BuiltInParameters::p00I20B10B10B10D, + 4, + StaticType::Get(), + EOpTexture2DProjGradEXT, + false); +constexpr const TFunction texture2DProjGradEXT_00I30B10B10B( + BuiltInId::texture2DProjGradEXT_Sampler2D1_Float4_Float2_Float2, + BuiltInName::texture2DProjGradEXT, + std::array{{TExtension::EXT_shader_texture_lod}}, + BuiltInParameters::p00I30B10B10B10D, + 4, + StaticType::Get(), + EOpTexture2DProjGradEXT, + false); +constexpr const TFunction textureCubeGradEXT_00K20B20B20B( + BuiltInId::textureCubeGradEXT_SamplerCube1_Float3_Float3_Float3, + BuiltInName::textureCubeGradEXT, + std::array{{TExtension::EXT_shader_texture_lod}}, + BuiltInParameters::p00K20B20B20B, + 4, + StaticType::Get(), + EOpTextureCubeGradEXT, + false); +constexpr const TFunction textureVideoWEBGL_00y10B( + BuiltInId::textureVideoWEBGL_SamplerVideoWEBGL1_Float2, + BuiltInName::textureVideoWEBGL, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00y10B, + 2, + StaticType::Get(), + EOpTextureVideoWEBGL, + false); +constexpr const TFunction texture2D_00I10B00B( + BuiltInId::texture2D_Sampler2D1_Float2_Float1, + BuiltInName::texture2D, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B00B10D, + 3, + StaticType::Get(), + EOpTexture2DBias, + false); +constexpr const TFunction texture2DProj_00I20B00B( + BuiltInId::texture2DProj_Sampler2D1_Float3_Float1, + BuiltInName::texture2DProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I20B00B10D, + 3, + StaticType::Get(), + EOpTexture2DProjBias, + false); +constexpr const TFunction texture2DProj_00I30B00B( + BuiltInId::texture2DProj_Sampler2D1_Float4_Float1, + BuiltInName::texture2DProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I30B00B10D, + 3, + StaticType::Get(), + EOpTexture2DProjBias, + false); +constexpr const TFunction textureCube_00K20B00B( + BuiltInId::textureCube_SamplerCube1_Float3_Float1, + BuiltInName::textureCube, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00K20B00B, + 3, + StaticType::Get(), + EOpTextureCubeBias, + false); +constexpr const TFunction texture3D_00J20B00B( + BuiltInId::texture3D_Sampler3D1_Float3_Float1, + BuiltInName::texture3D, + std::array{{TExtension::OES_texture_3D}}, + BuiltInParameters::p00J20B00B20D, + 3, + StaticType::Get(), + EOpTexture3DBias, + false); +constexpr const TFunction texture3DProj_00J30B00B( + BuiltInId::texture3DProj_Sampler3D1_Float4_Float1, + BuiltInName::texture3DProj, + std::array{{TExtension::OES_texture_3D}}, + BuiltInParameters::p00J30B00B20D, + 3, + StaticType::Get(), + EOpTexture3DProjBias, + false); +constexpr const TFunction texture3DLod_00J20B00B( + BuiltInId::texture3DLod_Sampler3D1_Float3_Float1, + BuiltInName::texture3DLod, + std::array{{TExtension::OES_texture_3D}}, + BuiltInParameters::p00J20B00B20D, + 3, + StaticType::Get(), + EOpTexture3DLod, + false); +constexpr const TFunction texture3DProjLod_00J30B00B( + BuiltInId::texture3DProjLod_Sampler3D1_Float4_Float1, + BuiltInName::texture3DProjLod, + std::array{{TExtension::OES_texture_3D}}, + BuiltInParameters::p00J30B00B20D, + 3, + StaticType::Get(), + EOpTexture3DProjLod, + false); +constexpr const TFunction texture2DLod_00I10B00B( + BuiltInId::texture2DLod_Sampler2D1_Float2_Float1, + BuiltInName::texture2DLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B00B10D, + 3, + StaticType::Get(), + EOpTexture2DLodVS, + false); +constexpr const TFunction texture2DProjLod_00I20B00B( + BuiltInId::texture2DProjLod_Sampler2D1_Float3_Float1, + BuiltInName::texture2DProjLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I20B00B10D, + 3, + StaticType::Get(), + EOpTexture2DProjLodVS, + false); +constexpr const TFunction texture2DProjLod_00I30B00B( + BuiltInId::texture2DProjLod_Sampler2D1_Float4_Float1, + BuiltInName::texture2DProjLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I30B00B10D, + 3, + StaticType::Get(), + EOpTexture2DProjLodVS, + false); +constexpr const TFunction textureCubeLod_00K20B00B( + BuiltInId::textureCubeLod_SamplerCube1_Float3_Float1, + BuiltInName::textureCubeLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00K20B00B, + 3, + StaticType::Get(), + EOpTextureCubeLodVS, + false); +constexpr const TFunction texture2DLodEXT_00I10B00B( + BuiltInId::texture2DLodEXT_Sampler2D1_Float2_Float1, + BuiltInName::texture2DLodEXT, + std::array{{TExtension::EXT_shader_texture_lod}}, + BuiltInParameters::p00I10B00B10D, + 3, + StaticType::Get(), + EOpTexture2DLodEXTFS, + false); +constexpr const TFunction texture2DProjLodEXT_00I20B00B( + BuiltInId::texture2DProjLodEXT_Sampler2D1_Float3_Float1, + BuiltInName::texture2DProjLodEXT, + std::array{{TExtension::EXT_shader_texture_lod}}, + BuiltInParameters::p00I20B00B10D, + 3, + StaticType::Get(), + EOpTexture2DProjLodEXTFS, + false); +constexpr const TFunction texture2DProjLodEXT_00I30B00B( + BuiltInId::texture2DProjLodEXT_Sampler2D1_Float4_Float1, + BuiltInName::texture2DProjLodEXT, + std::array{{TExtension::EXT_shader_texture_lod}}, + BuiltInParameters::p00I30B00B10D, + 3, + StaticType::Get(), + EOpTexture2DProjLodEXTFS, + false); +constexpr const TFunction textureCubeLodEXT_00K20B00B( + BuiltInId::textureCubeLodEXT_SamplerCube1_Float3_Float1, + BuiltInName::textureCubeLodEXT, + std::array{{TExtension::EXT_shader_texture_lod}}, + BuiltInParameters::p00K20B00B, + 3, + StaticType::Get(), + EOpTextureCubeLodEXTFS, + false); +constexpr const TFunction texture_00I10B(BuiltInId::texture_Sampler2D1_Float2, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B00B10D, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00R10B(BuiltInId::texture_ISampler2D1_Float2, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10B00B10D, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00X10B(BuiltInId::texture_USampler2D1_Float2, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10B00B10D, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00J20B(BuiltInId::texture_Sampler3D1_Float3, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J20B00B20D, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00S20B(BuiltInId::texture_ISampler3D1_Float3, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S20B00B20D, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00Y20B(BuiltInId::texture_USampler3D1_Float3, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y20B00B20D, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00K20B(BuiltInId::texture_SamplerCube1_Float3, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00K20B00B, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00T20B(BuiltInId::texture_ISamplerCube1_Float3, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00T20B00B, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00Z20B(BuiltInId::texture_USamplerCube1_Float3, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Z20B00B, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00L20B(BuiltInId::texture_Sampler2DArray1_Float3, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20B00B10D, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00U20B(BuiltInId::texture_ISampler2DArray1_Float3, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20B00B10D, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00a20B(BuiltInId::texture_USampler2DArray1_Float3, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20B00B10D, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00d20B(BuiltInId::texture_Sampler2DShadow1_Float3, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d20B00B10D, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00e30B(BuiltInId::texture_SamplerCubeShadow1_Float4, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00e30B00B, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00f30B(BuiltInId::texture_Sampler2DArrayShadow1_Float4, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00f30B10B10B10D, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00k30B(BuiltInId::texture_SamplerCubeArray1_Float4, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00k30B00B, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00s30B(BuiltInId::texture_ISamplerCubeArray1_Float4, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00s30B00B, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00x30B(BuiltInId::texture_USamplerCubeArray1_Float4, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00x30B00B, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00l30B00B( + BuiltInId::texture_SamplerCubeArrayShadow1_Float4_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00l30B00B, + 3, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction textureExt_00k30B( + BuiltInId::textureExt_SamplerCubeArray1_Float4, + BuiltInName::textureExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00k30B00B, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction textureExt_00s30B( + BuiltInId::textureExt_ISamplerCubeArray1_Float4, + BuiltInName::textureExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00s30B00B, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction textureExt_00x30B( + BuiltInId::textureExt_USamplerCubeArray1_Float4, + BuiltInName::textureExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00x30B00B, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction textureExt_00l30B00B( + BuiltInId::textureExt_SamplerCubeArrayShadow1_Float4_Float1, + BuiltInName::textureExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00l30B00B, + 3, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00M10B(BuiltInId::texture_SamplerExternalOES1_Float2, + BuiltInName::texture, + std::array{ + {TExtension::OES_EGL_image_external_essl3}}, + BuiltInParameters::p00M10B00B, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00N10B(BuiltInId::texture_SamplerExternal2DY2YEXT1_Float2, + BuiltInName::texture, + std::array{{TExtension::EXT_YUV_target}}, + BuiltInParameters::p00N10B00B, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00O10B(BuiltInId::texture_Sampler2DRect1_Float2, + BuiltInName::texture, + std::array{ + {TExtension::ARB_texture_rectangle}}, + BuiltInParameters::p00O10B, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction texture_00y10B(BuiltInId::texture_SamplerVideoWEBGL1_Float2, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00y10B, + 2, + StaticType::Get(), + EOpTexture, + false); +constexpr const TFunction textureProj_00I20B( + BuiltInId::textureProj_Sampler2D1_Float3, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I20B00B10D, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00R20B( + BuiltInId::textureProj_ISampler2D1_Float3, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R20B00B10D, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00X20B( + BuiltInId::textureProj_USampler2D1_Float3, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X20B00B10D, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00I30B( + BuiltInId::textureProj_Sampler2D1_Float4, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I30B00B10D, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00R30B( + BuiltInId::textureProj_ISampler2D1_Float4, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R30B00B10D, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00X30B( + BuiltInId::textureProj_USampler2D1_Float4, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X30B00B10D, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00J30B( + BuiltInId::textureProj_Sampler3D1_Float4, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J30B00B20D, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00S30B( + BuiltInId::textureProj_ISampler3D1_Float4, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S30B00B20D, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00Y30B( + BuiltInId::textureProj_USampler3D1_Float4, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y30B00B20D, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00d30B( + BuiltInId::textureProj_Sampler2DShadow1_Float4, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d30B00B10D, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00M20B( + BuiltInId::textureProj_SamplerExternalOES1_Float3, + BuiltInName::textureProj, + std::array{{TExtension::OES_EGL_image_external_essl3}}, + BuiltInParameters::p00M20B00B, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00M30B( + BuiltInId::textureProj_SamplerExternalOES1_Float4, + BuiltInName::textureProj, + std::array{{TExtension::OES_EGL_image_external_essl3}}, + BuiltInParameters::p00M30B00B, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00N20B( + BuiltInId::textureProj_SamplerExternal2DY2YEXT1_Float3, + BuiltInName::textureProj, + std::array{{TExtension::EXT_YUV_target}}, + BuiltInParameters::p00N20B00B, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00N30B( + BuiltInId::textureProj_SamplerExternal2DY2YEXT1_Float4, + BuiltInName::textureProj, + std::array{{TExtension::EXT_YUV_target}}, + BuiltInParameters::p00N30B00B, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00O20B( + BuiltInId::textureProj_Sampler2DRect1_Float3, + BuiltInName::textureProj, + std::array{{TExtension::ARB_texture_rectangle}}, + BuiltInParameters::p00O20B, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureProj_00O30B( + BuiltInId::textureProj_Sampler2DRect1_Float4, + BuiltInName::textureProj, + std::array{{TExtension::ARB_texture_rectangle}}, + BuiltInParameters::p00O30B, + 2, + StaticType::Get(), + EOpTextureProj, + false); +constexpr const TFunction textureLod_00I10B00B( + BuiltInId::textureLod_Sampler2D1_Float2_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B00B10D, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00R10B00B( + BuiltInId::textureLod_ISampler2D1_Float2_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10B00B10D, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00X10B00B( + BuiltInId::textureLod_USampler2D1_Float2_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10B00B10D, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00J20B00B( + BuiltInId::textureLod_Sampler3D1_Float3_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J20B00B20D, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00S20B00B( + BuiltInId::textureLod_ISampler3D1_Float3_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S20B00B20D, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00Y20B00B( + BuiltInId::textureLod_USampler3D1_Float3_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y20B00B20D, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00K20B00B( + BuiltInId::textureLod_SamplerCube1_Float3_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00K20B00B, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00T20B00B( + BuiltInId::textureLod_ISamplerCube1_Float3_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00T20B00B, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00Z20B00B( + BuiltInId::textureLod_USamplerCube1_Float3_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Z20B00B, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00L20B00B( + BuiltInId::textureLod_Sampler2DArray1_Float3_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20B00B10D, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00U20B00B( + BuiltInId::textureLod_ISampler2DArray1_Float3_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20B00B10D, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00a20B00B( + BuiltInId::textureLod_USampler2DArray1_Float3_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20B00B10D, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00d20B00B( + BuiltInId::textureLod_Sampler2DShadow1_Float3_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d20B00B10D, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00k30B00B( + BuiltInId::textureLod_SamplerCubeArray1_Float4_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00k30B00B, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00s30B00B( + BuiltInId::textureLod_ISamplerCubeArray1_Float4_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00s30B00B, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLod_00x30B00B( + BuiltInId::textureLod_USamplerCubeArray1_Float4_Float1, + BuiltInName::textureLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00x30B00B, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLodExt_00k30B00B( + BuiltInId::textureLodExt_SamplerCubeArray1_Float4_Float1, + BuiltInName::textureLodExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00k30B00B, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLodExt_00s30B00B( + BuiltInId::textureLodExt_ISamplerCubeArray1_Float4_Float1, + BuiltInName::textureLodExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00s30B00B, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureLodExt_00x30B00B( + BuiltInId::textureLodExt_USamplerCubeArray1_Float4_Float1, + BuiltInName::textureLodExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00x30B00B, + 3, + StaticType::Get(), + EOpTextureLod, + false); +constexpr const TFunction textureSize_00I00D( + BuiltInId::textureSize_Sampler2D1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00R00D( + BuiltInId::textureSize_ISampler2D1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00X00D( + BuiltInId::textureSize_USampler2D1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00J00D( + BuiltInId::textureSize_Sampler3D1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00S00D( + BuiltInId::textureSize_ISampler3D1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00Y00D( + BuiltInId::textureSize_USampler3D1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00K00D( + BuiltInId::textureSize_SamplerCube1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00K00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00T00D( + BuiltInId::textureSize_ISamplerCube1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00T00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00Z00D( + BuiltInId::textureSize_USamplerCube1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Z00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00L00D( + BuiltInId::textureSize_Sampler2DArray1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00U00D( + BuiltInId::textureSize_ISampler2DArray1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00a00D( + BuiltInId::textureSize_USampler2DArray1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00d00D( + BuiltInId::textureSize_Sampler2DShadow1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00e00D( + BuiltInId::textureSize_SamplerCubeShadow1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00e00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00f00D( + BuiltInId::textureSize_Sampler2DArrayShadow1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00f00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00k00D( + BuiltInId::textureSize_SamplerCubeArray1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00k00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00s00D( + BuiltInId::textureSize_ISamplerCubeArray1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00s00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00x00D( + BuiltInId::textureSize_USamplerCubeArray1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00x00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00l00D( + BuiltInId::textureSize_SamplerCubeArrayShadow1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00l00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSizeExt_00k00D( + BuiltInId::textureSizeExt_SamplerCubeArray1_Int1, + BuiltInName::textureSizeExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00k00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSizeExt_00s00D( + BuiltInId::textureSizeExt_ISamplerCubeArray1_Int1, + BuiltInName::textureSizeExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00s00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSizeExt_00x00D( + BuiltInId::textureSizeExt_USamplerCubeArray1_Int1, + BuiltInName::textureSizeExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00x00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSizeExt_00l00D( + BuiltInId::textureSizeExt_SamplerCubeArrayShadow1_Int1, + BuiltInName::textureSizeExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00l00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00j(BuiltInId::textureSize_SamplerBuffer1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00j00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00r(BuiltInId::textureSize_ISamplerBuffer1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00r00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00w(BuiltInId::textureSize_USamplerBuffer1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00w00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSizeExt_00j( + BuiltInId::textureSizeExt_SamplerBuffer1, + BuiltInName::textureSizeExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p00j00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSizeExt_00r( + BuiltInId::textureSizeExt_ISamplerBuffer1, + BuiltInName::textureSizeExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p00r00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSizeExt_00w( + BuiltInId::textureSizeExt_USamplerBuffer1, + BuiltInName::textureSizeExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p00w00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00P(BuiltInId::textureSize_Sampler2DMS1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00P10D00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00V(BuiltInId::textureSize_ISampler2DMS1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00V10D00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00b(BuiltInId::textureSize_USampler2DMS1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00b10D00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSizeExt_00P( + BuiltInId::textureSizeExt_Sampler2DMS1, + BuiltInName::textureSizeExt, + std::array{{TExtension::ANGLE_texture_multisample}}, + BuiltInParameters::p00P10D00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSizeExt_00V( + BuiltInId::textureSizeExt_ISampler2DMS1, + BuiltInName::textureSizeExt, + std::array{{TExtension::ANGLE_texture_multisample}}, + BuiltInParameters::p00V10D00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSizeExt_00b( + BuiltInId::textureSizeExt_USampler2DMS1, + BuiltInName::textureSizeExt, + std::array{{TExtension::ANGLE_texture_multisample}}, + BuiltInParameters::p00b10D00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00Q(BuiltInId::textureSize_Sampler2DMSArray1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Q20D00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00W(BuiltInId::textureSize_ISampler2DMSArray1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00W20D00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00c(BuiltInId::textureSize_USampler2DMSArray1, + BuiltInName::textureSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00c20D00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSizeExt_00Q( + BuiltInId::textureSizeExt_Sampler2DMSArray1, + BuiltInName::textureSizeExt, + std::array{{TExtension::OES_texture_storage_multisample_2d_array}}, + BuiltInParameters::p00Q20D00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSizeExt_00W( + BuiltInId::textureSizeExt_ISampler2DMSArray1, + BuiltInName::textureSizeExt, + std::array{{TExtension::OES_texture_storage_multisample_2d_array}}, + BuiltInParameters::p00W20D00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSizeExt_00c( + BuiltInId::textureSizeExt_USampler2DMSArray1, + BuiltInName::textureSizeExt, + std::array{{TExtension::OES_texture_storage_multisample_2d_array}}, + BuiltInParameters::p00c20D00D, + 1, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00M00D( + BuiltInId::textureSize_SamplerExternalOES1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::OES_EGL_image_external_essl3}}, + BuiltInParameters::p00M00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureSize_00N00D( + BuiltInId::textureSize_SamplerExternal2DY2YEXT1_Int1, + BuiltInName::textureSize, + std::array{{TExtension::EXT_YUV_target}}, + BuiltInParameters::p00N00D, + 2, + StaticType::Get(), + EOpTextureSize, + false); +constexpr const TFunction textureProjLod_00I20B00B( + BuiltInId::textureProjLod_Sampler2D1_Float3_Float1, + BuiltInName::textureProjLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I20B00B10D, + 3, + StaticType::Get(), + EOpTextureProjLod, + false); +constexpr const TFunction textureProjLod_00R20B00B( + BuiltInId::textureProjLod_ISampler2D1_Float3_Float1, + BuiltInName::textureProjLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R20B00B10D, + 3, + StaticType::Get(), + EOpTextureProjLod, + false); +constexpr const TFunction textureProjLod_00X20B00B( + BuiltInId::textureProjLod_USampler2D1_Float3_Float1, + BuiltInName::textureProjLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X20B00B10D, + 3, + StaticType::Get(), + EOpTextureProjLod, + false); +constexpr const TFunction textureProjLod_00I30B00B( + BuiltInId::textureProjLod_Sampler2D1_Float4_Float1, + BuiltInName::textureProjLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I30B00B10D, + 3, + StaticType::Get(), + EOpTextureProjLod, + false); +constexpr const TFunction textureProjLod_00R30B00B( + BuiltInId::textureProjLod_ISampler2D1_Float4_Float1, + BuiltInName::textureProjLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R30B00B10D, + 3, + StaticType::Get(), + EOpTextureProjLod, + false); +constexpr const TFunction textureProjLod_00X30B00B( + BuiltInId::textureProjLod_USampler2D1_Float4_Float1, + BuiltInName::textureProjLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X30B00B10D, + 3, + StaticType::Get(), + EOpTextureProjLod, + false); +constexpr const TFunction textureProjLod_00J30B00B( + BuiltInId::textureProjLod_Sampler3D1_Float4_Float1, + BuiltInName::textureProjLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J30B00B20D, + 3, + StaticType::Get(), + EOpTextureProjLod, + false); +constexpr const TFunction textureProjLod_00S30B00B( + BuiltInId::textureProjLod_ISampler3D1_Float4_Float1, + BuiltInName::textureProjLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S30B00B20D, + 3, + StaticType::Get(), + EOpTextureProjLod, + false); +constexpr const TFunction textureProjLod_00Y30B00B( + BuiltInId::textureProjLod_USampler3D1_Float4_Float1, + BuiltInName::textureProjLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y30B00B20D, + 3, + StaticType::Get(), + EOpTextureProjLod, + false); +constexpr const TFunction textureProjLod_00d30B00B( + BuiltInId::textureProjLod_Sampler2DShadow1_Float4_Float1, + BuiltInName::textureProjLod, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d30B00B10D, + 3, + StaticType::Get(), + EOpTextureProjLod, + false); +constexpr const TFunction texelFetch_00I10D00D( + BuiltInId::texelFetch_Sampler2D1_Int2_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10D00D10D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00R10D00D( + BuiltInId::texelFetch_ISampler2D1_Int2_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10D00D10D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00X10D00D( + BuiltInId::texelFetch_USampler2D1_Int2_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10D00D10D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00J20D00D( + BuiltInId::texelFetch_Sampler3D1_Int3_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J20D00D20D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00S20D00D( + BuiltInId::texelFetch_ISampler3D1_Int3_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S20D00D20D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00Y20D00D( + BuiltInId::texelFetch_USampler3D1_Int3_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y20D00D20D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00L20D00D( + BuiltInId::texelFetch_Sampler2DArray1_Int3_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20D00D10D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00U20D00D( + BuiltInId::texelFetch_ISampler2DArray1_Int3_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20D00D10D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00a20D00D( + BuiltInId::texelFetch_USampler2DArray1_Int3_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20D00D10D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00j00D( + BuiltInId::texelFetch_SamplerBuffer1_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00j00D, + 2, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00r00D( + BuiltInId::texelFetch_ISamplerBuffer1_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00r00D, + 2, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00w00D( + BuiltInId::texelFetch_USamplerBuffer1_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00w00D, + 2, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetchExt_00j00D( + BuiltInId::texelFetchExt_SamplerBuffer1_Int1, + BuiltInName::texelFetchExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p00j00D, + 2, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetchExt_00r00D( + BuiltInId::texelFetchExt_ISamplerBuffer1_Int1, + BuiltInName::texelFetchExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p00r00D, + 2, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetchExt_00w00D( + BuiltInId::texelFetchExt_USamplerBuffer1_Int1, + BuiltInName::texelFetchExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p00w00D, + 2, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00P10D00D( + BuiltInId::texelFetch_Sampler2DMS1_Int2_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00P10D00D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00V10D00D( + BuiltInId::texelFetch_ISampler2DMS1_Int2_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00V10D00D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00b10D00D( + BuiltInId::texelFetch_USampler2DMS1_Int2_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00b10D00D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetchExt_00P10D00D( + BuiltInId::texelFetchExt_Sampler2DMS1_Int2_Int1, + BuiltInName::texelFetchExt, + std::array{{TExtension::ANGLE_texture_multisample}}, + BuiltInParameters::p00P10D00D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetchExt_00V10D00D( + BuiltInId::texelFetchExt_ISampler2DMS1_Int2_Int1, + BuiltInName::texelFetchExt, + std::array{{TExtension::ANGLE_texture_multisample}}, + BuiltInParameters::p00V10D00D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetchExt_00b10D00D( + BuiltInId::texelFetchExt_USampler2DMS1_Int2_Int1, + BuiltInName::texelFetchExt, + std::array{{TExtension::ANGLE_texture_multisample}}, + BuiltInParameters::p00b10D00D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00Q20D00D( + BuiltInId::texelFetch_Sampler2DMSArray1_Int3_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Q20D00D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00W20D00D( + BuiltInId::texelFetch_ISampler2DMSArray1_Int3_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00W20D00D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00c20D00D( + BuiltInId::texelFetch_USampler2DMSArray1_Int3_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00c20D00D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetchExt_00Q20D00D( + BuiltInId::texelFetchExt_Sampler2DMSArray1_Int3_Int1, + BuiltInName::texelFetchExt, + std::array{{TExtension::OES_texture_storage_multisample_2d_array}}, + BuiltInParameters::p00Q20D00D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetchExt_00W20D00D( + BuiltInId::texelFetchExt_ISampler2DMSArray1_Int3_Int1, + BuiltInName::texelFetchExt, + std::array{{TExtension::OES_texture_storage_multisample_2d_array}}, + BuiltInParameters::p00W20D00D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetchExt_00c20D00D( + BuiltInId::texelFetchExt_USampler2DMSArray1_Int3_Int1, + BuiltInName::texelFetchExt, + std::array{{TExtension::OES_texture_storage_multisample_2d_array}}, + BuiltInParameters::p00c20D00D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00M10D00D( + BuiltInId::texelFetch_SamplerExternalOES1_Int2_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::OES_EGL_image_external_essl3}}, + BuiltInParameters::p00M10D00D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction texelFetch_00N10D00D( + BuiltInId::texelFetch_SamplerExternal2DY2YEXT1_Int2_Int1, + BuiltInName::texelFetch, + std::array{{TExtension::EXT_YUV_target}}, + BuiltInParameters::p00N10D00D, + 3, + StaticType::Get(), + EOpTexelFetch, + false); +constexpr const TFunction textureGrad_00I10B10B10B( + BuiltInId::textureGrad_Sampler2D1_Float2_Float2_Float2, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B10B10B10D, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00R10B10B10B( + BuiltInId::textureGrad_ISampler2D1_Float2_Float2_Float2, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10B10B10B10D, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00X10B10B10B( + BuiltInId::textureGrad_USampler2D1_Float2_Float2_Float2, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10B10B10B10D, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00J20B20B20B( + BuiltInId::textureGrad_Sampler3D1_Float3_Float3_Float3, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J20B20B20B20D, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00S20B20B20B( + BuiltInId::textureGrad_ISampler3D1_Float3_Float3_Float3, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S20B20B20B20D, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00Y20B20B20B( + BuiltInId::textureGrad_USampler3D1_Float3_Float3_Float3, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y20B20B20B20D, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00K20B20B20B( + BuiltInId::textureGrad_SamplerCube1_Float3_Float3_Float3, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00K20B20B20B, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00T20B20B20B( + BuiltInId::textureGrad_ISamplerCube1_Float3_Float3_Float3, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00T20B20B20B, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00Z20B20B20B( + BuiltInId::textureGrad_USamplerCube1_Float3_Float3_Float3, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Z20B20B20B, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00d20B10B10B( + BuiltInId::textureGrad_Sampler2DShadow1_Float3_Float2_Float2, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d20B10B10B10D, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00e30B20B20B( + BuiltInId::textureGrad_SamplerCubeShadow1_Float4_Float3_Float3, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00e30B20B20B, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00L20B10B10B( + BuiltInId::textureGrad_Sampler2DArray1_Float3_Float2_Float2, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20B10B10B10D, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00U20B10B10B( + BuiltInId::textureGrad_ISampler2DArray1_Float3_Float2_Float2, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20B10B10B10D, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00a20B10B10B( + BuiltInId::textureGrad_USampler2DArray1_Float3_Float2_Float2, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20B10B10B10D, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00f30B10B10B( + BuiltInId::textureGrad_Sampler2DArrayShadow1_Float4_Float2_Float2, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00f30B10B10B10D, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00k30B20B20B( + BuiltInId::textureGrad_SamplerCubeArray1_Float4_Float3_Float3, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00k30B20B20B, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00s30B20B20B( + BuiltInId::textureGrad_ISamplerCubeArray1_Float4_Float3_Float3, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00s30B20B20B, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGrad_00x30B20B20B( + BuiltInId::textureGrad_USamplerCubeArray1_Float4_Float3_Float3, + BuiltInName::textureGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00x30B20B20B, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGradExt_00k30B20B20B( + BuiltInId::textureGradExt_SamplerCubeArray1_Float4_Float3_Float3, + BuiltInName::textureGradExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00k30B20B20B, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGradExt_00s30B20B20B( + BuiltInId::textureGradExt_ISamplerCubeArray1_Float4_Float3_Float3, + BuiltInName::textureGradExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00s30B20B20B, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureGradExt_00x30B20B20B( + BuiltInId::textureGradExt_USamplerCubeArray1_Float4_Float3_Float3, + BuiltInName::textureGradExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00x30B20B20B, + 4, + StaticType::Get(), + EOpTextureGrad, + false); +constexpr const TFunction textureProjGrad_00I20B10B10B( + BuiltInId::textureProjGrad_Sampler2D1_Float3_Float2_Float2, + BuiltInName::textureProjGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I20B10B10B10D, + 4, + StaticType::Get(), + EOpTextureProjGrad, + false); +constexpr const TFunction textureProjGrad_00R20B10B10B( + BuiltInId::textureProjGrad_ISampler2D1_Float3_Float2_Float2, + BuiltInName::textureProjGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R20B10B10B10D, + 4, + StaticType::Get(), + EOpTextureProjGrad, + false); +constexpr const TFunction textureProjGrad_00X20B10B10B( + BuiltInId::textureProjGrad_USampler2D1_Float3_Float2_Float2, + BuiltInName::textureProjGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X20B10B10B10D, + 4, + StaticType::Get(), + EOpTextureProjGrad, + false); +constexpr const TFunction textureProjGrad_00I30B10B10B( + BuiltInId::textureProjGrad_Sampler2D1_Float4_Float2_Float2, + BuiltInName::textureProjGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I30B10B10B10D, + 4, + StaticType::Get(), + EOpTextureProjGrad, + false); +constexpr const TFunction textureProjGrad_00R30B10B10B( + BuiltInId::textureProjGrad_ISampler2D1_Float4_Float2_Float2, + BuiltInName::textureProjGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R30B10B10B10D, + 4, + StaticType::Get(), + EOpTextureProjGrad, + false); +constexpr const TFunction textureProjGrad_00X30B10B10B( + BuiltInId::textureProjGrad_USampler2D1_Float4_Float2_Float2, + BuiltInName::textureProjGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X30B10B10B10D, + 4, + StaticType::Get(), + EOpTextureProjGrad, + false); +constexpr const TFunction textureProjGrad_00J30B20B20B( + BuiltInId::textureProjGrad_Sampler3D1_Float4_Float3_Float3, + BuiltInName::textureProjGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J30B20B20B20D, + 4, + StaticType::Get(), + EOpTextureProjGrad, + false); +constexpr const TFunction textureProjGrad_00S30B20B20B( + BuiltInId::textureProjGrad_ISampler3D1_Float4_Float3_Float3, + BuiltInName::textureProjGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S30B20B20B20D, + 4, + StaticType::Get(), + EOpTextureProjGrad, + false); +constexpr const TFunction textureProjGrad_00Y30B20B20B( + BuiltInId::textureProjGrad_USampler3D1_Float4_Float3_Float3, + BuiltInName::textureProjGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y30B20B20B20D, + 4, + StaticType::Get(), + EOpTextureProjGrad, + false); +constexpr const TFunction textureProjGrad_00d30B10B10B( + BuiltInId::textureProjGrad_Sampler2DShadow1_Float4_Float2_Float2, + BuiltInName::textureProjGrad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d30B10B10B10D, + 4, + StaticType::Get(), + EOpTextureProjGrad, + false); +constexpr const TFunction texture_00I10B00B( + BuiltInId::texture_Sampler2D1_Float2_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B00B10D, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00R10B00B( + BuiltInId::texture_ISampler2D1_Float2_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10B00B10D, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00X10B00B( + BuiltInId::texture_USampler2D1_Float2_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10B00B10D, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00J20B00B( + BuiltInId::texture_Sampler3D1_Float3_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J20B00B20D, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00S20B00B( + BuiltInId::texture_ISampler3D1_Float3_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S20B00B20D, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00Y20B00B( + BuiltInId::texture_USampler3D1_Float3_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y20B00B20D, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00K20B00B( + BuiltInId::texture_SamplerCube1_Float3_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00K20B00B, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00T20B00B( + BuiltInId::texture_ISamplerCube1_Float3_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00T20B00B, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00Z20B00B( + BuiltInId::texture_USamplerCube1_Float3_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Z20B00B, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00L20B00B( + BuiltInId::texture_Sampler2DArray1_Float3_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20B00B10D, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00U20B00B( + BuiltInId::texture_ISampler2DArray1_Float3_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20B00B10D, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00a20B00B( + BuiltInId::texture_USampler2DArray1_Float3_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20B00B10D, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction textureProj_00I20B00B( + BuiltInId::textureProj_Sampler2D1_Float3_Float1, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I20B00B10D, + 3, + StaticType::Get(), + EOpTextureProjBias, + false); +constexpr const TFunction textureProj_00R20B00B( + BuiltInId::textureProj_ISampler2D1_Float3_Float1, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R20B00B10D, + 3, + StaticType::Get(), + EOpTextureProjBias, + false); +constexpr const TFunction textureProj_00X20B00B( + BuiltInId::textureProj_USampler2D1_Float3_Float1, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X20B00B10D, + 3, + StaticType::Get(), + EOpTextureProjBias, + false); +constexpr const TFunction textureProj_00I30B00B( + BuiltInId::textureProj_Sampler2D1_Float4_Float1, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I30B00B10D, + 3, + StaticType::Get(), + EOpTextureProjBias, + false); +constexpr const TFunction textureProj_00R30B00B( + BuiltInId::textureProj_ISampler2D1_Float4_Float1, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R30B00B10D, + 3, + StaticType::Get(), + EOpTextureProjBias, + false); +constexpr const TFunction textureProj_00X30B00B( + BuiltInId::textureProj_USampler2D1_Float4_Float1, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X30B00B10D, + 3, + StaticType::Get(), + EOpTextureProjBias, + false); +constexpr const TFunction textureProj_00J30B00B( + BuiltInId::textureProj_Sampler3D1_Float4_Float1, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J30B00B20D, + 3, + StaticType::Get(), + EOpTextureProjBias, + false); +constexpr const TFunction textureProj_00S30B00B( + BuiltInId::textureProj_ISampler3D1_Float4_Float1, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S30B00B20D, + 3, + StaticType::Get(), + EOpTextureProjBias, + false); +constexpr const TFunction textureProj_00Y30B00B( + BuiltInId::textureProj_USampler3D1_Float4_Float1, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y30B00B20D, + 3, + StaticType::Get(), + EOpTextureProjBias, + false); +constexpr const TFunction texture_00d20B00B( + BuiltInId::texture_Sampler2DShadow1_Float3_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d20B00B10D, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00e30B00B( + BuiltInId::texture_SamplerCubeShadow1_Float4_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00e30B00B, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction textureProj_00d30B00B( + BuiltInId::textureProj_Sampler2DShadow1_Float4_Float1, + BuiltInName::textureProj, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d30B00B10D, + 3, + StaticType::Get(), + EOpTextureProjBias, + false); +constexpr const TFunction texture_00k30B00B( + BuiltInId::texture_SamplerCubeArray1_Float4_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00k30B00B, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00s30B00B( + BuiltInId::texture_ISamplerCubeArray1_Float4_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00s30B00B, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00x30B00B( + BuiltInId::texture_USamplerCubeArray1_Float4_Float1, + BuiltInName::texture, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00x30B00B, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction textureExt_00k30B00B( + BuiltInId::textureExt_SamplerCubeArray1_Float4_Float1, + BuiltInName::textureExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00k30B00B, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction textureExt_00s30B00B( + BuiltInId::textureExt_ISamplerCubeArray1_Float4_Float1, + BuiltInName::textureExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00s30B00B, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction textureExt_00x30B00B( + BuiltInId::textureExt_USamplerCubeArray1_Float4_Float1, + BuiltInName::textureExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00x30B00B, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction texture_00M10B00B( + BuiltInId::texture_SamplerExternalOES1_Float2_Float1, + BuiltInName::texture, + std::array{{TExtension::OES_EGL_image_external_essl3}}, + BuiltInParameters::p00M10B00B, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction textureProj_00M20B00B( + BuiltInId::textureProj_SamplerExternalOES1_Float3_Float1, + BuiltInName::textureProj, + std::array{{TExtension::OES_EGL_image_external_essl3}}, + BuiltInParameters::p00M20B00B, + 3, + StaticType::Get(), + EOpTextureProjBias, + false); +constexpr const TFunction textureProj_00M30B00B( + BuiltInId::textureProj_SamplerExternalOES1_Float4_Float1, + BuiltInName::textureProj, + std::array{{TExtension::OES_EGL_image_external_essl3}}, + BuiltInParameters::p00M30B00B, + 3, + StaticType::Get(), + EOpTextureProjBias, + false); +constexpr const TFunction texture_00N10B00B( + BuiltInId::texture_SamplerExternal2DY2YEXT1_Float2_Float1, + BuiltInName::texture, + std::array{{TExtension::EXT_YUV_target}}, + BuiltInParameters::p00N10B00B, + 3, + StaticType::Get(), + EOpTextureBias, + false); +constexpr const TFunction textureProj_00N20B00B( + BuiltInId::textureProj_SamplerExternal2DY2YEXT1_Float3_Float1, + BuiltInName::textureProj, + std::array{{TExtension::EXT_YUV_target}}, + BuiltInParameters::p00N20B00B, + 3, + StaticType::Get(), + EOpTextureProjBias, + false); +constexpr const TFunction textureProj_00N30B00B( + BuiltInId::textureProj_SamplerExternal2DY2YEXT1_Float4_Float1, + BuiltInName::textureProj, + std::array{{TExtension::EXT_YUV_target}}, + BuiltInParameters::p00N30B00B, + 3, + StaticType::Get(), + EOpTextureProjBias, + false); +constexpr const TFunction textureOffset_00I10B10D( + BuiltInId::textureOffset_Sampler2D1_Float2_Int2, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B10D00B, + 3, + StaticType::Get(), + EOpTextureOffset, + false); +constexpr const TFunction textureOffset_00R10B10D( + BuiltInId::textureOffset_ISampler2D1_Float2_Int2, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10B10D00B, + 3, + StaticType::Get(), + EOpTextureOffset, + false); +constexpr const TFunction textureOffset_00X10B10D( + BuiltInId::textureOffset_USampler2D1_Float2_Int2, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10B10D00B, + 3, + StaticType::Get(), + EOpTextureOffset, + false); +constexpr const TFunction textureOffset_00J20B20D( + BuiltInId::textureOffset_Sampler3D1_Float3_Int3, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J20B20D00B, + 3, + StaticType::Get(), + EOpTextureOffset, + false); +constexpr const TFunction textureOffset_00S20B20D( + BuiltInId::textureOffset_ISampler3D1_Float3_Int3, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S20B20D00B, + 3, + StaticType::Get(), + EOpTextureOffset, + false); +constexpr const TFunction textureOffset_00Y20B20D( + BuiltInId::textureOffset_USampler3D1_Float3_Int3, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y20B20D00B, + 3, + StaticType::Get(), + EOpTextureOffset, + false); +constexpr const TFunction textureOffset_00d20B10D( + BuiltInId::textureOffset_Sampler2DShadow1_Float3_Int2, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d20B10D00B, + 3, + StaticType::Get(), + EOpTextureOffset, + false); +constexpr const TFunction textureOffset_00L20B10D( + BuiltInId::textureOffset_Sampler2DArray1_Float3_Int2, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20B10D00B, + 3, + StaticType::Get(), + EOpTextureOffset, + false); +constexpr const TFunction textureOffset_00U20B10D( + BuiltInId::textureOffset_ISampler2DArray1_Float3_Int2, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20B10D00B, + 3, + StaticType::Get(), + EOpTextureOffset, + false); +constexpr const TFunction textureOffset_00a20B10D( + BuiltInId::textureOffset_USampler2DArray1_Float3_Int2, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20B10D00B, + 3, + StaticType::Get(), + EOpTextureOffset, + false); +constexpr const TFunction textureProjOffset_00I20B10D( + BuiltInId::textureProjOffset_Sampler2D1_Float3_Int2, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I20B10D00B, + 3, + StaticType::Get(), + EOpTextureProjOffset, + false); +constexpr const TFunction textureProjOffset_00R20B10D( + BuiltInId::textureProjOffset_ISampler2D1_Float3_Int2, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R20B10D00B, + 3, + StaticType::Get(), + EOpTextureProjOffset, + false); +constexpr const TFunction textureProjOffset_00X20B10D( + BuiltInId::textureProjOffset_USampler2D1_Float3_Int2, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X20B10D00B, + 3, + StaticType::Get(), + EOpTextureProjOffset, + false); +constexpr const TFunction textureProjOffset_00I30B10D( + BuiltInId::textureProjOffset_Sampler2D1_Float4_Int2, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I30B10D00B, + 3, + StaticType::Get(), + EOpTextureProjOffset, + false); +constexpr const TFunction textureProjOffset_00R30B10D( + BuiltInId::textureProjOffset_ISampler2D1_Float4_Int2, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R30B10D00B, + 3, + StaticType::Get(), + EOpTextureProjOffset, + false); +constexpr const TFunction textureProjOffset_00X30B10D( + BuiltInId::textureProjOffset_USampler2D1_Float4_Int2, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X30B10D00B, + 3, + StaticType::Get(), + EOpTextureProjOffset, + false); +constexpr const TFunction textureProjOffset_00J30B20D( + BuiltInId::textureProjOffset_Sampler3D1_Float4_Int3, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J30B20D00B, + 3, + StaticType::Get(), + EOpTextureProjOffset, + false); +constexpr const TFunction textureProjOffset_00S30B20D( + BuiltInId::textureProjOffset_ISampler3D1_Float4_Int3, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S30B20D00B, + 3, + StaticType::Get(), + EOpTextureProjOffset, + false); +constexpr const TFunction textureProjOffset_00Y30B20D( + BuiltInId::textureProjOffset_USampler3D1_Float4_Int3, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y30B20D00B, + 3, + StaticType::Get(), + EOpTextureProjOffset, + false); +constexpr const TFunction textureProjOffset_00d30B10D( + BuiltInId::textureProjOffset_Sampler2DShadow1_Float4_Int2, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d30B10D00B, + 3, + StaticType::Get(), + EOpTextureProjOffset, + false); +constexpr const TFunction textureLodOffset_00I10B00B10D( + BuiltInId::textureLodOffset_Sampler2D1_Float2_Float1_Int2, + BuiltInName::textureLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B00B10D, + 4, + StaticType::Get(), + EOpTextureLodOffset, + false); +constexpr const TFunction textureLodOffset_00R10B00B10D( + BuiltInId::textureLodOffset_ISampler2D1_Float2_Float1_Int2, + BuiltInName::textureLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10B00B10D, + 4, + StaticType::Get(), + EOpTextureLodOffset, + false); +constexpr const TFunction textureLodOffset_00X10B00B10D( + BuiltInId::textureLodOffset_USampler2D1_Float2_Float1_Int2, + BuiltInName::textureLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10B00B10D, + 4, + StaticType::Get(), + EOpTextureLodOffset, + false); +constexpr const TFunction textureLodOffset_00J20B00B20D( + BuiltInId::textureLodOffset_Sampler3D1_Float3_Float1_Int3, + BuiltInName::textureLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J20B00B20D, + 4, + StaticType::Get(), + EOpTextureLodOffset, + false); +constexpr const TFunction textureLodOffset_00S20B00B20D( + BuiltInId::textureLodOffset_ISampler3D1_Float3_Float1_Int3, + BuiltInName::textureLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S20B00B20D, + 4, + StaticType::Get(), + EOpTextureLodOffset, + false); +constexpr const TFunction textureLodOffset_00Y20B00B20D( + BuiltInId::textureLodOffset_USampler3D1_Float3_Float1_Int3, + BuiltInName::textureLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y20B00B20D, + 4, + StaticType::Get(), + EOpTextureLodOffset, + false); +constexpr const TFunction textureLodOffset_00d20B00B10D( + BuiltInId::textureLodOffset_Sampler2DShadow1_Float3_Float1_Int2, + BuiltInName::textureLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d20B00B10D, + 4, + StaticType::Get(), + EOpTextureLodOffset, + false); +constexpr const TFunction textureLodOffset_00L20B00B10D( + BuiltInId::textureLodOffset_Sampler2DArray1_Float3_Float1_Int2, + BuiltInName::textureLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20B00B10D, + 4, + StaticType::Get(), + EOpTextureLodOffset, + false); +constexpr const TFunction textureLodOffset_00U20B00B10D( + BuiltInId::textureLodOffset_ISampler2DArray1_Float3_Float1_Int2, + BuiltInName::textureLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20B00B10D, + 4, + StaticType::Get(), + EOpTextureLodOffset, + false); +constexpr const TFunction textureLodOffset_00a20B00B10D( + BuiltInId::textureLodOffset_USampler2DArray1_Float3_Float1_Int2, + BuiltInName::textureLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20B00B10D, + 4, + StaticType::Get(), + EOpTextureLodOffset, + false); +constexpr const TFunction textureProjLodOffset_00I20B00B10D( + BuiltInId::textureProjLodOffset_Sampler2D1_Float3_Float1_Int2, + BuiltInName::textureProjLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I20B00B10D, + 4, + StaticType::Get(), + EOpTextureProjLodOffset, + false); +constexpr const TFunction textureProjLodOffset_00R20B00B10D( + BuiltInId::textureProjLodOffset_ISampler2D1_Float3_Float1_Int2, + BuiltInName::textureProjLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R20B00B10D, + 4, + StaticType::Get(), + EOpTextureProjLodOffset, + false); +constexpr const TFunction textureProjLodOffset_00X20B00B10D( + BuiltInId::textureProjLodOffset_USampler2D1_Float3_Float1_Int2, + BuiltInName::textureProjLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X20B00B10D, + 4, + StaticType::Get(), + EOpTextureProjLodOffset, + false); +constexpr const TFunction textureProjLodOffset_00I30B00B10D( + BuiltInId::textureProjLodOffset_Sampler2D1_Float4_Float1_Int2, + BuiltInName::textureProjLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I30B00B10D, + 4, + StaticType::Get(), + EOpTextureProjLodOffset, + false); +constexpr const TFunction textureProjLodOffset_00R30B00B10D( + BuiltInId::textureProjLodOffset_ISampler2D1_Float4_Float1_Int2, + BuiltInName::textureProjLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R30B00B10D, + 4, + StaticType::Get(), + EOpTextureProjLodOffset, + false); +constexpr const TFunction textureProjLodOffset_00X30B00B10D( + BuiltInId::textureProjLodOffset_USampler2D1_Float4_Float1_Int2, + BuiltInName::textureProjLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X30B00B10D, + 4, + StaticType::Get(), + EOpTextureProjLodOffset, + false); +constexpr const TFunction textureProjLodOffset_00J30B00B20D( + BuiltInId::textureProjLodOffset_Sampler3D1_Float4_Float1_Int3, + BuiltInName::textureProjLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J30B00B20D, + 4, + StaticType::Get(), + EOpTextureProjLodOffset, + false); +constexpr const TFunction textureProjLodOffset_00S30B00B20D( + BuiltInId::textureProjLodOffset_ISampler3D1_Float4_Float1_Int3, + BuiltInName::textureProjLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S30B00B20D, + 4, + StaticType::Get(), + EOpTextureProjLodOffset, + false); +constexpr const TFunction textureProjLodOffset_00Y30B00B20D( + BuiltInId::textureProjLodOffset_USampler3D1_Float4_Float1_Int3, + BuiltInName::textureProjLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y30B00B20D, + 4, + StaticType::Get(), + EOpTextureProjLodOffset, + false); +constexpr const TFunction textureProjLodOffset_00d30B00B10D( + BuiltInId::textureProjLodOffset_Sampler2DShadow1_Float4_Float1_Int2, + BuiltInName::textureProjLodOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d30B00B10D, + 4, + StaticType::Get(), + EOpTextureProjLodOffset, + false); +constexpr const TFunction texelFetchOffset_00I10D00D10D( + BuiltInId::texelFetchOffset_Sampler2D1_Int2_Int1_Int2, + BuiltInName::texelFetchOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10D00D10D, + 4, + StaticType::Get(), + EOpTexelFetchOffset, + false); +constexpr const TFunction texelFetchOffset_00R10D00D10D( + BuiltInId::texelFetchOffset_ISampler2D1_Int2_Int1_Int2, + BuiltInName::texelFetchOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10D00D10D, + 4, + StaticType::Get(), + EOpTexelFetchOffset, + false); +constexpr const TFunction texelFetchOffset_00X10D00D10D( + BuiltInId::texelFetchOffset_USampler2D1_Int2_Int1_Int2, + BuiltInName::texelFetchOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10D00D10D, + 4, + StaticType::Get(), + EOpTexelFetchOffset, + false); +constexpr const TFunction texelFetchOffset_00J20D00D20D( + BuiltInId::texelFetchOffset_Sampler3D1_Int3_Int1_Int3, + BuiltInName::texelFetchOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J20D00D20D, + 4, + StaticType::Get(), + EOpTexelFetchOffset, + false); +constexpr const TFunction texelFetchOffset_00S20D00D20D( + BuiltInId::texelFetchOffset_ISampler3D1_Int3_Int1_Int3, + BuiltInName::texelFetchOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S20D00D20D, + 4, + StaticType::Get(), + EOpTexelFetchOffset, + false); +constexpr const TFunction texelFetchOffset_00Y20D00D20D( + BuiltInId::texelFetchOffset_USampler3D1_Int3_Int1_Int3, + BuiltInName::texelFetchOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y20D00D20D, + 4, + StaticType::Get(), + EOpTexelFetchOffset, + false); +constexpr const TFunction texelFetchOffset_00L20D00D10D( + BuiltInId::texelFetchOffset_Sampler2DArray1_Int3_Int1_Int2, + BuiltInName::texelFetchOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20D00D10D, + 4, + StaticType::Get(), + EOpTexelFetchOffset, + false); +constexpr const TFunction texelFetchOffset_00U20D00D10D( + BuiltInId::texelFetchOffset_ISampler2DArray1_Int3_Int1_Int2, + BuiltInName::texelFetchOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20D00D10D, + 4, + StaticType::Get(), + EOpTexelFetchOffset, + false); +constexpr const TFunction texelFetchOffset_00a20D00D10D( + BuiltInId::texelFetchOffset_USampler2DArray1_Int3_Int1_Int2, + BuiltInName::texelFetchOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20D00D10D, + 4, + StaticType::Get(), + EOpTexelFetchOffset, + false); +constexpr const TFunction textureGradOffset_00I10B10B10B10D( + BuiltInId::textureGradOffset_Sampler2D1_Float2_Float2_Float2_Int2, + BuiltInName::textureGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B10B10B10D, + 5, + StaticType::Get(), + EOpTextureGradOffset, + false); +constexpr const TFunction textureGradOffset_00R10B10B10B10D( + BuiltInId::textureGradOffset_ISampler2D1_Float2_Float2_Float2_Int2, + BuiltInName::textureGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10B10B10B10D, + 5, + StaticType::Get(), + EOpTextureGradOffset, + false); +constexpr const TFunction textureGradOffset_00X10B10B10B10D( + BuiltInId::textureGradOffset_USampler2D1_Float2_Float2_Float2_Int2, + BuiltInName::textureGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10B10B10B10D, + 5, + StaticType::Get(), + EOpTextureGradOffset, + false); +constexpr const TFunction textureGradOffset_00J20B20B20B20D( + BuiltInId::textureGradOffset_Sampler3D1_Float3_Float3_Float3_Int3, + BuiltInName::textureGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J20B20B20B20D, + 5, + StaticType::Get(), + EOpTextureGradOffset, + false); +constexpr const TFunction textureGradOffset_00S20B20B20B20D( + BuiltInId::textureGradOffset_ISampler3D1_Float3_Float3_Float3_Int3, + BuiltInName::textureGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S20B20B20B20D, + 5, + StaticType::Get(), + EOpTextureGradOffset, + false); +constexpr const TFunction textureGradOffset_00Y20B20B20B20D( + BuiltInId::textureGradOffset_USampler3D1_Float3_Float3_Float3_Int3, + BuiltInName::textureGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y20B20B20B20D, + 5, + StaticType::Get(), + EOpTextureGradOffset, + false); +constexpr const TFunction textureGradOffset_00d20B10B10B10D( + BuiltInId::textureGradOffset_Sampler2DShadow1_Float3_Float2_Float2_Int2, + BuiltInName::textureGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d20B10B10B10D, + 5, + StaticType::Get(), + EOpTextureGradOffset, + false); +constexpr const TFunction textureGradOffset_00L20B10B10B10D( + BuiltInId::textureGradOffset_Sampler2DArray1_Float3_Float2_Float2_Int2, + BuiltInName::textureGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20B10B10B10D, + 5, + StaticType::Get(), + EOpTextureGradOffset, + false); +constexpr const TFunction textureGradOffset_00U20B10B10B10D( + BuiltInId::textureGradOffset_ISampler2DArray1_Float3_Float2_Float2_Int2, + BuiltInName::textureGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20B10B10B10D, + 5, + StaticType::Get(), + EOpTextureGradOffset, + false); +constexpr const TFunction textureGradOffset_00a20B10B10B10D( + BuiltInId::textureGradOffset_USampler2DArray1_Float3_Float2_Float2_Int2, + BuiltInName::textureGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20B10B10B10D, + 5, + StaticType::Get(), + EOpTextureGradOffset, + false); +constexpr const TFunction textureGradOffset_00f30B10B10B10D( + BuiltInId::textureGradOffset_Sampler2DArrayShadow1_Float4_Float2_Float2_Int2, + BuiltInName::textureGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00f30B10B10B10D, + 5, + StaticType::Get(), + EOpTextureGradOffset, + false); +constexpr const TFunction textureProjGradOffset_00I20B10B10B10D( + BuiltInId::textureProjGradOffset_Sampler2D1_Float3_Float2_Float2_Int2, + BuiltInName::textureProjGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I20B10B10B10D, + 5, + StaticType::Get(), + EOpTextureProjGradOffset, + false); +constexpr const TFunction textureProjGradOffset_00R20B10B10B10D( + BuiltInId::textureProjGradOffset_ISampler2D1_Float3_Float2_Float2_Int2, + BuiltInName::textureProjGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R20B10B10B10D, + 5, + StaticType::Get(), + EOpTextureProjGradOffset, + false); +constexpr const TFunction textureProjGradOffset_00X20B10B10B10D( + BuiltInId::textureProjGradOffset_USampler2D1_Float3_Float2_Float2_Int2, + BuiltInName::textureProjGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X20B10B10B10D, + 5, + StaticType::Get(), + EOpTextureProjGradOffset, + false); +constexpr const TFunction textureProjGradOffset_00I30B10B10B10D( + BuiltInId::textureProjGradOffset_Sampler2D1_Float4_Float2_Float2_Int2, + BuiltInName::textureProjGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I30B10B10B10D, + 5, + StaticType::Get(), + EOpTextureProjGradOffset, + false); +constexpr const TFunction textureProjGradOffset_00R30B10B10B10D( + BuiltInId::textureProjGradOffset_ISampler2D1_Float4_Float2_Float2_Int2, + BuiltInName::textureProjGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R30B10B10B10D, + 5, + StaticType::Get(), + EOpTextureProjGradOffset, + false); +constexpr const TFunction textureProjGradOffset_00X30B10B10B10D( + BuiltInId::textureProjGradOffset_USampler2D1_Float4_Float2_Float2_Int2, + BuiltInName::textureProjGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X30B10B10B10D, + 5, + StaticType::Get(), + EOpTextureProjGradOffset, + false); +constexpr const TFunction textureProjGradOffset_00J30B20B20B20D( + BuiltInId::textureProjGradOffset_Sampler3D1_Float4_Float3_Float3_Int3, + BuiltInName::textureProjGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J30B20B20B20D, + 5, + StaticType::Get(), + EOpTextureProjGradOffset, + false); +constexpr const TFunction textureProjGradOffset_00S30B20B20B20D( + BuiltInId::textureProjGradOffset_ISampler3D1_Float4_Float3_Float3_Int3, + BuiltInName::textureProjGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S30B20B20B20D, + 5, + StaticType::Get(), + EOpTextureProjGradOffset, + false); +constexpr const TFunction textureProjGradOffset_00Y30B20B20B20D( + BuiltInId::textureProjGradOffset_USampler3D1_Float4_Float3_Float3_Int3, + BuiltInName::textureProjGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y30B20B20B20D, + 5, + StaticType::Get(), + EOpTextureProjGradOffset, + false); +constexpr const TFunction textureProjGradOffset_00d30B10B10B10D( + BuiltInId::textureProjGradOffset_Sampler2DShadow1_Float4_Float2_Float2_Int2, + BuiltInName::textureProjGradOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d30B10B10B10D, + 5, + StaticType::Get(), + EOpTextureProjGradOffset, + false); +constexpr const TFunction textureOffset_00I10B10D00B( + BuiltInId::textureOffset_Sampler2D1_Float2_Int2_Float1, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B10D00B, + 4, + StaticType::Get(), + EOpTextureOffsetBias, + false); +constexpr const TFunction textureOffset_00R10B10D00B( + BuiltInId::textureOffset_ISampler2D1_Float2_Int2_Float1, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10B10D00B, + 4, + StaticType::Get(), + EOpTextureOffsetBias, + false); +constexpr const TFunction textureOffset_00X10B10D00B( + BuiltInId::textureOffset_USampler2D1_Float2_Int2_Float1, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10B10D00B, + 4, + StaticType::Get(), + EOpTextureOffsetBias, + false); +constexpr const TFunction textureOffset_00J20B20D00B( + BuiltInId::textureOffset_Sampler3D1_Float3_Int3_Float1, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J20B20D00B, + 4, + StaticType::Get(), + EOpTextureOffsetBias, + false); +constexpr const TFunction textureOffset_00S20B20D00B( + BuiltInId::textureOffset_ISampler3D1_Float3_Int3_Float1, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S20B20D00B, + 4, + StaticType::Get(), + EOpTextureOffsetBias, + false); +constexpr const TFunction textureOffset_00Y20B20D00B( + BuiltInId::textureOffset_USampler3D1_Float3_Int3_Float1, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y20B20D00B, + 4, + StaticType::Get(), + EOpTextureOffsetBias, + false); +constexpr const TFunction textureOffset_00d20B10D00B( + BuiltInId::textureOffset_Sampler2DShadow1_Float3_Int2_Float1, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d20B10D00B, + 4, + StaticType::Get(), + EOpTextureOffsetBias, + false); +constexpr const TFunction textureOffset_00L20B10D00B( + BuiltInId::textureOffset_Sampler2DArray1_Float3_Int2_Float1, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20B10D00B, + 4, + StaticType::Get(), + EOpTextureOffsetBias, + false); +constexpr const TFunction textureOffset_00U20B10D00B( + BuiltInId::textureOffset_ISampler2DArray1_Float3_Int2_Float1, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20B10D00B, + 4, + StaticType::Get(), + EOpTextureOffsetBias, + false); +constexpr const TFunction textureOffset_00a20B10D00B( + BuiltInId::textureOffset_USampler2DArray1_Float3_Int2_Float1, + BuiltInName::textureOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20B10D00B, + 4, + StaticType::Get(), + EOpTextureOffsetBias, + false); +constexpr const TFunction textureProjOffset_00I20B10D00B( + BuiltInId::textureProjOffset_Sampler2D1_Float3_Int2_Float1, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I20B10D00B, + 4, + StaticType::Get(), + EOpTextureProjOffsetBias, + false); +constexpr const TFunction textureProjOffset_00R20B10D00B( + BuiltInId::textureProjOffset_ISampler2D1_Float3_Int2_Float1, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R20B10D00B, + 4, + StaticType::Get(), + EOpTextureProjOffsetBias, + false); +constexpr const TFunction textureProjOffset_00X20B10D00B( + BuiltInId::textureProjOffset_USampler2D1_Float3_Int2_Float1, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X20B10D00B, + 4, + StaticType::Get(), + EOpTextureProjOffsetBias, + false); +constexpr const TFunction textureProjOffset_00I30B10D00B( + BuiltInId::textureProjOffset_Sampler2D1_Float4_Int2_Float1, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I30B10D00B, + 4, + StaticType::Get(), + EOpTextureProjOffsetBias, + false); +constexpr const TFunction textureProjOffset_00R30B10D00B( + BuiltInId::textureProjOffset_ISampler2D1_Float4_Int2_Float1, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R30B10D00B, + 4, + StaticType::Get(), + EOpTextureProjOffsetBias, + false); +constexpr const TFunction textureProjOffset_00X30B10D00B( + BuiltInId::textureProjOffset_USampler2D1_Float4_Int2_Float1, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X30B10D00B, + 4, + StaticType::Get(), + EOpTextureProjOffsetBias, + false); +constexpr const TFunction textureProjOffset_00J30B20D00B( + BuiltInId::textureProjOffset_Sampler3D1_Float4_Int3_Float1, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00J30B20D00B, + 4, + StaticType::Get(), + EOpTextureProjOffsetBias, + false); +constexpr const TFunction textureProjOffset_00S30B20D00B( + BuiltInId::textureProjOffset_ISampler3D1_Float4_Int3_Float1, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00S30B20D00B, + 4, + StaticType::Get(), + EOpTextureProjOffsetBias, + false); +constexpr const TFunction textureProjOffset_00Y30B20D00B( + BuiltInId::textureProjOffset_USampler3D1_Float4_Int3_Float1, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Y30B20D00B, + 4, + StaticType::Get(), + EOpTextureProjOffsetBias, + false); +constexpr const TFunction textureProjOffset_00d30B10D00B( + BuiltInId::textureProjOffset_Sampler2DShadow1_Float4_Int2_Float1, + BuiltInName::textureProjOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d30B10D00B, + 4, + StaticType::Get(), + EOpTextureProjOffsetBias, + false); +constexpr const TFunction textureGather_00I10B( + BuiltInId::textureGather_Sampler2D1_Float2, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B00B10D, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00R10B( + BuiltInId::textureGather_ISampler2D1_Float2, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10B00B10D, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00X10B( + BuiltInId::textureGather_USampler2D1_Float2, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10B00B10D, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00I10B00D( + BuiltInId::textureGather_Sampler2D1_Float2_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00R10B00D( + BuiltInId::textureGather_ISampler2D1_Float2_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00X10B00D( + BuiltInId::textureGather_USampler2D1_Float2_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00L20B( + BuiltInId::textureGather_Sampler2DArray1_Float3, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20B00B10D, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00U20B( + BuiltInId::textureGather_ISampler2DArray1_Float3, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20B00B10D, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00a20B( + BuiltInId::textureGather_USampler2DArray1_Float3, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20B00B10D, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00L20B00D( + BuiltInId::textureGather_Sampler2DArray1_Float3_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00U20B00D( + BuiltInId::textureGather_ISampler2DArray1_Float3_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00a20B00D( + BuiltInId::textureGather_USampler2DArray1_Float3_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00K20B( + BuiltInId::textureGather_SamplerCube1_Float3, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00K20B00B, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00T20B( + BuiltInId::textureGather_ISamplerCube1_Float3, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00T20B00B, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00Z20B( + BuiltInId::textureGather_USamplerCube1_Float3, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Z20B00B, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00K20B00D( + BuiltInId::textureGather_SamplerCube1_Float3_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00K20B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00T20B00D( + BuiltInId::textureGather_ISamplerCube1_Float3_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00T20B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00Z20B00D( + BuiltInId::textureGather_USamplerCube1_Float3_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00Z20B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00k30B( + BuiltInId::textureGather_SamplerCubeArray1_Float4, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00k30B00B, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00s30B( + BuiltInId::textureGather_ISamplerCubeArray1_Float4, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00s30B00B, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00x30B( + BuiltInId::textureGather_USamplerCubeArray1_Float4, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00x30B00B, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00k30B00D( + BuiltInId::textureGather_SamplerCubeArray1_Float4_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00k30B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00s30B00D( + BuiltInId::textureGather_ISamplerCubeArray1_Float4_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00s30B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00x30B00D( + BuiltInId::textureGather_USamplerCubeArray1_Float4_Int1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00x30B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00l30B00B( + BuiltInId::textureGather_SamplerCubeArrayShadow1_Float4_Float1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00l30B00B, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGatherExt_00k30B( + BuiltInId::textureGatherExt_SamplerCubeArray1_Float4, + BuiltInName::textureGatherExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00k30B00B, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGatherExt_00s30B( + BuiltInId::textureGatherExt_ISamplerCubeArray1_Float4, + BuiltInName::textureGatherExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00s30B00B, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGatherExt_00x30B( + BuiltInId::textureGatherExt_USamplerCubeArray1_Float4, + BuiltInName::textureGatherExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00x30B00B, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGatherExt_00k30B00D( + BuiltInId::textureGatherExt_SamplerCubeArray1_Float4_Int1, + BuiltInName::textureGatherExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00k30B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGatherExt_00s30B00D( + BuiltInId::textureGatherExt_ISamplerCubeArray1_Float4_Int1, + BuiltInName::textureGatherExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00s30B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGatherExt_00x30B00D( + BuiltInId::textureGatherExt_USamplerCubeArray1_Float4_Int1, + BuiltInName::textureGatherExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00x30B00D, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGatherExt_00l30B00B( + BuiltInId::textureGatherExt_SamplerCubeArrayShadow1_Float4_Float1, + BuiltInName::textureGatherExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p00l30B00B, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00d10B( + BuiltInId::textureGather_Sampler2DShadow1_Float2, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d10B00B10Dx4, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00d10B00B( + BuiltInId::textureGather_Sampler2DShadow1_Float2_Float1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d10B00B10Dx4, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00f20B( + BuiltInId::textureGather_Sampler2DArrayShadow1_Float3, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00f20B00B10Dx4, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00f20B00B( + BuiltInId::textureGather_Sampler2DArrayShadow1_Float3_Float1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00f20B00B10Dx4, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00e20B( + BuiltInId::textureGather_SamplerCubeShadow1_Float3, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00e20B00B, + 2, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGather_00e20B00B( + BuiltInId::textureGather_SamplerCubeShadow1_Float3_Float1, + BuiltInName::textureGather, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00e20B00B, + 3, + StaticType::Get(), + EOpTextureGather, + false); +constexpr const TFunction textureGatherOffset_00I10B10D( + BuiltInId::textureGatherOffset_Sampler2D1_Float2_Int2, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B10D00B, + 3, + StaticType::Get(), + EOpTextureGatherOffset, + false); +constexpr const TFunction textureGatherOffset_00R10B10D( + BuiltInId::textureGatherOffset_ISampler2D1_Float2_Int2, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10B10D00B, + 3, + StaticType::Get(), + EOpTextureGatherOffset, + false); +constexpr const TFunction textureGatherOffset_00X10B10D( + BuiltInId::textureGatherOffset_USampler2D1_Float2_Int2, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10B10D00B, + 3, + StaticType::Get(), + EOpTextureGatherOffset, + false); +constexpr const TFunction textureGatherOffset_00L20B10D( + BuiltInId::textureGatherOffset_Sampler2DArray1_Float3_Int2, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20B10D00B, + 3, + StaticType::Get(), + EOpTextureGatherOffset, + false); +constexpr const TFunction textureGatherOffset_00U20B10D( + BuiltInId::textureGatherOffset_ISampler2DArray1_Float3_Int2, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20B10D00B, + 3, + StaticType::Get(), + EOpTextureGatherOffset, + false); +constexpr const TFunction textureGatherOffset_00a20B10D( + BuiltInId::textureGatherOffset_USampler2DArray1_Float3_Int2, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20B10D00B, + 3, + StaticType::Get(), + EOpTextureGatherOffset, + false); +constexpr const TFunction textureGatherOffset_00d10B00B10D( + BuiltInId::textureGatherOffset_Sampler2DShadow1_Float2_Float1_Int2, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d10B00B10Dx4, + 4, + StaticType::Get(), + EOpTextureGatherOffset, + false); +constexpr const TFunction textureGatherOffset_00f20B00B10D( + BuiltInId::textureGatherOffset_Sampler2DArrayShadow1_Float3_Float1_Int2, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00f20B00B10Dx4, + 4, + StaticType::Get(), + EOpTextureGatherOffset, + false); +constexpr const TFunction textureGatherOffset_00I10B10D00D( + BuiltInId::textureGatherOffset_Sampler2D1_Float2_Int2_Int1, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B10D00D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetComp, + false); +constexpr const TFunction textureGatherOffset_00R10B10D00D( + BuiltInId::textureGatherOffset_ISampler2D1_Float2_Int2_Int1, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10B10D00D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetComp, + false); +constexpr const TFunction textureGatherOffset_00X10B10D00D( + BuiltInId::textureGatherOffset_USampler2D1_Float2_Int2_Int1, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10B10D00D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetComp, + false); +constexpr const TFunction textureGatherOffset_00L20B10D00D( + BuiltInId::textureGatherOffset_Sampler2DArray1_Float3_Int2_Int1, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20B10D00D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetComp, + false); +constexpr const TFunction textureGatherOffset_00U20B10D00D( + BuiltInId::textureGatherOffset_ISampler2DArray1_Float3_Int2_Int1, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20B10D00D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetComp, + false); +constexpr const TFunction textureGatherOffset_00a20B10D00D( + BuiltInId::textureGatherOffset_USampler2DArray1_Float3_Int2_Int1, + BuiltInName::textureGatherOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20B10D00D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetComp, + false); +constexpr const TFunction textureGatherOffsets_00I10B10Dx4( + BuiltInId::textureGatherOffsets_Sampler2D1_Float2_4xInt2, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B10Dx400D, + 3, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsets_00R10B10Dx4( + BuiltInId::textureGatherOffsets_ISampler2D1_Float2_4xInt2, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10B10Dx400D, + 3, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsets_00X10B10Dx4( + BuiltInId::textureGatherOffsets_USampler2D1_Float2_4xInt2, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10B10Dx400D, + 3, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsets_00L20B10Dx4( + BuiltInId::textureGatherOffsets_Sampler2DArray1_Float3_4xInt2, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20B10Dx400D, + 3, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsets_00U20B10Dx4( + BuiltInId::textureGatherOffsets_ISampler2DArray1_Float3_4xInt2, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20B10Dx400D, + 3, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsets_00a20B10Dx4( + BuiltInId::textureGatherOffsets_USampler2DArray1_Float3_4xInt2, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20B10Dx400D, + 3, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsets_00d10B00B10Dx4( + BuiltInId::textureGatherOffsets_Sampler2DShadow1_Float2_Float1_4xInt2, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00d10B00B10Dx4, + 4, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsets_00f20B00B10Dx4( + BuiltInId::textureGatherOffsets_Sampler2DArrayShadow1_Float3_Float1_4xInt2, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00f20B00B10Dx4, + 4, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsetsExt_00I10B10Dx4( + BuiltInId::textureGatherOffsetsExt_Sampler2D1_Float2_4xInt2, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00I10B10Dx400D, + 3, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsetsExt_00R10B10Dx4( + BuiltInId::textureGatherOffsetsExt_ISampler2D1_Float2_4xInt2, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00R10B10Dx400D, + 3, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsetsExt_00X10B10Dx4( + BuiltInId::textureGatherOffsetsExt_USampler2D1_Float2_4xInt2, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00X10B10Dx400D, + 3, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsetsExt_00L20B10Dx4( + BuiltInId::textureGatherOffsetsExt_Sampler2DArray1_Float3_4xInt2, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00L20B10Dx400D, + 3, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsetsExt_00U20B10Dx4( + BuiltInId::textureGatherOffsetsExt_ISampler2DArray1_Float3_4xInt2, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00U20B10Dx400D, + 3, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsetsExt_00a20B10Dx4( + BuiltInId::textureGatherOffsetsExt_USampler2DArray1_Float3_4xInt2, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00a20B10Dx400D, + 3, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsetsExt_00d10B00B10Dx4( + BuiltInId::textureGatherOffsetsExt_Sampler2DShadow1_Float2_Float1_4xInt2, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00d10B00B10Dx4, + 4, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsetsExt_00f20B00B10Dx4( + BuiltInId::textureGatherOffsetsExt_Sampler2DArrayShadow1_Float3_Float1_4xInt2, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00f20B00B10Dx4, + 4, + StaticType::Get(), + EOpTextureGatherOffsets, + false); +constexpr const TFunction textureGatherOffsets_00I10B10Dx400D( + BuiltInId::textureGatherOffsets_Sampler2D1_Float2_4xInt2_Int1, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00I10B10Dx400D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsComp, + false); +constexpr const TFunction textureGatherOffsets_00R10B10Dx400D( + BuiltInId::textureGatherOffsets_ISampler2D1_Float2_4xInt2_Int1, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00R10B10Dx400D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsComp, + false); +constexpr const TFunction textureGatherOffsets_00X10B10Dx400D( + BuiltInId::textureGatherOffsets_USampler2D1_Float2_4xInt2_Int1, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00X10B10Dx400D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsComp, + false); +constexpr const TFunction textureGatherOffsets_00L20B10Dx400D( + BuiltInId::textureGatherOffsets_Sampler2DArray1_Float3_4xInt2_Int1, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00L20B10Dx400D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsComp, + false); +constexpr const TFunction textureGatherOffsets_00U20B10Dx400D( + BuiltInId::textureGatherOffsets_ISampler2DArray1_Float3_4xInt2_Int1, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00U20B10Dx400D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsComp, + false); +constexpr const TFunction textureGatherOffsets_00a20B10Dx400D( + BuiltInId::textureGatherOffsets_USampler2DArray1_Float3_4xInt2_Int1, + BuiltInName::textureGatherOffsets, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00a20B10Dx400D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsComp, + false); +constexpr const TFunction textureGatherOffsetsExt_00I10B10Dx400D( + BuiltInId::textureGatherOffsetsExt_Sampler2D1_Float2_4xInt2_Int1, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00I10B10Dx400D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsComp, + false); +constexpr const TFunction textureGatherOffsetsExt_00R10B10Dx400D( + BuiltInId::textureGatherOffsetsExt_ISampler2D1_Float2_4xInt2_Int1, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00R10B10Dx400D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsComp, + false); +constexpr const TFunction textureGatherOffsetsExt_00X10B10Dx400D( + BuiltInId::textureGatherOffsetsExt_USampler2D1_Float2_4xInt2_Int1, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00X10B10Dx400D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsComp, + false); +constexpr const TFunction textureGatherOffsetsExt_00L20B10Dx400D( + BuiltInId::textureGatherOffsetsExt_Sampler2DArray1_Float3_4xInt2_Int1, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00L20B10Dx400D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsComp, + false); +constexpr const TFunction textureGatherOffsetsExt_00U20B10Dx400D( + BuiltInId::textureGatherOffsetsExt_ISampler2DArray1_Float3_4xInt2_Int1, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00U20B10Dx400D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsComp, + false); +constexpr const TFunction textureGatherOffsetsExt_00a20B10Dx400D( + BuiltInId::textureGatherOffsetsExt_USampler2DArray1_Float3_4xInt2_Int1, + BuiltInName::textureGatherOffsetsExt, + std::array{{TExtension::EXT_gpu_shader5}}, + BuiltInParameters::p00a20B10Dx400D, + 4, + StaticType::Get(), + EOpTextureGatherOffsetsComp, + false); +constexpr const TFunction rgb_2_yuv_20B00H( + BuiltInId::rgb_2_yuv_Float3_YuvCscStandardEXT1, + BuiltInName::rgb_2_yuv, + std::array{{TExtension::EXT_YUV_target}}, + BuiltInParameters::p20B00H, + 2, + StaticType::Get(), + EOpRgb_2_yuv, + false); +constexpr const TFunction yuv_2_rgb_20B00H( + BuiltInId::yuv_2_rgb_Float3_YuvCscStandardEXT1, + BuiltInName::yuv_2_rgb, + std::array{{TExtension::EXT_YUV_target}}, + BuiltInParameters::p20B00H, + 2, + StaticType::Get(), + EOpYuv_2_rgb, + false); +constexpr const TFunction dFdxExt_00B(BuiltInId::dFdxExt_Float1, + BuiltInName::dFdxExt, + std::array{ + {TExtension::OES_standard_derivatives}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpDFdx, + false); +constexpr const TFunction dFdxExt_10B(BuiltInId::dFdxExt_Float2, + BuiltInName::dFdxExt, + std::array{ + {TExtension::OES_standard_derivatives}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpDFdx, + false); +constexpr const TFunction dFdxExt_20B(BuiltInId::dFdxExt_Float3, + BuiltInName::dFdxExt, + std::array{ + {TExtension::OES_standard_derivatives}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpDFdx, + false); +constexpr const TFunction dFdxExt_30B(BuiltInId::dFdxExt_Float4, + BuiltInName::dFdxExt, + std::array{ + {TExtension::OES_standard_derivatives}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpDFdx, + false); +constexpr const TFunction dFdyExt_00B(BuiltInId::dFdyExt_Float1, + BuiltInName::dFdyExt, + std::array{ + {TExtension::OES_standard_derivatives}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpDFdy, + false); +constexpr const TFunction dFdyExt_10B(BuiltInId::dFdyExt_Float2, + BuiltInName::dFdyExt, + std::array{ + {TExtension::OES_standard_derivatives}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpDFdy, + false); +constexpr const TFunction dFdyExt_20B(BuiltInId::dFdyExt_Float3, + BuiltInName::dFdyExt, + std::array{ + {TExtension::OES_standard_derivatives}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpDFdy, + false); +constexpr const TFunction dFdyExt_30B(BuiltInId::dFdyExt_Float4, + BuiltInName::dFdyExt, + std::array{ + {TExtension::OES_standard_derivatives}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpDFdy, + false); +constexpr const TFunction fwidthExt_00B(BuiltInId::fwidthExt_Float1, + BuiltInName::fwidthExt, + std::array{ + {TExtension::OES_standard_derivatives}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpFwidth, + false); +constexpr const TFunction fwidthExt_10B(BuiltInId::fwidthExt_Float2, + BuiltInName::fwidthExt, + std::array{ + {TExtension::OES_standard_derivatives}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpFwidth, + false); +constexpr const TFunction fwidthExt_20B(BuiltInId::fwidthExt_Float3, + BuiltInName::fwidthExt, + std::array{ + {TExtension::OES_standard_derivatives}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpFwidth, + false); +constexpr const TFunction fwidthExt_30B(BuiltInId::fwidthExt_Float4, + BuiltInName::fwidthExt, + std::array{ + {TExtension::OES_standard_derivatives}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpFwidth, + false); +constexpr const TFunction dFdx_00B(BuiltInId::dFdx_Float1, + BuiltInName::dFdx, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpDFdx, + false); +constexpr const TFunction dFdx_10B(BuiltInId::dFdx_Float2, + BuiltInName::dFdx, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpDFdx, + false); +constexpr const TFunction dFdx_20B(BuiltInId::dFdx_Float3, + BuiltInName::dFdx, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpDFdx, + false); +constexpr const TFunction dFdx_30B(BuiltInId::dFdx_Float4, + BuiltInName::dFdx, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpDFdx, + false); +constexpr const TFunction dFdy_00B(BuiltInId::dFdy_Float1, + BuiltInName::dFdy, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpDFdy, + false); +constexpr const TFunction dFdy_10B(BuiltInId::dFdy_Float2, + BuiltInName::dFdy, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpDFdy, + false); +constexpr const TFunction dFdy_20B(BuiltInId::dFdy_Float3, + BuiltInName::dFdy, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpDFdy, + false); +constexpr const TFunction dFdy_30B(BuiltInId::dFdy_Float4, + BuiltInName::dFdy, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpDFdy, + false); +constexpr const TFunction fwidth_00B(BuiltInId::fwidth_Float1, + BuiltInName::fwidth, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpFwidth, + false); +constexpr const TFunction fwidth_10B(BuiltInId::fwidth_Float2, + BuiltInName::fwidth, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpFwidth, + false); +constexpr const TFunction fwidth_20B(BuiltInId::fwidth_Float3, + BuiltInName::fwidth, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpFwidth, + false); +constexpr const TFunction fwidth_30B(BuiltInId::fwidth_Float4, + BuiltInName::fwidth, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpFwidth, + false); +constexpr const TFunction interpolateAtCentroid_00B( + BuiltInId::interpolateAtCentroid_Float1, + BuiltInName::interpolateAtCentroid, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpInterpolateAtCentroid, + false); +constexpr const TFunction interpolateAtCentroid_10B( + BuiltInId::interpolateAtCentroid_Float2, + BuiltInName::interpolateAtCentroid, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpInterpolateAtCentroid, + false); +constexpr const TFunction interpolateAtCentroid_20B( + BuiltInId::interpolateAtCentroid_Float3, + BuiltInName::interpolateAtCentroid, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpInterpolateAtCentroid, + false); +constexpr const TFunction interpolateAtCentroid_30B( + BuiltInId::interpolateAtCentroid_Float4, + BuiltInName::interpolateAtCentroid, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpInterpolateAtCentroid, + false); +constexpr const TFunction interpolateAtSample_00B00D( + BuiltInId::interpolateAtSample_Float1_Int1, + BuiltInName::interpolateAtSample, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B00D, + 2, + StaticType::Get(), + EOpInterpolateAtSample, + false); +constexpr const TFunction interpolateAtSample_10B00D( + BuiltInId::interpolateAtSample_Float2_Int1, + BuiltInName::interpolateAtSample, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B00D, + 2, + StaticType::Get(), + EOpInterpolateAtSample, + false); +constexpr const TFunction interpolateAtSample_20B00D( + BuiltInId::interpolateAtSample_Float3_Int1, + BuiltInName::interpolateAtSample, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B00D, + 2, + StaticType::Get(), + EOpInterpolateAtSample, + false); +constexpr const TFunction interpolateAtSample_30B00D( + BuiltInId::interpolateAtSample_Float4_Int1, + BuiltInName::interpolateAtSample, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B00D, + 2, + StaticType::Get(), + EOpInterpolateAtSample, + false); +constexpr const TFunction interpolateAtOffset_00B10B( + BuiltInId::interpolateAtOffset_Float1_Float2, + BuiltInName::interpolateAtOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00B10B, + 2, + StaticType::Get(), + EOpInterpolateAtOffset, + false); +constexpr const TFunction interpolateAtOffset_10B10B( + BuiltInId::interpolateAtOffset_Float2_Float2, + BuiltInName::interpolateAtOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpInterpolateAtOffset, + false); +constexpr const TFunction interpolateAtOffset_20B10B( + BuiltInId::interpolateAtOffset_Float3_Float2, + BuiltInName::interpolateAtOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p20B10B, + 2, + StaticType::Get(), + EOpInterpolateAtOffset, + false); +constexpr const TFunction interpolateAtOffset_30B10B( + BuiltInId::interpolateAtOffset_Float4_Float2, + BuiltInName::interpolateAtOffset, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p30B10B, + 2, + StaticType::Get(), + EOpInterpolateAtOffset, + false); +constexpr const TFunction interpolateAtCentroidExt_00B( + BuiltInId::interpolateAtCentroidExt_Float1, + BuiltInName::interpolateAtCentroidExt, + std::array{{TExtension::OES_shader_multisample_interpolation}}, + BuiltInParameters::p00B00B00B, + 1, + StaticType::Get(), + EOpInterpolateAtCentroid, + false); +constexpr const TFunction interpolateAtCentroidExt_10B( + BuiltInId::interpolateAtCentroidExt_Float2, + BuiltInName::interpolateAtCentroidExt, + std::array{{TExtension::OES_shader_multisample_interpolation}}, + BuiltInParameters::p10B00B00B, + 1, + StaticType::Get(), + EOpInterpolateAtCentroid, + false); +constexpr const TFunction interpolateAtCentroidExt_20B( + BuiltInId::interpolateAtCentroidExt_Float3, + BuiltInName::interpolateAtCentroidExt, + std::array{{TExtension::OES_shader_multisample_interpolation}}, + BuiltInParameters::p20B00B00B, + 1, + StaticType::Get(), + EOpInterpolateAtCentroid, + false); +constexpr const TFunction interpolateAtCentroidExt_30B( + BuiltInId::interpolateAtCentroidExt_Float4, + BuiltInName::interpolateAtCentroidExt, + std::array{{TExtension::OES_shader_multisample_interpolation}}, + BuiltInParameters::p30B00B00B, + 1, + StaticType::Get(), + EOpInterpolateAtCentroid, + false); +constexpr const TFunction interpolateAtSampleExt_00B00D( + BuiltInId::interpolateAtSampleExt_Float1_Int1, + BuiltInName::interpolateAtSampleExt, + std::array{{TExtension::OES_shader_multisample_interpolation}}, + BuiltInParameters::p00B00D, + 2, + StaticType::Get(), + EOpInterpolateAtSample, + false); +constexpr const TFunction interpolateAtSampleExt_10B00D( + BuiltInId::interpolateAtSampleExt_Float2_Int1, + BuiltInName::interpolateAtSampleExt, + std::array{{TExtension::OES_shader_multisample_interpolation}}, + BuiltInParameters::p10B00D, + 2, + StaticType::Get(), + EOpInterpolateAtSample, + false); +constexpr const TFunction interpolateAtSampleExt_20B00D( + BuiltInId::interpolateAtSampleExt_Float3_Int1, + BuiltInName::interpolateAtSampleExt, + std::array{{TExtension::OES_shader_multisample_interpolation}}, + BuiltInParameters::p20B00D, + 2, + StaticType::Get(), + EOpInterpolateAtSample, + false); +constexpr const TFunction interpolateAtSampleExt_30B00D( + BuiltInId::interpolateAtSampleExt_Float4_Int1, + BuiltInName::interpolateAtSampleExt, + std::array{{TExtension::OES_shader_multisample_interpolation}}, + BuiltInParameters::p30B00D, + 2, + StaticType::Get(), + EOpInterpolateAtSample, + false); +constexpr const TFunction interpolateAtOffsetExt_00B10B( + BuiltInId::interpolateAtOffsetExt_Float1_Float2, + BuiltInName::interpolateAtOffsetExt, + std::array{{TExtension::OES_shader_multisample_interpolation}}, + BuiltInParameters::p00B10B, + 2, + StaticType::Get(), + EOpInterpolateAtOffset, + false); +constexpr const TFunction interpolateAtOffsetExt_10B10B( + BuiltInId::interpolateAtOffsetExt_Float2_Float2, + BuiltInName::interpolateAtOffsetExt, + std::array{{TExtension::OES_shader_multisample_interpolation}}, + BuiltInParameters::p10B10B00B, + 2, + StaticType::Get(), + EOpInterpolateAtOffset, + false); +constexpr const TFunction interpolateAtOffsetExt_20B10B( + BuiltInId::interpolateAtOffsetExt_Float3_Float2, + BuiltInName::interpolateAtOffsetExt, + std::array{{TExtension::OES_shader_multisample_interpolation}}, + BuiltInParameters::p20B10B, + 2, + StaticType::Get(), + EOpInterpolateAtOffset, + false); +constexpr const TFunction interpolateAtOffsetExt_30B10B( + BuiltInId::interpolateAtOffsetExt_Float4_Float2, + BuiltInName::interpolateAtOffsetExt, + std::array{{TExtension::OES_shader_multisample_interpolation}}, + BuiltInParameters::p30B10B, + 2, + StaticType::Get(), + EOpInterpolateAtOffset, + false); +constexpr const TFunction atomicCounter_00G( + BuiltInId::atomicCounter_AtomicCounter1, + BuiltInName::atomicCounter, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00G, + 1, + StaticType::Get(), + EOpAtomicCounter, + false); +constexpr const TFunction atomicCounterIncrement_00G( + BuiltInId::atomicCounterIncrement_AtomicCounter1, + BuiltInName::atomicCounterIncrement, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00G, + 1, + StaticType::Get(), + EOpAtomicCounterIncrement, + false); +constexpr const TFunction atomicCounterDecrement_00G( + BuiltInId::atomicCounterDecrement_AtomicCounter1, + BuiltInName::atomicCounterDecrement, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00G, + 1, + StaticType::Get(), + EOpAtomicCounterDecrement, + false); +constexpr const TFunction atomicAdd_00E00E( + BuiltInId::atomicAdd_UInt1_UInt1, + BuiltInName::atomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00E00E00E, + 2, + StaticType::Get(), + EOpAtomicAdd, + false); +constexpr const TFunction atomicAdd_00D00D(BuiltInId::atomicAdd_Int1_Int1, + BuiltInName::atomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00D00D00D, + 2, + StaticType::Get(), + EOpAtomicAdd, + false); +constexpr const TFunction atomicMin_00E00E( + BuiltInId::atomicMin_UInt1_UInt1, + BuiltInName::atomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00E00E00E, + 2, + StaticType::Get(), + EOpAtomicMin, + false); +constexpr const TFunction atomicMin_00D00D(BuiltInId::atomicMin_Int1_Int1, + BuiltInName::atomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00D00D00D, + 2, + StaticType::Get(), + EOpAtomicMin, + false); +constexpr const TFunction atomicMax_00E00E( + BuiltInId::atomicMax_UInt1_UInt1, + BuiltInName::atomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00E00E00E, + 2, + StaticType::Get(), + EOpAtomicMax, + false); +constexpr const TFunction atomicMax_00D00D(BuiltInId::atomicMax_Int1_Int1, + BuiltInName::atomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00D00D00D, + 2, + StaticType::Get(), + EOpAtomicMax, + false); +constexpr const TFunction atomicAnd_00E00E( + BuiltInId::atomicAnd_UInt1_UInt1, + BuiltInName::atomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00E00E00E, + 2, + StaticType::Get(), + EOpAtomicAnd, + false); +constexpr const TFunction atomicAnd_00D00D(BuiltInId::atomicAnd_Int1_Int1, + BuiltInName::atomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00D00D00D, + 2, + StaticType::Get(), + EOpAtomicAnd, + false); +constexpr const TFunction atomicOr_00E00E(BuiltInId::atomicOr_UInt1_UInt1, + BuiltInName::atomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00E00E00E, + 2, + StaticType::Get(), + EOpAtomicOr, + false); +constexpr const TFunction atomicOr_00D00D(BuiltInId::atomicOr_Int1_Int1, + BuiltInName::atomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00D00D00D, + 2, + StaticType::Get(), + EOpAtomicOr, + false); +constexpr const TFunction atomicXor_00E00E( + BuiltInId::atomicXor_UInt1_UInt1, + BuiltInName::atomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00E00E00E, + 2, + StaticType::Get(), + EOpAtomicXor, + false); +constexpr const TFunction atomicXor_00D00D(BuiltInId::atomicXor_Int1_Int1, + BuiltInName::atomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00D00D00D, + 2, + StaticType::Get(), + EOpAtomicXor, + false); +constexpr const TFunction atomicExchange_00E00E( + BuiltInId::atomicExchange_UInt1_UInt1, + BuiltInName::atomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00E00E00E, + 2, + StaticType::Get(), + EOpAtomicExchange, + false); +constexpr const TFunction atomicExchange_00D00D( + BuiltInId::atomicExchange_Int1_Int1, + BuiltInName::atomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00D00D00D, + 2, + StaticType::Get(), + EOpAtomicExchange, + false); +constexpr const TFunction atomicCompSwap_00E00E00E( + BuiltInId::atomicCompSwap_UInt1_UInt1_UInt1, + BuiltInName::atomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00E00E00E, + 3, + StaticType::Get(), + EOpAtomicCompSwap, + false); +constexpr const TFunction atomicCompSwap_00D00D00D( + BuiltInId::atomicCompSwap_Int1_Int1_Int1, + BuiltInName::atomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p_io_00D00D00D, + 3, + StaticType::Get(), + EOpAtomicCompSwap, + false); +constexpr const TFunction imageSize_00z(BuiltInId::imageSize_Image2D1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01K(BuiltInId::imageSize_IImage2D1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01V(BuiltInId::imageSize_UImage2D1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01A(BuiltInId::imageSize_Image3D1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01L(BuiltInId::imageSize_IImage3D1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01W(BuiltInId::imageSize_UImage3D1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01B(BuiltInId::imageSize_Image2DArray1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01M(BuiltInId::imageSize_IImage2DArray1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01X(BuiltInId::imageSize_UImage2DArray1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01C(BuiltInId::imageSize_ImageCube1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01N(BuiltInId::imageSize_IImageCube1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01Y(BuiltInId::imageSize_UImageCube1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01H(BuiltInId::imageSize_ImageCubeArray1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01S(BuiltInId::imageSize_IImageCubeArray1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01d(BuiltInId::imageSize_UImageCubeArray1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSizeExt_01H(BuiltInId::imageSizeExt_ImageCubeArray1, + BuiltInName::imageSizeExt, + std::array{ + {TExtension::OES_texture_cube_map_array, + TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p01H20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSizeExt_01S(BuiltInId::imageSizeExt_IImageCubeArray1, + BuiltInName::imageSizeExt, + std::array{ + {TExtension::OES_texture_cube_map_array, + TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p01S20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSizeExt_01d(BuiltInId::imageSizeExt_UImageCubeArray1, + BuiltInName::imageSizeExt, + std::array{ + {TExtension::OES_texture_cube_map_array, + TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p01d20D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01J(BuiltInId::imageSize_ImageBuffer1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01U(BuiltInId::imageSize_IImageBuffer1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSize_01f(BuiltInId::imageSize_UImageBuffer1, + BuiltInName::imageSize, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSizeExt_01J( + BuiltInId::imageSizeExt_ImageBuffer1, + BuiltInName::imageSizeExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p01J00D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSizeExt_01U( + BuiltInId::imageSizeExt_IImageBuffer1, + BuiltInName::imageSizeExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p01U00D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageSizeExt_01f( + BuiltInId::imageSizeExt_UImageBuffer1, + BuiltInName::imageSizeExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p01f00D00B, + 1, + StaticType::Get(), + EOpImageSize, + false); +constexpr const TFunction imageStore_00z10D30B( + BuiltInId::imageStore_Image2D1_Int2_Float4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D30B, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01K10D30D( + BuiltInId::imageStore_IImage2D1_Int2_Int4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D30D, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01V10D30E( + BuiltInId::imageStore_UImage2D1_Int2_UInt4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D30E, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01A20D30B( + BuiltInId::imageStore_Image3D1_Int3_Float4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D30B, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01L20D30D( + BuiltInId::imageStore_IImage3D1_Int3_Int4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D30D, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01W20D30E( + BuiltInId::imageStore_UImage3D1_Int3_UInt4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D30E, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01B20D30B( + BuiltInId::imageStore_Image2DArray1_Int3_Float4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D30B, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01M20D30D( + BuiltInId::imageStore_IImage2DArray1_Int3_Int4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D30D, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01X20D30E( + BuiltInId::imageStore_UImage2DArray1_Int3_UInt4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D30E, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01C20D30B( + BuiltInId::imageStore_ImageCube1_Int3_Float4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D30B, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01N20D30D( + BuiltInId::imageStore_IImageCube1_Int3_Int4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D30D, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01Y20D30E( + BuiltInId::imageStore_UImageCube1_Int3_UInt4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D30E, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01H20D30B( + BuiltInId::imageStore_ImageCubeArray1_Int3_Float4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D30B, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01S20D30D( + BuiltInId::imageStore_IImageCubeArray1_Int3_Int4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D30D, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01d20D30E( + BuiltInId::imageStore_UImageCubeArray1_Int3_UInt4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D30E, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStoreExt_01H20D30B( + BuiltInId::imageStoreExt_ImageCubeArray1_Int3_Float4, + BuiltInName::imageStoreExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p01H20D30B, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStoreExt_01S20D30D( + BuiltInId::imageStoreExt_IImageCubeArray1_Int3_Int4, + BuiltInName::imageStoreExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p01S20D30D, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStoreExt_01d20D30E( + BuiltInId::imageStoreExt_UImageCubeArray1_Int3_UInt4, + BuiltInName::imageStoreExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p01d20D30E, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01J00D30B( + BuiltInId::imageStore_ImageBuffer1_Int1_Float4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D30B, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01U00D30D( + BuiltInId::imageStore_IImageBuffer1_Int1_Int4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D30D, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStore_01f00D30E( + BuiltInId::imageStore_UImageBuffer1_Int1_UInt4, + BuiltInName::imageStore, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D30E, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStoreExt_01J00D30B( + BuiltInId::imageStoreExt_ImageBuffer1_Int1_Float4, + BuiltInName::imageStoreExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p01J00D30B, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStoreExt_01U00D30D( + BuiltInId::imageStoreExt_IImageBuffer1_Int1_Int4, + BuiltInName::imageStoreExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p01U00D30D, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageStoreExt_01f00D30E( + BuiltInId::imageStoreExt_UImageBuffer1_Int1_UInt4, + BuiltInName::imageStoreExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p01f00D30E, + 3, + StaticType::Get(), + EOpImageStore, + false); +constexpr const TFunction imageLoad_00z10D( + BuiltInId::imageLoad_Image2D1_Int2, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01K10D(BuiltInId::imageLoad_IImage2D1_Int2, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01V10D( + BuiltInId::imageLoad_UImage2D1_Int2, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01A20D( + BuiltInId::imageLoad_Image3D1_Int3, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01L20D(BuiltInId::imageLoad_IImage3D1_Int3, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01W20D( + BuiltInId::imageLoad_UImage3D1_Int3, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01B20D( + BuiltInId::imageLoad_Image2DArray1_Int3, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01M20D(BuiltInId::imageLoad_IImage2DArray1_Int3, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01X20D( + BuiltInId::imageLoad_UImage2DArray1_Int3, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01C20D( + BuiltInId::imageLoad_ImageCube1_Int3, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01N20D(BuiltInId::imageLoad_IImageCube1_Int3, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01Y20D( + BuiltInId::imageLoad_UImageCube1_Int3, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01H20D( + BuiltInId::imageLoad_ImageCubeArray1_Int3, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01S20D(BuiltInId::imageLoad_IImageCubeArray1_Int3, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01d20D( + BuiltInId::imageLoad_UImageCubeArray1_Int3, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoadExt_01H20D( + BuiltInId::imageLoadExt_ImageCubeArray1_Int3, + BuiltInName::imageLoadExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p01H20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoadExt_01S20D( + BuiltInId::imageLoadExt_IImageCubeArray1_Int3, + BuiltInName::imageLoadExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p01S20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoadExt_01d20D( + BuiltInId::imageLoadExt_UImageCubeArray1_Int3, + BuiltInName::imageLoadExt, + std::array{ + {TExtension::OES_texture_cube_map_array, TExtension::EXT_texture_cube_map_array}}, + BuiltInParameters::p01d20D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01J00D( + BuiltInId::imageLoad_ImageBuffer1_Int1, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01U00D(BuiltInId::imageLoad_IImageBuffer1_Int1, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoad_01f00D( + BuiltInId::imageLoad_UImageBuffer1_Int1, + BuiltInName::imageLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoadExt_01J00D( + BuiltInId::imageLoadExt_ImageBuffer1_Int1, + BuiltInName::imageLoadExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p01J00D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoadExt_01U00D( + BuiltInId::imageLoadExt_IImageBuffer1_Int1, + BuiltInName::imageLoadExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p01U00D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageLoadExt_01f00D( + BuiltInId::imageLoadExt_UImageBuffer1_Int1, + BuiltInName::imageLoadExt, + std::array{{TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}, + BuiltInParameters::p01f00D00B, + 2, + StaticType::Get(), + EOpImageLoad, + false); +constexpr const TFunction imageAtomicAdd_00z10D00E( + BuiltInId::imageAtomicAdd_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01K10D00E( + BuiltInId::imageAtomicAdd_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01V10D00E( + BuiltInId::imageAtomicAdd_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01A20D00E( + BuiltInId::imageAtomicAdd_Image3D1_Int3_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01L20D00E( + BuiltInId::imageAtomicAdd_IImage3D1_Int3_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01W20D00E( + BuiltInId::imageAtomicAdd_UImage3D1_Int3_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01C20D00E( + BuiltInId::imageAtomicAdd_ImageCube1_Int3_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01N20D00E( + BuiltInId::imageAtomicAdd_IImageCube1_Int3_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01Y20D00E( + BuiltInId::imageAtomicAdd_UImageCube1_Int3_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01J00D00E( + BuiltInId::imageAtomicAdd_ImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01U00D00E( + BuiltInId::imageAtomicAdd_IImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01f00D00E( + BuiltInId::imageAtomicAdd_UImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01B20D00E( + BuiltInId::imageAtomicAdd_Image2DArray1_Int3_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01M20D00E( + BuiltInId::imageAtomicAdd_IImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01X20D00E( + BuiltInId::imageAtomicAdd_UImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01H20D00E( + BuiltInId::imageAtomicAdd_ImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01S20D00E( + BuiltInId::imageAtomicAdd_IImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01d20D00E( + BuiltInId::imageAtomicAdd_UImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01D00D00E( + BuiltInId::imageAtomicAdd_Image1D1_Int1_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01O00D00E( + BuiltInId::imageAtomicAdd_IImage1D1_Int1_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01Z00D00E( + BuiltInId::imageAtomicAdd_UImage1D1_Int1_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01E10D00E( + BuiltInId::imageAtomicAdd_Image1DArray1_Int2_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01P10D00E( + BuiltInId::imageAtomicAdd_IImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01a10D00E( + BuiltInId::imageAtomicAdd_UImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01I10D00E( + BuiltInId::imageAtomicAdd_ImageRect1_Int2_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01T10D00E( + BuiltInId::imageAtomicAdd_IImageRect1_Int2_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01e10D00E( + BuiltInId::imageAtomicAdd_UImageRect1_Int2_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01F10D00D00E( + BuiltInId::imageAtomicAdd_Image2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01Q10D00D00E( + BuiltInId::imageAtomicAdd_IImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01b10D00D00E( + BuiltInId::imageAtomicAdd_UImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01G20D00D00E( + BuiltInId::imageAtomicAdd_Image2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01R20D00D00E( + BuiltInId::imageAtomicAdd_IImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01c20D00D00E( + BuiltInId::imageAtomicAdd_UImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_00z10D00D( + BuiltInId::imageAtomicAdd_Image2D1_Int2_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01K10D00D( + BuiltInId::imageAtomicAdd_IImage2D1_Int2_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01V10D00D( + BuiltInId::imageAtomicAdd_UImage2D1_Int2_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01A20D00D( + BuiltInId::imageAtomicAdd_Image3D1_Int3_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01L20D00D( + BuiltInId::imageAtomicAdd_IImage3D1_Int3_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01W20D00D( + BuiltInId::imageAtomicAdd_UImage3D1_Int3_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01C20D00D( + BuiltInId::imageAtomicAdd_ImageCube1_Int3_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01N20D00D( + BuiltInId::imageAtomicAdd_IImageCube1_Int3_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01Y20D00D( + BuiltInId::imageAtomicAdd_UImageCube1_Int3_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01J00D00D( + BuiltInId::imageAtomicAdd_ImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01U00D00D( + BuiltInId::imageAtomicAdd_IImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01f00D00D( + BuiltInId::imageAtomicAdd_UImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01B20D00D( + BuiltInId::imageAtomicAdd_Image2DArray1_Int3_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01M20D00D( + BuiltInId::imageAtomicAdd_IImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01X20D00D( + BuiltInId::imageAtomicAdd_UImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01H20D00D( + BuiltInId::imageAtomicAdd_ImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01S20D00D( + BuiltInId::imageAtomicAdd_IImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01d20D00D( + BuiltInId::imageAtomicAdd_UImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01D00D00D( + BuiltInId::imageAtomicAdd_Image1D1_Int1_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01O00D00D( + BuiltInId::imageAtomicAdd_IImage1D1_Int1_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01Z00D00D( + BuiltInId::imageAtomicAdd_UImage1D1_Int1_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01E10D00D( + BuiltInId::imageAtomicAdd_Image1DArray1_Int2_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01P10D00D( + BuiltInId::imageAtomicAdd_IImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01a10D00D( + BuiltInId::imageAtomicAdd_UImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01I10D00D( + BuiltInId::imageAtomicAdd_ImageRect1_Int2_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01T10D00D( + BuiltInId::imageAtomicAdd_IImageRect1_Int2_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01e10D00D( + BuiltInId::imageAtomicAdd_UImageRect1_Int2_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01F10D00D00D( + BuiltInId::imageAtomicAdd_Image2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01Q10D00D00D( + BuiltInId::imageAtomicAdd_IImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01b10D00D00D( + BuiltInId::imageAtomicAdd_UImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01G20D00D00D( + BuiltInId::imageAtomicAdd_Image2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01R20D00D00D( + BuiltInId::imageAtomicAdd_IImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAdd_01c20D00D00D( + BuiltInId::imageAtomicAdd_UImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicAdd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicMin_00z10D00E( + BuiltInId::imageAtomicMin_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01K10D00E( + BuiltInId::imageAtomicMin_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01V10D00E( + BuiltInId::imageAtomicMin_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01A20D00E( + BuiltInId::imageAtomicMin_Image3D1_Int3_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01L20D00E( + BuiltInId::imageAtomicMin_IImage3D1_Int3_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01W20D00E( + BuiltInId::imageAtomicMin_UImage3D1_Int3_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01C20D00E( + BuiltInId::imageAtomicMin_ImageCube1_Int3_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01N20D00E( + BuiltInId::imageAtomicMin_IImageCube1_Int3_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01Y20D00E( + BuiltInId::imageAtomicMin_UImageCube1_Int3_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01J00D00E( + BuiltInId::imageAtomicMin_ImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01U00D00E( + BuiltInId::imageAtomicMin_IImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01f00D00E( + BuiltInId::imageAtomicMin_UImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01B20D00E( + BuiltInId::imageAtomicMin_Image2DArray1_Int3_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01M20D00E( + BuiltInId::imageAtomicMin_IImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01X20D00E( + BuiltInId::imageAtomicMin_UImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01H20D00E( + BuiltInId::imageAtomicMin_ImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01S20D00E( + BuiltInId::imageAtomicMin_IImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01d20D00E( + BuiltInId::imageAtomicMin_UImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01D00D00E( + BuiltInId::imageAtomicMin_Image1D1_Int1_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01O00D00E( + BuiltInId::imageAtomicMin_IImage1D1_Int1_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01Z00D00E( + BuiltInId::imageAtomicMin_UImage1D1_Int1_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01E10D00E( + BuiltInId::imageAtomicMin_Image1DArray1_Int2_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01P10D00E( + BuiltInId::imageAtomicMin_IImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01a10D00E( + BuiltInId::imageAtomicMin_UImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01I10D00E( + BuiltInId::imageAtomicMin_ImageRect1_Int2_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01T10D00E( + BuiltInId::imageAtomicMin_IImageRect1_Int2_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01e10D00E( + BuiltInId::imageAtomicMin_UImageRect1_Int2_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01F10D00D00E( + BuiltInId::imageAtomicMin_Image2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01Q10D00D00E( + BuiltInId::imageAtomicMin_IImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01b10D00D00E( + BuiltInId::imageAtomicMin_UImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01G20D00D00E( + BuiltInId::imageAtomicMin_Image2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01R20D00D00E( + BuiltInId::imageAtomicMin_IImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01c20D00D00E( + BuiltInId::imageAtomicMin_UImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_00z10D00D( + BuiltInId::imageAtomicMin_Image2D1_Int2_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01K10D00D( + BuiltInId::imageAtomicMin_IImage2D1_Int2_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01V10D00D( + BuiltInId::imageAtomicMin_UImage2D1_Int2_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01A20D00D( + BuiltInId::imageAtomicMin_Image3D1_Int3_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01L20D00D( + BuiltInId::imageAtomicMin_IImage3D1_Int3_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01W20D00D( + BuiltInId::imageAtomicMin_UImage3D1_Int3_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01C20D00D( + BuiltInId::imageAtomicMin_ImageCube1_Int3_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01N20D00D( + BuiltInId::imageAtomicMin_IImageCube1_Int3_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01Y20D00D( + BuiltInId::imageAtomicMin_UImageCube1_Int3_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01J00D00D( + BuiltInId::imageAtomicMin_ImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01U00D00D( + BuiltInId::imageAtomicMin_IImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01f00D00D( + BuiltInId::imageAtomicMin_UImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01B20D00D( + BuiltInId::imageAtomicMin_Image2DArray1_Int3_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01M20D00D( + BuiltInId::imageAtomicMin_IImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01X20D00D( + BuiltInId::imageAtomicMin_UImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01H20D00D( + BuiltInId::imageAtomicMin_ImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01S20D00D( + BuiltInId::imageAtomicMin_IImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01d20D00D( + BuiltInId::imageAtomicMin_UImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01D00D00D( + BuiltInId::imageAtomicMin_Image1D1_Int1_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01O00D00D( + BuiltInId::imageAtomicMin_IImage1D1_Int1_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01Z00D00D( + BuiltInId::imageAtomicMin_UImage1D1_Int1_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01E10D00D( + BuiltInId::imageAtomicMin_Image1DArray1_Int2_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01P10D00D( + BuiltInId::imageAtomicMin_IImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01a10D00D( + BuiltInId::imageAtomicMin_UImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01I10D00D( + BuiltInId::imageAtomicMin_ImageRect1_Int2_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01T10D00D( + BuiltInId::imageAtomicMin_IImageRect1_Int2_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01e10D00D( + BuiltInId::imageAtomicMin_UImageRect1_Int2_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01F10D00D00D( + BuiltInId::imageAtomicMin_Image2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01Q10D00D00D( + BuiltInId::imageAtomicMin_IImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01b10D00D00D( + BuiltInId::imageAtomicMin_UImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01G20D00D00D( + BuiltInId::imageAtomicMin_Image2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01R20D00D00D( + BuiltInId::imageAtomicMin_IImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMin_01c20D00D00D( + BuiltInId::imageAtomicMin_UImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicMin, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMax_00z10D00E( + BuiltInId::imageAtomicMax_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01K10D00E( + BuiltInId::imageAtomicMax_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01V10D00E( + BuiltInId::imageAtomicMax_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01A20D00E( + BuiltInId::imageAtomicMax_Image3D1_Int3_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01L20D00E( + BuiltInId::imageAtomicMax_IImage3D1_Int3_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01W20D00E( + BuiltInId::imageAtomicMax_UImage3D1_Int3_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01C20D00E( + BuiltInId::imageAtomicMax_ImageCube1_Int3_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01N20D00E( + BuiltInId::imageAtomicMax_IImageCube1_Int3_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01Y20D00E( + BuiltInId::imageAtomicMax_UImageCube1_Int3_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01J00D00E( + BuiltInId::imageAtomicMax_ImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01U00D00E( + BuiltInId::imageAtomicMax_IImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01f00D00E( + BuiltInId::imageAtomicMax_UImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01B20D00E( + BuiltInId::imageAtomicMax_Image2DArray1_Int3_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01M20D00E( + BuiltInId::imageAtomicMax_IImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01X20D00E( + BuiltInId::imageAtomicMax_UImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01H20D00E( + BuiltInId::imageAtomicMax_ImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01S20D00E( + BuiltInId::imageAtomicMax_IImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01d20D00E( + BuiltInId::imageAtomicMax_UImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01D00D00E( + BuiltInId::imageAtomicMax_Image1D1_Int1_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01O00D00E( + BuiltInId::imageAtomicMax_IImage1D1_Int1_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01Z00D00E( + BuiltInId::imageAtomicMax_UImage1D1_Int1_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01E10D00E( + BuiltInId::imageAtomicMax_Image1DArray1_Int2_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01P10D00E( + BuiltInId::imageAtomicMax_IImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01a10D00E( + BuiltInId::imageAtomicMax_UImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01I10D00E( + BuiltInId::imageAtomicMax_ImageRect1_Int2_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01T10D00E( + BuiltInId::imageAtomicMax_IImageRect1_Int2_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01e10D00E( + BuiltInId::imageAtomicMax_UImageRect1_Int2_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01F10D00D00E( + BuiltInId::imageAtomicMax_Image2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01Q10D00D00E( + BuiltInId::imageAtomicMax_IImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01b10D00D00E( + BuiltInId::imageAtomicMax_UImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01G20D00D00E( + BuiltInId::imageAtomicMax_Image2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01R20D00D00E( + BuiltInId::imageAtomicMax_IImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01c20D00D00E( + BuiltInId::imageAtomicMax_UImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_00z10D00D( + BuiltInId::imageAtomicMax_Image2D1_Int2_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01K10D00D( + BuiltInId::imageAtomicMax_IImage2D1_Int2_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01V10D00D( + BuiltInId::imageAtomicMax_UImage2D1_Int2_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01A20D00D( + BuiltInId::imageAtomicMax_Image3D1_Int3_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01L20D00D( + BuiltInId::imageAtomicMax_IImage3D1_Int3_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01W20D00D( + BuiltInId::imageAtomicMax_UImage3D1_Int3_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01C20D00D( + BuiltInId::imageAtomicMax_ImageCube1_Int3_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01N20D00D( + BuiltInId::imageAtomicMax_IImageCube1_Int3_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01Y20D00D( + BuiltInId::imageAtomicMax_UImageCube1_Int3_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01J00D00D( + BuiltInId::imageAtomicMax_ImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01U00D00D( + BuiltInId::imageAtomicMax_IImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01f00D00D( + BuiltInId::imageAtomicMax_UImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01B20D00D( + BuiltInId::imageAtomicMax_Image2DArray1_Int3_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01M20D00D( + BuiltInId::imageAtomicMax_IImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01X20D00D( + BuiltInId::imageAtomicMax_UImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01H20D00D( + BuiltInId::imageAtomicMax_ImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01S20D00D( + BuiltInId::imageAtomicMax_IImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01d20D00D( + BuiltInId::imageAtomicMax_UImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01D00D00D( + BuiltInId::imageAtomicMax_Image1D1_Int1_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01O00D00D( + BuiltInId::imageAtomicMax_IImage1D1_Int1_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01Z00D00D( + BuiltInId::imageAtomicMax_UImage1D1_Int1_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01E10D00D( + BuiltInId::imageAtomicMax_Image1DArray1_Int2_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01P10D00D( + BuiltInId::imageAtomicMax_IImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01a10D00D( + BuiltInId::imageAtomicMax_UImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01I10D00D( + BuiltInId::imageAtomicMax_ImageRect1_Int2_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01T10D00D( + BuiltInId::imageAtomicMax_IImageRect1_Int2_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01e10D00D( + BuiltInId::imageAtomicMax_UImageRect1_Int2_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01F10D00D00D( + BuiltInId::imageAtomicMax_Image2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01Q10D00D00D( + BuiltInId::imageAtomicMax_IImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01b10D00D00D( + BuiltInId::imageAtomicMax_UImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01G20D00D00D( + BuiltInId::imageAtomicMax_Image2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01R20D00D00D( + BuiltInId::imageAtomicMax_IImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMax_01c20D00D00D( + BuiltInId::imageAtomicMax_UImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicMax, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicAnd_00z10D00E( + BuiltInId::imageAtomicAnd_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01K10D00E( + BuiltInId::imageAtomicAnd_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01V10D00E( + BuiltInId::imageAtomicAnd_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01A20D00E( + BuiltInId::imageAtomicAnd_Image3D1_Int3_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01L20D00E( + BuiltInId::imageAtomicAnd_IImage3D1_Int3_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01W20D00E( + BuiltInId::imageAtomicAnd_UImage3D1_Int3_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01C20D00E( + BuiltInId::imageAtomicAnd_ImageCube1_Int3_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01N20D00E( + BuiltInId::imageAtomicAnd_IImageCube1_Int3_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01Y20D00E( + BuiltInId::imageAtomicAnd_UImageCube1_Int3_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01J00D00E( + BuiltInId::imageAtomicAnd_ImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01U00D00E( + BuiltInId::imageAtomicAnd_IImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01f00D00E( + BuiltInId::imageAtomicAnd_UImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01B20D00E( + BuiltInId::imageAtomicAnd_Image2DArray1_Int3_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01M20D00E( + BuiltInId::imageAtomicAnd_IImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01X20D00E( + BuiltInId::imageAtomicAnd_UImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01H20D00E( + BuiltInId::imageAtomicAnd_ImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01S20D00E( + BuiltInId::imageAtomicAnd_IImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01d20D00E( + BuiltInId::imageAtomicAnd_UImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01D00D00E( + BuiltInId::imageAtomicAnd_Image1D1_Int1_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01O00D00E( + BuiltInId::imageAtomicAnd_IImage1D1_Int1_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01Z00D00E( + BuiltInId::imageAtomicAnd_UImage1D1_Int1_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01E10D00E( + BuiltInId::imageAtomicAnd_Image1DArray1_Int2_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01P10D00E( + BuiltInId::imageAtomicAnd_IImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01a10D00E( + BuiltInId::imageAtomicAnd_UImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01I10D00E( + BuiltInId::imageAtomicAnd_ImageRect1_Int2_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01T10D00E( + BuiltInId::imageAtomicAnd_IImageRect1_Int2_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01e10D00E( + BuiltInId::imageAtomicAnd_UImageRect1_Int2_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01F10D00D00E( + BuiltInId::imageAtomicAnd_Image2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01Q10D00D00E( + BuiltInId::imageAtomicAnd_IImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01b10D00D00E( + BuiltInId::imageAtomicAnd_UImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01G20D00D00E( + BuiltInId::imageAtomicAnd_Image2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01R20D00D00E( + BuiltInId::imageAtomicAnd_IImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01c20D00D00E( + BuiltInId::imageAtomicAnd_UImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_00z10D00D( + BuiltInId::imageAtomicAnd_Image2D1_Int2_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01K10D00D( + BuiltInId::imageAtomicAnd_IImage2D1_Int2_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01V10D00D( + BuiltInId::imageAtomicAnd_UImage2D1_Int2_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01A20D00D( + BuiltInId::imageAtomicAnd_Image3D1_Int3_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01L20D00D( + BuiltInId::imageAtomicAnd_IImage3D1_Int3_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01W20D00D( + BuiltInId::imageAtomicAnd_UImage3D1_Int3_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01C20D00D( + BuiltInId::imageAtomicAnd_ImageCube1_Int3_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01N20D00D( + BuiltInId::imageAtomicAnd_IImageCube1_Int3_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01Y20D00D( + BuiltInId::imageAtomicAnd_UImageCube1_Int3_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01J00D00D( + BuiltInId::imageAtomicAnd_ImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01U00D00D( + BuiltInId::imageAtomicAnd_IImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01f00D00D( + BuiltInId::imageAtomicAnd_UImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01B20D00D( + BuiltInId::imageAtomicAnd_Image2DArray1_Int3_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01M20D00D( + BuiltInId::imageAtomicAnd_IImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01X20D00D( + BuiltInId::imageAtomicAnd_UImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01H20D00D( + BuiltInId::imageAtomicAnd_ImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01S20D00D( + BuiltInId::imageAtomicAnd_IImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01d20D00D( + BuiltInId::imageAtomicAnd_UImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01D00D00D( + BuiltInId::imageAtomicAnd_Image1D1_Int1_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01O00D00D( + BuiltInId::imageAtomicAnd_IImage1D1_Int1_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01Z00D00D( + BuiltInId::imageAtomicAnd_UImage1D1_Int1_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01E10D00D( + BuiltInId::imageAtomicAnd_Image1DArray1_Int2_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01P10D00D( + BuiltInId::imageAtomicAnd_IImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01a10D00D( + BuiltInId::imageAtomicAnd_UImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01I10D00D( + BuiltInId::imageAtomicAnd_ImageRect1_Int2_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01T10D00D( + BuiltInId::imageAtomicAnd_IImageRect1_Int2_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01e10D00D( + BuiltInId::imageAtomicAnd_UImageRect1_Int2_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01F10D00D00D( + BuiltInId::imageAtomicAnd_Image2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01Q10D00D00D( + BuiltInId::imageAtomicAnd_IImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01b10D00D00D( + BuiltInId::imageAtomicAnd_UImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01G20D00D00D( + BuiltInId::imageAtomicAnd_Image2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01R20D00D00D( + BuiltInId::imageAtomicAnd_IImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAnd_01c20D00D00D( + BuiltInId::imageAtomicAnd_UImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicAnd, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicOr_00z10D00E( + BuiltInId::imageAtomicOr_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01K10D00E( + BuiltInId::imageAtomicOr_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01V10D00E( + BuiltInId::imageAtomicOr_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01A20D00E( + BuiltInId::imageAtomicOr_Image3D1_Int3_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01L20D00E( + BuiltInId::imageAtomicOr_IImage3D1_Int3_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01W20D00E( + BuiltInId::imageAtomicOr_UImage3D1_Int3_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01C20D00E( + BuiltInId::imageAtomicOr_ImageCube1_Int3_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01N20D00E( + BuiltInId::imageAtomicOr_IImageCube1_Int3_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01Y20D00E( + BuiltInId::imageAtomicOr_UImageCube1_Int3_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01J00D00E( + BuiltInId::imageAtomicOr_ImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01U00D00E( + BuiltInId::imageAtomicOr_IImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01f00D00E( + BuiltInId::imageAtomicOr_UImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01B20D00E( + BuiltInId::imageAtomicOr_Image2DArray1_Int3_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01M20D00E( + BuiltInId::imageAtomicOr_IImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01X20D00E( + BuiltInId::imageAtomicOr_UImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01H20D00E( + BuiltInId::imageAtomicOr_ImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01S20D00E( + BuiltInId::imageAtomicOr_IImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01d20D00E( + BuiltInId::imageAtomicOr_UImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01D00D00E( + BuiltInId::imageAtomicOr_Image1D1_Int1_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01O00D00E( + BuiltInId::imageAtomicOr_IImage1D1_Int1_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01Z00D00E( + BuiltInId::imageAtomicOr_UImage1D1_Int1_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01E10D00E( + BuiltInId::imageAtomicOr_Image1DArray1_Int2_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01P10D00E( + BuiltInId::imageAtomicOr_IImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01a10D00E( + BuiltInId::imageAtomicOr_UImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01I10D00E( + BuiltInId::imageAtomicOr_ImageRect1_Int2_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01T10D00E( + BuiltInId::imageAtomicOr_IImageRect1_Int2_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01e10D00E( + BuiltInId::imageAtomicOr_UImageRect1_Int2_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01F10D00D00E( + BuiltInId::imageAtomicOr_Image2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01Q10D00D00E( + BuiltInId::imageAtomicOr_IImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01b10D00D00E( + BuiltInId::imageAtomicOr_UImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01G20D00D00E( + BuiltInId::imageAtomicOr_Image2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01R20D00D00E( + BuiltInId::imageAtomicOr_IImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01c20D00D00E( + BuiltInId::imageAtomicOr_UImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_00z10D00D( + BuiltInId::imageAtomicOr_Image2D1_Int2_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01K10D00D( + BuiltInId::imageAtomicOr_IImage2D1_Int2_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01V10D00D( + BuiltInId::imageAtomicOr_UImage2D1_Int2_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01A20D00D( + BuiltInId::imageAtomicOr_Image3D1_Int3_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01L20D00D( + BuiltInId::imageAtomicOr_IImage3D1_Int3_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01W20D00D( + BuiltInId::imageAtomicOr_UImage3D1_Int3_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01C20D00D( + BuiltInId::imageAtomicOr_ImageCube1_Int3_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01N20D00D( + BuiltInId::imageAtomicOr_IImageCube1_Int3_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01Y20D00D( + BuiltInId::imageAtomicOr_UImageCube1_Int3_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01J00D00D( + BuiltInId::imageAtomicOr_ImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01U00D00D( + BuiltInId::imageAtomicOr_IImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01f00D00D( + BuiltInId::imageAtomicOr_UImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01B20D00D( + BuiltInId::imageAtomicOr_Image2DArray1_Int3_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01M20D00D( + BuiltInId::imageAtomicOr_IImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01X20D00D( + BuiltInId::imageAtomicOr_UImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01H20D00D( + BuiltInId::imageAtomicOr_ImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01S20D00D( + BuiltInId::imageAtomicOr_IImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01d20D00D( + BuiltInId::imageAtomicOr_UImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01D00D00D( + BuiltInId::imageAtomicOr_Image1D1_Int1_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01O00D00D( + BuiltInId::imageAtomicOr_IImage1D1_Int1_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01Z00D00D( + BuiltInId::imageAtomicOr_UImage1D1_Int1_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01E10D00D( + BuiltInId::imageAtomicOr_Image1DArray1_Int2_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01P10D00D( + BuiltInId::imageAtomicOr_IImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01a10D00D( + BuiltInId::imageAtomicOr_UImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01I10D00D( + BuiltInId::imageAtomicOr_ImageRect1_Int2_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01T10D00D( + BuiltInId::imageAtomicOr_IImageRect1_Int2_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01e10D00D( + BuiltInId::imageAtomicOr_UImageRect1_Int2_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01F10D00D00D( + BuiltInId::imageAtomicOr_Image2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01Q10D00D00D( + BuiltInId::imageAtomicOr_IImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01b10D00D00D( + BuiltInId::imageAtomicOr_UImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01G20D00D00D( + BuiltInId::imageAtomicOr_Image2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01R20D00D00D( + BuiltInId::imageAtomicOr_IImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOr_01c20D00D00D( + BuiltInId::imageAtomicOr_UImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicOr, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicXor_00z10D00E( + BuiltInId::imageAtomicXor_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01K10D00E( + BuiltInId::imageAtomicXor_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01V10D00E( + BuiltInId::imageAtomicXor_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01A20D00E( + BuiltInId::imageAtomicXor_Image3D1_Int3_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01L20D00E( + BuiltInId::imageAtomicXor_IImage3D1_Int3_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01W20D00E( + BuiltInId::imageAtomicXor_UImage3D1_Int3_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01C20D00E( + BuiltInId::imageAtomicXor_ImageCube1_Int3_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01N20D00E( + BuiltInId::imageAtomicXor_IImageCube1_Int3_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01Y20D00E( + BuiltInId::imageAtomicXor_UImageCube1_Int3_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01J00D00E( + BuiltInId::imageAtomicXor_ImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01U00D00E( + BuiltInId::imageAtomicXor_IImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01f00D00E( + BuiltInId::imageAtomicXor_UImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01B20D00E( + BuiltInId::imageAtomicXor_Image2DArray1_Int3_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01M20D00E( + BuiltInId::imageAtomicXor_IImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01X20D00E( + BuiltInId::imageAtomicXor_UImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01H20D00E( + BuiltInId::imageAtomicXor_ImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01S20D00E( + BuiltInId::imageAtomicXor_IImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01d20D00E( + BuiltInId::imageAtomicXor_UImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01D00D00E( + BuiltInId::imageAtomicXor_Image1D1_Int1_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01O00D00E( + BuiltInId::imageAtomicXor_IImage1D1_Int1_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01Z00D00E( + BuiltInId::imageAtomicXor_UImage1D1_Int1_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01E10D00E( + BuiltInId::imageAtomicXor_Image1DArray1_Int2_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01P10D00E( + BuiltInId::imageAtomicXor_IImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01a10D00E( + BuiltInId::imageAtomicXor_UImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01I10D00E( + BuiltInId::imageAtomicXor_ImageRect1_Int2_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01T10D00E( + BuiltInId::imageAtomicXor_IImageRect1_Int2_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01e10D00E( + BuiltInId::imageAtomicXor_UImageRect1_Int2_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01F10D00D00E( + BuiltInId::imageAtomicXor_Image2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01Q10D00D00E( + BuiltInId::imageAtomicXor_IImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01b10D00D00E( + BuiltInId::imageAtomicXor_UImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01G20D00D00E( + BuiltInId::imageAtomicXor_Image2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01R20D00D00E( + BuiltInId::imageAtomicXor_IImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01c20D00D00E( + BuiltInId::imageAtomicXor_UImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_00z10D00D( + BuiltInId::imageAtomicXor_Image2D1_Int2_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01K10D00D( + BuiltInId::imageAtomicXor_IImage2D1_Int2_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01V10D00D( + BuiltInId::imageAtomicXor_UImage2D1_Int2_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01A20D00D( + BuiltInId::imageAtomicXor_Image3D1_Int3_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01L20D00D( + BuiltInId::imageAtomicXor_IImage3D1_Int3_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01W20D00D( + BuiltInId::imageAtomicXor_UImage3D1_Int3_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01C20D00D( + BuiltInId::imageAtomicXor_ImageCube1_Int3_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01N20D00D( + BuiltInId::imageAtomicXor_IImageCube1_Int3_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01Y20D00D( + BuiltInId::imageAtomicXor_UImageCube1_Int3_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01J00D00D( + BuiltInId::imageAtomicXor_ImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01U00D00D( + BuiltInId::imageAtomicXor_IImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01f00D00D( + BuiltInId::imageAtomicXor_UImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01B20D00D( + BuiltInId::imageAtomicXor_Image2DArray1_Int3_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01M20D00D( + BuiltInId::imageAtomicXor_IImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01X20D00D( + BuiltInId::imageAtomicXor_UImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01H20D00D( + BuiltInId::imageAtomicXor_ImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01S20D00D( + BuiltInId::imageAtomicXor_IImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01d20D00D( + BuiltInId::imageAtomicXor_UImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01D00D00D( + BuiltInId::imageAtomicXor_Image1D1_Int1_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01O00D00D( + BuiltInId::imageAtomicXor_IImage1D1_Int1_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01Z00D00D( + BuiltInId::imageAtomicXor_UImage1D1_Int1_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01E10D00D( + BuiltInId::imageAtomicXor_Image1DArray1_Int2_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01P10D00D( + BuiltInId::imageAtomicXor_IImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01a10D00D( + BuiltInId::imageAtomicXor_UImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01I10D00D( + BuiltInId::imageAtomicXor_ImageRect1_Int2_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01T10D00D( + BuiltInId::imageAtomicXor_IImageRect1_Int2_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01e10D00D( + BuiltInId::imageAtomicXor_UImageRect1_Int2_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01F10D00D00D( + BuiltInId::imageAtomicXor_Image2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01Q10D00D00D( + BuiltInId::imageAtomicXor_IImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01b10D00D00D( + BuiltInId::imageAtomicXor_UImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01G20D00D00D( + BuiltInId::imageAtomicXor_Image2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01R20D00D00D( + BuiltInId::imageAtomicXor_IImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXor_01c20D00D00D( + BuiltInId::imageAtomicXor_UImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicXor, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicExchange_00z10D00E( + BuiltInId::imageAtomicExchange_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01K10D00E( + BuiltInId::imageAtomicExchange_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01V10D00E( + BuiltInId::imageAtomicExchange_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01A20D00E( + BuiltInId::imageAtomicExchange_Image3D1_Int3_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01L20D00E( + BuiltInId::imageAtomicExchange_IImage3D1_Int3_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01W20D00E( + BuiltInId::imageAtomicExchange_UImage3D1_Int3_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01C20D00E( + BuiltInId::imageAtomicExchange_ImageCube1_Int3_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01N20D00E( + BuiltInId::imageAtomicExchange_IImageCube1_Int3_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01Y20D00E( + BuiltInId::imageAtomicExchange_UImageCube1_Int3_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01J00D00E( + BuiltInId::imageAtomicExchange_ImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01U00D00E( + BuiltInId::imageAtomicExchange_IImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01f00D00E( + BuiltInId::imageAtomicExchange_UImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01B20D00E( + BuiltInId::imageAtomicExchange_Image2DArray1_Int3_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01M20D00E( + BuiltInId::imageAtomicExchange_IImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01X20D00E( + BuiltInId::imageAtomicExchange_UImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01H20D00E( + BuiltInId::imageAtomicExchange_ImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01S20D00E( + BuiltInId::imageAtomicExchange_IImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01d20D00E( + BuiltInId::imageAtomicExchange_UImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01D00D00E( + BuiltInId::imageAtomicExchange_Image1D1_Int1_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01O00D00E( + BuiltInId::imageAtomicExchange_IImage1D1_Int1_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01Z00D00E( + BuiltInId::imageAtomicExchange_UImage1D1_Int1_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01E10D00E( + BuiltInId::imageAtomicExchange_Image1DArray1_Int2_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01P10D00E( + BuiltInId::imageAtomicExchange_IImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01a10D00E( + BuiltInId::imageAtomicExchange_UImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01I10D00E( + BuiltInId::imageAtomicExchange_ImageRect1_Int2_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01T10D00E( + BuiltInId::imageAtomicExchange_IImageRect1_Int2_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01e10D00E( + BuiltInId::imageAtomicExchange_UImageRect1_Int2_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01F10D00D00E( + BuiltInId::imageAtomicExchange_Image2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01Q10D00D00E( + BuiltInId::imageAtomicExchange_IImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01b10D00D00E( + BuiltInId::imageAtomicExchange_UImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01G20D00D00E( + BuiltInId::imageAtomicExchange_Image2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01R20D00D00E( + BuiltInId::imageAtomicExchange_IImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01c20D00D00E( + BuiltInId::imageAtomicExchange_UImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_00z10D00D( + BuiltInId::imageAtomicExchange_Image2D1_Int2_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01K10D00D( + BuiltInId::imageAtomicExchange_IImage2D1_Int2_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01V10D00D( + BuiltInId::imageAtomicExchange_UImage2D1_Int2_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01A20D00D( + BuiltInId::imageAtomicExchange_Image3D1_Int3_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01L20D00D( + BuiltInId::imageAtomicExchange_IImage3D1_Int3_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01W20D00D( + BuiltInId::imageAtomicExchange_UImage3D1_Int3_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01C20D00D( + BuiltInId::imageAtomicExchange_ImageCube1_Int3_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01N20D00D( + BuiltInId::imageAtomicExchange_IImageCube1_Int3_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01Y20D00D( + BuiltInId::imageAtomicExchange_UImageCube1_Int3_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01J00D00D( + BuiltInId::imageAtomicExchange_ImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01U00D00D( + BuiltInId::imageAtomicExchange_IImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01f00D00D( + BuiltInId::imageAtomicExchange_UImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01B20D00D( + BuiltInId::imageAtomicExchange_Image2DArray1_Int3_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01M20D00D( + BuiltInId::imageAtomicExchange_IImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01X20D00D( + BuiltInId::imageAtomicExchange_UImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01H20D00D( + BuiltInId::imageAtomicExchange_ImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01S20D00D( + BuiltInId::imageAtomicExchange_IImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01d20D00D( + BuiltInId::imageAtomicExchange_UImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01D00D00D( + BuiltInId::imageAtomicExchange_Image1D1_Int1_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01O00D00D( + BuiltInId::imageAtomicExchange_IImage1D1_Int1_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01Z00D00D( + BuiltInId::imageAtomicExchange_UImage1D1_Int1_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01E10D00D( + BuiltInId::imageAtomicExchange_Image1DArray1_Int2_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01P10D00D( + BuiltInId::imageAtomicExchange_IImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01a10D00D( + BuiltInId::imageAtomicExchange_UImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01I10D00D( + BuiltInId::imageAtomicExchange_ImageRect1_Int2_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01T10D00D( + BuiltInId::imageAtomicExchange_IImageRect1_Int2_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01e10D00D( + BuiltInId::imageAtomicExchange_UImageRect1_Int2_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01F10D00D00D( + BuiltInId::imageAtomicExchange_Image2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01Q10D00D00D( + BuiltInId::imageAtomicExchange_IImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01b10D00D00D( + BuiltInId::imageAtomicExchange_UImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01G20D00D00D( + BuiltInId::imageAtomicExchange_Image2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01R20D00D00D( + BuiltInId::imageAtomicExchange_IImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01c20D00D00D( + BuiltInId::imageAtomicExchange_UImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_00z10D00B( + BuiltInId::imageAtomicExchange_Image2D1_Int2_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01K10D00B( + BuiltInId::imageAtomicExchange_IImage2D1_Int2_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01V10D00B( + BuiltInId::imageAtomicExchange_UImage2D1_Int2_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01A20D00B( + BuiltInId::imageAtomicExchange_Image3D1_Int3_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01L20D00B( + BuiltInId::imageAtomicExchange_IImage3D1_Int3_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01W20D00B( + BuiltInId::imageAtomicExchange_UImage3D1_Int3_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01C20D00B( + BuiltInId::imageAtomicExchange_ImageCube1_Int3_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01N20D00B( + BuiltInId::imageAtomicExchange_IImageCube1_Int3_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01Y20D00B( + BuiltInId::imageAtomicExchange_UImageCube1_Int3_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01J00D00B( + BuiltInId::imageAtomicExchange_ImageBuffer1_Int1_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01U00D00B( + BuiltInId::imageAtomicExchange_IImageBuffer1_Int1_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01f00D00B( + BuiltInId::imageAtomicExchange_UImageBuffer1_Int1_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01B20D00B( + BuiltInId::imageAtomicExchange_Image2DArray1_Int3_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01M20D00B( + BuiltInId::imageAtomicExchange_IImage2DArray1_Int3_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01X20D00B( + BuiltInId::imageAtomicExchange_UImage2DArray1_Int3_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01H20D00B( + BuiltInId::imageAtomicExchange_ImageCubeArray1_Int3_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01S20D00B( + BuiltInId::imageAtomicExchange_IImageCubeArray1_Int3_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01d20D00B( + BuiltInId::imageAtomicExchange_UImageCubeArray1_Int3_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01D00D00B( + BuiltInId::imageAtomicExchange_Image1D1_Int1_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01O00D00B( + BuiltInId::imageAtomicExchange_IImage1D1_Int1_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01Z00D00B( + BuiltInId::imageAtomicExchange_UImage1D1_Int1_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01E10D00B( + BuiltInId::imageAtomicExchange_Image1DArray1_Int2_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01P10D00B( + BuiltInId::imageAtomicExchange_IImage1DArray1_Int2_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01a10D00B( + BuiltInId::imageAtomicExchange_UImage1DArray1_Int2_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01I10D00B( + BuiltInId::imageAtomicExchange_ImageRect1_Int2_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01T10D00B( + BuiltInId::imageAtomicExchange_IImageRect1_Int2_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01e10D00B( + BuiltInId::imageAtomicExchange_UImageRect1_Int2_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01F10D00D00B( + BuiltInId::imageAtomicExchange_Image2DMS1_Int2_Int1_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00B, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01Q10D00D00B( + BuiltInId::imageAtomicExchange_IImage2DMS1_Int2_Int1_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00B, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01b10D00D00B( + BuiltInId::imageAtomicExchange_UImage2DMS1_Int2_Int1_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00B, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01G20D00D00B( + BuiltInId::imageAtomicExchange_Image2DMSArray1_Int3_Int1_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00B, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01R20D00D00B( + BuiltInId::imageAtomicExchange_IImage2DMSArray1_Int3_Int1_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00B, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchange_01c20D00D00B( + BuiltInId::imageAtomicExchange_UImage2DMSArray1_Int3_Int1_Float1, + BuiltInName::imageAtomicExchange, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00B, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicCompSwap_00z10D00E00E( + BuiltInId::imageAtomicCompSwap_Image2D1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01K10D00E00E( + BuiltInId::imageAtomicCompSwap_IImage2D1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01V10D00E00E( + BuiltInId::imageAtomicCompSwap_UImage2D1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01A20D00E00E( + BuiltInId::imageAtomicCompSwap_Image3D1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01L20D00E00E( + BuiltInId::imageAtomicCompSwap_IImage3D1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01W20D00E00E( + BuiltInId::imageAtomicCompSwap_UImage3D1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01C20D00E00E( + BuiltInId::imageAtomicCompSwap_ImageCube1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01N20D00E00E( + BuiltInId::imageAtomicCompSwap_IImageCube1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01Y20D00E00E( + BuiltInId::imageAtomicCompSwap_UImageCube1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01J00D00E00E( + BuiltInId::imageAtomicCompSwap_ImageBuffer1_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01U00D00E00E( + BuiltInId::imageAtomicCompSwap_IImageBuffer1_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01f00D00E00E( + BuiltInId::imageAtomicCompSwap_UImageBuffer1_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01B20D00E00E( + BuiltInId::imageAtomicCompSwap_Image2DArray1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01M20D00E00E( + BuiltInId::imageAtomicCompSwap_IImage2DArray1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01X20D00E00E( + BuiltInId::imageAtomicCompSwap_UImage2DArray1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01H20D00E00E( + BuiltInId::imageAtomicCompSwap_ImageCubeArray1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01S20D00E00E( + BuiltInId::imageAtomicCompSwap_IImageCubeArray1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01d20D00E00E( + BuiltInId::imageAtomicCompSwap_UImageCubeArray1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01D00D00E00E( + BuiltInId::imageAtomicCompSwap_Image1D1_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01O00D00E00E( + BuiltInId::imageAtomicCompSwap_IImage1D1_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01Z00D00E00E( + BuiltInId::imageAtomicCompSwap_UImage1D1_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01E10D00E00E( + BuiltInId::imageAtomicCompSwap_Image1DArray1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01P10D00E00E( + BuiltInId::imageAtomicCompSwap_IImage1DArray1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01a10D00E00E( + BuiltInId::imageAtomicCompSwap_UImage1DArray1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01I10D00E00E( + BuiltInId::imageAtomicCompSwap_ImageRect1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01T10D00E00E( + BuiltInId::imageAtomicCompSwap_IImageRect1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01e10D00E00E( + BuiltInId::imageAtomicCompSwap_UImageRect1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01F10D00D00E00E( + BuiltInId::imageAtomicCompSwap_Image2DMS1_Int2_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00E00E, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01Q10D00D00E00E( + BuiltInId::imageAtomicCompSwap_IImage2DMS1_Int2_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00E00E, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01b10D00D00E00E( + BuiltInId::imageAtomicCompSwap_UImage2DMS1_Int2_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00E00E, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01G20D00D00E00E( + BuiltInId::imageAtomicCompSwap_Image2DMSArray1_Int3_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00E00E, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01R20D00D00E00E( + BuiltInId::imageAtomicCompSwap_IImage2DMSArray1_Int3_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00E00E, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01c20D00D00E00E( + BuiltInId::imageAtomicCompSwap_UImage2DMSArray1_Int3_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00E00E, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_00z10D00D00D( + BuiltInId::imageAtomicCompSwap_Image2D1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p00z10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01K10D00D00D( + BuiltInId::imageAtomicCompSwap_IImage2D1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01K10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01V10D00D00D( + BuiltInId::imageAtomicCompSwap_UImage2D1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01V10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01A20D00D00D( + BuiltInId::imageAtomicCompSwap_Image3D1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01A20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01L20D00D00D( + BuiltInId::imageAtomicCompSwap_IImage3D1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01L20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01W20D00D00D( + BuiltInId::imageAtomicCompSwap_UImage3D1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01W20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01C20D00D00D( + BuiltInId::imageAtomicCompSwap_ImageCube1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01C20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01N20D00D00D( + BuiltInId::imageAtomicCompSwap_IImageCube1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01N20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01Y20D00D00D( + BuiltInId::imageAtomicCompSwap_UImageCube1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Y20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01J00D00D00D( + BuiltInId::imageAtomicCompSwap_ImageBuffer1_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01J00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01U00D00D00D( + BuiltInId::imageAtomicCompSwap_IImageBuffer1_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01U00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01f00D00D00D( + BuiltInId::imageAtomicCompSwap_UImageBuffer1_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01f00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01B20D00D00D( + BuiltInId::imageAtomicCompSwap_Image2DArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01B20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01M20D00D00D( + BuiltInId::imageAtomicCompSwap_IImage2DArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01M20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01X20D00D00D( + BuiltInId::imageAtomicCompSwap_UImage2DArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01X20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01H20D00D00D( + BuiltInId::imageAtomicCompSwap_ImageCubeArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01H20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01S20D00D00D( + BuiltInId::imageAtomicCompSwap_IImageCubeArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01S20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01d20D00D00D( + BuiltInId::imageAtomicCompSwap_UImageCubeArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01d20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01D00D00D00D( + BuiltInId::imageAtomicCompSwap_Image1D1_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01O00D00D00D( + BuiltInId::imageAtomicCompSwap_IImage1D1_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01O00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01Z00D00D00D( + BuiltInId::imageAtomicCompSwap_UImage1D1_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Z00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01E10D00D00D( + BuiltInId::imageAtomicCompSwap_Image1DArray1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01E10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01P10D00D00D( + BuiltInId::imageAtomicCompSwap_IImage1DArray1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01P10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01a10D00D00D( + BuiltInId::imageAtomicCompSwap_UImage1DArray1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01a10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01I10D00D00D( + BuiltInId::imageAtomicCompSwap_ImageRect1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01I10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01T10D00D00D( + BuiltInId::imageAtomicCompSwap_IImageRect1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01T10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01e10D00D00D( + BuiltInId::imageAtomicCompSwap_UImageRect1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01e10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01F10D00D00D00D( + BuiltInId::imageAtomicCompSwap_Image2DMS1_Int2_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01F10D00D00D00D, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01Q10D00D00D00D( + BuiltInId::imageAtomicCompSwap_IImage2DMS1_Int2_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01Q10D00D00D00D, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01b10D00D00D00D( + BuiltInId::imageAtomicCompSwap_UImage2DMS1_Int2_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01b10D00D00D00D, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01G20D00D00D00D( + BuiltInId::imageAtomicCompSwap_Image2DMSArray1_Int3_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01G20D00D00D00D, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01R20D00D00D00D( + BuiltInId::imageAtomicCompSwap_IImage2DMSArray1_Int3_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01R20D00D00D00D, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwap_01c20D00D00D00D( + BuiltInId::imageAtomicCompSwap_UImage2DMSArray1_Int3_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwap, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01c20D00D00D00D, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicAddExt_00z10D00E( + BuiltInId::imageAtomicAddExt_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01K10D00E( + BuiltInId::imageAtomicAddExt_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01V10D00E( + BuiltInId::imageAtomicAddExt_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01A20D00E( + BuiltInId::imageAtomicAddExt_Image3D1_Int3_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01L20D00E( + BuiltInId::imageAtomicAddExt_IImage3D1_Int3_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01W20D00E( + BuiltInId::imageAtomicAddExt_UImage3D1_Int3_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01C20D00E( + BuiltInId::imageAtomicAddExt_ImageCube1_Int3_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01N20D00E( + BuiltInId::imageAtomicAddExt_IImageCube1_Int3_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01Y20D00E( + BuiltInId::imageAtomicAddExt_UImageCube1_Int3_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01J00D00E( + BuiltInId::imageAtomicAddExt_ImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01U00D00E( + BuiltInId::imageAtomicAddExt_IImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01f00D00E( + BuiltInId::imageAtomicAddExt_UImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01B20D00E( + BuiltInId::imageAtomicAddExt_Image2DArray1_Int3_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01M20D00E( + BuiltInId::imageAtomicAddExt_IImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01X20D00E( + BuiltInId::imageAtomicAddExt_UImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01H20D00E( + BuiltInId::imageAtomicAddExt_ImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01S20D00E( + BuiltInId::imageAtomicAddExt_IImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01d20D00E( + BuiltInId::imageAtomicAddExt_UImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01D00D00E( + BuiltInId::imageAtomicAddExt_Image1D1_Int1_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01O00D00E( + BuiltInId::imageAtomicAddExt_IImage1D1_Int1_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01Z00D00E( + BuiltInId::imageAtomicAddExt_UImage1D1_Int1_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01E10D00E( + BuiltInId::imageAtomicAddExt_Image1DArray1_Int2_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01P10D00E( + BuiltInId::imageAtomicAddExt_IImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01a10D00E( + BuiltInId::imageAtomicAddExt_UImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01I10D00E( + BuiltInId::imageAtomicAddExt_ImageRect1_Int2_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01T10D00E( + BuiltInId::imageAtomicAddExt_IImageRect1_Int2_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01e10D00E( + BuiltInId::imageAtomicAddExt_UImageRect1_Int2_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01F10D00D00E( + BuiltInId::imageAtomicAddExt_Image2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01Q10D00D00E( + BuiltInId::imageAtomicAddExt_IImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01b10D00D00E( + BuiltInId::imageAtomicAddExt_UImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01G20D00D00E( + BuiltInId::imageAtomicAddExt_Image2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01R20D00D00E( + BuiltInId::imageAtomicAddExt_IImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01c20D00D00E( + BuiltInId::imageAtomicAddExt_UImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_00z10D00D( + BuiltInId::imageAtomicAddExt_Image2D1_Int2_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01K10D00D( + BuiltInId::imageAtomicAddExt_IImage2D1_Int2_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01V10D00D( + BuiltInId::imageAtomicAddExt_UImage2D1_Int2_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01A20D00D( + BuiltInId::imageAtomicAddExt_Image3D1_Int3_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01L20D00D( + BuiltInId::imageAtomicAddExt_IImage3D1_Int3_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01W20D00D( + BuiltInId::imageAtomicAddExt_UImage3D1_Int3_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01C20D00D( + BuiltInId::imageAtomicAddExt_ImageCube1_Int3_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01N20D00D( + BuiltInId::imageAtomicAddExt_IImageCube1_Int3_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01Y20D00D( + BuiltInId::imageAtomicAddExt_UImageCube1_Int3_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01J00D00D( + BuiltInId::imageAtomicAddExt_ImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01U00D00D( + BuiltInId::imageAtomicAddExt_IImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01f00D00D( + BuiltInId::imageAtomicAddExt_UImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01B20D00D( + BuiltInId::imageAtomicAddExt_Image2DArray1_Int3_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01M20D00D( + BuiltInId::imageAtomicAddExt_IImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01X20D00D( + BuiltInId::imageAtomicAddExt_UImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01H20D00D( + BuiltInId::imageAtomicAddExt_ImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01S20D00D( + BuiltInId::imageAtomicAddExt_IImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01d20D00D( + BuiltInId::imageAtomicAddExt_UImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01D00D00D( + BuiltInId::imageAtomicAddExt_Image1D1_Int1_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01O00D00D( + BuiltInId::imageAtomicAddExt_IImage1D1_Int1_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01Z00D00D( + BuiltInId::imageAtomicAddExt_UImage1D1_Int1_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01E10D00D( + BuiltInId::imageAtomicAddExt_Image1DArray1_Int2_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01P10D00D( + BuiltInId::imageAtomicAddExt_IImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01a10D00D( + BuiltInId::imageAtomicAddExt_UImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01I10D00D( + BuiltInId::imageAtomicAddExt_ImageRect1_Int2_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01T10D00D( + BuiltInId::imageAtomicAddExt_IImageRect1_Int2_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01e10D00D( + BuiltInId::imageAtomicAddExt_UImageRect1_Int2_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01F10D00D00D( + BuiltInId::imageAtomicAddExt_Image2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01Q10D00D00D( + BuiltInId::imageAtomicAddExt_IImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01b10D00D00D( + BuiltInId::imageAtomicAddExt_UImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01G20D00D00D( + BuiltInId::imageAtomicAddExt_Image2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01R20D00D00D( + BuiltInId::imageAtomicAddExt_IImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicAddExt_01c20D00D00D( + BuiltInId::imageAtomicAddExt_UImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicAddExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAdd, + false); +constexpr const TFunction imageAtomicMinExt_00z10D00E( + BuiltInId::imageAtomicMinExt_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01K10D00E( + BuiltInId::imageAtomicMinExt_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01V10D00E( + BuiltInId::imageAtomicMinExt_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01A20D00E( + BuiltInId::imageAtomicMinExt_Image3D1_Int3_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01L20D00E( + BuiltInId::imageAtomicMinExt_IImage3D1_Int3_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01W20D00E( + BuiltInId::imageAtomicMinExt_UImage3D1_Int3_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01C20D00E( + BuiltInId::imageAtomicMinExt_ImageCube1_Int3_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01N20D00E( + BuiltInId::imageAtomicMinExt_IImageCube1_Int3_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01Y20D00E( + BuiltInId::imageAtomicMinExt_UImageCube1_Int3_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01J00D00E( + BuiltInId::imageAtomicMinExt_ImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01U00D00E( + BuiltInId::imageAtomicMinExt_IImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01f00D00E( + BuiltInId::imageAtomicMinExt_UImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01B20D00E( + BuiltInId::imageAtomicMinExt_Image2DArray1_Int3_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01M20D00E( + BuiltInId::imageAtomicMinExt_IImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01X20D00E( + BuiltInId::imageAtomicMinExt_UImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01H20D00E( + BuiltInId::imageAtomicMinExt_ImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01S20D00E( + BuiltInId::imageAtomicMinExt_IImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01d20D00E( + BuiltInId::imageAtomicMinExt_UImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01D00D00E( + BuiltInId::imageAtomicMinExt_Image1D1_Int1_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01O00D00E( + BuiltInId::imageAtomicMinExt_IImage1D1_Int1_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01Z00D00E( + BuiltInId::imageAtomicMinExt_UImage1D1_Int1_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01E10D00E( + BuiltInId::imageAtomicMinExt_Image1DArray1_Int2_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01P10D00E( + BuiltInId::imageAtomicMinExt_IImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01a10D00E( + BuiltInId::imageAtomicMinExt_UImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01I10D00E( + BuiltInId::imageAtomicMinExt_ImageRect1_Int2_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01T10D00E( + BuiltInId::imageAtomicMinExt_IImageRect1_Int2_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01e10D00E( + BuiltInId::imageAtomicMinExt_UImageRect1_Int2_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01F10D00D00E( + BuiltInId::imageAtomicMinExt_Image2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01Q10D00D00E( + BuiltInId::imageAtomicMinExt_IImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01b10D00D00E( + BuiltInId::imageAtomicMinExt_UImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01G20D00D00E( + BuiltInId::imageAtomicMinExt_Image2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01R20D00D00E( + BuiltInId::imageAtomicMinExt_IImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01c20D00D00E( + BuiltInId::imageAtomicMinExt_UImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_00z10D00D( + BuiltInId::imageAtomicMinExt_Image2D1_Int2_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01K10D00D( + BuiltInId::imageAtomicMinExt_IImage2D1_Int2_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01V10D00D( + BuiltInId::imageAtomicMinExt_UImage2D1_Int2_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01A20D00D( + BuiltInId::imageAtomicMinExt_Image3D1_Int3_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01L20D00D( + BuiltInId::imageAtomicMinExt_IImage3D1_Int3_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01W20D00D( + BuiltInId::imageAtomicMinExt_UImage3D1_Int3_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01C20D00D( + BuiltInId::imageAtomicMinExt_ImageCube1_Int3_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01N20D00D( + BuiltInId::imageAtomicMinExt_IImageCube1_Int3_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01Y20D00D( + BuiltInId::imageAtomicMinExt_UImageCube1_Int3_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01J00D00D( + BuiltInId::imageAtomicMinExt_ImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01U00D00D( + BuiltInId::imageAtomicMinExt_IImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01f00D00D( + BuiltInId::imageAtomicMinExt_UImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01B20D00D( + BuiltInId::imageAtomicMinExt_Image2DArray1_Int3_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01M20D00D( + BuiltInId::imageAtomicMinExt_IImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01X20D00D( + BuiltInId::imageAtomicMinExt_UImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01H20D00D( + BuiltInId::imageAtomicMinExt_ImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01S20D00D( + BuiltInId::imageAtomicMinExt_IImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01d20D00D( + BuiltInId::imageAtomicMinExt_UImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01D00D00D( + BuiltInId::imageAtomicMinExt_Image1D1_Int1_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01O00D00D( + BuiltInId::imageAtomicMinExt_IImage1D1_Int1_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01Z00D00D( + BuiltInId::imageAtomicMinExt_UImage1D1_Int1_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01E10D00D( + BuiltInId::imageAtomicMinExt_Image1DArray1_Int2_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01P10D00D( + BuiltInId::imageAtomicMinExt_IImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01a10D00D( + BuiltInId::imageAtomicMinExt_UImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01I10D00D( + BuiltInId::imageAtomicMinExt_ImageRect1_Int2_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01T10D00D( + BuiltInId::imageAtomicMinExt_IImageRect1_Int2_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01e10D00D( + BuiltInId::imageAtomicMinExt_UImageRect1_Int2_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01F10D00D00D( + BuiltInId::imageAtomicMinExt_Image2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01Q10D00D00D( + BuiltInId::imageAtomicMinExt_IImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01b10D00D00D( + BuiltInId::imageAtomicMinExt_UImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01G20D00D00D( + BuiltInId::imageAtomicMinExt_Image2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01R20D00D00D( + BuiltInId::imageAtomicMinExt_IImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMinExt_01c20D00D00D( + BuiltInId::imageAtomicMinExt_UImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicMinExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMin, + false); +constexpr const TFunction imageAtomicMaxExt_00z10D00E( + BuiltInId::imageAtomicMaxExt_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01K10D00E( + BuiltInId::imageAtomicMaxExt_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01V10D00E( + BuiltInId::imageAtomicMaxExt_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01A20D00E( + BuiltInId::imageAtomicMaxExt_Image3D1_Int3_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01L20D00E( + BuiltInId::imageAtomicMaxExt_IImage3D1_Int3_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01W20D00E( + BuiltInId::imageAtomicMaxExt_UImage3D1_Int3_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01C20D00E( + BuiltInId::imageAtomicMaxExt_ImageCube1_Int3_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01N20D00E( + BuiltInId::imageAtomicMaxExt_IImageCube1_Int3_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01Y20D00E( + BuiltInId::imageAtomicMaxExt_UImageCube1_Int3_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01J00D00E( + BuiltInId::imageAtomicMaxExt_ImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01U00D00E( + BuiltInId::imageAtomicMaxExt_IImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01f00D00E( + BuiltInId::imageAtomicMaxExt_UImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01B20D00E( + BuiltInId::imageAtomicMaxExt_Image2DArray1_Int3_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01M20D00E( + BuiltInId::imageAtomicMaxExt_IImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01X20D00E( + BuiltInId::imageAtomicMaxExt_UImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01H20D00E( + BuiltInId::imageAtomicMaxExt_ImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01S20D00E( + BuiltInId::imageAtomicMaxExt_IImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01d20D00E( + BuiltInId::imageAtomicMaxExt_UImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01D00D00E( + BuiltInId::imageAtomicMaxExt_Image1D1_Int1_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01O00D00E( + BuiltInId::imageAtomicMaxExt_IImage1D1_Int1_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01Z00D00E( + BuiltInId::imageAtomicMaxExt_UImage1D1_Int1_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01E10D00E( + BuiltInId::imageAtomicMaxExt_Image1DArray1_Int2_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01P10D00E( + BuiltInId::imageAtomicMaxExt_IImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01a10D00E( + BuiltInId::imageAtomicMaxExt_UImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01I10D00E( + BuiltInId::imageAtomicMaxExt_ImageRect1_Int2_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01T10D00E( + BuiltInId::imageAtomicMaxExt_IImageRect1_Int2_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01e10D00E( + BuiltInId::imageAtomicMaxExt_UImageRect1_Int2_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01F10D00D00E( + BuiltInId::imageAtomicMaxExt_Image2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01Q10D00D00E( + BuiltInId::imageAtomicMaxExt_IImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01b10D00D00E( + BuiltInId::imageAtomicMaxExt_UImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01G20D00D00E( + BuiltInId::imageAtomicMaxExt_Image2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01R20D00D00E( + BuiltInId::imageAtomicMaxExt_IImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01c20D00D00E( + BuiltInId::imageAtomicMaxExt_UImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_00z10D00D( + BuiltInId::imageAtomicMaxExt_Image2D1_Int2_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01K10D00D( + BuiltInId::imageAtomicMaxExt_IImage2D1_Int2_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01V10D00D( + BuiltInId::imageAtomicMaxExt_UImage2D1_Int2_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01A20D00D( + BuiltInId::imageAtomicMaxExt_Image3D1_Int3_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01L20D00D( + BuiltInId::imageAtomicMaxExt_IImage3D1_Int3_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01W20D00D( + BuiltInId::imageAtomicMaxExt_UImage3D1_Int3_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01C20D00D( + BuiltInId::imageAtomicMaxExt_ImageCube1_Int3_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01N20D00D( + BuiltInId::imageAtomicMaxExt_IImageCube1_Int3_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01Y20D00D( + BuiltInId::imageAtomicMaxExt_UImageCube1_Int3_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01J00D00D( + BuiltInId::imageAtomicMaxExt_ImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01U00D00D( + BuiltInId::imageAtomicMaxExt_IImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01f00D00D( + BuiltInId::imageAtomicMaxExt_UImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01B20D00D( + BuiltInId::imageAtomicMaxExt_Image2DArray1_Int3_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01M20D00D( + BuiltInId::imageAtomicMaxExt_IImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01X20D00D( + BuiltInId::imageAtomicMaxExt_UImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01H20D00D( + BuiltInId::imageAtomicMaxExt_ImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01S20D00D( + BuiltInId::imageAtomicMaxExt_IImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01d20D00D( + BuiltInId::imageAtomicMaxExt_UImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01D00D00D( + BuiltInId::imageAtomicMaxExt_Image1D1_Int1_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01O00D00D( + BuiltInId::imageAtomicMaxExt_IImage1D1_Int1_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01Z00D00D( + BuiltInId::imageAtomicMaxExt_UImage1D1_Int1_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01E10D00D( + BuiltInId::imageAtomicMaxExt_Image1DArray1_Int2_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01P10D00D( + BuiltInId::imageAtomicMaxExt_IImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01a10D00D( + BuiltInId::imageAtomicMaxExt_UImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01I10D00D( + BuiltInId::imageAtomicMaxExt_ImageRect1_Int2_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01T10D00D( + BuiltInId::imageAtomicMaxExt_IImageRect1_Int2_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01e10D00D( + BuiltInId::imageAtomicMaxExt_UImageRect1_Int2_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01F10D00D00D( + BuiltInId::imageAtomicMaxExt_Image2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01Q10D00D00D( + BuiltInId::imageAtomicMaxExt_IImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01b10D00D00D( + BuiltInId::imageAtomicMaxExt_UImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01G20D00D00D( + BuiltInId::imageAtomicMaxExt_Image2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01R20D00D00D( + BuiltInId::imageAtomicMaxExt_IImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicMaxExt_01c20D00D00D( + BuiltInId::imageAtomicMaxExt_UImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicMaxExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicMax, + false); +constexpr const TFunction imageAtomicAndExt_00z10D00E( + BuiltInId::imageAtomicAndExt_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01K10D00E( + BuiltInId::imageAtomicAndExt_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01V10D00E( + BuiltInId::imageAtomicAndExt_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01A20D00E( + BuiltInId::imageAtomicAndExt_Image3D1_Int3_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01L20D00E( + BuiltInId::imageAtomicAndExt_IImage3D1_Int3_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01W20D00E( + BuiltInId::imageAtomicAndExt_UImage3D1_Int3_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01C20D00E( + BuiltInId::imageAtomicAndExt_ImageCube1_Int3_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01N20D00E( + BuiltInId::imageAtomicAndExt_IImageCube1_Int3_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01Y20D00E( + BuiltInId::imageAtomicAndExt_UImageCube1_Int3_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01J00D00E( + BuiltInId::imageAtomicAndExt_ImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01U00D00E( + BuiltInId::imageAtomicAndExt_IImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01f00D00E( + BuiltInId::imageAtomicAndExt_UImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01B20D00E( + BuiltInId::imageAtomicAndExt_Image2DArray1_Int3_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01M20D00E( + BuiltInId::imageAtomicAndExt_IImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01X20D00E( + BuiltInId::imageAtomicAndExt_UImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01H20D00E( + BuiltInId::imageAtomicAndExt_ImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01S20D00E( + BuiltInId::imageAtomicAndExt_IImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01d20D00E( + BuiltInId::imageAtomicAndExt_UImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01D00D00E( + BuiltInId::imageAtomicAndExt_Image1D1_Int1_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01O00D00E( + BuiltInId::imageAtomicAndExt_IImage1D1_Int1_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01Z00D00E( + BuiltInId::imageAtomicAndExt_UImage1D1_Int1_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01E10D00E( + BuiltInId::imageAtomicAndExt_Image1DArray1_Int2_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01P10D00E( + BuiltInId::imageAtomicAndExt_IImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01a10D00E( + BuiltInId::imageAtomicAndExt_UImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01I10D00E( + BuiltInId::imageAtomicAndExt_ImageRect1_Int2_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01T10D00E( + BuiltInId::imageAtomicAndExt_IImageRect1_Int2_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01e10D00E( + BuiltInId::imageAtomicAndExt_UImageRect1_Int2_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01F10D00D00E( + BuiltInId::imageAtomicAndExt_Image2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01Q10D00D00E( + BuiltInId::imageAtomicAndExt_IImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01b10D00D00E( + BuiltInId::imageAtomicAndExt_UImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01G20D00D00E( + BuiltInId::imageAtomicAndExt_Image2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01R20D00D00E( + BuiltInId::imageAtomicAndExt_IImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01c20D00D00E( + BuiltInId::imageAtomicAndExt_UImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_00z10D00D( + BuiltInId::imageAtomicAndExt_Image2D1_Int2_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01K10D00D( + BuiltInId::imageAtomicAndExt_IImage2D1_Int2_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01V10D00D( + BuiltInId::imageAtomicAndExt_UImage2D1_Int2_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01A20D00D( + BuiltInId::imageAtomicAndExt_Image3D1_Int3_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01L20D00D( + BuiltInId::imageAtomicAndExt_IImage3D1_Int3_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01W20D00D( + BuiltInId::imageAtomicAndExt_UImage3D1_Int3_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01C20D00D( + BuiltInId::imageAtomicAndExt_ImageCube1_Int3_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01N20D00D( + BuiltInId::imageAtomicAndExt_IImageCube1_Int3_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01Y20D00D( + BuiltInId::imageAtomicAndExt_UImageCube1_Int3_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01J00D00D( + BuiltInId::imageAtomicAndExt_ImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01U00D00D( + BuiltInId::imageAtomicAndExt_IImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01f00D00D( + BuiltInId::imageAtomicAndExt_UImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01B20D00D( + BuiltInId::imageAtomicAndExt_Image2DArray1_Int3_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01M20D00D( + BuiltInId::imageAtomicAndExt_IImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01X20D00D( + BuiltInId::imageAtomicAndExt_UImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01H20D00D( + BuiltInId::imageAtomicAndExt_ImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01S20D00D( + BuiltInId::imageAtomicAndExt_IImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01d20D00D( + BuiltInId::imageAtomicAndExt_UImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01D00D00D( + BuiltInId::imageAtomicAndExt_Image1D1_Int1_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01O00D00D( + BuiltInId::imageAtomicAndExt_IImage1D1_Int1_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01Z00D00D( + BuiltInId::imageAtomicAndExt_UImage1D1_Int1_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01E10D00D( + BuiltInId::imageAtomicAndExt_Image1DArray1_Int2_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01P10D00D( + BuiltInId::imageAtomicAndExt_IImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01a10D00D( + BuiltInId::imageAtomicAndExt_UImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01I10D00D( + BuiltInId::imageAtomicAndExt_ImageRect1_Int2_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01T10D00D( + BuiltInId::imageAtomicAndExt_IImageRect1_Int2_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01e10D00D( + BuiltInId::imageAtomicAndExt_UImageRect1_Int2_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01F10D00D00D( + BuiltInId::imageAtomicAndExt_Image2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01Q10D00D00D( + BuiltInId::imageAtomicAndExt_IImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01b10D00D00D( + BuiltInId::imageAtomicAndExt_UImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01G20D00D00D( + BuiltInId::imageAtomicAndExt_Image2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01R20D00D00D( + BuiltInId::imageAtomicAndExt_IImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicAndExt_01c20D00D00D( + BuiltInId::imageAtomicAndExt_UImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicAndExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicAnd, + false); +constexpr const TFunction imageAtomicOrExt_00z10D00E( + BuiltInId::imageAtomicOrExt_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01K10D00E( + BuiltInId::imageAtomicOrExt_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01V10D00E( + BuiltInId::imageAtomicOrExt_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01A20D00E( + BuiltInId::imageAtomicOrExt_Image3D1_Int3_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01L20D00E( + BuiltInId::imageAtomicOrExt_IImage3D1_Int3_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01W20D00E( + BuiltInId::imageAtomicOrExt_UImage3D1_Int3_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01C20D00E( + BuiltInId::imageAtomicOrExt_ImageCube1_Int3_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01N20D00E( + BuiltInId::imageAtomicOrExt_IImageCube1_Int3_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01Y20D00E( + BuiltInId::imageAtomicOrExt_UImageCube1_Int3_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01J00D00E( + BuiltInId::imageAtomicOrExt_ImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01U00D00E( + BuiltInId::imageAtomicOrExt_IImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01f00D00E( + BuiltInId::imageAtomicOrExt_UImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01B20D00E( + BuiltInId::imageAtomicOrExt_Image2DArray1_Int3_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01M20D00E( + BuiltInId::imageAtomicOrExt_IImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01X20D00E( + BuiltInId::imageAtomicOrExt_UImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01H20D00E( + BuiltInId::imageAtomicOrExt_ImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01S20D00E( + BuiltInId::imageAtomicOrExt_IImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01d20D00E( + BuiltInId::imageAtomicOrExt_UImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01D00D00E( + BuiltInId::imageAtomicOrExt_Image1D1_Int1_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01O00D00E( + BuiltInId::imageAtomicOrExt_IImage1D1_Int1_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01Z00D00E( + BuiltInId::imageAtomicOrExt_UImage1D1_Int1_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01E10D00E( + BuiltInId::imageAtomicOrExt_Image1DArray1_Int2_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01P10D00E( + BuiltInId::imageAtomicOrExt_IImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01a10D00E( + BuiltInId::imageAtomicOrExt_UImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01I10D00E( + BuiltInId::imageAtomicOrExt_ImageRect1_Int2_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01T10D00E( + BuiltInId::imageAtomicOrExt_IImageRect1_Int2_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01e10D00E( + BuiltInId::imageAtomicOrExt_UImageRect1_Int2_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01F10D00D00E( + BuiltInId::imageAtomicOrExt_Image2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01Q10D00D00E( + BuiltInId::imageAtomicOrExt_IImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01b10D00D00E( + BuiltInId::imageAtomicOrExt_UImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01G20D00D00E( + BuiltInId::imageAtomicOrExt_Image2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01R20D00D00E( + BuiltInId::imageAtomicOrExt_IImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01c20D00D00E( + BuiltInId::imageAtomicOrExt_UImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_00z10D00D( + BuiltInId::imageAtomicOrExt_Image2D1_Int2_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01K10D00D( + BuiltInId::imageAtomicOrExt_IImage2D1_Int2_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01V10D00D( + BuiltInId::imageAtomicOrExt_UImage2D1_Int2_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01A20D00D( + BuiltInId::imageAtomicOrExt_Image3D1_Int3_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01L20D00D( + BuiltInId::imageAtomicOrExt_IImage3D1_Int3_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01W20D00D( + BuiltInId::imageAtomicOrExt_UImage3D1_Int3_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01C20D00D( + BuiltInId::imageAtomicOrExt_ImageCube1_Int3_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01N20D00D( + BuiltInId::imageAtomicOrExt_IImageCube1_Int3_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01Y20D00D( + BuiltInId::imageAtomicOrExt_UImageCube1_Int3_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01J00D00D( + BuiltInId::imageAtomicOrExt_ImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01U00D00D( + BuiltInId::imageAtomicOrExt_IImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01f00D00D( + BuiltInId::imageAtomicOrExt_UImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01B20D00D( + BuiltInId::imageAtomicOrExt_Image2DArray1_Int3_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01M20D00D( + BuiltInId::imageAtomicOrExt_IImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01X20D00D( + BuiltInId::imageAtomicOrExt_UImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01H20D00D( + BuiltInId::imageAtomicOrExt_ImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01S20D00D( + BuiltInId::imageAtomicOrExt_IImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01d20D00D( + BuiltInId::imageAtomicOrExt_UImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01D00D00D( + BuiltInId::imageAtomicOrExt_Image1D1_Int1_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01O00D00D( + BuiltInId::imageAtomicOrExt_IImage1D1_Int1_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01Z00D00D( + BuiltInId::imageAtomicOrExt_UImage1D1_Int1_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01E10D00D( + BuiltInId::imageAtomicOrExt_Image1DArray1_Int2_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01P10D00D( + BuiltInId::imageAtomicOrExt_IImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01a10D00D( + BuiltInId::imageAtomicOrExt_UImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01I10D00D( + BuiltInId::imageAtomicOrExt_ImageRect1_Int2_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01T10D00D( + BuiltInId::imageAtomicOrExt_IImageRect1_Int2_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01e10D00D( + BuiltInId::imageAtomicOrExt_UImageRect1_Int2_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01F10D00D00D( + BuiltInId::imageAtomicOrExt_Image2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01Q10D00D00D( + BuiltInId::imageAtomicOrExt_IImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01b10D00D00D( + BuiltInId::imageAtomicOrExt_UImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01G20D00D00D( + BuiltInId::imageAtomicOrExt_Image2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01R20D00D00D( + BuiltInId::imageAtomicOrExt_IImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicOrExt_01c20D00D00D( + BuiltInId::imageAtomicOrExt_UImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicOrExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicOr, + false); +constexpr const TFunction imageAtomicXorExt_00z10D00E( + BuiltInId::imageAtomicXorExt_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01K10D00E( + BuiltInId::imageAtomicXorExt_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01V10D00E( + BuiltInId::imageAtomicXorExt_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01A20D00E( + BuiltInId::imageAtomicXorExt_Image3D1_Int3_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01L20D00E( + BuiltInId::imageAtomicXorExt_IImage3D1_Int3_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01W20D00E( + BuiltInId::imageAtomicXorExt_UImage3D1_Int3_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01C20D00E( + BuiltInId::imageAtomicXorExt_ImageCube1_Int3_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01N20D00E( + BuiltInId::imageAtomicXorExt_IImageCube1_Int3_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01Y20D00E( + BuiltInId::imageAtomicXorExt_UImageCube1_Int3_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01J00D00E( + BuiltInId::imageAtomicXorExt_ImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01U00D00E( + BuiltInId::imageAtomicXorExt_IImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01f00D00E( + BuiltInId::imageAtomicXorExt_UImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01B20D00E( + BuiltInId::imageAtomicXorExt_Image2DArray1_Int3_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01M20D00E( + BuiltInId::imageAtomicXorExt_IImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01X20D00E( + BuiltInId::imageAtomicXorExt_UImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01H20D00E( + BuiltInId::imageAtomicXorExt_ImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01S20D00E( + BuiltInId::imageAtomicXorExt_IImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01d20D00E( + BuiltInId::imageAtomicXorExt_UImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01D00D00E( + BuiltInId::imageAtomicXorExt_Image1D1_Int1_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01O00D00E( + BuiltInId::imageAtomicXorExt_IImage1D1_Int1_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01Z00D00E( + BuiltInId::imageAtomicXorExt_UImage1D1_Int1_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01E10D00E( + BuiltInId::imageAtomicXorExt_Image1DArray1_Int2_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01P10D00E( + BuiltInId::imageAtomicXorExt_IImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01a10D00E( + BuiltInId::imageAtomicXorExt_UImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01I10D00E( + BuiltInId::imageAtomicXorExt_ImageRect1_Int2_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01T10D00E( + BuiltInId::imageAtomicXorExt_IImageRect1_Int2_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01e10D00E( + BuiltInId::imageAtomicXorExt_UImageRect1_Int2_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01F10D00D00E( + BuiltInId::imageAtomicXorExt_Image2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01Q10D00D00E( + BuiltInId::imageAtomicXorExt_IImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01b10D00D00E( + BuiltInId::imageAtomicXorExt_UImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01G20D00D00E( + BuiltInId::imageAtomicXorExt_Image2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01R20D00D00E( + BuiltInId::imageAtomicXorExt_IImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01c20D00D00E( + BuiltInId::imageAtomicXorExt_UImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_00z10D00D( + BuiltInId::imageAtomicXorExt_Image2D1_Int2_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01K10D00D( + BuiltInId::imageAtomicXorExt_IImage2D1_Int2_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01V10D00D( + BuiltInId::imageAtomicXorExt_UImage2D1_Int2_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01A20D00D( + BuiltInId::imageAtomicXorExt_Image3D1_Int3_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01L20D00D( + BuiltInId::imageAtomicXorExt_IImage3D1_Int3_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01W20D00D( + BuiltInId::imageAtomicXorExt_UImage3D1_Int3_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01C20D00D( + BuiltInId::imageAtomicXorExt_ImageCube1_Int3_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01N20D00D( + BuiltInId::imageAtomicXorExt_IImageCube1_Int3_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01Y20D00D( + BuiltInId::imageAtomicXorExt_UImageCube1_Int3_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01J00D00D( + BuiltInId::imageAtomicXorExt_ImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01U00D00D( + BuiltInId::imageAtomicXorExt_IImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01f00D00D( + BuiltInId::imageAtomicXorExt_UImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01B20D00D( + BuiltInId::imageAtomicXorExt_Image2DArray1_Int3_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01M20D00D( + BuiltInId::imageAtomicXorExt_IImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01X20D00D( + BuiltInId::imageAtomicXorExt_UImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01H20D00D( + BuiltInId::imageAtomicXorExt_ImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01S20D00D( + BuiltInId::imageAtomicXorExt_IImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01d20D00D( + BuiltInId::imageAtomicXorExt_UImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01D00D00D( + BuiltInId::imageAtomicXorExt_Image1D1_Int1_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01O00D00D( + BuiltInId::imageAtomicXorExt_IImage1D1_Int1_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01Z00D00D( + BuiltInId::imageAtomicXorExt_UImage1D1_Int1_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01E10D00D( + BuiltInId::imageAtomicXorExt_Image1DArray1_Int2_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01P10D00D( + BuiltInId::imageAtomicXorExt_IImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01a10D00D( + BuiltInId::imageAtomicXorExt_UImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01I10D00D( + BuiltInId::imageAtomicXorExt_ImageRect1_Int2_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01T10D00D( + BuiltInId::imageAtomicXorExt_IImageRect1_Int2_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01e10D00D( + BuiltInId::imageAtomicXorExt_UImageRect1_Int2_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01F10D00D00D( + BuiltInId::imageAtomicXorExt_Image2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01Q10D00D00D( + BuiltInId::imageAtomicXorExt_IImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01b10D00D00D( + BuiltInId::imageAtomicXorExt_UImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01G20D00D00D( + BuiltInId::imageAtomicXorExt_Image2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01R20D00D00D( + BuiltInId::imageAtomicXorExt_IImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicXorExt_01c20D00D00D( + BuiltInId::imageAtomicXorExt_UImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicXorExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicXor, + false); +constexpr const TFunction imageAtomicExchangeExt_00z10D00E( + BuiltInId::imageAtomicExchangeExt_Image2D1_Int2_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01K10D00E( + BuiltInId::imageAtomicExchangeExt_IImage2D1_Int2_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01V10D00E( + BuiltInId::imageAtomicExchangeExt_UImage2D1_Int2_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01A20D00E( + BuiltInId::imageAtomicExchangeExt_Image3D1_Int3_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01L20D00E( + BuiltInId::imageAtomicExchangeExt_IImage3D1_Int3_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01W20D00E( + BuiltInId::imageAtomicExchangeExt_UImage3D1_Int3_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01C20D00E( + BuiltInId::imageAtomicExchangeExt_ImageCube1_Int3_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01N20D00E( + BuiltInId::imageAtomicExchangeExt_IImageCube1_Int3_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01Y20D00E( + BuiltInId::imageAtomicExchangeExt_UImageCube1_Int3_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01J00D00E( + BuiltInId::imageAtomicExchangeExt_ImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01U00D00E( + BuiltInId::imageAtomicExchangeExt_IImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01f00D00E( + BuiltInId::imageAtomicExchangeExt_UImageBuffer1_Int1_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01B20D00E( + BuiltInId::imageAtomicExchangeExt_Image2DArray1_Int3_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01M20D00E( + BuiltInId::imageAtomicExchangeExt_IImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01X20D00E( + BuiltInId::imageAtomicExchangeExt_UImage2DArray1_Int3_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01H20D00E( + BuiltInId::imageAtomicExchangeExt_ImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01S20D00E( + BuiltInId::imageAtomicExchangeExt_IImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01d20D00E( + BuiltInId::imageAtomicExchangeExt_UImageCubeArray1_Int3_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01D00D00E( + BuiltInId::imageAtomicExchangeExt_Image1D1_Int1_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01O00D00E( + BuiltInId::imageAtomicExchangeExt_IImage1D1_Int1_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01Z00D00E( + BuiltInId::imageAtomicExchangeExt_UImage1D1_Int1_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01E10D00E( + BuiltInId::imageAtomicExchangeExt_Image1DArray1_Int2_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01P10D00E( + BuiltInId::imageAtomicExchangeExt_IImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01a10D00E( + BuiltInId::imageAtomicExchangeExt_UImage1DArray1_Int2_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01I10D00E( + BuiltInId::imageAtomicExchangeExt_ImageRect1_Int2_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01T10D00E( + BuiltInId::imageAtomicExchangeExt_IImageRect1_Int2_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01e10D00E( + BuiltInId::imageAtomicExchangeExt_UImageRect1_Int2_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00E00E, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01F10D00D00E( + BuiltInId::imageAtomicExchangeExt_Image2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01Q10D00D00E( + BuiltInId::imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01b10D00D00E( + BuiltInId::imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01G20D00D00E( + BuiltInId::imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01R20D00D00E( + BuiltInId::imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01c20D00D00E( + BuiltInId::imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_UInt1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_00z10D00D( + BuiltInId::imageAtomicExchangeExt_Image2D1_Int2_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01K10D00D( + BuiltInId::imageAtomicExchangeExt_IImage2D1_Int2_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01V10D00D( + BuiltInId::imageAtomicExchangeExt_UImage2D1_Int2_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01A20D00D( + BuiltInId::imageAtomicExchangeExt_Image3D1_Int3_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01L20D00D( + BuiltInId::imageAtomicExchangeExt_IImage3D1_Int3_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01W20D00D( + BuiltInId::imageAtomicExchangeExt_UImage3D1_Int3_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01C20D00D( + BuiltInId::imageAtomicExchangeExt_ImageCube1_Int3_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01N20D00D( + BuiltInId::imageAtomicExchangeExt_IImageCube1_Int3_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01Y20D00D( + BuiltInId::imageAtomicExchangeExt_UImageCube1_Int3_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01J00D00D( + BuiltInId::imageAtomicExchangeExt_ImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01U00D00D( + BuiltInId::imageAtomicExchangeExt_IImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01f00D00D( + BuiltInId::imageAtomicExchangeExt_UImageBuffer1_Int1_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01B20D00D( + BuiltInId::imageAtomicExchangeExt_Image2DArray1_Int3_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01M20D00D( + BuiltInId::imageAtomicExchangeExt_IImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01X20D00D( + BuiltInId::imageAtomicExchangeExt_UImage2DArray1_Int3_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01H20D00D( + BuiltInId::imageAtomicExchangeExt_ImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01S20D00D( + BuiltInId::imageAtomicExchangeExt_IImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01d20D00D( + BuiltInId::imageAtomicExchangeExt_UImageCubeArray1_Int3_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01D00D00D( + BuiltInId::imageAtomicExchangeExt_Image1D1_Int1_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01O00D00D( + BuiltInId::imageAtomicExchangeExt_IImage1D1_Int1_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01Z00D00D( + BuiltInId::imageAtomicExchangeExt_UImage1D1_Int1_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01E10D00D( + BuiltInId::imageAtomicExchangeExt_Image1DArray1_Int2_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01P10D00D( + BuiltInId::imageAtomicExchangeExt_IImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01a10D00D( + BuiltInId::imageAtomicExchangeExt_UImage1DArray1_Int2_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01I10D00D( + BuiltInId::imageAtomicExchangeExt_ImageRect1_Int2_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01T10D00D( + BuiltInId::imageAtomicExchangeExt_IImageRect1_Int2_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01e10D00D( + BuiltInId::imageAtomicExchangeExt_UImageRect1_Int2_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00D00D, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01F10D00D00D( + BuiltInId::imageAtomicExchangeExt_Image2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01Q10D00D00D( + BuiltInId::imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01b10D00D00D( + BuiltInId::imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01G20D00D00D( + BuiltInId::imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01R20D00D00D( + BuiltInId::imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01c20D00D00D( + BuiltInId::imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_00z10D00B( + BuiltInId::imageAtomicExchangeExt_Image2D1_Int2_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01K10D00B( + BuiltInId::imageAtomicExchangeExt_IImage2D1_Int2_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01V10D00B( + BuiltInId::imageAtomicExchangeExt_UImage2D1_Int2_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01A20D00B( + BuiltInId::imageAtomicExchangeExt_Image3D1_Int3_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01L20D00B( + BuiltInId::imageAtomicExchangeExt_IImage3D1_Int3_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01W20D00B( + BuiltInId::imageAtomicExchangeExt_UImage3D1_Int3_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01C20D00B( + BuiltInId::imageAtomicExchangeExt_ImageCube1_Int3_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01N20D00B( + BuiltInId::imageAtomicExchangeExt_IImageCube1_Int3_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01Y20D00B( + BuiltInId::imageAtomicExchangeExt_UImageCube1_Int3_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01J00D00B( + BuiltInId::imageAtomicExchangeExt_ImageBuffer1_Int1_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01U00D00B( + BuiltInId::imageAtomicExchangeExt_IImageBuffer1_Int1_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01f00D00B( + BuiltInId::imageAtomicExchangeExt_UImageBuffer1_Int1_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01B20D00B( + BuiltInId::imageAtomicExchangeExt_Image2DArray1_Int3_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01M20D00B( + BuiltInId::imageAtomicExchangeExt_IImage2DArray1_Int3_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01X20D00B( + BuiltInId::imageAtomicExchangeExt_UImage2DArray1_Int3_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01H20D00B( + BuiltInId::imageAtomicExchangeExt_ImageCubeArray1_Int3_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01S20D00B( + BuiltInId::imageAtomicExchangeExt_IImageCubeArray1_Int3_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01d20D00B( + BuiltInId::imageAtomicExchangeExt_UImageCubeArray1_Int3_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01D00D00B( + BuiltInId::imageAtomicExchangeExt_Image1D1_Int1_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01O00D00B( + BuiltInId::imageAtomicExchangeExt_IImage1D1_Int1_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01Z00D00B( + BuiltInId::imageAtomicExchangeExt_UImage1D1_Int1_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01E10D00B( + BuiltInId::imageAtomicExchangeExt_Image1DArray1_Int2_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01P10D00B( + BuiltInId::imageAtomicExchangeExt_IImage1DArray1_Int2_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01a10D00B( + BuiltInId::imageAtomicExchangeExt_UImage1DArray1_Int2_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01I10D00B( + BuiltInId::imageAtomicExchangeExt_ImageRect1_Int2_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01T10D00B( + BuiltInId::imageAtomicExchangeExt_IImageRect1_Int2_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01e10D00B( + BuiltInId::imageAtomicExchangeExt_UImageRect1_Int2_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00B, + 3, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01F10D00D00B( + BuiltInId::imageAtomicExchangeExt_Image2DMS1_Int2_Int1_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00B, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01Q10D00D00B( + BuiltInId::imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00B, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01b10D00D00B( + BuiltInId::imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00B, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01G20D00D00B( + BuiltInId::imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00B, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01R20D00D00B( + BuiltInId::imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00B, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicExchangeExt_01c20D00D00B( + BuiltInId::imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_Float1, + BuiltInName::imageAtomicExchangeExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00B, + 4, + StaticType::Get(), + EOpImageAtomicExchange, + false); +constexpr const TFunction imageAtomicCompSwapExt_00z10D00E00E( + BuiltInId::imageAtomicCompSwapExt_Image2D1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01K10D00E00E( + BuiltInId::imageAtomicCompSwapExt_IImage2D1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01V10D00E00E( + BuiltInId::imageAtomicCompSwapExt_UImage2D1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01A20D00E00E( + BuiltInId::imageAtomicCompSwapExt_Image3D1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01L20D00E00E( + BuiltInId::imageAtomicCompSwapExt_IImage3D1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01W20D00E00E( + BuiltInId::imageAtomicCompSwapExt_UImage3D1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01C20D00E00E( + BuiltInId::imageAtomicCompSwapExt_ImageCube1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01N20D00E00E( + BuiltInId::imageAtomicCompSwapExt_IImageCube1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01Y20D00E00E( + BuiltInId::imageAtomicCompSwapExt_UImageCube1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01J00D00E00E( + BuiltInId::imageAtomicCompSwapExt_ImageBuffer1_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01U00D00E00E( + BuiltInId::imageAtomicCompSwapExt_IImageBuffer1_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01f00D00E00E( + BuiltInId::imageAtomicCompSwapExt_UImageBuffer1_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01B20D00E00E( + BuiltInId::imageAtomicCompSwapExt_Image2DArray1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01M20D00E00E( + BuiltInId::imageAtomicCompSwapExt_IImage2DArray1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01X20D00E00E( + BuiltInId::imageAtomicCompSwapExt_UImage2DArray1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01H20D00E00E( + BuiltInId::imageAtomicCompSwapExt_ImageCubeArray1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01S20D00E00E( + BuiltInId::imageAtomicCompSwapExt_IImageCubeArray1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01d20D00E00E( + BuiltInId::imageAtomicCompSwapExt_UImageCubeArray1_Int3_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01D00D00E00E( + BuiltInId::imageAtomicCompSwapExt_Image1D1_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01O00D00E00E( + BuiltInId::imageAtomicCompSwapExt_IImage1D1_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01Z00D00E00E( + BuiltInId::imageAtomicCompSwapExt_UImage1D1_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01E10D00E00E( + BuiltInId::imageAtomicCompSwapExt_Image1DArray1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01P10D00E00E( + BuiltInId::imageAtomicCompSwapExt_IImage1DArray1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01a10D00E00E( + BuiltInId::imageAtomicCompSwapExt_UImage1DArray1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01I10D00E00E( + BuiltInId::imageAtomicCompSwapExt_ImageRect1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01T10D00E00E( + BuiltInId::imageAtomicCompSwapExt_IImageRect1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01e10D00E00E( + BuiltInId::imageAtomicCompSwapExt_UImageRect1_Int2_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00E00E, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01F10D00D00E00E( + BuiltInId::imageAtomicCompSwapExt_Image2DMS1_Int2_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00E00E, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01Q10D00D00E00E( + BuiltInId::imageAtomicCompSwapExt_IImage2DMS1_Int2_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00E00E, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01b10D00D00E00E( + BuiltInId::imageAtomicCompSwapExt_UImage2DMS1_Int2_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00E00E, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01G20D00D00E00E( + BuiltInId::imageAtomicCompSwapExt_Image2DMSArray1_Int3_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00E00E, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01R20D00D00E00E( + BuiltInId::imageAtomicCompSwapExt_IImage2DMSArray1_Int3_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00E00E, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01c20D00D00E00E( + BuiltInId::imageAtomicCompSwapExt_UImage2DMSArray1_Int3_Int1_UInt1_UInt1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00E00E, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_00z10D00D00D( + BuiltInId::imageAtomicCompSwapExt_Image2D1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p00z10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01K10D00D00D( + BuiltInId::imageAtomicCompSwapExt_IImage2D1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01K10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01V10D00D00D( + BuiltInId::imageAtomicCompSwapExt_UImage2D1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01V10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01A20D00D00D( + BuiltInId::imageAtomicCompSwapExt_Image3D1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01A20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01L20D00D00D( + BuiltInId::imageAtomicCompSwapExt_IImage3D1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01L20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01W20D00D00D( + BuiltInId::imageAtomicCompSwapExt_UImage3D1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01W20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01C20D00D00D( + BuiltInId::imageAtomicCompSwapExt_ImageCube1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01C20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01N20D00D00D( + BuiltInId::imageAtomicCompSwapExt_IImageCube1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01N20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01Y20D00D00D( + BuiltInId::imageAtomicCompSwapExt_UImageCube1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Y20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01J00D00D00D( + BuiltInId::imageAtomicCompSwapExt_ImageBuffer1_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01J00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01U00D00D00D( + BuiltInId::imageAtomicCompSwapExt_IImageBuffer1_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01U00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01f00D00D00D( + BuiltInId::imageAtomicCompSwapExt_UImageBuffer1_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01f00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01B20D00D00D( + BuiltInId::imageAtomicCompSwapExt_Image2DArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01B20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01M20D00D00D( + BuiltInId::imageAtomicCompSwapExt_IImage2DArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01M20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01X20D00D00D( + BuiltInId::imageAtomicCompSwapExt_UImage2DArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01X20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01H20D00D00D( + BuiltInId::imageAtomicCompSwapExt_ImageCubeArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01H20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01S20D00D00D( + BuiltInId::imageAtomicCompSwapExt_IImageCubeArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01S20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01d20D00D00D( + BuiltInId::imageAtomicCompSwapExt_UImageCubeArray1_Int3_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01d20D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01D00D00D00D( + BuiltInId::imageAtomicCompSwapExt_Image1D1_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01D00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01O00D00D00D( + BuiltInId::imageAtomicCompSwapExt_IImage1D1_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01O00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01Z00D00D00D( + BuiltInId::imageAtomicCompSwapExt_UImage1D1_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Z00D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01E10D00D00D( + BuiltInId::imageAtomicCompSwapExt_Image1DArray1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01E10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01P10D00D00D( + BuiltInId::imageAtomicCompSwapExt_IImage1DArray1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01P10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01a10D00D00D( + BuiltInId::imageAtomicCompSwapExt_UImage1DArray1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01a10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01I10D00D00D( + BuiltInId::imageAtomicCompSwapExt_ImageRect1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01I10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01T10D00D00D( + BuiltInId::imageAtomicCompSwapExt_IImageRect1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01T10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01e10D00D00D( + BuiltInId::imageAtomicCompSwapExt_UImageRect1_Int2_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01e10D00D00D, + 4, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01F10D00D00D00D( + BuiltInId::imageAtomicCompSwapExt_Image2DMS1_Int2_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01F10D00D00D00D, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01Q10D00D00D00D( + BuiltInId::imageAtomicCompSwapExt_IImage2DMS1_Int2_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01Q10D00D00D00D, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01b10D00D00D00D( + BuiltInId::imageAtomicCompSwapExt_UImage2DMS1_Int2_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01b10D00D00D00D, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01G20D00D00D00D( + BuiltInId::imageAtomicCompSwapExt_Image2DMSArray1_Int3_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01G20D00D00D00D, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01R20D00D00D00D( + BuiltInId::imageAtomicCompSwapExt_IImage2DMSArray1_Int3_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01R20D00D00D00D, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction imageAtomicCompSwapExt_01c20D00D00D00D( + BuiltInId::imageAtomicCompSwapExt_UImage2DMSArray1_Int3_Int1_Int1_Int1, + BuiltInName::imageAtomicCompSwapExt, + std::array{{TExtension::OES_shader_image_atomic}}, + BuiltInParameters::p01c20D00D00D00D, + 5, + StaticType::Get(), + EOpImageAtomicCompSwap, + false); +constexpr const TFunction pixelLocalLoadANGLE_01g( + BuiltInId::pixelLocalLoadANGLE_PixelLocalANGLE1, + BuiltInName::pixelLocalLoadANGLE, + std::array{{TExtension::ANGLE_shader_pixel_local_storage}}, + BuiltInParameters::p01g30B, + 1, + StaticType::Get(), + EOpPixelLocalLoadANGLE, + false); +constexpr const TFunction pixelLocalLoadANGLE_01h( + BuiltInId::pixelLocalLoadANGLE_IPixelLocalANGLE1, + BuiltInName::pixelLocalLoadANGLE, + std::array{{TExtension::ANGLE_shader_pixel_local_storage}}, + BuiltInParameters::p01h30D, + 1, + StaticType::Get(), + EOpPixelLocalLoadANGLE, + false); +constexpr const TFunction pixelLocalLoadANGLE_01i( + BuiltInId::pixelLocalLoadANGLE_UPixelLocalANGLE1, + BuiltInName::pixelLocalLoadANGLE, + std::array{{TExtension::ANGLE_shader_pixel_local_storage}}, + BuiltInParameters::p01i30E, + 1, + StaticType::Get(), + EOpPixelLocalLoadANGLE, + false); +constexpr const TFunction pixelLocalStoreANGLE_01g30B( + BuiltInId::pixelLocalStoreANGLE_PixelLocalANGLE1_Float4, + BuiltInName::pixelLocalStoreANGLE, + std::array{{TExtension::ANGLE_shader_pixel_local_storage}}, + BuiltInParameters::p01g30B, + 2, + StaticType::Get(), + EOpPixelLocalStoreANGLE, + false); +constexpr const TFunction pixelLocalStoreANGLE_01h30D( + BuiltInId::pixelLocalStoreANGLE_IPixelLocalANGLE1_Int4, + BuiltInName::pixelLocalStoreANGLE, + std::array{{TExtension::ANGLE_shader_pixel_local_storage}}, + BuiltInParameters::p01h30D, + 2, + StaticType::Get(), + EOpPixelLocalStoreANGLE, + false); +constexpr const TFunction pixelLocalStoreANGLE_01i30E( + BuiltInId::pixelLocalStoreANGLE_UPixelLocalANGLE1_UInt4, + BuiltInName::pixelLocalStoreANGLE, + std::array{{TExtension::ANGLE_shader_pixel_local_storage}}, + BuiltInParameters::p01i30E, + 2, + StaticType::Get(), + EOpPixelLocalStoreANGLE, + false); +constexpr const TFunction beginInvocationInterlockNV_( + BuiltInId::beginInvocationInterlockNV, + BuiltInName::beginInvocationInterlockNV, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpBeginInvocationInterlockNV, + false); +constexpr const TFunction endInvocationInterlockNV_( + BuiltInId::endInvocationInterlockNV, + BuiltInName::endInvocationInterlockNV, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpEndInvocationInterlockNV, + false); +constexpr const TFunction beginFragmentShaderOrderingINTEL_( + BuiltInId::beginFragmentShaderOrderingINTEL, + BuiltInName::beginFragmentShaderOrderingINTEL, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpBeginFragmentShaderOrderingINTEL, + false); +constexpr const TFunction beginInvocationInterlockARB_( + BuiltInId::beginInvocationInterlockARB, + BuiltInName::beginInvocationInterlockARB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpBeginInvocationInterlockARB, + false); +constexpr const TFunction endInvocationInterlockARB_( + BuiltInId::endInvocationInterlockARB, + BuiltInName::endInvocationInterlockARB, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpEndInvocationInterlockARB, + false); +constexpr const TFunction memoryBarrier_(BuiltInId::memoryBarrier, + BuiltInName::memoryBarrier, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpMemoryBarrier, + false); +constexpr const TFunction memoryBarrierAtomicCounter_( + BuiltInId::memoryBarrierAtomicCounter, + BuiltInName::memoryBarrierAtomicCounter, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpMemoryBarrierAtomicCounter, + false); +constexpr const TFunction memoryBarrierBuffer_( + BuiltInId::memoryBarrierBuffer, + BuiltInName::memoryBarrierBuffer, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpMemoryBarrierBuffer, + false); +constexpr const TFunction memoryBarrierImage_( + BuiltInId::memoryBarrierImage, + BuiltInName::memoryBarrierImage, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpMemoryBarrierImage, + false); +constexpr const TFunction barrier_(BuiltInId::barrier, + BuiltInName::barrier, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpBarrier, + false); +constexpr const TFunction memoryBarrierShared_( + BuiltInId::memoryBarrierShared, + BuiltInName::memoryBarrierShared, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpMemoryBarrierShared, + false); +constexpr const TFunction groupMemoryBarrier_( + BuiltInId::groupMemoryBarrier, + BuiltInName::groupMemoryBarrier, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpGroupMemoryBarrier, + false); +constexpr const TFunction barrierTCS_(BuiltInId::barrierTCS, + BuiltInName::barrierTCS, + std::array{ + {TExtension::EXT_tessellation_shader}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpBarrierTCS, + false); +constexpr const TFunction barrierTCSES3_2_( + BuiltInId::barrierTCSES3_2, + BuiltInName::barrierTCSES3_2, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpBarrierTCS, + false); +constexpr const TFunction EmitVertex_(BuiltInId::EmitVertex, + BuiltInName::EmitVertex, + std::array{{TExtension::EXT_geometry_shader, + TExtension::OES_geometry_shader}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpEmitVertex, + false); +constexpr const TFunction EmitVertexES3_2_( + BuiltInId::EmitVertexES3_2, + BuiltInName::EmitVertexES3_2, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpEmitVertex, + false); +constexpr const TFunction EndPrimitive_( + BuiltInId::EndPrimitive, + BuiltInName::EndPrimitive, + std::array{{TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpEndPrimitive, + false); +constexpr const TFunction EndPrimitiveES3_2_( + BuiltInId::EndPrimitiveES3_2, + BuiltInName::EndPrimitiveES3_2, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::empty, + 0, + StaticType::Get(), + EOpEndPrimitive, + false); +constexpr const TFunction subpassLoad_01j( + BuiltInId::subpassLoad_SubpassInput1, + BuiltInName::subpassLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01j, + 1, + StaticType::Get(), + EOpSubpassLoad, + false); +constexpr const TFunction subpassLoad_01k(BuiltInId::subpassLoad_ISubpassInput1, + BuiltInName::subpassLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01k, + 1, + StaticType::Get(), + EOpSubpassLoad, + false); +constexpr const TFunction subpassLoad_01l(BuiltInId::subpassLoad_USubpassInput1, + BuiltInName::subpassLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01l, + 1, + StaticType::Get(), + EOpSubpassLoad, + false); +constexpr const TFunction subpassLoad_01m00D( + BuiltInId::subpassLoad_SubpassInputMS1_Int1, + BuiltInName::subpassLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01m00D, + 2, + StaticType::Get(), + EOpSubpassLoad, + false); +constexpr const TFunction subpassLoad_01n00D( + BuiltInId::subpassLoad_ISubpassInputMS1_Int1, + BuiltInName::subpassLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01n00D, + 2, + StaticType::Get(), + EOpSubpassLoad, + false); +constexpr const TFunction subpassLoad_01o00D( + BuiltInId::subpassLoad_USubpassInputMS1_Int1, + BuiltInName::subpassLoad, + std::array{{TExtension::UNDEFINED}}, + BuiltInParameters::p01o00D, + 2, + StaticType::Get(), + EOpSubpassLoad, + false); + +} // namespace Func + +namespace BuiltInArray +{ +using namespace Func; +using Rule = SymbolRule; + +// Rules used to initialize the mangled name array. +constexpr SymbolRule kRules[] = { + Rule::Get(&radians_00B), + Rule::Get(&radians_10B), + Rule::Get(&radians_20B), + Rule::Get(&radians_30B), + Rule::Get(°rees_00B), + Rule::Get(°rees_10B), + Rule::Get(°rees_20B), + Rule::Get(°rees_30B), + Rule::Get(&sin_00B), + Rule::Get(&sin_10B), + Rule::Get(&sin_20B), + Rule::Get(&sin_30B), + Rule::Get(&cos_00B), + Rule::Get(&cos_10B), + Rule::Get(&cos_20B), + Rule::Get(&cos_30B), + Rule::Get(&tan_00B), + Rule::Get(&tan_10B), + Rule::Get(&tan_20B), + Rule::Get(&tan_30B), + Rule::Get(&asin_00B), + Rule::Get(&asin_10B), + Rule::Get(&asin_20B), + Rule::Get(&asin_30B), + Rule::Get(&acos_00B), + Rule::Get(&acos_10B), + Rule::Get(&acos_20B), + Rule::Get(&acos_30B), + Rule::Get(&atan_00B00B), + Rule::Get(&atan_10B10B), + Rule::Get(&atan_20B20B), + Rule::Get(&atan_30B30B), + Rule::Get(&atan_00B), + Rule::Get(&atan_10B), + Rule::Get(&atan_20B), + Rule::Get(&atan_30B), + Rule::Get(&sinh_00B), + Rule::Get(&sinh_10B), + Rule::Get(&sinh_20B), + Rule::Get(&sinh_30B), + Rule::Get(&cosh_00B), + Rule::Get(&cosh_10B), + Rule::Get(&cosh_20B), + Rule::Get(&cosh_30B), + Rule::Get(&tanh_00B), + Rule::Get(&tanh_10B), + Rule::Get(&tanh_20B), + Rule::Get(&tanh_30B), + Rule::Get(&asinh_00B), + Rule::Get(&asinh_10B), + Rule::Get(&asinh_20B), + Rule::Get(&asinh_30B), + Rule::Get(&acosh_00B), + Rule::Get(&acosh_10B), + Rule::Get(&acosh_20B), + Rule::Get(&acosh_30B), + Rule::Get(&atanh_00B), + Rule::Get(&atanh_10B), + Rule::Get(&atanh_20B), + Rule::Get(&atanh_30B), + Rule::Get(&pow_00B00B), + Rule::Get(&pow_10B10B), + Rule::Get(&pow_20B20B), + Rule::Get(&pow_30B30B), + Rule::Get(&exp_00B), + Rule::Get(&exp_10B), + Rule::Get(&exp_20B), + Rule::Get(&exp_30B), + Rule::Get(&log_00B), + Rule::Get(&log_10B), + Rule::Get(&log_20B), + Rule::Get(&log_30B), + Rule::Get(&exp2_00B), + Rule::Get(&exp2_10B), + Rule::Get(&exp2_20B), + Rule::Get(&exp2_30B), + Rule::Get(&log2_00B), + Rule::Get(&log2_10B), + Rule::Get(&log2_20B), + Rule::Get(&log2_30B), + Rule::Get(&sqrt_00B), + Rule::Get(&sqrt_10B), + Rule::Get(&sqrt_20B), + Rule::Get(&sqrt_30B), + Rule::Get(&inversesqrt_00B), + Rule::Get(&inversesqrt_10B), + Rule::Get(&inversesqrt_20B), + Rule::Get(&inversesqrt_30B), + Rule::Get(&abs_00B), + Rule::Get(&abs_10B), + Rule::Get(&abs_20B), + Rule::Get(&abs_30B), + Rule::Get(&abs_00D), + Rule::Get(&abs_10D), + Rule::Get(&abs_20D), + Rule::Get(&abs_30D), + Rule::Get(&sign_00B), + Rule::Get(&sign_10B), + Rule::Get(&sign_20B), + Rule::Get(&sign_30B), + Rule::Get(&sign_00D), + Rule::Get(&sign_10D), + Rule::Get(&sign_20D), + Rule::Get(&sign_30D), + Rule::Get(&floor_00B), + Rule::Get(&floor_10B), + Rule::Get(&floor_20B), + Rule::Get(&floor_30B), + Rule::Get(&trunc_00B), + Rule::Get(&trunc_10B), + Rule::Get(&trunc_20B), + Rule::Get(&trunc_30B), + Rule::Get(&round_00B), + Rule::Get(&round_10B), + Rule::Get(&round_20B), + Rule::Get(&round_30B), + Rule::Get(&roundEven_00B), + Rule::Get(&roundEven_10B), + Rule::Get(&roundEven_20B), + Rule::Get(&roundEven_30B), + Rule::Get(&ceil_00B), + Rule::Get(&ceil_10B), + Rule::Get(&ceil_20B), + Rule::Get(&ceil_30B), + Rule::Get(&fract_00B), + Rule::Get(&fract_10B), + Rule::Get(&fract_20B), + Rule::Get(&fract_30B), + Rule::Get(&mod_00B00B), + Rule::Get(&mod_10B00B), + Rule::Get(&mod_20B00B), + Rule::Get(&mod_30B00B), + Rule::Get(&mod_10B10B), + Rule::Get(&mod_20B20B), + Rule::Get(&mod_30B30B), + Rule::Get(&min_00B00B), + Rule::Get(&min_10B00B), + Rule::Get(&min_20B00B), + Rule::Get(&min_30B00B), + Rule::Get(&min_10B10B), + Rule::Get(&min_20B20B), + Rule::Get(&min_30B30B), + Rule::Get(&min_00D00D), + Rule::Get(&min_10D10D), + Rule::Get(&min_20D20D), + Rule::Get(&min_30D30D), + Rule::Get(&min_10D00D), + Rule::Get(&min_20D00D), + Rule::Get(&min_30D00D), + Rule::Get(&min_00E00E), + Rule::Get(&min_10E10E), + Rule::Get(&min_20E20E), + Rule::Get(&min_30E30E), + Rule::Get(&min_10E00E), + Rule::Get(&min_20E00E), + Rule::Get(&min_30E00E), + Rule::Get(&max_00B00B), + Rule::Get(&max_10B00B), + Rule::Get(&max_20B00B), + Rule::Get(&max_30B00B), + Rule::Get(&max_10B10B), + Rule::Get(&max_20B20B), + Rule::Get(&max_30B30B), + Rule::Get(&max_00D00D), + Rule::Get(&max_10D10D), + Rule::Get(&max_20D20D), + Rule::Get(&max_30D30D), + Rule::Get(&max_10D00D), + Rule::Get(&max_20D00D), + Rule::Get(&max_30D00D), + Rule::Get(&max_00E00E), + Rule::Get(&max_10E10E), + Rule::Get(&max_20E20E), + Rule::Get(&max_30E30E), + Rule::Get(&max_10E00E), + Rule::Get(&max_20E00E), + Rule::Get(&max_30E00E), + Rule::Get(&clamp_00B00B00B), + Rule::Get(&clamp_10B00B00B), + Rule::Get(&clamp_20B00B00B), + Rule::Get(&clamp_30B00B00B), + Rule::Get(&clamp_10B10B10B), + Rule::Get(&clamp_20B20B20B), + Rule::Get(&clamp_30B30B30B), + Rule::Get(&clamp_00D00D00D), + Rule::Get(&clamp_10D00D00D), + Rule::Get(&clamp_20D00D00D), + Rule::Get(&clamp_30D00D00D), + Rule::Get(&clamp_10D10D10D), + Rule::Get(&clamp_20D20D20D), + Rule::Get(&clamp_30D30D30D), + Rule::Get(&clamp_00E00E00E), + Rule::Get(&clamp_10E00E00E), + Rule::Get(&clamp_20E00E00E), + Rule::Get(&clamp_30E00E00E), + Rule::Get(&clamp_10E10E10E), + Rule::Get(&clamp_20E20E20E), + Rule::Get(&clamp_30E30E30E), + Rule::Get(&mix_00B00B00B), + Rule::Get(&mix_10B10B00B), + Rule::Get(&mix_20B20B00B), + Rule::Get(&mix_30B30B00B), + Rule::Get(&mix_10B10B10B), + Rule::Get(&mix_20B20B20B), + Rule::Get(&mix_30B30B30B), + Rule::Get(&mix_00B00B00F), + Rule::Get(&mix_10B10B10F), + Rule::Get(&mix_20B20B20F), + Rule::Get(&mix_30B30B30F), + Rule::Get(&mix_00D00D00F), + Rule::Get(&mix_10D10D10F), + Rule::Get(&mix_20D20D20F), + Rule::Get(&mix_30D30D30F), + Rule::Get(&mix_00E00E00F), + Rule::Get(&mix_10E10E10F), + Rule::Get(&mix_20E20E20F), + Rule::Get(&mix_30E30E30F), + Rule::Get(&mix_00F00F00F), + Rule::Get(&mix_10F10F10F), + Rule::Get(&mix_20F20F20F), + Rule::Get(&mix_30F30F30F), + Rule::Get(&step_00B00B), + Rule::Get(&step_10B10B), + Rule::Get(&step_20B20B), + Rule::Get(&step_30B30B), + Rule::Get(&step_00B10B), + Rule::Get(&step_00B20B), + Rule::Get(&step_00B30B), + Rule::Get(&smoothstep_00B00B00B), + Rule::Get(&smoothstep_10B10B10B), + Rule::Get(&smoothstep_20B20B20B), + Rule::Get(&smoothstep_30B30B30B), + Rule::Get(&smoothstep_00B00B10B), + Rule::Get(&smoothstep_00B00B20B), + Rule::Get(&smoothstep_00B00B30B), + Rule::Get(&modf_00B00B), + Rule::Get(&modf_10B10B), + Rule::Get(&modf_20B20B), + Rule::Get(&modf_30B30B), + Rule::Get(&isnan_00B), + Rule::Get(&isnan_10B), + Rule::Get(&isnan_20B), + Rule::Get(&isnan_30B), + Rule::Get(&isinf_00B), + Rule::Get(&isinf_10B), + Rule::Get(&isinf_20B), + Rule::Get(&isinf_30B), + Rule::Get(&floatBitsToInt_00B), + Rule::Get(&floatBitsToInt_10B), + Rule::Get(&floatBitsToInt_20B), + Rule::Get(&floatBitsToInt_30B), + Rule::Get(&floatBitsToUint_00B), + Rule::Get(&floatBitsToUint_10B), + Rule::Get(&floatBitsToUint_20B), + Rule::Get(&floatBitsToUint_30B), + Rule::Get(&intBitsToFloat_00D), + Rule::Get(&intBitsToFloat_10D), + Rule::Get(&intBitsToFloat_20D), + Rule::Get(&intBitsToFloat_30D), + Rule::Get(&uintBitsToFloat_00E), + Rule::Get(&uintBitsToFloat_10E), + Rule::Get(&uintBitsToFloat_20E), + Rule::Get(&uintBitsToFloat_30E), + Rule::Get(&fma_00B00B00B), + Rule::Get(&fmaExt_00B00B00B), + Rule::Get(&fma_10B10B10B), + Rule::Get(&fmaExt_10B10B10B), + Rule::Get(&fma_20B20B20B), + Rule::Get(&fmaExt_20B20B20B), + Rule::Get(&fma_30B30B30B), + Rule::Get(&fmaExt_30B30B30B), + Rule::Get(&frexp_00B00D), + Rule::Get(&frexp_10B10D), + Rule::Get(&frexp_20B20D), + Rule::Get(&frexp_30B30D), + Rule::Get(&ldexp_00B00D), + Rule::Get(&ldexp_10B10D), + Rule::Get(&ldexp_20B20D), + Rule::Get(&ldexp_30B30D), + Rule::Get(&packSnorm2x16_10B), + Rule::Get(&packHalf2x16_10B), + Rule::Get(&unpackSnorm2x16_00E), + Rule::Get(&unpackHalf2x16_00E), + Rule::Get(&packUnorm2x16_10B), + Rule::Get(&unpackUnorm2x16_00E), + Rule::Get(&packUnorm4x8_30B), + Rule::Get(&packSnorm4x8_30B), + Rule::Get(&unpackUnorm4x8_00E), + Rule::Get(&unpackSnorm4x8_00E), + Rule::Get(&length_00B), + Rule::Get(&length_10B), + Rule::Get(&length_20B), + Rule::Get(&length_30B), + Rule::Get(&distance_00B00B), + Rule::Get(&distance_10B10B), + Rule::Get(&distance_20B20B), + Rule::Get(&distance_30B30B), + Rule::Get(&dot_00B00B), + Rule::Get(&dot_10B10B), + Rule::Get(&dot_20B20B), + Rule::Get(&dot_30B30B), + Rule::Get(&cross_20B20B), + Rule::Get(&normalize_00B), + Rule::Get(&normalize_10B), + Rule::Get(&normalize_20B), + Rule::Get(&normalize_30B), + Rule::Get(&faceforward_00B00B00B), + Rule::Get(&faceforward_10B10B10B), + Rule::Get(&faceforward_20B20B20B), + Rule::Get(&faceforward_30B30B30B), + Rule::Get(&reflect_00B00B), + Rule::Get(&reflect_10B10B), + Rule::Get(&reflect_20B20B), + Rule::Get(&reflect_30B30B), + Rule::Get(&refract_00B00B00B), + Rule::Get(&refract_10B10B00B), + Rule::Get(&refract_20B20B00B), + Rule::Get(&refract_30B30B00B), + Rule::Get(&matrixCompMult_50B50B), + Rule::Get(&matrixCompMult_A0BA0B), + Rule::Get(&matrixCompMult_F0BF0B), + Rule::Get(&matrixCompMult_90B90B), + Rule::Get(&matrixCompMult_60B60B), + Rule::Get(&matrixCompMult_D0BD0B), + Rule::Get(&matrixCompMult_70B70B), + Rule::Get(&matrixCompMult_E0BE0B), + Rule::Get(&matrixCompMult_B0BB0B), + Rule::Get(&outerProduct_10B10B), + Rule::Get(&outerProduct_20B20B), + Rule::Get(&outerProduct_30B30B), + Rule::Get(&outerProduct_20B10B), + Rule::Get(&outerProduct_10B20B), + Rule::Get(&outerProduct_30B10B), + Rule::Get(&outerProduct_10B30B), + Rule::Get(&outerProduct_30B20B), + Rule::Get(&outerProduct_20B30B), + Rule::Get(&transpose_50B), + Rule::Get(&transpose_A0B), + Rule::Get(&transpose_F0B), + Rule::Get(&transpose_60B), + Rule::Get(&transpose_90B), + Rule::Get(&transpose_70B), + Rule::Get(&transpose_D0B), + Rule::Get(&transpose_B0B), + Rule::Get(&transpose_E0B), + Rule::Get(&determinant_50B), + Rule::Get(&determinant_A0B), + Rule::Get(&determinant_F0B), + Rule::Get(&inverse_50B), + Rule::Get(&inverse_A0B), + Rule::Get(&inverse_F0B), + Rule::Get(&lessThan_10B10B), + Rule::Get(&lessThan_20B20B), + Rule::Get(&lessThan_30B30B), + Rule::Get(&lessThan_10D10D), + Rule::Get(&lessThan_20D20D), + Rule::Get(&lessThan_30D30D), + Rule::Get(&lessThan_10E10E), + Rule::Get(&lessThan_20E20E), + Rule::Get(&lessThan_30E30E), + Rule::Get(&lessThanEqual_10B10B), + Rule::Get(&lessThanEqual_20B20B), + Rule::Get(&lessThanEqual_30B30B), + Rule::Get(&lessThanEqual_10D10D), + Rule::Get(&lessThanEqual_20D20D), + Rule::Get(&lessThanEqual_30D30D), + Rule::Get(&lessThanEqual_10E10E), + Rule::Get(&lessThanEqual_20E20E), + Rule::Get(&lessThanEqual_30E30E), + Rule::Get(&greaterThan_10B10B), + Rule::Get(&greaterThan_20B20B), + Rule::Get(&greaterThan_30B30B), + Rule::Get(&greaterThan_10D10D), + Rule::Get(&greaterThan_20D20D), + Rule::Get(&greaterThan_30D30D), + Rule::Get(&greaterThan_10E10E), + Rule::Get(&greaterThan_20E20E), + Rule::Get(&greaterThan_30E30E), + Rule::Get(&greaterThanEqual_10B10B), + Rule::Get(&greaterThanEqual_20B20B), + Rule::Get(&greaterThanEqual_30B30B), + Rule::Get(&greaterThanEqual_10D10D), + Rule::Get(&greaterThanEqual_20D20D), + Rule::Get(&greaterThanEqual_30D30D), + Rule::Get(&greaterThanEqual_10E10E), + Rule::Get(&greaterThanEqual_20E20E), + Rule::Get(&greaterThanEqual_30E30E), + Rule::Get(&equal_10B10B), + Rule::Get(&equal_20B20B), + Rule::Get(&equal_30B30B), + Rule::Get(&equal_10D10D), + Rule::Get(&equal_20D20D), + Rule::Get(&equal_30D30D), + Rule::Get(&equal_10E10E), + Rule::Get(&equal_20E20E), + Rule::Get(&equal_30E30E), + Rule::Get(&equal_10F10F), + Rule::Get(&equal_20F20F), + Rule::Get(&equal_30F30F), + Rule::Get(¬Equal_10B10B), + Rule::Get(¬Equal_20B20B), + Rule::Get(¬Equal_30B30B), + Rule::Get(¬Equal_10D10D), + Rule::Get(¬Equal_20D20D), + Rule::Get(¬Equal_30D30D), + Rule::Get(¬Equal_10E10E), + Rule::Get(¬Equal_20E20E), + Rule::Get(¬Equal_30E30E), + Rule::Get(¬Equal_10F10F), + Rule::Get(¬Equal_20F20F), + Rule::Get(¬Equal_30F30F), + Rule::Get(&any_10F), + Rule::Get(&any_20F), + Rule::Get(&any_30F), + Rule::Get(&all_10F), + Rule::Get(&all_20F), + Rule::Get(&all_30F), + Rule::Get(¬Func_10F), + Rule::Get(¬Func_20F), + Rule::Get(¬Func_30F), + Rule::Get(&bitfieldExtract_00D00D00D), + Rule::Get(&bitfieldExtract_10D00D00D), + Rule::Get(&bitfieldExtract_20D00D00D), + Rule::Get(&bitfieldExtract_30D00D00D), + Rule::Get(&bitfieldExtract_00E00D00D), + Rule::Get(&bitfieldExtract_10E00D00D), + Rule::Get(&bitfieldExtract_20E00D00D), + Rule::Get(&bitfieldExtract_30E00D00D), + Rule::Get(&bitfieldInsert_00D00D00D00D), + Rule::Get(&bitfieldInsert_10D10D00D00D), + Rule::Get(&bitfieldInsert_20D20D00D00D), + Rule::Get(&bitfieldInsert_30D30D00D00D), + Rule::Get(&bitfieldInsert_00E00E00D00D), + Rule::Get(&bitfieldInsert_10E10E00D00D), + Rule::Get(&bitfieldInsert_20E20E00D00D), + Rule::Get(&bitfieldInsert_30E30E00D00D), + Rule::Get(&bitfieldReverse_00D), + Rule::Get(&bitfieldReverse_10D), + Rule::Get(&bitfieldReverse_20D), + Rule::Get(&bitfieldReverse_30D), + Rule::Get(&bitfieldReverse_00E), + Rule::Get(&bitfieldReverse_10E), + Rule::Get(&bitfieldReverse_20E), + Rule::Get(&bitfieldReverse_30E), + Rule::Get(&bitCount_00D), + Rule::Get(&bitCount_10D), + Rule::Get(&bitCount_20D), + Rule::Get(&bitCount_30D), + Rule::Get(&bitCount_00E), + Rule::Get(&bitCount_10E), + Rule::Get(&bitCount_20E), + Rule::Get(&bitCount_30E), + Rule::Get(&findLSB_00D), + Rule::Get(&findLSB_10D), + Rule::Get(&findLSB_20D), + Rule::Get(&findLSB_30D), + Rule::Get(&findLSB_00E), + Rule::Get(&findLSB_10E), + Rule::Get(&findLSB_20E), + Rule::Get(&findLSB_30E), + Rule::Get(&findMSB_00D), + Rule::Get(&findMSB_10D), + Rule::Get(&findMSB_20D), + Rule::Get(&findMSB_30D), + Rule::Get(&findMSB_00E), + Rule::Get(&findMSB_10E), + Rule::Get(&findMSB_20E), + Rule::Get(&findMSB_30E), + Rule::Get(&uaddCarry_00E00E00E), + Rule::Get(&uaddCarry_10E10E10E), + Rule::Get(&uaddCarry_20E20E20E), + Rule::Get(&uaddCarry_30E30E30E), + Rule::Get(&usubBorrow_00E00E00E), + Rule::Get(&usubBorrow_10E10E10E), + Rule::Get(&usubBorrow_20E20E20E), + Rule::Get(&usubBorrow_30E30E30E), + Rule::Get(&umulExtended_00E00E00E00E), + Rule::Get(&umulExtended_10E10E10E10E), + Rule::Get(&umulExtended_20E20E20E20E), + Rule::Get(&umulExtended_30E30E30E30E), + Rule::Get(&imulExtended_00D00D00D00D), + Rule::Get(&imulExtended_10D10D10D10D), + Rule::Get(&imulExtended_20D20D20D20D), + Rule::Get(&imulExtended_30D30D30D30D), + Rule::Get(&texture2D_00I10B), + Rule::Get(&texture2DProj_00I20B), + Rule::Get(&texture2DProj_00I30B), + Rule::Get(&textureCube_00K20B), + Rule::Get(&texture3D_00J20B), + Rule::Get(&texture3DProj_00J30B), + Rule::Get(&shadow2DEXT_00d20B), + Rule::Get( + &shadow2DProjEXT_00d30B), + Rule::Get(&texture2D_00M10B), + Rule::Get( + &texture2D_00M10B), + Rule::Get( + &texture2DProj_00M20B), + Rule::Get( + &texture2DProj_00M20B), + Rule::Get( + &texture2DProj_00M30B), + Rule::Get( + &texture2DProj_00M30B), + Rule::Get( + &texture2DRect_00O10B), + Rule::Get( + &texture2DRectProj_00O20B), + Rule::Get( + &texture2DRectProj_00O30B), + Rule::Get( + &texture2DGradEXT_00I10B10B10B), + Rule::Get( + &texture2DProjGradEXT_00I20B10B10B), + Rule::Get( + &texture2DProjGradEXT_00I30B10B10B), + Rule::Get( + &textureCubeGradEXT_00K20B20B20B), + Rule::Get(&textureVideoWEBGL_00y10B), + Rule::Get(&texture2D_00I10B00B), + Rule::Get(&texture2DProj_00I20B00B), + Rule::Get(&texture2DProj_00I30B00B), + Rule::Get(&textureCube_00K20B00B), + Rule::Get(&texture3D_00J20B00B), + Rule::Get( + &texture3DProj_00J30B00B), + Rule::Get(&texture3DLod_00J20B00B), + Rule::Get(&texture3DProjLod_00J30B00B), + Rule::Get(&texture2DLod_00I10B00B), + Rule::Get(&texture2DProjLod_00I20B00B), + Rule::Get(&texture2DProjLod_00I30B00B), + Rule::Get(&textureCubeLod_00K20B00B), + Rule::Get( + &texture2DLodEXT_00I10B00B), + Rule::Get( + &texture2DProjLodEXT_00I20B00B), + Rule::Get( + &texture2DProjLodEXT_00I30B00B), + Rule::Get( + &textureCubeLodEXT_00K20B00B), + Rule::Get(&texture_00I10B), + Rule::Get(&texture_00R10B), + Rule::Get(&texture_00X10B), + Rule::Get(&texture_00J20B), + Rule::Get(&texture_00S20B), + Rule::Get(&texture_00Y20B), + Rule::Get(&texture_00K20B), + Rule::Get(&texture_00T20B), + Rule::Get(&texture_00Z20B), + Rule::Get(&texture_00L20B), + Rule::Get(&texture_00U20B), + Rule::Get(&texture_00a20B), + Rule::Get(&texture_00d20B), + Rule::Get(&texture_00e30B), + Rule::Get(&texture_00f30B), + Rule::Get(&texture_00k30B), + Rule::Get( + &textureExt_00k30B), + Rule::Get( + &textureExt_00k30B), + Rule::Get(&texture_00s30B), + Rule::Get( + &textureExt_00s30B), + Rule::Get( + &textureExt_00s30B), + Rule::Get(&texture_00x30B), + Rule::Get( + &textureExt_00x30B), + Rule::Get( + &textureExt_00x30B), + Rule::Get(&texture_00l30B00B), + Rule::Get( + &textureExt_00l30B00B), + Rule::Get( + &textureExt_00l30B00B), + Rule::Get( + &texture_00M10B), + Rule::Get(&texture_00N10B), + Rule::Get(&texture_00O10B), + Rule::Get(&texture_00y10B), + Rule::Get(&textureProj_00I20B), + Rule::Get(&textureProj_00R20B), + Rule::Get(&textureProj_00X20B), + Rule::Get(&textureProj_00I30B), + Rule::Get(&textureProj_00R30B), + Rule::Get(&textureProj_00X30B), + Rule::Get(&textureProj_00J30B), + Rule::Get(&textureProj_00S30B), + Rule::Get(&textureProj_00Y30B), + Rule::Get(&textureProj_00d30B), + Rule::Get( + &textureProj_00M20B), + Rule::Get( + &textureProj_00M30B), + Rule::Get(&textureProj_00N20B), + Rule::Get(&textureProj_00N30B), + Rule::Get(&textureProj_00O20B), + Rule::Get(&textureProj_00O30B), + Rule::Get(&textureLod_00I10B00B), + Rule::Get(&textureLod_00R10B00B), + Rule::Get(&textureLod_00X10B00B), + Rule::Get(&textureLod_00J20B00B), + Rule::Get(&textureLod_00S20B00B), + Rule::Get(&textureLod_00Y20B00B), + Rule::Get(&textureLod_00K20B00B), + Rule::Get(&textureLod_00T20B00B), + Rule::Get(&textureLod_00Z20B00B), + Rule::Get(&textureLod_00L20B00B), + Rule::Get(&textureLod_00U20B00B), + Rule::Get(&textureLod_00a20B00B), + Rule::Get(&textureLod_00d20B00B), + Rule::Get(&textureLod_00k30B00B), + Rule::Get( + &textureLodExt_00k30B00B), + Rule::Get( + &textureLodExt_00k30B00B), + Rule::Get(&textureLod_00s30B00B), + Rule::Get( + &textureLodExt_00s30B00B), + Rule::Get( + &textureLodExt_00s30B00B), + Rule::Get(&textureLod_00x30B00B), + Rule::Get( + &textureLodExt_00x30B00B), + Rule::Get( + &textureLodExt_00x30B00B), + Rule::Get(&textureSize_00I00D), + Rule::Get(&textureSize_00R00D), + Rule::Get(&textureSize_00X00D), + Rule::Get(&textureSize_00J00D), + Rule::Get(&textureSize_00S00D), + Rule::Get(&textureSize_00Y00D), + Rule::Get(&textureSize_00K00D), + Rule::Get(&textureSize_00T00D), + Rule::Get(&textureSize_00Z00D), + Rule::Get(&textureSize_00L00D), + Rule::Get(&textureSize_00U00D), + Rule::Get(&textureSize_00a00D), + Rule::Get(&textureSize_00d00D), + Rule::Get(&textureSize_00e00D), + Rule::Get(&textureSize_00f00D), + Rule::Get(&textureSize_00k00D), + Rule::Get( + &textureSizeExt_00k00D), + Rule::Get( + &textureSizeExt_00k00D), + Rule::Get(&textureSize_00s00D), + Rule::Get( + &textureSizeExt_00s00D), + Rule::Get( + &textureSizeExt_00s00D), + Rule::Get(&textureSize_00x00D), + Rule::Get( + &textureSizeExt_00x00D), + Rule::Get( + &textureSizeExt_00x00D), + Rule::Get(&textureSize_00l00D), + Rule::Get( + &textureSizeExt_00l00D), + Rule::Get( + &textureSizeExt_00l00D), + Rule::Get(&textureSize_00j), + Rule::Get(&textureSizeExt_00j), + Rule::Get(&textureSizeExt_00j), + Rule::Get(&textureSize_00r), + Rule::Get(&textureSizeExt_00r), + Rule::Get(&textureSizeExt_00r), + Rule::Get(&textureSize_00w), + Rule::Get(&textureSizeExt_00w), + Rule::Get(&textureSizeExt_00w), + Rule::Get(&textureSize_00P), + Rule::Get( + &textureSizeExt_00P), + Rule::Get(&textureSize_00V), + Rule::Get( + &textureSizeExt_00V), + Rule::Get(&textureSize_00b), + Rule::Get( + &textureSizeExt_00b), + Rule::Get(&textureSize_00Q), + Rule::Get( + &textureSizeExt_00Q), + Rule::Get(&textureSize_00W), + Rule::Get( + &textureSizeExt_00W), + Rule::Get(&textureSize_00c), + Rule::Get( + &textureSizeExt_00c), + Rule::Get( + &textureSize_00M00D), + Rule::Get(&textureSize_00N00D), + Rule::Get(&textureProjLod_00I20B00B), + Rule::Get(&textureProjLod_00R20B00B), + Rule::Get(&textureProjLod_00X20B00B), + Rule::Get(&textureProjLod_00I30B00B), + Rule::Get(&textureProjLod_00R30B00B), + Rule::Get(&textureProjLod_00X30B00B), + Rule::Get(&textureProjLod_00J30B00B), + Rule::Get(&textureProjLod_00S30B00B), + Rule::Get(&textureProjLod_00Y30B00B), + Rule::Get(&textureProjLod_00d30B00B), + Rule::Get(&texelFetch_00I10D00D), + Rule::Get(&texelFetch_00R10D00D), + Rule::Get(&texelFetch_00X10D00D), + Rule::Get(&texelFetch_00J20D00D), + Rule::Get(&texelFetch_00S20D00D), + Rule::Get(&texelFetch_00Y20D00D), + Rule::Get(&texelFetch_00L20D00D), + Rule::Get(&texelFetch_00U20D00D), + Rule::Get(&texelFetch_00a20D00D), + Rule::Get(&texelFetch_00j00D), + Rule::Get(&texelFetchExt_00j00D), + Rule::Get(&texelFetchExt_00j00D), + Rule::Get(&texelFetch_00r00D), + Rule::Get(&texelFetchExt_00r00D), + Rule::Get(&texelFetchExt_00r00D), + Rule::Get(&texelFetch_00w00D), + Rule::Get(&texelFetchExt_00w00D), + Rule::Get(&texelFetchExt_00w00D), + Rule::Get(&texelFetch_00P10D00D), + Rule::Get( + &texelFetchExt_00P10D00D), + Rule::Get(&texelFetch_00V10D00D), + Rule::Get( + &texelFetchExt_00V10D00D), + Rule::Get(&texelFetch_00b10D00D), + Rule::Get( + &texelFetchExt_00b10D00D), + Rule::Get(&texelFetch_00Q20D00D), + Rule::Get( + &texelFetchExt_00Q20D00D), + Rule::Get(&texelFetch_00W20D00D), + Rule::Get( + &texelFetchExt_00W20D00D), + Rule::Get(&texelFetch_00c20D00D), + Rule::Get( + &texelFetchExt_00c20D00D), + Rule::Get( + &texelFetch_00M10D00D), + Rule::Get(&texelFetch_00N10D00D), + Rule::Get(&textureGrad_00I10B10B10B), + Rule::Get(&textureGrad_00R10B10B10B), + Rule::Get(&textureGrad_00X10B10B10B), + Rule::Get(&textureGrad_00J20B20B20B), + Rule::Get(&textureGrad_00S20B20B20B), + Rule::Get(&textureGrad_00Y20B20B20B), + Rule::Get(&textureGrad_00K20B20B20B), + Rule::Get(&textureGrad_00T20B20B20B), + Rule::Get(&textureGrad_00Z20B20B20B), + Rule::Get(&textureGrad_00d20B10B10B), + Rule::Get(&textureGrad_00e30B20B20B), + Rule::Get(&textureGrad_00L20B10B10B), + Rule::Get(&textureGrad_00U20B10B10B), + Rule::Get(&textureGrad_00a20B10B10B), + Rule::Get(&textureGrad_00f30B10B10B), + Rule::Get(&textureGrad_00k30B20B20B), + Rule::Get( + &textureGradExt_00k30B20B20B), + Rule::Get( + &textureGradExt_00k30B20B20B), + Rule::Get(&textureGrad_00s30B20B20B), + Rule::Get( + &textureGradExt_00s30B20B20B), + Rule::Get( + &textureGradExt_00s30B20B20B), + Rule::Get(&textureGrad_00x30B20B20B), + Rule::Get( + &textureGradExt_00x30B20B20B), + Rule::Get( + &textureGradExt_00x30B20B20B), + Rule::Get(&textureProjGrad_00I20B10B10B), + Rule::Get(&textureProjGrad_00R20B10B10B), + Rule::Get(&textureProjGrad_00X20B10B10B), + Rule::Get(&textureProjGrad_00I30B10B10B), + Rule::Get(&textureProjGrad_00R30B10B10B), + Rule::Get(&textureProjGrad_00X30B10B10B), + Rule::Get(&textureProjGrad_00J30B20B20B), + Rule::Get(&textureProjGrad_00S30B20B20B), + Rule::Get(&textureProjGrad_00Y30B20B20B), + Rule::Get(&textureProjGrad_00d30B10B10B), + Rule::Get(&texture_00I10B00B), + Rule::Get(&texture_00R10B00B), + Rule::Get(&texture_00X10B00B), + Rule::Get(&texture_00J20B00B), + Rule::Get(&texture_00S20B00B), + Rule::Get(&texture_00Y20B00B), + Rule::Get(&texture_00K20B00B), + Rule::Get(&texture_00T20B00B), + Rule::Get(&texture_00Z20B00B), + Rule::Get(&texture_00L20B00B), + Rule::Get(&texture_00U20B00B), + Rule::Get(&texture_00a20B00B), + Rule::Get(&textureProj_00I20B00B), + Rule::Get(&textureProj_00R20B00B), + Rule::Get(&textureProj_00X20B00B), + Rule::Get(&textureProj_00I30B00B), + Rule::Get(&textureProj_00R30B00B), + Rule::Get(&textureProj_00X30B00B), + Rule::Get(&textureProj_00J30B00B), + Rule::Get(&textureProj_00S30B00B), + Rule::Get(&textureProj_00Y30B00B), + Rule::Get(&texture_00d20B00B), + Rule::Get(&texture_00e30B00B), + Rule::Get(&textureProj_00d30B00B), + Rule::Get(&texture_00k30B00B), + Rule::Get( + &textureExt_00k30B00B), + Rule::Get( + &textureExt_00k30B00B), + Rule::Get(&texture_00s30B00B), + Rule::Get( + &textureExt_00s30B00B), + Rule::Get( + &textureExt_00s30B00B), + Rule::Get(&texture_00x30B00B), + Rule::Get( + &textureExt_00x30B00B), + Rule::Get( + &textureExt_00x30B00B), + Rule::Get( + &texture_00M10B00B), + Rule::Get( + &textureProj_00M20B00B), + Rule::Get( + &textureProj_00M30B00B), + Rule::Get(&texture_00N10B00B), + Rule::Get(&textureProj_00N20B00B), + Rule::Get(&textureProj_00N30B00B), + Rule::Get(&textureOffset_00I10B10D), + Rule::Get(&textureOffset_00R10B10D), + Rule::Get(&textureOffset_00X10B10D), + Rule::Get(&textureOffset_00J20B20D), + Rule::Get(&textureOffset_00S20B20D), + Rule::Get(&textureOffset_00Y20B20D), + Rule::Get(&textureOffset_00d20B10D), + Rule::Get(&textureOffset_00L20B10D), + Rule::Get(&textureOffset_00U20B10D), + Rule::Get(&textureOffset_00a20B10D), + Rule::Get(&textureProjOffset_00I20B10D), + Rule::Get(&textureProjOffset_00R20B10D), + Rule::Get(&textureProjOffset_00X20B10D), + Rule::Get(&textureProjOffset_00I30B10D), + Rule::Get(&textureProjOffset_00R30B10D), + Rule::Get(&textureProjOffset_00X30B10D), + Rule::Get(&textureProjOffset_00J30B20D), + Rule::Get(&textureProjOffset_00S30B20D), + Rule::Get(&textureProjOffset_00Y30B20D), + Rule::Get(&textureProjOffset_00d30B10D), + Rule::Get(&textureLodOffset_00I10B00B10D), + Rule::Get(&textureLodOffset_00R10B00B10D), + Rule::Get(&textureLodOffset_00X10B00B10D), + Rule::Get(&textureLodOffset_00J20B00B20D), + Rule::Get(&textureLodOffset_00S20B00B20D), + Rule::Get(&textureLodOffset_00Y20B00B20D), + Rule::Get(&textureLodOffset_00d20B00B10D), + Rule::Get(&textureLodOffset_00L20B00B10D), + Rule::Get(&textureLodOffset_00U20B00B10D), + Rule::Get(&textureLodOffset_00a20B00B10D), + Rule::Get(&textureProjLodOffset_00I20B00B10D), + Rule::Get(&textureProjLodOffset_00R20B00B10D), + Rule::Get(&textureProjLodOffset_00X20B00B10D), + Rule::Get(&textureProjLodOffset_00I30B00B10D), + Rule::Get(&textureProjLodOffset_00R30B00B10D), + Rule::Get(&textureProjLodOffset_00X30B00B10D), + Rule::Get(&textureProjLodOffset_00J30B00B20D), + Rule::Get(&textureProjLodOffset_00S30B00B20D), + Rule::Get(&textureProjLodOffset_00Y30B00B20D), + Rule::Get(&textureProjLodOffset_00d30B00B10D), + Rule::Get(&texelFetchOffset_00I10D00D10D), + Rule::Get(&texelFetchOffset_00R10D00D10D), + Rule::Get(&texelFetchOffset_00X10D00D10D), + Rule::Get(&texelFetchOffset_00J20D00D20D), + Rule::Get(&texelFetchOffset_00S20D00D20D), + Rule::Get(&texelFetchOffset_00Y20D00D20D), + Rule::Get(&texelFetchOffset_00L20D00D10D), + Rule::Get(&texelFetchOffset_00U20D00D10D), + Rule::Get(&texelFetchOffset_00a20D00D10D), + Rule::Get(&textureGradOffset_00I10B10B10B10D), + Rule::Get(&textureGradOffset_00R10B10B10B10D), + Rule::Get(&textureGradOffset_00X10B10B10B10D), + Rule::Get(&textureGradOffset_00J20B20B20B20D), + Rule::Get(&textureGradOffset_00S20B20B20B20D), + Rule::Get(&textureGradOffset_00Y20B20B20B20D), + Rule::Get(&textureGradOffset_00d20B10B10B10D), + Rule::Get(&textureGradOffset_00L20B10B10B10D), + Rule::Get(&textureGradOffset_00U20B10B10B10D), + Rule::Get(&textureGradOffset_00a20B10B10B10D), + Rule::Get(&textureGradOffset_00f30B10B10B10D), + Rule::Get(&textureProjGradOffset_00I20B10B10B10D), + Rule::Get(&textureProjGradOffset_00R20B10B10B10D), + Rule::Get(&textureProjGradOffset_00X20B10B10B10D), + Rule::Get(&textureProjGradOffset_00I30B10B10B10D), + Rule::Get(&textureProjGradOffset_00R30B10B10B10D), + Rule::Get(&textureProjGradOffset_00X30B10B10B10D), + Rule::Get(&textureProjGradOffset_00J30B20B20B20D), + Rule::Get(&textureProjGradOffset_00S30B20B20B20D), + Rule::Get(&textureProjGradOffset_00Y30B20B20B20D), + Rule::Get(&textureProjGradOffset_00d30B10B10B10D), + Rule::Get(&textureOffset_00I10B10D00B), + Rule::Get(&textureOffset_00R10B10D00B), + Rule::Get(&textureOffset_00X10B10D00B), + Rule::Get(&textureOffset_00J20B20D00B), + Rule::Get(&textureOffset_00S20B20D00B), + Rule::Get(&textureOffset_00Y20B20D00B), + Rule::Get(&textureOffset_00d20B10D00B), + Rule::Get(&textureOffset_00L20B10D00B), + Rule::Get(&textureOffset_00U20B10D00B), + Rule::Get(&textureOffset_00a20B10D00B), + Rule::Get(&textureProjOffset_00I20B10D00B), + Rule::Get(&textureProjOffset_00R20B10D00B), + Rule::Get(&textureProjOffset_00X20B10D00B), + Rule::Get(&textureProjOffset_00I30B10D00B), + Rule::Get(&textureProjOffset_00R30B10D00B), + Rule::Get(&textureProjOffset_00X30B10D00B), + Rule::Get(&textureProjOffset_00J30B20D00B), + Rule::Get(&textureProjOffset_00S30B20D00B), + Rule::Get(&textureProjOffset_00Y30B20D00B), + Rule::Get(&textureProjOffset_00d30B10D00B), + Rule::Get(&textureGather_00I10B), + Rule::Get(&textureGather_00R10B), + Rule::Get(&textureGather_00X10B), + Rule::Get(&textureGather_00I10B00D), + Rule::Get(&textureGather_00R10B00D), + Rule::Get(&textureGather_00X10B00D), + Rule::Get(&textureGather_00L20B), + Rule::Get(&textureGather_00U20B), + Rule::Get(&textureGather_00a20B), + Rule::Get(&textureGather_00L20B00D), + Rule::Get(&textureGather_00U20B00D), + Rule::Get(&textureGather_00a20B00D), + Rule::Get(&textureGather_00K20B), + Rule::Get(&textureGather_00T20B), + Rule::Get(&textureGather_00Z20B), + Rule::Get(&textureGather_00K20B00D), + Rule::Get(&textureGather_00T20B00D), + Rule::Get(&textureGather_00Z20B00D), + Rule::Get(&textureGather_00k30B), + Rule::Get( + &textureGatherExt_00k30B), + Rule::Get( + &textureGatherExt_00k30B), + Rule::Get(&textureGather_00s30B), + Rule::Get( + &textureGatherExt_00s30B), + Rule::Get( + &textureGatherExt_00s30B), + Rule::Get(&textureGather_00x30B), + Rule::Get( + &textureGatherExt_00x30B), + Rule::Get( + &textureGatherExt_00x30B), + Rule::Get(&textureGather_00k30B00D), + Rule::Get( + &textureGatherExt_00k30B00D), + Rule::Get( + &textureGatherExt_00k30B00D), + Rule::Get(&textureGather_00s30B00D), + Rule::Get( + &textureGatherExt_00s30B00D), + Rule::Get( + &textureGatherExt_00s30B00D), + Rule::Get(&textureGather_00x30B00D), + Rule::Get( + &textureGatherExt_00x30B00D), + Rule::Get( + &textureGatherExt_00x30B00D), + Rule::Get(&textureGather_00l30B00B), + Rule::Get( + &textureGatherExt_00l30B00B), + Rule::Get( + &textureGatherExt_00l30B00B), + Rule::Get(&textureGather_00d10B), + Rule::Get(&textureGather_00d10B00B), + Rule::Get(&textureGather_00f20B), + Rule::Get(&textureGather_00f20B00B), + Rule::Get(&textureGather_00e20B), + Rule::Get(&textureGather_00e20B00B), + Rule::Get(&textureGatherOffset_00I10B10D), + Rule::Get(&textureGatherOffset_00R10B10D), + Rule::Get(&textureGatherOffset_00X10B10D), + Rule::Get(&textureGatherOffset_00L20B10D), + Rule::Get(&textureGatherOffset_00U20B10D), + Rule::Get(&textureGatherOffset_00a20B10D), + Rule::Get(&textureGatherOffset_00d10B00B10D), + Rule::Get(&textureGatherOffset_00f20B00B10D), + Rule::Get(&textureGatherOffset_00I10B10D00D), + Rule::Get(&textureGatherOffset_00R10B10D00D), + Rule::Get(&textureGatherOffset_00X10B10D00D), + Rule::Get(&textureGatherOffset_00L20B10D00D), + Rule::Get(&textureGatherOffset_00U20B10D00D), + Rule::Get(&textureGatherOffset_00a20B10D00D), + Rule::Get(&textureGatherOffsets_00I10B10Dx4), + Rule::Get( + &textureGatherOffsetsExt_00I10B10Dx4), + Rule::Get(&textureGatherOffsets_00R10B10Dx4), + Rule::Get( + &textureGatherOffsetsExt_00R10B10Dx4), + Rule::Get(&textureGatherOffsets_00X10B10Dx4), + Rule::Get( + &textureGatherOffsetsExt_00X10B10Dx4), + Rule::Get(&textureGatherOffsets_00L20B10Dx4), + Rule::Get( + &textureGatherOffsetsExt_00L20B10Dx4), + Rule::Get(&textureGatherOffsets_00U20B10Dx4), + Rule::Get( + &textureGatherOffsetsExt_00U20B10Dx4), + Rule::Get(&textureGatherOffsets_00a20B10Dx4), + Rule::Get( + &textureGatherOffsetsExt_00a20B10Dx4), + Rule::Get(&textureGatherOffsets_00d10B00B10Dx4), + Rule::Get( + &textureGatherOffsetsExt_00d10B00B10Dx4), + Rule::Get(&textureGatherOffsets_00f20B00B10Dx4), + Rule::Get( + &textureGatherOffsetsExt_00f20B00B10Dx4), + Rule::Get(&textureGatherOffsets_00I10B10Dx400D), + Rule::Get( + &textureGatherOffsetsExt_00I10B10Dx400D), + Rule::Get(&textureGatherOffsets_00R10B10Dx400D), + Rule::Get( + &textureGatherOffsetsExt_00R10B10Dx400D), + Rule::Get(&textureGatherOffsets_00X10B10Dx400D), + Rule::Get( + &textureGatherOffsetsExt_00X10B10Dx400D), + Rule::Get(&textureGatherOffsets_00L20B10Dx400D), + Rule::Get( + &textureGatherOffsetsExt_00L20B10Dx400D), + Rule::Get(&textureGatherOffsets_00U20B10Dx400D), + Rule::Get( + &textureGatherOffsetsExt_00U20B10Dx400D), + Rule::Get(&textureGatherOffsets_00a20B10Dx400D), + Rule::Get( + &textureGatherOffsetsExt_00a20B10Dx400D), + Rule::Get(&rgb_2_yuv_20B00H), + Rule::Get(&yuv_2_rgb_20B00H), + Rule::Get(&dFdx_00B), + Rule::Get(&dFdxExt_00B), + Rule::Get(&dFdx_10B), + Rule::Get(&dFdxExt_10B), + Rule::Get(&dFdx_20B), + Rule::Get(&dFdxExt_20B), + Rule::Get(&dFdx_30B), + Rule::Get(&dFdxExt_30B), + Rule::Get(&dFdy_00B), + Rule::Get(&dFdyExt_00B), + Rule::Get(&dFdy_10B), + Rule::Get(&dFdyExt_10B), + Rule::Get(&dFdy_20B), + Rule::Get(&dFdyExt_20B), + Rule::Get(&dFdy_30B), + Rule::Get(&dFdyExt_30B), + Rule::Get(&fwidth_00B), + Rule::Get( + &fwidthExt_00B), + Rule::Get(&fwidth_10B), + Rule::Get( + &fwidthExt_10B), + Rule::Get(&fwidth_20B), + Rule::Get( + &fwidthExt_20B), + Rule::Get(&fwidth_30B), + Rule::Get( + &fwidthExt_30B), + Rule::Get(&interpolateAtCentroid_00B), + Rule::Get( + &interpolateAtCentroidExt_00B), + Rule::Get(&interpolateAtCentroid_10B), + Rule::Get( + &interpolateAtCentroidExt_10B), + Rule::Get(&interpolateAtCentroid_20B), + Rule::Get( + &interpolateAtCentroidExt_20B), + Rule::Get(&interpolateAtCentroid_30B), + Rule::Get( + &interpolateAtCentroidExt_30B), + Rule::Get(&interpolateAtSample_00B00D), + Rule::Get( + &interpolateAtSampleExt_00B00D), + Rule::Get(&interpolateAtSample_10B00D), + Rule::Get( + &interpolateAtSampleExt_10B00D), + Rule::Get(&interpolateAtSample_20B00D), + Rule::Get( + &interpolateAtSampleExt_20B00D), + Rule::Get(&interpolateAtSample_30B00D), + Rule::Get( + &interpolateAtSampleExt_30B00D), + Rule::Get(&interpolateAtOffset_00B10B), + Rule::Get( + &interpolateAtOffsetExt_00B10B), + Rule::Get(&interpolateAtOffset_10B10B), + Rule::Get( + &interpolateAtOffsetExt_10B10B), + Rule::Get(&interpolateAtOffset_20B10B), + Rule::Get( + &interpolateAtOffsetExt_20B10B), + Rule::Get(&interpolateAtOffset_30B10B), + Rule::Get( + &interpolateAtOffsetExt_30B10B), + Rule::Get(&atomicCounter_00G), + Rule::Get(&atomicCounterIncrement_00G), + Rule::Get(&atomicCounterDecrement_00G), + Rule::Get(&atomicAdd_00E00E), + Rule::Get(&atomicAdd_00D00D), + Rule::Get(&atomicMin_00E00E), + Rule::Get(&atomicMin_00D00D), + Rule::Get(&atomicMax_00E00E), + Rule::Get(&atomicMax_00D00D), + Rule::Get(&atomicAnd_00E00E), + Rule::Get(&atomicAnd_00D00D), + Rule::Get(&atomicOr_00E00E), + Rule::Get(&atomicOr_00D00D), + Rule::Get(&atomicXor_00E00E), + Rule::Get(&atomicXor_00D00D), + Rule::Get(&atomicExchange_00E00E), + Rule::Get(&atomicExchange_00D00D), + Rule::Get(&atomicCompSwap_00E00E00E), + Rule::Get(&atomicCompSwap_00D00D00D), + Rule::Get(&imageSize_00z), + Rule::Get(&imageSize_01K), + Rule::Get(&imageSize_01V), + Rule::Get(&imageSize_01A), + Rule::Get(&imageSize_01L), + Rule::Get(&imageSize_01W), + Rule::Get(&imageSize_01B), + Rule::Get(&imageSize_01M), + Rule::Get(&imageSize_01X), + Rule::Get(&imageSize_01C), + Rule::Get(&imageSize_01N), + Rule::Get(&imageSize_01Y), + Rule::Get(&imageSize_01H), + Rule::Get( + &imageSizeExt_01H), + Rule::Get( + &imageSizeExt_01H), + Rule::Get(&imageSize_01S), + Rule::Get( + &imageSizeExt_01S), + Rule::Get( + &imageSizeExt_01S), + Rule::Get(&imageSize_01d), + Rule::Get( + &imageSizeExt_01d), + Rule::Get( + &imageSizeExt_01d), + Rule::Get(&imageSize_01J), + Rule::Get(&imageSizeExt_01J), + Rule::Get(&imageSizeExt_01J), + Rule::Get(&imageSize_01U), + Rule::Get(&imageSizeExt_01U), + Rule::Get(&imageSizeExt_01U), + Rule::Get(&imageSize_01f), + Rule::Get(&imageSizeExt_01f), + Rule::Get(&imageSizeExt_01f), + Rule::Get(&imageStore_00z10D30B), + Rule::Get(&imageStore_01K10D30D), + Rule::Get(&imageStore_01V10D30E), + Rule::Get(&imageStore_01A20D30B), + Rule::Get(&imageStore_01L20D30D), + Rule::Get(&imageStore_01W20D30E), + Rule::Get(&imageStore_01B20D30B), + Rule::Get(&imageStore_01M20D30D), + Rule::Get(&imageStore_01X20D30E), + Rule::Get(&imageStore_01C20D30B), + Rule::Get(&imageStore_01N20D30D), + Rule::Get(&imageStore_01Y20D30E), + Rule::Get(&imageStore_01H20D30B), + Rule::Get( + &imageStoreExt_01H20D30B), + Rule::Get( + &imageStoreExt_01H20D30B), + Rule::Get(&imageStore_01S20D30D), + Rule::Get( + &imageStoreExt_01S20D30D), + Rule::Get( + &imageStoreExt_01S20D30D), + Rule::Get(&imageStore_01d20D30E), + Rule::Get( + &imageStoreExt_01d20D30E), + Rule::Get( + &imageStoreExt_01d20D30E), + Rule::Get(&imageStore_01J00D30B), + Rule::Get( + &imageStoreExt_01J00D30B), + Rule::Get( + &imageStoreExt_01J00D30B), + Rule::Get(&imageStore_01U00D30D), + Rule::Get( + &imageStoreExt_01U00D30D), + Rule::Get( + &imageStoreExt_01U00D30D), + Rule::Get(&imageStore_01f00D30E), + Rule::Get( + &imageStoreExt_01f00D30E), + Rule::Get( + &imageStoreExt_01f00D30E), + Rule::Get(&imageLoad_00z10D), + Rule::Get(&imageLoad_01K10D), + Rule::Get(&imageLoad_01V10D), + Rule::Get(&imageLoad_01A20D), + Rule::Get(&imageLoad_01L20D), + Rule::Get(&imageLoad_01W20D), + Rule::Get(&imageLoad_01B20D), + Rule::Get(&imageLoad_01M20D), + Rule::Get(&imageLoad_01X20D), + Rule::Get(&imageLoad_01C20D), + Rule::Get(&imageLoad_01N20D), + Rule::Get(&imageLoad_01Y20D), + Rule::Get(&imageLoad_01H20D), + Rule::Get( + &imageLoadExt_01H20D), + Rule::Get( + &imageLoadExt_01H20D), + Rule::Get(&imageLoad_01S20D), + Rule::Get( + &imageLoadExt_01S20D), + Rule::Get( + &imageLoadExt_01S20D), + Rule::Get(&imageLoad_01d20D), + Rule::Get( + &imageLoadExt_01d20D), + Rule::Get( + &imageLoadExt_01d20D), + Rule::Get(&imageLoad_01J00D), + Rule::Get(&imageLoadExt_01J00D), + Rule::Get(&imageLoadExt_01J00D), + Rule::Get(&imageLoad_01U00D), + Rule::Get(&imageLoadExt_01U00D), + Rule::Get(&imageLoadExt_01U00D), + Rule::Get(&imageLoad_01f00D), + Rule::Get(&imageLoadExt_01f00D), + Rule::Get(&imageLoadExt_01f00D), + Rule::Get(&imageAtomicAdd_00z10D00E), + Rule::Get( + &imageAtomicAddExt_00z10D00E), + Rule::Get(&imageAtomicAdd_01K10D00E), + Rule::Get( + &imageAtomicAddExt_01K10D00E), + Rule::Get(&imageAtomicAdd_01V10D00E), + Rule::Get( + &imageAtomicAddExt_01V10D00E), + Rule::Get(&imageAtomicAdd_01A20D00E), + Rule::Get( + &imageAtomicAddExt_01A20D00E), + Rule::Get(&imageAtomicAdd_01L20D00E), + Rule::Get( + &imageAtomicAddExt_01L20D00E), + Rule::Get(&imageAtomicAdd_01W20D00E), + Rule::Get( + &imageAtomicAddExt_01W20D00E), + Rule::Get(&imageAtomicAdd_01C20D00E), + Rule::Get( + &imageAtomicAddExt_01C20D00E), + Rule::Get(&imageAtomicAdd_01N20D00E), + Rule::Get( + &imageAtomicAddExt_01N20D00E), + Rule::Get(&imageAtomicAdd_01Y20D00E), + Rule::Get( + &imageAtomicAddExt_01Y20D00E), + Rule::Get(&imageAtomicAdd_01J00D00E), + Rule::Get( + &imageAtomicAddExt_01J00D00E), + Rule::Get(&imageAtomicAdd_01U00D00E), + Rule::Get( + &imageAtomicAddExt_01U00D00E), + Rule::Get(&imageAtomicAdd_01f00D00E), + Rule::Get( + &imageAtomicAddExt_01f00D00E), + Rule::Get(&imageAtomicAdd_01B20D00E), + Rule::Get( + &imageAtomicAddExt_01B20D00E), + Rule::Get(&imageAtomicAdd_01M20D00E), + Rule::Get( + &imageAtomicAddExt_01M20D00E), + Rule::Get(&imageAtomicAdd_01X20D00E), + Rule::Get( + &imageAtomicAddExt_01X20D00E), + Rule::Get(&imageAtomicAdd_01H20D00E), + Rule::Get( + &imageAtomicAddExt_01H20D00E), + Rule::Get(&imageAtomicAdd_01S20D00E), + Rule::Get( + &imageAtomicAddExt_01S20D00E), + Rule::Get(&imageAtomicAdd_01d20D00E), + Rule::Get( + &imageAtomicAddExt_01d20D00E), + Rule::Get(&imageAtomicAdd_01D00D00E), + Rule::Get( + &imageAtomicAddExt_01D00D00E), + Rule::Get(&imageAtomicAdd_01O00D00E), + Rule::Get( + &imageAtomicAddExt_01O00D00E), + Rule::Get(&imageAtomicAdd_01Z00D00E), + Rule::Get( + &imageAtomicAddExt_01Z00D00E), + Rule::Get(&imageAtomicAdd_01E10D00E), + Rule::Get( + &imageAtomicAddExt_01E10D00E), + Rule::Get(&imageAtomicAdd_01P10D00E), + Rule::Get( + &imageAtomicAddExt_01P10D00E), + Rule::Get(&imageAtomicAdd_01a10D00E), + Rule::Get( + &imageAtomicAddExt_01a10D00E), + Rule::Get(&imageAtomicAdd_01I10D00E), + Rule::Get( + &imageAtomicAddExt_01I10D00E), + Rule::Get(&imageAtomicAdd_01T10D00E), + Rule::Get( + &imageAtomicAddExt_01T10D00E), + Rule::Get(&imageAtomicAdd_01e10D00E), + Rule::Get( + &imageAtomicAddExt_01e10D00E), + Rule::Get(&imageAtomicAdd_01F10D00D00E), + Rule::Get( + &imageAtomicAddExt_01F10D00D00E), + Rule::Get(&imageAtomicAdd_01Q10D00D00E), + Rule::Get( + &imageAtomicAddExt_01Q10D00D00E), + Rule::Get(&imageAtomicAdd_01b10D00D00E), + Rule::Get( + &imageAtomicAddExt_01b10D00D00E), + Rule::Get(&imageAtomicAdd_01G20D00D00E), + Rule::Get( + &imageAtomicAddExt_01G20D00D00E), + Rule::Get(&imageAtomicAdd_01R20D00D00E), + Rule::Get( + &imageAtomicAddExt_01R20D00D00E), + Rule::Get(&imageAtomicAdd_01c20D00D00E), + Rule::Get( + &imageAtomicAddExt_01c20D00D00E), + Rule::Get(&imageAtomicAdd_00z10D00D), + Rule::Get( + &imageAtomicAddExt_00z10D00D), + Rule::Get(&imageAtomicAdd_01K10D00D), + Rule::Get( + &imageAtomicAddExt_01K10D00D), + Rule::Get(&imageAtomicAdd_01V10D00D), + Rule::Get( + &imageAtomicAddExt_01V10D00D), + Rule::Get(&imageAtomicAdd_01A20D00D), + Rule::Get( + &imageAtomicAddExt_01A20D00D), + Rule::Get(&imageAtomicAdd_01L20D00D), + Rule::Get( + &imageAtomicAddExt_01L20D00D), + Rule::Get(&imageAtomicAdd_01W20D00D), + Rule::Get( + &imageAtomicAddExt_01W20D00D), + Rule::Get(&imageAtomicAdd_01C20D00D), + Rule::Get( + &imageAtomicAddExt_01C20D00D), + Rule::Get(&imageAtomicAdd_01N20D00D), + Rule::Get( + &imageAtomicAddExt_01N20D00D), + Rule::Get(&imageAtomicAdd_01Y20D00D), + Rule::Get( + &imageAtomicAddExt_01Y20D00D), + Rule::Get(&imageAtomicAdd_01J00D00D), + Rule::Get( + &imageAtomicAddExt_01J00D00D), + Rule::Get(&imageAtomicAdd_01U00D00D), + Rule::Get( + &imageAtomicAddExt_01U00D00D), + Rule::Get(&imageAtomicAdd_01f00D00D), + Rule::Get( + &imageAtomicAddExt_01f00D00D), + Rule::Get(&imageAtomicAdd_01B20D00D), + Rule::Get( + &imageAtomicAddExt_01B20D00D), + Rule::Get(&imageAtomicAdd_01M20D00D), + Rule::Get( + &imageAtomicAddExt_01M20D00D), + Rule::Get(&imageAtomicAdd_01X20D00D), + Rule::Get( + &imageAtomicAddExt_01X20D00D), + Rule::Get(&imageAtomicAdd_01H20D00D), + Rule::Get( + &imageAtomicAddExt_01H20D00D), + Rule::Get(&imageAtomicAdd_01S20D00D), + Rule::Get( + &imageAtomicAddExt_01S20D00D), + Rule::Get(&imageAtomicAdd_01d20D00D), + Rule::Get( + &imageAtomicAddExt_01d20D00D), + Rule::Get(&imageAtomicAdd_01D00D00D), + Rule::Get( + &imageAtomicAddExt_01D00D00D), + Rule::Get(&imageAtomicAdd_01O00D00D), + Rule::Get( + &imageAtomicAddExt_01O00D00D), + Rule::Get(&imageAtomicAdd_01Z00D00D), + Rule::Get( + &imageAtomicAddExt_01Z00D00D), + Rule::Get(&imageAtomicAdd_01E10D00D), + Rule::Get( + &imageAtomicAddExt_01E10D00D), + Rule::Get(&imageAtomicAdd_01P10D00D), + Rule::Get( + &imageAtomicAddExt_01P10D00D), + Rule::Get(&imageAtomicAdd_01a10D00D), + Rule::Get( + &imageAtomicAddExt_01a10D00D), + Rule::Get(&imageAtomicAdd_01I10D00D), + Rule::Get( + &imageAtomicAddExt_01I10D00D), + Rule::Get(&imageAtomicAdd_01T10D00D), + Rule::Get( + &imageAtomicAddExt_01T10D00D), + Rule::Get(&imageAtomicAdd_01e10D00D), + Rule::Get( + &imageAtomicAddExt_01e10D00D), + Rule::Get(&imageAtomicAdd_01F10D00D00D), + Rule::Get( + &imageAtomicAddExt_01F10D00D00D), + Rule::Get(&imageAtomicAdd_01Q10D00D00D), + Rule::Get( + &imageAtomicAddExt_01Q10D00D00D), + Rule::Get(&imageAtomicAdd_01b10D00D00D), + Rule::Get( + &imageAtomicAddExt_01b10D00D00D), + Rule::Get(&imageAtomicAdd_01G20D00D00D), + Rule::Get( + &imageAtomicAddExt_01G20D00D00D), + Rule::Get(&imageAtomicAdd_01R20D00D00D), + Rule::Get( + &imageAtomicAddExt_01R20D00D00D), + Rule::Get(&imageAtomicAdd_01c20D00D00D), + Rule::Get( + &imageAtomicAddExt_01c20D00D00D), + Rule::Get(&imageAtomicMin_00z10D00E), + Rule::Get( + &imageAtomicMinExt_00z10D00E), + Rule::Get(&imageAtomicMin_01K10D00E), + Rule::Get( + &imageAtomicMinExt_01K10D00E), + Rule::Get(&imageAtomicMin_01V10D00E), + Rule::Get( + &imageAtomicMinExt_01V10D00E), + Rule::Get(&imageAtomicMin_01A20D00E), + Rule::Get( + &imageAtomicMinExt_01A20D00E), + Rule::Get(&imageAtomicMin_01L20D00E), + Rule::Get( + &imageAtomicMinExt_01L20D00E), + Rule::Get(&imageAtomicMin_01W20D00E), + Rule::Get( + &imageAtomicMinExt_01W20D00E), + Rule::Get(&imageAtomicMin_01C20D00E), + Rule::Get( + &imageAtomicMinExt_01C20D00E), + Rule::Get(&imageAtomicMin_01N20D00E), + Rule::Get( + &imageAtomicMinExt_01N20D00E), + Rule::Get(&imageAtomicMin_01Y20D00E), + Rule::Get( + &imageAtomicMinExt_01Y20D00E), + Rule::Get(&imageAtomicMin_01J00D00E), + Rule::Get( + &imageAtomicMinExt_01J00D00E), + Rule::Get(&imageAtomicMin_01U00D00E), + Rule::Get( + &imageAtomicMinExt_01U00D00E), + Rule::Get(&imageAtomicMin_01f00D00E), + Rule::Get( + &imageAtomicMinExt_01f00D00E), + Rule::Get(&imageAtomicMin_01B20D00E), + Rule::Get( + &imageAtomicMinExt_01B20D00E), + Rule::Get(&imageAtomicMin_01M20D00E), + Rule::Get( + &imageAtomicMinExt_01M20D00E), + Rule::Get(&imageAtomicMin_01X20D00E), + Rule::Get( + &imageAtomicMinExt_01X20D00E), + Rule::Get(&imageAtomicMin_01H20D00E), + Rule::Get( + &imageAtomicMinExt_01H20D00E), + Rule::Get(&imageAtomicMin_01S20D00E), + Rule::Get( + &imageAtomicMinExt_01S20D00E), + Rule::Get(&imageAtomicMin_01d20D00E), + Rule::Get( + &imageAtomicMinExt_01d20D00E), + Rule::Get(&imageAtomicMin_01D00D00E), + Rule::Get( + &imageAtomicMinExt_01D00D00E), + Rule::Get(&imageAtomicMin_01O00D00E), + Rule::Get( + &imageAtomicMinExt_01O00D00E), + Rule::Get(&imageAtomicMin_01Z00D00E), + Rule::Get( + &imageAtomicMinExt_01Z00D00E), + Rule::Get(&imageAtomicMin_01E10D00E), + Rule::Get( + &imageAtomicMinExt_01E10D00E), + Rule::Get(&imageAtomicMin_01P10D00E), + Rule::Get( + &imageAtomicMinExt_01P10D00E), + Rule::Get(&imageAtomicMin_01a10D00E), + Rule::Get( + &imageAtomicMinExt_01a10D00E), + Rule::Get(&imageAtomicMin_01I10D00E), + Rule::Get( + &imageAtomicMinExt_01I10D00E), + Rule::Get(&imageAtomicMin_01T10D00E), + Rule::Get( + &imageAtomicMinExt_01T10D00E), + Rule::Get(&imageAtomicMin_01e10D00E), + Rule::Get( + &imageAtomicMinExt_01e10D00E), + Rule::Get(&imageAtomicMin_01F10D00D00E), + Rule::Get( + &imageAtomicMinExt_01F10D00D00E), + Rule::Get(&imageAtomicMin_01Q10D00D00E), + Rule::Get( + &imageAtomicMinExt_01Q10D00D00E), + Rule::Get(&imageAtomicMin_01b10D00D00E), + Rule::Get( + &imageAtomicMinExt_01b10D00D00E), + Rule::Get(&imageAtomicMin_01G20D00D00E), + Rule::Get( + &imageAtomicMinExt_01G20D00D00E), + Rule::Get(&imageAtomicMin_01R20D00D00E), + Rule::Get( + &imageAtomicMinExt_01R20D00D00E), + Rule::Get(&imageAtomicMin_01c20D00D00E), + Rule::Get( + &imageAtomicMinExt_01c20D00D00E), + Rule::Get(&imageAtomicMin_00z10D00D), + Rule::Get( + &imageAtomicMinExt_00z10D00D), + Rule::Get(&imageAtomicMin_01K10D00D), + Rule::Get( + &imageAtomicMinExt_01K10D00D), + Rule::Get(&imageAtomicMin_01V10D00D), + Rule::Get( + &imageAtomicMinExt_01V10D00D), + Rule::Get(&imageAtomicMin_01A20D00D), + Rule::Get( + &imageAtomicMinExt_01A20D00D), + Rule::Get(&imageAtomicMin_01L20D00D), + Rule::Get( + &imageAtomicMinExt_01L20D00D), + Rule::Get(&imageAtomicMin_01W20D00D), + Rule::Get( + &imageAtomicMinExt_01W20D00D), + Rule::Get(&imageAtomicMin_01C20D00D), + Rule::Get( + &imageAtomicMinExt_01C20D00D), + Rule::Get(&imageAtomicMin_01N20D00D), + Rule::Get( + &imageAtomicMinExt_01N20D00D), + Rule::Get(&imageAtomicMin_01Y20D00D), + Rule::Get( + &imageAtomicMinExt_01Y20D00D), + Rule::Get(&imageAtomicMin_01J00D00D), + Rule::Get( + &imageAtomicMinExt_01J00D00D), + Rule::Get(&imageAtomicMin_01U00D00D), + Rule::Get( + &imageAtomicMinExt_01U00D00D), + Rule::Get(&imageAtomicMin_01f00D00D), + Rule::Get( + &imageAtomicMinExt_01f00D00D), + Rule::Get(&imageAtomicMin_01B20D00D), + Rule::Get( + &imageAtomicMinExt_01B20D00D), + Rule::Get(&imageAtomicMin_01M20D00D), + Rule::Get( + &imageAtomicMinExt_01M20D00D), + Rule::Get(&imageAtomicMin_01X20D00D), + Rule::Get( + &imageAtomicMinExt_01X20D00D), + Rule::Get(&imageAtomicMin_01H20D00D), + Rule::Get( + &imageAtomicMinExt_01H20D00D), + Rule::Get(&imageAtomicMin_01S20D00D), + Rule::Get( + &imageAtomicMinExt_01S20D00D), + Rule::Get(&imageAtomicMin_01d20D00D), + Rule::Get( + &imageAtomicMinExt_01d20D00D), + Rule::Get(&imageAtomicMin_01D00D00D), + Rule::Get( + &imageAtomicMinExt_01D00D00D), + Rule::Get(&imageAtomicMin_01O00D00D), + Rule::Get( + &imageAtomicMinExt_01O00D00D), + Rule::Get(&imageAtomicMin_01Z00D00D), + Rule::Get( + &imageAtomicMinExt_01Z00D00D), + Rule::Get(&imageAtomicMin_01E10D00D), + Rule::Get( + &imageAtomicMinExt_01E10D00D), + Rule::Get(&imageAtomicMin_01P10D00D), + Rule::Get( + &imageAtomicMinExt_01P10D00D), + Rule::Get(&imageAtomicMin_01a10D00D), + Rule::Get( + &imageAtomicMinExt_01a10D00D), + Rule::Get(&imageAtomicMin_01I10D00D), + Rule::Get( + &imageAtomicMinExt_01I10D00D), + Rule::Get(&imageAtomicMin_01T10D00D), + Rule::Get( + &imageAtomicMinExt_01T10D00D), + Rule::Get(&imageAtomicMin_01e10D00D), + Rule::Get( + &imageAtomicMinExt_01e10D00D), + Rule::Get(&imageAtomicMin_01F10D00D00D), + Rule::Get( + &imageAtomicMinExt_01F10D00D00D), + Rule::Get(&imageAtomicMin_01Q10D00D00D), + Rule::Get( + &imageAtomicMinExt_01Q10D00D00D), + Rule::Get(&imageAtomicMin_01b10D00D00D), + Rule::Get( + &imageAtomicMinExt_01b10D00D00D), + Rule::Get(&imageAtomicMin_01G20D00D00D), + Rule::Get( + &imageAtomicMinExt_01G20D00D00D), + Rule::Get(&imageAtomicMin_01R20D00D00D), + Rule::Get( + &imageAtomicMinExt_01R20D00D00D), + Rule::Get(&imageAtomicMin_01c20D00D00D), + Rule::Get( + &imageAtomicMinExt_01c20D00D00D), + Rule::Get(&imageAtomicMax_00z10D00E), + Rule::Get( + &imageAtomicMaxExt_00z10D00E), + Rule::Get(&imageAtomicMax_01K10D00E), + Rule::Get( + &imageAtomicMaxExt_01K10D00E), + Rule::Get(&imageAtomicMax_01V10D00E), + Rule::Get( + &imageAtomicMaxExt_01V10D00E), + Rule::Get(&imageAtomicMax_01A20D00E), + Rule::Get( + &imageAtomicMaxExt_01A20D00E), + Rule::Get(&imageAtomicMax_01L20D00E), + Rule::Get( + &imageAtomicMaxExt_01L20D00E), + Rule::Get(&imageAtomicMax_01W20D00E), + Rule::Get( + &imageAtomicMaxExt_01W20D00E), + Rule::Get(&imageAtomicMax_01C20D00E), + Rule::Get( + &imageAtomicMaxExt_01C20D00E), + Rule::Get(&imageAtomicMax_01N20D00E), + Rule::Get( + &imageAtomicMaxExt_01N20D00E), + Rule::Get(&imageAtomicMax_01Y20D00E), + Rule::Get( + &imageAtomicMaxExt_01Y20D00E), + Rule::Get(&imageAtomicMax_01J00D00E), + Rule::Get( + &imageAtomicMaxExt_01J00D00E), + Rule::Get(&imageAtomicMax_01U00D00E), + Rule::Get( + &imageAtomicMaxExt_01U00D00E), + Rule::Get(&imageAtomicMax_01f00D00E), + Rule::Get( + &imageAtomicMaxExt_01f00D00E), + Rule::Get(&imageAtomicMax_01B20D00E), + Rule::Get( + &imageAtomicMaxExt_01B20D00E), + Rule::Get(&imageAtomicMax_01M20D00E), + Rule::Get( + &imageAtomicMaxExt_01M20D00E), + Rule::Get(&imageAtomicMax_01X20D00E), + Rule::Get( + &imageAtomicMaxExt_01X20D00E), + Rule::Get(&imageAtomicMax_01H20D00E), + Rule::Get( + &imageAtomicMaxExt_01H20D00E), + Rule::Get(&imageAtomicMax_01S20D00E), + Rule::Get( + &imageAtomicMaxExt_01S20D00E), + Rule::Get(&imageAtomicMax_01d20D00E), + Rule::Get( + &imageAtomicMaxExt_01d20D00E), + Rule::Get(&imageAtomicMax_01D00D00E), + Rule::Get( + &imageAtomicMaxExt_01D00D00E), + Rule::Get(&imageAtomicMax_01O00D00E), + Rule::Get( + &imageAtomicMaxExt_01O00D00E), + Rule::Get(&imageAtomicMax_01Z00D00E), + Rule::Get( + &imageAtomicMaxExt_01Z00D00E), + Rule::Get(&imageAtomicMax_01E10D00E), + Rule::Get( + &imageAtomicMaxExt_01E10D00E), + Rule::Get(&imageAtomicMax_01P10D00E), + Rule::Get( + &imageAtomicMaxExt_01P10D00E), + Rule::Get(&imageAtomicMax_01a10D00E), + Rule::Get( + &imageAtomicMaxExt_01a10D00E), + Rule::Get(&imageAtomicMax_01I10D00E), + Rule::Get( + &imageAtomicMaxExt_01I10D00E), + Rule::Get(&imageAtomicMax_01T10D00E), + Rule::Get( + &imageAtomicMaxExt_01T10D00E), + Rule::Get(&imageAtomicMax_01e10D00E), + Rule::Get( + &imageAtomicMaxExt_01e10D00E), + Rule::Get(&imageAtomicMax_01F10D00D00E), + Rule::Get( + &imageAtomicMaxExt_01F10D00D00E), + Rule::Get(&imageAtomicMax_01Q10D00D00E), + Rule::Get( + &imageAtomicMaxExt_01Q10D00D00E), + Rule::Get(&imageAtomicMax_01b10D00D00E), + Rule::Get( + &imageAtomicMaxExt_01b10D00D00E), + Rule::Get(&imageAtomicMax_01G20D00D00E), + Rule::Get( + &imageAtomicMaxExt_01G20D00D00E), + Rule::Get(&imageAtomicMax_01R20D00D00E), + Rule::Get( + &imageAtomicMaxExt_01R20D00D00E), + Rule::Get(&imageAtomicMax_01c20D00D00E), + Rule::Get( + &imageAtomicMaxExt_01c20D00D00E), + Rule::Get(&imageAtomicMax_00z10D00D), + Rule::Get( + &imageAtomicMaxExt_00z10D00D), + Rule::Get(&imageAtomicMax_01K10D00D), + Rule::Get( + &imageAtomicMaxExt_01K10D00D), + Rule::Get(&imageAtomicMax_01V10D00D), + Rule::Get( + &imageAtomicMaxExt_01V10D00D), + Rule::Get(&imageAtomicMax_01A20D00D), + Rule::Get( + &imageAtomicMaxExt_01A20D00D), + Rule::Get(&imageAtomicMax_01L20D00D), + Rule::Get( + &imageAtomicMaxExt_01L20D00D), + Rule::Get(&imageAtomicMax_01W20D00D), + Rule::Get( + &imageAtomicMaxExt_01W20D00D), + Rule::Get(&imageAtomicMax_01C20D00D), + Rule::Get( + &imageAtomicMaxExt_01C20D00D), + Rule::Get(&imageAtomicMax_01N20D00D), + Rule::Get( + &imageAtomicMaxExt_01N20D00D), + Rule::Get(&imageAtomicMax_01Y20D00D), + Rule::Get( + &imageAtomicMaxExt_01Y20D00D), + Rule::Get(&imageAtomicMax_01J00D00D), + Rule::Get( + &imageAtomicMaxExt_01J00D00D), + Rule::Get(&imageAtomicMax_01U00D00D), + Rule::Get( + &imageAtomicMaxExt_01U00D00D), + Rule::Get(&imageAtomicMax_01f00D00D), + Rule::Get( + &imageAtomicMaxExt_01f00D00D), + Rule::Get(&imageAtomicMax_01B20D00D), + Rule::Get( + &imageAtomicMaxExt_01B20D00D), + Rule::Get(&imageAtomicMax_01M20D00D), + Rule::Get( + &imageAtomicMaxExt_01M20D00D), + Rule::Get(&imageAtomicMax_01X20D00D), + Rule::Get( + &imageAtomicMaxExt_01X20D00D), + Rule::Get(&imageAtomicMax_01H20D00D), + Rule::Get( + &imageAtomicMaxExt_01H20D00D), + Rule::Get(&imageAtomicMax_01S20D00D), + Rule::Get( + &imageAtomicMaxExt_01S20D00D), + Rule::Get(&imageAtomicMax_01d20D00D), + Rule::Get( + &imageAtomicMaxExt_01d20D00D), + Rule::Get(&imageAtomicMax_01D00D00D), + Rule::Get( + &imageAtomicMaxExt_01D00D00D), + Rule::Get(&imageAtomicMax_01O00D00D), + Rule::Get( + &imageAtomicMaxExt_01O00D00D), + Rule::Get(&imageAtomicMax_01Z00D00D), + Rule::Get( + &imageAtomicMaxExt_01Z00D00D), + Rule::Get(&imageAtomicMax_01E10D00D), + Rule::Get( + &imageAtomicMaxExt_01E10D00D), + Rule::Get(&imageAtomicMax_01P10D00D), + Rule::Get( + &imageAtomicMaxExt_01P10D00D), + Rule::Get(&imageAtomicMax_01a10D00D), + Rule::Get( + &imageAtomicMaxExt_01a10D00D), + Rule::Get(&imageAtomicMax_01I10D00D), + Rule::Get( + &imageAtomicMaxExt_01I10D00D), + Rule::Get(&imageAtomicMax_01T10D00D), + Rule::Get( + &imageAtomicMaxExt_01T10D00D), + Rule::Get(&imageAtomicMax_01e10D00D), + Rule::Get( + &imageAtomicMaxExt_01e10D00D), + Rule::Get(&imageAtomicMax_01F10D00D00D), + Rule::Get( + &imageAtomicMaxExt_01F10D00D00D), + Rule::Get(&imageAtomicMax_01Q10D00D00D), + Rule::Get( + &imageAtomicMaxExt_01Q10D00D00D), + Rule::Get(&imageAtomicMax_01b10D00D00D), + Rule::Get( + &imageAtomicMaxExt_01b10D00D00D), + Rule::Get(&imageAtomicMax_01G20D00D00D), + Rule::Get( + &imageAtomicMaxExt_01G20D00D00D), + Rule::Get(&imageAtomicMax_01R20D00D00D), + Rule::Get( + &imageAtomicMaxExt_01R20D00D00D), + Rule::Get(&imageAtomicMax_01c20D00D00D), + Rule::Get( + &imageAtomicMaxExt_01c20D00D00D), + Rule::Get(&imageAtomicAnd_00z10D00E), + Rule::Get( + &imageAtomicAndExt_00z10D00E), + Rule::Get(&imageAtomicAnd_01K10D00E), + Rule::Get( + &imageAtomicAndExt_01K10D00E), + Rule::Get(&imageAtomicAnd_01V10D00E), + Rule::Get( + &imageAtomicAndExt_01V10D00E), + Rule::Get(&imageAtomicAnd_01A20D00E), + Rule::Get( + &imageAtomicAndExt_01A20D00E), + Rule::Get(&imageAtomicAnd_01L20D00E), + Rule::Get( + &imageAtomicAndExt_01L20D00E), + Rule::Get(&imageAtomicAnd_01W20D00E), + Rule::Get( + &imageAtomicAndExt_01W20D00E), + Rule::Get(&imageAtomicAnd_01C20D00E), + Rule::Get( + &imageAtomicAndExt_01C20D00E), + Rule::Get(&imageAtomicAnd_01N20D00E), + Rule::Get( + &imageAtomicAndExt_01N20D00E), + Rule::Get(&imageAtomicAnd_01Y20D00E), + Rule::Get( + &imageAtomicAndExt_01Y20D00E), + Rule::Get(&imageAtomicAnd_01J00D00E), + Rule::Get( + &imageAtomicAndExt_01J00D00E), + Rule::Get(&imageAtomicAnd_01U00D00E), + Rule::Get( + &imageAtomicAndExt_01U00D00E), + Rule::Get(&imageAtomicAnd_01f00D00E), + Rule::Get( + &imageAtomicAndExt_01f00D00E), + Rule::Get(&imageAtomicAnd_01B20D00E), + Rule::Get( + &imageAtomicAndExt_01B20D00E), + Rule::Get(&imageAtomicAnd_01M20D00E), + Rule::Get( + &imageAtomicAndExt_01M20D00E), + Rule::Get(&imageAtomicAnd_01X20D00E), + Rule::Get( + &imageAtomicAndExt_01X20D00E), + Rule::Get(&imageAtomicAnd_01H20D00E), + Rule::Get( + &imageAtomicAndExt_01H20D00E), + Rule::Get(&imageAtomicAnd_01S20D00E), + Rule::Get( + &imageAtomicAndExt_01S20D00E), + Rule::Get(&imageAtomicAnd_01d20D00E), + Rule::Get( + &imageAtomicAndExt_01d20D00E), + Rule::Get(&imageAtomicAnd_01D00D00E), + Rule::Get( + &imageAtomicAndExt_01D00D00E), + Rule::Get(&imageAtomicAnd_01O00D00E), + Rule::Get( + &imageAtomicAndExt_01O00D00E), + Rule::Get(&imageAtomicAnd_01Z00D00E), + Rule::Get( + &imageAtomicAndExt_01Z00D00E), + Rule::Get(&imageAtomicAnd_01E10D00E), + Rule::Get( + &imageAtomicAndExt_01E10D00E), + Rule::Get(&imageAtomicAnd_01P10D00E), + Rule::Get( + &imageAtomicAndExt_01P10D00E), + Rule::Get(&imageAtomicAnd_01a10D00E), + Rule::Get( + &imageAtomicAndExt_01a10D00E), + Rule::Get(&imageAtomicAnd_01I10D00E), + Rule::Get( + &imageAtomicAndExt_01I10D00E), + Rule::Get(&imageAtomicAnd_01T10D00E), + Rule::Get( + &imageAtomicAndExt_01T10D00E), + Rule::Get(&imageAtomicAnd_01e10D00E), + Rule::Get( + &imageAtomicAndExt_01e10D00E), + Rule::Get(&imageAtomicAnd_01F10D00D00E), + Rule::Get( + &imageAtomicAndExt_01F10D00D00E), + Rule::Get(&imageAtomicAnd_01Q10D00D00E), + Rule::Get( + &imageAtomicAndExt_01Q10D00D00E), + Rule::Get(&imageAtomicAnd_01b10D00D00E), + Rule::Get( + &imageAtomicAndExt_01b10D00D00E), + Rule::Get(&imageAtomicAnd_01G20D00D00E), + Rule::Get( + &imageAtomicAndExt_01G20D00D00E), + Rule::Get(&imageAtomicAnd_01R20D00D00E), + Rule::Get( + &imageAtomicAndExt_01R20D00D00E), + Rule::Get(&imageAtomicAnd_01c20D00D00E), + Rule::Get( + &imageAtomicAndExt_01c20D00D00E), + Rule::Get(&imageAtomicAnd_00z10D00D), + Rule::Get( + &imageAtomicAndExt_00z10D00D), + Rule::Get(&imageAtomicAnd_01K10D00D), + Rule::Get( + &imageAtomicAndExt_01K10D00D), + Rule::Get(&imageAtomicAnd_01V10D00D), + Rule::Get( + &imageAtomicAndExt_01V10D00D), + Rule::Get(&imageAtomicAnd_01A20D00D), + Rule::Get( + &imageAtomicAndExt_01A20D00D), + Rule::Get(&imageAtomicAnd_01L20D00D), + Rule::Get( + &imageAtomicAndExt_01L20D00D), + Rule::Get(&imageAtomicAnd_01W20D00D), + Rule::Get( + &imageAtomicAndExt_01W20D00D), + Rule::Get(&imageAtomicAnd_01C20D00D), + Rule::Get( + &imageAtomicAndExt_01C20D00D), + Rule::Get(&imageAtomicAnd_01N20D00D), + Rule::Get( + &imageAtomicAndExt_01N20D00D), + Rule::Get(&imageAtomicAnd_01Y20D00D), + Rule::Get( + &imageAtomicAndExt_01Y20D00D), + Rule::Get(&imageAtomicAnd_01J00D00D), + Rule::Get( + &imageAtomicAndExt_01J00D00D), + Rule::Get(&imageAtomicAnd_01U00D00D), + Rule::Get( + &imageAtomicAndExt_01U00D00D), + Rule::Get(&imageAtomicAnd_01f00D00D), + Rule::Get( + &imageAtomicAndExt_01f00D00D), + Rule::Get(&imageAtomicAnd_01B20D00D), + Rule::Get( + &imageAtomicAndExt_01B20D00D), + Rule::Get(&imageAtomicAnd_01M20D00D), + Rule::Get( + &imageAtomicAndExt_01M20D00D), + Rule::Get(&imageAtomicAnd_01X20D00D), + Rule::Get( + &imageAtomicAndExt_01X20D00D), + Rule::Get(&imageAtomicAnd_01H20D00D), + Rule::Get( + &imageAtomicAndExt_01H20D00D), + Rule::Get(&imageAtomicAnd_01S20D00D), + Rule::Get( + &imageAtomicAndExt_01S20D00D), + Rule::Get(&imageAtomicAnd_01d20D00D), + Rule::Get( + &imageAtomicAndExt_01d20D00D), + Rule::Get(&imageAtomicAnd_01D00D00D), + Rule::Get( + &imageAtomicAndExt_01D00D00D), + Rule::Get(&imageAtomicAnd_01O00D00D), + Rule::Get( + &imageAtomicAndExt_01O00D00D), + Rule::Get(&imageAtomicAnd_01Z00D00D), + Rule::Get( + &imageAtomicAndExt_01Z00D00D), + Rule::Get(&imageAtomicAnd_01E10D00D), + Rule::Get( + &imageAtomicAndExt_01E10D00D), + Rule::Get(&imageAtomicAnd_01P10D00D), + Rule::Get( + &imageAtomicAndExt_01P10D00D), + Rule::Get(&imageAtomicAnd_01a10D00D), + Rule::Get( + &imageAtomicAndExt_01a10D00D), + Rule::Get(&imageAtomicAnd_01I10D00D), + Rule::Get( + &imageAtomicAndExt_01I10D00D), + Rule::Get(&imageAtomicAnd_01T10D00D), + Rule::Get( + &imageAtomicAndExt_01T10D00D), + Rule::Get(&imageAtomicAnd_01e10D00D), + Rule::Get( + &imageAtomicAndExt_01e10D00D), + Rule::Get(&imageAtomicAnd_01F10D00D00D), + Rule::Get( + &imageAtomicAndExt_01F10D00D00D), + Rule::Get(&imageAtomicAnd_01Q10D00D00D), + Rule::Get( + &imageAtomicAndExt_01Q10D00D00D), + Rule::Get(&imageAtomicAnd_01b10D00D00D), + Rule::Get( + &imageAtomicAndExt_01b10D00D00D), + Rule::Get(&imageAtomicAnd_01G20D00D00D), + Rule::Get( + &imageAtomicAndExt_01G20D00D00D), + Rule::Get(&imageAtomicAnd_01R20D00D00D), + Rule::Get( + &imageAtomicAndExt_01R20D00D00D), + Rule::Get(&imageAtomicAnd_01c20D00D00D), + Rule::Get( + &imageAtomicAndExt_01c20D00D00D), + Rule::Get(&imageAtomicOr_00z10D00E), + Rule::Get( + &imageAtomicOrExt_00z10D00E), + Rule::Get(&imageAtomicOr_01K10D00E), + Rule::Get( + &imageAtomicOrExt_01K10D00E), + Rule::Get(&imageAtomicOr_01V10D00E), + Rule::Get( + &imageAtomicOrExt_01V10D00E), + Rule::Get(&imageAtomicOr_01A20D00E), + Rule::Get( + &imageAtomicOrExt_01A20D00E), + Rule::Get(&imageAtomicOr_01L20D00E), + Rule::Get( + &imageAtomicOrExt_01L20D00E), + Rule::Get(&imageAtomicOr_01W20D00E), + Rule::Get( + &imageAtomicOrExt_01W20D00E), + Rule::Get(&imageAtomicOr_01C20D00E), + Rule::Get( + &imageAtomicOrExt_01C20D00E), + Rule::Get(&imageAtomicOr_01N20D00E), + Rule::Get( + &imageAtomicOrExt_01N20D00E), + Rule::Get(&imageAtomicOr_01Y20D00E), + Rule::Get( + &imageAtomicOrExt_01Y20D00E), + Rule::Get(&imageAtomicOr_01J00D00E), + Rule::Get( + &imageAtomicOrExt_01J00D00E), + Rule::Get(&imageAtomicOr_01U00D00E), + Rule::Get( + &imageAtomicOrExt_01U00D00E), + Rule::Get(&imageAtomicOr_01f00D00E), + Rule::Get( + &imageAtomicOrExt_01f00D00E), + Rule::Get(&imageAtomicOr_01B20D00E), + Rule::Get( + &imageAtomicOrExt_01B20D00E), + Rule::Get(&imageAtomicOr_01M20D00E), + Rule::Get( + &imageAtomicOrExt_01M20D00E), + Rule::Get(&imageAtomicOr_01X20D00E), + Rule::Get( + &imageAtomicOrExt_01X20D00E), + Rule::Get(&imageAtomicOr_01H20D00E), + Rule::Get( + &imageAtomicOrExt_01H20D00E), + Rule::Get(&imageAtomicOr_01S20D00E), + Rule::Get( + &imageAtomicOrExt_01S20D00E), + Rule::Get(&imageAtomicOr_01d20D00E), + Rule::Get( + &imageAtomicOrExt_01d20D00E), + Rule::Get(&imageAtomicOr_01D00D00E), + Rule::Get( + &imageAtomicOrExt_01D00D00E), + Rule::Get(&imageAtomicOr_01O00D00E), + Rule::Get( + &imageAtomicOrExt_01O00D00E), + Rule::Get(&imageAtomicOr_01Z00D00E), + Rule::Get( + &imageAtomicOrExt_01Z00D00E), + Rule::Get(&imageAtomicOr_01E10D00E), + Rule::Get( + &imageAtomicOrExt_01E10D00E), + Rule::Get(&imageAtomicOr_01P10D00E), + Rule::Get( + &imageAtomicOrExt_01P10D00E), + Rule::Get(&imageAtomicOr_01a10D00E), + Rule::Get( + &imageAtomicOrExt_01a10D00E), + Rule::Get(&imageAtomicOr_01I10D00E), + Rule::Get( + &imageAtomicOrExt_01I10D00E), + Rule::Get(&imageAtomicOr_01T10D00E), + Rule::Get( + &imageAtomicOrExt_01T10D00E), + Rule::Get(&imageAtomicOr_01e10D00E), + Rule::Get( + &imageAtomicOrExt_01e10D00E), + Rule::Get(&imageAtomicOr_01F10D00D00E), + Rule::Get( + &imageAtomicOrExt_01F10D00D00E), + Rule::Get(&imageAtomicOr_01Q10D00D00E), + Rule::Get( + &imageAtomicOrExt_01Q10D00D00E), + Rule::Get(&imageAtomicOr_01b10D00D00E), + Rule::Get( + &imageAtomicOrExt_01b10D00D00E), + Rule::Get(&imageAtomicOr_01G20D00D00E), + Rule::Get( + &imageAtomicOrExt_01G20D00D00E), + Rule::Get(&imageAtomicOr_01R20D00D00E), + Rule::Get( + &imageAtomicOrExt_01R20D00D00E), + Rule::Get(&imageAtomicOr_01c20D00D00E), + Rule::Get( + &imageAtomicOrExt_01c20D00D00E), + Rule::Get(&imageAtomicOr_00z10D00D), + Rule::Get( + &imageAtomicOrExt_00z10D00D), + Rule::Get(&imageAtomicOr_01K10D00D), + Rule::Get( + &imageAtomicOrExt_01K10D00D), + Rule::Get(&imageAtomicOr_01V10D00D), + Rule::Get( + &imageAtomicOrExt_01V10D00D), + Rule::Get(&imageAtomicOr_01A20D00D), + Rule::Get( + &imageAtomicOrExt_01A20D00D), + Rule::Get(&imageAtomicOr_01L20D00D), + Rule::Get( + &imageAtomicOrExt_01L20D00D), + Rule::Get(&imageAtomicOr_01W20D00D), + Rule::Get( + &imageAtomicOrExt_01W20D00D), + Rule::Get(&imageAtomicOr_01C20D00D), + Rule::Get( + &imageAtomicOrExt_01C20D00D), + Rule::Get(&imageAtomicOr_01N20D00D), + Rule::Get( + &imageAtomicOrExt_01N20D00D), + Rule::Get(&imageAtomicOr_01Y20D00D), + Rule::Get( + &imageAtomicOrExt_01Y20D00D), + Rule::Get(&imageAtomicOr_01J00D00D), + Rule::Get( + &imageAtomicOrExt_01J00D00D), + Rule::Get(&imageAtomicOr_01U00D00D), + Rule::Get( + &imageAtomicOrExt_01U00D00D), + Rule::Get(&imageAtomicOr_01f00D00D), + Rule::Get( + &imageAtomicOrExt_01f00D00D), + Rule::Get(&imageAtomicOr_01B20D00D), + Rule::Get( + &imageAtomicOrExt_01B20D00D), + Rule::Get(&imageAtomicOr_01M20D00D), + Rule::Get( + &imageAtomicOrExt_01M20D00D), + Rule::Get(&imageAtomicOr_01X20D00D), + Rule::Get( + &imageAtomicOrExt_01X20D00D), + Rule::Get(&imageAtomicOr_01H20D00D), + Rule::Get( + &imageAtomicOrExt_01H20D00D), + Rule::Get(&imageAtomicOr_01S20D00D), + Rule::Get( + &imageAtomicOrExt_01S20D00D), + Rule::Get(&imageAtomicOr_01d20D00D), + Rule::Get( + &imageAtomicOrExt_01d20D00D), + Rule::Get(&imageAtomicOr_01D00D00D), + Rule::Get( + &imageAtomicOrExt_01D00D00D), + Rule::Get(&imageAtomicOr_01O00D00D), + Rule::Get( + &imageAtomicOrExt_01O00D00D), + Rule::Get(&imageAtomicOr_01Z00D00D), + Rule::Get( + &imageAtomicOrExt_01Z00D00D), + Rule::Get(&imageAtomicOr_01E10D00D), + Rule::Get( + &imageAtomicOrExt_01E10D00D), + Rule::Get(&imageAtomicOr_01P10D00D), + Rule::Get( + &imageAtomicOrExt_01P10D00D), + Rule::Get(&imageAtomicOr_01a10D00D), + Rule::Get( + &imageAtomicOrExt_01a10D00D), + Rule::Get(&imageAtomicOr_01I10D00D), + Rule::Get( + &imageAtomicOrExt_01I10D00D), + Rule::Get(&imageAtomicOr_01T10D00D), + Rule::Get( + &imageAtomicOrExt_01T10D00D), + Rule::Get(&imageAtomicOr_01e10D00D), + Rule::Get( + &imageAtomicOrExt_01e10D00D), + Rule::Get(&imageAtomicOr_01F10D00D00D), + Rule::Get( + &imageAtomicOrExt_01F10D00D00D), + Rule::Get(&imageAtomicOr_01Q10D00D00D), + Rule::Get( + &imageAtomicOrExt_01Q10D00D00D), + Rule::Get(&imageAtomicOr_01b10D00D00D), + Rule::Get( + &imageAtomicOrExt_01b10D00D00D), + Rule::Get(&imageAtomicOr_01G20D00D00D), + Rule::Get( + &imageAtomicOrExt_01G20D00D00D), + Rule::Get(&imageAtomicOr_01R20D00D00D), + Rule::Get( + &imageAtomicOrExt_01R20D00D00D), + Rule::Get(&imageAtomicOr_01c20D00D00D), + Rule::Get( + &imageAtomicOrExt_01c20D00D00D), + Rule::Get(&imageAtomicXor_00z10D00E), + Rule::Get( + &imageAtomicXorExt_00z10D00E), + Rule::Get(&imageAtomicXor_01K10D00E), + Rule::Get( + &imageAtomicXorExt_01K10D00E), + Rule::Get(&imageAtomicXor_01V10D00E), + Rule::Get( + &imageAtomicXorExt_01V10D00E), + Rule::Get(&imageAtomicXor_01A20D00E), + Rule::Get( + &imageAtomicXorExt_01A20D00E), + Rule::Get(&imageAtomicXor_01L20D00E), + Rule::Get( + &imageAtomicXorExt_01L20D00E), + Rule::Get(&imageAtomicXor_01W20D00E), + Rule::Get( + &imageAtomicXorExt_01W20D00E), + Rule::Get(&imageAtomicXor_01C20D00E), + Rule::Get( + &imageAtomicXorExt_01C20D00E), + Rule::Get(&imageAtomicXor_01N20D00E), + Rule::Get( + &imageAtomicXorExt_01N20D00E), + Rule::Get(&imageAtomicXor_01Y20D00E), + Rule::Get( + &imageAtomicXorExt_01Y20D00E), + Rule::Get(&imageAtomicXor_01J00D00E), + Rule::Get( + &imageAtomicXorExt_01J00D00E), + Rule::Get(&imageAtomicXor_01U00D00E), + Rule::Get( + &imageAtomicXorExt_01U00D00E), + Rule::Get(&imageAtomicXor_01f00D00E), + Rule::Get( + &imageAtomicXorExt_01f00D00E), + Rule::Get(&imageAtomicXor_01B20D00E), + Rule::Get( + &imageAtomicXorExt_01B20D00E), + Rule::Get(&imageAtomicXor_01M20D00E), + Rule::Get( + &imageAtomicXorExt_01M20D00E), + Rule::Get(&imageAtomicXor_01X20D00E), + Rule::Get( + &imageAtomicXorExt_01X20D00E), + Rule::Get(&imageAtomicXor_01H20D00E), + Rule::Get( + &imageAtomicXorExt_01H20D00E), + Rule::Get(&imageAtomicXor_01S20D00E), + Rule::Get( + &imageAtomicXorExt_01S20D00E), + Rule::Get(&imageAtomicXor_01d20D00E), + Rule::Get( + &imageAtomicXorExt_01d20D00E), + Rule::Get(&imageAtomicXor_01D00D00E), + Rule::Get( + &imageAtomicXorExt_01D00D00E), + Rule::Get(&imageAtomicXor_01O00D00E), + Rule::Get( + &imageAtomicXorExt_01O00D00E), + Rule::Get(&imageAtomicXor_01Z00D00E), + Rule::Get( + &imageAtomicXorExt_01Z00D00E), + Rule::Get(&imageAtomicXor_01E10D00E), + Rule::Get( + &imageAtomicXorExt_01E10D00E), + Rule::Get(&imageAtomicXor_01P10D00E), + Rule::Get( + &imageAtomicXorExt_01P10D00E), + Rule::Get(&imageAtomicXor_01a10D00E), + Rule::Get( + &imageAtomicXorExt_01a10D00E), + Rule::Get(&imageAtomicXor_01I10D00E), + Rule::Get( + &imageAtomicXorExt_01I10D00E), + Rule::Get(&imageAtomicXor_01T10D00E), + Rule::Get( + &imageAtomicXorExt_01T10D00E), + Rule::Get(&imageAtomicXor_01e10D00E), + Rule::Get( + &imageAtomicXorExt_01e10D00E), + Rule::Get(&imageAtomicXor_01F10D00D00E), + Rule::Get( + &imageAtomicXorExt_01F10D00D00E), + Rule::Get(&imageAtomicXor_01Q10D00D00E), + Rule::Get( + &imageAtomicXorExt_01Q10D00D00E), + Rule::Get(&imageAtomicXor_01b10D00D00E), + Rule::Get( + &imageAtomicXorExt_01b10D00D00E), + Rule::Get(&imageAtomicXor_01G20D00D00E), + Rule::Get( + &imageAtomicXorExt_01G20D00D00E), + Rule::Get(&imageAtomicXor_01R20D00D00E), + Rule::Get( + &imageAtomicXorExt_01R20D00D00E), + Rule::Get(&imageAtomicXor_01c20D00D00E), + Rule::Get( + &imageAtomicXorExt_01c20D00D00E), + Rule::Get(&imageAtomicXor_00z10D00D), + Rule::Get( + &imageAtomicXorExt_00z10D00D), + Rule::Get(&imageAtomicXor_01K10D00D), + Rule::Get( + &imageAtomicXorExt_01K10D00D), + Rule::Get(&imageAtomicXor_01V10D00D), + Rule::Get( + &imageAtomicXorExt_01V10D00D), + Rule::Get(&imageAtomicXor_01A20D00D), + Rule::Get( + &imageAtomicXorExt_01A20D00D), + Rule::Get(&imageAtomicXor_01L20D00D), + Rule::Get( + &imageAtomicXorExt_01L20D00D), + Rule::Get(&imageAtomicXor_01W20D00D), + Rule::Get( + &imageAtomicXorExt_01W20D00D), + Rule::Get(&imageAtomicXor_01C20D00D), + Rule::Get( + &imageAtomicXorExt_01C20D00D), + Rule::Get(&imageAtomicXor_01N20D00D), + Rule::Get( + &imageAtomicXorExt_01N20D00D), + Rule::Get(&imageAtomicXor_01Y20D00D), + Rule::Get( + &imageAtomicXorExt_01Y20D00D), + Rule::Get(&imageAtomicXor_01J00D00D), + Rule::Get( + &imageAtomicXorExt_01J00D00D), + Rule::Get(&imageAtomicXor_01U00D00D), + Rule::Get( + &imageAtomicXorExt_01U00D00D), + Rule::Get(&imageAtomicXor_01f00D00D), + Rule::Get( + &imageAtomicXorExt_01f00D00D), + Rule::Get(&imageAtomicXor_01B20D00D), + Rule::Get( + &imageAtomicXorExt_01B20D00D), + Rule::Get(&imageAtomicXor_01M20D00D), + Rule::Get( + &imageAtomicXorExt_01M20D00D), + Rule::Get(&imageAtomicXor_01X20D00D), + Rule::Get( + &imageAtomicXorExt_01X20D00D), + Rule::Get(&imageAtomicXor_01H20D00D), + Rule::Get( + &imageAtomicXorExt_01H20D00D), + Rule::Get(&imageAtomicXor_01S20D00D), + Rule::Get( + &imageAtomicXorExt_01S20D00D), + Rule::Get(&imageAtomicXor_01d20D00D), + Rule::Get( + &imageAtomicXorExt_01d20D00D), + Rule::Get(&imageAtomicXor_01D00D00D), + Rule::Get( + &imageAtomicXorExt_01D00D00D), + Rule::Get(&imageAtomicXor_01O00D00D), + Rule::Get( + &imageAtomicXorExt_01O00D00D), + Rule::Get(&imageAtomicXor_01Z00D00D), + Rule::Get( + &imageAtomicXorExt_01Z00D00D), + Rule::Get(&imageAtomicXor_01E10D00D), + Rule::Get( + &imageAtomicXorExt_01E10D00D), + Rule::Get(&imageAtomicXor_01P10D00D), + Rule::Get( + &imageAtomicXorExt_01P10D00D), + Rule::Get(&imageAtomicXor_01a10D00D), + Rule::Get( + &imageAtomicXorExt_01a10D00D), + Rule::Get(&imageAtomicXor_01I10D00D), + Rule::Get( + &imageAtomicXorExt_01I10D00D), + Rule::Get(&imageAtomicXor_01T10D00D), + Rule::Get( + &imageAtomicXorExt_01T10D00D), + Rule::Get(&imageAtomicXor_01e10D00D), + Rule::Get( + &imageAtomicXorExt_01e10D00D), + Rule::Get(&imageAtomicXor_01F10D00D00D), + Rule::Get( + &imageAtomicXorExt_01F10D00D00D), + Rule::Get(&imageAtomicXor_01Q10D00D00D), + Rule::Get( + &imageAtomicXorExt_01Q10D00D00D), + Rule::Get(&imageAtomicXor_01b10D00D00D), + Rule::Get( + &imageAtomicXorExt_01b10D00D00D), + Rule::Get(&imageAtomicXor_01G20D00D00D), + Rule::Get( + &imageAtomicXorExt_01G20D00D00D), + Rule::Get(&imageAtomicXor_01R20D00D00D), + Rule::Get( + &imageAtomicXorExt_01R20D00D00D), + Rule::Get(&imageAtomicXor_01c20D00D00D), + Rule::Get( + &imageAtomicXorExt_01c20D00D00D), + Rule::Get(&imageAtomicExchange_00z10D00E), + Rule::Get( + &imageAtomicExchangeExt_00z10D00E), + Rule::Get(&imageAtomicExchange_01K10D00E), + Rule::Get( + &imageAtomicExchangeExt_01K10D00E), + Rule::Get(&imageAtomicExchange_01V10D00E), + Rule::Get( + &imageAtomicExchangeExt_01V10D00E), + Rule::Get(&imageAtomicExchange_01A20D00E), + Rule::Get( + &imageAtomicExchangeExt_01A20D00E), + Rule::Get(&imageAtomicExchange_01L20D00E), + Rule::Get( + &imageAtomicExchangeExt_01L20D00E), + Rule::Get(&imageAtomicExchange_01W20D00E), + Rule::Get( + &imageAtomicExchangeExt_01W20D00E), + Rule::Get(&imageAtomicExchange_01C20D00E), + Rule::Get( + &imageAtomicExchangeExt_01C20D00E), + Rule::Get(&imageAtomicExchange_01N20D00E), + Rule::Get( + &imageAtomicExchangeExt_01N20D00E), + Rule::Get(&imageAtomicExchange_01Y20D00E), + Rule::Get( + &imageAtomicExchangeExt_01Y20D00E), + Rule::Get(&imageAtomicExchange_01J00D00E), + Rule::Get( + &imageAtomicExchangeExt_01J00D00E), + Rule::Get(&imageAtomicExchange_01U00D00E), + Rule::Get( + &imageAtomicExchangeExt_01U00D00E), + Rule::Get(&imageAtomicExchange_01f00D00E), + Rule::Get( + &imageAtomicExchangeExt_01f00D00E), + Rule::Get(&imageAtomicExchange_01B20D00E), + Rule::Get( + &imageAtomicExchangeExt_01B20D00E), + Rule::Get(&imageAtomicExchange_01M20D00E), + Rule::Get( + &imageAtomicExchangeExt_01M20D00E), + Rule::Get(&imageAtomicExchange_01X20D00E), + Rule::Get( + &imageAtomicExchangeExt_01X20D00E), + Rule::Get(&imageAtomicExchange_01H20D00E), + Rule::Get( + &imageAtomicExchangeExt_01H20D00E), + Rule::Get(&imageAtomicExchange_01S20D00E), + Rule::Get( + &imageAtomicExchangeExt_01S20D00E), + Rule::Get(&imageAtomicExchange_01d20D00E), + Rule::Get( + &imageAtomicExchangeExt_01d20D00E), + Rule::Get(&imageAtomicExchange_01D00D00E), + Rule::Get( + &imageAtomicExchangeExt_01D00D00E), + Rule::Get(&imageAtomicExchange_01O00D00E), + Rule::Get( + &imageAtomicExchangeExt_01O00D00E), + Rule::Get(&imageAtomicExchange_01Z00D00E), + Rule::Get( + &imageAtomicExchangeExt_01Z00D00E), + Rule::Get(&imageAtomicExchange_01E10D00E), + Rule::Get( + &imageAtomicExchangeExt_01E10D00E), + Rule::Get(&imageAtomicExchange_01P10D00E), + Rule::Get( + &imageAtomicExchangeExt_01P10D00E), + Rule::Get(&imageAtomicExchange_01a10D00E), + Rule::Get( + &imageAtomicExchangeExt_01a10D00E), + Rule::Get(&imageAtomicExchange_01I10D00E), + Rule::Get( + &imageAtomicExchangeExt_01I10D00E), + Rule::Get(&imageAtomicExchange_01T10D00E), + Rule::Get( + &imageAtomicExchangeExt_01T10D00E), + Rule::Get(&imageAtomicExchange_01e10D00E), + Rule::Get( + &imageAtomicExchangeExt_01e10D00E), + Rule::Get(&imageAtomicExchange_01F10D00D00E), + Rule::Get( + &imageAtomicExchangeExt_01F10D00D00E), + Rule::Get(&imageAtomicExchange_01Q10D00D00E), + Rule::Get( + &imageAtomicExchangeExt_01Q10D00D00E), + Rule::Get(&imageAtomicExchange_01b10D00D00E), + Rule::Get( + &imageAtomicExchangeExt_01b10D00D00E), + Rule::Get(&imageAtomicExchange_01G20D00D00E), + Rule::Get( + &imageAtomicExchangeExt_01G20D00D00E), + Rule::Get(&imageAtomicExchange_01R20D00D00E), + Rule::Get( + &imageAtomicExchangeExt_01R20D00D00E), + Rule::Get(&imageAtomicExchange_01c20D00D00E), + Rule::Get( + &imageAtomicExchangeExt_01c20D00D00E), + Rule::Get(&imageAtomicExchange_00z10D00D), + Rule::Get( + &imageAtomicExchangeExt_00z10D00D), + Rule::Get(&imageAtomicExchange_01K10D00D), + Rule::Get( + &imageAtomicExchangeExt_01K10D00D), + Rule::Get(&imageAtomicExchange_01V10D00D), + Rule::Get( + &imageAtomicExchangeExt_01V10D00D), + Rule::Get(&imageAtomicExchange_01A20D00D), + Rule::Get( + &imageAtomicExchangeExt_01A20D00D), + Rule::Get(&imageAtomicExchange_01L20D00D), + Rule::Get( + &imageAtomicExchangeExt_01L20D00D), + Rule::Get(&imageAtomicExchange_01W20D00D), + Rule::Get( + &imageAtomicExchangeExt_01W20D00D), + Rule::Get(&imageAtomicExchange_01C20D00D), + Rule::Get( + &imageAtomicExchangeExt_01C20D00D), + Rule::Get(&imageAtomicExchange_01N20D00D), + Rule::Get( + &imageAtomicExchangeExt_01N20D00D), + Rule::Get(&imageAtomicExchange_01Y20D00D), + Rule::Get( + &imageAtomicExchangeExt_01Y20D00D), + Rule::Get(&imageAtomicExchange_01J00D00D), + Rule::Get( + &imageAtomicExchangeExt_01J00D00D), + Rule::Get(&imageAtomicExchange_01U00D00D), + Rule::Get( + &imageAtomicExchangeExt_01U00D00D), + Rule::Get(&imageAtomicExchange_01f00D00D), + Rule::Get( + &imageAtomicExchangeExt_01f00D00D), + Rule::Get(&imageAtomicExchange_01B20D00D), + Rule::Get( + &imageAtomicExchangeExt_01B20D00D), + Rule::Get(&imageAtomicExchange_01M20D00D), + Rule::Get( + &imageAtomicExchangeExt_01M20D00D), + Rule::Get(&imageAtomicExchange_01X20D00D), + Rule::Get( + &imageAtomicExchangeExt_01X20D00D), + Rule::Get(&imageAtomicExchange_01H20D00D), + Rule::Get( + &imageAtomicExchangeExt_01H20D00D), + Rule::Get(&imageAtomicExchange_01S20D00D), + Rule::Get( + &imageAtomicExchangeExt_01S20D00D), + Rule::Get(&imageAtomicExchange_01d20D00D), + Rule::Get( + &imageAtomicExchangeExt_01d20D00D), + Rule::Get(&imageAtomicExchange_01D00D00D), + Rule::Get( + &imageAtomicExchangeExt_01D00D00D), + Rule::Get(&imageAtomicExchange_01O00D00D), + Rule::Get( + &imageAtomicExchangeExt_01O00D00D), + Rule::Get(&imageAtomicExchange_01Z00D00D), + Rule::Get( + &imageAtomicExchangeExt_01Z00D00D), + Rule::Get(&imageAtomicExchange_01E10D00D), + Rule::Get( + &imageAtomicExchangeExt_01E10D00D), + Rule::Get(&imageAtomicExchange_01P10D00D), + Rule::Get( + &imageAtomicExchangeExt_01P10D00D), + Rule::Get(&imageAtomicExchange_01a10D00D), + Rule::Get( + &imageAtomicExchangeExt_01a10D00D), + Rule::Get(&imageAtomicExchange_01I10D00D), + Rule::Get( + &imageAtomicExchangeExt_01I10D00D), + Rule::Get(&imageAtomicExchange_01T10D00D), + Rule::Get( + &imageAtomicExchangeExt_01T10D00D), + Rule::Get(&imageAtomicExchange_01e10D00D), + Rule::Get( + &imageAtomicExchangeExt_01e10D00D), + Rule::Get(&imageAtomicExchange_01F10D00D00D), + Rule::Get( + &imageAtomicExchangeExt_01F10D00D00D), + Rule::Get(&imageAtomicExchange_01Q10D00D00D), + Rule::Get( + &imageAtomicExchangeExt_01Q10D00D00D), + Rule::Get(&imageAtomicExchange_01b10D00D00D), + Rule::Get( + &imageAtomicExchangeExt_01b10D00D00D), + Rule::Get(&imageAtomicExchange_01G20D00D00D), + Rule::Get( + &imageAtomicExchangeExt_01G20D00D00D), + Rule::Get(&imageAtomicExchange_01R20D00D00D), + Rule::Get( + &imageAtomicExchangeExt_01R20D00D00D), + Rule::Get(&imageAtomicExchange_01c20D00D00D), + Rule::Get( + &imageAtomicExchangeExt_01c20D00D00D), + Rule::Get(&imageAtomicExchange_00z10D00B), + Rule::Get( + &imageAtomicExchangeExt_00z10D00B), + Rule::Get(&imageAtomicExchange_01K10D00B), + Rule::Get( + &imageAtomicExchangeExt_01K10D00B), + Rule::Get(&imageAtomicExchange_01V10D00B), + Rule::Get( + &imageAtomicExchangeExt_01V10D00B), + Rule::Get(&imageAtomicExchange_01A20D00B), + Rule::Get( + &imageAtomicExchangeExt_01A20D00B), + Rule::Get(&imageAtomicExchange_01L20D00B), + Rule::Get( + &imageAtomicExchangeExt_01L20D00B), + Rule::Get(&imageAtomicExchange_01W20D00B), + Rule::Get( + &imageAtomicExchangeExt_01W20D00B), + Rule::Get(&imageAtomicExchange_01C20D00B), + Rule::Get( + &imageAtomicExchangeExt_01C20D00B), + Rule::Get(&imageAtomicExchange_01N20D00B), + Rule::Get( + &imageAtomicExchangeExt_01N20D00B), + Rule::Get(&imageAtomicExchange_01Y20D00B), + Rule::Get( + &imageAtomicExchangeExt_01Y20D00B), + Rule::Get(&imageAtomicExchange_01J00D00B), + Rule::Get( + &imageAtomicExchangeExt_01J00D00B), + Rule::Get(&imageAtomicExchange_01U00D00B), + Rule::Get( + &imageAtomicExchangeExt_01U00D00B), + Rule::Get(&imageAtomicExchange_01f00D00B), + Rule::Get( + &imageAtomicExchangeExt_01f00D00B), + Rule::Get(&imageAtomicExchange_01B20D00B), + Rule::Get( + &imageAtomicExchangeExt_01B20D00B), + Rule::Get(&imageAtomicExchange_01M20D00B), + Rule::Get( + &imageAtomicExchangeExt_01M20D00B), + Rule::Get(&imageAtomicExchange_01X20D00B), + Rule::Get( + &imageAtomicExchangeExt_01X20D00B), + Rule::Get(&imageAtomicExchange_01H20D00B), + Rule::Get( + &imageAtomicExchangeExt_01H20D00B), + Rule::Get(&imageAtomicExchange_01S20D00B), + Rule::Get( + &imageAtomicExchangeExt_01S20D00B), + Rule::Get(&imageAtomicExchange_01d20D00B), + Rule::Get( + &imageAtomicExchangeExt_01d20D00B), + Rule::Get(&imageAtomicExchange_01D00D00B), + Rule::Get( + &imageAtomicExchangeExt_01D00D00B), + Rule::Get(&imageAtomicExchange_01O00D00B), + Rule::Get( + &imageAtomicExchangeExt_01O00D00B), + Rule::Get(&imageAtomicExchange_01Z00D00B), + Rule::Get( + &imageAtomicExchangeExt_01Z00D00B), + Rule::Get(&imageAtomicExchange_01E10D00B), + Rule::Get( + &imageAtomicExchangeExt_01E10D00B), + Rule::Get(&imageAtomicExchange_01P10D00B), + Rule::Get( + &imageAtomicExchangeExt_01P10D00B), + Rule::Get(&imageAtomicExchange_01a10D00B), + Rule::Get( + &imageAtomicExchangeExt_01a10D00B), + Rule::Get(&imageAtomicExchange_01I10D00B), + Rule::Get( + &imageAtomicExchangeExt_01I10D00B), + Rule::Get(&imageAtomicExchange_01T10D00B), + Rule::Get( + &imageAtomicExchangeExt_01T10D00B), + Rule::Get(&imageAtomicExchange_01e10D00B), + Rule::Get( + &imageAtomicExchangeExt_01e10D00B), + Rule::Get(&imageAtomicExchange_01F10D00D00B), + Rule::Get( + &imageAtomicExchangeExt_01F10D00D00B), + Rule::Get(&imageAtomicExchange_01Q10D00D00B), + Rule::Get( + &imageAtomicExchangeExt_01Q10D00D00B), + Rule::Get(&imageAtomicExchange_01b10D00D00B), + Rule::Get( + &imageAtomicExchangeExt_01b10D00D00B), + Rule::Get(&imageAtomicExchange_01G20D00D00B), + Rule::Get( + &imageAtomicExchangeExt_01G20D00D00B), + Rule::Get(&imageAtomicExchange_01R20D00D00B), + Rule::Get( + &imageAtomicExchangeExt_01R20D00D00B), + Rule::Get(&imageAtomicExchange_01c20D00D00B), + Rule::Get( + &imageAtomicExchangeExt_01c20D00D00B), + Rule::Get(&imageAtomicCompSwap_00z10D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_00z10D00E00E), + Rule::Get(&imageAtomicCompSwap_01K10D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01K10D00E00E), + Rule::Get(&imageAtomicCompSwap_01V10D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01V10D00E00E), + Rule::Get(&imageAtomicCompSwap_01A20D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01A20D00E00E), + Rule::Get(&imageAtomicCompSwap_01L20D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01L20D00E00E), + Rule::Get(&imageAtomicCompSwap_01W20D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01W20D00E00E), + Rule::Get(&imageAtomicCompSwap_01C20D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01C20D00E00E), + Rule::Get(&imageAtomicCompSwap_01N20D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01N20D00E00E), + Rule::Get(&imageAtomicCompSwap_01Y20D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01Y20D00E00E), + Rule::Get(&imageAtomicCompSwap_01J00D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01J00D00E00E), + Rule::Get(&imageAtomicCompSwap_01U00D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01U00D00E00E), + Rule::Get(&imageAtomicCompSwap_01f00D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01f00D00E00E), + Rule::Get(&imageAtomicCompSwap_01B20D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01B20D00E00E), + Rule::Get(&imageAtomicCompSwap_01M20D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01M20D00E00E), + Rule::Get(&imageAtomicCompSwap_01X20D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01X20D00E00E), + Rule::Get(&imageAtomicCompSwap_01H20D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01H20D00E00E), + Rule::Get(&imageAtomicCompSwap_01S20D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01S20D00E00E), + Rule::Get(&imageAtomicCompSwap_01d20D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01d20D00E00E), + Rule::Get(&imageAtomicCompSwap_01D00D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01D00D00E00E), + Rule::Get(&imageAtomicCompSwap_01O00D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01O00D00E00E), + Rule::Get(&imageAtomicCompSwap_01Z00D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01Z00D00E00E), + Rule::Get(&imageAtomicCompSwap_01E10D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01E10D00E00E), + Rule::Get(&imageAtomicCompSwap_01P10D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01P10D00E00E), + Rule::Get(&imageAtomicCompSwap_01a10D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01a10D00E00E), + Rule::Get(&imageAtomicCompSwap_01I10D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01I10D00E00E), + Rule::Get(&imageAtomicCompSwap_01T10D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01T10D00E00E), + Rule::Get(&imageAtomicCompSwap_01e10D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01e10D00E00E), + Rule::Get(&imageAtomicCompSwap_01F10D00D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01F10D00D00E00E), + Rule::Get(&imageAtomicCompSwap_01Q10D00D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01Q10D00D00E00E), + Rule::Get(&imageAtomicCompSwap_01b10D00D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01b10D00D00E00E), + Rule::Get(&imageAtomicCompSwap_01G20D00D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01G20D00D00E00E), + Rule::Get(&imageAtomicCompSwap_01R20D00D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01R20D00D00E00E), + Rule::Get(&imageAtomicCompSwap_01c20D00D00E00E), + Rule::Get( + &imageAtomicCompSwapExt_01c20D00D00E00E), + Rule::Get(&imageAtomicCompSwap_00z10D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_00z10D00D00D), + Rule::Get(&imageAtomicCompSwap_01K10D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01K10D00D00D), + Rule::Get(&imageAtomicCompSwap_01V10D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01V10D00D00D), + Rule::Get(&imageAtomicCompSwap_01A20D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01A20D00D00D), + Rule::Get(&imageAtomicCompSwap_01L20D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01L20D00D00D), + Rule::Get(&imageAtomicCompSwap_01W20D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01W20D00D00D), + Rule::Get(&imageAtomicCompSwap_01C20D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01C20D00D00D), + Rule::Get(&imageAtomicCompSwap_01N20D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01N20D00D00D), + Rule::Get(&imageAtomicCompSwap_01Y20D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01Y20D00D00D), + Rule::Get(&imageAtomicCompSwap_01J00D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01J00D00D00D), + Rule::Get(&imageAtomicCompSwap_01U00D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01U00D00D00D), + Rule::Get(&imageAtomicCompSwap_01f00D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01f00D00D00D), + Rule::Get(&imageAtomicCompSwap_01B20D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01B20D00D00D), + Rule::Get(&imageAtomicCompSwap_01M20D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01M20D00D00D), + Rule::Get(&imageAtomicCompSwap_01X20D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01X20D00D00D), + Rule::Get(&imageAtomicCompSwap_01H20D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01H20D00D00D), + Rule::Get(&imageAtomicCompSwap_01S20D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01S20D00D00D), + Rule::Get(&imageAtomicCompSwap_01d20D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01d20D00D00D), + Rule::Get(&imageAtomicCompSwap_01D00D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01D00D00D00D), + Rule::Get(&imageAtomicCompSwap_01O00D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01O00D00D00D), + Rule::Get(&imageAtomicCompSwap_01Z00D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01Z00D00D00D), + Rule::Get(&imageAtomicCompSwap_01E10D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01E10D00D00D), + Rule::Get(&imageAtomicCompSwap_01P10D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01P10D00D00D), + Rule::Get(&imageAtomicCompSwap_01a10D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01a10D00D00D), + Rule::Get(&imageAtomicCompSwap_01I10D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01I10D00D00D), + Rule::Get(&imageAtomicCompSwap_01T10D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01T10D00D00D), + Rule::Get(&imageAtomicCompSwap_01e10D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01e10D00D00D), + Rule::Get(&imageAtomicCompSwap_01F10D00D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01F10D00D00D00D), + Rule::Get(&imageAtomicCompSwap_01Q10D00D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01Q10D00D00D00D), + Rule::Get(&imageAtomicCompSwap_01b10D00D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01b10D00D00D00D), + Rule::Get(&imageAtomicCompSwap_01G20D00D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01G20D00D00D00D), + Rule::Get(&imageAtomicCompSwap_01R20D00D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01R20D00D00D00D), + Rule::Get(&imageAtomicCompSwap_01c20D00D00D00D), + Rule::Get( + &imageAtomicCompSwapExt_01c20D00D00D00D), + Rule::Get( + &pixelLocalLoadANGLE_01g), + Rule::Get( + &pixelLocalLoadANGLE_01h), + Rule::Get( + &pixelLocalLoadANGLE_01i), + Rule::Get( + &pixelLocalStoreANGLE_01g30B), + Rule::Get( + &pixelLocalStoreANGLE_01h30D), + Rule::Get( + &pixelLocalStoreANGLE_01i30E), + Rule::Get( + &beginInvocationInterlockNV_), + Rule::Get(&endInvocationInterlockNV_), + Rule::Get( + &beginFragmentShaderOrderingINTEL_), + Rule::Get( + &beginInvocationInterlockARB_), + Rule::Get( + &endInvocationInterlockARB_), + Rule::Get(&memoryBarrier_), + Rule::Get(&memoryBarrierAtomicCounter_), + Rule::Get(&memoryBarrierBuffer_), + Rule::Get(&memoryBarrierImage_), + Rule::Get(&barrier_), + Rule::Get(&barrierTCSES3_2_), + Rule::Get( + &barrierTCS_), + Rule::Get(&memoryBarrierShared_), + Rule::Get(&groupMemoryBarrier_), + Rule::Get(&EmitVertexES3_2_), + Rule::Get(&EmitVertex_), + Rule::Get(&EmitVertex_), + Rule::Get(&EndPrimitiveES3_2_), + Rule::Get(&EndPrimitive_), + Rule::Get(&EndPrimitive_), + Rule::Get(&subpassLoad_01j), + Rule::Get(&subpassLoad_01k), + Rule::Get(&subpassLoad_01l), + Rule::Get(&subpassLoad_01m00D), + Rule::Get(&subpassLoad_01n00D), + Rule::Get(&subpassLoad_01o00D), + Rule::Get(&TableBase::m_gl_DepthRangeParameters), + Rule::Get(&TableBase::m_gl_DepthRange), + Rule::Get(&BuiltInVariable::kgl_NumSamplesES3_2), + Rule::Get( + &BuiltInVariable::kgl_NumSamples), + Rule::Get(&TableBase::m_gl_MaxVertexAttribs), + Rule::Get(&TableBase::m_gl_MaxVertexUniformVectors), + Rule::Get(&TableBase::m_gl_MaxVertexTextureImageUnits), + Rule::Get(&TableBase::m_gl_MaxCombinedTextureImageUnits), + Rule::Get(&TableBase::m_gl_MaxTextureImageUnits), + Rule::Get(&TableBase::m_gl_MaxFragmentUniformVectors), + Rule::Get(&TableBase::m_gl_MaxVaryingVectors), + Rule::Get(&TableBase::m_gl_MaxDrawBuffers), + Rule::Get( + &TableBase::m_gl_MaxDualSourceDrawBuffersEXT), + Rule::Get(&TableBase::m_gl_MaxVertexOutputVectors), + Rule::Get(&TableBase::m_gl_MaxFragmentInputVectors), + Rule::Get(&TableBase::m_gl_MinProgramTexelOffset), + Rule::Get(&TableBase::m_gl_MaxProgramTexelOffset), + Rule::Get(&TableBase::m_gl_MaxImageUnits), + Rule::Get(&TableBase::m_gl_MaxVertexImageUniforms), + Rule::Get(&TableBase::m_gl_MaxFragmentImageUniforms), + Rule::Get(&TableBase::m_gl_MaxComputeImageUniforms), + Rule::Get(&TableBase::m_gl_MaxCombinedImageUniforms), + Rule::Get(&TableBase::m_gl_MaxCombinedShaderOutputResources), + Rule::Get(&TableBase::m_gl_MaxComputeWorkGroupCount), + Rule::Get(&TableBase::m_gl_MaxComputeWorkGroupSize), + Rule::Get(&TableBase::m_gl_MaxComputeUniformComponents), + Rule::Get(&TableBase::m_gl_MaxComputeTextureImageUnits), + Rule::Get(&TableBase::m_gl_MaxComputeAtomicCounters), + Rule::Get(&TableBase::m_gl_MaxComputeAtomicCounterBuffers), + Rule::Get(&TableBase::m_gl_MaxVertexAtomicCounters), + Rule::Get(&TableBase::m_gl_MaxFragmentAtomicCounters), + Rule::Get(&TableBase::m_gl_MaxCombinedAtomicCounters), + Rule::Get(&TableBase::m_gl_MaxAtomicCounterBindings), + Rule::Get(&TableBase::m_gl_MaxVertexAtomicCounterBuffers), + Rule::Get(&TableBase::m_gl_MaxFragmentAtomicCounterBuffers), + Rule::Get(&TableBase::m_gl_MaxCombinedAtomicCounterBuffers), + Rule::Get(&TableBase::m_gl_MaxAtomicCounterBufferSize), + Rule::Get(&TableBase::m_gl_MaxGeometryInputComponentsES3_2), + Rule::Get( + &TableBase::m_gl_MaxGeometryInputComponents), + Rule::Get( + &TableBase::m_gl_MaxGeometryInputComponents), + Rule::Get(&TableBase::m_gl_MaxGeometryOutputComponentsES3_2), + Rule::Get( + &TableBase::m_gl_MaxGeometryOutputComponents), + Rule::Get( + &TableBase::m_gl_MaxGeometryOutputComponents), + Rule::Get(&TableBase::m_gl_MaxGeometryImageUniformsES3_2), + Rule::Get( + &TableBase::m_gl_MaxGeometryImageUniforms), + Rule::Get( + &TableBase::m_gl_MaxGeometryImageUniforms), + Rule::Get(&TableBase::m_gl_MaxGeometryTextureImageUnitsES3_2), + Rule::Get( + &TableBase::m_gl_MaxGeometryTextureImageUnits), + Rule::Get( + &TableBase::m_gl_MaxGeometryTextureImageUnits), + Rule::Get(&TableBase::m_gl_MaxGeometryOutputVerticesES3_2), + Rule::Get( + &TableBase::m_gl_MaxGeometryOutputVertices), + Rule::Get( + &TableBase::m_gl_MaxGeometryOutputVertices), + Rule::Get( + &TableBase::m_gl_MaxGeometryTotalOutputComponentsES3_2), + Rule::Get( + &TableBase::m_gl_MaxGeometryTotalOutputComponents), + Rule::Get( + &TableBase::m_gl_MaxGeometryTotalOutputComponents), + Rule::Get(&TableBase::m_gl_MaxGeometryUniformComponentsES3_2), + Rule::Get( + &TableBase::m_gl_MaxGeometryUniformComponents), + Rule::Get( + &TableBase::m_gl_MaxGeometryUniformComponents), + Rule::Get(&TableBase::m_gl_MaxGeometryAtomicCountersES3_2), + Rule::Get( + &TableBase::m_gl_MaxGeometryAtomicCounters), + Rule::Get( + &TableBase::m_gl_MaxGeometryAtomicCounters), + Rule::Get( + &TableBase::m_gl_MaxGeometryAtomicCounterBuffersES3_2), + Rule::Get( + &TableBase::m_gl_MaxGeometryAtomicCounterBuffers), + Rule::Get( + &TableBase::m_gl_MaxGeometryAtomicCounterBuffers), + Rule::Get(&TableBase::m_gl_MaxTessControlInputComponentsES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessControlInputComponents), + Rule::Get( + &TableBase::m_gl_MaxTessControlOutputComponentsES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessControlOutputComponents), + Rule::Get( + &TableBase::m_gl_MaxTessControlTextureImageUnitsES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessControlTextureImageUnits), + Rule::Get( + &TableBase::m_gl_MaxTessControlUniformComponentsES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessControlUniformComponents), + Rule::Get( + &TableBase::m_gl_MaxTessControlTotalOutputComponentsES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessControlTotalOutputComponents), + Rule::Get(&TableBase::m_gl_MaxTessControlImageUniformsES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessControlImageUniforms), + Rule::Get(&TableBase::m_gl_MaxTessControlAtomicCountersES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessControlAtomicCounters), + Rule::Get( + &TableBase::m_gl_MaxTessControlAtomicCounterBuffersES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessControlAtomicCounterBuffers), + Rule::Get(&TableBase::m_gl_MaxTessPatchComponentsES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessPatchComponents), + Rule::Get(&TableBase::m_gl_MaxPatchVerticesES3_2), + Rule::Get( + &TableBase::m_gl_MaxPatchVertices), + Rule::Get(&TableBase::m_gl_MaxTessGenLevelES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessGenLevel), + Rule::Get( + &TableBase::m_gl_MaxTessEvaluationInputComponentsES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessEvaluationInputComponents), + Rule::Get( + &TableBase::m_gl_MaxTessEvaluationOutputComponentsES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessEvaluationOutputComponents), + Rule::Get( + &TableBase::m_gl_MaxTessEvaluationTextureImageUnitsES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessEvaluationTextureImageUnits), + Rule::Get( + &TableBase::m_gl_MaxTessEvaluationUniformComponentsES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessEvaluationUniformComponents), + Rule::Get( + &TableBase::m_gl_MaxTessEvaluationImageUniformsES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessEvaluationImageUniforms), + Rule::Get( + &TableBase::m_gl_MaxTessEvaluationAtomicCountersES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessEvaluationAtomicCounters), + Rule::Get( + &TableBase::m_gl_MaxTessEvaluationAtomicCounterBuffersES3_2), + Rule::Get( + &TableBase::m_gl_MaxTessEvaluationAtomicCounterBuffers), + Rule::Get(&TableBase::m_gl_MaxSamplesES3_2), + Rule::Get( + &TableBase::m_gl_MaxSamples), + Rule::Get( + &TableBase::m_gl_MaxClipDistancesAPPLE), + Rule::Get( + &TableBase::m_gl_MaxCullDistancesEXT), + Rule::Get( + &TableBase::m_gl_MaxCombinedClipAndCullDistancesEXT), + Rule::Get(&BuiltInVariable::kgl_FragCoord), + Rule::Get(&BuiltInVariable::kgl_FragCoord300), + Rule::Get(&BuiltInVariable::kgl_FrontFacing), + Rule::Get(&BuiltInVariable::kgl_PointCoord), + Rule::Get(&BuiltInVariable::kgl_FragColor), + Rule::Get(&TableBase::m_gl_FragData), + Rule::Get(&BuiltInVariable::kgl_FragDepth), + Rule::Get(&BuiltInVariable::kgl_HelperInvocation), + Rule::Get( + &BuiltInVariable::kgl_SecondaryFragColorEXT), + Rule::Get( + &TableBase::m_gl_SecondaryFragDataEXT), + Rule::Get( + &TableBase::m_gl_FragDepthEXT), + Rule::Get( + &TableBase::m_gl_LastFragData), + Rule::Get(&TableBase::m_gl_LastFragData), + Rule::Get( + &TableBase::m_gl_LastFragDataNV), + Rule::Get( + &BuiltInVariable::kgl_LastFragColor), + Rule::Get( + &BuiltInVariable::kgl_LastFragColorARM), + Rule::Get(&BuiltInVariable::kgl_PrimitiveIDES3_2), + Rule::Get(&BuiltInVariable::kgl_PrimitiveIDGSES3_2), + Rule::Get( + &BuiltInVariable::kgl_PrimitiveIDTCSES3_2), + Rule::Get( + &BuiltInVariable::kgl_PrimitiveIDTESES3_2), + Rule::Get( + &BuiltInVariable::kgl_PrimitiveID), + Rule::Get( + &BuiltInVariable::kgl_PrimitiveID), + Rule::Get( + &BuiltInVariable::kgl_PrimitiveIDGS), + Rule::Get( + &BuiltInVariable::kgl_PrimitiveIDGS), + Rule::Get( + &BuiltInVariable::kgl_PrimitiveIDTCS), + Rule::Get( + &BuiltInVariable::kgl_PrimitiveIDTES), + Rule::Get(&BuiltInVariable::kgl_LayerES3_2), + Rule::Get(&BuiltInVariable::kgl_LayerGSES3_2), + Rule::Get( + &BuiltInVariable::kgl_Layer), + Rule::Get( + &BuiltInVariable::kgl_Layer), + Rule::Get( + &BuiltInVariable::kgl_LayerGS), + Rule::Get( + &BuiltInVariable::kgl_LayerGS), + Rule::Get(&BuiltInVariable::kgl_SampleIDES3_2), + Rule::Get( + &BuiltInVariable::kgl_SampleID), + Rule::Get(&BuiltInVariable::kgl_SamplePositionES3_2), + Rule::Get( + &BuiltInVariable::kgl_SamplePosition), + Rule::Get(&TableBase::m_gl_SampleMaskInES3_2), + Rule::Get( + &TableBase::m_gl_SampleMaskIn), + Rule::Get(&TableBase::m_gl_SampleMaskES3_2), + Rule::Get( + &TableBase::m_gl_SampleMask), + Rule::Get( + &TableBase::m_gl_CullDistance), + Rule::Get( + &TableBase::m_gl_CullDistanceEXT), + Rule::Get( + &TableBase::m_gl_ClipDistance), + Rule::Get( + &TableBase::m_gl_ClipDistanceAPPLE), + Rule::Get(&BuiltInVariable::kgl_Position), + Rule::Get(&TableBase::m_gl_PositionGSES3_2), + Rule::Get(&TableBase::m_gl_PositionTCSES3_2), + Rule::Get(&TableBase::m_gl_PositionTESES3_2), + Rule::Get( + &TableBase::m_gl_PositionGS), + Rule::Get( + &TableBase::m_gl_PositionGS), + Rule::Get( + &TableBase::m_gl_PositionTCS), + Rule::Get( + &TableBase::m_gl_PositionTES), + Rule::Get(&BuiltInVariable::kgl_PointSize), + Rule::Get(&BuiltInVariable::kgl_PointSize300), + Rule::Get(&BuiltInVariable::kgl_InstanceID), + Rule::Get(&BuiltInVariable::kgl_VertexID), + Rule::Get( + &BuiltInVariable::kgl_DrawID), + Rule::Get( + &BuiltInVariable::kgl_BaseVertex), + Rule::Get( + &BuiltInVariable::kgl_BaseInstance), + Rule::Get( + &BuiltInVariable::kangle_BaseVertex), + Rule::Get( + &BuiltInVariable::kangle_BaseInstance), + Rule::Get(&BuiltInVariable::kgl_NumWorkGroups), + Rule::Get(&BuiltInVariable::kgl_WorkGroupSize), + Rule::Get(&BuiltInVariable::kgl_WorkGroupID), + Rule::Get(&BuiltInVariable::kgl_LocalInvocationID), + Rule::Get(&BuiltInVariable::kgl_GlobalInvocationID), + Rule::Get(&BuiltInVariable::kgl_LocalInvocationIndex), + Rule::Get(&BuiltInVariable::kgl_PrimitiveIDInES3_2), + Rule::Get( + &BuiltInVariable::kgl_PrimitiveIDIn), + Rule::Get( + &BuiltInVariable::kgl_PrimitiveIDIn), + Rule::Get(&BuiltInVariable::kgl_InvocationIDES3_2), + Rule::Get( + &BuiltInVariable::kgl_InvocationIDTCSES3_2), + Rule::Get( + &BuiltInVariable::kgl_InvocationID), + Rule::Get( + &BuiltInVariable::kgl_InvocationID), + Rule::Get( + &BuiltInVariable::kgl_InvocationIDTCS), + Rule::Get(&TableBase::m_gl_PerVertexES3_2), + Rule::Get(&TableBase::m_gl_PerVertexTCSES3_2), + Rule::Get(&TableBase::m_gl_PerVertexTESES3_2), + Rule::Get( + &TableBase::m_gl_PerVertex), + Rule::Get( + &TableBase::m_gl_PerVertex), + Rule::Get( + &TableBase::m_gl_PerVertexTCS), + Rule::Get( + &TableBase::m_gl_PerVertexTES), + Rule::Get(&TableBase::m_gl_inES3_2), + Rule::Get(&TableBase::m_gl_inTCSES3_2), + Rule::Get(&TableBase::m_gl_inTESES3_2), + Rule::Get( + &TableBase::m_gl_in), + Rule::Get( + &TableBase::m_gl_in), + Rule::Get( + &TableBase::m_gl_inTCS), + Rule::Get( + &TableBase::m_gl_inTES), + Rule::Get( + &BuiltInVariable::kgl_PatchVerticesInTCSES3_2), + Rule::Get( + &BuiltInVariable::kgl_PatchVerticesInTESES3_2), + Rule::Get( + &BuiltInVariable::kgl_PatchVerticesInTCS), + Rule::Get( + &BuiltInVariable::kgl_PatchVerticesInTES), + Rule::Get( + &TableBase::m_gl_TessLevelOuterTCSES3_2), + Rule::Get( + &TableBase::m_gl_TessLevelOuterTESES3_2), + Rule::Get( + &TableBase::m_gl_TessLevelOuterTCS), + Rule::Get( + &TableBase::m_gl_TessLevelOuterTES), + Rule::Get( + &TableBase::m_gl_TessLevelInnerTCSES3_2), + Rule::Get( + &TableBase::m_gl_TessLevelInnerTESES3_2), + Rule::Get( + &TableBase::m_gl_TessLevelInnerTCS), + Rule::Get( + &TableBase::m_gl_TessLevelInnerTES), + Rule::Get(&TableBase::m_gl_outTCSES3_2), + Rule::Get(&TableBase::m_gl_outTESES3_2), + Rule::Get( + &TableBase::m_gl_outTCS), + Rule::Get( + &TableBase::m_gl_outTES), + Rule::Get(&TableBase::m_gl_BoundingBoxTCSES3_2), + Rule::Get( + &TableBase::m_gl_BoundingBoxTCS), + Rule::Get( + &TableBase::m_gl_BoundingBoxEXTTCSES3_2), + Rule::Get( + &TableBase::m_gl_BoundingBoxEXTTCS), + Rule::Get( + &TableBase::m_gl_BoundingBoxOESTCSES3_2), + Rule::Get( + &TableBase::m_gl_BoundingBoxOESTCS), + Rule::Get(&BuiltInVariable::kgl_TessCoord), + Rule::Get( + &BuiltInVariable::kgl_ViewID_OVR)}; + +// Flat array of all mangled names. +constexpr const char *kMangledNames[] = {"radians(00B", + "radians(10B", + "radians(20B", + "radians(30B", + "degrees(00B", + "degrees(10B", + "degrees(20B", + "degrees(30B", + "sin(00B", + "sin(10B", + "sin(20B", + "sin(30B", + "cos(00B", + "cos(10B", + "cos(20B", + "cos(30B", + "tan(00B", + "tan(10B", + "tan(20B", + "tan(30B", + "asin(00B", + "asin(10B", + "asin(20B", + "asin(30B", + "acos(00B", + "acos(10B", + "acos(20B", + "acos(30B", + "atan(00B00B", + "atan(10B10B", + "atan(20B20B", + "atan(30B30B", + "atan(00B", + "atan(10B", + "atan(20B", + "atan(30B", + "sinh(00B", + "sinh(10B", + "sinh(20B", + "sinh(30B", + "cosh(00B", + "cosh(10B", + "cosh(20B", + "cosh(30B", + "tanh(00B", + "tanh(10B", + "tanh(20B", + "tanh(30B", + "asinh(00B", + "asinh(10B", + "asinh(20B", + "asinh(30B", + "acosh(00B", + "acosh(10B", + "acosh(20B", + "acosh(30B", + "atanh(00B", + "atanh(10B", + "atanh(20B", + "atanh(30B", + "pow(00B00B", + "pow(10B10B", + "pow(20B20B", + "pow(30B30B", + "exp(00B", + "exp(10B", + "exp(20B", + "exp(30B", + "log(00B", + "log(10B", + "log(20B", + "log(30B", + "exp2(00B", + "exp2(10B", + "exp2(20B", + "exp2(30B", + "log2(00B", + "log2(10B", + "log2(20B", + "log2(30B", + "sqrt(00B", + "sqrt(10B", + "sqrt(20B", + "sqrt(30B", + "inversesqrt(00B", + "inversesqrt(10B", + "inversesqrt(20B", + "inversesqrt(30B", + "abs(00B", + "abs(10B", + "abs(20B", + "abs(30B", + "abs(00D", + "abs(10D", + "abs(20D", + "abs(30D", + "sign(00B", + "sign(10B", + "sign(20B", + "sign(30B", + "sign(00D", + "sign(10D", + "sign(20D", + "sign(30D", + "floor(00B", + "floor(10B", + "floor(20B", + "floor(30B", + "trunc(00B", + "trunc(10B", + "trunc(20B", + "trunc(30B", + "round(00B", + "round(10B", + "round(20B", + "round(30B", + "roundEven(00B", + "roundEven(10B", + "roundEven(20B", + "roundEven(30B", + "ceil(00B", + "ceil(10B", + "ceil(20B", + "ceil(30B", + "fract(00B", + "fract(10B", + "fract(20B", + "fract(30B", + "mod(00B00B", + "mod(10B00B", + "mod(20B00B", + "mod(30B00B", + "mod(10B10B", + "mod(20B20B", + "mod(30B30B", + "min(00B00B", + "min(10B00B", + "min(20B00B", + "min(30B00B", + "min(10B10B", + "min(20B20B", + "min(30B30B", + "min(00D00D", + "min(10D10D", + "min(20D20D", + "min(30D30D", + "min(10D00D", + "min(20D00D", + "min(30D00D", + "min(00E00E", + "min(10E10E", + "min(20E20E", + "min(30E30E", + "min(10E00E", + "min(20E00E", + "min(30E00E", + "max(00B00B", + "max(10B00B", + "max(20B00B", + "max(30B00B", + "max(10B10B", + "max(20B20B", + "max(30B30B", + "max(00D00D", + "max(10D10D", + "max(20D20D", + "max(30D30D", + "max(10D00D", + "max(20D00D", + "max(30D00D", + "max(00E00E", + "max(10E10E", + "max(20E20E", + "max(30E30E", + "max(10E00E", + "max(20E00E", + "max(30E00E", + "clamp(00B00B00B", + "clamp(10B00B00B", + "clamp(20B00B00B", + "clamp(30B00B00B", + "clamp(10B10B10B", + "clamp(20B20B20B", + "clamp(30B30B30B", + "clamp(00D00D00D", + "clamp(10D00D00D", + "clamp(20D00D00D", + "clamp(30D00D00D", + "clamp(10D10D10D", + "clamp(20D20D20D", + "clamp(30D30D30D", + "clamp(00E00E00E", + "clamp(10E00E00E", + "clamp(20E00E00E", + "clamp(30E00E00E", + "clamp(10E10E10E", + "clamp(20E20E20E", + "clamp(30E30E30E", + "mix(00B00B00B", + "mix(10B10B00B", + "mix(20B20B00B", + "mix(30B30B00B", + "mix(10B10B10B", + "mix(20B20B20B", + "mix(30B30B30B", + "mix(00B00B00F", + "mix(10B10B10F", + "mix(20B20B20F", + "mix(30B30B30F", + "mix(00D00D00F", + "mix(10D10D10F", + "mix(20D20D20F", + "mix(30D30D30F", + "mix(00E00E00F", + "mix(10E10E10F", + "mix(20E20E20F", + "mix(30E30E30F", + "mix(00F00F00F", + "mix(10F10F10F", + "mix(20F20F20F", + "mix(30F30F30F", + "step(00B00B", + "step(10B10B", + "step(20B20B", + "step(30B30B", + "step(00B10B", + "step(00B20B", + "step(00B30B", + "smoothstep(00B00B00B", + "smoothstep(10B10B10B", + "smoothstep(20B20B20B", + "smoothstep(30B30B30B", + "smoothstep(00B00B10B", + "smoothstep(00B00B20B", + "smoothstep(00B00B30B", + "modf(00B00B", + "modf(10B10B", + "modf(20B20B", + "modf(30B30B", + "isnan(00B", + "isnan(10B", + "isnan(20B", + "isnan(30B", + "isinf(00B", + "isinf(10B", + "isinf(20B", + "isinf(30B", + "floatBitsToInt(00B", + "floatBitsToInt(10B", + "floatBitsToInt(20B", + "floatBitsToInt(30B", + "floatBitsToUint(00B", + "floatBitsToUint(10B", + "floatBitsToUint(20B", + "floatBitsToUint(30B", + "intBitsToFloat(00D", + "intBitsToFloat(10D", + "intBitsToFloat(20D", + "intBitsToFloat(30D", + "uintBitsToFloat(00E", + "uintBitsToFloat(10E", + "uintBitsToFloat(20E", + "uintBitsToFloat(30E", + "fma(00B00B00B", + "fma(10B10B10B", + "fma(20B20B20B", + "fma(30B30B30B", + "frexp(00B00D", + "frexp(10B10D", + "frexp(20B20D", + "frexp(30B30D", + "ldexp(00B00D", + "ldexp(10B10D", + "ldexp(20B20D", + "ldexp(30B30D", + "packSnorm2x16(10B", + "packHalf2x16(10B", + "unpackSnorm2x16(00E", + "unpackHalf2x16(00E", + "packUnorm2x16(10B", + "unpackUnorm2x16(00E", + "packUnorm4x8(30B", + "packSnorm4x8(30B", + "unpackUnorm4x8(00E", + "unpackSnorm4x8(00E", + "length(00B", + "length(10B", + "length(20B", + "length(30B", + "distance(00B00B", + "distance(10B10B", + "distance(20B20B", + "distance(30B30B", + "dot(00B00B", + "dot(10B10B", + "dot(20B20B", + "dot(30B30B", + "cross(20B20B", + "normalize(00B", + "normalize(10B", + "normalize(20B", + "normalize(30B", + "faceforward(00B00B00B", + "faceforward(10B10B10B", + "faceforward(20B20B20B", + "faceforward(30B30B30B", + "reflect(00B00B", + "reflect(10B10B", + "reflect(20B20B", + "reflect(30B30B", + "refract(00B00B00B", + "refract(10B10B00B", + "refract(20B20B00B", + "refract(30B30B00B", + "matrixCompMult(50B50B", + "matrixCompMult(A0BA0B", + "matrixCompMult(F0BF0B", + "matrixCompMult(90B90B", + "matrixCompMult(60B60B", + "matrixCompMult(D0BD0B", + "matrixCompMult(70B70B", + "matrixCompMult(E0BE0B", + "matrixCompMult(B0BB0B", + "outerProduct(10B10B", + "outerProduct(20B20B", + "outerProduct(30B30B", + "outerProduct(20B10B", + "outerProduct(10B20B", + "outerProduct(30B10B", + "outerProduct(10B30B", + "outerProduct(30B20B", + "outerProduct(20B30B", + "transpose(50B", + "transpose(A0B", + "transpose(F0B", + "transpose(60B", + "transpose(90B", + "transpose(70B", + "transpose(D0B", + "transpose(B0B", + "transpose(E0B", + "determinant(50B", + "determinant(A0B", + "determinant(F0B", + "inverse(50B", + "inverse(A0B", + "inverse(F0B", + "lessThan(10B10B", + "lessThan(20B20B", + "lessThan(30B30B", + "lessThan(10D10D", + "lessThan(20D20D", + "lessThan(30D30D", + "lessThan(10E10E", + "lessThan(20E20E", + "lessThan(30E30E", + "lessThanEqual(10B10B", + "lessThanEqual(20B20B", + "lessThanEqual(30B30B", + "lessThanEqual(10D10D", + "lessThanEqual(20D20D", + "lessThanEqual(30D30D", + "lessThanEqual(10E10E", + "lessThanEqual(20E20E", + "lessThanEqual(30E30E", + "greaterThan(10B10B", + "greaterThan(20B20B", + "greaterThan(30B30B", + "greaterThan(10D10D", + "greaterThan(20D20D", + "greaterThan(30D30D", + "greaterThan(10E10E", + "greaterThan(20E20E", + "greaterThan(30E30E", + "greaterThanEqual(10B10B", + "greaterThanEqual(20B20B", + "greaterThanEqual(30B30B", + "greaterThanEqual(10D10D", + "greaterThanEqual(20D20D", + "greaterThanEqual(30D30D", + "greaterThanEqual(10E10E", + "greaterThanEqual(20E20E", + "greaterThanEqual(30E30E", + "equal(10B10B", + "equal(20B20B", + "equal(30B30B", + "equal(10D10D", + "equal(20D20D", + "equal(30D30D", + "equal(10E10E", + "equal(20E20E", + "equal(30E30E", + "equal(10F10F", + "equal(20F20F", + "equal(30F30F", + "notEqual(10B10B", + "notEqual(20B20B", + "notEqual(30B30B", + "notEqual(10D10D", + "notEqual(20D20D", + "notEqual(30D30D", + "notEqual(10E10E", + "notEqual(20E20E", + "notEqual(30E30E", + "notEqual(10F10F", + "notEqual(20F20F", + "notEqual(30F30F", + "any(10F", + "any(20F", + "any(30F", + "all(10F", + "all(20F", + "all(30F", + "not(10F", + "not(20F", + "not(30F", + "bitfieldExtract(00D00D00D", + "bitfieldExtract(10D00D00D", + "bitfieldExtract(20D00D00D", + "bitfieldExtract(30D00D00D", + "bitfieldExtract(00E00D00D", + "bitfieldExtract(10E00D00D", + "bitfieldExtract(20E00D00D", + "bitfieldExtract(30E00D00D", + "bitfieldInsert(00D00D00D00D", + "bitfieldInsert(10D10D00D00D", + "bitfieldInsert(20D20D00D00D", + "bitfieldInsert(30D30D00D00D", + "bitfieldInsert(00E00E00D00D", + "bitfieldInsert(10E10E00D00D", + "bitfieldInsert(20E20E00D00D", + "bitfieldInsert(30E30E00D00D", + "bitfieldReverse(00D", + "bitfieldReverse(10D", + "bitfieldReverse(20D", + "bitfieldReverse(30D", + "bitfieldReverse(00E", + "bitfieldReverse(10E", + "bitfieldReverse(20E", + "bitfieldReverse(30E", + "bitCount(00D", + "bitCount(10D", + "bitCount(20D", + "bitCount(30D", + "bitCount(00E", + "bitCount(10E", + "bitCount(20E", + "bitCount(30E", + "findLSB(00D", + "findLSB(10D", + "findLSB(20D", + "findLSB(30D", + "findLSB(00E", + "findLSB(10E", + "findLSB(20E", + "findLSB(30E", + "findMSB(00D", + "findMSB(10D", + "findMSB(20D", + "findMSB(30D", + "findMSB(00E", + "findMSB(10E", + "findMSB(20E", + "findMSB(30E", + "uaddCarry(00E00E00E", + "uaddCarry(10E10E10E", + "uaddCarry(20E20E20E", + "uaddCarry(30E30E30E", + "usubBorrow(00E00E00E", + "usubBorrow(10E10E10E", + "usubBorrow(20E20E20E", + "usubBorrow(30E30E30E", + "umulExtended(00E00E00E00E", + "umulExtended(10E10E10E10E", + "umulExtended(20E20E20E20E", + "umulExtended(30E30E30E30E", + "imulExtended(00D00D00D00D", + "imulExtended(10D10D10D10D", + "imulExtended(20D20D20D20D", + "imulExtended(30D30D30D30D", + "texture2D(00I10B", + "texture2DProj(00I20B", + "texture2DProj(00I30B", + "textureCube(00K20B", + "texture3D(00J20B", + "texture3DProj(00J30B", + "shadow2DEXT(00d20B", + "shadow2DProjEXT(00d30B", + "texture2D(00M10B", + "texture2DProj(00M20B", + "texture2DProj(00M30B", + "texture2DRect(00O10B", + "texture2DRectProj(00O20B", + "texture2DRectProj(00O30B", + "texture2DGradEXT(00I10B10B10B", + "texture2DProjGradEXT(00I20B10B10B", + "texture2DProjGradEXT(00I30B10B10B", + "textureCubeGradEXT(00K20B20B20B", + "textureVideoWEBGL(00y10B", + "texture2D(00I10B00B", + "texture2DProj(00I20B00B", + "texture2DProj(00I30B00B", + "textureCube(00K20B00B", + "texture3D(00J20B00B", + "texture3DProj(00J30B00B", + "texture3DLod(00J20B00B", + "texture3DProjLod(00J30B00B", + "texture2DLod(00I10B00B", + "texture2DProjLod(00I20B00B", + "texture2DProjLod(00I30B00B", + "textureCubeLod(00K20B00B", + "texture2DLodEXT(00I10B00B", + "texture2DProjLodEXT(00I20B00B", + "texture2DProjLodEXT(00I30B00B", + "textureCubeLodEXT(00K20B00B", + "texture(00I10B", + "texture(00R10B", + "texture(00X10B", + "texture(00J20B", + "texture(00S20B", + "texture(00Y20B", + "texture(00K20B", + "texture(00T20B", + "texture(00Z20B", + "texture(00L20B", + "texture(00U20B", + "texture(00a20B", + "texture(00d20B", + "texture(00e30B", + "texture(00f30B", + "texture(00k30B", + "texture(00s30B", + "texture(00x30B", + "texture(00l30B00B", + "texture(00M10B", + "texture(00N10B", + "texture(00O10B", + "texture(00y10B", + "textureProj(00I20B", + "textureProj(00R20B", + "textureProj(00X20B", + "textureProj(00I30B", + "textureProj(00R30B", + "textureProj(00X30B", + "textureProj(00J30B", + "textureProj(00S30B", + "textureProj(00Y30B", + "textureProj(00d30B", + "textureProj(00M20B", + "textureProj(00M30B", + "textureProj(00N20B", + "textureProj(00N30B", + "textureProj(00O20B", + "textureProj(00O30B", + "textureLod(00I10B00B", + "textureLod(00R10B00B", + "textureLod(00X10B00B", + "textureLod(00J20B00B", + "textureLod(00S20B00B", + "textureLod(00Y20B00B", + "textureLod(00K20B00B", + "textureLod(00T20B00B", + "textureLod(00Z20B00B", + "textureLod(00L20B00B", + "textureLod(00U20B00B", + "textureLod(00a20B00B", + "textureLod(00d20B00B", + "textureLod(00k30B00B", + "textureLod(00s30B00B", + "textureLod(00x30B00B", + "textureSize(00I00D", + "textureSize(00R00D", + "textureSize(00X00D", + "textureSize(00J00D", + "textureSize(00S00D", + "textureSize(00Y00D", + "textureSize(00K00D", + "textureSize(00T00D", + "textureSize(00Z00D", + "textureSize(00L00D", + "textureSize(00U00D", + "textureSize(00a00D", + "textureSize(00d00D", + "textureSize(00e00D", + "textureSize(00f00D", + "textureSize(00k00D", + "textureSize(00s00D", + "textureSize(00x00D", + "textureSize(00l00D", + "textureSize(00j", + "textureSize(00r", + "textureSize(00w", + "textureSize(00P", + "textureSize(00V", + "textureSize(00b", + "textureSize(00Q", + "textureSize(00W", + "textureSize(00c", + "textureSize(00M00D", + "textureSize(00N00D", + "textureProjLod(00I20B00B", + "textureProjLod(00R20B00B", + "textureProjLod(00X20B00B", + "textureProjLod(00I30B00B", + "textureProjLod(00R30B00B", + "textureProjLod(00X30B00B", + "textureProjLod(00J30B00B", + "textureProjLod(00S30B00B", + "textureProjLod(00Y30B00B", + "textureProjLod(00d30B00B", + "texelFetch(00I10D00D", + "texelFetch(00R10D00D", + "texelFetch(00X10D00D", + "texelFetch(00J20D00D", + "texelFetch(00S20D00D", + "texelFetch(00Y20D00D", + "texelFetch(00L20D00D", + "texelFetch(00U20D00D", + "texelFetch(00a20D00D", + "texelFetch(00j00D", + "texelFetch(00r00D", + "texelFetch(00w00D", + "texelFetch(00P10D00D", + "texelFetch(00V10D00D", + "texelFetch(00b10D00D", + "texelFetch(00Q20D00D", + "texelFetch(00W20D00D", + "texelFetch(00c20D00D", + "texelFetch(00M10D00D", + "texelFetch(00N10D00D", + "textureGrad(00I10B10B10B", + "textureGrad(00R10B10B10B", + "textureGrad(00X10B10B10B", + "textureGrad(00J20B20B20B", + "textureGrad(00S20B20B20B", + "textureGrad(00Y20B20B20B", + "textureGrad(00K20B20B20B", + "textureGrad(00T20B20B20B", + "textureGrad(00Z20B20B20B", + "textureGrad(00d20B10B10B", + "textureGrad(00e30B20B20B", + "textureGrad(00L20B10B10B", + "textureGrad(00U20B10B10B", + "textureGrad(00a20B10B10B", + "textureGrad(00f30B10B10B", + "textureGrad(00k30B20B20B", + "textureGrad(00s30B20B20B", + "textureGrad(00x30B20B20B", + "textureProjGrad(00I20B10B10B", + "textureProjGrad(00R20B10B10B", + "textureProjGrad(00X20B10B10B", + "textureProjGrad(00I30B10B10B", + "textureProjGrad(00R30B10B10B", + "textureProjGrad(00X30B10B10B", + "textureProjGrad(00J30B20B20B", + "textureProjGrad(00S30B20B20B", + "textureProjGrad(00Y30B20B20B", + "textureProjGrad(00d30B10B10B", + "texture(00I10B00B", + "texture(00R10B00B", + "texture(00X10B00B", + "texture(00J20B00B", + "texture(00S20B00B", + "texture(00Y20B00B", + "texture(00K20B00B", + "texture(00T20B00B", + "texture(00Z20B00B", + "texture(00L20B00B", + "texture(00U20B00B", + "texture(00a20B00B", + "textureProj(00I20B00B", + "textureProj(00R20B00B", + "textureProj(00X20B00B", + "textureProj(00I30B00B", + "textureProj(00R30B00B", + "textureProj(00X30B00B", + "textureProj(00J30B00B", + "textureProj(00S30B00B", + "textureProj(00Y30B00B", + "texture(00d20B00B", + "texture(00e30B00B", + "textureProj(00d30B00B", + "texture(00k30B00B", + "texture(00s30B00B", + "texture(00x30B00B", + "texture(00M10B00B", + "textureProj(00M20B00B", + "textureProj(00M30B00B", + "texture(00N10B00B", + "textureProj(00N20B00B", + "textureProj(00N30B00B", + "textureOffset(00I10B10D", + "textureOffset(00R10B10D", + "textureOffset(00X10B10D", + "textureOffset(00J20B20D", + "textureOffset(00S20B20D", + "textureOffset(00Y20B20D", + "textureOffset(00d20B10D", + "textureOffset(00L20B10D", + "textureOffset(00U20B10D", + "textureOffset(00a20B10D", + "textureProjOffset(00I20B10D", + "textureProjOffset(00R20B10D", + "textureProjOffset(00X20B10D", + "textureProjOffset(00I30B10D", + "textureProjOffset(00R30B10D", + "textureProjOffset(00X30B10D", + "textureProjOffset(00J30B20D", + "textureProjOffset(00S30B20D", + "textureProjOffset(00Y30B20D", + "textureProjOffset(00d30B10D", + "textureLodOffset(00I10B00B10D", + "textureLodOffset(00R10B00B10D", + "textureLodOffset(00X10B00B10D", + "textureLodOffset(00J20B00B20D", + "textureLodOffset(00S20B00B20D", + "textureLodOffset(00Y20B00B20D", + "textureLodOffset(00d20B00B10D", + "textureLodOffset(00L20B00B10D", + "textureLodOffset(00U20B00B10D", + "textureLodOffset(00a20B00B10D", + "textureProjLodOffset(00I20B00B10D", + "textureProjLodOffset(00R20B00B10D", + "textureProjLodOffset(00X20B00B10D", + "textureProjLodOffset(00I30B00B10D", + "textureProjLodOffset(00R30B00B10D", + "textureProjLodOffset(00X30B00B10D", + "textureProjLodOffset(00J30B00B20D", + "textureProjLodOffset(00S30B00B20D", + "textureProjLodOffset(00Y30B00B20D", + "textureProjLodOffset(00d30B00B10D", + "texelFetchOffset(00I10D00D10D", + "texelFetchOffset(00R10D00D10D", + "texelFetchOffset(00X10D00D10D", + "texelFetchOffset(00J20D00D20D", + "texelFetchOffset(00S20D00D20D", + "texelFetchOffset(00Y20D00D20D", + "texelFetchOffset(00L20D00D10D", + "texelFetchOffset(00U20D00D10D", + "texelFetchOffset(00a20D00D10D", + "textureGradOffset(00I10B10B10B10D", + "textureGradOffset(00R10B10B10B10D", + "textureGradOffset(00X10B10B10B10D", + "textureGradOffset(00J20B20B20B20D", + "textureGradOffset(00S20B20B20B20D", + "textureGradOffset(00Y20B20B20B20D", + "textureGradOffset(00d20B10B10B10D", + "textureGradOffset(00L20B10B10B10D", + "textureGradOffset(00U20B10B10B10D", + "textureGradOffset(00a20B10B10B10D", + "textureGradOffset(00f30B10B10B10D", + "textureProjGradOffset(00I20B10B10B10D", + "textureProjGradOffset(00R20B10B10B10D", + "textureProjGradOffset(00X20B10B10B10D", + "textureProjGradOffset(00I30B10B10B10D", + "textureProjGradOffset(00R30B10B10B10D", + "textureProjGradOffset(00X30B10B10B10D", + "textureProjGradOffset(00J30B20B20B20D", + "textureProjGradOffset(00S30B20B20B20D", + "textureProjGradOffset(00Y30B20B20B20D", + "textureProjGradOffset(00d30B10B10B10D", + "textureOffset(00I10B10D00B", + "textureOffset(00R10B10D00B", + "textureOffset(00X10B10D00B", + "textureOffset(00J20B20D00B", + "textureOffset(00S20B20D00B", + "textureOffset(00Y20B20D00B", + "textureOffset(00d20B10D00B", + "textureOffset(00L20B10D00B", + "textureOffset(00U20B10D00B", + "textureOffset(00a20B10D00B", + "textureProjOffset(00I20B10D00B", + "textureProjOffset(00R20B10D00B", + "textureProjOffset(00X20B10D00B", + "textureProjOffset(00I30B10D00B", + "textureProjOffset(00R30B10D00B", + "textureProjOffset(00X30B10D00B", + "textureProjOffset(00J30B20D00B", + "textureProjOffset(00S30B20D00B", + "textureProjOffset(00Y30B20D00B", + "textureProjOffset(00d30B10D00B", + "textureGather(00I10B", + "textureGather(00R10B", + "textureGather(00X10B", + "textureGather(00I10B00D", + "textureGather(00R10B00D", + "textureGather(00X10B00D", + "textureGather(00L20B", + "textureGather(00U20B", + "textureGather(00a20B", + "textureGather(00L20B00D", + "textureGather(00U20B00D", + "textureGather(00a20B00D", + "textureGather(00K20B", + "textureGather(00T20B", + "textureGather(00Z20B", + "textureGather(00K20B00D", + "textureGather(00T20B00D", + "textureGather(00Z20B00D", + "textureGather(00k30B", + "textureGather(00s30B", + "textureGather(00x30B", + "textureGather(00k30B00D", + "textureGather(00s30B00D", + "textureGather(00x30B00D", + "textureGather(00l30B00B", + "textureGather(00d10B", + "textureGather(00d10B00B", + "textureGather(00f20B", + "textureGather(00f20B00B", + "textureGather(00e20B", + "textureGather(00e20B00B", + "textureGatherOffset(00I10B10D", + "textureGatherOffset(00R10B10D", + "textureGatherOffset(00X10B10D", + "textureGatherOffset(00L20B10D", + "textureGatherOffset(00U20B10D", + "textureGatherOffset(00a20B10D", + "textureGatherOffset(00d10B00B10D", + "textureGatherOffset(00f20B00B10D", + "textureGatherOffset(00I10B10D00D", + "textureGatherOffset(00R10B10D00D", + "textureGatherOffset(00X10B10D00D", + "textureGatherOffset(00L20B10D00D", + "textureGatherOffset(00U20B10D00D", + "textureGatherOffset(00a20B10D00D", + "textureGatherOffsets(00I10B10Dx4", + "textureGatherOffsets(00R10B10Dx4", + "textureGatherOffsets(00X10B10Dx4", + "textureGatherOffsets(00L20B10Dx4", + "textureGatherOffsets(00U20B10Dx4", + "textureGatherOffsets(00a20B10Dx4", + "textureGatherOffsets(00d10B00B10Dx4", + "textureGatherOffsets(00f20B00B10Dx4", + "textureGatherOffsets(00I10B10Dx400D", + "textureGatherOffsets(00R10B10Dx400D", + "textureGatherOffsets(00X10B10Dx400D", + "textureGatherOffsets(00L20B10Dx400D", + "textureGatherOffsets(00U20B10Dx400D", + "textureGatherOffsets(00a20B10Dx400D", + "rgb_2_yuv(20B00H", + "yuv_2_rgb(20B00H", + "dFdx(00B", + "dFdx(10B", + "dFdx(20B", + "dFdx(30B", + "dFdy(00B", + "dFdy(10B", + "dFdy(20B", + "dFdy(30B", + "fwidth(00B", + "fwidth(10B", + "fwidth(20B", + "fwidth(30B", + "interpolateAtCentroid(00B", + "interpolateAtCentroid(10B", + "interpolateAtCentroid(20B", + "interpolateAtCentroid(30B", + "interpolateAtSample(00B00D", + "interpolateAtSample(10B00D", + "interpolateAtSample(20B00D", + "interpolateAtSample(30B00D", + "interpolateAtOffset(00B10B", + "interpolateAtOffset(10B10B", + "interpolateAtOffset(20B10B", + "interpolateAtOffset(30B10B", + "atomicCounter(00G", + "atomicCounterIncrement(00G", + "atomicCounterDecrement(00G", + "atomicAdd(00E00E", + "atomicAdd(00D00D", + "atomicMin(00E00E", + "atomicMin(00D00D", + "atomicMax(00E00E", + "atomicMax(00D00D", + "atomicAnd(00E00E", + "atomicAnd(00D00D", + "atomicOr(00E00E", + "atomicOr(00D00D", + "atomicXor(00E00E", + "atomicXor(00D00D", + "atomicExchange(00E00E", + "atomicExchange(00D00D", + "atomicCompSwap(00E00E00E", + "atomicCompSwap(00D00D00D", + "imageSize(00z", + "imageSize(01K", + "imageSize(01V", + "imageSize(01A", + "imageSize(01L", + "imageSize(01W", + "imageSize(01B", + "imageSize(01M", + "imageSize(01X", + "imageSize(01C", + "imageSize(01N", + "imageSize(01Y", + "imageSize(01H", + "imageSize(01S", + "imageSize(01d", + "imageSize(01J", + "imageSize(01U", + "imageSize(01f", + "imageStore(00z10D30B", + "imageStore(01K10D30D", + "imageStore(01V10D30E", + "imageStore(01A20D30B", + "imageStore(01L20D30D", + "imageStore(01W20D30E", + "imageStore(01B20D30B", + "imageStore(01M20D30D", + "imageStore(01X20D30E", + "imageStore(01C20D30B", + "imageStore(01N20D30D", + "imageStore(01Y20D30E", + "imageStore(01H20D30B", + "imageStore(01S20D30D", + "imageStore(01d20D30E", + "imageStore(01J00D30B", + "imageStore(01U00D30D", + "imageStore(01f00D30E", + "imageLoad(00z10D", + "imageLoad(01K10D", + "imageLoad(01V10D", + "imageLoad(01A20D", + "imageLoad(01L20D", + "imageLoad(01W20D", + "imageLoad(01B20D", + "imageLoad(01M20D", + "imageLoad(01X20D", + "imageLoad(01C20D", + "imageLoad(01N20D", + "imageLoad(01Y20D", + "imageLoad(01H20D", + "imageLoad(01S20D", + "imageLoad(01d20D", + "imageLoad(01J00D", + "imageLoad(01U00D", + "imageLoad(01f00D", + "imageAtomicAdd(00z10D00E", + "imageAtomicAdd(01K10D00E", + "imageAtomicAdd(01V10D00E", + "imageAtomicAdd(01A20D00E", + "imageAtomicAdd(01L20D00E", + "imageAtomicAdd(01W20D00E", + "imageAtomicAdd(01C20D00E", + "imageAtomicAdd(01N20D00E", + "imageAtomicAdd(01Y20D00E", + "imageAtomicAdd(01J00D00E", + "imageAtomicAdd(01U00D00E", + "imageAtomicAdd(01f00D00E", + "imageAtomicAdd(01B20D00E", + "imageAtomicAdd(01M20D00E", + "imageAtomicAdd(01X20D00E", + "imageAtomicAdd(01H20D00E", + "imageAtomicAdd(01S20D00E", + "imageAtomicAdd(01d20D00E", + "imageAtomicAdd(01D00D00E", + "imageAtomicAdd(01O00D00E", + "imageAtomicAdd(01Z00D00E", + "imageAtomicAdd(01E10D00E", + "imageAtomicAdd(01P10D00E", + "imageAtomicAdd(01a10D00E", + "imageAtomicAdd(01I10D00E", + "imageAtomicAdd(01T10D00E", + "imageAtomicAdd(01e10D00E", + "imageAtomicAdd(01F10D00D00E", + "imageAtomicAdd(01Q10D00D00E", + "imageAtomicAdd(01b10D00D00E", + "imageAtomicAdd(01G20D00D00E", + "imageAtomicAdd(01R20D00D00E", + "imageAtomicAdd(01c20D00D00E", + "imageAtomicAdd(00z10D00D", + "imageAtomicAdd(01K10D00D", + "imageAtomicAdd(01V10D00D", + "imageAtomicAdd(01A20D00D", + "imageAtomicAdd(01L20D00D", + "imageAtomicAdd(01W20D00D", + "imageAtomicAdd(01C20D00D", + "imageAtomicAdd(01N20D00D", + "imageAtomicAdd(01Y20D00D", + "imageAtomicAdd(01J00D00D", + "imageAtomicAdd(01U00D00D", + "imageAtomicAdd(01f00D00D", + "imageAtomicAdd(01B20D00D", + "imageAtomicAdd(01M20D00D", + "imageAtomicAdd(01X20D00D", + "imageAtomicAdd(01H20D00D", + "imageAtomicAdd(01S20D00D", + "imageAtomicAdd(01d20D00D", + "imageAtomicAdd(01D00D00D", + "imageAtomicAdd(01O00D00D", + "imageAtomicAdd(01Z00D00D", + "imageAtomicAdd(01E10D00D", + "imageAtomicAdd(01P10D00D", + "imageAtomicAdd(01a10D00D", + "imageAtomicAdd(01I10D00D", + "imageAtomicAdd(01T10D00D", + "imageAtomicAdd(01e10D00D", + "imageAtomicAdd(01F10D00D00D", + "imageAtomicAdd(01Q10D00D00D", + "imageAtomicAdd(01b10D00D00D", + "imageAtomicAdd(01G20D00D00D", + "imageAtomicAdd(01R20D00D00D", + "imageAtomicAdd(01c20D00D00D", + "imageAtomicMin(00z10D00E", + "imageAtomicMin(01K10D00E", + "imageAtomicMin(01V10D00E", + "imageAtomicMin(01A20D00E", + "imageAtomicMin(01L20D00E", + "imageAtomicMin(01W20D00E", + "imageAtomicMin(01C20D00E", + "imageAtomicMin(01N20D00E", + "imageAtomicMin(01Y20D00E", + "imageAtomicMin(01J00D00E", + "imageAtomicMin(01U00D00E", + "imageAtomicMin(01f00D00E", + "imageAtomicMin(01B20D00E", + "imageAtomicMin(01M20D00E", + "imageAtomicMin(01X20D00E", + "imageAtomicMin(01H20D00E", + "imageAtomicMin(01S20D00E", + "imageAtomicMin(01d20D00E", + "imageAtomicMin(01D00D00E", + "imageAtomicMin(01O00D00E", + "imageAtomicMin(01Z00D00E", + "imageAtomicMin(01E10D00E", + "imageAtomicMin(01P10D00E", + "imageAtomicMin(01a10D00E", + "imageAtomicMin(01I10D00E", + "imageAtomicMin(01T10D00E", + "imageAtomicMin(01e10D00E", + "imageAtomicMin(01F10D00D00E", + "imageAtomicMin(01Q10D00D00E", + "imageAtomicMin(01b10D00D00E", + "imageAtomicMin(01G20D00D00E", + "imageAtomicMin(01R20D00D00E", + "imageAtomicMin(01c20D00D00E", + "imageAtomicMin(00z10D00D", + "imageAtomicMin(01K10D00D", + "imageAtomicMin(01V10D00D", + "imageAtomicMin(01A20D00D", + "imageAtomicMin(01L20D00D", + "imageAtomicMin(01W20D00D", + "imageAtomicMin(01C20D00D", + "imageAtomicMin(01N20D00D", + "imageAtomicMin(01Y20D00D", + "imageAtomicMin(01J00D00D", + "imageAtomicMin(01U00D00D", + "imageAtomicMin(01f00D00D", + "imageAtomicMin(01B20D00D", + "imageAtomicMin(01M20D00D", + "imageAtomicMin(01X20D00D", + "imageAtomicMin(01H20D00D", + "imageAtomicMin(01S20D00D", + "imageAtomicMin(01d20D00D", + "imageAtomicMin(01D00D00D", + "imageAtomicMin(01O00D00D", + "imageAtomicMin(01Z00D00D", + "imageAtomicMin(01E10D00D", + "imageAtomicMin(01P10D00D", + "imageAtomicMin(01a10D00D", + "imageAtomicMin(01I10D00D", + "imageAtomicMin(01T10D00D", + "imageAtomicMin(01e10D00D", + "imageAtomicMin(01F10D00D00D", + "imageAtomicMin(01Q10D00D00D", + "imageAtomicMin(01b10D00D00D", + "imageAtomicMin(01G20D00D00D", + "imageAtomicMin(01R20D00D00D", + "imageAtomicMin(01c20D00D00D", + "imageAtomicMax(00z10D00E", + "imageAtomicMax(01K10D00E", + "imageAtomicMax(01V10D00E", + "imageAtomicMax(01A20D00E", + "imageAtomicMax(01L20D00E", + "imageAtomicMax(01W20D00E", + "imageAtomicMax(01C20D00E", + "imageAtomicMax(01N20D00E", + "imageAtomicMax(01Y20D00E", + "imageAtomicMax(01J00D00E", + "imageAtomicMax(01U00D00E", + "imageAtomicMax(01f00D00E", + "imageAtomicMax(01B20D00E", + "imageAtomicMax(01M20D00E", + "imageAtomicMax(01X20D00E", + "imageAtomicMax(01H20D00E", + "imageAtomicMax(01S20D00E", + "imageAtomicMax(01d20D00E", + "imageAtomicMax(01D00D00E", + "imageAtomicMax(01O00D00E", + "imageAtomicMax(01Z00D00E", + "imageAtomicMax(01E10D00E", + "imageAtomicMax(01P10D00E", + "imageAtomicMax(01a10D00E", + "imageAtomicMax(01I10D00E", + "imageAtomicMax(01T10D00E", + "imageAtomicMax(01e10D00E", + "imageAtomicMax(01F10D00D00E", + "imageAtomicMax(01Q10D00D00E", + "imageAtomicMax(01b10D00D00E", + "imageAtomicMax(01G20D00D00E", + "imageAtomicMax(01R20D00D00E", + "imageAtomicMax(01c20D00D00E", + "imageAtomicMax(00z10D00D", + "imageAtomicMax(01K10D00D", + "imageAtomicMax(01V10D00D", + "imageAtomicMax(01A20D00D", + "imageAtomicMax(01L20D00D", + "imageAtomicMax(01W20D00D", + "imageAtomicMax(01C20D00D", + "imageAtomicMax(01N20D00D", + "imageAtomicMax(01Y20D00D", + "imageAtomicMax(01J00D00D", + "imageAtomicMax(01U00D00D", + "imageAtomicMax(01f00D00D", + "imageAtomicMax(01B20D00D", + "imageAtomicMax(01M20D00D", + "imageAtomicMax(01X20D00D", + "imageAtomicMax(01H20D00D", + "imageAtomicMax(01S20D00D", + "imageAtomicMax(01d20D00D", + "imageAtomicMax(01D00D00D", + "imageAtomicMax(01O00D00D", + "imageAtomicMax(01Z00D00D", + "imageAtomicMax(01E10D00D", + "imageAtomicMax(01P10D00D", + "imageAtomicMax(01a10D00D", + "imageAtomicMax(01I10D00D", + "imageAtomicMax(01T10D00D", + "imageAtomicMax(01e10D00D", + "imageAtomicMax(01F10D00D00D", + "imageAtomicMax(01Q10D00D00D", + "imageAtomicMax(01b10D00D00D", + "imageAtomicMax(01G20D00D00D", + "imageAtomicMax(01R20D00D00D", + "imageAtomicMax(01c20D00D00D", + "imageAtomicAnd(00z10D00E", + "imageAtomicAnd(01K10D00E", + "imageAtomicAnd(01V10D00E", + "imageAtomicAnd(01A20D00E", + "imageAtomicAnd(01L20D00E", + "imageAtomicAnd(01W20D00E", + "imageAtomicAnd(01C20D00E", + "imageAtomicAnd(01N20D00E", + "imageAtomicAnd(01Y20D00E", + "imageAtomicAnd(01J00D00E", + "imageAtomicAnd(01U00D00E", + "imageAtomicAnd(01f00D00E", + "imageAtomicAnd(01B20D00E", + "imageAtomicAnd(01M20D00E", + "imageAtomicAnd(01X20D00E", + "imageAtomicAnd(01H20D00E", + "imageAtomicAnd(01S20D00E", + "imageAtomicAnd(01d20D00E", + "imageAtomicAnd(01D00D00E", + "imageAtomicAnd(01O00D00E", + "imageAtomicAnd(01Z00D00E", + "imageAtomicAnd(01E10D00E", + "imageAtomicAnd(01P10D00E", + "imageAtomicAnd(01a10D00E", + "imageAtomicAnd(01I10D00E", + "imageAtomicAnd(01T10D00E", + "imageAtomicAnd(01e10D00E", + "imageAtomicAnd(01F10D00D00E", + "imageAtomicAnd(01Q10D00D00E", + "imageAtomicAnd(01b10D00D00E", + "imageAtomicAnd(01G20D00D00E", + "imageAtomicAnd(01R20D00D00E", + "imageAtomicAnd(01c20D00D00E", + "imageAtomicAnd(00z10D00D", + "imageAtomicAnd(01K10D00D", + "imageAtomicAnd(01V10D00D", + "imageAtomicAnd(01A20D00D", + "imageAtomicAnd(01L20D00D", + "imageAtomicAnd(01W20D00D", + "imageAtomicAnd(01C20D00D", + "imageAtomicAnd(01N20D00D", + "imageAtomicAnd(01Y20D00D", + "imageAtomicAnd(01J00D00D", + "imageAtomicAnd(01U00D00D", + "imageAtomicAnd(01f00D00D", + "imageAtomicAnd(01B20D00D", + "imageAtomicAnd(01M20D00D", + "imageAtomicAnd(01X20D00D", + "imageAtomicAnd(01H20D00D", + "imageAtomicAnd(01S20D00D", + "imageAtomicAnd(01d20D00D", + "imageAtomicAnd(01D00D00D", + "imageAtomicAnd(01O00D00D", + "imageAtomicAnd(01Z00D00D", + "imageAtomicAnd(01E10D00D", + "imageAtomicAnd(01P10D00D", + "imageAtomicAnd(01a10D00D", + "imageAtomicAnd(01I10D00D", + "imageAtomicAnd(01T10D00D", + "imageAtomicAnd(01e10D00D", + "imageAtomicAnd(01F10D00D00D", + "imageAtomicAnd(01Q10D00D00D", + "imageAtomicAnd(01b10D00D00D", + "imageAtomicAnd(01G20D00D00D", + "imageAtomicAnd(01R20D00D00D", + "imageAtomicAnd(01c20D00D00D", + "imageAtomicOr(00z10D00E", + "imageAtomicOr(01K10D00E", + "imageAtomicOr(01V10D00E", + "imageAtomicOr(01A20D00E", + "imageAtomicOr(01L20D00E", + "imageAtomicOr(01W20D00E", + "imageAtomicOr(01C20D00E", + "imageAtomicOr(01N20D00E", + "imageAtomicOr(01Y20D00E", + "imageAtomicOr(01J00D00E", + "imageAtomicOr(01U00D00E", + "imageAtomicOr(01f00D00E", + "imageAtomicOr(01B20D00E", + "imageAtomicOr(01M20D00E", + "imageAtomicOr(01X20D00E", + "imageAtomicOr(01H20D00E", + "imageAtomicOr(01S20D00E", + "imageAtomicOr(01d20D00E", + "imageAtomicOr(01D00D00E", + "imageAtomicOr(01O00D00E", + "imageAtomicOr(01Z00D00E", + "imageAtomicOr(01E10D00E", + "imageAtomicOr(01P10D00E", + "imageAtomicOr(01a10D00E", + "imageAtomicOr(01I10D00E", + "imageAtomicOr(01T10D00E", + "imageAtomicOr(01e10D00E", + "imageAtomicOr(01F10D00D00E", + "imageAtomicOr(01Q10D00D00E", + "imageAtomicOr(01b10D00D00E", + "imageAtomicOr(01G20D00D00E", + "imageAtomicOr(01R20D00D00E", + "imageAtomicOr(01c20D00D00E", + "imageAtomicOr(00z10D00D", + "imageAtomicOr(01K10D00D", + "imageAtomicOr(01V10D00D", + "imageAtomicOr(01A20D00D", + "imageAtomicOr(01L20D00D", + "imageAtomicOr(01W20D00D", + "imageAtomicOr(01C20D00D", + "imageAtomicOr(01N20D00D", + "imageAtomicOr(01Y20D00D", + "imageAtomicOr(01J00D00D", + "imageAtomicOr(01U00D00D", + "imageAtomicOr(01f00D00D", + "imageAtomicOr(01B20D00D", + "imageAtomicOr(01M20D00D", + "imageAtomicOr(01X20D00D", + "imageAtomicOr(01H20D00D", + "imageAtomicOr(01S20D00D", + "imageAtomicOr(01d20D00D", + "imageAtomicOr(01D00D00D", + "imageAtomicOr(01O00D00D", + "imageAtomicOr(01Z00D00D", + "imageAtomicOr(01E10D00D", + "imageAtomicOr(01P10D00D", + "imageAtomicOr(01a10D00D", + "imageAtomicOr(01I10D00D", + "imageAtomicOr(01T10D00D", + "imageAtomicOr(01e10D00D", + "imageAtomicOr(01F10D00D00D", + "imageAtomicOr(01Q10D00D00D", + "imageAtomicOr(01b10D00D00D", + "imageAtomicOr(01G20D00D00D", + "imageAtomicOr(01R20D00D00D", + "imageAtomicOr(01c20D00D00D", + "imageAtomicXor(00z10D00E", + "imageAtomicXor(01K10D00E", + "imageAtomicXor(01V10D00E", + "imageAtomicXor(01A20D00E", + "imageAtomicXor(01L20D00E", + "imageAtomicXor(01W20D00E", + "imageAtomicXor(01C20D00E", + "imageAtomicXor(01N20D00E", + "imageAtomicXor(01Y20D00E", + "imageAtomicXor(01J00D00E", + "imageAtomicXor(01U00D00E", + "imageAtomicXor(01f00D00E", + "imageAtomicXor(01B20D00E", + "imageAtomicXor(01M20D00E", + "imageAtomicXor(01X20D00E", + "imageAtomicXor(01H20D00E", + "imageAtomicXor(01S20D00E", + "imageAtomicXor(01d20D00E", + "imageAtomicXor(01D00D00E", + "imageAtomicXor(01O00D00E", + "imageAtomicXor(01Z00D00E", + "imageAtomicXor(01E10D00E", + "imageAtomicXor(01P10D00E", + "imageAtomicXor(01a10D00E", + "imageAtomicXor(01I10D00E", + "imageAtomicXor(01T10D00E", + "imageAtomicXor(01e10D00E", + "imageAtomicXor(01F10D00D00E", + "imageAtomicXor(01Q10D00D00E", + "imageAtomicXor(01b10D00D00E", + "imageAtomicXor(01G20D00D00E", + "imageAtomicXor(01R20D00D00E", + "imageAtomicXor(01c20D00D00E", + "imageAtomicXor(00z10D00D", + "imageAtomicXor(01K10D00D", + "imageAtomicXor(01V10D00D", + "imageAtomicXor(01A20D00D", + "imageAtomicXor(01L20D00D", + "imageAtomicXor(01W20D00D", + "imageAtomicXor(01C20D00D", + "imageAtomicXor(01N20D00D", + "imageAtomicXor(01Y20D00D", + "imageAtomicXor(01J00D00D", + "imageAtomicXor(01U00D00D", + "imageAtomicXor(01f00D00D", + "imageAtomicXor(01B20D00D", + "imageAtomicXor(01M20D00D", + "imageAtomicXor(01X20D00D", + "imageAtomicXor(01H20D00D", + "imageAtomicXor(01S20D00D", + "imageAtomicXor(01d20D00D", + "imageAtomicXor(01D00D00D", + "imageAtomicXor(01O00D00D", + "imageAtomicXor(01Z00D00D", + "imageAtomicXor(01E10D00D", + "imageAtomicXor(01P10D00D", + "imageAtomicXor(01a10D00D", + "imageAtomicXor(01I10D00D", + "imageAtomicXor(01T10D00D", + "imageAtomicXor(01e10D00D", + "imageAtomicXor(01F10D00D00D", + "imageAtomicXor(01Q10D00D00D", + "imageAtomicXor(01b10D00D00D", + "imageAtomicXor(01G20D00D00D", + "imageAtomicXor(01R20D00D00D", + "imageAtomicXor(01c20D00D00D", + "imageAtomicExchange(00z10D00E", + "imageAtomicExchange(01K10D00E", + "imageAtomicExchange(01V10D00E", + "imageAtomicExchange(01A20D00E", + "imageAtomicExchange(01L20D00E", + "imageAtomicExchange(01W20D00E", + "imageAtomicExchange(01C20D00E", + "imageAtomicExchange(01N20D00E", + "imageAtomicExchange(01Y20D00E", + "imageAtomicExchange(01J00D00E", + "imageAtomicExchange(01U00D00E", + "imageAtomicExchange(01f00D00E", + "imageAtomicExchange(01B20D00E", + "imageAtomicExchange(01M20D00E", + "imageAtomicExchange(01X20D00E", + "imageAtomicExchange(01H20D00E", + "imageAtomicExchange(01S20D00E", + "imageAtomicExchange(01d20D00E", + "imageAtomicExchange(01D00D00E", + "imageAtomicExchange(01O00D00E", + "imageAtomicExchange(01Z00D00E", + "imageAtomicExchange(01E10D00E", + "imageAtomicExchange(01P10D00E", + "imageAtomicExchange(01a10D00E", + "imageAtomicExchange(01I10D00E", + "imageAtomicExchange(01T10D00E", + "imageAtomicExchange(01e10D00E", + "imageAtomicExchange(01F10D00D00E", + "imageAtomicExchange(01Q10D00D00E", + "imageAtomicExchange(01b10D00D00E", + "imageAtomicExchange(01G20D00D00E", + "imageAtomicExchange(01R20D00D00E", + "imageAtomicExchange(01c20D00D00E", + "imageAtomicExchange(00z10D00D", + "imageAtomicExchange(01K10D00D", + "imageAtomicExchange(01V10D00D", + "imageAtomicExchange(01A20D00D", + "imageAtomicExchange(01L20D00D", + "imageAtomicExchange(01W20D00D", + "imageAtomicExchange(01C20D00D", + "imageAtomicExchange(01N20D00D", + "imageAtomicExchange(01Y20D00D", + "imageAtomicExchange(01J00D00D", + "imageAtomicExchange(01U00D00D", + "imageAtomicExchange(01f00D00D", + "imageAtomicExchange(01B20D00D", + "imageAtomicExchange(01M20D00D", + "imageAtomicExchange(01X20D00D", + "imageAtomicExchange(01H20D00D", + "imageAtomicExchange(01S20D00D", + "imageAtomicExchange(01d20D00D", + "imageAtomicExchange(01D00D00D", + "imageAtomicExchange(01O00D00D", + "imageAtomicExchange(01Z00D00D", + "imageAtomicExchange(01E10D00D", + "imageAtomicExchange(01P10D00D", + "imageAtomicExchange(01a10D00D", + "imageAtomicExchange(01I10D00D", + "imageAtomicExchange(01T10D00D", + "imageAtomicExchange(01e10D00D", + "imageAtomicExchange(01F10D00D00D", + "imageAtomicExchange(01Q10D00D00D", + "imageAtomicExchange(01b10D00D00D", + "imageAtomicExchange(01G20D00D00D", + "imageAtomicExchange(01R20D00D00D", + "imageAtomicExchange(01c20D00D00D", + "imageAtomicExchange(00z10D00B", + "imageAtomicExchange(01K10D00B", + "imageAtomicExchange(01V10D00B", + "imageAtomicExchange(01A20D00B", + "imageAtomicExchange(01L20D00B", + "imageAtomicExchange(01W20D00B", + "imageAtomicExchange(01C20D00B", + "imageAtomicExchange(01N20D00B", + "imageAtomicExchange(01Y20D00B", + "imageAtomicExchange(01J00D00B", + "imageAtomicExchange(01U00D00B", + "imageAtomicExchange(01f00D00B", + "imageAtomicExchange(01B20D00B", + "imageAtomicExchange(01M20D00B", + "imageAtomicExchange(01X20D00B", + "imageAtomicExchange(01H20D00B", + "imageAtomicExchange(01S20D00B", + "imageAtomicExchange(01d20D00B", + "imageAtomicExchange(01D00D00B", + "imageAtomicExchange(01O00D00B", + "imageAtomicExchange(01Z00D00B", + "imageAtomicExchange(01E10D00B", + "imageAtomicExchange(01P10D00B", + "imageAtomicExchange(01a10D00B", + "imageAtomicExchange(01I10D00B", + "imageAtomicExchange(01T10D00B", + "imageAtomicExchange(01e10D00B", + "imageAtomicExchange(01F10D00D00B", + "imageAtomicExchange(01Q10D00D00B", + "imageAtomicExchange(01b10D00D00B", + "imageAtomicExchange(01G20D00D00B", + "imageAtomicExchange(01R20D00D00B", + "imageAtomicExchange(01c20D00D00B", + "imageAtomicCompSwap(00z10D00E00E", + "imageAtomicCompSwap(01K10D00E00E", + "imageAtomicCompSwap(01V10D00E00E", + "imageAtomicCompSwap(01A20D00E00E", + "imageAtomicCompSwap(01L20D00E00E", + "imageAtomicCompSwap(01W20D00E00E", + "imageAtomicCompSwap(01C20D00E00E", + "imageAtomicCompSwap(01N20D00E00E", + "imageAtomicCompSwap(01Y20D00E00E", + "imageAtomicCompSwap(01J00D00E00E", + "imageAtomicCompSwap(01U00D00E00E", + "imageAtomicCompSwap(01f00D00E00E", + "imageAtomicCompSwap(01B20D00E00E", + "imageAtomicCompSwap(01M20D00E00E", + "imageAtomicCompSwap(01X20D00E00E", + "imageAtomicCompSwap(01H20D00E00E", + "imageAtomicCompSwap(01S20D00E00E", + "imageAtomicCompSwap(01d20D00E00E", + "imageAtomicCompSwap(01D00D00E00E", + "imageAtomicCompSwap(01O00D00E00E", + "imageAtomicCompSwap(01Z00D00E00E", + "imageAtomicCompSwap(01E10D00E00E", + "imageAtomicCompSwap(01P10D00E00E", + "imageAtomicCompSwap(01a10D00E00E", + "imageAtomicCompSwap(01I10D00E00E", + "imageAtomicCompSwap(01T10D00E00E", + "imageAtomicCompSwap(01e10D00E00E", + "imageAtomicCompSwap(01F10D00D00E00E", + "imageAtomicCompSwap(01Q10D00D00E00E", + "imageAtomicCompSwap(01b10D00D00E00E", + "imageAtomicCompSwap(01G20D00D00E00E", + "imageAtomicCompSwap(01R20D00D00E00E", + "imageAtomicCompSwap(01c20D00D00E00E", + "imageAtomicCompSwap(00z10D00D00D", + "imageAtomicCompSwap(01K10D00D00D", + "imageAtomicCompSwap(01V10D00D00D", + "imageAtomicCompSwap(01A20D00D00D", + "imageAtomicCompSwap(01L20D00D00D", + "imageAtomicCompSwap(01W20D00D00D", + "imageAtomicCompSwap(01C20D00D00D", + "imageAtomicCompSwap(01N20D00D00D", + "imageAtomicCompSwap(01Y20D00D00D", + "imageAtomicCompSwap(01J00D00D00D", + "imageAtomicCompSwap(01U00D00D00D", + "imageAtomicCompSwap(01f00D00D00D", + "imageAtomicCompSwap(01B20D00D00D", + "imageAtomicCompSwap(01M20D00D00D", + "imageAtomicCompSwap(01X20D00D00D", + "imageAtomicCompSwap(01H20D00D00D", + "imageAtomicCompSwap(01S20D00D00D", + "imageAtomicCompSwap(01d20D00D00D", + "imageAtomicCompSwap(01D00D00D00D", + "imageAtomicCompSwap(01O00D00D00D", + "imageAtomicCompSwap(01Z00D00D00D", + "imageAtomicCompSwap(01E10D00D00D", + "imageAtomicCompSwap(01P10D00D00D", + "imageAtomicCompSwap(01a10D00D00D", + "imageAtomicCompSwap(01I10D00D00D", + "imageAtomicCompSwap(01T10D00D00D", + "imageAtomicCompSwap(01e10D00D00D", + "imageAtomicCompSwap(01F10D00D00D00D", + "imageAtomicCompSwap(01Q10D00D00D00D", + "imageAtomicCompSwap(01b10D00D00D00D", + "imageAtomicCompSwap(01G20D00D00D00D", + "imageAtomicCompSwap(01R20D00D00D00D", + "imageAtomicCompSwap(01c20D00D00D00D", + "pixelLocalLoadANGLE(01g", + "pixelLocalLoadANGLE(01h", + "pixelLocalLoadANGLE(01i", + "pixelLocalStoreANGLE(01g30B", + "pixelLocalStoreANGLE(01h30D", + "pixelLocalStoreANGLE(01i30E", + "beginInvocationInterlockNV(", + "endInvocationInterlockNV(", + "beginFragmentShaderOrderingINTEL(", + "beginInvocationInterlockARB(", + "endInvocationInterlockARB(", + "memoryBarrier(", + "memoryBarrierAtomicCounter(", + "memoryBarrierBuffer(", + "memoryBarrierImage(", + "barrier(", + "memoryBarrierShared(", + "groupMemoryBarrier(", + "EmitVertex(", + "EndPrimitive(", + "subpassLoad(01j", + "subpassLoad(01k", + "subpassLoad(01l", + "subpassLoad(01m00D", + "subpassLoad(01n00D", + "subpassLoad(01o00D", + "gl_DepthRangeParameters", + "gl_DepthRange", + "gl_NumSamples", + "gl_MaxVertexAttribs", + "gl_MaxVertexUniformVectors", + "gl_MaxVertexTextureImageUnits", + "gl_MaxCombinedTextureImageUnits", + "gl_MaxTextureImageUnits", + "gl_MaxFragmentUniformVectors", + "gl_MaxVaryingVectors", + "gl_MaxDrawBuffers", + "gl_MaxDualSourceDrawBuffersEXT", + "gl_MaxVertexOutputVectors", + "gl_MaxFragmentInputVectors", + "gl_MinProgramTexelOffset", + "gl_MaxProgramTexelOffset", + "gl_MaxImageUnits", + "gl_MaxVertexImageUniforms", + "gl_MaxFragmentImageUniforms", + "gl_MaxComputeImageUniforms", + "gl_MaxCombinedImageUniforms", + "gl_MaxCombinedShaderOutputResources", + "gl_MaxComputeWorkGroupCount", + "gl_MaxComputeWorkGroupSize", + "gl_MaxComputeUniformComponents", + "gl_MaxComputeTextureImageUnits", + "gl_MaxComputeAtomicCounters", + "gl_MaxComputeAtomicCounterBuffers", + "gl_MaxVertexAtomicCounters", + "gl_MaxFragmentAtomicCounters", + "gl_MaxCombinedAtomicCounters", + "gl_MaxAtomicCounterBindings", + "gl_MaxVertexAtomicCounterBuffers", + "gl_MaxFragmentAtomicCounterBuffers", + "gl_MaxCombinedAtomicCounterBuffers", + "gl_MaxAtomicCounterBufferSize", + "gl_MaxGeometryInputComponents", + "gl_MaxGeometryOutputComponents", + "gl_MaxGeometryImageUniforms", + "gl_MaxGeometryTextureImageUnits", + "gl_MaxGeometryOutputVertices", + "gl_MaxGeometryTotalOutputComponents", + "gl_MaxGeometryUniformComponents", + "gl_MaxGeometryAtomicCounters", + "gl_MaxGeometryAtomicCounterBuffers", + "gl_MaxTessControlInputComponents", + "gl_MaxTessControlOutputComponents", + "gl_MaxTessControlTextureImageUnits", + "gl_MaxTessControlUniformComponents", + "gl_MaxTessControlTotalOutputComponents", + "gl_MaxTessControlImageUniforms", + "gl_MaxTessControlAtomicCounters", + "gl_MaxTessControlAtomicCounterBuffers", + "gl_MaxTessPatchComponents", + "gl_MaxPatchVertices", + "gl_MaxTessGenLevel", + "gl_MaxTessEvaluationInputComponents", + "gl_MaxTessEvaluationOutputComponents", + "gl_MaxTessEvaluationTextureImageUnits", + "gl_MaxTessEvaluationUniformComponents", + "gl_MaxTessEvaluationImageUniforms", + "gl_MaxTessEvaluationAtomicCounters", + "gl_MaxTessEvaluationAtomicCounterBuffers", + "gl_MaxSamples", + "gl_MaxClipDistances", + "gl_MaxCullDistances", + "gl_MaxCombinedClipAndCullDistances", + "gl_FragCoord", + "gl_FrontFacing", + "gl_PointCoord", + "gl_FragColor", + "gl_FragData", + "gl_FragDepth", + "gl_HelperInvocation", + "gl_SecondaryFragColorEXT", + "gl_SecondaryFragDataEXT", + "gl_FragDepthEXT", + "gl_LastFragData", + "gl_LastFragColor", + "gl_LastFragColorARM", + "gl_PrimitiveID", + "gl_Layer", + "gl_SampleID", + "gl_SamplePosition", + "gl_SampleMaskIn", + "gl_SampleMask", + "gl_CullDistance", + "gl_ClipDistance", + "gl_Position", + "gl_PointSize", + "gl_InstanceID", + "", + "gl_VertexID", + "", + "", + "gl_DrawID", + "gl_BaseVertex", + "gl_BaseInstance", + "angle_BaseVertex", + "angle_BaseInstance", + "gl_NumWorkGroups", + "gl_WorkGroupSize", + "gl_WorkGroupID", + "gl_LocalInvocationID", + "gl_GlobalInvocationID", + "gl_LocalInvocationIndex", + "gl_PrimitiveIDIn", + "gl_InvocationID", + "gl_PerVertex", + "gl_in", + "gl_PatchVerticesIn", + "gl_TessLevelOuter", + "gl_TessLevelInner", + "gl_out", + "gl_BoundingBox", + "gl_BoundingBoxEXT", + "gl_BoundingBoxOES", + "gl_TessCoord", + "gl_ViewID_OVR"}; + +// Flat array of offsets from a symbol into the rules table. +constexpr uint16_t kMangledOffsets[] = { + 0, // radians_00B + 1, // radians_10B + 2, // radians_20B + 3, // radians_30B + 4, // degrees_00B + 5, // degrees_10B + 6, // degrees_20B + 7, // degrees_30B + 8, // sin_00B + 9, // sin_10B + 10, // sin_20B + 11, // sin_30B + 12, // cos_00B + 13, // cos_10B + 14, // cos_20B + 15, // cos_30B + 16, // tan_00B + 17, // tan_10B + 18, // tan_20B + 19, // tan_30B + 20, // asin_00B + 21, // asin_10B + 22, // asin_20B + 23, // asin_30B + 24, // acos_00B + 25, // acos_10B + 26, // acos_20B + 27, // acos_30B + 28, // atan_00B00B + 29, // atan_10B10B + 30, // atan_20B20B + 31, // atan_30B30B + 32, // atan_00B + 33, // atan_10B + 34, // atan_20B + 35, // atan_30B + 36, // sinh_00B + 37, // sinh_10B + 38, // sinh_20B + 39, // sinh_30B + 40, // cosh_00B + 41, // cosh_10B + 42, // cosh_20B + 43, // cosh_30B + 44, // tanh_00B + 45, // tanh_10B + 46, // tanh_20B + 47, // tanh_30B + 48, // asinh_00B + 49, // asinh_10B + 50, // asinh_20B + 51, // asinh_30B + 52, // acosh_00B + 53, // acosh_10B + 54, // acosh_20B + 55, // acosh_30B + 56, // atanh_00B + 57, // atanh_10B + 58, // atanh_20B + 59, // atanh_30B + 60, // pow_00B00B + 61, // pow_10B10B + 62, // pow_20B20B + 63, // pow_30B30B + 64, // exp_00B + 65, // exp_10B + 66, // exp_20B + 67, // exp_30B + 68, // log_00B + 69, // log_10B + 70, // log_20B + 71, // log_30B + 72, // exp2_00B + 73, // exp2_10B + 74, // exp2_20B + 75, // exp2_30B + 76, // log2_00B + 77, // log2_10B + 78, // log2_20B + 79, // log2_30B + 80, // sqrt_00B + 81, // sqrt_10B + 82, // sqrt_20B + 83, // sqrt_30B + 84, // inversesqrt_00B + 85, // inversesqrt_10B + 86, // inversesqrt_20B + 87, // inversesqrt_30B + 88, // abs_00B + 89, // abs_10B + 90, // abs_20B + 91, // abs_30B + 92, // abs_00D + 93, // abs_10D + 94, // abs_20D + 95, // abs_30D + 96, // sign_00B + 97, // sign_10B + 98, // sign_20B + 99, // sign_30B + 100, // sign_00D + 101, // sign_10D + 102, // sign_20D + 103, // sign_30D + 104, // floor_00B + 105, // floor_10B + 106, // floor_20B + 107, // floor_30B + 108, // trunc_00B + 109, // trunc_10B + 110, // trunc_20B + 111, // trunc_30B + 112, // round_00B + 113, // round_10B + 114, // round_20B + 115, // round_30B + 116, // roundEven_00B + 117, // roundEven_10B + 118, // roundEven_20B + 119, // roundEven_30B + 120, // ceil_00B + 121, // ceil_10B + 122, // ceil_20B + 123, // ceil_30B + 124, // fract_00B + 125, // fract_10B + 126, // fract_20B + 127, // fract_30B + 128, // mod_00B00B + 129, // mod_10B00B + 130, // mod_20B00B + 131, // mod_30B00B + 132, // mod_10B10B + 133, // mod_20B20B + 134, // mod_30B30B + 135, // min_00B00B + 136, // min_10B00B + 137, // min_20B00B + 138, // min_30B00B + 139, // min_10B10B + 140, // min_20B20B + 141, // min_30B30B + 142, // min_00D00D + 143, // min_10D10D + 144, // min_20D20D + 145, // min_30D30D + 146, // min_10D00D + 147, // min_20D00D + 148, // min_30D00D + 149, // min_00E00E + 150, // min_10E10E + 151, // min_20E20E + 152, // min_30E30E + 153, // min_10E00E + 154, // min_20E00E + 155, // min_30E00E + 156, // max_00B00B + 157, // max_10B00B + 158, // max_20B00B + 159, // max_30B00B + 160, // max_10B10B + 161, // max_20B20B + 162, // max_30B30B + 163, // max_00D00D + 164, // max_10D10D + 165, // max_20D20D + 166, // max_30D30D + 167, // max_10D00D + 168, // max_20D00D + 169, // max_30D00D + 170, // max_00E00E + 171, // max_10E10E + 172, // max_20E20E + 173, // max_30E30E + 174, // max_10E00E + 175, // max_20E00E + 176, // max_30E00E + 177, // clamp_00B00B00B + 178, // clamp_10B00B00B + 179, // clamp_20B00B00B + 180, // clamp_30B00B00B + 181, // clamp_10B10B10B + 182, // clamp_20B20B20B + 183, // clamp_30B30B30B + 184, // clamp_00D00D00D + 185, // clamp_10D00D00D + 186, // clamp_20D00D00D + 187, // clamp_30D00D00D + 188, // clamp_10D10D10D + 189, // clamp_20D20D20D + 190, // clamp_30D30D30D + 191, // clamp_00E00E00E + 192, // clamp_10E00E00E + 193, // clamp_20E00E00E + 194, // clamp_30E00E00E + 195, // clamp_10E10E10E + 196, // clamp_20E20E20E + 197, // clamp_30E30E30E + 198, // mix_00B00B00B + 199, // mix_10B10B00B + 200, // mix_20B20B00B + 201, // mix_30B30B00B + 202, // mix_10B10B10B + 203, // mix_20B20B20B + 204, // mix_30B30B30B + 205, // mix_00B00B00F + 206, // mix_10B10B10F + 207, // mix_20B20B20F + 208, // mix_30B30B30F + 209, // mix_00D00D00F + 210, // mix_10D10D10F + 211, // mix_20D20D20F + 212, // mix_30D30D30F + 213, // mix_00E00E00F + 214, // mix_10E10E10F + 215, // mix_20E20E20F + 216, // mix_30E30E30F + 217, // mix_00F00F00F + 218, // mix_10F10F10F + 219, // mix_20F20F20F + 220, // mix_30F30F30F + 221, // step_00B00B + 222, // step_10B10B + 223, // step_20B20B + 224, // step_30B30B + 225, // step_00B10B + 226, // step_00B20B + 227, // step_00B30B + 228, // smoothstep_00B00B00B + 229, // smoothstep_10B10B10B + 230, // smoothstep_20B20B20B + 231, // smoothstep_30B30B30B + 232, // smoothstep_00B00B10B + 233, // smoothstep_00B00B20B + 234, // smoothstep_00B00B30B + 235, // modf_00B00B + 236, // modf_10B10B + 237, // modf_20B20B + 238, // modf_30B30B + 239, // isnan_00B + 240, // isnan_10B + 241, // isnan_20B + 242, // isnan_30B + 243, // isinf_00B + 244, // isinf_10B + 245, // isinf_20B + 246, // isinf_30B + 247, // floatBitsToInt_00B + 248, // floatBitsToInt_10B + 249, // floatBitsToInt_20B + 250, // floatBitsToInt_30B + 251, // floatBitsToUint_00B + 252, // floatBitsToUint_10B + 253, // floatBitsToUint_20B + 254, // floatBitsToUint_30B + 255, // intBitsToFloat_00D + 256, // intBitsToFloat_10D + 257, // intBitsToFloat_20D + 258, // intBitsToFloat_30D + 259, // uintBitsToFloat_00E + 260, // uintBitsToFloat_10E + 261, // uintBitsToFloat_20E + 262, // uintBitsToFloat_30E + 263, // fma_00B00B00B + 265, // fma_10B10B10B + 267, // fma_20B20B20B + 269, // fma_30B30B30B + 271, // frexp_00B00D + 272, // frexp_10B10D + 273, // frexp_20B20D + 274, // frexp_30B30D + 275, // ldexp_00B00D + 276, // ldexp_10B10D + 277, // ldexp_20B20D + 278, // ldexp_30B30D + 279, // packSnorm2x16_10B + 280, // packHalf2x16_10B + 281, // unpackSnorm2x16_00E + 282, // unpackHalf2x16_00E + 283, // packUnorm2x16_10B + 284, // unpackUnorm2x16_00E + 285, // packUnorm4x8_30B + 286, // packSnorm4x8_30B + 287, // unpackUnorm4x8_00E + 288, // unpackSnorm4x8_00E + 289, // length_00B + 290, // length_10B + 291, // length_20B + 292, // length_30B + 293, // distance_00B00B + 294, // distance_10B10B + 295, // distance_20B20B + 296, // distance_30B30B + 297, // dot_00B00B + 298, // dot_10B10B + 299, // dot_20B20B + 300, // dot_30B30B + 301, // cross_20B20B + 302, // normalize_00B + 303, // normalize_10B + 304, // normalize_20B + 305, // normalize_30B + 306, // faceforward_00B00B00B + 307, // faceforward_10B10B10B + 308, // faceforward_20B20B20B + 309, // faceforward_30B30B30B + 310, // reflect_00B00B + 311, // reflect_10B10B + 312, // reflect_20B20B + 313, // reflect_30B30B + 314, // refract_00B00B00B + 315, // refract_10B10B00B + 316, // refract_20B20B00B + 317, // refract_30B30B00B + 318, // matrixCompMult_50B50B + 319, // matrixCompMult_A0BA0B + 320, // matrixCompMult_F0BF0B + 321, // matrixCompMult_90B90B + 322, // matrixCompMult_60B60B + 323, // matrixCompMult_D0BD0B + 324, // matrixCompMult_70B70B + 325, // matrixCompMult_E0BE0B + 326, // matrixCompMult_B0BB0B + 327, // outerProduct_10B10B + 328, // outerProduct_20B20B + 329, // outerProduct_30B30B + 330, // outerProduct_20B10B + 331, // outerProduct_10B20B + 332, // outerProduct_30B10B + 333, // outerProduct_10B30B + 334, // outerProduct_30B20B + 335, // outerProduct_20B30B + 336, // transpose_50B + 337, // transpose_A0B + 338, // transpose_F0B + 339, // transpose_60B + 340, // transpose_90B + 341, // transpose_70B + 342, // transpose_D0B + 343, // transpose_B0B + 344, // transpose_E0B + 345, // determinant_50B + 346, // determinant_A0B + 347, // determinant_F0B + 348, // inverse_50B + 349, // inverse_A0B + 350, // inverse_F0B + 351, // lessThan_10B10B + 352, // lessThan_20B20B + 353, // lessThan_30B30B + 354, // lessThan_10D10D + 355, // lessThan_20D20D + 356, // lessThan_30D30D + 357, // lessThan_10E10E + 358, // lessThan_20E20E + 359, // lessThan_30E30E + 360, // lessThanEqual_10B10B + 361, // lessThanEqual_20B20B + 362, // lessThanEqual_30B30B + 363, // lessThanEqual_10D10D + 364, // lessThanEqual_20D20D + 365, // lessThanEqual_30D30D + 366, // lessThanEqual_10E10E + 367, // lessThanEqual_20E20E + 368, // lessThanEqual_30E30E + 369, // greaterThan_10B10B + 370, // greaterThan_20B20B + 371, // greaterThan_30B30B + 372, // greaterThan_10D10D + 373, // greaterThan_20D20D + 374, // greaterThan_30D30D + 375, // greaterThan_10E10E + 376, // greaterThan_20E20E + 377, // greaterThan_30E30E + 378, // greaterThanEqual_10B10B + 379, // greaterThanEqual_20B20B + 380, // greaterThanEqual_30B30B + 381, // greaterThanEqual_10D10D + 382, // greaterThanEqual_20D20D + 383, // greaterThanEqual_30D30D + 384, // greaterThanEqual_10E10E + 385, // greaterThanEqual_20E20E + 386, // greaterThanEqual_30E30E + 387, // equal_10B10B + 388, // equal_20B20B + 389, // equal_30B30B + 390, // equal_10D10D + 391, // equal_20D20D + 392, // equal_30D30D + 393, // equal_10E10E + 394, // equal_20E20E + 395, // equal_30E30E + 396, // equal_10F10F + 397, // equal_20F20F + 398, // equal_30F30F + 399, // notEqual_10B10B + 400, // notEqual_20B20B + 401, // notEqual_30B30B + 402, // notEqual_10D10D + 403, // notEqual_20D20D + 404, // notEqual_30D30D + 405, // notEqual_10E10E + 406, // notEqual_20E20E + 407, // notEqual_30E30E + 408, // notEqual_10F10F + 409, // notEqual_20F20F + 410, // notEqual_30F30F + 411, // any_10F + 412, // any_20F + 413, // any_30F + 414, // all_10F + 415, // all_20F + 416, // all_30F + 417, // not_10F + 418, // not_20F + 419, // not_30F + 420, // bitfieldExtract_00D00D00D + 421, // bitfieldExtract_10D00D00D + 422, // bitfieldExtract_20D00D00D + 423, // bitfieldExtract_30D00D00D + 424, // bitfieldExtract_00E00D00D + 425, // bitfieldExtract_10E00D00D + 426, // bitfieldExtract_20E00D00D + 427, // bitfieldExtract_30E00D00D + 428, // bitfieldInsert_00D00D00D00D + 429, // bitfieldInsert_10D10D00D00D + 430, // bitfieldInsert_20D20D00D00D + 431, // bitfieldInsert_30D30D00D00D + 432, // bitfieldInsert_00E00E00D00D + 433, // bitfieldInsert_10E10E00D00D + 434, // bitfieldInsert_20E20E00D00D + 435, // bitfieldInsert_30E30E00D00D + 436, // bitfieldReverse_00D + 437, // bitfieldReverse_10D + 438, // bitfieldReverse_20D + 439, // bitfieldReverse_30D + 440, // bitfieldReverse_00E + 441, // bitfieldReverse_10E + 442, // bitfieldReverse_20E + 443, // bitfieldReverse_30E + 444, // bitCount_00D + 445, // bitCount_10D + 446, // bitCount_20D + 447, // bitCount_30D + 448, // bitCount_00E + 449, // bitCount_10E + 450, // bitCount_20E + 451, // bitCount_30E + 452, // findLSB_00D + 453, // findLSB_10D + 454, // findLSB_20D + 455, // findLSB_30D + 456, // findLSB_00E + 457, // findLSB_10E + 458, // findLSB_20E + 459, // findLSB_30E + 460, // findMSB_00D + 461, // findMSB_10D + 462, // findMSB_20D + 463, // findMSB_30D + 464, // findMSB_00E + 465, // findMSB_10E + 466, // findMSB_20E + 467, // findMSB_30E + 468, // uaddCarry_00E00E00E + 469, // uaddCarry_10E10E10E + 470, // uaddCarry_20E20E20E + 471, // uaddCarry_30E30E30E + 472, // usubBorrow_00E00E00E + 473, // usubBorrow_10E10E10E + 474, // usubBorrow_20E20E20E + 475, // usubBorrow_30E30E30E + 476, // umulExtended_00E00E00E00E + 477, // umulExtended_10E10E10E10E + 478, // umulExtended_20E20E20E20E + 479, // umulExtended_30E30E30E30E + 480, // imulExtended_00D00D00D00D + 481, // imulExtended_10D10D10D10D + 482, // imulExtended_20D20D20D20D + 483, // imulExtended_30D30D30D30D + 484, // texture2D_00I10B + 485, // texture2DProj_00I20B + 486, // texture2DProj_00I30B + 487, // textureCube_00K20B + 488, // texture3D_00J20B + 489, // texture3DProj_00J30B + 490, // shadow2DEXT_00d20B + 491, // shadow2DProjEXT_00d30B + 492, // texture2D_00M10B + 494, // texture2DProj_00M20B + 496, // texture2DProj_00M30B + 498, // texture2DRect_00O10B + 499, // texture2DRectProj_00O20B + 500, // texture2DRectProj_00O30B + 501, // texture2DGradEXT_00I10B10B10B + 502, // texture2DProjGradEXT_00I20B10B10B + 503, // texture2DProjGradEXT_00I30B10B10B + 504, // textureCubeGradEXT_00K20B20B20B + 505, // textureVideoWEBGL_00y10B + 506, // texture2D_00I10B00B + 507, // texture2DProj_00I20B00B + 508, // texture2DProj_00I30B00B + 509, // textureCube_00K20B00B + 510, // texture3D_00J20B00B + 511, // texture3DProj_00J30B00B + 512, // texture3DLod_00J20B00B + 513, // texture3DProjLod_00J30B00B + 514, // texture2DLod_00I10B00B + 515, // texture2DProjLod_00I20B00B + 516, // texture2DProjLod_00I30B00B + 517, // textureCubeLod_00K20B00B + 518, // texture2DLodEXT_00I10B00B + 519, // texture2DProjLodEXT_00I20B00B + 520, // texture2DProjLodEXT_00I30B00B + 521, // textureCubeLodEXT_00K20B00B + 522, // texture_00I10B + 523, // texture_00R10B + 524, // texture_00X10B + 525, // texture_00J20B + 526, // texture_00S20B + 527, // texture_00Y20B + 528, // texture_00K20B + 529, // texture_00T20B + 530, // texture_00Z20B + 531, // texture_00L20B + 532, // texture_00U20B + 533, // texture_00a20B + 534, // texture_00d20B + 535, // texture_00e30B + 536, // texture_00f30B + 537, // texture_00k30B + 540, // texture_00s30B + 543, // texture_00x30B + 546, // texture_00l30B00B + 549, // texture_00M10B + 550, // texture_00N10B + 551, // texture_00O10B + 552, // texture_00y10B + 553, // textureProj_00I20B + 554, // textureProj_00R20B + 555, // textureProj_00X20B + 556, // textureProj_00I30B + 557, // textureProj_00R30B + 558, // textureProj_00X30B + 559, // textureProj_00J30B + 560, // textureProj_00S30B + 561, // textureProj_00Y30B + 562, // textureProj_00d30B + 563, // textureProj_00M20B + 564, // textureProj_00M30B + 565, // textureProj_00N20B + 566, // textureProj_00N30B + 567, // textureProj_00O20B + 568, // textureProj_00O30B + 569, // textureLod_00I10B00B + 570, // textureLod_00R10B00B + 571, // textureLod_00X10B00B + 572, // textureLod_00J20B00B + 573, // textureLod_00S20B00B + 574, // textureLod_00Y20B00B + 575, // textureLod_00K20B00B + 576, // textureLod_00T20B00B + 577, // textureLod_00Z20B00B + 578, // textureLod_00L20B00B + 579, // textureLod_00U20B00B + 580, // textureLod_00a20B00B + 581, // textureLod_00d20B00B + 582, // textureLod_00k30B00B + 585, // textureLod_00s30B00B + 588, // textureLod_00x30B00B + 591, // textureSize_00I00D + 592, // textureSize_00R00D + 593, // textureSize_00X00D + 594, // textureSize_00J00D + 595, // textureSize_00S00D + 596, // textureSize_00Y00D + 597, // textureSize_00K00D + 598, // textureSize_00T00D + 599, // textureSize_00Z00D + 600, // textureSize_00L00D + 601, // textureSize_00U00D + 602, // textureSize_00a00D + 603, // textureSize_00d00D + 604, // textureSize_00e00D + 605, // textureSize_00f00D + 606, // textureSize_00k00D + 609, // textureSize_00s00D + 612, // textureSize_00x00D + 615, // textureSize_00l00D + 618, // textureSize_00j + 621, // textureSize_00r + 624, // textureSize_00w + 627, // textureSize_00P + 629, // textureSize_00V + 631, // textureSize_00b + 633, // textureSize_00Q + 635, // textureSize_00W + 637, // textureSize_00c + 639, // textureSize_00M00D + 640, // textureSize_00N00D + 641, // textureProjLod_00I20B00B + 642, // textureProjLod_00R20B00B + 643, // textureProjLod_00X20B00B + 644, // textureProjLod_00I30B00B + 645, // textureProjLod_00R30B00B + 646, // textureProjLod_00X30B00B + 647, // textureProjLod_00J30B00B + 648, // textureProjLod_00S30B00B + 649, // textureProjLod_00Y30B00B + 650, // textureProjLod_00d30B00B + 651, // texelFetch_00I10D00D + 652, // texelFetch_00R10D00D + 653, // texelFetch_00X10D00D + 654, // texelFetch_00J20D00D + 655, // texelFetch_00S20D00D + 656, // texelFetch_00Y20D00D + 657, // texelFetch_00L20D00D + 658, // texelFetch_00U20D00D + 659, // texelFetch_00a20D00D + 660, // texelFetch_00j00D + 663, // texelFetch_00r00D + 666, // texelFetch_00w00D + 669, // texelFetch_00P10D00D + 671, // texelFetch_00V10D00D + 673, // texelFetch_00b10D00D + 675, // texelFetch_00Q20D00D + 677, // texelFetch_00W20D00D + 679, // texelFetch_00c20D00D + 681, // texelFetch_00M10D00D + 682, // texelFetch_00N10D00D + 683, // textureGrad_00I10B10B10B + 684, // textureGrad_00R10B10B10B + 685, // textureGrad_00X10B10B10B + 686, // textureGrad_00J20B20B20B + 687, // textureGrad_00S20B20B20B + 688, // textureGrad_00Y20B20B20B + 689, // textureGrad_00K20B20B20B + 690, // textureGrad_00T20B20B20B + 691, // textureGrad_00Z20B20B20B + 692, // textureGrad_00d20B10B10B + 693, // textureGrad_00e30B20B20B + 694, // textureGrad_00L20B10B10B + 695, // textureGrad_00U20B10B10B + 696, // textureGrad_00a20B10B10B + 697, // textureGrad_00f30B10B10B + 698, // textureGrad_00k30B20B20B + 701, // textureGrad_00s30B20B20B + 704, // textureGrad_00x30B20B20B + 707, // textureProjGrad_00I20B10B10B + 708, // textureProjGrad_00R20B10B10B + 709, // textureProjGrad_00X20B10B10B + 710, // textureProjGrad_00I30B10B10B + 711, // textureProjGrad_00R30B10B10B + 712, // textureProjGrad_00X30B10B10B + 713, // textureProjGrad_00J30B20B20B + 714, // textureProjGrad_00S30B20B20B + 715, // textureProjGrad_00Y30B20B20B + 716, // textureProjGrad_00d30B10B10B + 717, // texture_00I10B00B + 718, // texture_00R10B00B + 719, // texture_00X10B00B + 720, // texture_00J20B00B + 721, // texture_00S20B00B + 722, // texture_00Y20B00B + 723, // texture_00K20B00B + 724, // texture_00T20B00B + 725, // texture_00Z20B00B + 726, // texture_00L20B00B + 727, // texture_00U20B00B + 728, // texture_00a20B00B + 729, // textureProj_00I20B00B + 730, // textureProj_00R20B00B + 731, // textureProj_00X20B00B + 732, // textureProj_00I30B00B + 733, // textureProj_00R30B00B + 734, // textureProj_00X30B00B + 735, // textureProj_00J30B00B + 736, // textureProj_00S30B00B + 737, // textureProj_00Y30B00B + 738, // texture_00d20B00B + 739, // texture_00e30B00B + 740, // textureProj_00d30B00B + 741, // texture_00k30B00B + 744, // texture_00s30B00B + 747, // texture_00x30B00B + 750, // texture_00M10B00B + 751, // textureProj_00M20B00B + 752, // textureProj_00M30B00B + 753, // texture_00N10B00B + 754, // textureProj_00N20B00B + 755, // textureProj_00N30B00B + 756, // textureOffset_00I10B10D + 757, // textureOffset_00R10B10D + 758, // textureOffset_00X10B10D + 759, // textureOffset_00J20B20D + 760, // textureOffset_00S20B20D + 761, // textureOffset_00Y20B20D + 762, // textureOffset_00d20B10D + 763, // textureOffset_00L20B10D + 764, // textureOffset_00U20B10D + 765, // textureOffset_00a20B10D + 766, // textureProjOffset_00I20B10D + 767, // textureProjOffset_00R20B10D + 768, // textureProjOffset_00X20B10D + 769, // textureProjOffset_00I30B10D + 770, // textureProjOffset_00R30B10D + 771, // textureProjOffset_00X30B10D + 772, // textureProjOffset_00J30B20D + 773, // textureProjOffset_00S30B20D + 774, // textureProjOffset_00Y30B20D + 775, // textureProjOffset_00d30B10D + 776, // textureLodOffset_00I10B00B10D + 777, // textureLodOffset_00R10B00B10D + 778, // textureLodOffset_00X10B00B10D + 779, // textureLodOffset_00J20B00B20D + 780, // textureLodOffset_00S20B00B20D + 781, // textureLodOffset_00Y20B00B20D + 782, // textureLodOffset_00d20B00B10D + 783, // textureLodOffset_00L20B00B10D + 784, // textureLodOffset_00U20B00B10D + 785, // textureLodOffset_00a20B00B10D + 786, // textureProjLodOffset_00I20B00B10D + 787, // textureProjLodOffset_00R20B00B10D + 788, // textureProjLodOffset_00X20B00B10D + 789, // textureProjLodOffset_00I30B00B10D + 790, // textureProjLodOffset_00R30B00B10D + 791, // textureProjLodOffset_00X30B00B10D + 792, // textureProjLodOffset_00J30B00B20D + 793, // textureProjLodOffset_00S30B00B20D + 794, // textureProjLodOffset_00Y30B00B20D + 795, // textureProjLodOffset_00d30B00B10D + 796, // texelFetchOffset_00I10D00D10D + 797, // texelFetchOffset_00R10D00D10D + 798, // texelFetchOffset_00X10D00D10D + 799, // texelFetchOffset_00J20D00D20D + 800, // texelFetchOffset_00S20D00D20D + 801, // texelFetchOffset_00Y20D00D20D + 802, // texelFetchOffset_00L20D00D10D + 803, // texelFetchOffset_00U20D00D10D + 804, // texelFetchOffset_00a20D00D10D + 805, // textureGradOffset_00I10B10B10B10D + 806, // textureGradOffset_00R10B10B10B10D + 807, // textureGradOffset_00X10B10B10B10D + 808, // textureGradOffset_00J20B20B20B20D + 809, // textureGradOffset_00S20B20B20B20D + 810, // textureGradOffset_00Y20B20B20B20D + 811, // textureGradOffset_00d20B10B10B10D + 812, // textureGradOffset_00L20B10B10B10D + 813, // textureGradOffset_00U20B10B10B10D + 814, // textureGradOffset_00a20B10B10B10D + 815, // textureGradOffset_00f30B10B10B10D + 816, // textureProjGradOffset_00I20B10B10B10D + 817, // textureProjGradOffset_00R20B10B10B10D + 818, // textureProjGradOffset_00X20B10B10B10D + 819, // textureProjGradOffset_00I30B10B10B10D + 820, // textureProjGradOffset_00R30B10B10B10D + 821, // textureProjGradOffset_00X30B10B10B10D + 822, // textureProjGradOffset_00J30B20B20B20D + 823, // textureProjGradOffset_00S30B20B20B20D + 824, // textureProjGradOffset_00Y30B20B20B20D + 825, // textureProjGradOffset_00d30B10B10B10D + 826, // textureOffset_00I10B10D00B + 827, // textureOffset_00R10B10D00B + 828, // textureOffset_00X10B10D00B + 829, // textureOffset_00J20B20D00B + 830, // textureOffset_00S20B20D00B + 831, // textureOffset_00Y20B20D00B + 832, // textureOffset_00d20B10D00B + 833, // textureOffset_00L20B10D00B + 834, // textureOffset_00U20B10D00B + 835, // textureOffset_00a20B10D00B + 836, // textureProjOffset_00I20B10D00B + 837, // textureProjOffset_00R20B10D00B + 838, // textureProjOffset_00X20B10D00B + 839, // textureProjOffset_00I30B10D00B + 840, // textureProjOffset_00R30B10D00B + 841, // textureProjOffset_00X30B10D00B + 842, // textureProjOffset_00J30B20D00B + 843, // textureProjOffset_00S30B20D00B + 844, // textureProjOffset_00Y30B20D00B + 845, // textureProjOffset_00d30B10D00B + 846, // textureGather_00I10B + 847, // textureGather_00R10B + 848, // textureGather_00X10B + 849, // textureGather_00I10B00D + 850, // textureGather_00R10B00D + 851, // textureGather_00X10B00D + 852, // textureGather_00L20B + 853, // textureGather_00U20B + 854, // textureGather_00a20B + 855, // textureGather_00L20B00D + 856, // textureGather_00U20B00D + 857, // textureGather_00a20B00D + 858, // textureGather_00K20B + 859, // textureGather_00T20B + 860, // textureGather_00Z20B + 861, // textureGather_00K20B00D + 862, // textureGather_00T20B00D + 863, // textureGather_00Z20B00D + 864, // textureGather_00k30B + 867, // textureGather_00s30B + 870, // textureGather_00x30B + 873, // textureGather_00k30B00D + 876, // textureGather_00s30B00D + 879, // textureGather_00x30B00D + 882, // textureGather_00l30B00B + 885, // textureGather_00d10B + 886, // textureGather_00d10B00B + 887, // textureGather_00f20B + 888, // textureGather_00f20B00B + 889, // textureGather_00e20B + 890, // textureGather_00e20B00B + 891, // textureGatherOffset_00I10B10D + 892, // textureGatherOffset_00R10B10D + 893, // textureGatherOffset_00X10B10D + 894, // textureGatherOffset_00L20B10D + 895, // textureGatherOffset_00U20B10D + 896, // textureGatherOffset_00a20B10D + 897, // textureGatherOffset_00d10B00B10D + 898, // textureGatherOffset_00f20B00B10D + 899, // textureGatherOffset_00I10B10D00D + 900, // textureGatherOffset_00R10B10D00D + 901, // textureGatherOffset_00X10B10D00D + 902, // textureGatherOffset_00L20B10D00D + 903, // textureGatherOffset_00U20B10D00D + 904, // textureGatherOffset_00a20B10D00D + 905, // textureGatherOffsets_00I10B10Dx4 + 907, // textureGatherOffsets_00R10B10Dx4 + 909, // textureGatherOffsets_00X10B10Dx4 + 911, // textureGatherOffsets_00L20B10Dx4 + 913, // textureGatherOffsets_00U20B10Dx4 + 915, // textureGatherOffsets_00a20B10Dx4 + 917, // textureGatherOffsets_00d10B00B10Dx4 + 919, // textureGatherOffsets_00f20B00B10Dx4 + 921, // textureGatherOffsets_00I10B10Dx400D + 923, // textureGatherOffsets_00R10B10Dx400D + 925, // textureGatherOffsets_00X10B10Dx400D + 927, // textureGatherOffsets_00L20B10Dx400D + 929, // textureGatherOffsets_00U20B10Dx400D + 931, // textureGatherOffsets_00a20B10Dx400D + 933, // rgb_2_yuv_20B00H + 934, // yuv_2_rgb_20B00H + 935, // dFdx_00B + 937, // dFdx_10B + 939, // dFdx_20B + 941, // dFdx_30B + 943, // dFdy_00B + 945, // dFdy_10B + 947, // dFdy_20B + 949, // dFdy_30B + 951, // fwidth_00B + 953, // fwidth_10B + 955, // fwidth_20B + 957, // fwidth_30B + 959, // interpolateAtCentroid_00B + 961, // interpolateAtCentroid_10B + 963, // interpolateAtCentroid_20B + 965, // interpolateAtCentroid_30B + 967, // interpolateAtSample_00B00D + 969, // interpolateAtSample_10B00D + 971, // interpolateAtSample_20B00D + 973, // interpolateAtSample_30B00D + 975, // interpolateAtOffset_00B10B + 977, // interpolateAtOffset_10B10B + 979, // interpolateAtOffset_20B10B + 981, // interpolateAtOffset_30B10B + 983, // atomicCounter_00G + 984, // atomicCounterIncrement_00G + 985, // atomicCounterDecrement_00G + 986, // atomicAdd_00E00E + 987, // atomicAdd_00D00D + 988, // atomicMin_00E00E + 989, // atomicMin_00D00D + 990, // atomicMax_00E00E + 991, // atomicMax_00D00D + 992, // atomicAnd_00E00E + 993, // atomicAnd_00D00D + 994, // atomicOr_00E00E + 995, // atomicOr_00D00D + 996, // atomicXor_00E00E + 997, // atomicXor_00D00D + 998, // atomicExchange_00E00E + 999, // atomicExchange_00D00D + 1000, // atomicCompSwap_00E00E00E + 1001, // atomicCompSwap_00D00D00D + 1002, // imageSize_00z + 1003, // imageSize_01K + 1004, // imageSize_01V + 1005, // imageSize_01A + 1006, // imageSize_01L + 1007, // imageSize_01W + 1008, // imageSize_01B + 1009, // imageSize_01M + 1010, // imageSize_01X + 1011, // imageSize_01C + 1012, // imageSize_01N + 1013, // imageSize_01Y + 1014, // imageSize_01H + 1017, // imageSize_01S + 1020, // imageSize_01d + 1023, // imageSize_01J + 1026, // imageSize_01U + 1029, // imageSize_01f + 1032, // imageStore_00z10D30B + 1033, // imageStore_01K10D30D + 1034, // imageStore_01V10D30E + 1035, // imageStore_01A20D30B + 1036, // imageStore_01L20D30D + 1037, // imageStore_01W20D30E + 1038, // imageStore_01B20D30B + 1039, // imageStore_01M20D30D + 1040, // imageStore_01X20D30E + 1041, // imageStore_01C20D30B + 1042, // imageStore_01N20D30D + 1043, // imageStore_01Y20D30E + 1044, // imageStore_01H20D30B + 1047, // imageStore_01S20D30D + 1050, // imageStore_01d20D30E + 1053, // imageStore_01J00D30B + 1056, // imageStore_01U00D30D + 1059, // imageStore_01f00D30E + 1062, // imageLoad_00z10D + 1063, // imageLoad_01K10D + 1064, // imageLoad_01V10D + 1065, // imageLoad_01A20D + 1066, // imageLoad_01L20D + 1067, // imageLoad_01W20D + 1068, // imageLoad_01B20D + 1069, // imageLoad_01M20D + 1070, // imageLoad_01X20D + 1071, // imageLoad_01C20D + 1072, // imageLoad_01N20D + 1073, // imageLoad_01Y20D + 1074, // imageLoad_01H20D + 1077, // imageLoad_01S20D + 1080, // imageLoad_01d20D + 1083, // imageLoad_01J00D + 1086, // imageLoad_01U00D + 1089, // imageLoad_01f00D + 1092, // imageAtomicAdd_00z10D00E + 1094, // imageAtomicAdd_01K10D00E + 1096, // imageAtomicAdd_01V10D00E + 1098, // imageAtomicAdd_01A20D00E + 1100, // imageAtomicAdd_01L20D00E + 1102, // imageAtomicAdd_01W20D00E + 1104, // imageAtomicAdd_01C20D00E + 1106, // imageAtomicAdd_01N20D00E + 1108, // imageAtomicAdd_01Y20D00E + 1110, // imageAtomicAdd_01J00D00E + 1112, // imageAtomicAdd_01U00D00E + 1114, // imageAtomicAdd_01f00D00E + 1116, // imageAtomicAdd_01B20D00E + 1118, // imageAtomicAdd_01M20D00E + 1120, // imageAtomicAdd_01X20D00E + 1122, // imageAtomicAdd_01H20D00E + 1124, // imageAtomicAdd_01S20D00E + 1126, // imageAtomicAdd_01d20D00E + 1128, // imageAtomicAdd_01D00D00E + 1130, // imageAtomicAdd_01O00D00E + 1132, // imageAtomicAdd_01Z00D00E + 1134, // imageAtomicAdd_01E10D00E + 1136, // imageAtomicAdd_01P10D00E + 1138, // imageAtomicAdd_01a10D00E + 1140, // imageAtomicAdd_01I10D00E + 1142, // imageAtomicAdd_01T10D00E + 1144, // imageAtomicAdd_01e10D00E + 1146, // imageAtomicAdd_01F10D00D00E + 1148, // imageAtomicAdd_01Q10D00D00E + 1150, // imageAtomicAdd_01b10D00D00E + 1152, // imageAtomicAdd_01G20D00D00E + 1154, // imageAtomicAdd_01R20D00D00E + 1156, // imageAtomicAdd_01c20D00D00E + 1158, // imageAtomicAdd_00z10D00D + 1160, // imageAtomicAdd_01K10D00D + 1162, // imageAtomicAdd_01V10D00D + 1164, // imageAtomicAdd_01A20D00D + 1166, // imageAtomicAdd_01L20D00D + 1168, // imageAtomicAdd_01W20D00D + 1170, // imageAtomicAdd_01C20D00D + 1172, // imageAtomicAdd_01N20D00D + 1174, // imageAtomicAdd_01Y20D00D + 1176, // imageAtomicAdd_01J00D00D + 1178, // imageAtomicAdd_01U00D00D + 1180, // imageAtomicAdd_01f00D00D + 1182, // imageAtomicAdd_01B20D00D + 1184, // imageAtomicAdd_01M20D00D + 1186, // imageAtomicAdd_01X20D00D + 1188, // imageAtomicAdd_01H20D00D + 1190, // imageAtomicAdd_01S20D00D + 1192, // imageAtomicAdd_01d20D00D + 1194, // imageAtomicAdd_01D00D00D + 1196, // imageAtomicAdd_01O00D00D + 1198, // imageAtomicAdd_01Z00D00D + 1200, // imageAtomicAdd_01E10D00D + 1202, // imageAtomicAdd_01P10D00D + 1204, // imageAtomicAdd_01a10D00D + 1206, // imageAtomicAdd_01I10D00D + 1208, // imageAtomicAdd_01T10D00D + 1210, // imageAtomicAdd_01e10D00D + 1212, // imageAtomicAdd_01F10D00D00D + 1214, // imageAtomicAdd_01Q10D00D00D + 1216, // imageAtomicAdd_01b10D00D00D + 1218, // imageAtomicAdd_01G20D00D00D + 1220, // imageAtomicAdd_01R20D00D00D + 1222, // imageAtomicAdd_01c20D00D00D + 1224, // imageAtomicMin_00z10D00E + 1226, // imageAtomicMin_01K10D00E + 1228, // imageAtomicMin_01V10D00E + 1230, // imageAtomicMin_01A20D00E + 1232, // imageAtomicMin_01L20D00E + 1234, // imageAtomicMin_01W20D00E + 1236, // imageAtomicMin_01C20D00E + 1238, // imageAtomicMin_01N20D00E + 1240, // imageAtomicMin_01Y20D00E + 1242, // imageAtomicMin_01J00D00E + 1244, // imageAtomicMin_01U00D00E + 1246, // imageAtomicMin_01f00D00E + 1248, // imageAtomicMin_01B20D00E + 1250, // imageAtomicMin_01M20D00E + 1252, // imageAtomicMin_01X20D00E + 1254, // imageAtomicMin_01H20D00E + 1256, // imageAtomicMin_01S20D00E + 1258, // imageAtomicMin_01d20D00E + 1260, // imageAtomicMin_01D00D00E + 1262, // imageAtomicMin_01O00D00E + 1264, // imageAtomicMin_01Z00D00E + 1266, // imageAtomicMin_01E10D00E + 1268, // imageAtomicMin_01P10D00E + 1270, // imageAtomicMin_01a10D00E + 1272, // imageAtomicMin_01I10D00E + 1274, // imageAtomicMin_01T10D00E + 1276, // imageAtomicMin_01e10D00E + 1278, // imageAtomicMin_01F10D00D00E + 1280, // imageAtomicMin_01Q10D00D00E + 1282, // imageAtomicMin_01b10D00D00E + 1284, // imageAtomicMin_01G20D00D00E + 1286, // imageAtomicMin_01R20D00D00E + 1288, // imageAtomicMin_01c20D00D00E + 1290, // imageAtomicMin_00z10D00D + 1292, // imageAtomicMin_01K10D00D + 1294, // imageAtomicMin_01V10D00D + 1296, // imageAtomicMin_01A20D00D + 1298, // imageAtomicMin_01L20D00D + 1300, // imageAtomicMin_01W20D00D + 1302, // imageAtomicMin_01C20D00D + 1304, // imageAtomicMin_01N20D00D + 1306, // imageAtomicMin_01Y20D00D + 1308, // imageAtomicMin_01J00D00D + 1310, // imageAtomicMin_01U00D00D + 1312, // imageAtomicMin_01f00D00D + 1314, // imageAtomicMin_01B20D00D + 1316, // imageAtomicMin_01M20D00D + 1318, // imageAtomicMin_01X20D00D + 1320, // imageAtomicMin_01H20D00D + 1322, // imageAtomicMin_01S20D00D + 1324, // imageAtomicMin_01d20D00D + 1326, // imageAtomicMin_01D00D00D + 1328, // imageAtomicMin_01O00D00D + 1330, // imageAtomicMin_01Z00D00D + 1332, // imageAtomicMin_01E10D00D + 1334, // imageAtomicMin_01P10D00D + 1336, // imageAtomicMin_01a10D00D + 1338, // imageAtomicMin_01I10D00D + 1340, // imageAtomicMin_01T10D00D + 1342, // imageAtomicMin_01e10D00D + 1344, // imageAtomicMin_01F10D00D00D + 1346, // imageAtomicMin_01Q10D00D00D + 1348, // imageAtomicMin_01b10D00D00D + 1350, // imageAtomicMin_01G20D00D00D + 1352, // imageAtomicMin_01R20D00D00D + 1354, // imageAtomicMin_01c20D00D00D + 1356, // imageAtomicMax_00z10D00E + 1358, // imageAtomicMax_01K10D00E + 1360, // imageAtomicMax_01V10D00E + 1362, // imageAtomicMax_01A20D00E + 1364, // imageAtomicMax_01L20D00E + 1366, // imageAtomicMax_01W20D00E + 1368, // imageAtomicMax_01C20D00E + 1370, // imageAtomicMax_01N20D00E + 1372, // imageAtomicMax_01Y20D00E + 1374, // imageAtomicMax_01J00D00E + 1376, // imageAtomicMax_01U00D00E + 1378, // imageAtomicMax_01f00D00E + 1380, // imageAtomicMax_01B20D00E + 1382, // imageAtomicMax_01M20D00E + 1384, // imageAtomicMax_01X20D00E + 1386, // imageAtomicMax_01H20D00E + 1388, // imageAtomicMax_01S20D00E + 1390, // imageAtomicMax_01d20D00E + 1392, // imageAtomicMax_01D00D00E + 1394, // imageAtomicMax_01O00D00E + 1396, // imageAtomicMax_01Z00D00E + 1398, // imageAtomicMax_01E10D00E + 1400, // imageAtomicMax_01P10D00E + 1402, // imageAtomicMax_01a10D00E + 1404, // imageAtomicMax_01I10D00E + 1406, // imageAtomicMax_01T10D00E + 1408, // imageAtomicMax_01e10D00E + 1410, // imageAtomicMax_01F10D00D00E + 1412, // imageAtomicMax_01Q10D00D00E + 1414, // imageAtomicMax_01b10D00D00E + 1416, // imageAtomicMax_01G20D00D00E + 1418, // imageAtomicMax_01R20D00D00E + 1420, // imageAtomicMax_01c20D00D00E + 1422, // imageAtomicMax_00z10D00D + 1424, // imageAtomicMax_01K10D00D + 1426, // imageAtomicMax_01V10D00D + 1428, // imageAtomicMax_01A20D00D + 1430, // imageAtomicMax_01L20D00D + 1432, // imageAtomicMax_01W20D00D + 1434, // imageAtomicMax_01C20D00D + 1436, // imageAtomicMax_01N20D00D + 1438, // imageAtomicMax_01Y20D00D + 1440, // imageAtomicMax_01J00D00D + 1442, // imageAtomicMax_01U00D00D + 1444, // imageAtomicMax_01f00D00D + 1446, // imageAtomicMax_01B20D00D + 1448, // imageAtomicMax_01M20D00D + 1450, // imageAtomicMax_01X20D00D + 1452, // imageAtomicMax_01H20D00D + 1454, // imageAtomicMax_01S20D00D + 1456, // imageAtomicMax_01d20D00D + 1458, // imageAtomicMax_01D00D00D + 1460, // imageAtomicMax_01O00D00D + 1462, // imageAtomicMax_01Z00D00D + 1464, // imageAtomicMax_01E10D00D + 1466, // imageAtomicMax_01P10D00D + 1468, // imageAtomicMax_01a10D00D + 1470, // imageAtomicMax_01I10D00D + 1472, // imageAtomicMax_01T10D00D + 1474, // imageAtomicMax_01e10D00D + 1476, // imageAtomicMax_01F10D00D00D + 1478, // imageAtomicMax_01Q10D00D00D + 1480, // imageAtomicMax_01b10D00D00D + 1482, // imageAtomicMax_01G20D00D00D + 1484, // imageAtomicMax_01R20D00D00D + 1486, // imageAtomicMax_01c20D00D00D + 1488, // imageAtomicAnd_00z10D00E + 1490, // imageAtomicAnd_01K10D00E + 1492, // imageAtomicAnd_01V10D00E + 1494, // imageAtomicAnd_01A20D00E + 1496, // imageAtomicAnd_01L20D00E + 1498, // imageAtomicAnd_01W20D00E + 1500, // imageAtomicAnd_01C20D00E + 1502, // imageAtomicAnd_01N20D00E + 1504, // imageAtomicAnd_01Y20D00E + 1506, // imageAtomicAnd_01J00D00E + 1508, // imageAtomicAnd_01U00D00E + 1510, // imageAtomicAnd_01f00D00E + 1512, // imageAtomicAnd_01B20D00E + 1514, // imageAtomicAnd_01M20D00E + 1516, // imageAtomicAnd_01X20D00E + 1518, // imageAtomicAnd_01H20D00E + 1520, // imageAtomicAnd_01S20D00E + 1522, // imageAtomicAnd_01d20D00E + 1524, // imageAtomicAnd_01D00D00E + 1526, // imageAtomicAnd_01O00D00E + 1528, // imageAtomicAnd_01Z00D00E + 1530, // imageAtomicAnd_01E10D00E + 1532, // imageAtomicAnd_01P10D00E + 1534, // imageAtomicAnd_01a10D00E + 1536, // imageAtomicAnd_01I10D00E + 1538, // imageAtomicAnd_01T10D00E + 1540, // imageAtomicAnd_01e10D00E + 1542, // imageAtomicAnd_01F10D00D00E + 1544, // imageAtomicAnd_01Q10D00D00E + 1546, // imageAtomicAnd_01b10D00D00E + 1548, // imageAtomicAnd_01G20D00D00E + 1550, // imageAtomicAnd_01R20D00D00E + 1552, // imageAtomicAnd_01c20D00D00E + 1554, // imageAtomicAnd_00z10D00D + 1556, // imageAtomicAnd_01K10D00D + 1558, // imageAtomicAnd_01V10D00D + 1560, // imageAtomicAnd_01A20D00D + 1562, // imageAtomicAnd_01L20D00D + 1564, // imageAtomicAnd_01W20D00D + 1566, // imageAtomicAnd_01C20D00D + 1568, // imageAtomicAnd_01N20D00D + 1570, // imageAtomicAnd_01Y20D00D + 1572, // imageAtomicAnd_01J00D00D + 1574, // imageAtomicAnd_01U00D00D + 1576, // imageAtomicAnd_01f00D00D + 1578, // imageAtomicAnd_01B20D00D + 1580, // imageAtomicAnd_01M20D00D + 1582, // imageAtomicAnd_01X20D00D + 1584, // imageAtomicAnd_01H20D00D + 1586, // imageAtomicAnd_01S20D00D + 1588, // imageAtomicAnd_01d20D00D + 1590, // imageAtomicAnd_01D00D00D + 1592, // imageAtomicAnd_01O00D00D + 1594, // imageAtomicAnd_01Z00D00D + 1596, // imageAtomicAnd_01E10D00D + 1598, // imageAtomicAnd_01P10D00D + 1600, // imageAtomicAnd_01a10D00D + 1602, // imageAtomicAnd_01I10D00D + 1604, // imageAtomicAnd_01T10D00D + 1606, // imageAtomicAnd_01e10D00D + 1608, // imageAtomicAnd_01F10D00D00D + 1610, // imageAtomicAnd_01Q10D00D00D + 1612, // imageAtomicAnd_01b10D00D00D + 1614, // imageAtomicAnd_01G20D00D00D + 1616, // imageAtomicAnd_01R20D00D00D + 1618, // imageAtomicAnd_01c20D00D00D + 1620, // imageAtomicOr_00z10D00E + 1622, // imageAtomicOr_01K10D00E + 1624, // imageAtomicOr_01V10D00E + 1626, // imageAtomicOr_01A20D00E + 1628, // imageAtomicOr_01L20D00E + 1630, // imageAtomicOr_01W20D00E + 1632, // imageAtomicOr_01C20D00E + 1634, // imageAtomicOr_01N20D00E + 1636, // imageAtomicOr_01Y20D00E + 1638, // imageAtomicOr_01J00D00E + 1640, // imageAtomicOr_01U00D00E + 1642, // imageAtomicOr_01f00D00E + 1644, // imageAtomicOr_01B20D00E + 1646, // imageAtomicOr_01M20D00E + 1648, // imageAtomicOr_01X20D00E + 1650, // imageAtomicOr_01H20D00E + 1652, // imageAtomicOr_01S20D00E + 1654, // imageAtomicOr_01d20D00E + 1656, // imageAtomicOr_01D00D00E + 1658, // imageAtomicOr_01O00D00E + 1660, // imageAtomicOr_01Z00D00E + 1662, // imageAtomicOr_01E10D00E + 1664, // imageAtomicOr_01P10D00E + 1666, // imageAtomicOr_01a10D00E + 1668, // imageAtomicOr_01I10D00E + 1670, // imageAtomicOr_01T10D00E + 1672, // imageAtomicOr_01e10D00E + 1674, // imageAtomicOr_01F10D00D00E + 1676, // imageAtomicOr_01Q10D00D00E + 1678, // imageAtomicOr_01b10D00D00E + 1680, // imageAtomicOr_01G20D00D00E + 1682, // imageAtomicOr_01R20D00D00E + 1684, // imageAtomicOr_01c20D00D00E + 1686, // imageAtomicOr_00z10D00D + 1688, // imageAtomicOr_01K10D00D + 1690, // imageAtomicOr_01V10D00D + 1692, // imageAtomicOr_01A20D00D + 1694, // imageAtomicOr_01L20D00D + 1696, // imageAtomicOr_01W20D00D + 1698, // imageAtomicOr_01C20D00D + 1700, // imageAtomicOr_01N20D00D + 1702, // imageAtomicOr_01Y20D00D + 1704, // imageAtomicOr_01J00D00D + 1706, // imageAtomicOr_01U00D00D + 1708, // imageAtomicOr_01f00D00D + 1710, // imageAtomicOr_01B20D00D + 1712, // imageAtomicOr_01M20D00D + 1714, // imageAtomicOr_01X20D00D + 1716, // imageAtomicOr_01H20D00D + 1718, // imageAtomicOr_01S20D00D + 1720, // imageAtomicOr_01d20D00D + 1722, // imageAtomicOr_01D00D00D + 1724, // imageAtomicOr_01O00D00D + 1726, // imageAtomicOr_01Z00D00D + 1728, // imageAtomicOr_01E10D00D + 1730, // imageAtomicOr_01P10D00D + 1732, // imageAtomicOr_01a10D00D + 1734, // imageAtomicOr_01I10D00D + 1736, // imageAtomicOr_01T10D00D + 1738, // imageAtomicOr_01e10D00D + 1740, // imageAtomicOr_01F10D00D00D + 1742, // imageAtomicOr_01Q10D00D00D + 1744, // imageAtomicOr_01b10D00D00D + 1746, // imageAtomicOr_01G20D00D00D + 1748, // imageAtomicOr_01R20D00D00D + 1750, // imageAtomicOr_01c20D00D00D + 1752, // imageAtomicXor_00z10D00E + 1754, // imageAtomicXor_01K10D00E + 1756, // imageAtomicXor_01V10D00E + 1758, // imageAtomicXor_01A20D00E + 1760, // imageAtomicXor_01L20D00E + 1762, // imageAtomicXor_01W20D00E + 1764, // imageAtomicXor_01C20D00E + 1766, // imageAtomicXor_01N20D00E + 1768, // imageAtomicXor_01Y20D00E + 1770, // imageAtomicXor_01J00D00E + 1772, // imageAtomicXor_01U00D00E + 1774, // imageAtomicXor_01f00D00E + 1776, // imageAtomicXor_01B20D00E + 1778, // imageAtomicXor_01M20D00E + 1780, // imageAtomicXor_01X20D00E + 1782, // imageAtomicXor_01H20D00E + 1784, // imageAtomicXor_01S20D00E + 1786, // imageAtomicXor_01d20D00E + 1788, // imageAtomicXor_01D00D00E + 1790, // imageAtomicXor_01O00D00E + 1792, // imageAtomicXor_01Z00D00E + 1794, // imageAtomicXor_01E10D00E + 1796, // imageAtomicXor_01P10D00E + 1798, // imageAtomicXor_01a10D00E + 1800, // imageAtomicXor_01I10D00E + 1802, // imageAtomicXor_01T10D00E + 1804, // imageAtomicXor_01e10D00E + 1806, // imageAtomicXor_01F10D00D00E + 1808, // imageAtomicXor_01Q10D00D00E + 1810, // imageAtomicXor_01b10D00D00E + 1812, // imageAtomicXor_01G20D00D00E + 1814, // imageAtomicXor_01R20D00D00E + 1816, // imageAtomicXor_01c20D00D00E + 1818, // imageAtomicXor_00z10D00D + 1820, // imageAtomicXor_01K10D00D + 1822, // imageAtomicXor_01V10D00D + 1824, // imageAtomicXor_01A20D00D + 1826, // imageAtomicXor_01L20D00D + 1828, // imageAtomicXor_01W20D00D + 1830, // imageAtomicXor_01C20D00D + 1832, // imageAtomicXor_01N20D00D + 1834, // imageAtomicXor_01Y20D00D + 1836, // imageAtomicXor_01J00D00D + 1838, // imageAtomicXor_01U00D00D + 1840, // imageAtomicXor_01f00D00D + 1842, // imageAtomicXor_01B20D00D + 1844, // imageAtomicXor_01M20D00D + 1846, // imageAtomicXor_01X20D00D + 1848, // imageAtomicXor_01H20D00D + 1850, // imageAtomicXor_01S20D00D + 1852, // imageAtomicXor_01d20D00D + 1854, // imageAtomicXor_01D00D00D + 1856, // imageAtomicXor_01O00D00D + 1858, // imageAtomicXor_01Z00D00D + 1860, // imageAtomicXor_01E10D00D + 1862, // imageAtomicXor_01P10D00D + 1864, // imageAtomicXor_01a10D00D + 1866, // imageAtomicXor_01I10D00D + 1868, // imageAtomicXor_01T10D00D + 1870, // imageAtomicXor_01e10D00D + 1872, // imageAtomicXor_01F10D00D00D + 1874, // imageAtomicXor_01Q10D00D00D + 1876, // imageAtomicXor_01b10D00D00D + 1878, // imageAtomicXor_01G20D00D00D + 1880, // imageAtomicXor_01R20D00D00D + 1882, // imageAtomicXor_01c20D00D00D + 1884, // imageAtomicExchange_00z10D00E + 1886, // imageAtomicExchange_01K10D00E + 1888, // imageAtomicExchange_01V10D00E + 1890, // imageAtomicExchange_01A20D00E + 1892, // imageAtomicExchange_01L20D00E + 1894, // imageAtomicExchange_01W20D00E + 1896, // imageAtomicExchange_01C20D00E + 1898, // imageAtomicExchange_01N20D00E + 1900, // imageAtomicExchange_01Y20D00E + 1902, // imageAtomicExchange_01J00D00E + 1904, // imageAtomicExchange_01U00D00E + 1906, // imageAtomicExchange_01f00D00E + 1908, // imageAtomicExchange_01B20D00E + 1910, // imageAtomicExchange_01M20D00E + 1912, // imageAtomicExchange_01X20D00E + 1914, // imageAtomicExchange_01H20D00E + 1916, // imageAtomicExchange_01S20D00E + 1918, // imageAtomicExchange_01d20D00E + 1920, // imageAtomicExchange_01D00D00E + 1922, // imageAtomicExchange_01O00D00E + 1924, // imageAtomicExchange_01Z00D00E + 1926, // imageAtomicExchange_01E10D00E + 1928, // imageAtomicExchange_01P10D00E + 1930, // imageAtomicExchange_01a10D00E + 1932, // imageAtomicExchange_01I10D00E + 1934, // imageAtomicExchange_01T10D00E + 1936, // imageAtomicExchange_01e10D00E + 1938, // imageAtomicExchange_01F10D00D00E + 1940, // imageAtomicExchange_01Q10D00D00E + 1942, // imageAtomicExchange_01b10D00D00E + 1944, // imageAtomicExchange_01G20D00D00E + 1946, // imageAtomicExchange_01R20D00D00E + 1948, // imageAtomicExchange_01c20D00D00E + 1950, // imageAtomicExchange_00z10D00D + 1952, // imageAtomicExchange_01K10D00D + 1954, // imageAtomicExchange_01V10D00D + 1956, // imageAtomicExchange_01A20D00D + 1958, // imageAtomicExchange_01L20D00D + 1960, // imageAtomicExchange_01W20D00D + 1962, // imageAtomicExchange_01C20D00D + 1964, // imageAtomicExchange_01N20D00D + 1966, // imageAtomicExchange_01Y20D00D + 1968, // imageAtomicExchange_01J00D00D + 1970, // imageAtomicExchange_01U00D00D + 1972, // imageAtomicExchange_01f00D00D + 1974, // imageAtomicExchange_01B20D00D + 1976, // imageAtomicExchange_01M20D00D + 1978, // imageAtomicExchange_01X20D00D + 1980, // imageAtomicExchange_01H20D00D + 1982, // imageAtomicExchange_01S20D00D + 1984, // imageAtomicExchange_01d20D00D + 1986, // imageAtomicExchange_01D00D00D + 1988, // imageAtomicExchange_01O00D00D + 1990, // imageAtomicExchange_01Z00D00D + 1992, // imageAtomicExchange_01E10D00D + 1994, // imageAtomicExchange_01P10D00D + 1996, // imageAtomicExchange_01a10D00D + 1998, // imageAtomicExchange_01I10D00D + 2000, // imageAtomicExchange_01T10D00D + 2002, // imageAtomicExchange_01e10D00D + 2004, // imageAtomicExchange_01F10D00D00D + 2006, // imageAtomicExchange_01Q10D00D00D + 2008, // imageAtomicExchange_01b10D00D00D + 2010, // imageAtomicExchange_01G20D00D00D + 2012, // imageAtomicExchange_01R20D00D00D + 2014, // imageAtomicExchange_01c20D00D00D + 2016, // imageAtomicExchange_00z10D00B + 2018, // imageAtomicExchange_01K10D00B + 2020, // imageAtomicExchange_01V10D00B + 2022, // imageAtomicExchange_01A20D00B + 2024, // imageAtomicExchange_01L20D00B + 2026, // imageAtomicExchange_01W20D00B + 2028, // imageAtomicExchange_01C20D00B + 2030, // imageAtomicExchange_01N20D00B + 2032, // imageAtomicExchange_01Y20D00B + 2034, // imageAtomicExchange_01J00D00B + 2036, // imageAtomicExchange_01U00D00B + 2038, // imageAtomicExchange_01f00D00B + 2040, // imageAtomicExchange_01B20D00B + 2042, // imageAtomicExchange_01M20D00B + 2044, // imageAtomicExchange_01X20D00B + 2046, // imageAtomicExchange_01H20D00B + 2048, // imageAtomicExchange_01S20D00B + 2050, // imageAtomicExchange_01d20D00B + 2052, // imageAtomicExchange_01D00D00B + 2054, // imageAtomicExchange_01O00D00B + 2056, // imageAtomicExchange_01Z00D00B + 2058, // imageAtomicExchange_01E10D00B + 2060, // imageAtomicExchange_01P10D00B + 2062, // imageAtomicExchange_01a10D00B + 2064, // imageAtomicExchange_01I10D00B + 2066, // imageAtomicExchange_01T10D00B + 2068, // imageAtomicExchange_01e10D00B + 2070, // imageAtomicExchange_01F10D00D00B + 2072, // imageAtomicExchange_01Q10D00D00B + 2074, // imageAtomicExchange_01b10D00D00B + 2076, // imageAtomicExchange_01G20D00D00B + 2078, // imageAtomicExchange_01R20D00D00B + 2080, // imageAtomicExchange_01c20D00D00B + 2082, // imageAtomicCompSwap_00z10D00E00E + 2084, // imageAtomicCompSwap_01K10D00E00E + 2086, // imageAtomicCompSwap_01V10D00E00E + 2088, // imageAtomicCompSwap_01A20D00E00E + 2090, // imageAtomicCompSwap_01L20D00E00E + 2092, // imageAtomicCompSwap_01W20D00E00E + 2094, // imageAtomicCompSwap_01C20D00E00E + 2096, // imageAtomicCompSwap_01N20D00E00E + 2098, // imageAtomicCompSwap_01Y20D00E00E + 2100, // imageAtomicCompSwap_01J00D00E00E + 2102, // imageAtomicCompSwap_01U00D00E00E + 2104, // imageAtomicCompSwap_01f00D00E00E + 2106, // imageAtomicCompSwap_01B20D00E00E + 2108, // imageAtomicCompSwap_01M20D00E00E + 2110, // imageAtomicCompSwap_01X20D00E00E + 2112, // imageAtomicCompSwap_01H20D00E00E + 2114, // imageAtomicCompSwap_01S20D00E00E + 2116, // imageAtomicCompSwap_01d20D00E00E + 2118, // imageAtomicCompSwap_01D00D00E00E + 2120, // imageAtomicCompSwap_01O00D00E00E + 2122, // imageAtomicCompSwap_01Z00D00E00E + 2124, // imageAtomicCompSwap_01E10D00E00E + 2126, // imageAtomicCompSwap_01P10D00E00E + 2128, // imageAtomicCompSwap_01a10D00E00E + 2130, // imageAtomicCompSwap_01I10D00E00E + 2132, // imageAtomicCompSwap_01T10D00E00E + 2134, // imageAtomicCompSwap_01e10D00E00E + 2136, // imageAtomicCompSwap_01F10D00D00E00E + 2138, // imageAtomicCompSwap_01Q10D00D00E00E + 2140, // imageAtomicCompSwap_01b10D00D00E00E + 2142, // imageAtomicCompSwap_01G20D00D00E00E + 2144, // imageAtomicCompSwap_01R20D00D00E00E + 2146, // imageAtomicCompSwap_01c20D00D00E00E + 2148, // imageAtomicCompSwap_00z10D00D00D + 2150, // imageAtomicCompSwap_01K10D00D00D + 2152, // imageAtomicCompSwap_01V10D00D00D + 2154, // imageAtomicCompSwap_01A20D00D00D + 2156, // imageAtomicCompSwap_01L20D00D00D + 2158, // imageAtomicCompSwap_01W20D00D00D + 2160, // imageAtomicCompSwap_01C20D00D00D + 2162, // imageAtomicCompSwap_01N20D00D00D + 2164, // imageAtomicCompSwap_01Y20D00D00D + 2166, // imageAtomicCompSwap_01J00D00D00D + 2168, // imageAtomicCompSwap_01U00D00D00D + 2170, // imageAtomicCompSwap_01f00D00D00D + 2172, // imageAtomicCompSwap_01B20D00D00D + 2174, // imageAtomicCompSwap_01M20D00D00D + 2176, // imageAtomicCompSwap_01X20D00D00D + 2178, // imageAtomicCompSwap_01H20D00D00D + 2180, // imageAtomicCompSwap_01S20D00D00D + 2182, // imageAtomicCompSwap_01d20D00D00D + 2184, // imageAtomicCompSwap_01D00D00D00D + 2186, // imageAtomicCompSwap_01O00D00D00D + 2188, // imageAtomicCompSwap_01Z00D00D00D + 2190, // imageAtomicCompSwap_01E10D00D00D + 2192, // imageAtomicCompSwap_01P10D00D00D + 2194, // imageAtomicCompSwap_01a10D00D00D + 2196, // imageAtomicCompSwap_01I10D00D00D + 2198, // imageAtomicCompSwap_01T10D00D00D + 2200, // imageAtomicCompSwap_01e10D00D00D + 2202, // imageAtomicCompSwap_01F10D00D00D00D + 2204, // imageAtomicCompSwap_01Q10D00D00D00D + 2206, // imageAtomicCompSwap_01b10D00D00D00D + 2208, // imageAtomicCompSwap_01G20D00D00D00D + 2210, // imageAtomicCompSwap_01R20D00D00D00D + 2212, // imageAtomicCompSwap_01c20D00D00D00D + 2214, // pixelLocalLoadANGLE_01g + 2215, // pixelLocalLoadANGLE_01h + 2216, // pixelLocalLoadANGLE_01i + 2217, // pixelLocalStoreANGLE_01g30B + 2218, // pixelLocalStoreANGLE_01h30D + 2219, // pixelLocalStoreANGLE_01i30E + 2220, // beginInvocationInterlockNV_ + 2221, // endInvocationInterlockNV_ + 2222, // beginFragmentShaderOrderingINTEL_ + 2223, // beginInvocationInterlockARB_ + 2224, // endInvocationInterlockARB_ + 2225, // memoryBarrier_ + 2226, // memoryBarrierAtomicCounter_ + 2227, // memoryBarrierBuffer_ + 2228, // memoryBarrierImage_ + 2229, // barrier_ + 2232, // memoryBarrierShared_ + 2233, // groupMemoryBarrier_ + 2234, // EmitVertex_ + 2237, // EndPrimitive_ + 2240, // subpassLoad_01j + 2241, // subpassLoad_01k + 2242, // subpassLoad_01l + 2243, // subpassLoad_01m00D + 2244, // subpassLoad_01n00D + 2245, // subpassLoad_01o00D + 2246, // gl_DepthRangeParameters + 2247, // gl_DepthRange + 2248, // gl_NumSamples + 2250, // gl_MaxVertexAttribs + 2251, // gl_MaxVertexUniformVectors + 2252, // gl_MaxVertexTextureImageUnits + 2253, // gl_MaxCombinedTextureImageUnits + 2254, // gl_MaxTextureImageUnits + 2255, // gl_MaxFragmentUniformVectors + 2256, // gl_MaxVaryingVectors + 2257, // gl_MaxDrawBuffers + 2258, // gl_MaxDualSourceDrawBuffersEXT + 2259, // gl_MaxVertexOutputVectors + 2260, // gl_MaxFragmentInputVectors + 2261, // gl_MinProgramTexelOffset + 2262, // gl_MaxProgramTexelOffset + 2263, // gl_MaxImageUnits + 2264, // gl_MaxVertexImageUniforms + 2265, // gl_MaxFragmentImageUniforms + 2266, // gl_MaxComputeImageUniforms + 2267, // gl_MaxCombinedImageUniforms + 2268, // gl_MaxCombinedShaderOutputResources + 2269, // gl_MaxComputeWorkGroupCount + 2270, // gl_MaxComputeWorkGroupSize + 2271, // gl_MaxComputeUniformComponents + 2272, // gl_MaxComputeTextureImageUnits + 2273, // gl_MaxComputeAtomicCounters + 2274, // gl_MaxComputeAtomicCounterBuffers + 2275, // gl_MaxVertexAtomicCounters + 2276, // gl_MaxFragmentAtomicCounters + 2277, // gl_MaxCombinedAtomicCounters + 2278, // gl_MaxAtomicCounterBindings + 2279, // gl_MaxVertexAtomicCounterBuffers + 2280, // gl_MaxFragmentAtomicCounterBuffers + 2281, // gl_MaxCombinedAtomicCounterBuffers + 2282, // gl_MaxAtomicCounterBufferSize + 2283, // gl_MaxGeometryInputComponents + 2286, // gl_MaxGeometryOutputComponents + 2289, // gl_MaxGeometryImageUniforms + 2292, // gl_MaxGeometryTextureImageUnits + 2295, // gl_MaxGeometryOutputVertices + 2298, // gl_MaxGeometryTotalOutputComponents + 2301, // gl_MaxGeometryUniformComponents + 2304, // gl_MaxGeometryAtomicCounters + 2307, // gl_MaxGeometryAtomicCounterBuffers + 2310, // gl_MaxTessControlInputComponents + 2312, // gl_MaxTessControlOutputComponents + 2314, // gl_MaxTessControlTextureImageUnits + 2316, // gl_MaxTessControlUniformComponents + 2318, // gl_MaxTessControlTotalOutputComponents + 2320, // gl_MaxTessControlImageUniforms + 2322, // gl_MaxTessControlAtomicCounters + 2324, // gl_MaxTessControlAtomicCounterBuffers + 2326, // gl_MaxTessPatchComponents + 2328, // gl_MaxPatchVertices + 2330, // gl_MaxTessGenLevel + 2332, // gl_MaxTessEvaluationInputComponents + 2334, // gl_MaxTessEvaluationOutputComponents + 2336, // gl_MaxTessEvaluationTextureImageUnits + 2338, // gl_MaxTessEvaluationUniformComponents + 2340, // gl_MaxTessEvaluationImageUniforms + 2342, // gl_MaxTessEvaluationAtomicCounters + 2344, // gl_MaxTessEvaluationAtomicCounterBuffers + 2346, // gl_MaxSamples + 2348, // gl_MaxClipDistances + 2349, // gl_MaxCullDistances + 2350, // gl_MaxCombinedClipAndCullDistances + 2351, // gl_FragCoord + 2353, // gl_FrontFacing + 2354, // gl_PointCoord + 2355, // gl_FragColor + 2356, // gl_FragData + 2357, // gl_FragDepth + 2358, // gl_HelperInvocation + 2359, // gl_SecondaryFragColorEXT + 2360, // gl_SecondaryFragDataEXT + 2361, // gl_FragDepthEXT + 2362, // gl_LastFragData + 2365, // gl_LastFragColor + 2366, // gl_LastFragColorARM + 2367, // gl_PrimitiveID + 2377, // gl_Layer + 2383, // gl_SampleID + 2385, // gl_SamplePosition + 2387, // gl_SampleMaskIn + 2389, // gl_SampleMask + 2391, // gl_CullDistance + 2393, // gl_ClipDistance + 2395, // gl_Position + 2403, // gl_PointSize + 2405, // gl_InstanceID + 2406, // Empty + 2406, // gl_VertexID + 2407, // Empty + 2407, // Empty + 2407, // gl_DrawID + 2408, // gl_BaseVertex + 2409, // gl_BaseInstance + 2410, // angle_BaseVertex + 2411, // angle_BaseInstance + 2412, // gl_NumWorkGroups + 2413, // gl_WorkGroupSize + 2414, // gl_WorkGroupID + 2415, // gl_LocalInvocationID + 2416, // gl_GlobalInvocationID + 2417, // gl_LocalInvocationIndex + 2418, // gl_PrimitiveIDIn + 2421, // gl_InvocationID + 2426, // gl_PerVertex + 2433, // gl_in + 2440, // gl_PatchVerticesIn + 2444, // gl_TessLevelOuter + 2448, // gl_TessLevelInner + 2452, // gl_out + 2456, // gl_BoundingBox + 2458, // gl_BoundingBoxEXT + 2460, // gl_BoundingBoxOES + 2462, // gl_TessCoord + 2463, // gl_ViewID_OVR +}; + +using Ext = TExtension; + +// Flat array of all unmangled name identifiers. +constexpr UnmangledEntry unmangled[] = { + {"radians", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"degrees", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"sin", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"cos", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"tan", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"asin", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"acos", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"atan", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"sinh", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"cosh", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"tanh", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"asinh", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"acosh", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"atanh", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"pow", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"exp", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"log", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"exp2", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"log2", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"sqrt", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"inversesqrt", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"abs", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"sign", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"floor", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"trunc", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"round", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"roundEven", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, + Shader::ALL}, + {"ceil", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"fract", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"mod", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"min", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"max", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"clamp", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"mix", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 450, Shader::ALL}, + {"step", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"smoothstep", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"modf", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"isnan", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"isinf", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, Shader::ALL}, + {"floatBitsToInt", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 330, + Shader::ALL}, + {"floatBitsToUint", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 330, + Shader::ALL}, + {"intBitsToFloat", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 330, + Shader::ALL}, + {"uintBitsToFloat", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 330, + Shader::ALL}, + {"fma", std::array{{Ext::EXT_gpu_shader5}}, Ext::UNDEFINED, 310, -1, + Shader::ALL}, + {"frexp", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, Shader::ALL}, + {"ldexp", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, Shader::ALL}, + {"packSnorm2x16", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 420, + Shader::ALL}, + {"packHalf2x16", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 420, + Shader::ALL}, + {"unpackSnorm2x16", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 420, + Shader::ALL}, + {"unpackHalf2x16", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 420, + Shader::ALL}, + {"packUnorm2x16", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 400, + Shader::ALL}, + {"unpackUnorm2x16", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 400, + Shader::ALL}, + {"packUnorm4x8", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, + Shader::ALL}, + {"packSnorm4x8", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, + Shader::ALL}, + {"unpackUnorm4x8", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, + Shader::ALL}, + {"unpackSnorm4x8", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, + Shader::ALL}, + {"length", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"distance", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"dot", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"cross", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"normalize", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"faceforward", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"reflect", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"refract", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"matrixCompMult", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, -1, + Shader::ALL}, + {"outerProduct", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 120, + Shader::ALL}, + {"transpose", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 120, + Shader::ALL}, + {"determinant", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, -1, + Shader::ALL}, + {"inverse", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 140, Shader::ALL}, + {"lessThan", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, + Shader::ALL}, + {"lessThanEqual", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, + Shader::ALL}, + {"greaterThan", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, + Shader::ALL}, + {"greaterThanEqual", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, + Shader::ALL}, + {"equal", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"notEqual", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"any", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"all", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"not", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 0, 0, Shader::ALL}, + {"bitfieldExtract", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, + Shader::ALL}, + {"bitfieldInsert", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, + Shader::ALL}, + {"bitfieldReverse", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, + Shader::ALL}, + {"bitCount", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, + Shader::ALL}, + {"findLSB", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, Shader::ALL}, + {"findMSB", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, Shader::ALL}, + {"uaddCarry", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, + Shader::ALL}, + {"usubBorrow", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, + Shader::ALL}, + {"umulExtended", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, + Shader::ALL}, + {"imulExtended", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, + Shader::ALL}, + {"texture2D", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 100, 0, + Shader::FRAGMENT}, + {"texture2DProj", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 100, 0, + Shader::FRAGMENT}, + {"textureCube", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 100, 0, + Shader::ALL}, + {"texture3D", std::array{{Ext::OES_texture_3D}}, Ext::UNDEFINED, 100, -1, + Shader::FRAGMENT}, + {"texture3DProj", std::array{{Ext::OES_texture_3D}}, Ext::UNDEFINED, 100, -1, + Shader::FRAGMENT}, + {"shadow2DEXT", std::array{{Ext::EXT_shadow_samplers}}, Ext::UNDEFINED, 100, -1, + Shader::ALL}, + {"shadow2DProjEXT", std::array{{Ext::EXT_shadow_samplers}}, Ext::UNDEFINED, 100, + -1, Shader::ALL}, + {"texture2DRect", std::array{{Ext::ARB_texture_rectangle}}, Ext::UNDEFINED, 100, + -1, Shader::ALL}, + {"texture2DRectProj", std::array{{Ext::ARB_texture_rectangle}}, Ext::UNDEFINED, + 100, -1, Shader::ALL}, + {"texture2DGradEXT", std::array{{Ext::EXT_shader_texture_lod}}, Ext::UNDEFINED, + 100, -1, Shader::ALL}, + {"texture2DProjGradEXT", std::array{{Ext::EXT_shader_texture_lod}}, + Ext::UNDEFINED, 100, -1, Shader::ALL}, + {"textureCubeGradEXT", std::array{{Ext::EXT_shader_texture_lod}}, Ext::UNDEFINED, + 100, -1, Shader::ALL}, + {"textureVideoWEBGL", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 100, 0, + Shader::ALL}, + {"texture3DLod", std::array{{Ext::OES_texture_3D}}, Ext::UNDEFINED, 100, -1, + Shader::ALL}, + {"texture3DProjLod", std::array{{Ext::OES_texture_3D}}, Ext::UNDEFINED, 100, -1, + Shader::ALL}, + {"texture2DLod", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 100, -1, + Shader::VERTEX}, + {"texture2DProjLod", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 100, -1, + Shader::VERTEX}, + {"textureCubeLod", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 100, -1, + Shader::VERTEX}, + {"texture2DLodEXT", std::array{{Ext::EXT_shader_texture_lod}}, Ext::UNDEFINED, + 100, -1, Shader::FRAGMENT}, + {"texture2DProjLodEXT", std::array{{Ext::EXT_shader_texture_lod}}, + Ext::UNDEFINED, 100, -1, Shader::FRAGMENT}, + {"textureCubeLodEXT", std::array{{Ext::EXT_shader_texture_lod}}, Ext::UNDEFINED, + 100, -1, Shader::FRAGMENT}, + {"texture", std::array{{Ext::OES_EGL_image_external_essl3}}, Ext::UNDEFINED, 300, + -1, Shader::FRAGMENT}, + {"textureProj", std::array{{Ext::OES_EGL_image_external_essl3}}, Ext::UNDEFINED, + 300, -1, Shader::FRAGMENT}, + {"textureLod", + std::array{{Ext::OES_texture_cube_map_array, Ext::EXT_texture_cube_map_array}}, + Ext::UNDEFINED, 310, -1, Shader::ALL}, + {"textureSize", std::array{{Ext::OES_EGL_image_external_essl3}}, Ext::UNDEFINED, + 300, -1, Shader::ALL}, + {"textureProjLod", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, + Shader::ALL}, + {"texelFetch", std::array{{Ext::OES_EGL_image_external_essl3}}, Ext::UNDEFINED, + 300, -1, Shader::ALL}, + {"textureGrad", + std::array{{Ext::OES_texture_cube_map_array, Ext::EXT_texture_cube_map_array}}, + Ext::UNDEFINED, 310, -1, Shader::ALL}, + {"textureProjGrad", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, + Shader::ALL}, + {"textureOffset", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, + Shader::ALL}, + {"textureProjOffset", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, + Shader::ALL}, + {"textureLodOffset", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, + Shader::ALL}, + {"textureProjLodOffset", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, + Shader::ALL}, + {"texelFetchOffset", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, + Shader::ALL}, + {"textureGradOffset", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, + Shader::ALL}, + {"textureProjGradOffset", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 130, + Shader::ALL}, + {"textureGather", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, + Shader::ALL}, + {"textureGatherOffset", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 400, + Shader::ALL}, + {"textureGatherOffsets", std::array{{Ext::EXT_gpu_shader5}}, Ext::UNDEFINED, 310, + -1, Shader::ALL}, + {"rgb_2_yuv", std::array{{Ext::EXT_YUV_target}}, Ext::UNDEFINED, 300, -1, + Shader::ALL}, + {"yuv_2_rgb", std::array{{Ext::EXT_YUV_target}}, Ext::UNDEFINED, 300, -1, + Shader::ALL}, + {"dFdx", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 0, Shader::FRAGMENT}, + {"dFdy", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 0, Shader::FRAGMENT}, + {"fwidth", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 300, 0, + Shader::FRAGMENT}, + {"interpolateAtCentroid", + std::array{{Ext::OES_shader_multisample_interpolation}}, Ext::UNDEFINED, 300, + -1, Shader::FRAGMENT}, + {"interpolateAtSample", std::array{{Ext::OES_shader_multisample_interpolation}}, + Ext::UNDEFINED, 300, -1, Shader::FRAGMENT}, + {"interpolateAtOffset", std::array{{Ext::OES_shader_multisample_interpolation}}, + Ext::UNDEFINED, 300, -1, Shader::FRAGMENT}, + {"atomicCounter", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 420, + Shader::ALL}, + {"atomicCounterIncrement", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, + 420, Shader::ALL}, + {"atomicCounterDecrement", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, + 420, Shader::ALL}, + {"atomicAdd", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 430, + Shader::ALL}, + {"atomicMin", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 430, + Shader::ALL}, + {"atomicMax", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 430, + Shader::ALL}, + {"atomicAnd", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 430, + Shader::ALL}, + {"atomicOr", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 430, + Shader::ALL}, + {"atomicXor", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 430, + Shader::ALL}, + {"atomicExchange", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 430, + Shader::ALL}, + {"atomicCompSwap", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 430, + Shader::ALL}, + {"imageSize", std::array{{Ext::OES_texture_buffer, Ext::EXT_texture_buffer}}, + Ext::UNDEFINED, 310, -1, Shader::ALL}, + {"imageStore", std::array{{Ext::OES_texture_buffer, Ext::EXT_texture_buffer}}, + Ext::UNDEFINED, 310, -1, Shader::ALL}, + {"imageLoad", std::array{{Ext::OES_texture_buffer, Ext::EXT_texture_buffer}}, + Ext::UNDEFINED, 310, -1, Shader::ALL}, + {"imageAtomicAdd", std::array{{Ext::OES_shader_image_atomic}}, Ext::UNDEFINED, + 310, -1, Shader::ALL}, + {"imageAtomicMin", std::array{{Ext::OES_shader_image_atomic}}, Ext::UNDEFINED, + 310, -1, Shader::ALL}, + {"imageAtomicMax", std::array{{Ext::OES_shader_image_atomic}}, Ext::UNDEFINED, + 310, -1, Shader::ALL}, + {"imageAtomicAnd", std::array{{Ext::OES_shader_image_atomic}}, Ext::UNDEFINED, + 310, -1, Shader::ALL}, + {"imageAtomicOr", std::array{{Ext::OES_shader_image_atomic}}, Ext::UNDEFINED, + 310, -1, Shader::ALL}, + {"imageAtomicXor", std::array{{Ext::OES_shader_image_atomic}}, Ext::UNDEFINED, + 310, -1, Shader::ALL}, + {"imageAtomicExchange", std::array{{Ext::OES_shader_image_atomic}}, + Ext::UNDEFINED, 310, -1, Shader::ALL}, + {"imageAtomicCompSwap", std::array{{Ext::OES_shader_image_atomic}}, + Ext::UNDEFINED, 310, -1, Shader::ALL}, + {"pixelLocalLoadANGLE", std::array{{Ext::ANGLE_shader_pixel_local_storage}}, + Ext::UNDEFINED, 300, -1, Shader::ALL}, + {"pixelLocalStoreANGLE", std::array{{Ext::ANGLE_shader_pixel_local_storage}}, + Ext::UNDEFINED, 300, -1, Shader::ALL}, + {"beginInvocationInterlockNV", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, + kESSLInternalBackendBuiltIns, -1, Shader::ALL}, + {"endInvocationInterlockNV", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, + kESSLInternalBackendBuiltIns, -1, Shader::ALL}, + {"beginFragmentShaderOrderingINTEL", std::array{{Ext::UNDEFINED}}, + Ext::UNDEFINED, kESSLInternalBackendBuiltIns, -1, Shader::ALL}, + {"beginInvocationInterlockARB", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, + kESSLInternalBackendBuiltIns, -1, Shader::ALL}, + {"endInvocationInterlockARB", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, + kESSLInternalBackendBuiltIns, -1, Shader::ALL}, + {"memoryBarrier", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 420, + Shader::ALL}, + {"memoryBarrierAtomicCounter", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, + 430, Shader::ALL}, + {"memoryBarrierBuffer", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 430, + Shader::ALL}, + {"memoryBarrierImage", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 430, + Shader::ALL}, + {"barrier", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 320, -1, + Shader::TESS_CONTROL_EXT}, + {"memoryBarrierShared", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 430, + Shader::COMPUTE}, + {"groupMemoryBarrier", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 310, 430, + Shader::COMPUTE}, + {"EmitVertex", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 320, -1, + Shader::GEOMETRY}, + {"EndPrimitive", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, 320, -1, + Shader::GEOMETRY}, + {"subpassLoad", std::array{{Ext::UNDEFINED}}, Ext::UNDEFINED, + kESSLInternalBackendBuiltIns, 460, Shader::ALL}}; + +} // namespace BuiltInArray + +void TSymbolTable::initializeBuiltInVariables(sh::GLenum shaderType, + ShShaderSpec spec, + const ShBuiltInResources &resources) +{ + const TSourceLoc zeroSourceLoc = {0, 0, 0, 0}; + TFieldList *fields_gl_DepthRangeParameters = new TFieldList(); + fields_gl_DepthRangeParameters->push_back( + new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1), BuiltInName::near, zeroSourceLoc, + SymbolType::BuiltIn)); + fields_gl_DepthRangeParameters->push_back( + new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1), BuiltInName::far, zeroSourceLoc, + SymbolType::BuiltIn)); + fields_gl_DepthRangeParameters->push_back( + new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1), BuiltInName::diff, zeroSourceLoc, + SymbolType::BuiltIn)); + TStructure *gl_DepthRangeParameters = new TStructure( + BuiltInId::gl_DepthRangeParameters, BuiltInName::gl_DepthRangeParameters, + std::array{{TExtension::UNDEFINED}}, fields_gl_DepthRangeParameters); + m_gl_DepthRangeParameters = gl_DepthRangeParameters; + TType *type_gl_DepthRange = new TType(gl_DepthRangeParameters, false); + type_gl_DepthRange->setQualifier(EvqUniform); + type_gl_DepthRange->realize(); + m_gl_DepthRange = + new TVariable(BuiltInId::gl_DepthRange, BuiltInName::gl_DepthRange, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_DepthRange); + m_gl_MaxVertexAttribs = + new TVariable(BuiltInId::gl_MaxVertexAttribs, BuiltInName::gl_MaxVertexAttribs, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxVertexAttribs); + static_cast(m_gl_MaxVertexAttribs)->shareConstPointer(unionArray); + } + m_gl_MaxVertexUniformVectors = new TVariable( + BuiltInId::gl_MaxVertexUniformVectors, BuiltInName::gl_MaxVertexUniformVectors, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxVertexUniformVectors); + static_cast(m_gl_MaxVertexUniformVectors)->shareConstPointer(unionArray); + } + m_gl_MaxVertexTextureImageUnits = new TVariable( + BuiltInId::gl_MaxVertexTextureImageUnits, BuiltInName::gl_MaxVertexTextureImageUnits, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxVertexTextureImageUnits); + static_cast(m_gl_MaxVertexTextureImageUnits)->shareConstPointer(unionArray); + } + m_gl_MaxCombinedTextureImageUnits = new TVariable( + BuiltInId::gl_MaxCombinedTextureImageUnits, BuiltInName::gl_MaxCombinedTextureImageUnits, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxCombinedTextureImageUnits); + static_cast(m_gl_MaxCombinedTextureImageUnits)->shareConstPointer(unionArray); + } + m_gl_MaxTextureImageUnits = + new TVariable(BuiltInId::gl_MaxTextureImageUnits, BuiltInName::gl_MaxTextureImageUnits, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTextureImageUnits); + static_cast(m_gl_MaxTextureImageUnits)->shareConstPointer(unionArray); + } + m_gl_MaxFragmentUniformVectors = new TVariable( + BuiltInId::gl_MaxFragmentUniformVectors, BuiltInName::gl_MaxFragmentUniformVectors, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxFragmentUniformVectors); + static_cast(m_gl_MaxFragmentUniformVectors)->shareConstPointer(unionArray); + } + m_gl_MaxVaryingVectors = + new TVariable(BuiltInId::gl_MaxVaryingVectors, BuiltInName::gl_MaxVaryingVectors, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxVaryingVectors); + static_cast(m_gl_MaxVaryingVectors)->shareConstPointer(unionArray); + } + m_gl_MaxDrawBuffers = + new TVariable(BuiltInId::gl_MaxDrawBuffers, BuiltInName::gl_MaxDrawBuffers, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxDrawBuffers); + static_cast(m_gl_MaxDrawBuffers)->shareConstPointer(unionArray); + } + m_gl_MaxDualSourceDrawBuffersEXT = new TVariable( + BuiltInId::gl_MaxDualSourceDrawBuffersEXT, BuiltInName::gl_MaxDualSourceDrawBuffersEXT, + SymbolType::BuiltIn, std::array{{TExtension::EXT_blend_func_extended}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxDualSourceDrawBuffers); + static_cast(m_gl_MaxDualSourceDrawBuffersEXT)->shareConstPointer(unionArray); + } + m_gl_MaxVertexOutputVectors = + new TVariable(BuiltInId::gl_MaxVertexOutputVectors, BuiltInName::gl_MaxVertexOutputVectors, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxVertexOutputVectors); + static_cast(m_gl_MaxVertexOutputVectors)->shareConstPointer(unionArray); + } + m_gl_MaxFragmentInputVectors = new TVariable( + BuiltInId::gl_MaxFragmentInputVectors, BuiltInName::gl_MaxFragmentInputVectors, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxFragmentInputVectors); + static_cast(m_gl_MaxFragmentInputVectors)->shareConstPointer(unionArray); + } + m_gl_MinProgramTexelOffset = + new TVariable(BuiltInId::gl_MinProgramTexelOffset, BuiltInName::gl_MinProgramTexelOffset, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MinProgramTexelOffset); + static_cast(m_gl_MinProgramTexelOffset)->shareConstPointer(unionArray); + } + m_gl_MaxProgramTexelOffset = + new TVariable(BuiltInId::gl_MaxProgramTexelOffset, BuiltInName::gl_MaxProgramTexelOffset, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxProgramTexelOffset); + static_cast(m_gl_MaxProgramTexelOffset)->shareConstPointer(unionArray); + } + m_gl_MaxImageUnits = + new TVariable(BuiltInId::gl_MaxImageUnits, BuiltInName::gl_MaxImageUnits, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxImageUnits); + static_cast(m_gl_MaxImageUnits)->shareConstPointer(unionArray); + } + m_gl_MaxVertexImageUniforms = + new TVariable(BuiltInId::gl_MaxVertexImageUniforms, BuiltInName::gl_MaxVertexImageUniforms, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxVertexImageUniforms); + static_cast(m_gl_MaxVertexImageUniforms)->shareConstPointer(unionArray); + } + m_gl_MaxFragmentImageUniforms = new TVariable( + BuiltInId::gl_MaxFragmentImageUniforms, BuiltInName::gl_MaxFragmentImageUniforms, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxFragmentImageUniforms); + static_cast(m_gl_MaxFragmentImageUniforms)->shareConstPointer(unionArray); + } + m_gl_MaxComputeImageUniforms = new TVariable( + BuiltInId::gl_MaxComputeImageUniforms, BuiltInName::gl_MaxComputeImageUniforms, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxComputeImageUniforms); + static_cast(m_gl_MaxComputeImageUniforms)->shareConstPointer(unionArray); + } + m_gl_MaxCombinedImageUniforms = new TVariable( + BuiltInId::gl_MaxCombinedImageUniforms, BuiltInName::gl_MaxCombinedImageUniforms, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxCombinedImageUniforms); + static_cast(m_gl_MaxCombinedImageUniforms)->shareConstPointer(unionArray); + } + m_gl_MaxCombinedShaderOutputResources = + new TVariable(BuiltInId::gl_MaxCombinedShaderOutputResources, + BuiltInName::gl_MaxCombinedShaderOutputResources, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxCombinedShaderOutputResources); + static_cast(m_gl_MaxCombinedShaderOutputResources) + ->shareConstPointer(unionArray); + } + m_gl_MaxComputeWorkGroupCount = new TVariable( + BuiltInId::gl_MaxComputeWorkGroupCount, BuiltInName::gl_MaxComputeWorkGroupCount, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[3]; + for (size_t index = 0u; index < 3; ++index) + { + unionArray[index].setIConst(resources.MaxComputeWorkGroupCount[index]); + } + static_cast(m_gl_MaxComputeWorkGroupCount)->shareConstPointer(unionArray); + } + m_gl_MaxComputeWorkGroupSize = new TVariable( + BuiltInId::gl_MaxComputeWorkGroupSize, BuiltInName::gl_MaxComputeWorkGroupSize, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[3]; + for (size_t index = 0u; index < 3; ++index) + { + unionArray[index].setIConst(resources.MaxComputeWorkGroupSize[index]); + } + static_cast(m_gl_MaxComputeWorkGroupSize)->shareConstPointer(unionArray); + } + m_gl_MaxComputeUniformComponents = new TVariable( + BuiltInId::gl_MaxComputeUniformComponents, BuiltInName::gl_MaxComputeUniformComponents, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxComputeUniformComponents); + static_cast(m_gl_MaxComputeUniformComponents)->shareConstPointer(unionArray); + } + m_gl_MaxComputeTextureImageUnits = new TVariable( + BuiltInId::gl_MaxComputeTextureImageUnits, BuiltInName::gl_MaxComputeTextureImageUnits, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxComputeTextureImageUnits); + static_cast(m_gl_MaxComputeTextureImageUnits)->shareConstPointer(unionArray); + } + m_gl_MaxComputeAtomicCounters = new TVariable( + BuiltInId::gl_MaxComputeAtomicCounters, BuiltInName::gl_MaxComputeAtomicCounters, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxComputeAtomicCounters); + static_cast(m_gl_MaxComputeAtomicCounters)->shareConstPointer(unionArray); + } + m_gl_MaxComputeAtomicCounterBuffers = + new TVariable(BuiltInId::gl_MaxComputeAtomicCounterBuffers, + BuiltInName::gl_MaxComputeAtomicCounterBuffers, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxComputeAtomicCounterBuffers); + static_cast(m_gl_MaxComputeAtomicCounterBuffers) + ->shareConstPointer(unionArray); + } + m_gl_MaxVertexAtomicCounters = new TVariable( + BuiltInId::gl_MaxVertexAtomicCounters, BuiltInName::gl_MaxVertexAtomicCounters, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxVertexAtomicCounters); + static_cast(m_gl_MaxVertexAtomicCounters)->shareConstPointer(unionArray); + } + m_gl_MaxFragmentAtomicCounters = new TVariable( + BuiltInId::gl_MaxFragmentAtomicCounters, BuiltInName::gl_MaxFragmentAtomicCounters, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxFragmentAtomicCounters); + static_cast(m_gl_MaxFragmentAtomicCounters)->shareConstPointer(unionArray); + } + m_gl_MaxCombinedAtomicCounters = new TVariable( + BuiltInId::gl_MaxCombinedAtomicCounters, BuiltInName::gl_MaxCombinedAtomicCounters, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxCombinedAtomicCounters); + static_cast(m_gl_MaxCombinedAtomicCounters)->shareConstPointer(unionArray); + } + m_gl_MaxAtomicCounterBindings = new TVariable( + BuiltInId::gl_MaxAtomicCounterBindings, BuiltInName::gl_MaxAtomicCounterBindings, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxAtomicCounterBindings); + static_cast(m_gl_MaxAtomicCounterBindings)->shareConstPointer(unionArray); + } + m_gl_MaxVertexAtomicCounterBuffers = new TVariable( + BuiltInId::gl_MaxVertexAtomicCounterBuffers, BuiltInName::gl_MaxVertexAtomicCounterBuffers, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxVertexAtomicCounterBuffers); + static_cast(m_gl_MaxVertexAtomicCounterBuffers)->shareConstPointer(unionArray); + } + m_gl_MaxFragmentAtomicCounterBuffers = + new TVariable(BuiltInId::gl_MaxFragmentAtomicCounterBuffers, + BuiltInName::gl_MaxFragmentAtomicCounterBuffers, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxFragmentAtomicCounterBuffers); + static_cast(m_gl_MaxFragmentAtomicCounterBuffers) + ->shareConstPointer(unionArray); + } + m_gl_MaxCombinedAtomicCounterBuffers = + new TVariable(BuiltInId::gl_MaxCombinedAtomicCounterBuffers, + BuiltInName::gl_MaxCombinedAtomicCounterBuffers, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxCombinedAtomicCounterBuffers); + static_cast(m_gl_MaxCombinedAtomicCounterBuffers) + ->shareConstPointer(unionArray); + } + m_gl_MaxAtomicCounterBufferSize = new TVariable( + BuiltInId::gl_MaxAtomicCounterBufferSize, BuiltInName::gl_MaxAtomicCounterBufferSize, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxAtomicCounterBufferSize); + static_cast(m_gl_MaxAtomicCounterBufferSize)->shareConstPointer(unionArray); + } + m_gl_MaxGeometryInputComponents = + new TVariable(BuiltInId::gl_MaxGeometryInputComponents, + BuiltInName::gl_MaxGeometryInputComponents, SymbolType::BuiltIn, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryInputComponents); + static_cast(m_gl_MaxGeometryInputComponents)->shareConstPointer(unionArray); + } + m_gl_MaxGeometryInputComponentsES3_2 = new TVariable( + BuiltInId::gl_MaxGeometryInputComponentsES3_2, BuiltInName::gl_MaxGeometryInputComponents, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryInputComponents); + static_cast(m_gl_MaxGeometryInputComponentsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxGeometryOutputComponents = + new TVariable(BuiltInId::gl_MaxGeometryOutputComponents, + BuiltInName::gl_MaxGeometryOutputComponents, SymbolType::BuiltIn, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryOutputComponents); + static_cast(m_gl_MaxGeometryOutputComponents)->shareConstPointer(unionArray); + } + m_gl_MaxGeometryOutputComponentsES3_2 = new TVariable( + BuiltInId::gl_MaxGeometryOutputComponentsES3_2, BuiltInName::gl_MaxGeometryOutputComponents, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryOutputComponents); + static_cast(m_gl_MaxGeometryOutputComponentsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxGeometryImageUniforms = + new TVariable(BuiltInId::gl_MaxGeometryImageUniforms, + BuiltInName::gl_MaxGeometryImageUniforms, SymbolType::BuiltIn, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryImageUniforms); + static_cast(m_gl_MaxGeometryImageUniforms)->shareConstPointer(unionArray); + } + m_gl_MaxGeometryImageUniformsES3_2 = new TVariable( + BuiltInId::gl_MaxGeometryImageUniformsES3_2, BuiltInName::gl_MaxGeometryImageUniforms, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryImageUniforms); + static_cast(m_gl_MaxGeometryImageUniformsES3_2)->shareConstPointer(unionArray); + } + m_gl_MaxGeometryTextureImageUnits = + new TVariable(BuiltInId::gl_MaxGeometryTextureImageUnits, + BuiltInName::gl_MaxGeometryTextureImageUnits, SymbolType::BuiltIn, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryTextureImageUnits); + static_cast(m_gl_MaxGeometryTextureImageUnits)->shareConstPointer(unionArray); + } + m_gl_MaxGeometryTextureImageUnitsES3_2 = + new TVariable(BuiltInId::gl_MaxGeometryTextureImageUnitsES3_2, + BuiltInName::gl_MaxGeometryTextureImageUnits, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryTextureImageUnits); + static_cast(m_gl_MaxGeometryTextureImageUnitsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxGeometryOutputVertices = + new TVariable(BuiltInId::gl_MaxGeometryOutputVertices, + BuiltInName::gl_MaxGeometryOutputVertices, SymbolType::BuiltIn, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryOutputVertices); + static_cast(m_gl_MaxGeometryOutputVertices)->shareConstPointer(unionArray); + } + m_gl_MaxGeometryOutputVerticesES3_2 = new TVariable( + BuiltInId::gl_MaxGeometryOutputVerticesES3_2, BuiltInName::gl_MaxGeometryOutputVertices, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryOutputVertices); + static_cast(m_gl_MaxGeometryOutputVerticesES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxGeometryTotalOutputComponents = + new TVariable(BuiltInId::gl_MaxGeometryTotalOutputComponents, + BuiltInName::gl_MaxGeometryTotalOutputComponents, SymbolType::BuiltIn, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryTotalOutputComponents); + static_cast(m_gl_MaxGeometryTotalOutputComponents) + ->shareConstPointer(unionArray); + } + m_gl_MaxGeometryTotalOutputComponentsES3_2 = + new TVariable(BuiltInId::gl_MaxGeometryTotalOutputComponentsES3_2, + BuiltInName::gl_MaxGeometryTotalOutputComponents, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryTotalOutputComponents); + static_cast(m_gl_MaxGeometryTotalOutputComponentsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxGeometryUniformComponents = + new TVariable(BuiltInId::gl_MaxGeometryUniformComponents, + BuiltInName::gl_MaxGeometryUniformComponents, SymbolType::BuiltIn, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryUniformComponents); + static_cast(m_gl_MaxGeometryUniformComponents)->shareConstPointer(unionArray); + } + m_gl_MaxGeometryUniformComponentsES3_2 = + new TVariable(BuiltInId::gl_MaxGeometryUniformComponentsES3_2, + BuiltInName::gl_MaxGeometryUniformComponents, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryUniformComponents); + static_cast(m_gl_MaxGeometryUniformComponentsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxGeometryAtomicCounters = + new TVariable(BuiltInId::gl_MaxGeometryAtomicCounters, + BuiltInName::gl_MaxGeometryAtomicCounters, SymbolType::BuiltIn, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryAtomicCounters); + static_cast(m_gl_MaxGeometryAtomicCounters)->shareConstPointer(unionArray); + } + m_gl_MaxGeometryAtomicCountersES3_2 = new TVariable( + BuiltInId::gl_MaxGeometryAtomicCountersES3_2, BuiltInName::gl_MaxGeometryAtomicCounters, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryAtomicCounters); + static_cast(m_gl_MaxGeometryAtomicCountersES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxGeometryAtomicCounterBuffers = + new TVariable(BuiltInId::gl_MaxGeometryAtomicCounterBuffers, + BuiltInName::gl_MaxGeometryAtomicCounterBuffers, SymbolType::BuiltIn, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryAtomicCounterBuffers); + static_cast(m_gl_MaxGeometryAtomicCounterBuffers) + ->shareConstPointer(unionArray); + } + m_gl_MaxGeometryAtomicCounterBuffersES3_2 = + new TVariable(BuiltInId::gl_MaxGeometryAtomicCounterBuffersES3_2, + BuiltInName::gl_MaxGeometryAtomicCounterBuffers, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxGeometryAtomicCounterBuffers); + static_cast(m_gl_MaxGeometryAtomicCounterBuffersES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessControlInputComponents = new TVariable( + BuiltInId::gl_MaxTessControlInputComponents, BuiltInName::gl_MaxTessControlInputComponents, + SymbolType::BuiltIn, std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlInputComponents); + static_cast(m_gl_MaxTessControlInputComponents)->shareConstPointer(unionArray); + } + m_gl_MaxTessControlInputComponentsES3_2 = + new TVariable(BuiltInId::gl_MaxTessControlInputComponentsES3_2, + BuiltInName::gl_MaxTessControlInputComponents, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlInputComponents); + static_cast(m_gl_MaxTessControlInputComponentsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessControlOutputComponents = + new TVariable(BuiltInId::gl_MaxTessControlOutputComponents, + BuiltInName::gl_MaxTessControlOutputComponents, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlOutputComponents); + static_cast(m_gl_MaxTessControlOutputComponents) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessControlOutputComponentsES3_2 = + new TVariable(BuiltInId::gl_MaxTessControlOutputComponentsES3_2, + BuiltInName::gl_MaxTessControlOutputComponents, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlOutputComponents); + static_cast(m_gl_MaxTessControlOutputComponentsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessControlTextureImageUnits = + new TVariable(BuiltInId::gl_MaxTessControlTextureImageUnits, + BuiltInName::gl_MaxTessControlTextureImageUnits, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlTextureImageUnits); + static_cast(m_gl_MaxTessControlTextureImageUnits) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessControlTextureImageUnitsES3_2 = + new TVariable(BuiltInId::gl_MaxTessControlTextureImageUnitsES3_2, + BuiltInName::gl_MaxTessControlTextureImageUnits, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlTextureImageUnits); + static_cast(m_gl_MaxTessControlTextureImageUnitsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessControlUniformComponents = + new TVariable(BuiltInId::gl_MaxTessControlUniformComponents, + BuiltInName::gl_MaxTessControlUniformComponents, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlUniformComponents); + static_cast(m_gl_MaxTessControlUniformComponents) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessControlUniformComponentsES3_2 = + new TVariable(BuiltInId::gl_MaxTessControlUniformComponentsES3_2, + BuiltInName::gl_MaxTessControlUniformComponents, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlUniformComponents); + static_cast(m_gl_MaxTessControlUniformComponentsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessControlTotalOutputComponents = + new TVariable(BuiltInId::gl_MaxTessControlTotalOutputComponents, + BuiltInName::gl_MaxTessControlTotalOutputComponents, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlTotalOutputComponents); + static_cast(m_gl_MaxTessControlTotalOutputComponents) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessControlTotalOutputComponentsES3_2 = + new TVariable(BuiltInId::gl_MaxTessControlTotalOutputComponentsES3_2, + BuiltInName::gl_MaxTessControlTotalOutputComponents, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlTotalOutputComponents); + static_cast(m_gl_MaxTessControlTotalOutputComponentsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessControlImageUniforms = new TVariable( + BuiltInId::gl_MaxTessControlImageUniforms, BuiltInName::gl_MaxTessControlImageUniforms, + SymbolType::BuiltIn, std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlImageUniforms); + static_cast(m_gl_MaxTessControlImageUniforms)->shareConstPointer(unionArray); + } + m_gl_MaxTessControlImageUniformsES3_2 = new TVariable( + BuiltInId::gl_MaxTessControlImageUniformsES3_2, BuiltInName::gl_MaxTessControlImageUniforms, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlImageUniforms); + static_cast(m_gl_MaxTessControlImageUniformsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessControlAtomicCounters = new TVariable( + BuiltInId::gl_MaxTessControlAtomicCounters, BuiltInName::gl_MaxTessControlAtomicCounters, + SymbolType::BuiltIn, std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlAtomicCounters); + static_cast(m_gl_MaxTessControlAtomicCounters)->shareConstPointer(unionArray); + } + m_gl_MaxTessControlAtomicCountersES3_2 = + new TVariable(BuiltInId::gl_MaxTessControlAtomicCountersES3_2, + BuiltInName::gl_MaxTessControlAtomicCounters, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlAtomicCounters); + static_cast(m_gl_MaxTessControlAtomicCountersES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessControlAtomicCounterBuffers = + new TVariable(BuiltInId::gl_MaxTessControlAtomicCounterBuffers, + BuiltInName::gl_MaxTessControlAtomicCounterBuffers, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlAtomicCounterBuffers); + static_cast(m_gl_MaxTessControlAtomicCounterBuffers) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessControlAtomicCounterBuffersES3_2 = + new TVariable(BuiltInId::gl_MaxTessControlAtomicCounterBuffersES3_2, + BuiltInName::gl_MaxTessControlAtomicCounterBuffers, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessControlAtomicCounterBuffers); + static_cast(m_gl_MaxTessControlAtomicCounterBuffersES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessPatchComponents = new TVariable( + BuiltInId::gl_MaxTessPatchComponents, BuiltInName::gl_MaxTessPatchComponents, + SymbolType::BuiltIn, std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessPatchComponents); + static_cast(m_gl_MaxTessPatchComponents)->shareConstPointer(unionArray); + } + m_gl_MaxTessPatchComponentsES3_2 = new TVariable( + BuiltInId::gl_MaxTessPatchComponentsES3_2, BuiltInName::gl_MaxTessPatchComponents, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessPatchComponents); + static_cast(m_gl_MaxTessPatchComponentsES3_2)->shareConstPointer(unionArray); + } + m_gl_MaxPatchVertices = new TVariable( + BuiltInId::gl_MaxPatchVertices, BuiltInName::gl_MaxPatchVertices, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxPatchVertices); + static_cast(m_gl_MaxPatchVertices)->shareConstPointer(unionArray); + } + m_gl_MaxPatchVerticesES3_2 = + new TVariable(BuiltInId::gl_MaxPatchVerticesES3_2, BuiltInName::gl_MaxPatchVertices, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxPatchVertices); + static_cast(m_gl_MaxPatchVerticesES3_2)->shareConstPointer(unionArray); + } + m_gl_MaxTessGenLevel = new TVariable( + BuiltInId::gl_MaxTessGenLevel, BuiltInName::gl_MaxTessGenLevel, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessGenLevel); + static_cast(m_gl_MaxTessGenLevel)->shareConstPointer(unionArray); + } + m_gl_MaxTessGenLevelES3_2 = + new TVariable(BuiltInId::gl_MaxTessGenLevelES3_2, BuiltInName::gl_MaxTessGenLevel, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessGenLevel); + static_cast(m_gl_MaxTessGenLevelES3_2)->shareConstPointer(unionArray); + } + m_gl_MaxTessEvaluationInputComponents = + new TVariable(BuiltInId::gl_MaxTessEvaluationInputComponents, + BuiltInName::gl_MaxTessEvaluationInputComponents, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessEvaluationInputComponents); + static_cast(m_gl_MaxTessEvaluationInputComponents) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessEvaluationInputComponentsES3_2 = + new TVariable(BuiltInId::gl_MaxTessEvaluationInputComponentsES3_2, + BuiltInName::gl_MaxTessEvaluationInputComponents, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessEvaluationInputComponents); + static_cast(m_gl_MaxTessEvaluationInputComponentsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessEvaluationOutputComponents = + new TVariable(BuiltInId::gl_MaxTessEvaluationOutputComponents, + BuiltInName::gl_MaxTessEvaluationOutputComponents, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessEvaluationOutputComponents); + static_cast(m_gl_MaxTessEvaluationOutputComponents) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessEvaluationOutputComponentsES3_2 = + new TVariable(BuiltInId::gl_MaxTessEvaluationOutputComponentsES3_2, + BuiltInName::gl_MaxTessEvaluationOutputComponents, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessEvaluationOutputComponents); + static_cast(m_gl_MaxTessEvaluationOutputComponentsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessEvaluationTextureImageUnits = + new TVariable(BuiltInId::gl_MaxTessEvaluationTextureImageUnits, + BuiltInName::gl_MaxTessEvaluationTextureImageUnits, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessEvaluationTextureImageUnits); + static_cast(m_gl_MaxTessEvaluationTextureImageUnits) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessEvaluationTextureImageUnitsES3_2 = + new TVariable(BuiltInId::gl_MaxTessEvaluationTextureImageUnitsES3_2, + BuiltInName::gl_MaxTessEvaluationTextureImageUnits, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessEvaluationTextureImageUnits); + static_cast(m_gl_MaxTessEvaluationTextureImageUnitsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessEvaluationUniformComponents = + new TVariable(BuiltInId::gl_MaxTessEvaluationUniformComponents, + BuiltInName::gl_MaxTessEvaluationUniformComponents, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessEvaluationUniformComponents); + static_cast(m_gl_MaxTessEvaluationUniformComponents) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessEvaluationUniformComponentsES3_2 = + new TVariable(BuiltInId::gl_MaxTessEvaluationUniformComponentsES3_2, + BuiltInName::gl_MaxTessEvaluationUniformComponents, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessEvaluationUniformComponents); + static_cast(m_gl_MaxTessEvaluationUniformComponentsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessEvaluationImageUniforms = + new TVariable(BuiltInId::gl_MaxTessEvaluationImageUniforms, + BuiltInName::gl_MaxTessEvaluationImageUniforms, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessEvaluationImageUniforms); + static_cast(m_gl_MaxTessEvaluationImageUniforms) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessEvaluationImageUniformsES3_2 = + new TVariable(BuiltInId::gl_MaxTessEvaluationImageUniformsES3_2, + BuiltInName::gl_MaxTessEvaluationImageUniforms, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessEvaluationImageUniforms); + static_cast(m_gl_MaxTessEvaluationImageUniformsES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessEvaluationAtomicCounters = + new TVariable(BuiltInId::gl_MaxTessEvaluationAtomicCounters, + BuiltInName::gl_MaxTessEvaluationAtomicCounters, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessEvaluationAtomicCounters); + static_cast(m_gl_MaxTessEvaluationAtomicCounters) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessEvaluationAtomicCountersES3_2 = + new TVariable(BuiltInId::gl_MaxTessEvaluationAtomicCountersES3_2, + BuiltInName::gl_MaxTessEvaluationAtomicCounters, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessEvaluationAtomicCounters); + static_cast(m_gl_MaxTessEvaluationAtomicCountersES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessEvaluationAtomicCounterBuffers = + new TVariable(BuiltInId::gl_MaxTessEvaluationAtomicCounterBuffers, + BuiltInName::gl_MaxTessEvaluationAtomicCounterBuffers, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessEvaluationAtomicCounterBuffers); + static_cast(m_gl_MaxTessEvaluationAtomicCounterBuffers) + ->shareConstPointer(unionArray); + } + m_gl_MaxTessEvaluationAtomicCounterBuffersES3_2 = + new TVariable(BuiltInId::gl_MaxTessEvaluationAtomicCounterBuffersES3_2, + BuiltInName::gl_MaxTessEvaluationAtomicCounterBuffers, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxTessEvaluationAtomicCounterBuffers); + static_cast(m_gl_MaxTessEvaluationAtomicCounterBuffersES3_2) + ->shareConstPointer(unionArray); + } + m_gl_MaxSamples = + new TVariable(BuiltInId::gl_MaxSamples, BuiltInName::gl_MaxSamples, SymbolType::BuiltIn, + std::array{{TExtension::OES_sample_variables}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxSamples); + static_cast(m_gl_MaxSamples)->shareConstPointer(unionArray); + } + m_gl_MaxSamplesES3_2 = + new TVariable(BuiltInId::gl_MaxSamplesES3_2, BuiltInName::gl_MaxSamples, + SymbolType::BuiltIn, std::array{{TExtension::UNDEFINED}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxSamples); + static_cast(m_gl_MaxSamplesES3_2)->shareConstPointer(unionArray); + } + m_gl_MaxClipDistancesAPPLE = new TVariable( + BuiltInId::gl_MaxClipDistancesAPPLE, BuiltInName::gl_MaxClipDistances, SymbolType::BuiltIn, + std::array{{TExtension::APPLE_clip_distance}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxClipDistances); + static_cast(m_gl_MaxClipDistancesAPPLE)->shareConstPointer(unionArray); + } + m_gl_MaxCullDistancesEXT = new TVariable( + BuiltInId::gl_MaxCullDistancesEXT, BuiltInName::gl_MaxCullDistances, SymbolType::BuiltIn, + std::array{{TExtension::EXT_clip_cull_distance}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxCullDistances); + static_cast(m_gl_MaxCullDistancesEXT)->shareConstPointer(unionArray); + } + m_gl_MaxCombinedClipAndCullDistancesEXT = + new TVariable(BuiltInId::gl_MaxCombinedClipAndCullDistancesEXT, + BuiltInName::gl_MaxCombinedClipAndCullDistances, SymbolType::BuiltIn, + std::array{{TExtension::EXT_clip_cull_distance}}, + StaticType::Get()); + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray[0].setIConst(resources.MaxCombinedClipAndCullDistances); + static_cast(m_gl_MaxCombinedClipAndCullDistancesEXT) + ->shareConstPointer(unionArray); + } + TType *type_gl_FragData = new TType(EbtFloat, EbpMedium, EvqFragData, 4); + if (spec != SH_WEBGL2_SPEC && spec != SH_WEBGL3_SPEC) + { + type_gl_FragData->makeArray(resources.MaxDrawBuffers); + } + else + { + type_gl_FragData->makeArray(1u); + } + type_gl_FragData->realize(); + m_gl_FragData = + new TVariable(BuiltInId::gl_FragData, BuiltInName::gl_FragData, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_FragData); + TType *type_gl_SecondaryFragDataEXT = + new TType(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1); + type_gl_SecondaryFragDataEXT->makeArray(resources.MaxDualSourceDrawBuffers); + type_gl_SecondaryFragDataEXT->realize(); + m_gl_SecondaryFragDataEXT = new TVariable( + BuiltInId::gl_SecondaryFragDataEXT, BuiltInName::gl_SecondaryFragDataEXT, + SymbolType::BuiltIn, std::array{{TExtension::EXT_blend_func_extended}}, + type_gl_SecondaryFragDataEXT); + TType *type_gl_FragDepthEXT = + new TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1); + type_gl_FragDepthEXT->realize(); + m_gl_FragDepthEXT = new TVariable( + BuiltInId::gl_FragDepthEXT, BuiltInName::gl_FragDepthEXT, SymbolType::BuiltIn, + std::array{{TExtension::EXT_frag_depth}}, type_gl_FragDepthEXT); + TType *type_gl_LastFragData = new TType(EbtFloat, EbpMedium, EvqLastFragData, 4, 1); + type_gl_LastFragData->makeArray(resources.MaxDrawBuffers); + type_gl_LastFragData->realize(); + m_gl_LastFragData = new TVariable( + BuiltInId::gl_LastFragData, BuiltInName::gl_LastFragData, SymbolType::BuiltIn, + std::array{{TExtension::EXT_shader_framebuffer_fetch, + TExtension::EXT_shader_framebuffer_fetch_non_coherent}}, + type_gl_LastFragData); + TType *type_gl_LastFragDataNV = new TType(EbtFloat, EbpMedium, EvqLastFragData, 4, 1); + type_gl_LastFragDataNV->makeArray(resources.MaxDrawBuffers); + type_gl_LastFragDataNV->realize(); + m_gl_LastFragDataNV = new TVariable( + BuiltInId::gl_LastFragDataNV, BuiltInName::gl_LastFragData, SymbolType::BuiltIn, + std::array{{TExtension::NV_shader_framebuffer_fetch}}, + type_gl_LastFragDataNV); + TType *type_gl_SampleMaskIn = new TType(EbtInt, EbpHigh, EvqSampleMaskIn, 1); + type_gl_SampleMaskIn->makeArray((resources.MaxSamples + 31) / 32); + type_gl_SampleMaskIn->realize(); + m_gl_SampleMaskIn = new TVariable( + BuiltInId::gl_SampleMaskIn, BuiltInName::gl_SampleMaskIn, SymbolType::BuiltIn, + std::array{{TExtension::OES_sample_variables}}, type_gl_SampleMaskIn); + TType *type_gl_SampleMaskInES3_2 = new TType(EbtInt, EbpHigh, EvqSampleMaskIn, 1); + type_gl_SampleMaskInES3_2->makeArray((resources.MaxSamples + 31) / 32); + type_gl_SampleMaskInES3_2->realize(); + m_gl_SampleMaskInES3_2 = new TVariable( + BuiltInId::gl_SampleMaskInES3_2, BuiltInName::gl_SampleMaskIn, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_SampleMaskInES3_2); + TType *type_gl_SampleMask = new TType(EbtInt, EbpHigh, EvqSampleMask, 1); + type_gl_SampleMask->makeArray((resources.MaxSamples + 31) / 32); + type_gl_SampleMask->realize(); + m_gl_SampleMask = new TVariable( + BuiltInId::gl_SampleMask, BuiltInName::gl_SampleMask, SymbolType::BuiltIn, + std::array{{TExtension::OES_sample_variables}}, type_gl_SampleMask); + TType *type_gl_SampleMaskES3_2 = new TType(EbtInt, EbpHigh, EvqSampleMask, 1); + type_gl_SampleMaskES3_2->makeArray((resources.MaxSamples + 31) / 32); + type_gl_SampleMaskES3_2->realize(); + m_gl_SampleMaskES3_2 = new TVariable( + BuiltInId::gl_SampleMaskES3_2, BuiltInName::gl_SampleMask, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_SampleMaskES3_2); + TType *type_gl_CullDistance = new TType(EbtFloat, EbpHigh, EvqCullDistance, 1); + type_gl_CullDistance->makeArray(resources.MaxCullDistances); + type_gl_CullDistance->realize(); + m_gl_CullDistance = new TVariable( + BuiltInId::gl_CullDistance, BuiltInName::gl_CullDistance, SymbolType::BuiltIn, + std::array{{TExtension::EXT_clip_cull_distance}}, type_gl_CullDistance); + TType *type_gl_ClipDistance = new TType(EbtFloat, EbpHigh, EvqClipDistance, 1); + type_gl_ClipDistance->makeArray(resources.MaxClipDistances); + type_gl_ClipDistance->realize(); + m_gl_ClipDistance = new TVariable( + BuiltInId::gl_ClipDistance, BuiltInName::gl_ClipDistance, SymbolType::BuiltIn, + std::array{{TExtension::EXT_clip_cull_distance}}, type_gl_ClipDistance); + TType *type_gl_ClipDistanceAPPLE = new TType(EbtFloat, EbpHigh, EvqClipDistance, 1); + type_gl_ClipDistanceAPPLE->makeArray(resources.MaxClipDistances); + type_gl_ClipDistanceAPPLE->realize(); + m_gl_ClipDistanceAPPLE = new TVariable( + BuiltInId::gl_ClipDistanceAPPLE, BuiltInName::gl_ClipDistance, SymbolType::BuiltIn, + std::array{{TExtension::APPLE_clip_distance}}, type_gl_ClipDistanceAPPLE); + TType *type_gl_CullDistanceEXT = new TType(EbtFloat, EbpHigh, EvqCullDistance, 1); + type_gl_CullDistanceEXT->makeArray(resources.MaxCullDistances); + type_gl_CullDistanceEXT->realize(); + m_gl_CullDistanceEXT = new TVariable( + BuiltInId::gl_CullDistanceEXT, BuiltInName::gl_CullDistance, SymbolType::BuiltIn, + std::array{{TExtension::EXT_clip_cull_distance}}, type_gl_CullDistanceEXT); + TFieldList *fields_gl_PerVertex = new TFieldList(); + fields_gl_PerVertex->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), + BuiltInName::gl_Position, zeroSourceLoc, + SymbolType::BuiltIn)); + TInterfaceBlock *gl_PerVertex = + new TInterfaceBlock(BuiltInId::gl_PerVertex, BuiltInName::gl_PerVertex, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + fields_gl_PerVertex); + m_gl_PerVertex = gl_PerVertex; + TFieldList *fields_gl_PerVertexES3_2 = new TFieldList(); + fields_gl_PerVertexES3_2->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), + BuiltInName::gl_Position, zeroSourceLoc, + SymbolType::BuiltIn)); + TInterfaceBlock *gl_PerVertexES3_2 = new TInterfaceBlock( + BuiltInId::gl_PerVertexES3_2, BuiltInName::gl_PerVertex, + std::array{{TExtension::UNDEFINED}}, fields_gl_PerVertexES3_2); + m_gl_PerVertexES3_2 = gl_PerVertexES3_2; + TType *type_gl_in = new TType(gl_PerVertex, EvqPerVertexIn, TLayoutQualifier::Create()); + type_gl_in->makeArray(0u); + type_gl_in->realize(); + m_gl_in = new TVariable(BuiltInId::gl_in, BuiltInName::gl_in, SymbolType::BuiltIn, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + type_gl_in); + TType *type_gl_inES3_2 = new TType(gl_PerVertex, EvqPerVertexIn, TLayoutQualifier::Create()); + type_gl_inES3_2->makeArray(0u); + type_gl_inES3_2->realize(); + m_gl_inES3_2 = + new TVariable(BuiltInId::gl_inES3_2, BuiltInName::gl_in, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_inES3_2); + TFieldList *fields_gl_PerVertexOutBlock = new TFieldList(); + fields_gl_PerVertexOutBlock->push_back( + new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), BuiltInName::gl_Position, + zeroSourceLoc, SymbolType::BuiltIn)); + TInterfaceBlock *gl_PerVertexOutBlock = + new TInterfaceBlock(BuiltInId::gl_PerVertexOutBlock, BuiltInName::gl_PerVertex, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + fields_gl_PerVertexOutBlock); + TFieldList *fields_gl_PerVertexOutBlockES3_2 = new TFieldList(); + fields_gl_PerVertexOutBlockES3_2->push_back( + new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), BuiltInName::gl_Position, + zeroSourceLoc, SymbolType::BuiltIn)); + TInterfaceBlock *gl_PerVertexOutBlockES3_2 = new TInterfaceBlock( + BuiltInId::gl_PerVertexOutBlockES3_2, BuiltInName::gl_PerVertex, + std::array{{TExtension::UNDEFINED}}, fields_gl_PerVertexOutBlockES3_2); + TType *type_gl_PositionGS = new TType(EbtFloat, EbpHigh, EvqPosition, 4); + type_gl_PositionGS->setInterfaceBlock(gl_PerVertexOutBlock); + type_gl_PositionGS->realize(); + m_gl_PositionGS = + new TVariable(BuiltInId::gl_PositionGS, BuiltInName::gl_Position, SymbolType::BuiltIn, + std::array{ + {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}, + type_gl_PositionGS); + TType *type_gl_PositionGSES3_2 = new TType(EbtFloat, EbpHigh, EvqPosition, 4); + type_gl_PositionGSES3_2->setInterfaceBlock(gl_PerVertexOutBlockES3_2); + type_gl_PositionGSES3_2->realize(); + m_gl_PositionGSES3_2 = + new TVariable(BuiltInId::gl_PositionGSES3_2, BuiltInName::gl_Position, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_PositionGSES3_2); + TType *type_gl_TessLevelOuterTCS = new TType(EbtFloat, EbpHigh, EvqTessLevelOuter, 1); + type_gl_TessLevelOuterTCS->makeArray(4u); + type_gl_TessLevelOuterTCS->realize(); + m_gl_TessLevelOuterTCS = new TVariable( + BuiltInId::gl_TessLevelOuterTCS, BuiltInName::gl_TessLevelOuter, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + type_gl_TessLevelOuterTCS); + TType *type_gl_TessLevelOuterTCSES3_2 = new TType(EbtFloat, EbpHigh, EvqTessLevelOuter, 1); + type_gl_TessLevelOuterTCSES3_2->makeArray(4u); + type_gl_TessLevelOuterTCSES3_2->realize(); + m_gl_TessLevelOuterTCSES3_2 = new TVariable( + BuiltInId::gl_TessLevelOuterTCSES3_2, BuiltInName::gl_TessLevelOuter, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_TessLevelOuterTCSES3_2); + TType *type_gl_TessLevelInnerTCS = new TType(EbtFloat, EbpHigh, EvqTessLevelInner, 1); + type_gl_TessLevelInnerTCS->makeArray(2u); + type_gl_TessLevelInnerTCS->realize(); + m_gl_TessLevelInnerTCS = new TVariable( + BuiltInId::gl_TessLevelInnerTCS, BuiltInName::gl_TessLevelInner, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + type_gl_TessLevelInnerTCS); + TType *type_gl_TessLevelInnerTCSES3_2 = new TType(EbtFloat, EbpHigh, EvqTessLevelInner, 1); + type_gl_TessLevelInnerTCSES3_2->makeArray(2u); + type_gl_TessLevelInnerTCSES3_2->realize(); + m_gl_TessLevelInnerTCSES3_2 = new TVariable( + BuiltInId::gl_TessLevelInnerTCSES3_2, BuiltInName::gl_TessLevelInner, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_TessLevelInnerTCSES3_2); + TFieldList *fields_gl_PerVertexTCS = new TFieldList(); + fields_gl_PerVertexTCS->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), + BuiltInName::gl_Position, zeroSourceLoc, + SymbolType::BuiltIn)); + TInterfaceBlock *gl_PerVertexTCS = new TInterfaceBlock( + BuiltInId::gl_PerVertexTCS, BuiltInName::gl_PerVertex, + std::array{{TExtension::EXT_tessellation_shader}}, fields_gl_PerVertexTCS); + m_gl_PerVertexTCS = gl_PerVertexTCS; + TFieldList *fields_gl_PerVertexTCSES3_2 = new TFieldList(); + fields_gl_PerVertexTCSES3_2->push_back( + new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), BuiltInName::gl_Position, + zeroSourceLoc, SymbolType::BuiltIn)); + TInterfaceBlock *gl_PerVertexTCSES3_2 = new TInterfaceBlock( + BuiltInId::gl_PerVertexTCSES3_2, BuiltInName::gl_PerVertex, + std::array{{TExtension::UNDEFINED}}, fields_gl_PerVertexTCSES3_2); + m_gl_PerVertexTCSES3_2 = gl_PerVertexTCSES3_2; + TType *type_gl_inTCS = new TType(gl_PerVertex, EvqPerVertexIn, TLayoutQualifier::Create()); + type_gl_inTCS->makeArray(resources.MaxPatchVertices); + type_gl_inTCS->realize(); + m_gl_inTCS = new TVariable(BuiltInId::gl_inTCS, BuiltInName::gl_in, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + type_gl_inTCS); + TType *type_gl_inTCSES3_2 = new TType(gl_PerVertex, EvqPerVertexIn, TLayoutQualifier::Create()); + type_gl_inTCSES3_2->makeArray(resources.MaxPatchVertices); + type_gl_inTCSES3_2->realize(); + m_gl_inTCSES3_2 = + new TVariable(BuiltInId::gl_inTCSES3_2, BuiltInName::gl_in, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_inTCSES3_2); + TType *type_gl_outTCS = new TType(gl_PerVertex, EvqPerVertexOut, TLayoutQualifier::Create()); + type_gl_outTCS->makeArray(resources.MaxPatchVertices); + type_gl_outTCS->realize(); + m_gl_outTCS = new TVariable(BuiltInId::gl_outTCS, BuiltInName::gl_out, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + type_gl_outTCS); + TType *type_gl_outTCSES3_2 = + new TType(gl_PerVertex, EvqPerVertexOut, TLayoutQualifier::Create()); + type_gl_outTCSES3_2->makeArray(resources.MaxPatchVertices); + type_gl_outTCSES3_2->realize(); + m_gl_outTCSES3_2 = + new TVariable(BuiltInId::gl_outTCSES3_2, BuiltInName::gl_out, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_outTCSES3_2); + TType *type_gl_BoundingBoxTCS = new TType(EbtFloat, EbpHigh, EvqBoundingBox, 4); + type_gl_BoundingBoxTCS->makeArray(2u); + type_gl_BoundingBoxTCS->realize(); + m_gl_BoundingBoxTCS = new TVariable( + BuiltInId::gl_BoundingBoxTCS, BuiltInName::gl_BoundingBox, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, type_gl_BoundingBoxTCS); + TType *type_gl_BoundingBoxTCSES3_2 = new TType(EbtFloat, EbpHigh, EvqBoundingBox, 4); + type_gl_BoundingBoxTCSES3_2->makeArray(2u); + type_gl_BoundingBoxTCSES3_2->realize(); + m_gl_BoundingBoxTCSES3_2 = new TVariable( + BuiltInId::gl_BoundingBoxTCSES3_2, BuiltInName::gl_BoundingBox, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_BoundingBoxTCSES3_2); + TFieldList *fields_gl_PerVertexOutTcsBlock = new TFieldList(); + fields_gl_PerVertexOutTcsBlock->push_back( + new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), BuiltInName::gl_Position, + zeroSourceLoc, SymbolType::BuiltIn)); + TInterfaceBlock *gl_PerVertexOutTcsBlock = + new TInterfaceBlock(BuiltInId::gl_PerVertexOutTcsBlock, BuiltInName::gl_PerVertex, + std::array{{TExtension::EXT_tessellation_shader}}, + fields_gl_PerVertexOutTcsBlock); + TFieldList *fields_gl_PerVertexOutTcsBlockES3_2 = new TFieldList(); + fields_gl_PerVertexOutTcsBlockES3_2->push_back( + new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), BuiltInName::gl_Position, + zeroSourceLoc, SymbolType::BuiltIn)); + TInterfaceBlock *gl_PerVertexOutTcsBlockES3_2 = new TInterfaceBlock( + BuiltInId::gl_PerVertexOutTcsBlockES3_2, BuiltInName::gl_PerVertex, + std::array{{TExtension::UNDEFINED}}, fields_gl_PerVertexOutTcsBlockES3_2); + TType *type_gl_PositionTCS = new TType(EbtFloat, EbpHigh, EvqPosition, 4); + type_gl_PositionTCS->setInterfaceBlock(gl_PerVertexOutTcsBlock); + type_gl_PositionTCS->realize(); + m_gl_PositionTCS = new TVariable( + BuiltInId::gl_PositionTCS, BuiltInName::gl_Position, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, type_gl_PositionTCS); + TType *type_gl_PositionTCSES3_2 = new TType(EbtFloat, EbpHigh, EvqPosition, 4); + type_gl_PositionTCSES3_2->setInterfaceBlock(gl_PerVertexOutTcsBlockES3_2); + type_gl_PositionTCSES3_2->realize(); + m_gl_PositionTCSES3_2 = new TVariable( + BuiltInId::gl_PositionTCSES3_2, BuiltInName::gl_Position, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_PositionTCSES3_2); + TType *type_gl_BoundingBoxEXTTCS = new TType(EbtFloat, EbpHigh, EvqBoundingBox, 4); + type_gl_BoundingBoxEXTTCS->makeArray(2u); + type_gl_BoundingBoxEXTTCS->realize(); + m_gl_BoundingBoxEXTTCS = new TVariable( + BuiltInId::gl_BoundingBoxEXTTCS, BuiltInName::gl_BoundingBoxEXT, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + type_gl_BoundingBoxEXTTCS); + TType *type_gl_BoundingBoxEXTTCSES3_2 = new TType(EbtFloat, EbpHigh, EvqBoundingBox, 4); + type_gl_BoundingBoxEXTTCSES3_2->makeArray(2u); + type_gl_BoundingBoxEXTTCSES3_2->realize(); + m_gl_BoundingBoxEXTTCSES3_2 = new TVariable( + BuiltInId::gl_BoundingBoxEXTTCSES3_2, BuiltInName::gl_BoundingBoxEXT, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_BoundingBoxEXTTCSES3_2); + TType *type_gl_BoundingBoxOESTCS = new TType(EbtFloat, EbpHigh, EvqBoundingBox, 4); + type_gl_BoundingBoxOESTCS->makeArray(2u); + type_gl_BoundingBoxOESTCS->realize(); + m_gl_BoundingBoxOESTCS = new TVariable( + BuiltInId::gl_BoundingBoxOESTCS, BuiltInName::gl_BoundingBoxOES, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + type_gl_BoundingBoxOESTCS); + TType *type_gl_BoundingBoxOESTCSES3_2 = new TType(EbtFloat, EbpHigh, EvqBoundingBox, 4); + type_gl_BoundingBoxOESTCSES3_2->makeArray(2u); + type_gl_BoundingBoxOESTCSES3_2->realize(); + m_gl_BoundingBoxOESTCSES3_2 = new TVariable( + BuiltInId::gl_BoundingBoxOESTCSES3_2, BuiltInName::gl_BoundingBoxOES, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_BoundingBoxOESTCSES3_2); + TType *type_gl_TessLevelOuterTES = new TType(EbtFloat, EbpHigh, EvqTessLevelOuter, 1); + type_gl_TessLevelOuterTES->makeArray(4u); + type_gl_TessLevelOuterTES->realize(); + m_gl_TessLevelOuterTES = new TVariable( + BuiltInId::gl_TessLevelOuterTES, BuiltInName::gl_TessLevelOuter, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + type_gl_TessLevelOuterTES); + TType *type_gl_TessLevelOuterTESES3_2 = new TType(EbtFloat, EbpHigh, EvqTessLevelOuter, 1); + type_gl_TessLevelOuterTESES3_2->makeArray(4u); + type_gl_TessLevelOuterTESES3_2->realize(); + m_gl_TessLevelOuterTESES3_2 = new TVariable( + BuiltInId::gl_TessLevelOuterTESES3_2, BuiltInName::gl_TessLevelOuter, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_TessLevelOuterTESES3_2); + TType *type_gl_TessLevelInnerTES = new TType(EbtFloat, EbpHigh, EvqTessLevelInner, 1); + type_gl_TessLevelInnerTES->makeArray(2u); + type_gl_TessLevelInnerTES->realize(); + m_gl_TessLevelInnerTES = new TVariable( + BuiltInId::gl_TessLevelInnerTES, BuiltInName::gl_TessLevelInner, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + type_gl_TessLevelInnerTES); + TType *type_gl_TessLevelInnerTESES3_2 = new TType(EbtFloat, EbpHigh, EvqTessLevelInner, 1); + type_gl_TessLevelInnerTESES3_2->makeArray(2u); + type_gl_TessLevelInnerTESES3_2->realize(); + m_gl_TessLevelInnerTESES3_2 = new TVariable( + BuiltInId::gl_TessLevelInnerTESES3_2, BuiltInName::gl_TessLevelInner, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_TessLevelInnerTESES3_2); + TFieldList *fields_gl_PerVertexTES = new TFieldList(); + fields_gl_PerVertexTES->push_back(new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), + BuiltInName::gl_Position, zeroSourceLoc, + SymbolType::BuiltIn)); + TInterfaceBlock *gl_PerVertexTES = new TInterfaceBlock( + BuiltInId::gl_PerVertexTES, BuiltInName::gl_PerVertex, + std::array{{TExtension::EXT_tessellation_shader}}, fields_gl_PerVertexTES); + m_gl_PerVertexTES = gl_PerVertexTES; + TFieldList *fields_gl_PerVertexTESES3_2 = new TFieldList(); + fields_gl_PerVertexTESES3_2->push_back( + new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), BuiltInName::gl_Position, + zeroSourceLoc, SymbolType::BuiltIn)); + TInterfaceBlock *gl_PerVertexTESES3_2 = new TInterfaceBlock( + BuiltInId::gl_PerVertexTESES3_2, BuiltInName::gl_PerVertex, + std::array{{TExtension::UNDEFINED}}, fields_gl_PerVertexTESES3_2); + m_gl_PerVertexTESES3_2 = gl_PerVertexTESES3_2; + TType *type_gl_inTES = new TType(gl_PerVertex, EvqPerVertexIn, TLayoutQualifier::Create()); + type_gl_inTES->makeArray(resources.MaxPatchVertices); + type_gl_inTES->realize(); + m_gl_inTES = new TVariable(BuiltInId::gl_inTES, BuiltInName::gl_in, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + type_gl_inTES); + TType *type_gl_inTESES3_2 = new TType(gl_PerVertex, EvqPerVertexIn, TLayoutQualifier::Create()); + type_gl_inTESES3_2->makeArray(resources.MaxPatchVertices); + type_gl_inTESES3_2->realize(); + m_gl_inTESES3_2 = + new TVariable(BuiltInId::gl_inTESES3_2, BuiltInName::gl_in, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_inTESES3_2); + TType *type_gl_outTES = new TType(gl_PerVertex, EvqPerVertexOut, TLayoutQualifier::Create()); + type_gl_outTES->makeArray(resources.MaxPatchVertices); + type_gl_outTES->realize(); + m_gl_outTES = new TVariable(BuiltInId::gl_outTES, BuiltInName::gl_out, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, + type_gl_outTES); + TType *type_gl_outTESES3_2 = + new TType(gl_PerVertex, EvqPerVertexOut, TLayoutQualifier::Create()); + type_gl_outTESES3_2->makeArray(resources.MaxPatchVertices); + type_gl_outTESES3_2->realize(); + m_gl_outTESES3_2 = + new TVariable(BuiltInId::gl_outTESES3_2, BuiltInName::gl_out, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_outTESES3_2); + TFieldList *fields_gl_PerVertexOutTesBlock = new TFieldList(); + fields_gl_PerVertexOutTesBlock->push_back( + new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), BuiltInName::gl_Position, + zeroSourceLoc, SymbolType::BuiltIn)); + TInterfaceBlock *gl_PerVertexOutTesBlock = + new TInterfaceBlock(BuiltInId::gl_PerVertexOutTesBlock, BuiltInName::gl_PerVertex, + std::array{{TExtension::EXT_tessellation_shader}}, + fields_gl_PerVertexOutTesBlock); + TFieldList *fields_gl_PerVertexOutTesBlockES3_2 = new TFieldList(); + fields_gl_PerVertexOutTesBlockES3_2->push_back( + new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4, 1), BuiltInName::gl_Position, + zeroSourceLoc, SymbolType::BuiltIn)); + TInterfaceBlock *gl_PerVertexOutTesBlockES3_2 = new TInterfaceBlock( + BuiltInId::gl_PerVertexOutTesBlockES3_2, BuiltInName::gl_PerVertex, + std::array{{TExtension::UNDEFINED}}, fields_gl_PerVertexOutTesBlockES3_2); + TType *type_gl_PositionTES = new TType(EbtFloat, EbpHigh, EvqPosition, 4); + type_gl_PositionTES->setInterfaceBlock(gl_PerVertexOutTesBlock); + type_gl_PositionTES->realize(); + m_gl_PositionTES = new TVariable( + BuiltInId::gl_PositionTES, BuiltInName::gl_Position, SymbolType::BuiltIn, + std::array{{TExtension::EXT_tessellation_shader}}, type_gl_PositionTES); + TType *type_gl_PositionTESES3_2 = new TType(EbtFloat, EbpHigh, EvqPosition, 4); + type_gl_PositionTESES3_2->setInterfaceBlock(gl_PerVertexOutTesBlockES3_2); + type_gl_PositionTESES3_2->realize(); + m_gl_PositionTESES3_2 = new TVariable( + BuiltInId::gl_PositionTESES3_2, BuiltInName::gl_Position, SymbolType::BuiltIn, + std::array{{TExtension::UNDEFINED}}, type_gl_PositionTESES3_2); +} + +namespace +{ +uint16_t GetNextRuleIndex(uint32_t nameHash) +{ + if (nameHash == 1645 - 1) + return ArraySize(BuiltInArray::kRules); + return BuiltInArray::kMangledOffsets[nameHash + 1]; +} +} // namespace + +const TSymbol *TSymbolTable::findBuiltIn(const ImmutableString &name, int shaderVersion) const +{ + if (name.length() > 40) + return nullptr; + + uint32_t nameHash = name.mangledNameHash(); + if (nameHash >= 1645) + return nullptr; + + const char *actualName = BuiltInArray::kMangledNames[nameHash]; + if (name != actualName) + return nullptr; + + uint16_t startIndex = BuiltInArray::kMangledOffsets[nameHash]; + uint16_t nextIndex = GetNextRuleIndex(nameHash); + + return FindMangledBuiltIn(mShaderSpec, shaderVersion, mShaderType, mResources, *this, + BuiltInArray::kRules, startIndex, nextIndex); +} + +bool TSymbolTable::isUnmangledBuiltInName(const ImmutableString &name, + int shaderVersion, + const TExtensionBehavior &extensions) const +{ + if (name.length() > 32) + return false; + + uint32_t nameHash = name.unmangledNameHash(); + if (nameHash >= 174) + return false; + + return BuiltInArray::unmangled[nameHash].matches(name, mShaderSpec, shaderVersion, mShaderType, + extensions); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/SymbolTable_autogen.h b/gfx/angle/checkout/src/compiler/translator/SymbolTable_autogen.h new file mode 100644 index 0000000000..37c3c46462 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/SymbolTable_autogen.h @@ -0,0 +1,169 @@ +// GENERATED FILE - DO NOT EDIT. +// Generated by gen_builtin_symbols.py using data from builtin_variables.json and +// builtin_function_declarations.txt. +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SymbolTable_autogen.h: +// Autogenerated member variables of TSymbolTable. + +#ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_AUTOGEN_H_ +#define COMPILER_TRANSLATOR_SYMBOLTABLE_AUTOGEN_H_ + +namespace sh +{ + +class TSymbolTableBase +{ + public: + TSymbolTableBase() = default; + TSymbol *m_gl_DepthRangeParameters = nullptr; + TSymbol *m_gl_DepthRange = nullptr; + TSymbol *m_gl_MaxVertexAttribs = nullptr; + TSymbol *m_gl_MaxVertexUniformVectors = nullptr; + TSymbol *m_gl_MaxVertexTextureImageUnits = nullptr; + TSymbol *m_gl_MaxCombinedTextureImageUnits = nullptr; + TSymbol *m_gl_MaxTextureImageUnits = nullptr; + TSymbol *m_gl_MaxFragmentUniformVectors = nullptr; + TSymbol *m_gl_MaxVaryingVectors = nullptr; + TSymbol *m_gl_MaxDrawBuffers = nullptr; + TSymbol *m_gl_MaxDualSourceDrawBuffersEXT = nullptr; + TSymbol *m_gl_MaxVertexOutputVectors = nullptr; + TSymbol *m_gl_MaxFragmentInputVectors = nullptr; + TSymbol *m_gl_MinProgramTexelOffset = nullptr; + TSymbol *m_gl_MaxProgramTexelOffset = nullptr; + TSymbol *m_gl_MaxImageUnits = nullptr; + TSymbol *m_gl_MaxVertexImageUniforms = nullptr; + TSymbol *m_gl_MaxFragmentImageUniforms = nullptr; + TSymbol *m_gl_MaxComputeImageUniforms = nullptr; + TSymbol *m_gl_MaxCombinedImageUniforms = nullptr; + TSymbol *m_gl_MaxCombinedShaderOutputResources = nullptr; + TSymbol *m_gl_MaxComputeWorkGroupCount = nullptr; + TSymbol *m_gl_MaxComputeWorkGroupSize = nullptr; + TSymbol *m_gl_MaxComputeUniformComponents = nullptr; + TSymbol *m_gl_MaxComputeTextureImageUnits = nullptr; + TSymbol *m_gl_MaxComputeAtomicCounters = nullptr; + TSymbol *m_gl_MaxComputeAtomicCounterBuffers = nullptr; + TSymbol *m_gl_MaxVertexAtomicCounters = nullptr; + TSymbol *m_gl_MaxFragmentAtomicCounters = nullptr; + TSymbol *m_gl_MaxCombinedAtomicCounters = nullptr; + TSymbol *m_gl_MaxAtomicCounterBindings = nullptr; + TSymbol *m_gl_MaxVertexAtomicCounterBuffers = nullptr; + TSymbol *m_gl_MaxFragmentAtomicCounterBuffers = nullptr; + TSymbol *m_gl_MaxCombinedAtomicCounterBuffers = nullptr; + TSymbol *m_gl_MaxAtomicCounterBufferSize = nullptr; + TSymbol *m_gl_MaxGeometryInputComponents = nullptr; + TSymbol *m_gl_MaxGeometryInputComponentsES3_2 = nullptr; + TSymbol *m_gl_MaxGeometryOutputComponents = nullptr; + TSymbol *m_gl_MaxGeometryOutputComponentsES3_2 = nullptr; + TSymbol *m_gl_MaxGeometryImageUniforms = nullptr; + TSymbol *m_gl_MaxGeometryImageUniformsES3_2 = nullptr; + TSymbol *m_gl_MaxGeometryTextureImageUnits = nullptr; + TSymbol *m_gl_MaxGeometryTextureImageUnitsES3_2 = nullptr; + TSymbol *m_gl_MaxGeometryOutputVertices = nullptr; + TSymbol *m_gl_MaxGeometryOutputVerticesES3_2 = nullptr; + TSymbol *m_gl_MaxGeometryTotalOutputComponents = nullptr; + TSymbol *m_gl_MaxGeometryTotalOutputComponentsES3_2 = nullptr; + TSymbol *m_gl_MaxGeometryUniformComponents = nullptr; + TSymbol *m_gl_MaxGeometryUniformComponentsES3_2 = nullptr; + TSymbol *m_gl_MaxGeometryAtomicCounters = nullptr; + TSymbol *m_gl_MaxGeometryAtomicCountersES3_2 = nullptr; + TSymbol *m_gl_MaxGeometryAtomicCounterBuffers = nullptr; + TSymbol *m_gl_MaxGeometryAtomicCounterBuffersES3_2 = nullptr; + TSymbol *m_gl_MaxTessControlInputComponents = nullptr; + TSymbol *m_gl_MaxTessControlInputComponentsES3_2 = nullptr; + TSymbol *m_gl_MaxTessControlOutputComponents = nullptr; + TSymbol *m_gl_MaxTessControlOutputComponentsES3_2 = nullptr; + TSymbol *m_gl_MaxTessControlTextureImageUnits = nullptr; + TSymbol *m_gl_MaxTessControlTextureImageUnitsES3_2 = nullptr; + TSymbol *m_gl_MaxTessControlUniformComponents = nullptr; + TSymbol *m_gl_MaxTessControlUniformComponentsES3_2 = nullptr; + TSymbol *m_gl_MaxTessControlTotalOutputComponents = nullptr; + TSymbol *m_gl_MaxTessControlTotalOutputComponentsES3_2 = nullptr; + TSymbol *m_gl_MaxTessControlImageUniforms = nullptr; + TSymbol *m_gl_MaxTessControlImageUniformsES3_2 = nullptr; + TSymbol *m_gl_MaxTessControlAtomicCounters = nullptr; + TSymbol *m_gl_MaxTessControlAtomicCountersES3_2 = nullptr; + TSymbol *m_gl_MaxTessControlAtomicCounterBuffers = nullptr; + TSymbol *m_gl_MaxTessControlAtomicCounterBuffersES3_2 = nullptr; + TSymbol *m_gl_MaxTessPatchComponents = nullptr; + TSymbol *m_gl_MaxTessPatchComponentsES3_2 = nullptr; + TSymbol *m_gl_MaxPatchVertices = nullptr; + TSymbol *m_gl_MaxPatchVerticesES3_2 = nullptr; + TSymbol *m_gl_MaxTessGenLevel = nullptr; + TSymbol *m_gl_MaxTessGenLevelES3_2 = nullptr; + TSymbol *m_gl_MaxTessEvaluationInputComponents = nullptr; + TSymbol *m_gl_MaxTessEvaluationInputComponentsES3_2 = nullptr; + TSymbol *m_gl_MaxTessEvaluationOutputComponents = nullptr; + TSymbol *m_gl_MaxTessEvaluationOutputComponentsES3_2 = nullptr; + TSymbol *m_gl_MaxTessEvaluationTextureImageUnits = nullptr; + TSymbol *m_gl_MaxTessEvaluationTextureImageUnitsES3_2 = nullptr; + TSymbol *m_gl_MaxTessEvaluationUniformComponents = nullptr; + TSymbol *m_gl_MaxTessEvaluationUniformComponentsES3_2 = nullptr; + TSymbol *m_gl_MaxTessEvaluationImageUniforms = nullptr; + TSymbol *m_gl_MaxTessEvaluationImageUniformsES3_2 = nullptr; + TSymbol *m_gl_MaxTessEvaluationAtomicCounters = nullptr; + TSymbol *m_gl_MaxTessEvaluationAtomicCountersES3_2 = nullptr; + TSymbol *m_gl_MaxTessEvaluationAtomicCounterBuffers = nullptr; + TSymbol *m_gl_MaxTessEvaluationAtomicCounterBuffersES3_2 = nullptr; + TSymbol *m_gl_MaxSamples = nullptr; + TSymbol *m_gl_MaxSamplesES3_2 = nullptr; + TSymbol *m_gl_MaxClipDistancesAPPLE = nullptr; + TSymbol *m_gl_MaxCullDistancesEXT = nullptr; + TSymbol *m_gl_MaxCombinedClipAndCullDistancesEXT = nullptr; + TSymbol *m_gl_FragData = nullptr; + TSymbol *m_gl_SecondaryFragDataEXT = nullptr; + TSymbol *m_gl_FragDepthEXT = nullptr; + TSymbol *m_gl_LastFragData = nullptr; + TSymbol *m_gl_LastFragDataNV = nullptr; + TSymbol *m_gl_SampleMaskIn = nullptr; + TSymbol *m_gl_SampleMaskInES3_2 = nullptr; + TSymbol *m_gl_SampleMask = nullptr; + TSymbol *m_gl_SampleMaskES3_2 = nullptr; + TSymbol *m_gl_CullDistance = nullptr; + TSymbol *m_gl_ClipDistance = nullptr; + TSymbol *m_gl_ClipDistanceAPPLE = nullptr; + TSymbol *m_gl_CullDistanceEXT = nullptr; + TSymbol *m_gl_PerVertex = nullptr; + TSymbol *m_gl_PerVertexES3_2 = nullptr; + TSymbol *m_gl_in = nullptr; + TSymbol *m_gl_inES3_2 = nullptr; + TSymbol *m_gl_PositionGS = nullptr; + TSymbol *m_gl_PositionGSES3_2 = nullptr; + TSymbol *m_gl_TessLevelOuterTCS = nullptr; + TSymbol *m_gl_TessLevelOuterTCSES3_2 = nullptr; + TSymbol *m_gl_TessLevelInnerTCS = nullptr; + TSymbol *m_gl_TessLevelInnerTCSES3_2 = nullptr; + TSymbol *m_gl_PerVertexTCS = nullptr; + TSymbol *m_gl_PerVertexTCSES3_2 = nullptr; + TSymbol *m_gl_inTCS = nullptr; + TSymbol *m_gl_inTCSES3_2 = nullptr; + TSymbol *m_gl_outTCS = nullptr; + TSymbol *m_gl_outTCSES3_2 = nullptr; + TSymbol *m_gl_BoundingBoxTCS = nullptr; + TSymbol *m_gl_BoundingBoxTCSES3_2 = nullptr; + TSymbol *m_gl_PositionTCS = nullptr; + TSymbol *m_gl_PositionTCSES3_2 = nullptr; + TSymbol *m_gl_BoundingBoxEXTTCS = nullptr; + TSymbol *m_gl_BoundingBoxEXTTCSES3_2 = nullptr; + TSymbol *m_gl_BoundingBoxOESTCS = nullptr; + TSymbol *m_gl_BoundingBoxOESTCSES3_2 = nullptr; + TSymbol *m_gl_TessLevelOuterTES = nullptr; + TSymbol *m_gl_TessLevelOuterTESES3_2 = nullptr; + TSymbol *m_gl_TessLevelInnerTES = nullptr; + TSymbol *m_gl_TessLevelInnerTESES3_2 = nullptr; + TSymbol *m_gl_PerVertexTES = nullptr; + TSymbol *m_gl_PerVertexTESES3_2 = nullptr; + TSymbol *m_gl_inTES = nullptr; + TSymbol *m_gl_inTESES3_2 = nullptr; + TSymbol *m_gl_outTES = nullptr; + TSymbol *m_gl_outTESES3_2 = nullptr; + TSymbol *m_gl_PositionTES = nullptr; + TSymbol *m_gl_PositionTESES3_2 = nullptr; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_AUTOGEN_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/SymbolUniqueId.cpp b/gfx/angle/checkout/src/compiler/translator/SymbolUniqueId.cpp new file mode 100644 index 0000000000..2bdf08fa5f --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/SymbolUniqueId.cpp @@ -0,0 +1,27 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SymbolUniqueId.cpp: Encapsulates a unique id for a symbol. + +#include "compiler/translator/SymbolUniqueId.h" + +#include "compiler/translator/SymbolTable.h" + +namespace sh +{ + +TSymbolUniqueId::TSymbolUniqueId(TSymbolTable *symbolTable) : mId(symbolTable->nextUniqueIdValue()) +{} + +TSymbolUniqueId::TSymbolUniqueId(const TSymbol &symbol) : mId(symbol.uniqueId().get()) {} + +TSymbolUniqueId &TSymbolUniqueId::operator=(const TSymbolUniqueId &) = default; + +bool TSymbolUniqueId::operator==(const TSymbolUniqueId &other) const +{ + return mId == other.mId; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/SymbolUniqueId.h b/gfx/angle/checkout/src/compiler/translator/SymbolUniqueId.h new file mode 100644 index 0000000000..7e0312d054 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/SymbolUniqueId.h @@ -0,0 +1,58 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SymbolUniqueId.h: Encapsulates a unique id for a symbol. + +#ifndef COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_ +#define COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_ + +#include "compiler/translator/Common.h" + +namespace sh +{ + +class TSymbolTable; +class TSymbol; + +class TSymbolUniqueId +{ + public: + POOL_ALLOCATOR_NEW_DELETE + explicit TSymbolUniqueId(const TSymbol &symbol); + constexpr TSymbolUniqueId(const TSymbolUniqueId &) = default; + TSymbolUniqueId &operator =(const TSymbolUniqueId &); + bool operator==(const TSymbolUniqueId &) const; + + constexpr int get() const { return mId; } + + private: + friend class TSymbolTable; + explicit TSymbolUniqueId(TSymbolTable *symbolTable); + + friend class BuiltInId; + constexpr TSymbolUniqueId(int staticId) : mId(staticId) {} + + int mId; +}; + +enum class SymbolType : uint8_t +{ + BuiltIn, + UserDefined, + AngleInternal, + Empty // Meaning symbol without a name. +}; + +enum class SymbolClass : uint8_t +{ + Function, + Variable, + Struct, + InterfaceBlock +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/TextureFunctionHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/TextureFunctionHLSL.cpp new file mode 100644 index 0000000000..b88e6c9ce4 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/TextureFunctionHLSL.cpp @@ -0,0 +1,1614 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// TextureFunctionHLSL: Class for writing implementations of ESSL texture functions into HLSL +// output. Some of the implementations are straightforward and just call the HLSL equivalent of the +// ESSL texture function, others do more work to emulate ESSL texture sampling or size query +// behavior. +// + +#include "compiler/translator/TextureFunctionHLSL.h" + +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/UtilsHLSL.h" + +namespace sh +{ + +namespace +{ + +void OutputIntTexCoordWrap(TInfoSinkBase &out, + const char *wrapMode, + const char *size, + const ImmutableString &texCoord, + const char *texCoordOffset, + const char *texCoordOutName) +{ + // GLES 3.0.4 table 3.22 specifies how the wrap modes work. We don't use the formulas verbatim + // but rather use equivalent formulas that map better to HLSL. + out << "int " << texCoordOutName << ";\n"; + out << "float " << texCoordOutName << "Offset = " << texCoord << " + float(" << texCoordOffset + << ") / " << size << ";\n"; + out << "bool " << texCoordOutName << "UseBorderColor = false;\n"; + + // CLAMP_TO_EDGE + out << "if (" << wrapMode << " == 0)\n"; + out << "{\n"; + out << " " << texCoordOutName << " = clamp(int(floor(" << size << " * " << texCoordOutName + << "Offset)), 0, int(" << size << ") - 1);\n"; + out << "}\n"; + + // CLAMP_TO_BORDER + out << "else if (" << wrapMode << " == 3)\n"; + out << "{\n"; + out << " int texCoordInt = int(floor(" << size << " * " << texCoordOutName << "Offset));\n"; + out << " " << texCoordOutName << " = clamp(texCoordInt, 0, int(" << size << ") - 1);\n"; + out << " " << texCoordOutName << "UseBorderColor = (texCoordInt != " << texCoordOutName + << ");\n"; + out << "}\n"; + + // MIRRORED_REPEAT + out << "else if (" << wrapMode << " == 2)\n"; + out << "{\n"; + out << " float coordWrapped = 1.0 - abs(frac(abs(" << texCoordOutName + << "Offset) * 0.5) * 2.0 - 1.0);\n"; + out << " " << texCoordOutName << " = int(floor(" << size << " * coordWrapped));\n"; + out << "}\n"; + + // REPEAT + out << "else\n"; + out << "{\n"; + out << " " << texCoordOutName << " = int(floor(" << size << " * frac(" << texCoordOutName + << "Offset)));\n"; + out << "}\n"; +} + +void OutputIntTexCoordWraps(TInfoSinkBase &out, + const TextureFunctionHLSL::TextureFunction &textureFunction, + ImmutableString *texCoordX, + ImmutableString *texCoordY, + ImmutableString *texCoordZ) +{ + // Convert from normalized floating-point to integer + out << "int wrapS = samplerMetadata[samplerIndex].wrapModes & 0x3;\n"; + if (textureFunction.offset) + { + OutputIntTexCoordWrap(out, "wrapS", "width", *texCoordX, "offset.x", "tix"); + } + else + { + OutputIntTexCoordWrap(out, "wrapS", "width", *texCoordX, "0", "tix"); + } + *texCoordX = ImmutableString("tix"); + out << "int wrapT = (samplerMetadata[samplerIndex].wrapModes >> 2) & 0x3;\n"; + if (textureFunction.offset) + { + OutputIntTexCoordWrap(out, "wrapT", "height", *texCoordY, "offset.y", "tiy"); + } + else + { + OutputIntTexCoordWrap(out, "wrapT", "height", *texCoordY, "0", "tiy"); + } + *texCoordY = ImmutableString("tiy"); + + bool tizAvailable = false; + + if (IsSamplerArray(textureFunction.sampler)) + { + *texCoordZ = ImmutableString("int(max(0, min(layers - 1, floor(0.5 + t.z))))"); + } + else if (!IsSamplerCube(textureFunction.sampler) && !IsSampler2D(textureFunction.sampler)) + { + out << "int wrapR = (samplerMetadata[samplerIndex].wrapModes >> 4) & 0x3;\n"; + if (textureFunction.offset) + { + OutputIntTexCoordWrap(out, "wrapR", "depth", *texCoordZ, "offset.z", "tiz"); + } + else + { + OutputIntTexCoordWrap(out, "wrapR", "depth", *texCoordZ, "0", "tiz"); + } + *texCoordZ = ImmutableString("tiz"); + tizAvailable = true; + } + + out << "bool useBorderColor = tixUseBorderColor || tiyUseBorderColor" + << (tizAvailable ? " || tizUseBorderColor" : "") << ";\n"; +} + +void OutputHLSL4SampleFunctionPrefix(TInfoSinkBase &out, + const TextureFunctionHLSL::TextureFunction &textureFunction, + const ImmutableString &textureReference, + const ImmutableString &samplerReference) +{ + out << textureReference; + if (IsIntegerSampler(textureFunction.sampler) || + textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH) + { + out << ".Load("; + return; + } + + if (IsShadowSampler(textureFunction.sampler)) + { + switch (textureFunction.method) + { + case TextureFunctionHLSL::TextureFunction::IMPLICIT: + case TextureFunctionHLSL::TextureFunction::BIAS: + case TextureFunctionHLSL::TextureFunction::LOD: + out << ".SampleCmp("; + break; + case TextureFunctionHLSL::TextureFunction::LOD0: + case TextureFunctionHLSL::TextureFunction::LOD0BIAS: + case TextureFunctionHLSL::TextureFunction::GRAD: + out << ".SampleCmpLevelZero("; + break; + default: + UNREACHABLE(); + } + } + else + { + switch (textureFunction.method) + { + case TextureFunctionHLSL::TextureFunction::IMPLICIT: + out << ".Sample("; + break; + case TextureFunctionHLSL::TextureFunction::BIAS: + out << ".SampleBias("; + break; + case TextureFunctionHLSL::TextureFunction::LOD: + case TextureFunctionHLSL::TextureFunction::LOD0: + case TextureFunctionHLSL::TextureFunction::LOD0BIAS: + out << ".SampleLevel("; + break; + case TextureFunctionHLSL::TextureFunction::GRAD: + out << ".SampleGrad("; + break; + default: + UNREACHABLE(); + } + } + out << samplerReference << ", "; +} + +const char *GetSamplerCoordinateTypeString( + const TextureFunctionHLSL::TextureFunction &textureFunction, + int hlslCoords) +{ + // Gather[Red|Green|Blue|Alpha] accepts float texture coordinates on textures in integer or + // unsigned integer formats. + // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-to-gather + if ((IsIntegerSampler(textureFunction.sampler) && + textureFunction.method != TextureFunctionHLSL::TextureFunction::GATHER) || + textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH) + { + switch (hlslCoords) + { + case 1: + return "int"; + case 2: + if (IsSampler2DMS(textureFunction.sampler)) + { + return "int2"; + } + else + { + return "int3"; + } + case 3: + if (IsSampler2DMSArray(textureFunction.sampler)) + { + return "int3"; + } + else + { + return "int4"; + } + default: + UNREACHABLE(); + } + } + else + { + switch (hlslCoords) + { + case 1: + return "float"; + case 2: + return "float2"; + case 3: + return "float3"; + case 4: + return "float4"; + default: + UNREACHABLE(); + } + } + return ""; +} + +int GetHLSLCoordCount(const TextureFunctionHLSL::TextureFunction &textureFunction, + ShShaderOutput outputType) +{ + if (outputType == SH_HLSL_3_0_OUTPUT) + { + int hlslCoords = 2; + switch (textureFunction.sampler) + { + case EbtSamplerBuffer: + hlslCoords = 1; + break; + case EbtSampler2D: + case EbtSamplerExternalOES: + case EbtSampler2DMS: + case EbtSamplerVideoWEBGL: + hlslCoords = 2; + break; + case EbtSamplerCube: + hlslCoords = 3; + break; + default: + UNREACHABLE(); + } + + switch (textureFunction.method) + { + case TextureFunctionHLSL::TextureFunction::IMPLICIT: + case TextureFunctionHLSL::TextureFunction::GRAD: + return hlslCoords; + case TextureFunctionHLSL::TextureFunction::BIAS: + case TextureFunctionHLSL::TextureFunction::LOD: + case TextureFunctionHLSL::TextureFunction::LOD0: + case TextureFunctionHLSL::TextureFunction::LOD0BIAS: + return 4; + default: + UNREACHABLE(); + } + } + else + { + if (IsSamplerBuffer(textureFunction.sampler)) + { + return 1; + } + else if (IsSampler3D(textureFunction.sampler) || IsSamplerArray(textureFunction.sampler) || + IsSamplerCube(textureFunction.sampler)) + { + return 3; + } + ASSERT(IsSampler2D(textureFunction.sampler)); + return 2; + } + return 0; +} + +void OutputTextureFunctionArgumentList(TInfoSinkBase &out, + const TextureFunctionHLSL::TextureFunction &textureFunction, + const ShShaderOutput outputType) +{ + if (outputType == SH_HLSL_3_0_OUTPUT) + { + switch (textureFunction.sampler) + { + case EbtSampler2D: + case EbtSamplerVideoWEBGL: + case EbtSamplerExternalOES: + out << "sampler2D s"; + break; + case EbtSamplerCube: + out << "samplerCUBE s"; + break; + default: + UNREACHABLE(); + } + } + else + { + if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT) + { + out << TextureString(textureFunction.sampler) << " x, " + << SamplerString(textureFunction.sampler) << " s"; + } + else + { + ASSERT(outputType == SH_HLSL_4_1_OUTPUT); + // A bug in the D3D compiler causes some nested sampling operations to fail. + // See http://anglebug.com/1923 + // TODO(jmadill): Reinstate the const keyword when possible. + out << /*"const"*/ "uint samplerIndex"; + } + } + + if (textureFunction.method == + TextureFunctionHLSL::TextureFunction::FETCH) // Integer coordinates + { + switch (textureFunction.coords) + { + case 1: + out << ", int t"; + break; + case 2: + out << ", int2 t"; + break; + case 3: + out << ", int3 t"; + break; + default: + UNREACHABLE(); + } + } + else // Floating-point coordinates (except textureSize) + { + switch (textureFunction.coords) + { + case 0: + break; // textureSize(gSampler2DMS sampler) + case 1: + out << ", int lod"; + break; // textureSize() + case 2: + out << ", float2 t"; + break; + case 3: + out << ", float3 t"; + break; + case 4: + out << ", float4 t"; + break; + default: + UNREACHABLE(); + } + } + + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) + { + switch (textureFunction.sampler) + { + case EbtSampler2D: + case EbtISampler2D: + case EbtUSampler2D: + case EbtSampler2DArray: + case EbtISampler2DArray: + case EbtUSampler2DArray: + case EbtSampler2DShadow: + case EbtSampler2DArrayShadow: + case EbtSamplerExternalOES: + case EbtSamplerVideoWEBGL: + out << ", float2 ddx, float2 ddy"; + break; + case EbtSampler3D: + case EbtISampler3D: + case EbtUSampler3D: + case EbtSamplerCube: + case EbtISamplerCube: + case EbtUSamplerCube: + case EbtSamplerCubeShadow: + out << ", float3 ddx, float3 ddy"; + break; + default: + UNREACHABLE(); + } + } + + switch (textureFunction.method) + { + case TextureFunctionHLSL::TextureFunction::IMPLICIT: + break; + case TextureFunctionHLSL::TextureFunction::BIAS: + break; // Comes after the offset parameter + case TextureFunctionHLSL::TextureFunction::LOD: + out << ", float lod"; + break; + case TextureFunctionHLSL::TextureFunction::LOD0: + break; + case TextureFunctionHLSL::TextureFunction::LOD0BIAS: + break; // Comes after the offset parameter + case TextureFunctionHLSL::TextureFunction::SIZE: + break; + case TextureFunctionHLSL::TextureFunction::FETCH: + if (IsSampler2DMS(textureFunction.sampler) || + IsSampler2DMSArray(textureFunction.sampler)) + out << ", int index"; + else if (!IsSamplerBuffer(textureFunction.sampler)) + out << ", int mip"; + break; + case TextureFunctionHLSL::TextureFunction::GRAD: + break; + case TextureFunctionHLSL::TextureFunction::GATHER: + break; + default: + UNREACHABLE(); + } + + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GATHER && + IsShadowSampler(textureFunction.sampler)) + { + out << ", float refZ"; + } + + if (textureFunction.offset) + { + switch (textureFunction.sampler) + { + case EbtSampler3D: + case EbtISampler3D: + case EbtUSampler3D: + out << ", int3 offset"; + break; + case EbtSampler2D: + case EbtSampler2DArray: + case EbtISampler2D: + case EbtISampler2DArray: + case EbtUSampler2D: + case EbtUSampler2DArray: + case EbtSampler2DShadow: + case EbtSampler2DArrayShadow: + case EbtSamplerExternalOES: + case EbtSamplerVideoWEBGL: + out << ", int2 offset"; + break; + default: + // Offset is not supported for multisampled textures. + UNREACHABLE(); + } + } + + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS || + textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS) + { + out << ", float bias"; + } + else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GATHER && + !IsShadowSampler(textureFunction.sampler)) + { + out << ", int comp = 0"; + } +} + +void GetTextureReference(TInfoSinkBase &out, + const TextureFunctionHLSL::TextureFunction &textureFunction, + const ShShaderOutput outputType, + ImmutableString *textureReference, + ImmutableString *samplerReference) +{ + if (outputType == SH_HLSL_4_1_OUTPUT) + { + static const ImmutableString kTexturesStr("textures"); + static const ImmutableString kSamplersStr("samplers"); + static const ImmutableString kSamplerIndexStr("[samplerIndex]"); + static const ImmutableString kTextureIndexStr("[textureIndex]"); + static const ImmutableString kSamplerArrayIndexStr("[samplerArrayIndex]"); + ImmutableString suffix(TextureGroupSuffix(textureFunction.sampler)); + + if (TextureGroup(textureFunction.sampler) == HLSL_TEXTURE_2D) + { + ImmutableStringBuilder textureRefBuilder(kTexturesStr.length() + suffix.length() + + kSamplerIndexStr.length()); + textureRefBuilder << kTexturesStr << suffix << kSamplerIndexStr; + *textureReference = textureRefBuilder; + ImmutableStringBuilder samplerRefBuilder(kSamplersStr.length() + suffix.length() + + kSamplerIndexStr.length()); + samplerRefBuilder << kSamplersStr << suffix << kSamplerIndexStr; + *samplerReference = samplerRefBuilder; + } + else + { + out << " const uint textureIndex = samplerIndex - textureIndexOffset" + << suffix.data() << ";\n"; + ImmutableStringBuilder textureRefBuilder(kTexturesStr.length() + suffix.length() + + kTextureIndexStr.length()); + textureRefBuilder << kTexturesStr << suffix << kTextureIndexStr; + *textureReference = textureRefBuilder; + + out << " const uint samplerArrayIndex = samplerIndex - samplerIndexOffset" + << suffix.data() << ";\n"; + ImmutableStringBuilder samplerRefBuilder(kSamplersStr.length() + suffix.length() + + kSamplerArrayIndexStr.length()); + samplerRefBuilder << kSamplersStr << suffix << kSamplerArrayIndexStr; + *samplerReference = samplerRefBuilder; + } + } + else + { + *textureReference = ImmutableString("x"); + *samplerReference = ImmutableString("s"); + } +} + +void OutputTextureSizeFunctionBody(TInfoSinkBase &out, + const TextureFunctionHLSL::TextureFunction &textureFunction, + const ImmutableString &textureReference, + bool getDimensionsIgnoresBaseLevel) +{ + if (IsSampler2DMS(textureFunction.sampler)) + { + out << " uint width; uint height; uint samples;\n" + << " " << textureReference << ".GetDimensions(width, height, samples);\n"; + } + else if (IsSampler2DMSArray(textureFunction.sampler)) + { + out << " uint width; uint height; uint depth; uint samples;\n" + << " " << textureReference << ".GetDimensions(width, height, depth, samples);\n"; + } + else if (IsSamplerBuffer(textureFunction.sampler)) + { + out << " uint width;\n" + << " " << textureReference << ".GetDimensions(width);\n"; + } + else + { + if (getDimensionsIgnoresBaseLevel) + { + out << " int baseLevel = samplerMetadata[samplerIndex].baseLevel;\n"; + } + else + { + out << " int baseLevel = 0;\n"; + } + + if (IsSampler3D(textureFunction.sampler) || IsSamplerArray(textureFunction.sampler) || + (IsIntegerSampler(textureFunction.sampler) && IsSamplerCube(textureFunction.sampler))) + { + // "depth" stores either the number of layers in an array texture or 3D depth + out << " uint width; uint height; uint depth; uint numberOfLevels;\n" + << " " << textureReference + << ".GetDimensions(baseLevel, width, height, depth, numberOfLevels);\n" + << " width = max(width >> lod, 1);\n" + << " height = max(height >> lod, 1);\n"; + + if (!IsSamplerArray(textureFunction.sampler)) + { + out << " depth = max(depth >> lod, 1);\n"; + } + } + else if (IsSampler2D(textureFunction.sampler) || IsSamplerCube(textureFunction.sampler)) + { + out << " uint width; uint height; uint numberOfLevels;\n" + << " " << textureReference + << ".GetDimensions(baseLevel, width, height, numberOfLevels);\n" + << " width = max(width >> lod, 1);\n" + << " height = max(height >> lod, 1);\n"; + } + else + UNREACHABLE(); + } + + const char *returnType = textureFunction.getReturnType(); + if (strcmp(returnType, "int3") == 0) + { + out << " return int3(width, height, depth);\n"; + } + else if (strcmp(returnType, "int2") == 0) + { + out << " return int2(width, height);\n"; + } + else + { + out << " return int(width);\n"; + } +} + +void ProjectTextureCoordinates(const TextureFunctionHLSL::TextureFunction &textureFunction, + ImmutableString *texCoordX, + ImmutableString *texCoordY, + ImmutableString *texCoordZ) +{ + if (textureFunction.proj) + { + ImmutableString proj(""); + switch (textureFunction.coords) + { + case 3: + proj = ImmutableString(" / t.z"); + break; + case 4: + proj = ImmutableString(" / t.w"); + break; + default: + UNREACHABLE(); + } + ImmutableStringBuilder texCoordXBuilder(texCoordX->length() + proj.length() + 2u); + texCoordXBuilder << '(' << *texCoordX << proj << ')'; + *texCoordX = texCoordXBuilder; + ImmutableStringBuilder texCoordYBuilder(texCoordY->length() + proj.length() + 2u); + texCoordYBuilder << '(' << *texCoordY << proj << ')'; + *texCoordY = texCoordYBuilder; + ImmutableStringBuilder texCoordZBuilder(texCoordZ->length() + proj.length() + 2u); + texCoordZBuilder << '(' << *texCoordZ << proj << ')'; + *texCoordZ = texCoordZBuilder; + } +} + +void OutputIntegerTextureSampleFunctionComputations( + TInfoSinkBase &out, + const TextureFunctionHLSL::TextureFunction &textureFunction, + const ShShaderOutput outputType, + const ImmutableString &textureReference, + ImmutableString *texCoordX, + ImmutableString *texCoordY, + ImmutableString *texCoordZ, + bool getDimensionsIgnoresBaseLevel) +{ + if (!IsIntegerSampler(textureFunction.sampler)) + { + return; + } + + if (getDimensionsIgnoresBaseLevel) + { + out << " int baseLevel = samplerMetadata[samplerIndex].baseLevel;\n"; + } + else + { + out << " int baseLevel = 0;\n"; + } + + if (IsSamplerCube(textureFunction.sampler)) + { + out << " float width; float height; float layers; float levels;\n"; + + out << " uint mip = 0;\n"; + + out << " " << textureReference + << ".GetDimensions(baseLevel + mip, width, height, layers, levels);\n"; + + out << " bool xMajor = abs(t.x) >= abs(t.y) && abs(t.x) >= abs(t.z);\n"; + out << " bool yMajor = abs(t.y) >= abs(t.z) && abs(t.y) > abs(t.x);\n"; + out << " bool zMajor = abs(t.z) > abs(t.x) && abs(t.z) > abs(t.y);\n"; + out << " bool negative = (xMajor && t.x < 0.0f) || (yMajor && t.y < 0.0f) || " + "(zMajor && t.z < 0.0f);\n"; + + // FACE_POSITIVE_X = 000b + // FACE_NEGATIVE_X = 001b + // FACE_POSITIVE_Y = 010b + // FACE_NEGATIVE_Y = 011b + // FACE_POSITIVE_Z = 100b + // FACE_NEGATIVE_Z = 101b + out << " int face = (int)negative + (int)yMajor * 2 + (int)zMajor * 4;\n"; + + out << " float u = xMajor ? -t.z : (yMajor && t.y < 0.0f ? -t.x : t.x);\n"; + out << " float v = yMajor ? t.z : (negative ? t.y : -t.y);\n"; + out << " float m = xMajor ? t.x : (yMajor ? t.y : t.z);\n"; + + out << " float3 r = any(t) ? t : float3(1, 0, 0);\n"; + out << " t.x = (u * 0.5f / m) + 0.5f;\n"; + out << " t.y = (v * 0.5f / m) + 0.5f;\n"; + + // Mip level computation. + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT || + textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD || + textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) + { + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT) + { + // We would like to calculate tha maximum of how many texels we move in the major + // face's texture as we move across the screen in any direction. Namely, we want the + // length of the directional derivative of the function p (defined below), maximized + // over screen space directions. (For short: we want the norm of Dp.) For + // simplicity, assume that z-axis is the major axis. By symmetry, we can assume that + // the positive z direction is major. (The calculated value will be the same even if + // this is false.) Let r denote the function from screen position to cube texture + // coordinates. Then p can be written as p = s . P . r, where P(r) = (r.x, r.y)/r.z + // is the projection onto the major cube face, and s = diag(width, height)/2. (s + // linearly maps from the cube face into texture space, so that p(r) is in units of + // texels.) The derivative is + // Dp(r) = s |1 0 -r.x/r.z| + // |0 1 -r.y/r.z| |ddx(r) ddy(r)| / r.z + // = |dot(a, ddx(r)) dot(a, ddy(r))| + // |dot(b, ddx(r)) dot(b, ddy(r))| / (2 r.z) + // where a = w * vec3(1, 0, -r.x/r.z) + // b = h * vec3(0, 1, -r.y/r.z) + // We would like to know max(L(x)) over unit vectors x, where L(x) = |Dp(r) x|^2. + // Since ddx(r) and ddy(r) are unknown, the best we can do is to sample L in some + // directions and take the maximum across the samples. + // + // Some implementations use max(L(n1), L(n2)) where n1 = vec2(1,0) and n2 = + // vec2(0,1). + // + // Some implementations use max(L(n1), L(n2), L(n3), L(n4)), + // where n3 = (n1 + n2) / |n1 + n2| = (n1 + n2)/sqrt(2) + // n4 = (n1 - n2) / |n1 - n2| = (n1 - n2)/sqrt(2). + // In other words, two samples along the diagonal screen space directions have been + // added, giving a strictly better estimate of the true maximum. + // + // It turns out we can get twice the sample count very cheaply. + // We can use the linearity of Dp(r) to get these extra samples of L cheaply in + // terms of the already taken samples, L(n1) and L(n2): + // Denoting + // dpx = Dp(r)n1 + // dpy = Dp(r)n2 + // dpxx = dot(dpx, dpx) + // dpyy = dot(dpy, dpy) + // dpxy = dot(dpx, dpy) + // we obtain + // L(n3) = |Dp(r)n1 + Dp(r)n2|^2/2 = (dpxx + dpyy)/2 + dpxy + // L(n4) = |Dp(r)n1 - Dp(r)n2|^2/2 = (dpxx + dpyy)/2 - dpxy + // max(L(n1), L(n2), L(n3), L(n4)) + // = max(max(L(n1), L(n2)), max(L(n3), L(n4))) + // = max(max(dpxx, dpyy), (dpxx + dpyy)/2 + abs(dpxy)) + // So the extra cost is: one dot, one abs, one add, one multiply-add and one max. + // (All scalar.) + // + // In section 3.8.10.1, the OpenGL ES 3 specification defines the "scale factor", + // rho. In our terminology, this definition works out to taking sqrt(max(L(n1), + // L(n2))). Some implementations will use this estimate, here we use the strictly + // better sqrt(max(L(n1), L(n2), L(n3), L(n4))), since it's not much more expensive + // to calculate. + + // Swap coordinates such that we can assume that the positive z-axis is major, in + // what follows. + out << " float3 ddxr = xMajor ? ddx(r).yzx : yMajor ? ddx(r).zxy : ddx(r).xyz;\n" + " float3 ddyr = xMajor ? ddy(r).yzx : yMajor ? ddy(r).zxy : ddy(r).xyz;\n" + " r = xMajor ? r.yzx : yMajor ? r.zxy : r.xyz;\n"; + + out << " float2 s = 0.5*float2(width, height);\n" + " float2 dpx = s * (ddxr.xy - ddxr.z*r.xy/r.z)/r.z;\n" + " float2 dpy = s * (ddyr.xy - ddyr.z*r.xy/r.z)/r.z;\n" + " float dpxx = dot(dpx, dpx);\n;" + " float dpyy = dot(dpy, dpy);\n;" + " float dpxy = dot(dpx, dpy);\n" + " float ma = max(dpxx, dpyy);\n" + " float mb = 0.5 * (dpxx + dpyy) + abs(dpxy);\n" + " float mab = max(ma, mb);\n" + " float lod = 0.5f * log2(mab);\n"; + } + else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) + { + // ESSL 3.00.6 spec section 8.8: "For the cube version, the partial + // derivatives of P are assumed to be in the coordinate system used before + // texture coordinates are projected onto the appropriate cube face." + // ddx[0] and ddy[0] are the derivatives of t.x passed into the function + // ddx[1] and ddy[1] are the derivatives of t.y passed into the function + // ddx[2] and ddy[2] are the derivatives of t.z passed into the function + // Determine the derivatives of u, v and m + out << " float dudx = xMajor ? ddx[2] : (yMajor && t.y < 0.0f ? -ddx[0] " + ": ddx[0]);\n" + " float dudy = xMajor ? ddy[2] : (yMajor && t.y < 0.0f ? -ddy[0] " + ": ddy[0]);\n" + " float dvdx = yMajor ? ddx[2] : (negative ? ddx[1] : -ddx[1]);\n" + " float dvdy = yMajor ? ddy[2] : (negative ? ddy[1] : -ddy[1]);\n" + " float dmdx = xMajor ? ddx[0] : (yMajor ? ddx[1] : ddx[2]);\n" + " float dmdy = xMajor ? ddy[0] : (yMajor ? ddy[1] : ddy[2]);\n"; + // Now determine the derivatives of the face coordinates, using the + // derivatives calculated above. + // d / dx (u(x) * 0.5 / m(x) + 0.5) + // = 0.5 * (m(x) * u'(x) - u(x) * m'(x)) / m(x)^2 + out << " float dfacexdx = 0.5f * (m * dudx - u * dmdx) / (m * m);\n" + " float dfaceydx = 0.5f * (m * dvdx - v * dmdx) / (m * m);\n" + " float dfacexdy = 0.5f * (m * dudy - u * dmdy) / (m * m);\n" + " float dfaceydy = 0.5f * (m * dvdy - v * dmdy) / (m * m);\n" + " float2 sizeVec = float2(width, height);\n" + " float2 faceddx = float2(dfacexdx, dfaceydx) * sizeVec;\n" + " float2 faceddy = float2(dfacexdy, dfaceydy) * sizeVec;\n"; + // Optimization: instead of: log2(max(length(faceddx), length(faceddy))) + // we compute: log2(max(length(faceddx)^2, length(faceddy)^2)) / 2 + out << " float lengthfaceddx2 = dot(faceddx, faceddx);\n" + " float lengthfaceddy2 = dot(faceddy, faceddy);\n" + " float lod = log2(max(lengthfaceddx2, lengthfaceddy2)) * 0.5f;\n"; + } + out << " mip = uint(min(max(round(lod), 0), levels - 1));\n" + << " " << textureReference + << ".GetDimensions(baseLevel + mip, width, height, layers, levels);\n"; + } + + // Convert from normalized floating-point to integer + static const ImmutableString kXPrefix("int(floor(width * frac("); + static const ImmutableString kYPrefix("int(floor(height * frac("); + static const ImmutableString kSuffix(")))"); + ImmutableStringBuilder texCoordXBuilder(kXPrefix.length() + texCoordX->length() + + kSuffix.length()); + texCoordXBuilder << kXPrefix << *texCoordX << kSuffix; + *texCoordX = texCoordXBuilder; + ImmutableStringBuilder texCoordYBuilder(kYPrefix.length() + texCoordX->length() + + kSuffix.length()); + texCoordYBuilder << kYPrefix << *texCoordY << kSuffix; + *texCoordY = texCoordYBuilder; + *texCoordZ = ImmutableString("face"); + } + else if (textureFunction.method != TextureFunctionHLSL::TextureFunction::FETCH) + { + if (IsSamplerArray(textureFunction.sampler)) + { + out << " float width; float height; float layers; float levels;\n"; + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0) + { + out << " uint mip = 0;\n"; + } + else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS) + { + out << " uint mip = bias;\n"; + } + else + { + + out << " " << textureReference + << ".GetDimensions(baseLevel, width, height, layers, levels);\n"; + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT || + textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) + { + out << " float2 tSized = float2(t.x * width, t.y * height);\n" + " float dx = length(ddx(tSized));\n" + " float dy = length(ddy(tSized));\n" + " float lod = log2(max(dx, dy));\n"; + + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) + { + out << " lod += bias;\n"; + } + } + else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) + { + out << " float2 sizeVec = float2(width, height);\n" + " float2 sizeDdx = ddx * sizeVec;\n" + " float2 sizeDdy = ddy * sizeVec;\n" + " float lod = log2(max(dot(sizeDdx, sizeDdx), " + "dot(sizeDdy, sizeDdy))) * 0.5f;\n"; + } + + out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n"; + } + + out << " " << textureReference + << ".GetDimensions(baseLevel + mip, width, height, layers, levels);\n"; + } + else if (IsSampler2D(textureFunction.sampler)) + { + out << " float width; float height; float levels;\n"; + + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0) + { + out << " uint mip = 0;\n"; + } + else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS) + { + out << " uint mip = bias;\n"; + } + else + { + out << " " << textureReference + << ".GetDimensions(baseLevel, width, height, levels);\n"; + + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT || + textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) + { + out << " float2 tSized = float2(t.x * width, t.y * height);\n" + " float dx = length(ddx(tSized));\n" + " float dy = length(ddy(tSized));\n" + " float lod = log2(max(dx, dy));\n"; + + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) + { + out << " lod += bias;\n"; + } + } + else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) + { + out << " float2 sizeVec = float2(width, height);\n" + " float2 sizeDdx = ddx * sizeVec;\n" + " float2 sizeDdy = ddy * sizeVec;\n" + " float lod = log2(max(dot(sizeDdx, sizeDdx), " + "dot(sizeDdy, sizeDdy))) * 0.5f;\n"; + } + + out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n"; + } + + out << " " << textureReference + << ".GetDimensions(baseLevel + mip, width, height, levels);\n"; + } + else if (IsSampler3D(textureFunction.sampler)) + { + out << " float width; float height; float depth; float levels;\n"; + + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0) + { + out << " uint mip = 0;\n"; + } + else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS) + { + out << " uint mip = bias;\n"; + } + else + { + out << " " << textureReference + << ".GetDimensions(baseLevel, width, height, depth, levels);\n"; + + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT || + textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) + { + out << " float3 tSized = float3(t.x * width, t.y * height, t.z * depth);\n" + " float dx = length(ddx(tSized));\n" + " float dy = length(ddy(tSized));\n" + " float lod = log2(max(dx, dy));\n"; + + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) + { + out << " lod += bias;\n"; + } + } + else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) + { + out << " float3 sizeVec = float3(width, height, depth);\n" + " float3 sizeDdx = ddx * sizeVec;\n" + " float3 sizeDdy = ddy * sizeVec;\n" + " float lod = log2(max(dot(sizeDdx, sizeDdx), dot(sizeDdy, " + "sizeDdy))) * 0.5f;\n"; + } + + out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n"; + } + + out << " " << textureReference + << ".GetDimensions(baseLevel + mip, width, height, depth, levels);\n"; + } + else + UNREACHABLE(); + + OutputIntTexCoordWraps(out, textureFunction, texCoordX, texCoordY, texCoordZ); + } +} + +void OutputTextureGatherFunctionBody(TInfoSinkBase &out, + const TextureFunctionHLSL::TextureFunction &textureFunction, + ShShaderOutput outputType, + const ImmutableString &textureReference, + const ImmutableString &samplerReference, + const ImmutableString &texCoordX, + const ImmutableString &texCoordY, + const ImmutableString &texCoordZ) +{ + const int hlslCoords = GetHLSLCoordCount(textureFunction, outputType); + ImmutableString samplerCoordTypeString( + GetSamplerCoordinateTypeString(textureFunction, hlslCoords)); + ImmutableStringBuilder samplerCoordBuilder( + samplerCoordTypeString.length() + strlen("(") + texCoordX.length() + strlen(", ") + + texCoordY.length() + strlen(", ") + texCoordZ.length() + strlen(")")); + + samplerCoordBuilder << samplerCoordTypeString << "(" << texCoordX << ", " << texCoordY; + if (hlslCoords >= 3) + { + if (textureFunction.coords < 3) + { + samplerCoordBuilder << ", 0"; + } + else + { + samplerCoordBuilder << ", " << texCoordZ; + } + } + samplerCoordBuilder << ")"; + + ImmutableString samplerCoordString(samplerCoordBuilder); + + if (IsShadowSampler(textureFunction.sampler)) + { + out << "return " << textureReference << ".GatherCmp(" << samplerReference << ", " + << samplerCoordString << ", refZ"; + if (textureFunction.offset) + { + out << ", offset"; + } + out << ");\n"; + return; + } + + constexpr std::array kHLSLGatherFunctions = { + {"GatherRed", "GatherGreen", "GatherBlue", "GatherAlpha"}}; + + out << " switch(comp)\n" + " {\n"; + for (size_t component = 0; component < kHLSLGatherFunctions.size(); ++component) + { + out << " case " << component << ":\n" + << " return " << textureReference << "." << kHLSLGatherFunctions[component] + << "(" << samplerReference << ", " << samplerCoordString; + if (textureFunction.offset) + { + out << ", offset"; + } + out << ");\n"; + } + + out << " default:\n" + " return float4(0.0, 0.0, 0.0, 1.0);\n" + " }\n"; +} + +void OutputTextureSampleFunctionReturnStatement( + TInfoSinkBase &out, + const TextureFunctionHLSL::TextureFunction &textureFunction, + const ShShaderOutput outputType, + const ImmutableString &textureReference, + const ImmutableString &samplerReference, + const ImmutableString &texCoordX, + const ImmutableString &texCoordY, + const ImmutableString &texCoordZ) +{ + out << " return "; + + if (IsIntegerSampler(textureFunction.sampler) && !IsSamplerCube(textureFunction.sampler) && + textureFunction.method != TextureFunctionHLSL::TextureFunction::FETCH) + { + out << " useBorderColor ? "; + if (IsIntegerSamplerUnsigned(textureFunction.sampler)) + { + out << "asuint"; + } + out << "(samplerMetadata[samplerIndex].intBorderColor) : "; + } + + // HLSL intrinsic + if (outputType == SH_HLSL_3_0_OUTPUT) + { + switch (textureFunction.sampler) + { + case EbtSampler2D: + case EbtSamplerVideoWEBGL: + case EbtSamplerExternalOES: + out << "tex2D"; + break; + case EbtSamplerCube: + out << "texCUBE"; + break; + default: + UNREACHABLE(); + } + + switch (textureFunction.method) + { + case TextureFunctionHLSL::TextureFunction::IMPLICIT: + out << "(" << samplerReference << ", "; + break; + case TextureFunctionHLSL::TextureFunction::BIAS: + out << "bias(" << samplerReference << ", "; + break; + case TextureFunctionHLSL::TextureFunction::LOD: + out << "lod(" << samplerReference << ", "; + break; + case TextureFunctionHLSL::TextureFunction::LOD0: + out << "lod(" << samplerReference << ", "; + break; + case TextureFunctionHLSL::TextureFunction::LOD0BIAS: + out << "lod(" << samplerReference << ", "; + break; + case TextureFunctionHLSL::TextureFunction::GRAD: + out << "grad(" << samplerReference << ", "; + break; + default: + UNREACHABLE(); + } + } + else if (outputType == SH_HLSL_4_1_OUTPUT || outputType == SH_HLSL_4_0_FL9_3_OUTPUT) + { + OutputHLSL4SampleFunctionPrefix(out, textureFunction, textureReference, samplerReference); + } + else + UNREACHABLE(); + + const int hlslCoords = GetHLSLCoordCount(textureFunction, outputType); + out << GetSamplerCoordinateTypeString(textureFunction, hlslCoords); + + if (hlslCoords >= 2) + { + out << "(" << texCoordX << ", " << texCoordY; + } + else if (hlslCoords == 1) + { + std::string varName(texCoordX.data()); + if (size_t pos = varName.find_last_of('.') != std::string::npos) + { + varName = varName.substr(0, pos); + } + out << "(" << varName; + } + else + { + out << "("; + } + + if (outputType == SH_HLSL_3_0_OUTPUT) + { + if (hlslCoords >= 3) + { + if (textureFunction.coords < 3) + { + out << ", 0"; + } + else + { + out << ", " << texCoordZ; + } + } + + if (hlslCoords == 4) + { + switch (textureFunction.method) + { + case TextureFunctionHLSL::TextureFunction::BIAS: + out << ", bias"; + break; + case TextureFunctionHLSL::TextureFunction::LOD: + out << ", lod"; + break; + case TextureFunctionHLSL::TextureFunction::LOD0: + out << ", 0"; + break; + case TextureFunctionHLSL::TextureFunction::LOD0BIAS: + out << ", bias"; + break; + default: + UNREACHABLE(); + } + } + + out << ")"; + } + else if (outputType == SH_HLSL_4_1_OUTPUT || outputType == SH_HLSL_4_0_FL9_3_OUTPUT) + { + if (hlslCoords >= 3) + { + ASSERT(!IsIntegerSampler(textureFunction.sampler) || + !IsSamplerCube(textureFunction.sampler) || texCoordZ == "face"); + out << ", " << texCoordZ; + } + + if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) + { + if (IsIntegerSampler(textureFunction.sampler)) + { + out << ", mip)"; + } + else if (IsShadowSampler(textureFunction.sampler)) + { + // Compare value + if (textureFunction.proj) + { + // According to ESSL 3.00.4 sec 8.8 p95 on textureProj: + // The resulting third component of P' in the shadow forms is used as + // Dref + out << "), " << texCoordZ; + } + else + { + switch (textureFunction.coords) + { + case 3: + out << "), t.z"; + break; + case 4: + out << "), t.w"; + break; + default: + UNREACHABLE(); + } + } + } + else + { + out << "), ddx, ddy"; + } + } + else if (IsIntegerSampler(textureFunction.sampler) || + textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH) + { + if (IsSampler2DMS(textureFunction.sampler) || + IsSampler2DMSArray(textureFunction.sampler)) + out << "), index"; + else if (IsSamplerBuffer(textureFunction.sampler)) + out << ")"; + else + out << ", mip)"; + } + else if (IsShadowSampler(textureFunction.sampler)) + { + // Compare value + if (textureFunction.proj) + { + // According to ESSL 3.00.4 sec 8.8 p95 on textureProj: + // The resulting third component of P' in the shadow forms is used as Dref + out << "), " << texCoordZ; + } + else + { + switch (textureFunction.coords) + { + case 3: + out << "), t.z"; + break; + case 4: + out << "), t.w"; + break; + default: + UNREACHABLE(); + } + } + } + else + { + switch (textureFunction.method) + { + case TextureFunctionHLSL::TextureFunction::IMPLICIT: + out << ")"; + break; + case TextureFunctionHLSL::TextureFunction::BIAS: + out << "), bias"; + break; + case TextureFunctionHLSL::TextureFunction::LOD: + out << "), lod"; + break; + case TextureFunctionHLSL::TextureFunction::LOD0: + out << "), 0"; + break; + case TextureFunctionHLSL::TextureFunction::LOD0BIAS: + out << "), bias"; + break; + default: + UNREACHABLE(); + } + } + + if (textureFunction.offset && + (!IsIntegerSampler(textureFunction.sampler) || + textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH)) + { + out << ", offset"; + } + } + else + UNREACHABLE(); + + out << ");\n"; // Close the sample function call and return statement +} + +} // Anonymous namespace + +ImmutableString TextureFunctionHLSL::TextureFunction::name() const +{ + static const ImmutableString kGlTextureName("gl_texture"); + + ImmutableString suffix(TextureTypeSuffix(this->sampler)); + + ImmutableStringBuilder name(kGlTextureName.length() + suffix.length() + 4u + 6u + 5u); + + name << kGlTextureName; + + // We need to include full the sampler type in the function name to make the signature unique + // on D3D11, where samplers are passed to texture functions as indices. + name << suffix; + + if (proj) + { + name << "Proj"; + } + + if (offset) + { + name << "Offset"; + } + + switch (method) + { + case IMPLICIT: + break; + case BIAS: + break; // Extra parameter makes the signature unique + case LOD: + name << "Lod"; + break; + case LOD0: + name << "Lod0"; + break; + case LOD0BIAS: + name << "Lod0"; + break; // Extra parameter makes the signature unique + case SIZE: + name << "Size"; + break; + case FETCH: + name << "Fetch"; + break; + case GRAD: + name << "Grad"; + break; + case GATHER: + name << "Gather"; + break; + default: + UNREACHABLE(); + } + + return name; +} + +const char *TextureFunctionHLSL::TextureFunction::getReturnType() const +{ + if (method == TextureFunction::SIZE) + { + switch (sampler) + { + case EbtSampler2D: + case EbtISampler2D: + case EbtUSampler2D: + case EbtSampler2DShadow: + case EbtSamplerCube: + case EbtISamplerCube: + case EbtUSamplerCube: + case EbtSamplerCubeShadow: + case EbtSamplerExternalOES: + case EbtSampler2DMS: + case EbtISampler2DMS: + case EbtUSampler2DMS: + case EbtSamplerVideoWEBGL: + return "int2"; + case EbtSampler3D: + case EbtISampler3D: + case EbtUSampler3D: + case EbtSampler2DArray: + case EbtISampler2DArray: + case EbtUSampler2DArray: + case EbtSampler2DMSArray: + case EbtISampler2DMSArray: + case EbtUSampler2DMSArray: + case EbtSampler2DArrayShadow: + return "int3"; + case EbtISamplerBuffer: + case EbtUSamplerBuffer: + case EbtSamplerBuffer: + return "int"; + default: + UNREACHABLE(); + } + } + else // Sampling function + { + switch (sampler) + { + case EbtSampler2D: + case EbtSampler2DMS: + case EbtSampler2DMSArray: + case EbtSampler3D: + case EbtSamplerCube: + case EbtSampler2DArray: + case EbtSamplerExternalOES: + case EbtSamplerVideoWEBGL: + case EbtSamplerBuffer: + return "float4"; + case EbtISampler2D: + case EbtISampler2DMS: + case EbtISampler2DMSArray: + case EbtISampler3D: + case EbtISamplerCube: + case EbtISampler2DArray: + case EbtISamplerBuffer: + return "int4"; + case EbtUSampler2D: + case EbtUSampler2DMS: + case EbtUSampler2DMSArray: + case EbtUSampler3D: + case EbtUSamplerCube: + case EbtUSampler2DArray: + case EbtUSamplerBuffer: + return "uint4"; + case EbtSampler2DShadow: + case EbtSamplerCubeShadow: + case EbtSampler2DArrayShadow: + if (method == TextureFunctionHLSL::TextureFunction::GATHER) + { + return "float4"; + } + else + { + return "float"; + } + default: + UNREACHABLE(); + } + } + return ""; +} + +bool TextureFunctionHLSL::TextureFunction::operator<(const TextureFunction &rhs) const +{ + return std::tie(sampler, coords, proj, offset, method) < + std::tie(rhs.sampler, rhs.coords, rhs.proj, rhs.offset, rhs.method); +} + +ImmutableString TextureFunctionHLSL::useTextureFunction(const ImmutableString &name, + TBasicType samplerType, + int coords, + size_t argumentCount, + bool lod0, + sh::GLenum shaderType) +{ + TextureFunction textureFunction; + textureFunction.sampler = samplerType; + textureFunction.coords = coords; + textureFunction.method = TextureFunction::IMPLICIT; + textureFunction.proj = false; + textureFunction.offset = false; + + if (name == "texture2D" || name == "textureCube" || name == "texture") + { + textureFunction.method = TextureFunction::IMPLICIT; + } + else if (name == "texture2DProj" || name == "textureProj") + { + textureFunction.method = TextureFunction::IMPLICIT; + textureFunction.proj = true; + } + else if (name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod" || + name == "texture2DLodEXT" || name == "textureCubeLodEXT") + { + textureFunction.method = TextureFunction::LOD; + } + else if (name == "texture2DProjLod" || name == "textureProjLod" || + name == "texture2DProjLodEXT") + { + textureFunction.method = TextureFunction::LOD; + textureFunction.proj = true; + } + else if (name == "textureSize") + { + textureFunction.method = TextureFunction::SIZE; + } + else if (name == "textureOffset") + { + textureFunction.method = TextureFunction::IMPLICIT; + textureFunction.offset = true; + } + else if (name == "textureProjOffset") + { + textureFunction.method = TextureFunction::IMPLICIT; + textureFunction.offset = true; + textureFunction.proj = true; + } + else if (name == "textureLodOffset") + { + textureFunction.method = TextureFunction::LOD; + textureFunction.offset = true; + } + else if (name == "textureProjLodOffset") + { + textureFunction.method = TextureFunction::LOD; + textureFunction.proj = true; + textureFunction.offset = true; + } + else if (name == "texelFetch") + { + textureFunction.method = TextureFunction::FETCH; + } + else if (name == "texelFetchOffset") + { + textureFunction.method = TextureFunction::FETCH; + textureFunction.offset = true; + } + else if (name == "textureGrad" || name == "texture2DGradEXT") + { + textureFunction.method = TextureFunction::GRAD; + } + else if (name == "textureGradOffset") + { + textureFunction.method = TextureFunction::GRAD; + textureFunction.offset = true; + } + else if (name == "textureProjGrad" || name == "texture2DProjGradEXT" || + name == "textureCubeGradEXT") + { + textureFunction.method = TextureFunction::GRAD; + textureFunction.proj = true; + } + else if (name == "textureProjGradOffset") + { + textureFunction.method = TextureFunction::GRAD; + textureFunction.proj = true; + textureFunction.offset = true; + } + else if (name == "textureGather") + { + textureFunction.method = TextureFunction::GATHER; + } + else if (name == "textureGatherOffset") + { + textureFunction.method = TextureFunction::GATHER; + textureFunction.offset = true; + } + else if (name == "textureVideoWEBGL") + { + textureFunction.method = TextureFunction::IMPLICIT; + } + else + UNREACHABLE(); + + if (textureFunction.method == + TextureFunction::IMPLICIT) // Could require lod 0 or have a bias argument + { + size_t mandatoryArgumentCount = 2; // All functions have sampler and coordinate arguments + + if (textureFunction.offset) + { + mandatoryArgumentCount++; + } + + bool bias = (argumentCount > mandatoryArgumentCount); // Bias argument is optional + + if (lod0 || shaderType == GL_VERTEX_SHADER || shaderType == GL_COMPUTE_SHADER) + { + if (bias) + { + textureFunction.method = TextureFunction::LOD0BIAS; + } + else + { + textureFunction.method = TextureFunction::LOD0; + } + } + else if (bias) + { + textureFunction.method = TextureFunction::BIAS; + } + } + + mUsesTexture.insert(textureFunction); + return textureFunction.name(); +} + +void TextureFunctionHLSL::textureFunctionHeader(TInfoSinkBase &out, + const ShShaderOutput outputType, + bool getDimensionsIgnoresBaseLevel) +{ + for (const TextureFunction &textureFunction : mUsesTexture) + { + // Function header + out << textureFunction.getReturnType() << " " << textureFunction.name() << "("; + + OutputTextureFunctionArgumentList(out, textureFunction, outputType); + + out << ")\n" + "{\n"; + + // In some cases we use a variable to store the texture/sampler objects, but to work around + // a D3D11 compiler bug related to discard inside a loop that is conditional on texture + // sampling we need to call the function directly on references to the texture and sampler + // arrays. The bug was found using dEQP-GLES3.functional.shaders.discard*loop_texture* + // tests. + ImmutableString textureReference(""); + ImmutableString samplerReference(""); + GetTextureReference(out, textureFunction, outputType, &textureReference, &samplerReference); + + if (textureFunction.method == TextureFunction::SIZE) + { + OutputTextureSizeFunctionBody(out, textureFunction, textureReference, + getDimensionsIgnoresBaseLevel); + } + else + { + ImmutableString texCoordX("t.x"); + ImmutableString texCoordY("t.y"); + ImmutableString texCoordZ("t.z"); + if (textureFunction.method == TextureFunction::GATHER) + { + OutputTextureGatherFunctionBody(out, textureFunction, outputType, textureReference, + samplerReference, texCoordX, texCoordY, texCoordZ); + } + else + { + ProjectTextureCoordinates(textureFunction, &texCoordX, &texCoordY, &texCoordZ); + OutputIntegerTextureSampleFunctionComputations( + out, textureFunction, outputType, textureReference, &texCoordX, &texCoordY, + &texCoordZ, getDimensionsIgnoresBaseLevel); + OutputTextureSampleFunctionReturnStatement(out, textureFunction, outputType, + textureReference, samplerReference, + texCoordX, texCoordY, texCoordZ); + } + } + + out << "}\n" + "\n"; + } +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/TextureFunctionHLSL.h b/gfx/angle/checkout/src/compiler/translator/TextureFunctionHLSL.h new file mode 100644 index 0000000000..6e81ad00c6 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/TextureFunctionHLSL.h @@ -0,0 +1,77 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// TextureFunctionHLSL: Class for writing implementations of ESSL texture functions into HLSL +// output. Some of the implementations are straightforward and just call the HLSL equivalent of the +// ESSL texture function, others do more work to emulate ESSL texture sampling or size query +// behavior. +// + +#ifndef COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_ +#define COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_ + +#include + +#include "GLSLANG/ShaderLang.h" +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/Common.h" +#include "compiler/translator/InfoSink.h" + +namespace sh +{ + +class TextureFunctionHLSL final : angle::NonCopyable +{ + public: + struct TextureFunction + { + // See ESSL 3.00.6 section 8.8 for reference about what the different methods below do. + enum Method + { + IMPLICIT, // Mipmap LOD determined implicitly (standard lookup) + BIAS, + LOD, + LOD0, + LOD0BIAS, + SIZE, // textureSize() + FETCH, + GRAD, + GATHER + }; + + ImmutableString name() const; + + bool operator<(const TextureFunction &rhs) const; + + const char *getReturnType() const; + + TBasicType sampler; + int coords; + bool proj; + bool offset; + Method method; + }; + + // Returns the name of the texture function implementation to call. + // The name that's passed in is the name of the GLSL texture function that it should implement. + ImmutableString useTextureFunction(const ImmutableString &name, + TBasicType samplerType, + int coords, + size_t argumentCount, + bool lod0, + sh::GLenum shaderType); + + void textureFunctionHeader(TInfoSinkBase &out, + const ShShaderOutput outputType, + bool getDimensionsIgnoresBaseLevel); + + private: + typedef std::set TextureFunctionSet; + TextureFunctionSet mUsesTexture; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/TranslatorESSL.cpp b/gfx/angle/checkout/src/compiler/translator/TranslatorESSL.cpp new file mode 100644 index 0000000000..5179b8c9b3 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/TranslatorESSL.cpp @@ -0,0 +1,219 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/TranslatorESSL.h" + +#include "angle_gl.h" +#include "common/utilities.h" +#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" +#include "compiler/translator/OutputESSL.h" +#include "compiler/translator/tree_ops/RecordConstantPrecision.h" + +namespace sh +{ + +TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec) + : TCompiler(type, spec, SH_ESSL_OUTPUT) +{} + +void TranslatorESSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, + const ShCompileOptions &compileOptions) +{ + if (compileOptions.emulateAtan2FloatFunction) + { + InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu); + } +} + +bool TranslatorESSL::translate(TIntermBlock *root, + const ShCompileOptions &compileOptions, + PerformanceDiagnostics * /*perfDiagnostics*/) +{ + TInfoSinkBase &sink = getInfoSink().obj; + + int shaderVer = getShaderVersion(); // Frontend shader version. + if (hasPixelLocalStorageUniforms() && + ShPixelLocalStorageTypeUsesImages(compileOptions.pls.type)) + { + // The backend translator emits shader image code. Use a minimum version of 310. + shaderVer = std::max(shaderVer, 310); + } + if (shaderVer > 100) + { + sink << "#version " << shaderVer << " es\n"; + } + + // Write built-in extension behaviors. + writeExtensionBehavior(compileOptions); + + // Write pragmas after extensions because some drivers consider pragmas + // like non-preprocessor tokens. + WritePragma(sink, compileOptions, getPragma()); + + if (!RecordConstantPrecision(this, root, &getSymbolTable())) + { + return false; + } + + // Write emulated built-in functions if needed. + if (!getBuiltInFunctionEmulator().isOutputEmpty()) + { + sink << "// BEGIN: Generated code for built-in function emulation\n\n"; + if (getShaderType() == GL_FRAGMENT_SHADER) + { + sink << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n" + << "#define emu_precision highp\n" + << "#else\n" + << "#define emu_precision mediump\n" + << "#endif\n\n"; + } + else + { + sink << "#define emu_precision highp\n"; + } + + getBuiltInFunctionEmulator().outputEmulatedFunctions(sink); + sink << "// END: Generated code for built-in function emulation\n\n"; + } + + if (getShaderType() == GL_FRAGMENT_SHADER) + { + EmitEarlyFragmentTestsGLSL(*this, sink); + } + + if (getShaderType() == GL_COMPUTE_SHADER) + { + EmitWorkGroupSizeGLSL(*this, sink); + } + + if (getShaderType() == GL_GEOMETRY_SHADER_EXT) + { + WriteGeometryShaderLayoutQualifiers( + sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(), + getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices()); + } + + // Write translated shader. + TOutputESSL outputESSL(this, sink, compileOptions); + + root->traverse(&outputESSL); + + return true; +} + +bool TranslatorESSL::shouldFlattenPragmaStdglInvariantAll() +{ + // If following the spec to the letter, we should not flatten this pragma. + // However, the spec's wording means that the pragma applies only to outputs. + // This contradicts the spirit of using the pragma, + // because if the pragma is used in a vertex shader, + // the only way to be able to link it to a fragment shader + // is to manually qualify each of fragment shader's inputs as invariant. + // Which defeats the purpose of this pragma - temporarily make all varyings + // invariant for debugging. + // Thus, we should be non-conformant to spec's letter here and flatten. + return true; +} + +void TranslatorESSL::writeExtensionBehavior(const ShCompileOptions &compileOptions) +{ + TInfoSinkBase &sink = getInfoSink().obj; + const TExtensionBehavior &extBehavior = getExtensionBehavior(); + for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); iter != extBehavior.end(); + ++iter) + { + if (iter->second != EBhUndefined) + { + const bool isMultiview = (iter->first == TExtension::OVR_multiview) || + (iter->first == TExtension::OVR_multiview2); + if (getResources().NV_shader_framebuffer_fetch && + iter->first == TExtension::EXT_shader_framebuffer_fetch) + { + sink << "#extension GL_NV_shader_framebuffer_fetch : " + << GetBehaviorString(iter->second) << "\n"; + } + else if (getResources().NV_draw_buffers && iter->first == TExtension::EXT_draw_buffers) + { + sink << "#extension GL_NV_draw_buffers : " << GetBehaviorString(iter->second) + << "\n"; + } + else if (isMultiview) + { + // Only either OVR_multiview OR OVR_multiview2 should be emitted. + if ((iter->first != TExtension::OVR_multiview) || + !IsExtensionEnabled(extBehavior, TExtension::OVR_multiview2)) + { + EmitMultiviewGLSL(*this, compileOptions, iter->first, iter->second, sink); + } + } + else if (iter->first == TExtension::EXT_geometry_shader || + iter->first == TExtension::OES_geometry_shader) + { + sink << "#ifdef GL_EXT_geometry_shader\n" + << "#extension GL_EXT_geometry_shader : " << GetBehaviorString(iter->second) + << "\n" + << "#elif defined GL_OES_geometry_shader\n" + << "#extension GL_OES_geometry_shader : " << GetBehaviorString(iter->second) + << "\n"; + if (iter->second == EBhRequire) + { + sink << "#else\n" + << "#error \"No geometry shader extensions available.\" // Only generate " + "this if the extension is \"required\"\n"; + } + sink << "#endif\n"; + } + else if (iter->first == TExtension::ANGLE_multi_draw) + { + // Don't emit anything. This extension is emulated + ASSERT(compileOptions.emulateGLDrawID); + continue; + } + else if (iter->first == TExtension::ANGLE_base_vertex_base_instance_shader_builtin) + { + // Don't emit anything. This extension is emulated + ASSERT(compileOptions.emulateGLBaseVertexBaseInstance); + continue; + } + else if (iter->first == TExtension::ANGLE_shader_pixel_local_storage) + { + // TODO(anglebug.com/7279): future impl that uses EXT_shader_pixel_local_storage. + if (compileOptions.pls.type == ShPixelLocalStorageType::FramebufferFetch) + { + // Just enable the extension. Appropriate warnings will be generated by the + // frontend compiler for GL_ANGLE_shader_pixel_local_storage, if desired. + sink << "#extension GL_EXT_shader_framebuffer_fetch : enable\n"; + } + continue; + } + else if (iter->first == TExtension::EXT_shader_framebuffer_fetch) + { + sink << "#extension GL_EXT_shader_framebuffer_fetch : " + << GetBehaviorString(iter->second) << "\n"; + continue; + } + else if (iter->first == TExtension::EXT_shader_framebuffer_fetch_non_coherent) + { + sink << "#extension GL_EXT_shader_framebuffer_fetch_non_coherent : " + << GetBehaviorString(iter->second) << "\n"; + continue; + } + else if (iter->first == TExtension::WEBGL_video_texture) + { + // Don't emit anything. This extension is emulated + // TODO(crbug.com/776222): support external image. + continue; + } + else + { + sink << "#extension " << GetExtensionNameString(iter->first) << " : " + << GetBehaviorString(iter->second) << "\n"; + } + } + } +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/TranslatorESSL.h b/gfx/angle/checkout/src/compiler/translator/TranslatorESSL.h new file mode 100644 index 0000000000..913d441364 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/TranslatorESSL.h @@ -0,0 +1,35 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TRANSLATORESSL_H_ +#define COMPILER_TRANSLATOR_TRANSLATORESSL_H_ + +#include "compiler/translator/Compiler.h" + +namespace sh +{ + +class TranslatorESSL : public TCompiler +{ + public: + TranslatorESSL(sh::GLenum type, ShShaderSpec spec); + + protected: + void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, + const ShCompileOptions &compileOptions) override; + + [[nodiscard]] bool translate(TIntermBlock *root, + const ShCompileOptions &compileOptions, + PerformanceDiagnostics *perfDiagnostics) override; + bool shouldFlattenPragmaStdglInvariantAll() override; + + private: + void writeExtensionBehavior(const ShCompileOptions &compileOptions); +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TRANSLATORESSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/TranslatorGLSL.cpp b/gfx/angle/checkout/src/compiler/translator/TranslatorGLSL.cpp new file mode 100644 index 0000000000..76e0130e77 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/TranslatorGLSL.cpp @@ -0,0 +1,388 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/TranslatorGLSL.h" + +#include "angle_gl.h" +#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" +#include "compiler/translator/ExtensionGLSL.h" +#include "compiler/translator/OutputGLSL.h" +#include "compiler/translator/VersionGLSL.h" +#include "compiler/translator/tree_ops/RewriteTexelFetchOffset.h" +#include "compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.h" +#include "compiler/translator/tree_ops/apple/RewriteUnaryMinusOperatorFloat.h" + +namespace sh +{ + +TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) + : TCompiler(type, spec, output) +{} + +void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, + const ShCompileOptions &compileOptions) +{ + if (compileOptions.emulateAbsIntFunction) + { + InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(emu, getShaderType()); + } + + if (compileOptions.emulateIsnanFloatFunction) + { + InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(emu, getShaderVersion()); + } + + if (compileOptions.emulateAtan2FloatFunction) + { + InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu); + } + + int targetGLSLVersion = ShaderOutputTypeToGLSLVersion(getOutputType()); + InitBuiltInFunctionEmulatorForGLSLMissingFunctions(emu, getShaderType(), targetGLSLVersion); +} + +bool TranslatorGLSL::translate(TIntermBlock *root, + const ShCompileOptions &compileOptions, + PerformanceDiagnostics * /*perfDiagnostics*/) +{ + TInfoSinkBase &sink = getInfoSink().obj; + + // Write GLSL version. + writeVersion(root); + + // Write extension behaviour as needed + writeExtensionBehavior(root, compileOptions); + + // Write pragmas after extensions because some drivers consider pragmas + // like non-preprocessor tokens. + WritePragma(sink, compileOptions, getPragma()); + + // If flattening the global invariant pragma, write invariant declarations for built-in + // variables. It should be harmless to do this twice in the case that the shader also explicitly + // did this. However, it's important to emit invariant qualifiers only for those built-in + // variables that are actually used, to avoid affecting the behavior of the shader. + if (compileOptions.flattenPragmaSTDGLInvariantAll && getPragma().stdgl.invariantAll && + !sh::RemoveInvariant(getShaderType(), getShaderVersion(), getOutputType(), compileOptions)) + { + ASSERT(wereVariablesCollected()); + + switch (getShaderType()) + { + case GL_VERTEX_SHADER: + sink << "invariant gl_Position;\n"; + + // gl_PointSize should be declared invariant in both ESSL 1.00 and 3.00 fragment + // shaders if it's statically referenced. + conditionallyOutputInvariantDeclaration("gl_PointSize"); + break; + case GL_FRAGMENT_SHADER: + // The preprocessor will reject this pragma if it's used in ESSL 3.00 fragment + // shaders, so we can use simple logic to determine whether to declare these + // variables invariant. + conditionallyOutputInvariantDeclaration("gl_FragCoord"); + conditionallyOutputInvariantDeclaration("gl_PointCoord"); + break; + default: + // Currently not reached, but leave this in for future expansion. + ASSERT(false); + break; + } + } + + if (compileOptions.rewriteTexelFetchOffsetToTexelFetch) + { + if (!sh::RewriteTexelFetchOffset(this, root, getSymbolTable(), getShaderVersion())) + { + return false; + } + } + + if (compileOptions.rewriteFloatUnaryMinusOperator) + { + if (!sh::RewriteUnaryMinusOperatorFloat(this, root)) + { + return false; + } + } + + if (compileOptions.rewriteRowMajorMatrices && getShaderVersion() >= 300) + { + if (!RewriteRowMajorMatrices(this, root, &getSymbolTable())) + { + return false; + } + } + + // Write emulated built-in functions if needed. + if (!getBuiltInFunctionEmulator().isOutputEmpty()) + { + sink << "// BEGIN: Generated code for built-in function emulation\n\n"; + sink << "#define emu_precision\n\n"; + getBuiltInFunctionEmulator().outputEmulatedFunctions(sink); + sink << "// END: Generated code for built-in function emulation\n\n"; + } + + // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData + // if it's core profile shaders and they are used. + if (getShaderType() == GL_FRAGMENT_SHADER) + { + const bool mayHaveESSL1SecondaryOutputs = + IsExtensionEnabled(getExtensionBehavior(), TExtension::EXT_blend_func_extended) && + getShaderVersion() == 100; + const bool declareGLFragmentOutputs = IsGLSL130OrNewer(getOutputType()); + + bool hasGLFragColor = false; + bool hasGLFragData = false; + bool hasGLSecondaryFragColor = false; + bool hasGLSecondaryFragData = false; + + for (const auto &outputVar : mOutputVariables) + { + if (declareGLFragmentOutputs) + { + if (outputVar.name == "gl_FragColor") + { + ASSERT(!hasGLFragColor); + hasGLFragColor = true; + continue; + } + else if (outputVar.name == "gl_FragData") + { + ASSERT(!hasGLFragData); + hasGLFragData = true; + continue; + } + } + if (mayHaveESSL1SecondaryOutputs) + { + if (outputVar.name == "gl_SecondaryFragColorEXT") + { + ASSERT(!hasGLSecondaryFragColor); + hasGLSecondaryFragColor = true; + continue; + } + else if (outputVar.name == "gl_SecondaryFragDataEXT") + { + ASSERT(!hasGLSecondaryFragData); + hasGLSecondaryFragData = true; + continue; + } + } + } + ASSERT(!((hasGLFragColor || hasGLSecondaryFragColor) && + (hasGLFragData || hasGLSecondaryFragData))); + if (hasGLFragColor) + { + sink << "out vec4 webgl_FragColor;\n"; + } + if (hasGLFragData) + { + sink << "out vec4 webgl_FragData[gl_MaxDrawBuffers];\n"; + } + if (hasGLSecondaryFragColor) + { + sink << "out vec4 webgl_SecondaryFragColor;\n"; + } + if (hasGLSecondaryFragData) + { + sink << "out vec4 webgl_SecondaryFragData[" << getResources().MaxDualSourceDrawBuffers + << "];\n"; + } + + EmitEarlyFragmentTestsGLSL(*this, sink); + } + + if (getShaderType() == GL_COMPUTE_SHADER) + { + EmitWorkGroupSizeGLSL(*this, sink); + } + + if (getShaderType() == GL_GEOMETRY_SHADER_EXT) + { + WriteGeometryShaderLayoutQualifiers( + sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(), + getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices()); + } + + // Write translated shader. + TOutputGLSL outputGLSL(this, sink, compileOptions); + + root->traverse(&outputGLSL); + + return true; +} + +bool TranslatorGLSL::shouldFlattenPragmaStdglInvariantAll() +{ + // Required when outputting to any GLSL version greater than 1.20, but since ANGLE doesn't + // translate to that version, return true for the next higher version. + return IsGLSL130OrNewer(getOutputType()); +} + +bool TranslatorGLSL::shouldCollectVariables(const ShCompileOptions &compileOptions) +{ + return compileOptions.flattenPragmaSTDGLInvariantAll || + TCompiler::shouldCollectVariables(compileOptions); +} + +void TranslatorGLSL::writeVersion(TIntermNode *root) +{ + TVersionGLSL versionGLSL(getShaderType(), getPragma(), getOutputType()); + root->traverse(&versionGLSL); + int version = versionGLSL.getVersion(); + // We need to write version directive only if it is greater than 110. + // If there is no version directive in the shader, 110 is implied. + if (version > 110) + { + TInfoSinkBase &sink = getInfoSink().obj; + sink << "#version " << version << "\n"; + } +} + +void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root, + const ShCompileOptions &compileOptions) +{ + bool usesTextureCubeMapArray = false; + bool usesTextureBuffer = false; + + TInfoSinkBase &sink = getInfoSink().obj; + const TExtensionBehavior &extBehavior = getExtensionBehavior(); + for (const auto &iter : extBehavior) + { + if (iter.second == EBhUndefined) + { + continue; + } + + if (getOutputType() == SH_GLSL_COMPATIBILITY_OUTPUT) + { + // For GLSL output, we don't need to emit most extensions explicitly, + // but some we need to translate in GL compatibility profile. + if (iter.first == TExtension::EXT_shader_texture_lod) + { + sink << "#extension GL_ARB_shader_texture_lod : " << GetBehaviorString(iter.second) + << "\n"; + } + + if (iter.first == TExtension::EXT_draw_buffers) + { + sink << "#extension GL_ARB_draw_buffers : " << GetBehaviorString(iter.second) + << "\n"; + } + + if (iter.first == TExtension::EXT_geometry_shader || + iter.first == TExtension::OES_geometry_shader) + { + sink << "#extension GL_ARB_geometry_shader4 : " << GetBehaviorString(iter.second) + << "\n"; + } + } + + const bool isMultiview = + (iter.first == TExtension::OVR_multiview) || (iter.first == TExtension::OVR_multiview2); + if (isMultiview) + { + // Only either OVR_multiview or OVR_multiview2 should be emitted. + if ((iter.first != TExtension::OVR_multiview) || + !IsExtensionEnabled(extBehavior, TExtension::OVR_multiview2)) + { + EmitMultiviewGLSL(*this, compileOptions, iter.first, iter.second, sink); + } + } + + // Support ANGLE_texture_multisample extension on GLSL300 + if (getShaderVersion() >= 300 && iter.first == TExtension::ANGLE_texture_multisample && + getOutputType() < SH_GLSL_330_CORE_OUTPUT) + { + sink << "#extension GL_ARB_texture_multisample : " << GetBehaviorString(iter.second) + << "\n"; + } + + if ((iter.first == TExtension::OES_texture_cube_map_array || + iter.first == TExtension::EXT_texture_cube_map_array) && + (iter.second == EBhRequire || iter.second == EBhEnable)) + { + usesTextureCubeMapArray = true; + } + + if ((iter.first == TExtension::OES_texture_buffer || + iter.first == TExtension::EXT_texture_buffer) && + (iter.second == EBhRequire || iter.second == EBhEnable)) + { + usesTextureBuffer = true; + } + } + + // GLSL ES 3 explicit location qualifiers need to use an extension before GLSL 330 + if (getShaderVersion() >= 300 && getOutputType() < SH_GLSL_330_CORE_OUTPUT && + getShaderType() != GL_COMPUTE_SHADER) + { + sink << "#extension GL_ARB_explicit_attrib_location : require\n"; + } + + // Need to enable gpu_shader5 to have index constant sampler array indexing + if (getOutputType() != SH_ESSL_OUTPUT && getOutputType() < SH_GLSL_400_CORE_OUTPUT && + getShaderVersion() == 100) + { + // Don't use "require" on to avoid breaking WebGL 1 on drivers that silently + // support index constant sampler array indexing, but don't have the extension or + // on drivers that don't have the extension at all as it would break WebGL 1 for + // some users. + sink << "#extension GL_ARB_gpu_shader5 : enable\n"; + sink << "#extension GL_EXT_gpu_shader5 : enable\n"; + } + + if (usesTextureCubeMapArray) + { + if (getOutputType() >= SH_GLSL_COMPATIBILITY_OUTPUT && + getOutputType() < SH_GLSL_400_CORE_OUTPUT) + { + sink << "#extension GL_ARB_texture_cube_map_array : enable\n"; + } + else if (getOutputType() == SH_ESSL_OUTPUT && getShaderVersion() < 320) + { + sink << "#extension GL_OES_texture_cube_map_array : enable\n"; + sink << "#extension GL_EXT_texture_cube_map_array : enable\n"; + } + } + + if (usesTextureBuffer) + { + if (getOutputType() >= SH_GLSL_COMPATIBILITY_OUTPUT && + getOutputType() < SH_GLSL_400_CORE_OUTPUT) + { + sink << "#extension GL_ARB_texture_buffer_objects : enable\n"; + } + else if (getOutputType() == SH_ESSL_OUTPUT && getShaderVersion() < 320) + { + sink << "#extension GL_OES_texture_buffer : enable\n"; + sink << "#extension GL_EXT_texture_buffer : enable\n"; + } + } + + TExtensionGLSL extensionGLSL(getOutputType()); + root->traverse(&extensionGLSL); + + for (const auto &ext : extensionGLSL.getEnabledExtensions()) + { + sink << "#extension " << ext << " : enable\n"; + } + for (const auto &ext : extensionGLSL.getRequiredExtensions()) + { + sink << "#extension " << ext << " : require\n"; + } +} + +void TranslatorGLSL::conditionallyOutputInvariantDeclaration(const char *builtinVaryingName) +{ + if (isVaryingDefined(builtinVaryingName)) + { + TInfoSinkBase &sink = getInfoSink().obj; + sink << "invariant " << builtinVaryingName << ";\n"; + } +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/TranslatorGLSL.h b/gfx/angle/checkout/src/compiler/translator/TranslatorGLSL.h new file mode 100644 index 0000000000..0e0c65f09a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/TranslatorGLSL.h @@ -0,0 +1,38 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ +#define COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ + +#include "compiler/translator/Compiler.h" + +namespace sh +{ + +class TranslatorGLSL : public TCompiler +{ + public: + TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); + + protected: + void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, + const ShCompileOptions &compileOptions) override; + + [[nodiscard]] bool translate(TIntermBlock *root, + const ShCompileOptions &compileOptions, + PerformanceDiagnostics *perfDiagnostics) override; + bool shouldFlattenPragmaStdglInvariantAll() override; + bool shouldCollectVariables(const ShCompileOptions &compileOptions) override; + + private: + void writeVersion(TIntermNode *root); + void writeExtensionBehavior(TIntermNode *root, const ShCompileOptions &compileOptions); + void conditionallyOutputInvariantDeclaration(const char *builtinVaryingName); +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/TranslatorHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/TranslatorHLSL.cpp new file mode 100644 index 0000000000..d07ed2975e --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/TranslatorHLSL.cpp @@ -0,0 +1,311 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/TranslatorHLSL.h" + +#include "compiler/translator/OutputHLSL.h" +#include "compiler/translator/tree_ops/RemoveDynamicIndexing.h" +#include "compiler/translator/tree_ops/RewriteTexelFetchOffset.h" +#include "compiler/translator/tree_ops/SimplifyLoopConditions.h" +#include "compiler/translator/tree_ops/SplitSequenceOperator.h" +#include "compiler/translator/tree_ops/d3d/AddDefaultReturnStatements.h" +#include "compiler/translator/tree_ops/d3d/AggregateAssignArraysInSSBOs.h" +#include "compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.h" +#include "compiler/translator/tree_ops/d3d/ArrayReturnValueToOutParameter.h" +#include "compiler/translator/tree_ops/d3d/BreakVariableAliasingInInnerLoops.h" +#include "compiler/translator/tree_ops/d3d/ExpandIntegerPowExpressions.h" +#include "compiler/translator/tree_ops/d3d/RecordUniformBlocksWithLargeArrayMember.h" +#include "compiler/translator/tree_ops/d3d/RewriteAtomicFunctionExpressions.h" +#include "compiler/translator/tree_ops/d3d/RewriteElseBlocks.h" +#include "compiler/translator/tree_ops/d3d/RewriteExpressionsWithShaderStorageBlock.h" +#include "compiler/translator/tree_ops/d3d/RewriteUnaryMinusOperatorInt.h" +#include "compiler/translator/tree_ops/d3d/SeparateArrayConstructorStatements.h" +#include "compiler/translator/tree_ops/d3d/SeparateArrayInitialization.h" +#include "compiler/translator/tree_ops/d3d/SeparateExpressionsReturningArrays.h" +#include "compiler/translator/tree_ops/d3d/UnfoldShortCircuitToIf.h" +#include "compiler/translator/tree_ops/d3d/WrapSwitchStatementsInBlocks.h" +#include "compiler/translator/tree_util/IntermNodePatternMatcher.h" + +namespace sh +{ + +TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) + : TCompiler(type, spec, output) +{} + +bool TranslatorHLSL::translate(TIntermBlock *root, + const ShCompileOptions &compileOptions, + PerformanceDiagnostics *perfDiagnostics) +{ + // A few transformations leave the tree in an inconsistent state. For example, when unfolding + // the short-circuit in the following function: + // + // mediump float f(float a) { return a > 0 ? 0.0 : 1.0; } + // + // a temp variable is created to hold the result of the expression. Currently the precision of + // the return value of the function is not propagated to its return expressions. Additionally, + // an expression such as + // + // cond ? gl_NumWorkGroups.x : gl_NumWorkGroups.y + // + // does not have a precision as the built-in does not specify a precision. + // + // Precision is not applicable to HLSL so fixing these issues are deferred. + mValidateASTOptions.validatePrecision = false; + + const ShBuiltInResources &resources = getResources(); + int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; + int maxDualSourceDrawBuffers = + resources.EXT_blend_func_extended ? resources.MaxDualSourceDrawBuffers : 0; + + if (!sh::AddDefaultReturnStatements(this, root)) + { + return false; + } + + // Note that SimplifyLoopConditions needs to be run before any other AST transformations that + // may need to generate new statements from loop conditions or loop expressions. + // Note that SeparateDeclarations has already been run in TCompiler::compileTreeImpl(). + if (!SimplifyLoopConditions( + this, root, + IntermNodePatternMatcher::kExpressionReturningArray | + IntermNodePatternMatcher::kUnfoldedShortCircuitExpression | + IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue, + &getSymbolTable())) + { + return false; + } + + if (!SplitSequenceOperator( + this, root, + IntermNodePatternMatcher::kExpressionReturningArray | + IntermNodePatternMatcher::kUnfoldedShortCircuitExpression | + IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue, + &getSymbolTable())) + { + return false; + } + + // Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf. + if (!UnfoldShortCircuitToIf(this, root, &getSymbolTable())) + { + return false; + } + + if (!SeparateArrayConstructorStatements(this, root)) + { + return false; + } + + if (getShaderVersion() >= 310) + { + // Do element-by-element assignments of arrays in SSBOs. This allows the D3D backend to use + // RWByteAddressBuffer.Load() and .Store(), which only operate on values up to 16 bytes in + // size. Note that this must be done before SeparateExpressionsReturningArrays. + if (!sh::AggregateAssignArraysInSSBOs(this, root, &getSymbolTable())) + { + return false; + } + // Do field-by-field assignment of structs in SSBOs. This allows the D3D backend to use + // RWByteAddressBuffer.Load() and .Store(), which only operate on values up to 16 bytes in + // size. + if (!sh::AggregateAssignStructsInSSBOs(this, root, &getSymbolTable())) + { + return false; + } + } + + if (!SeparateExpressionsReturningArrays(this, root, &getSymbolTable())) + { + return false; + } + + // Note that SeparateDeclarations needs to be run before SeparateArrayInitialization. + if (!SeparateArrayInitialization(this, root)) + { + return false; + } + + // HLSL doesn't support arrays as return values, we'll need to make functions that have an array + // as a return value to use an out parameter to transfer the array data instead. + if (!ArrayReturnValueToOutParameter(this, root, &getSymbolTable())) + { + return false; + } + + if (!shouldRunLoopAndIndexingValidation(compileOptions)) + { + // HLSL doesn't support dynamic indexing of vectors and matrices. + if (!RemoveDynamicIndexingOfNonSSBOVectorOrMatrix(this, root, &getSymbolTable(), + perfDiagnostics)) + { + return false; + } + } + + // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which + // use a vertex attribute as a condition, and some related computation in the else block. + if (getOutputType() == SH_HLSL_3_0_OUTPUT && getShaderType() == GL_VERTEX_SHADER) + { + if (!sh::RewriteElseBlocks(this, root, &getSymbolTable())) + { + return false; + } + } + + // Work around an HLSL compiler frontend aliasing optimization bug. + // TODO(cwallez) The date is 2016-08-25, Microsoft said the bug would be fixed + // in the next release of d3dcompiler.dll, it would be nice to detect the DLL + // version and only apply the workaround if it is too old. + if (!sh::BreakVariableAliasingInInnerLoops(this, root)) + { + return false; + } + + // WrapSwitchStatementsInBlocks should be called after any AST transformations that might + // introduce variable declarations inside the main scope of any switch statement. It cannot + // result in no-op cases at the end of switch statements, because unreferenced variables + // have already been pruned. + if (!WrapSwitchStatementsInBlocks(this, root)) + { + return false; + } + + if (compileOptions.expandSelectHLSLIntegerPowExpressions) + { + if (!sh::ExpandIntegerPowExpressions(this, root, &getSymbolTable())) + { + return false; + } + } + + if (compileOptions.rewriteTexelFetchOffsetToTexelFetch) + { + if (!sh::RewriteTexelFetchOffset(this, root, getSymbolTable(), getShaderVersion())) + { + return false; + } + } + + if (compileOptions.rewriteIntegerUnaryMinusOperator && getShaderType() == GL_VERTEX_SHADER) + { + if (!sh::RewriteUnaryMinusOperatorInt(this, root)) + { + return false; + } + } + + if (getShaderVersion() >= 310) + { + // Due to ssbo also can be used as the argument of atomic memory functions, we should put + // RewriteExpressionsWithShaderStorageBlock before RewriteAtomicFunctionExpressions. + if (!sh::RewriteExpressionsWithShaderStorageBlock(this, root, &getSymbolTable())) + { + return false; + } + if (!sh::RewriteAtomicFunctionExpressions(this, root, &getSymbolTable(), + getShaderVersion())) + { + return false; + } + } + + mUniformBlockOptimizedMap.clear(); + mSlowCompilingUniformBlockSet.clear(); + // In order to get the exact maximum of slots are available for shader resources, which would + // been bound with StructuredBuffer, we only translate uniform block with a large array member + // into StructuredBuffer when shader version is 300. + if (getShaderVersion() == 300 && compileOptions.allowTranslateUniformBlockToStructuredBuffer) + { + if (!sh::RecordUniformBlocksWithLargeArrayMember(root, mUniformBlockOptimizedMap, + mSlowCompilingUniformBlockSet)) + { + return false; + } + } + + sh::OutputHLSL outputHLSL( + getShaderType(), getShaderSpec(), getShaderVersion(), getExtensionBehavior(), + getSourcePath(), getOutputType(), numRenderTargets, maxDualSourceDrawBuffers, getUniforms(), + compileOptions, getComputeShaderLocalSize(), &getSymbolTable(), perfDiagnostics, + mUniformBlockOptimizedMap, mShaderStorageBlocks, isEarlyFragmentTestsSpecified()); + + outputHLSL.output(root, getInfoSink().obj); + + mShaderStorageBlockRegisterMap = outputHLSL.getShaderStorageBlockRegisterMap(); + mUniformBlockRegisterMap = outputHLSL.getUniformBlockRegisterMap(); + mUniformBlockUseStructuredBufferMap = outputHLSL.getUniformBlockUseStructuredBufferMap(); + mUniformRegisterMap = outputHLSL.getUniformRegisterMap(); + mReadonlyImage2DRegisterIndex = outputHLSL.getReadonlyImage2DRegisterIndex(); + mImage2DRegisterIndex = outputHLSL.getImage2DRegisterIndex(); + mUsedImage2DFunctionNames = outputHLSL.getUsedImage2DFunctionNames(); + + return true; +} + +bool TranslatorHLSL::shouldFlattenPragmaStdglInvariantAll() +{ + // Not necessary when translating to HLSL. + return false; +} + +bool TranslatorHLSL::hasShaderStorageBlock(const std::string &uniformBlockName) const +{ + return (mShaderStorageBlockRegisterMap.count(uniformBlockName) > 0); +} + +unsigned int TranslatorHLSL::getShaderStorageBlockRegister( + const std::string &shaderStorageBlockName) const +{ + ASSERT(hasShaderStorageBlock(shaderStorageBlockName)); + return mShaderStorageBlockRegisterMap.find(shaderStorageBlockName)->second; +} + +bool TranslatorHLSL::hasUniformBlock(const std::string &uniformBlockName) const +{ + return (mUniformBlockRegisterMap.count(uniformBlockName) > 0); +} + +unsigned int TranslatorHLSL::getUniformBlockRegister(const std::string &uniformBlockName) const +{ + ASSERT(hasUniformBlock(uniformBlockName)); + return mUniformBlockRegisterMap.find(uniformBlockName)->second; +} + +const std::map *TranslatorHLSL::getUniformRegisterMap() const +{ + return &mUniformRegisterMap; +} + +const std::set *TranslatorHLSL::getSlowCompilingUniformBlockSet() const +{ + return &mSlowCompilingUniformBlockSet; +} + +unsigned int TranslatorHLSL::getReadonlyImage2DRegisterIndex() const +{ + return mReadonlyImage2DRegisterIndex; +} + +unsigned int TranslatorHLSL::getImage2DRegisterIndex() const +{ + return mImage2DRegisterIndex; +} + +const std::set *TranslatorHLSL::getUsedImage2DFunctionNames() const +{ + return &mUsedImage2DFunctionNames; +} + +bool TranslatorHLSL::shouldUniformBlockUseStructuredBuffer( + const std::string &uniformBlockName) const +{ + auto uniformBlockIter = mUniformBlockUseStructuredBufferMap.find(uniformBlockName); + return uniformBlockIter != mUniformBlockUseStructuredBufferMap.end() && + uniformBlockIter->second; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/TranslatorHLSL.h b/gfx/angle/checkout/src/compiler/translator/TranslatorHLSL.h new file mode 100644 index 0000000000..309176bed8 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/TranslatorHLSL.h @@ -0,0 +1,56 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ +#define COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ + +#include "compiler/translator/Compiler.h" + +namespace sh +{ + +class TranslatorHLSL : public TCompiler +{ + public: + TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); + TranslatorHLSL *getAsTranslatorHLSL() override { return this; } + + bool hasShaderStorageBlock(const std::string &interfaceBlockName) const; + unsigned int getShaderStorageBlockRegister(const std::string &interfaceBlockName) const; + + bool hasUniformBlock(const std::string &interfaceBlockName) const; + unsigned int getUniformBlockRegister(const std::string &interfaceBlockName) const; + bool shouldUniformBlockUseStructuredBuffer(const std::string &uniformBlockName) const; + const std::set *getSlowCompilingUniformBlockSet() const; + + const std::map *getUniformRegisterMap() const; + unsigned int getReadonlyImage2DRegisterIndex() const; + unsigned int getImage2DRegisterIndex() const; + const std::set *getUsedImage2DFunctionNames() const; + + protected: + [[nodiscard]] bool translate(TIntermBlock *root, + const ShCompileOptions &compileOptions, + PerformanceDiagnostics *perfDiagnostics) override; + bool shouldFlattenPragmaStdglInvariantAll() override; + + // collectVariables needs to be run always so registers can be assigned. + bool shouldCollectVariables(const ShCompileOptions &compileOptions) override { return true; } + + std::map mShaderStorageBlockRegisterMap; + std::map mUniformBlockRegisterMap; + std::map mUniformBlockUseStructuredBufferMap; + std::map mUniformRegisterMap; + unsigned int mReadonlyImage2DRegisterIndex; + unsigned int mImage2DRegisterIndex; + std::set mUsedImage2DFunctionNames; + std::map mUniformBlockOptimizedMap; + std::set mSlowCompilingUniformBlockSet; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/TranslatorMetal.h b/gfx/angle/checkout/src/compiler/translator/TranslatorMetal.h new file mode 100644 index 0000000000..32b7564f34 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/TranslatorMetal.h @@ -0,0 +1,62 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// TranslatorMetal: +// A GLSL-based translator that outputs shaders that fit GL_KHR_vulkan_glsl. +// It takes into account some considerations for Metal backend also. +// The shaders are then fed into glslang to spit out SPIR-V. +// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt +// +// The SPIR-V will then be translated to Metal Shading Language later in Metal backend. +// + +#ifndef LIBANGLE_RENDERER_METAL_TRANSLATORMETAL_H_ +#define LIBANGLE_RENDERER_METAL_TRANSLATORMETAL_H_ + +#include "compiler/translator/DriverUniformMetal.h" +#include "compiler/translator/TranslatorVulkan.h" +#include "compiler/translator/tree_util/DriverUniform.h" +#include "compiler/translator/tree_util/SpecializationConstant.h" + +namespace sh +{ + +// TODO: http://anglebug.com/5339 Implement it using actual specialization constant. For now we are +// redirecting to driver uniforms +class SpecConstMetal : public SpecConst +{ + public: + SpecConstMetal(TSymbolTable *symbolTable, + const ShCompileOptions &compileOptions, + GLenum shaderType) + : SpecConst(symbolTable, compileOptions, shaderType) + {} + ~SpecConstMetal() override {} + + private: +}; + +class TranslatorMetal : public TranslatorVulkan +{ + public: + TranslatorMetal(sh::GLenum type, ShShaderSpec spec); + + protected: + [[nodiscard]] bool translate(TIntermBlock *root, + const ShCompileOptions &compileOptions, + PerformanceDiagnostics *perfDiagnostics) override; + + [[nodiscard]] bool transformDepthBeforeCorrection(TIntermBlock *root, + const DriverUniform *driverUniforms) override; + + [[nodiscard]] bool insertSampleMaskWritingLogic(TInfoSinkBase &sink, + TIntermBlock *root, + const DriverUniformMetal *driverUniforms); + [[nodiscard]] bool insertRasterizerDiscardLogic(TInfoSinkBase &sink, TIntermBlock *root); +}; + +} // namespace sh + +#endif /* LIBANGLE_RENDERER_METAL_TRANSLATORMETAL_H_ */ diff --git a/gfx/angle/checkout/src/compiler/translator/TranslatorMetalDirect.h b/gfx/angle/checkout/src/compiler/translator/TranslatorMetalDirect.h new file mode 100644 index 0000000000..679687df07 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/TranslatorMetalDirect.h @@ -0,0 +1,195 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TRANSLATORMETALDIRECT_H_ +#define COMPILER_TRANSLATOR_TRANSLATORMETALDIRECT_H_ + +#include "compiler/translator/Compiler.h" + +namespace sh +{ + +constexpr const char kUniformsVar[] = "angleUniforms"; +constexpr const char kUnassignedAttributeString[] = " __unassigned_attribute__"; + +class DriverUniform; +class DriverUniformMetal; +class SpecConst; +class TOutputMSL; +class TranslatorMetalReflection; +typedef std::unordered_map originalNamesMap; +typedef std::unordered_map samplerBindingMap; +typedef std::unordered_map textureBindingMap; +typedef std::unordered_map userUniformBufferBindingMap; +typedef std::pair uboBindingInfo; +struct UBOBindingInfo +{ + size_t bindIndex = 0; + size_t arraySize = 0; +}; +typedef std::unordered_map uniformBufferBindingMap; + +namespace mtl +{ +TranslatorMetalReflection *getTranslatorMetalReflection(const TCompiler *compiler); +} + +class TranslatorMetalReflection +{ + public: + TranslatorMetalReflection() : hasUBOs(false), hasFlatInput(false) {} + ~TranslatorMetalReflection() {} + + void addOriginalName(const size_t id, const std::string &name) + { + originalNames.insert({id, name}); + } + void addSamplerBinding(const std::string &name, size_t samplerBinding) + { + samplerBindings.insert({name, samplerBinding}); + } + void addTextureBinding(const std::string &name, size_t textureBinding) + { + textureBindings.insert({name, textureBinding}); + } + void addUserUniformBufferBinding(const std::string &name, size_t userUniformBufferBinding) + { + userUniformBufferBindings.insert({name, userUniformBufferBinding}); + } + void addUniformBufferBinding(const std::string &name, UBOBindingInfo bindingInfo) + { + uniformBufferBindings.insert({name, bindingInfo}); + } + std::string getOriginalName(const size_t id) { return originalNames.at(id); } + samplerBindingMap getSamplerBindings() const { return samplerBindings; } + textureBindingMap getTextureBindings() const { return textureBindings; } + userUniformBufferBindingMap getUserUniformBufferBindings() const + { + return userUniformBufferBindings; + } + uniformBufferBindingMap getUniformBufferBindings() const { return uniformBufferBindings; } + size_t getSamplerBinding(const std::string &name) const + { + auto it = samplerBindings.find(name); + if (it != samplerBindings.end()) + { + return it->second; + } + // If we can't find a matching sampler, assert out on Debug, and return an invalid value on + // release. + ASSERT(0); + return std::numeric_limits::max(); + } + size_t getTextureBinding(const std::string &name) const + { + auto it = textureBindings.find(name); + if (it != textureBindings.end()) + { + return it->second; + } + // If we can't find a matching texture, assert out on Debug, and return an invalid value on + // release. + ASSERT(0); + return std::numeric_limits::max(); + } + size_t getUserUniformBufferBinding(const std::string &name) const + { + auto it = userUniformBufferBindings.find(name); + if (it != userUniformBufferBindings.end()) + { + return it->second; + } + // If we can't find a matching Uniform binding, assert out on Debug, and return an invalid + // value. + ASSERT(0); + return std::numeric_limits::max(); + } + UBOBindingInfo getUniformBufferBinding(const std::string &name) const + { + auto it = uniformBufferBindings.find(name); + if (it != uniformBufferBindings.end()) + { + return it->second; + } + // If we can't find a matching UBO binding by name, assert out on Debug, and return an + // invalid value. + ASSERT(0); + return {.bindIndex = std::numeric_limits::max(), + .arraySize = std::numeric_limits::max()}; + } + void reset() + { + hasUBOs = false; + hasFlatInput = false; + hasAtan = false; + hasInvariance = false; + originalNames.clear(); + samplerBindings.clear(); + textureBindings.clear(); + userUniformBufferBindings.clear(); + uniformBufferBindings.clear(); + } + + bool hasUBOs = false; + bool hasFlatInput = false; + bool hasAtan = false; + bool hasInvariance = false; + + private: + originalNamesMap originalNames; + samplerBindingMap samplerBindings; + textureBindingMap textureBindings; + userUniformBufferBindingMap userUniformBufferBindings; + uniformBufferBindingMap uniformBufferBindings; +}; + +class TranslatorMetalDirect : public TCompiler +{ + public: + TranslatorMetalDirect(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); + +#ifdef ANGLE_ENABLE_METAL + TranslatorMetalDirect *getAsTranslatorMetalDirect() override { return this; } +#endif + + TranslatorMetalReflection *getTranslatorMetalReflection() { return &translatorMetalReflection; } + + protected: + bool translate(TIntermBlock *root, + const ShCompileOptions &compileOptions, + PerformanceDiagnostics *perfDiagnostics) override; + + // The sample mask can't be in our fragment output struct if we read the framebuffer. Luckily, + // pixel local storage bans gl_SampleMask, so we can just not use it when PLS is active. + bool usesSampleMask() const { return !hasPixelLocalStorageUniforms(); } + + // Need to collect variables so that RemoveInactiveInterfaceVariables works. + bool shouldCollectVariables(const ShCompileOptions &compileOptions) override { return true; } + + [[nodiscard]] bool translateImpl(TInfoSinkBase &sink, + TIntermBlock *root, + const ShCompileOptions &compileOptions, + PerformanceDiagnostics *perfDiagnostics, + SpecConst *specConst, + DriverUniformMetal *driverUniforms); + + [[nodiscard]] bool shouldFlattenPragmaStdglInvariantAll() override; + + [[nodiscard]] bool transformDepthBeforeCorrection(TIntermBlock *root, + const DriverUniformMetal *driverUniforms); + + [[nodiscard]] bool appendVertexShaderDepthCorrectionToMain(TIntermBlock *root); + + [[nodiscard]] bool insertSampleMaskWritingLogic(TIntermBlock &root, + DriverUniformMetal &driverUniforms); + [[nodiscard]] bool insertRasterizationDiscardLogic(TIntermBlock &root); + + TranslatorMetalReflection translatorMetalReflection = {}; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TRANSLATORMETALDIRECT_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/TranslatorVulkan.h b/gfx/angle/checkout/src/compiler/translator/TranslatorVulkan.h new file mode 100644 index 0000000000..db80f499e8 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/TranslatorVulkan.h @@ -0,0 +1,60 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// TranslatorVulkan: +// A GLSL-based translator that outputs shaders that fit GL_KHR_vulkan_glsl and feeds them into +// glslang to spit out SPIR-V. +// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt +// + +#ifndef COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_ +#define COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_ + +#include "compiler/translator/Compiler.h" + +namespace sh +{ + +class TOutputVulkanGLSL; +class SpecConst; +class DriverUniform; + +class TranslatorVulkan : public TCompiler +{ + public: + TranslatorVulkan(sh::GLenum type, ShShaderSpec spec); + + protected: + [[nodiscard]] bool translate(TIntermBlock *root, + const ShCompileOptions &compileOptions, + PerformanceDiagnostics *perfDiagnostics) override; + bool shouldFlattenPragmaStdglInvariantAll() override; + + // Subclass can call this method to transform the AST before writing the final output. + // See TranslatorMetal.cpp. + [[nodiscard]] bool translateImpl(TInfoSinkBase &sink, + TIntermBlock *root, + const ShCompileOptions &compileOptions, + PerformanceDiagnostics *perfDiagnostics, + SpecConst *specConst, + DriverUniform *driverUniforms); + + void writeExtensionBehavior(const ShCompileOptions &compileOptions, TInfoSinkBase &sink); + + // Give subclass such as TranslatorMetal a chance to do depth transform before + // TranslatorVulkan apply its own transform. + [[nodiscard]] virtual bool transformDepthBeforeCorrection(TIntermBlock *root, + const DriverUniform *driverUniforms) + { + return true; + } + + // Generate SPIR-V out of intermediate GLSL through glslang. + [[nodiscard]] bool compileToSpirv(const TInfoSinkBase &glsl); +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/Types.cpp b/gfx/angle/checkout/src/compiler/translator/Types.cpp new file mode 100644 index 0000000000..c1d57fdaef --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Types.cpp @@ -0,0 +1,984 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#if defined(_MSC_VER) +# pragma warning(disable : 4718) +#endif + +#include "compiler/translator/Types.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/SymbolTable.h" + +#include +#include + +namespace sh +{ + +const char *getBasicString(TBasicType t) +{ + switch (t) + { + case EbtVoid: + return "void"; + case EbtFloat: + return "float"; + case EbtInt: + return "int"; + case EbtUInt: + return "uint"; + case EbtBool: + return "bool"; + case EbtYuvCscStandardEXT: + return "yuvCscStandardEXT"; + case EbtSampler2D: + return "sampler2D"; + case EbtSampler3D: + return "sampler3D"; + case EbtSamplerCube: + return "samplerCube"; + case EbtSamplerExternalOES: + return "samplerExternalOES"; + case EbtSamplerExternal2DY2YEXT: + return "__samplerExternal2DY2YEXT"; + case EbtSampler2DRect: + return "sampler2DRect"; + case EbtSampler2DArray: + return "sampler2DArray"; + case EbtSampler2DMS: + return "sampler2DMS"; + case EbtSampler2DMSArray: + return "sampler2DMSArray"; + case EbtSamplerCubeArray: + return "samplerCubeArray"; + case EbtSamplerBuffer: + return "samplerBuffer"; + case EbtISampler2D: + return "isampler2D"; + case EbtISampler3D: + return "isampler3D"; + case EbtISamplerCube: + return "isamplerCube"; + case EbtISampler2DArray: + return "isampler2DArray"; + case EbtISampler2DMS: + return "isampler2DMS"; + case EbtISampler2DMSArray: + return "isampler2DMSArray"; + case EbtISamplerCubeArray: + return "isamplerCubeArray"; + case EbtISamplerBuffer: + return "isamplerBuffer"; + case EbtUSampler2D: + return "usampler2D"; + case EbtUSampler3D: + return "usampler3D"; + case EbtUSamplerCube: + return "usamplerCube"; + case EbtUSampler2DArray: + return "usampler2DArray"; + case EbtUSampler2DMS: + return "usampler2DMS"; + case EbtUSampler2DMSArray: + return "usampler2DMSArray"; + case EbtUSamplerCubeArray: + return "usamplerCubeArray"; + case EbtUSamplerBuffer: + return "usamplerBuffer"; + case EbtSampler2DShadow: + return "sampler2DShadow"; + case EbtSamplerCubeShadow: + return "samplerCubeShadow"; + case EbtSampler2DArrayShadow: + return "sampler2DArrayShadow"; + case EbtSamplerCubeArrayShadow: + return "samplerCubeArrayShadow"; + case EbtStruct: + return "structure"; + case EbtInterfaceBlock: + return "interface block"; + case EbtImage2D: + return "image2D"; + case EbtIImage2D: + return "iimage2D"; + case EbtUImage2D: + return "uimage2D"; + case EbtImage3D: + return "image3D"; + case EbtIImage3D: + return "iimage3D"; + case EbtUImage3D: + return "uimage3D"; + case EbtImage2DArray: + return "image2DArray"; + case EbtIImage2DArray: + return "iimage2DArray"; + case EbtUImage2DArray: + return "uimage2DArray"; + case EbtImageCube: + return "imageCube"; + case EbtIImageCube: + return "iimageCube"; + case EbtUImageCube: + return "uimageCube"; + case EbtImageCubeArray: + return "imageCubeArray"; + case EbtIImageCubeArray: + return "iimageCubeArray"; + case EbtUImageCubeArray: + return "uimageCubeArray"; + case EbtImageBuffer: + return "imageBuffer"; + case EbtIImageBuffer: + return "iimageBuffer"; + case EbtUImageBuffer: + return "uimageBuffer"; + case EbtAtomicCounter: + return "atomic_uint"; + case EbtSamplerVideoWEBGL: + return "samplerVideoWEBGL"; + case EbtPixelLocalANGLE: + return "pixelLocalANGLE"; + case EbtIPixelLocalANGLE: + return "ipixelLocalANGLE"; + case EbtUPixelLocalANGLE: + return "upixelLocalANGLE"; + case EbtSubpassInput: + return "subpassInput"; + case EbtISubpassInput: + return "isubpassInput"; + case EbtUSubpassInput: + return "usubpassInput"; + case EbtSubpassInputMS: + return "subpassInputMS"; + case EbtISubpassInputMS: + return "isubpassInputMS"; + case EbtUSubpassInputMS: + return "usubpassInputMS"; + default: + UNREACHABLE(); + return "unknown type"; + } +} + +// TType implementation. +TType::TType() : TType(EbtVoid, 0, 0) {} + +TType::TType(TBasicType t, uint8_t ps, uint8_t ss) : TType(t, EbpUndefined, EvqGlobal, ps, ss) {} + +TType::TType(TBasicType t, TPrecision p, TQualifier q, uint8_t ps, uint8_t ss) + : TType(t, p, q, ps, ss, TSpan(), nullptr) +{} + +TType::TType(const TPublicType &p) + : type(p.getBasicType()), + precision(p.precision), + qualifier(p.qualifier), + invariant(p.invariant), + precise(p.precise), + memoryQualifier(p.memoryQualifier), + layoutQualifier(p.layoutQualifier), + primarySize(p.getPrimarySize()), + secondarySize(p.getSecondarySize()), + mArraySizesStorage(nullptr), + mInterfaceBlock(nullptr), + mStructure(nullptr), + mIsStructSpecifier(false), + mInterfaceBlockFieldIndex(0), + mMangledName(nullptr) +{ + ASSERT(primarySize <= 4); + ASSERT(secondarySize <= 4); + if (p.isArray()) + { + makeArrays(*p.arraySizes); + } + if (p.getUserDef()) + { + mStructure = p.getUserDef(); + mIsStructSpecifier = p.isStructSpecifier(); + } +} + +TType::TType(const TStructure *userDef, bool isStructSpecifier) + : TType(EbtStruct, EbpUndefined, EvqTemporary, 1, 1) +{ + mStructure = userDef; + mIsStructSpecifier = isStructSpecifier; +} + +TType::TType(const TInterfaceBlock *interfaceBlockIn, + TQualifier qualifierIn, + TLayoutQualifier layoutQualifierIn) + : TType(EbtInterfaceBlock, EbpUndefined, qualifierIn, 1, 1) +{ + layoutQualifier = layoutQualifierIn; + mInterfaceBlock = interfaceBlockIn; +} + +TType::TType(const TType &t) +{ + *this = t; +} + +TType &TType::operator=(const TType &t) +{ + type = t.type; + precision = t.precision; + qualifier = t.qualifier; + invariant = t.invariant; + precise = t.precise; + memoryQualifier = t.memoryQualifier; + layoutQualifier = t.layoutQualifier; + primarySize = t.primarySize; + secondarySize = t.secondarySize; + mArraySizesStorage = nullptr; + mInterfaceBlock = t.mInterfaceBlock; + mStructure = t.mStructure; + mIsStructSpecifier = t.mIsStructSpecifier; + mInterfaceBlockFieldIndex = t.mInterfaceBlockFieldIndex; + mMangledName = t.mMangledName; + + if (t.mArraySizesStorage) + { + // If other type has storage, duplicate the storage and set the view to our own storage. + mArraySizesStorage = new TVector(*t.mArraySizesStorage); + mArraySizes = *mArraySizesStorage; + } + else + { + // Otherwise reference the same (constexpr) array sizes as the other type. + mArraySizes = t.mArraySizes; + } + + return *this; +} + +bool TType::canBeConstructed() const +{ + switch (type) + { + case EbtFloat: + case EbtInt: + case EbtUInt: + case EbtBool: + case EbtStruct: + return true; + default: + return false; + } +} + +const char *TType::getBuiltInTypeNameString() const +{ + if (isMatrix()) + { + switch (getCols()) + { + case 2: + switch (getRows()) + { + case 2: + return "mat2"; + case 3: + return "mat2x3"; + case 4: + return "mat2x4"; + default: + UNREACHABLE(); + return nullptr; + } + case 3: + switch (getRows()) + { + case 2: + return "mat3x2"; + case 3: + return "mat3"; + case 4: + return "mat3x4"; + default: + UNREACHABLE(); + return nullptr; + } + case 4: + switch (getRows()) + { + case 2: + return "mat4x2"; + case 3: + return "mat4x3"; + case 4: + return "mat4"; + default: + UNREACHABLE(); + return nullptr; + } + default: + UNREACHABLE(); + return nullptr; + } + } + if (isVector()) + { + switch (getBasicType()) + { + case EbtFloat: + switch (getNominalSize()) + { + case 2: + return "vec2"; + case 3: + return "vec3"; + case 4: + return "vec4"; + default: + UNREACHABLE(); + return nullptr; + } + case EbtInt: + switch (getNominalSize()) + { + case 2: + return "ivec2"; + case 3: + return "ivec3"; + case 4: + return "ivec4"; + default: + UNREACHABLE(); + return nullptr; + } + case EbtBool: + switch (getNominalSize()) + { + case 2: + return "bvec2"; + case 3: + return "bvec3"; + case 4: + return "bvec4"; + default: + UNREACHABLE(); + return nullptr; + } + case EbtUInt: + switch (getNominalSize()) + { + case 2: + return "uvec2"; + case 3: + return "uvec3"; + case 4: + return "uvec4"; + default: + UNREACHABLE(); + return nullptr; + } + default: + UNREACHABLE(); + return nullptr; + } + } + ASSERT(getBasicType() != EbtStruct); + ASSERT(getBasicType() != EbtInterfaceBlock); + return getBasicString(); +} + +int TType::getDeepestStructNesting() const +{ + return mStructure ? mStructure->deepestNesting() : 0; +} + +bool TType::isNamelessStruct() const +{ + return mStructure && mStructure->symbolType() == SymbolType::Empty; +} + +bool TType::isStructureContainingArrays() const +{ + return mStructure ? mStructure->containsArrays() : false; +} + +bool TType::isStructureContainingMatrices() const +{ + return mStructure ? mStructure->containsMatrices() : false; +} + +bool TType::isStructureContainingType(TBasicType t) const +{ + return mStructure ? mStructure->containsType(t) : false; +} + +bool TType::isStructureContainingSamplers() const +{ + return mStructure ? mStructure->containsSamplers() : false; +} + +bool TType::isInterfaceBlockContainingType(TBasicType t) const +{ + return isInterfaceBlock() ? mInterfaceBlock->containsType(t) : false; +} + +bool TType::canReplaceWithConstantUnion() const +{ + if (isArray()) + { + return false; + } + if (!mStructure) + { + return true; + } + if (isStructureContainingArrays()) + { + return false; + } + if (getObjectSize() > 16) + { + return false; + } + return true; +} + +// +// Recursively generate mangled names. +// +const char *TType::buildMangledName() const +{ + TString mangledName(1, GetSizeMangledName(primarySize, secondarySize)); + + TBasicMangledName typeName(type); + char *basicMangledName = typeName.getName(); + static_assert(TBasicMangledName::mangledNameSize == 2, "Mangled name size is not 2"); + if (basicMangledName[0] != '{') + { + mangledName += basicMangledName[0]; + mangledName += basicMangledName[1]; + } + else + { + ASSERT(type == EbtStruct || type == EbtInterfaceBlock); + switch (type) + { + case EbtStruct: + mangledName += "{s"; + if (mStructure->symbolType() != SymbolType::Empty) + { + mangledName += mStructure->name().data(); + } + mangledName += mStructure->mangledFieldList(); + mangledName += '}'; + break; + case EbtInterfaceBlock: + mangledName += "{i"; + mangledName += mInterfaceBlock->name().data(); + mangledName += mInterfaceBlock->mangledFieldList(); + mangledName += '}'; + break; + default: + UNREACHABLE(); + break; + } + } + + for (unsigned int arraySize : mArraySizes) + { + char buf[20]; + snprintf(buf, sizeof(buf), "%d", arraySize); + mangledName += 'x'; + mangledName += buf; + } + + // Copy string contents into a pool-allocated buffer, so we never need to call delete. + return AllocatePoolCharArray(mangledName.c_str(), mangledName.size()); +} + +size_t TType::getObjectSize() const +{ + size_t totalSize; + + if (getBasicType() == EbtStruct) + totalSize = mStructure->objectSize(); + else + totalSize = primarySize * secondarySize; + + if (totalSize == 0) + return 0; + + for (size_t arraySize : mArraySizes) + { + if (arraySize > INT_MAX / totalSize) + totalSize = INT_MAX; + else + totalSize *= arraySize; + } + + return totalSize; +} + +int TType::getLocationCount() const +{ + int count = 1; + + if (getBasicType() == EbtStruct) + { + count = mStructure->getLocationCount(); + } + + if (count == 0) + { + return 0; + } + + for (unsigned int arraySize : mArraySizes) + { + if (arraySize > static_cast(std::numeric_limits::max() / count)) + { + count = std::numeric_limits::max(); + } + else + { + count *= static_cast(arraySize); + } + } + + return count; +} + +unsigned int TType::getArraySizeProduct() const +{ + unsigned int product = 1u; + + for (unsigned int arraySize : mArraySizes) + { + product *= arraySize; + } + return product; +} + +bool TType::isUnsizedArray() const +{ + for (unsigned int arraySize : mArraySizes) + { + if (arraySize == 0u) + { + return true; + } + } + return false; +} + +bool TType::sameNonArrayType(const TType &right) const +{ + return (type == right.type && primarySize == right.primarySize && + secondarySize == right.secondarySize && mStructure == right.mStructure); +} + +bool TType::isElementTypeOf(const TType &arrayType) const +{ + if (!sameNonArrayType(arrayType)) + { + return false; + } + if (arrayType.getNumArraySizes() != getNumArraySizes() + 1u) + { + return false; + } + for (size_t i = 0; i < mArraySizes.size(); ++i) + { + if (mArraySizes[i] != arrayType.mArraySizes[i]) + { + return false; + } + } + return true; +} + +void TType::sizeUnsizedArrays(const TSpan &newArraySizes) +{ + ASSERT(!isArray() || mArraySizesStorage != nullptr); + for (size_t i = 0u; i < getNumArraySizes(); ++i) + { + if (mArraySizes[i] == 0) + { + if (i < newArraySizes.size()) + { + (*mArraySizesStorage)[i] = newArraySizes[i]; + } + else + { + (*mArraySizesStorage)[i] = 1u; + } + } + } + invalidateMangledName(); +} + +void TType::sizeOutermostUnsizedArray(unsigned int arraySize) +{ + ASSERT(isArray() && mArraySizesStorage != nullptr); + ASSERT((*mArraySizesStorage).back() == 0u); + (*mArraySizesStorage).back() = arraySize; +} + +void TType::setBasicType(TBasicType t) +{ + if (type != t) + { + type = t; + invalidateMangledName(); + } +} + +void TType::setPrimarySize(uint8_t ps) +{ + if (primarySize != ps) + { + ASSERT(ps <= 4); + primarySize = ps; + invalidateMangledName(); + } +} + +void TType::setSecondarySize(uint8_t ss) +{ + if (secondarySize != ss) + { + ASSERT(ss <= 4); + secondarySize = ss; + invalidateMangledName(); + } +} + +void TType::makeArray(unsigned int s) +{ + if (mArraySizesStorage == nullptr) + { + mArraySizesStorage = new TVector(); + } + // Add a dimension to the current ones. + mArraySizesStorage->push_back(s); + onArrayDimensionsChange(*mArraySizesStorage); +} + +void TType::makeArrays(const TSpan &sizes) +{ + if (mArraySizesStorage == nullptr) + { + mArraySizesStorage = new TVector(); + } + // Add dimensions to the current ones. + mArraySizesStorage->insert(mArraySizesStorage->end(), sizes.begin(), sizes.end()); + onArrayDimensionsChange(*mArraySizesStorage); +} + +void TType::setArraySize(size_t arrayDimension, unsigned int s) +{ + ASSERT(isArray() && mArraySizesStorage != nullptr); + ASSERT(arrayDimension < mArraySizesStorage->size()); + if (mArraySizes[arrayDimension] != s) + { + (*mArraySizesStorage)[arrayDimension] = s; + invalidateMangledName(); + } +} + +void TType::toArrayElementType() +{ + ASSERT(isArray() && mArraySizesStorage != nullptr); + mArraySizesStorage->pop_back(); + onArrayDimensionsChange(*mArraySizesStorage); +} + +void TType::toArrayBaseType() +{ + if (!isArray()) + { + return; + } + if (mArraySizesStorage) + { + mArraySizesStorage->clear(); + } + onArrayDimensionsChange(TSpan()); +} + +void TType::toMatrixColumnType() +{ + ASSERT(isMatrix()); + primarySize = secondarySize; + secondarySize = 1; + invalidateMangledName(); +} + +void TType::toComponentType() +{ + primarySize = 1; + secondarySize = 1; + invalidateMangledName(); +} + +void TType::setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn) +{ + if (mInterfaceBlock != interfaceBlockIn) + { + mInterfaceBlock = interfaceBlockIn; + invalidateMangledName(); + } +} + +void TType::setInterfaceBlockField(const TInterfaceBlock *interfaceBlockIn, size_t fieldIndex) +{ + setInterfaceBlock(interfaceBlockIn); + mInterfaceBlockFieldIndex = fieldIndex; +} + +const char *TType::getMangledName() const +{ + if (mMangledName == nullptr) + { + mMangledName = buildMangledName(); + } + + return mMangledName; +} + +void TType::realize() +{ + getMangledName(); +} + +void TType::createSamplerSymbols(const ImmutableString &namePrefix, + const TString &apiNamePrefix, + TVector *outputSymbols, + TMap *outputSymbolsToAPINames, + TSymbolTable *symbolTable) const +{ + if (isStructureContainingSamplers()) + { + if (isArray()) + { + TType elementType(*this); + elementType.toArrayElementType(); + for (unsigned int arrayIndex = 0u; arrayIndex < getOutermostArraySize(); ++arrayIndex) + { + std::stringstream elementName = sh::InitializeStream(); + elementName << namePrefix << "_" << arrayIndex; + TStringStream elementApiName; + elementApiName << apiNamePrefix << "[" << arrayIndex << "]"; + elementType.createSamplerSymbols(ImmutableString(elementName.str()), + elementApiName.str(), outputSymbols, + outputSymbolsToAPINames, symbolTable); + } + } + else + { + mStructure->createSamplerSymbols(namePrefix.data(), apiNamePrefix, outputSymbols, + outputSymbolsToAPINames, symbolTable); + } + return; + } + + ASSERT(IsSampler(type)); + TVariable *variable = + new TVariable(symbolTable, namePrefix, new TType(*this), SymbolType::AngleInternal); + outputSymbols->push_back(variable); + if (outputSymbolsToAPINames) + { + (*outputSymbolsToAPINames)[variable] = apiNamePrefix; + } +} + +TFieldListCollection::TFieldListCollection(const TFieldList *fields) + : mFields(fields), mObjectSize(0), mDeepestNesting(0) +{} + +bool TFieldListCollection::containsArrays() const +{ + for (const auto *field : *mFields) + { + const TType *fieldType = field->type(); + if (fieldType->isArray() || fieldType->isStructureContainingArrays()) + return true; + } + return false; +} + +bool TFieldListCollection::containsMatrices() const +{ + for (const auto *field : *mFields) + { + const TType *fieldType = field->type(); + if (fieldType->isMatrix() || fieldType->isStructureContainingMatrices()) + return true; + } + return false; +} + +bool TFieldListCollection::containsType(TBasicType type) const +{ + for (const auto *field : *mFields) + { + const TType *fieldType = field->type(); + if (fieldType->getBasicType() == type || fieldType->isStructureContainingType(type)) + return true; + } + return false; +} + +bool TFieldListCollection::containsSamplers() const +{ + for (const auto *field : *mFields) + { + const TType *fieldType = field->type(); + if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers()) + return true; + } + return false; +} + +TString TFieldListCollection::buildMangledFieldList() const +{ + TString mangledName; + for (const auto *field : *mFields) + { + mangledName += field->type()->getMangledName(); + } + return mangledName; +} + +size_t TFieldListCollection::calculateObjectSize() const +{ + size_t size = 0; + for (const TField *field : *mFields) + { + size_t fieldSize = field->type()->getObjectSize(); + if (fieldSize > INT_MAX - size) + size = INT_MAX; + else + size += fieldSize; + } + return size; +} + +size_t TFieldListCollection::objectSize() const +{ + if (mObjectSize == 0) + mObjectSize = calculateObjectSize(); + return mObjectSize; +} + +int TFieldListCollection::getLocationCount() const +{ + int count = 0; + for (const TField *field : *mFields) + { + int fieldCount = field->type()->getLocationCount(); + if (fieldCount > std::numeric_limits::max() - count) + { + count = std::numeric_limits::max(); + } + else + { + count += fieldCount; + } + } + return count; +} + +int TFieldListCollection::deepestNesting() const +{ + if (mDeepestNesting == 0) + mDeepestNesting = calculateDeepestNesting(); + return mDeepestNesting; +} + +const TString &TFieldListCollection::mangledFieldList() const +{ + if (mMangledFieldList.empty()) + mMangledFieldList = buildMangledFieldList(); + return mMangledFieldList; +} + +int TFieldListCollection::calculateDeepestNesting() const +{ + int maxNesting = 0; + for (size_t i = 0; i < mFields->size(); ++i) + maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting()); + return 1 + maxNesting; +} + +// TPublicType implementation. +void TPublicType::initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q) +{ + typeSpecifierNonArray = typeSpecifier; + layoutQualifier = TLayoutQualifier::Create(); + memoryQualifier = TMemoryQualifier::Create(); + qualifier = q; + invariant = false; + precise = false; + precision = EbpUndefined; + arraySizes = nullptr; +} + +void TPublicType::initializeBasicType(TBasicType basicType) +{ + typeSpecifierNonArray.type = basicType; + typeSpecifierNonArray.primarySize = 1; + typeSpecifierNonArray.secondarySize = 1; + layoutQualifier = TLayoutQualifier::Create(); + memoryQualifier = TMemoryQualifier::Create(); + qualifier = EvqTemporary; + invariant = false; + precise = false; + precision = EbpUndefined; + arraySizes = nullptr; +} + +bool TPublicType::isStructureContainingArrays() const +{ + if (!typeSpecifierNonArray.userDef) + { + return false; + } + + return typeSpecifierNonArray.userDef->containsArrays(); +} + +bool TPublicType::isStructureContainingType(TBasicType t) const +{ + if (!typeSpecifierNonArray.userDef) + { + return false; + } + + return typeSpecifierNonArray.userDef->containsType(t); +} + +void TPublicType::setArraySizes(TVector *sizes) +{ + arraySizes = sizes; +} + +bool TPublicType::isArray() const +{ + return arraySizes && !arraySizes->empty(); +} + +void TPublicType::clearArrayness() +{ + arraySizes = nullptr; +} + +bool TPublicType::isAggregate() const +{ + return isArray() || typeSpecifierNonArray.isMatrix() || typeSpecifierNonArray.isVector(); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/Types.h b/gfx/angle/checkout/src/compiler/translator/Types.h new file mode 100644 index 0000000000..623a3b335b --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/Types.h @@ -0,0 +1,508 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TYPES_H_ +#define COMPILER_TRANSLATOR_TYPES_H_ + +#include "common/angleutils.h" +#include "common/debug.h" + +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/Common.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/SymbolUniqueId.h" + +namespace sh +{ + +struct TPublicType; +class TType; +class TInterfaceBlock; +class TStructure; +class TSymbol; +class TVariable; +class TIntermSymbol; +class TSymbolTable; + +class TField : angle::NonCopyable +{ + public: + POOL_ALLOCATOR_NEW_DELETE + TField(TType *type, const ImmutableString &name, const TSourceLoc &line, SymbolType symbolType) + : mType(type), mName(name), mLine(line), mSymbolType(symbolType) + { + ASSERT(mSymbolType != SymbolType::Empty); + } + + // TODO(alokp): We should only return const type. + // Fix it by tweaking grammar. + TType *type() { return mType; } + const TType *type() const { return mType; } + const ImmutableString &name() const { return mName; } + const TSourceLoc &line() const { return mLine; } + SymbolType symbolType() const { return mSymbolType; } + + private: + TType *mType; + const ImmutableString mName; + const TSourceLoc mLine; + const SymbolType mSymbolType; +}; + +typedef TVector TFieldList; + +class TFieldListCollection : angle::NonCopyable +{ + public: + const TFieldList &fields() const { return *mFields; } + + bool containsArrays() const; + bool containsMatrices() const; + bool containsType(TBasicType t) const; + bool containsSamplers() const; + + size_t objectSize() const; + // How many locations the field list consumes as a uniform. + int getLocationCount() const; + int deepestNesting() const; + const TString &mangledFieldList() const; + + protected: + TFieldListCollection(const TFieldList *fields); + + const TFieldList *mFields; + + private: + size_t calculateObjectSize() const; + int calculateDeepestNesting() const; + TString buildMangledFieldList() const; + + mutable size_t mObjectSize; + mutable int mDeepestNesting; + mutable TString mMangledFieldList; +}; + +// +// Base class for things that have a type. +// +class TType +{ + public: + POOL_ALLOCATOR_NEW_DELETE + TType(); + explicit TType(TBasicType t, uint8_t ps = 1, uint8_t ss = 1); + TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, uint8_t ps = 1, uint8_t ss = 1); + explicit TType(const TPublicType &p); + TType(const TStructure *userDef, bool isStructSpecifier); + TType(const TInterfaceBlock *interfaceBlockIn, + TQualifier qualifierIn, + TLayoutQualifier layoutQualifierIn); + TType(const TType &t); + TType &operator=(const TType &t); + + constexpr TType(TBasicType t, + TPrecision p, + TQualifier q, + uint8_t ps, + uint8_t ss, + const TSpan arraySizes, + const char *mangledName) + : type(t), + precision(p), + qualifier(q), + invariant(false), + precise(false), + memoryQualifier(TMemoryQualifier::Create()), + layoutQualifier(TLayoutQualifier::Create()), + primarySize(ps), + secondarySize(ss), + mArraySizes(arraySizes), + mArraySizesStorage(nullptr), + mInterfaceBlock(nullptr), + mStructure(nullptr), + mIsStructSpecifier(false), + mInterfaceBlockFieldIndex(0), + mMangledName(mangledName) + {} + + constexpr TType(TType &&t) + : type(t.type), + precision(t.precision), + qualifier(t.qualifier), + invariant(t.invariant), + precise(t.precise), + memoryQualifier(t.memoryQualifier), + layoutQualifier(t.layoutQualifier), + primarySize(t.primarySize), + secondarySize(t.secondarySize), + mArraySizes(t.mArraySizes), + mArraySizesStorage(t.mArraySizesStorage), + mInterfaceBlock(t.mInterfaceBlock), + mStructure(t.mStructure), + mIsStructSpecifier(t.mIsStructSpecifier), + mInterfaceBlockFieldIndex(0), + mMangledName(t.mMangledName) + { + t.mArraySizesStorage = nullptr; + } + + constexpr TBasicType getBasicType() const { return type; } + void setBasicType(TBasicType t); + + TPrecision getPrecision() const { return precision; } + void setPrecision(TPrecision p) { precision = p; } + + constexpr TQualifier getQualifier() const { return qualifier; } + void setQualifier(TQualifier q) { qualifier = q; } + + bool isInvariant() const { return invariant; } + void setInvariant(bool i) { invariant = i; } + + bool isPrecise() const { return precise; } + void setPrecise(bool i) { precise = i; } + + TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; } + void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; } + + TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; } + void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; } + + uint8_t getNominalSize() const { return primarySize; } + uint8_t getSecondarySize() const { return secondarySize; } + uint8_t getCols() const + { + ASSERT(isMatrix()); + return primarySize; + } + uint8_t getRows() const + { + ASSERT(isMatrix()); + return secondarySize; + } + void setPrimarySize(uint8_t ps); + void setSecondarySize(uint8_t ss); + + // Full size of single instance of type + size_t getObjectSize() const; + + // Get how many locations this type consumes as a uniform. + int getLocationCount() const; + + bool isMatrix() const { return primarySize > 1 && secondarySize > 1; } + bool isNonSquareMatrix() const { return isMatrix() && primarySize != secondarySize; } + bool isArray() const { return !mArraySizes.empty(); } + bool isArrayOfArrays() const { return mArraySizes.size() > 1u; } + size_t getNumArraySizes() const { return mArraySizes.size(); } + const TSpan &getArraySizes() const { return mArraySizes; } + unsigned int getArraySizeProduct() const; + bool isUnsizedArray() const; + unsigned int getOutermostArraySize() const + { + ASSERT(isArray()); + return mArraySizes.back(); + } + void makeArray(unsigned int s); + + // sizes contain new outermost array sizes. + void makeArrays(const TSpan &sizes); + // Here, the array dimension value 0 corresponds to the innermost array. + void setArraySize(size_t arrayDimension, unsigned int s); + + // Will set unsized array sizes according to newArraySizes. In case there are more + // unsized arrays than there are sizes in newArraySizes, defaults to setting any + // remaining array sizes to 1. + void sizeUnsizedArrays(const TSpan &newArraySizes); + + // Will size the outermost array according to arraySize. + void sizeOutermostUnsizedArray(unsigned int arraySize); + + // Note that the array element type might still be an array type in GLSL ES version >= 3.10. + void toArrayElementType(); + // Removes all array sizes. + void toArrayBaseType(); + // Turns a matrix into a column of it. + void toMatrixColumnType(); + // Turns a matrix or vector into a component of it. + void toComponentType(); + + const TInterfaceBlock *getInterfaceBlock() const { return mInterfaceBlock; } + void setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn); + bool isInterfaceBlock() const { return type == EbtInterfaceBlock; } + + void setInterfaceBlockField(const TInterfaceBlock *interfaceBlockIn, size_t fieldIndex); + size_t getInterfaceBlockFieldIndex() const { return mInterfaceBlockFieldIndex; } + + bool isVector() const { return primarySize > 1 && secondarySize == 1; } + bool isVectorArray() const { return primarySize > 1 && secondarySize == 1 && isArray(); } + bool isRank0() const { return primarySize == 1 && secondarySize == 1; } + bool isScalar() const + { + return primarySize == 1 && secondarySize == 1 && !mStructure && !isArray(); + } + bool isScalarArray() const + { + return primarySize == 1 && secondarySize == 1 && !mStructure && isArray(); + } + bool isScalarFloat() const { return isScalar() && type == EbtFloat; } + bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); } + + bool canBeConstructed() const; + + const TStructure *getStruct() const { return mStructure; } + + static constexpr char GetSizeMangledName(uint8_t primarySize, uint8_t secondarySize) + { + unsigned int sizeKey = (secondarySize - 1u) * 4u + primarySize - 1u; + if (sizeKey < 10u) + { + return static_cast('0' + sizeKey); + } + return static_cast('A' + sizeKey - 10); + } + const char *getMangledName() const; + + bool sameNonArrayType(const TType &right) const; + + // Returns true if arrayType is an array made of this type. + bool isElementTypeOf(const TType &arrayType) const; + + bool operator==(const TType &right) const + { + size_t numArraySizesL = getNumArraySizes(); + size_t numArraySizesR = right.getNumArraySizes(); + bool arraySizesEqual = numArraySizesL == numArraySizesR && + (numArraySizesL == 0 || mArraySizes == right.mArraySizes); + return type == right.type && primarySize == right.primarySize && + secondarySize == right.secondarySize && arraySizesEqual && + mStructure == right.mStructure; + // don't check the qualifier, it's not ever what's being sought after + } + bool operator!=(const TType &right) const { return !operator==(right); } + bool operator<(const TType &right) const + { + if (type != right.type) + return type < right.type; + if (primarySize != right.primarySize) + return primarySize < right.primarySize; + if (secondarySize != right.secondarySize) + return secondarySize < right.secondarySize; + size_t numArraySizesL = getNumArraySizes(); + size_t numArraySizesR = right.getNumArraySizes(); + if (numArraySizesL != numArraySizesR) + return numArraySizesL < numArraySizesR; + for (size_t i = 0; i < numArraySizesL; ++i) + { + if (mArraySizes[i] != right.mArraySizes[i]) + return mArraySizes[i] < right.mArraySizes[i]; + } + if (mStructure != right.mStructure) + return mStructure < right.mStructure; + + return false; + } + + const char *getBasicString() const { return sh::getBasicString(type); } + + const char *getPrecisionString() const { return sh::getPrecisionString(precision); } + const char *getQualifierString() const { return sh::getQualifierString(qualifier); } + + const char *getBuiltInTypeNameString() const; + + // If this type is a struct, returns the deepest struct nesting of + // any field in the struct. For example: + // struct nesting1 { + // vec4 position; + // }; + // struct nesting2 { + // nesting1 field1; + // vec4 field2; + // }; + // For type "nesting2", this method would return 2 -- the number + // of structures through which indirection must occur to reach the + // deepest field (nesting2.field1.position). + int getDeepestStructNesting() const; + + bool isNamelessStruct() const; + + bool isStructureContainingArrays() const; + bool isStructureContainingMatrices() const; + bool isStructureContainingType(TBasicType t) const; + bool isStructureContainingSamplers() const; + bool isInterfaceBlockContainingType(TBasicType t) const; + + bool isStructSpecifier() const { return mIsStructSpecifier; } + + // Return true if variables of this type should be replaced with an inline constant value if + // such is available. False will be returned in cases where output doesn't support + // TIntermConstantUnion nodes of the type, or if the type contains a lot of fields and creating + // several copies of it in the output code is undesirable for performance. + bool canReplaceWithConstantUnion() const; + + // The char arrays passed in must be pool allocated or static. + void createSamplerSymbols(const ImmutableString &namePrefix, + const TString &apiNamePrefix, + TVector *outputSymbols, + TMap *outputSymbolsToAPINames, + TSymbolTable *symbolTable) const; + + // Initializes all lazily-initialized members. + void realize(); + + bool isSampler() const { return IsSampler(type); } + bool isSamplerCube() const { return type == EbtSamplerCube; } + bool isAtomicCounter() const { return IsAtomicCounter(type); } + bool isSamplerVideoWEBGL() const { return type == EbtSamplerVideoWEBGL; } + bool isImage() const { return IsImage(type); } + bool isPixelLocal() const { return IsPixelLocal(type); } + + private: + constexpr void invalidateMangledName() { mMangledName = nullptr; } + const char *buildMangledName() const; + constexpr void onArrayDimensionsChange(const TSpan &sizes) + { + mArraySizes = sizes; + invalidateMangledName(); + } + + TBasicType type; + TPrecision precision; + TQualifier qualifier; + bool invariant; + bool precise; + + TMemoryQualifier memoryQualifier; + TLayoutQualifier layoutQualifier; + uint8_t primarySize; // size of vector or cols matrix + uint8_t secondarySize; // rows of a matrix + + // Used to make an array type. Outermost array size is stored at the end of the vector. Having 0 + // in this vector means an unsized array. + TSpan mArraySizes; + // Storage for mArraySizes, if any. This is usually the case, except for constexpr TTypes which + // only have a valid mArraySizes (with mArraySizesStorage being nullptr). Therefore, all + // modifications to array sizes happen on the storage (and if dimensions change, mArraySizes is + // also updated) and all reads are from mArraySizes. + TVector *mArraySizesStorage; + + // This is set only in the following two cases: + // 1) Represents an interface block. + // 2) Represents the member variable of an unnamed interface block. + // It's nullptr also for members of named interface blocks. + const TInterfaceBlock *mInterfaceBlock; + + // nullptr unless this is a struct + const TStructure *mStructure; + bool mIsStructSpecifier; + + // If this is a field of a nameless interface block, this would indicate which member it's + // refering to. + size_t mInterfaceBlockFieldIndex; + + mutable const char *mMangledName; +}; + +// TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the +// grammar +struct TTypeSpecifierNonArray +{ + TBasicType type; + uint8_t primarySize; // size of vector or cols of matrix + uint8_t secondarySize; // rows of matrix + const TStructure *userDef; + TSourceLoc line; + + // true if the type was defined by a struct specifier rather than a reference to a type name. + bool isStructSpecifier; + + void initialize(TBasicType aType, const TSourceLoc &aLine) + { + ASSERT(aType != EbtStruct); + type = aType; + primarySize = 1; + secondarySize = 1; + userDef = nullptr; + line = aLine; + isStructSpecifier = false; + } + + void initializeStruct(const TStructure *aUserDef, + bool aIsStructSpecifier, + const TSourceLoc &aLine) + { + type = EbtStruct; + primarySize = 1; + secondarySize = 1; + userDef = aUserDef; + line = aLine; + isStructSpecifier = aIsStructSpecifier; + } + + void setAggregate(uint8_t size) { primarySize = size; } + + void setMatrix(uint8_t columns, uint8_t rows) + { + ASSERT(columns > 1 && rows > 1 && columns <= 4 && rows <= 4); + primarySize = columns; + secondarySize = rows; + } + + bool isMatrix() const { return primarySize > 1 && secondarySize > 1; } + + bool isVector() const { return primarySize > 1 && secondarySize == 1; } +}; + +// +// This is a workaround for a problem with the yacc stack, It can't have +// types that it thinks have non-trivial constructors. It should +// just be used while recognizing the grammar, not anything else. Pointers +// could be used, but also trying to avoid lots of memory management overhead. +// +// Not as bad as it looks, there is no actual assumption that the fields +// match up or are name the same or anything like that. +// +struct TPublicType +{ + // Must have a trivial default constructor since it is used in YYSTYPE. + TPublicType() = default; + + void initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q); + void initializeBasicType(TBasicType basicType); + + TBasicType getBasicType() const { return typeSpecifierNonArray.type; } + void setBasicType(TBasicType basicType) { typeSpecifierNonArray.type = basicType; } + + uint8_t getPrimarySize() const { return typeSpecifierNonArray.primarySize; } + uint8_t getSecondarySize() const { return typeSpecifierNonArray.secondarySize; } + + const TStructure *getUserDef() const { return typeSpecifierNonArray.userDef; } + const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; } + + bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; } + + bool isStructureContainingArrays() const; + bool isStructureContainingType(TBasicType t) const; + void setArraySizes(TVector *sizes); + bool isArray() const; + void clearArrayness(); + bool isAggregate() const; + + TTypeSpecifierNonArray typeSpecifierNonArray; + TLayoutQualifier layoutQualifier; + TMemoryQualifier memoryQualifier; + TQualifier qualifier; + bool invariant; + bool precise; + TPrecision precision; + + // Either nullptr or empty in case the type is not an array. The last element is the outermost + // array size. Note that due to bison restrictions, copies of the public type created by the + // copy constructor share the same arraySizes pointer. + const TVector *arraySizes; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TYPES_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/UtilsHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/UtilsHLSL.cpp new file mode 100644 index 0000000000..5d9a573d7b --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/UtilsHLSL.cpp @@ -0,0 +1,1223 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// UtilsHLSL.cpp: +// Utility methods for GLSL to HLSL translation. +// + +#include "compiler/translator/UtilsHLSL.h" + +#include "common/utilities.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/StructureHLSL.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +// Parameter types are only added to function names if they are ambiguous according to the +// native HLSL compiler. Other parameter types are not added to function names to avoid +// making function names longer. +bool FunctionParameterNeedsDisambiguation(const TType ¶mType) +{ + if (paramType.getObjectSize() == 4 && paramType.getBasicType() == EbtFloat) + { + // Disambiguation is needed for float2x2 and float4 parameters. These are the only + // built-in types that HLSL thinks are identical. float2x3 and float3x2 are different + // types, for example. + return true; + } + + if (paramType.getBasicType() == EbtUInt || paramType.getBasicType() == EbtInt) + { + // The HLSL compiler can't always tell the difference between int and uint types when an + // expression is passed as a function parameter + return true; + } + + if (paramType.getBasicType() == EbtStruct) + { + // Disambiguation is needed for struct parameters, since HLSL thinks that structs with + // the same fields but a different name are identical. + ASSERT(paramType.getStruct()->symbolType() != SymbolType::Empty); + return true; + } + + return false; +} + +void DisambiguateFunctionNameForParameterType(const TType ¶mType, + TString *disambiguatingStringOut) +{ + if (FunctionParameterNeedsDisambiguation(paramType)) + { + *disambiguatingStringOut += "_" + TypeString(paramType); + } +} + +} // anonymous namespace + +const char *SamplerString(const TBasicType type) +{ + if (IsShadowSampler(type)) + { + return "SamplerComparisonState"; + } + else + { + return "SamplerState"; + } +} + +const char *SamplerString(HLSLTextureGroup type) +{ + if (type >= HLSL_COMPARISON_SAMPLER_GROUP_BEGIN && type <= HLSL_COMPARISON_SAMPLER_GROUP_END) + { + return "SamplerComparisonState"; + } + else + { + return "SamplerState"; + } +} + +HLSLTextureGroup TextureGroup(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) + +{ + switch (type) + { + case EbtSampler2D: + case EbtSamplerVideoWEBGL: + return HLSL_TEXTURE_2D; + case EbtSamplerCube: + return HLSL_TEXTURE_CUBE; + case EbtSamplerExternalOES: + return HLSL_TEXTURE_2D; + case EbtSampler2DArray: + return HLSL_TEXTURE_2D_ARRAY; + case EbtSampler3D: + return HLSL_TEXTURE_3D; + case EbtSampler2DMS: + return HLSL_TEXTURE_2D_MS; + case EbtSampler2DMSArray: + return HLSL_TEXTURE_2D_MS_ARRAY; + case EbtSamplerBuffer: + return HLSL_TEXTURE_BUFFER; + case EbtISampler2D: + return HLSL_TEXTURE_2D_INT4; + case EbtISamplerBuffer: + return HLSL_TEXTURE_BUFFER_INT4; + case EbtISampler3D: + return HLSL_TEXTURE_3D_INT4; + case EbtISamplerCube: + return HLSL_TEXTURE_2D_ARRAY_INT4; + case EbtISampler2DArray: + return HLSL_TEXTURE_2D_ARRAY_INT4; + case EbtISampler2DMS: + return HLSL_TEXTURE_2D_MS_INT4; + case EbtISampler2DMSArray: + return HLSL_TEXTURE_2D_MS_ARRAY_INT4; + case EbtUSampler2D: + return HLSL_TEXTURE_2D_UINT4; + case EbtUSampler3D: + return HLSL_TEXTURE_3D_UINT4; + case EbtUSamplerCube: + return HLSL_TEXTURE_2D_ARRAY_UINT4; + case EbtUSamplerBuffer: + return HLSL_TEXTURE_BUFFER_UINT4; + case EbtUSampler2DArray: + return HLSL_TEXTURE_2D_ARRAY_UINT4; + case EbtUSampler2DMS: + return HLSL_TEXTURE_2D_MS_UINT4; + case EbtUSampler2DMSArray: + return HLSL_TEXTURE_2D_MS_ARRAY_UINT4; + case EbtSampler2DShadow: + return HLSL_TEXTURE_2D_COMPARISON; + case EbtSamplerCubeShadow: + return HLSL_TEXTURE_CUBE_COMPARISON; + case EbtSampler2DArrayShadow: + return HLSL_TEXTURE_2D_ARRAY_COMPARISON; + case EbtImage2D: + { + switch (imageInternalFormat) + { + case EiifRGBA32F: + case EiifRGBA16F: + case EiifR32F: + return HLSL_TEXTURE_2D; + case EiifRGBA8: + return HLSL_TEXTURE_2D_UNORM; + case EiifRGBA8_SNORM: + return HLSL_TEXTURE_2D_SNORM; + default: + UNREACHABLE(); + return HLSL_TEXTURE_UNKNOWN; + } + } + case EbtIImage2D: + { + switch (imageInternalFormat) + { + case EiifRGBA32I: + case EiifRGBA16I: + case EiifRGBA8I: + case EiifR32I: + return HLSL_TEXTURE_2D_INT4; + default: + UNREACHABLE(); + return HLSL_TEXTURE_UNKNOWN; + } + } + case EbtUImage2D: + { + switch (imageInternalFormat) + { + + case EiifRGBA32UI: + case EiifRGBA16UI: + case EiifRGBA8UI: + case EiifR32UI: + return HLSL_TEXTURE_2D_UINT4; + default: + UNREACHABLE(); + return HLSL_TEXTURE_UNKNOWN; + } + } + case EbtImage3D: + { + switch (imageInternalFormat) + { + case EiifRGBA32F: + case EiifRGBA16F: + case EiifR32F: + return HLSL_TEXTURE_3D; + case EiifRGBA8: + return HLSL_TEXTURE_3D_UNORM; + case EiifRGBA8_SNORM: + return HLSL_TEXTURE_3D_SNORM; + default: + UNREACHABLE(); + return HLSL_TEXTURE_UNKNOWN; + } + } + case EbtIImage3D: + { + switch (imageInternalFormat) + { + case EiifRGBA32I: + case EiifRGBA16I: + case EiifRGBA8I: + case EiifR32I: + return HLSL_TEXTURE_3D_INT4; + default: + UNREACHABLE(); + return HLSL_TEXTURE_UNKNOWN; + } + } + case EbtUImage3D: + { + switch (imageInternalFormat) + { + case EiifRGBA32UI: + case EiifRGBA16UI: + case EiifRGBA8UI: + case EiifR32UI: + return HLSL_TEXTURE_3D_UINT4; + default: + UNREACHABLE(); + return HLSL_TEXTURE_UNKNOWN; + } + } + case EbtImage2DArray: + case EbtImageCube: + { + switch (imageInternalFormat) + { + case EiifRGBA32F: + case EiifRGBA16F: + case EiifR32F: + return HLSL_TEXTURE_2D_ARRAY; + case EiifRGBA8: + return HLSL_TEXTURE_2D_ARRAY_UNORN; + case EiifRGBA8_SNORM: + return HLSL_TEXTURE_2D_ARRAY_SNORM; + default: + UNREACHABLE(); + return HLSL_TEXTURE_UNKNOWN; + } + } + case EbtIImage2DArray: + case EbtIImageCube: + { + switch (imageInternalFormat) + { + case EiifRGBA32I: + case EiifRGBA16I: + case EiifRGBA8I: + case EiifR32I: + return HLSL_TEXTURE_2D_ARRAY_INT4; + default: + UNREACHABLE(); + return HLSL_TEXTURE_UNKNOWN; + } + } + case EbtUImage2DArray: + case EbtUImageCube: + { + switch (imageInternalFormat) + { + case EiifRGBA32UI: + case EiifRGBA16UI: + case EiifRGBA8UI: + case EiifR32UI: + return HLSL_TEXTURE_2D_ARRAY_UINT4; + default: + UNREACHABLE(); + return HLSL_TEXTURE_UNKNOWN; + } + } + case EbtImageBuffer: + { + switch (imageInternalFormat) + { + case EiifRGBA32F: + case EiifRGBA16F: + case EiifR32F: + return HLSL_TEXTURE_BUFFER; + case EiifRGBA8: + return HLSL_TEXTURE_BUFFER_UNORM; + case EiifRGBA8_SNORM: + return HLSL_TEXTURE_BUFFER_SNORM; + default: + UNREACHABLE(); + return HLSL_TEXTURE_UNKNOWN; + } + } + case EbtUImageBuffer: + { + switch (imageInternalFormat) + { + case EiifRGBA32UI: + case EiifRGBA16UI: + case EiifRGBA8UI: + case EiifR32UI: + return HLSL_TEXTURE_BUFFER_UINT4; + default: + UNREACHABLE(); + return HLSL_TEXTURE_UNKNOWN; + } + } + case EbtIImageBuffer: + { + switch (imageInternalFormat) + { + case EiifRGBA32I: + case EiifRGBA16I: + case EiifRGBA8I: + case EiifR32I: + return HLSL_TEXTURE_BUFFER_INT4; + default: + UNREACHABLE(); + return HLSL_TEXTURE_UNKNOWN; + } + } + default: + UNREACHABLE(); + return HLSL_TEXTURE_UNKNOWN; + } +} + +const char *TextureString(const HLSLTextureGroup textureGroup) +{ + switch (textureGroup) + { + case HLSL_TEXTURE_2D: + return "Texture2D"; + case HLSL_TEXTURE_CUBE: + return "TextureCube"; + case HLSL_TEXTURE_2D_ARRAY: + return "Texture2DArray"; + case HLSL_TEXTURE_3D: + return "Texture3D"; + case HLSL_TEXTURE_2D_UNORM: + return "Texture2D"; + case HLSL_TEXTURE_CUBE_UNORM: + return "TextureCube"; + case HLSL_TEXTURE_2D_ARRAY_UNORN: + return "Texture2DArray"; + case HLSL_TEXTURE_3D_UNORM: + return "Texture3D"; + case HLSL_TEXTURE_2D_SNORM: + return "Texture2D"; + case HLSL_TEXTURE_CUBE_SNORM: + return "TextureCube"; + case HLSL_TEXTURE_2D_ARRAY_SNORM: + return "Texture2DArray"; + case HLSL_TEXTURE_3D_SNORM: + return "Texture3D"; + case HLSL_TEXTURE_2D_MS: + return "Texture2DMS"; + case HLSL_TEXTURE_2D_MS_ARRAY: + return "Texture2DMSArray"; + case HLSL_TEXTURE_2D_INT4: + return "Texture2D"; + case HLSL_TEXTURE_3D_INT4: + return "Texture3D"; + case HLSL_TEXTURE_2D_ARRAY_INT4: + return "Texture2DArray"; + case HLSL_TEXTURE_2D_MS_INT4: + return "Texture2DMS"; + case HLSL_TEXTURE_2D_MS_ARRAY_INT4: + return "Texture2DMSArray"; + case HLSL_TEXTURE_2D_UINT4: + return "Texture2D"; + case HLSL_TEXTURE_3D_UINT4: + return "Texture3D"; + case HLSL_TEXTURE_2D_ARRAY_UINT4: + return "Texture2DArray"; + case HLSL_TEXTURE_2D_MS_UINT4: + return "Texture2DMS"; + case HLSL_TEXTURE_2D_MS_ARRAY_UINT4: + return "Texture2DMSArray"; + case HLSL_TEXTURE_2D_COMPARISON: + return "Texture2D"; + case HLSL_TEXTURE_CUBE_COMPARISON: + return "TextureCube"; + case HLSL_TEXTURE_2D_ARRAY_COMPARISON: + return "Texture2DArray"; + case HLSL_TEXTURE_BUFFER: + return "Buffer"; + case HLSL_TEXTURE_BUFFER_INT4: + return "Buffer"; + case HLSL_TEXTURE_BUFFER_UINT4: + return "Buffer"; + case HLSL_TEXTURE_BUFFER_UNORM: + return "Buffer"; + case HLSL_TEXTURE_BUFFER_SNORM: + return "Buffer"; + default: + UNREACHABLE(); + } + + return ""; +} + +const char *TextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) +{ + return TextureString(TextureGroup(type, imageInternalFormat)); +} + +const char *TextureGroupSuffix(const HLSLTextureGroup type) +{ + switch (type) + { + case HLSL_TEXTURE_2D: + return "2D"; + case HLSL_TEXTURE_CUBE: + return "Cube"; + case HLSL_TEXTURE_2D_ARRAY: + return "2DArray"; + case HLSL_TEXTURE_3D: + return "3D"; + case HLSL_TEXTURE_2D_UNORM: + return "2D_unorm_float4_"; + case HLSL_TEXTURE_CUBE_UNORM: + return "Cube_unorm_float4_"; + case HLSL_TEXTURE_2D_ARRAY_UNORN: + return "2DArray_unorm_float4_"; + case HLSL_TEXTURE_3D_UNORM: + return "3D_unorm_float4_"; + case HLSL_TEXTURE_2D_SNORM: + return "2D_snorm_float4_"; + case HLSL_TEXTURE_CUBE_SNORM: + return "Cube_snorm_float4_"; + case HLSL_TEXTURE_2D_ARRAY_SNORM: + return "2DArray_snorm_float4_"; + case HLSL_TEXTURE_3D_SNORM: + return "3D_snorm_float4_"; + case HLSL_TEXTURE_2D_MS: + return "2DMS"; + case HLSL_TEXTURE_2D_MS_ARRAY: + return "2DMSArray"; + case HLSL_TEXTURE_2D_INT4: + return "2D_int4_"; + case HLSL_TEXTURE_3D_INT4: + return "3D_int4_"; + case HLSL_TEXTURE_2D_ARRAY_INT4: + return "2DArray_int4_"; + case HLSL_TEXTURE_2D_MS_INT4: + return "2DMS_int4_"; + case HLSL_TEXTURE_2D_MS_ARRAY_INT4: + return "2DMSArray_int4_"; + case HLSL_TEXTURE_2D_UINT4: + return "2D_uint4_"; + case HLSL_TEXTURE_3D_UINT4: + return "3D_uint4_"; + case HLSL_TEXTURE_2D_ARRAY_UINT4: + return "2DArray_uint4_"; + case HLSL_TEXTURE_2D_MS_UINT4: + return "2DMS_uint4_"; + case HLSL_TEXTURE_2D_MS_ARRAY_UINT4: + return "2DMSArray_uint4_"; + case HLSL_TEXTURE_2D_COMPARISON: + return "2D_comparison"; + case HLSL_TEXTURE_CUBE_COMPARISON: + return "Cube_comparison"; + case HLSL_TEXTURE_2D_ARRAY_COMPARISON: + return "2DArray_comparison"; + case HLSL_TEXTURE_BUFFER: + return "Buffer"; + case HLSL_TEXTURE_BUFFER_INT4: + return "Buffer_int4_"; + case HLSL_TEXTURE_BUFFER_UINT4: + return "Buffer_uint4_"; + case HLSL_TEXTURE_BUFFER_UNORM: + return "Buffer_unorm_float4_"; + case HLSL_TEXTURE_BUFFER_SNORM: + return "Buffer_snorm_float4_"; + default: + UNREACHABLE(); + } + + return ""; +} + +const char *TextureGroupSuffix(const TBasicType type, + TLayoutImageInternalFormat imageInternalFormat) +{ + return TextureGroupSuffix(TextureGroup(type, imageInternalFormat)); +} + +const char *TextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) +{ + switch (type) + { + case EbtISamplerCube: + return "Cube_int4_"; + case EbtUSamplerCube: + return "Cube_uint4_"; + case EbtSamplerExternalOES: + return "_External"; + case EbtImageCube: + { + switch (imageInternalFormat) + { + case EiifRGBA32F: + case EiifRGBA16F: + case EiifR32F: + return "Cube_float4_"; + case EiifRGBA8: + return "Cube_unorm_float4_"; + case EiifRGBA8_SNORM: + return "Cube_snorm_float4_"; + default: + UNREACHABLE(); + } + break; + } + case EbtIImageCube: + { + switch (imageInternalFormat) + { + case EiifRGBA32I: + case EiifRGBA16I: + case EiifRGBA8I: + case EiifR32I: + return "Cube_int4_"; + default: + UNREACHABLE(); + } + break; + } + case EbtUImageCube: + { + switch (imageInternalFormat) + { + case EiifRGBA32UI: + case EiifRGBA16UI: + case EiifRGBA8UI: + case EiifR32UI: + return "Cube_uint4_"; + default: + UNREACHABLE(); + } + break; + } + default: + // All other types are identified by their group suffix + return TextureGroupSuffix(type, imageInternalFormat); + } + UNREACHABLE(); + return "_TTS_invalid_"; +} + +HLSLRWTextureGroup RWTextureGroup(const TBasicType type, + TLayoutImageInternalFormat imageInternalFormat) + +{ + switch (type) + { + case EbtImage2D: + { + switch (imageInternalFormat) + { + case EiifRGBA32F: + case EiifRGBA16F: + case EiifR32F: + return HLSL_RWTEXTURE_2D_FLOAT4; + case EiifRGBA8: + return HLSL_RWTEXTURE_2D_UNORM; + case EiifRGBA8_SNORM: + return HLSL_RWTEXTURE_2D_SNORM; + default: + UNREACHABLE(); + } + break; + } + case EbtIImage2D: + { + switch (imageInternalFormat) + { + case EiifRGBA32I: + case EiifRGBA16I: + case EiifRGBA8I: + case EiifR32I: + return HLSL_RWTEXTURE_2D_INT4; + default: + UNREACHABLE(); + } + break; + } + case EbtUImage2D: + { + switch (imageInternalFormat) + { + + case EiifRGBA32UI: + case EiifRGBA16UI: + case EiifRGBA8UI: + case EiifR32UI: + return HLSL_RWTEXTURE_2D_UINT4; + default: + UNREACHABLE(); + } + break; + } + case EbtImage3D: + { + switch (imageInternalFormat) + { + case EiifRGBA32F: + case EiifRGBA16F: + case EiifR32F: + return HLSL_RWTEXTURE_3D_FLOAT4; + case EiifRGBA8: + return HLSL_RWTEXTURE_3D_UNORM; + case EiifRGBA8_SNORM: + return HLSL_RWTEXTURE_3D_SNORM; + default: + UNREACHABLE(); + } + break; + } + case EbtIImage3D: + { + switch (imageInternalFormat) + { + case EiifRGBA32I: + case EiifRGBA16I: + case EiifRGBA8I: + case EiifR32I: + return HLSL_RWTEXTURE_3D_INT4; + default: + UNREACHABLE(); + } + break; + } + case EbtUImage3D: + { + switch (imageInternalFormat) + { + case EiifRGBA32UI: + case EiifRGBA16UI: + case EiifRGBA8UI: + case EiifR32UI: + return HLSL_RWTEXTURE_3D_UINT4; + default: + UNREACHABLE(); + } + break; + } + case EbtImage2DArray: + case EbtImageCube: + { + switch (imageInternalFormat) + { + case EiifRGBA32F: + case EiifRGBA16F: + case EiifR32F: + return HLSL_RWTEXTURE_2D_ARRAY_FLOAT4; + case EiifRGBA8: + return HLSL_RWTEXTURE_2D_ARRAY_UNORN; + case EiifRGBA8_SNORM: + return HLSL_RWTEXTURE_2D_ARRAY_SNORM; + default: + UNREACHABLE(); + } + break; + } + case EbtIImage2DArray: + case EbtIImageCube: + { + switch (imageInternalFormat) + { + case EiifRGBA32I: + case EiifRGBA16I: + case EiifRGBA8I: + case EiifR32I: + return HLSL_RWTEXTURE_2D_ARRAY_INT4; + default: + UNREACHABLE(); + } + break; + } + case EbtUImage2DArray: + case EbtUImageCube: + { + switch (imageInternalFormat) + { + case EiifRGBA32UI: + case EiifRGBA16UI: + case EiifRGBA8UI: + case EiifR32UI: + return HLSL_RWTEXTURE_2D_ARRAY_UINT4; + default: + UNREACHABLE(); + } + break; + } + case EbtImageBuffer: + { + switch (imageInternalFormat) + { + case EiifRGBA32F: + case EiifRGBA16F: + case EiifR32F: + return HLSL_RWTEXTURE_BUFFER_FLOAT4; + case EiifRGBA8: + return HLSL_RWTEXTURE_BUFFER_UNORM; + case EiifRGBA8_SNORM: + return HLSL_RWTEXTURE_BUFFER_SNORM; + default: + UNREACHABLE(); + } + break; + } + case EbtIImageBuffer: + { + switch (imageInternalFormat) + { + case EiifRGBA32I: + case EiifRGBA16I: + case EiifRGBA8I: + case EiifR32I: + return HLSL_RWTEXTURE_BUFFER_INT4; + default: + UNREACHABLE(); + } + break; + } + case EbtUImageBuffer: + { + switch (imageInternalFormat) + { + case EiifRGBA32UI: + case EiifRGBA16UI: + case EiifRGBA8UI: + case EiifR32UI: + return HLSL_RWTEXTURE_BUFFER_UINT4; + default: + UNREACHABLE(); + } + break; + } + default: + UNREACHABLE(); + } + return HLSL_RWTEXTURE_UNKNOWN; +} + +const char *RWTextureString(const HLSLRWTextureGroup RWTextureGroup) +{ + switch (RWTextureGroup) + { + case HLSL_RWTEXTURE_2D_FLOAT4: + return "RWTexture2D"; + case HLSL_RWTEXTURE_2D_ARRAY_FLOAT4: + return "RWTexture2DArray"; + case HLSL_RWTEXTURE_3D_FLOAT4: + return "RWTexture3D"; + case HLSL_RWTEXTURE_2D_UNORM: + return "RWTexture2D"; + case HLSL_RWTEXTURE_2D_ARRAY_UNORN: + return "RWTexture2DArray"; + case HLSL_RWTEXTURE_3D_UNORM: + return "RWTexture3D"; + case HLSL_RWTEXTURE_2D_SNORM: + return "RWTexture2D"; + case HLSL_RWTEXTURE_2D_ARRAY_SNORM: + return "RWTexture2DArray"; + case HLSL_RWTEXTURE_3D_SNORM: + return "RWTexture3D"; + case HLSL_RWTEXTURE_2D_UINT4: + return "RWTexture2D"; + case HLSL_RWTEXTURE_2D_ARRAY_UINT4: + return "RWTexture2DArray"; + case HLSL_RWTEXTURE_3D_UINT4: + return "RWTexture3D"; + case HLSL_RWTEXTURE_2D_INT4: + return "RWTexture2D"; + case HLSL_RWTEXTURE_2D_ARRAY_INT4: + return "RWTexture2DArray"; + case HLSL_RWTEXTURE_3D_INT4: + return "RWTexture3D"; + case HLSL_RWTEXTURE_BUFFER_FLOAT4: + return "RWBuffer"; + case HLSL_RWTEXTURE_BUFFER_UNORM: + return "RWBuffer"; + case HLSL_RWTEXTURE_BUFFER_SNORM: + return "RWBuffer"; + case HLSL_RWTEXTURE_BUFFER_UINT4: + return "RWBuffer"; + case HLSL_RWTEXTURE_BUFFER_INT4: + return "RWBuffer"; + default: + UNREACHABLE(); + } + + return ""; +} + +const char *RWTextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) +{ + return RWTextureString(RWTextureGroup(type, imageInternalFormat)); +} + +const char *RWTextureGroupSuffix(const HLSLRWTextureGroup type) +{ + switch (type) + { + case HLSL_RWTEXTURE_2D_FLOAT4: + return "RW2D_float4_"; + case HLSL_RWTEXTURE_2D_ARRAY_FLOAT4: + return "RW2DArray_float4_"; + case HLSL_RWTEXTURE_3D_FLOAT4: + return "RW3D_float4_"; + case HLSL_RWTEXTURE_2D_UNORM: + return "RW2D_unorm_float4_"; + case HLSL_RWTEXTURE_2D_ARRAY_UNORN: + return "RW2DArray_unorm_float4_"; + case HLSL_RWTEXTURE_3D_UNORM: + return "RW3D_unorm_float4_"; + case HLSL_RWTEXTURE_2D_SNORM: + return "RW2D_snorm_float4_"; + case HLSL_RWTEXTURE_2D_ARRAY_SNORM: + return "RW2DArray_snorm_float4_"; + case HLSL_RWTEXTURE_3D_SNORM: + return "RW3D_snorm_float4_"; + case HLSL_RWTEXTURE_2D_UINT4: + return "RW2D_uint4_"; + case HLSL_RWTEXTURE_2D_ARRAY_UINT4: + return "RW2DArray_uint4_"; + case HLSL_RWTEXTURE_3D_UINT4: + return "RW3D_uint4_"; + case HLSL_RWTEXTURE_2D_INT4: + return "RW2D_int4_"; + case HLSL_RWTEXTURE_2D_ARRAY_INT4: + return "RW2DArray_int4_"; + case HLSL_RWTEXTURE_3D_INT4: + return "RW3D_int4_"; + case HLSL_RWTEXTURE_BUFFER_FLOAT4: + return "RWBuffer_float4_"; + case HLSL_RWTEXTURE_BUFFER_UNORM: + return "RWBuffer_unorm_float4_"; + case HLSL_RWTEXTURE_BUFFER_SNORM: + return "RWBuffer_snorm_float4_"; + case HLSL_RWTEXTURE_BUFFER_UINT4: + return "RWBuffer_uint4_"; + case HLSL_RWTEXTURE_BUFFER_INT4: + return "RWBuffer_int4_"; + default: + UNREACHABLE(); + } + + return ""; +} + +const char *RWTextureGroupSuffix(const TBasicType type, + TLayoutImageInternalFormat imageInternalFormat) +{ + return RWTextureGroupSuffix(RWTextureGroup(type, imageInternalFormat)); +} + +const char *RWTextureTypeSuffix(const TBasicType type, + TLayoutImageInternalFormat imageInternalFormat) +{ + switch (type) + { + case EbtImageCube: + { + switch (imageInternalFormat) + { + case EiifRGBA32F: + case EiifRGBA16F: + case EiifR32F: + return "RWCube_float4_"; + case EiifRGBA8: + return "RWCube_unorm_float4_"; + case EiifRGBA8_SNORM: + return "RWCube_unorm_float4_"; + default: + UNREACHABLE(); + } + break; + } + case EbtIImageCube: + { + switch (imageInternalFormat) + { + case EiifRGBA32I: + case EiifRGBA16I: + case EiifRGBA8I: + case EiifR32I: + return "RWCube_int4_"; + default: + UNREACHABLE(); + } + break; + } + case EbtUImageCube: + { + switch (imageInternalFormat) + { + case EiifRGBA32UI: + case EiifRGBA16UI: + case EiifRGBA8UI: + case EiifR32UI: + return "RWCube_uint4_"; + default: + UNREACHABLE(); + } + break; + } + default: + // All other types are identified by their group suffix + return RWTextureGroupSuffix(type, imageInternalFormat); + } + UNREACHABLE(); + return "_RWTS_invalid_"; +} + +TString DecorateField(const ImmutableString &string, const TStructure &structure) +{ + if (structure.symbolType() != SymbolType::BuiltIn) + { + return Decorate(string); + } + + return TString(string.data()); +} + +TString DecoratePrivate(const ImmutableString &privateText) +{ + return "dx_" + TString(privateText.data()); +} + +TString Decorate(const ImmutableString &string) +{ + if (!gl::IsBuiltInName(string.data())) + { + return "_" + TString(string.data()); + } + + return TString(string.data()); +} + +TString DecorateVariableIfNeeded(const TVariable &variable) +{ + if (variable.symbolType() == SymbolType::AngleInternal || + variable.symbolType() == SymbolType::BuiltIn || variable.symbolType() == SymbolType::Empty) + { + // Besides handling internal variables, we generate names for nameless parameters here. + const ImmutableString &name = variable.name(); + // The name should not have a prefix reserved for user-defined variables or functions. + ASSERT(!name.beginsWith("f_")); + ASSERT(!name.beginsWith("_")); + return TString(name.data()); + } + // For user defined variables, combine variable name with unique id + // so variables of the same name in different scopes do not get overwritten. + else if (variable.symbolType() == SymbolType::UserDefined && + variable.getType().getQualifier() == EvqTemporary) + { + return Decorate(variable.name()) + str(variable.uniqueId().get()); + } + else + { + return Decorate(variable.name()); + } +} + +TString DecorateFunctionIfNeeded(const TFunction *func) +{ + if (func->symbolType() == SymbolType::AngleInternal) + { + // The name should not have a prefix reserved for user-defined variables or functions. + ASSERT(!func->name().beginsWith("f_")); + ASSERT(!func->name().beginsWith("_")); + return TString(func->name().data()); + } + ASSERT(!gl::IsBuiltInName(func->name().data())); + // Add an additional f prefix to functions so that they're always disambiguated from variables. + // This is necessary in the corner case where a variable declaration hides a function that it + // uses in its initializer. + return "f_" + TString(func->name().data()); +} + +TString TypeString(const TType &type) +{ + const TStructure *structure = type.getStruct(); + if (structure) + { + if (structure->symbolType() != SymbolType::Empty) + { + return StructNameString(*structure); + } + else // Nameless structure, define in place + { + return StructureHLSL::defineNameless(*structure); + } + } + else if (type.isMatrix()) + { + uint8_t cols = type.getCols(); + uint8_t rows = type.getRows(); + return "float" + str(cols) + "x" + str(rows); + } + else + { + switch (type.getBasicType()) + { + case EbtFloat: + switch (type.getNominalSize()) + { + case 1: + return "float"; + case 2: + return "float2"; + case 3: + return "float3"; + case 4: + return "float4"; + } + case EbtInt: + switch (type.getNominalSize()) + { + case 1: + return "int"; + case 2: + return "int2"; + case 3: + return "int3"; + case 4: + return "int4"; + } + case EbtUInt: + switch (type.getNominalSize()) + { + case 1: + return "uint"; + case 2: + return "uint2"; + case 3: + return "uint3"; + case 4: + return "uint4"; + } + case EbtBool: + switch (type.getNominalSize()) + { + case 1: + return "bool"; + case 2: + return "bool2"; + case 3: + return "bool3"; + case 4: + return "bool4"; + } + case EbtVoid: + return "void"; + case EbtSampler2D: + case EbtISampler2D: + case EbtUSampler2D: + case EbtSampler2DArray: + case EbtISampler2DArray: + case EbtUSampler2DArray: + return "sampler2D"; + case EbtSamplerCube: + case EbtISamplerCube: + case EbtUSamplerCube: + return "samplerCUBE"; + case EbtSamplerExternalOES: + return "sampler2D"; + case EbtSamplerVideoWEBGL: + return "sampler2D"; + case EbtAtomicCounter: + // Multiple atomic_uints will be implemented as a single RWByteAddressBuffer + return "RWByteAddressBuffer"; + default: + break; + } + } + + UNREACHABLE(); + return ""; +} + +TString StructNameString(const TStructure &structure) +{ + if (structure.symbolType() == SymbolType::Empty) + { + return ""; + } + + // For structures at global scope we use a consistent + // translation so that we can link between shader stages. + if (structure.atGlobalScope()) + { + return Decorate(structure.name()); + } + + return "ss" + str(structure.uniqueId().get()) + "_" + TString(structure.name().data()); +} + +TString QualifiedStructNameString(const TStructure &structure, + bool useHLSLRowMajorPacking, + bool useStd140Packing, + bool forcePadding) +{ + if (structure.symbolType() == SymbolType::Empty) + { + return ""; + } + + TString prefix = ""; + + // Structs packed with row-major matrices in HLSL are prefixed with "rm" + // GLSL column-major maps to HLSL row-major, and the converse is true + + if (useStd140Packing) + { + prefix += "std_"; + } + + if (useHLSLRowMajorPacking) + { + prefix += "rm_"; + } + + if (forcePadding) + { + prefix += "fp_"; + } + + return prefix + StructNameString(structure); +} + +const char *InterpolationString(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqVaryingIn: + return ""; + case EvqFragmentIn: + return ""; + case EvqSmoothIn: + return "linear"; + case EvqFlatIn: + return "nointerpolation"; + case EvqCentroidIn: + return "centroid"; + case EvqVaryingOut: + return ""; + case EvqVertexOut: + return ""; + case EvqSmoothOut: + return "linear"; + case EvqFlatOut: + return "nointerpolation"; + case EvqCentroidOut: + return "centroid"; + case EvqSampleIn: + return "sample"; + default: + UNREACHABLE(); + } + + return ""; +} + +const char *QualifierString(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqParamIn: + return "in"; + case EvqParamOut: + return "inout"; // 'out' results in an HLSL error if not all fields are written, for + // GLSL it's undefined + case EvqParamInOut: + return "inout"; + case EvqParamConst: + return "const"; + case EvqSampleOut: + return "sample"; + default: + UNREACHABLE(); + } + + return ""; +} + +TString DisambiguateFunctionName(const TFunction *func) +{ + TString disambiguatingString; + size_t paramCount = func->getParamCount(); + for (size_t i = 0; i < paramCount; ++i) + { + DisambiguateFunctionNameForParameterType(func->getParam(i)->getType(), + &disambiguatingString); + } + return disambiguatingString; +} + +TString DisambiguateFunctionName(const TIntermSequence *args) +{ + TString disambiguatingString; + for (TIntermNode *arg : *args) + { + ASSERT(arg->getAsTyped()); + DisambiguateFunctionNameForParameterType(arg->getAsTyped()->getType(), + &disambiguatingString); + } + return disambiguatingString; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/UtilsHLSL.h b/gfx/angle/checkout/src/compiler/translator/UtilsHLSL.h new file mode 100644 index 0000000000..722b61f3ca --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/UtilsHLSL.h @@ -0,0 +1,148 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// UtilsHLSL.h: +// Utility methods for GLSL to HLSL translation. +// + +#ifndef COMPILER_TRANSLATOR_UTILSHLSL_H_ +#define COMPILER_TRANSLATOR_UTILSHLSL_H_ + +#include +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Types.h" + +#include "angle_gl.h" + +namespace sh +{ + +class TFunction; + +// HLSL Texture type for GLSL sampler type and readonly image type. +enum HLSLTextureGroup +{ + // read resources + HLSL_TEXTURE_2D, + HLSL_TEXTURE_MIN = HLSL_TEXTURE_2D, + + HLSL_TEXTURE_CUBE, + HLSL_TEXTURE_2D_ARRAY, + HLSL_TEXTURE_3D, + HLSL_TEXTURE_2D_UNORM, + HLSL_TEXTURE_CUBE_UNORM, + HLSL_TEXTURE_2D_ARRAY_UNORN, + HLSL_TEXTURE_3D_UNORM, + HLSL_TEXTURE_2D_SNORM, + HLSL_TEXTURE_CUBE_SNORM, + HLSL_TEXTURE_2D_ARRAY_SNORM, + HLSL_TEXTURE_3D_SNORM, + HLSL_TEXTURE_2D_MS, + HLSL_TEXTURE_2D_MS_ARRAY, + HLSL_TEXTURE_2D_INT4, + HLSL_TEXTURE_3D_INT4, + HLSL_TEXTURE_2D_ARRAY_INT4, + HLSL_TEXTURE_2D_MS_INT4, + HLSL_TEXTURE_2D_MS_ARRAY_INT4, + HLSL_TEXTURE_2D_UINT4, + HLSL_TEXTURE_3D_UINT4, + HLSL_TEXTURE_2D_ARRAY_UINT4, + HLSL_TEXTURE_2D_MS_UINT4, + HLSL_TEXTURE_2D_MS_ARRAY_UINT4, + + HLSL_TEXTURE_BUFFER, + HLSL_TEXTURE_BUFFER_UNORM, + HLSL_TEXTURE_BUFFER_SNORM, + HLSL_TEXTURE_BUFFER_UINT4, + HLSL_TEXTURE_BUFFER_INT4, + + // Comparison samplers + + HLSL_TEXTURE_2D_COMPARISON, + HLSL_TEXTURE_CUBE_COMPARISON, + HLSL_TEXTURE_2D_ARRAY_COMPARISON, + + HLSL_COMPARISON_SAMPLER_GROUP_BEGIN = HLSL_TEXTURE_2D_COMPARISON, + HLSL_COMPARISON_SAMPLER_GROUP_END = HLSL_TEXTURE_2D_ARRAY_COMPARISON, + + HLSL_TEXTURE_UNKNOWN, + HLSL_TEXTURE_MAX = HLSL_TEXTURE_UNKNOWN +}; + +// HLSL RWTexture type for GLSL read and write image type. +enum HLSLRWTextureGroup +{ + // read/write resource + HLSL_RWTEXTURE_2D_FLOAT4, + HLSL_RWTEXTURE_MIN = HLSL_RWTEXTURE_2D_FLOAT4, + HLSL_RWTEXTURE_2D_ARRAY_FLOAT4, + HLSL_RWTEXTURE_3D_FLOAT4, + HLSL_RWTEXTURE_2D_UNORM, + HLSL_RWTEXTURE_2D_ARRAY_UNORN, + HLSL_RWTEXTURE_3D_UNORM, + HLSL_RWTEXTURE_2D_SNORM, + HLSL_RWTEXTURE_2D_ARRAY_SNORM, + HLSL_RWTEXTURE_3D_SNORM, + HLSL_RWTEXTURE_2D_UINT4, + HLSL_RWTEXTURE_2D_ARRAY_UINT4, + HLSL_RWTEXTURE_3D_UINT4, + HLSL_RWTEXTURE_2D_INT4, + HLSL_RWTEXTURE_2D_ARRAY_INT4, + HLSL_RWTEXTURE_3D_INT4, + + HLSL_RWTEXTURE_BUFFER_FLOAT4, + HLSL_RWTEXTURE_BUFFER_UNORM, + HLSL_RWTEXTURE_BUFFER_SNORM, + HLSL_RWTEXTURE_BUFFER_UINT4, + HLSL_RWTEXTURE_BUFFER_INT4, + + HLSL_RWTEXTURE_UNKNOWN, + HLSL_RWTEXTURE_MAX = HLSL_RWTEXTURE_UNKNOWN +}; + +HLSLTextureGroup TextureGroup(const TBasicType type, + TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified); +const char *TextureString(const HLSLTextureGroup textureGroup); +const char *TextureString(const TBasicType type, + TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified); +const char *TextureGroupSuffix(const HLSLTextureGroup type); +const char *TextureGroupSuffix(const TBasicType type, + TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified); +const char *TextureTypeSuffix(const TBasicType type, + TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified); +HLSLRWTextureGroup RWTextureGroup(const TBasicType type, + TLayoutImageInternalFormat imageInternalFormat); +const char *RWTextureString(const HLSLRWTextureGroup textureGroup); +const char *RWTextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat); +const char *RWTextureGroupSuffix(const HLSLRWTextureGroup type); +const char *RWTextureGroupSuffix(const TBasicType type, + TLayoutImageInternalFormat imageInternalFormat); +const char *RWTextureTypeSuffix(const TBasicType type, + TLayoutImageInternalFormat imageInternalFormat); + +const char *SamplerString(const TBasicType type); +const char *SamplerString(HLSLTextureGroup type); + +// Adds a prefix to user-defined names to avoid naming clashes. +TString Decorate(const ImmutableString &string); +TString DecorateVariableIfNeeded(const TVariable &variable); +TString DecorateFunctionIfNeeded(const TFunction *func); +TString DecorateField(const ImmutableString &string, const TStructure &structure); +TString DecoratePrivate(const ImmutableString &privateText); +TString TypeString(const TType &type); +TString StructNameString(const TStructure &structure); +TString QualifiedStructNameString(const TStructure &structure, + bool useHLSLRowMajorPacking, + bool useStd140Packing, + bool forcePackingEnd); +const char *InterpolationString(TQualifier qualifier); +const char *QualifierString(TQualifier qualifier); +// Parameters may need to be included in function names to disambiguate between overloaded +// functions. +TString DisambiguateFunctionName(const TFunction *func); +TString DisambiguateFunctionName(const TIntermSequence *args); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_UTILSHLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateAST.cpp b/gfx/angle/checkout/src/compiler/translator/ValidateAST.cpp new file mode 100644 index 0000000000..faba9a9a82 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateAST.cpp @@ -0,0 +1,1133 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/ValidateAST.h" + +#include "common/utilities.h" +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/SpecializationConstant.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +class ValidateAST : public TIntermTraverser +{ + public: + static bool validate(TIntermNode *root, + TDiagnostics *diagnostics, + const ValidateASTOptions &options); + + void visitSymbol(TIntermSymbol *node) override; + void visitConstantUnion(TIntermConstantUnion *node) override; + bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; + bool visitBinary(Visit visit, TIntermBinary *node) override; + bool visitUnary(Visit visit, TIntermUnary *node) override; + bool visitTernary(Visit visit, TIntermTernary *node) override; + bool visitIfElse(Visit visit, TIntermIfElse *node) override; + bool visitSwitch(Visit visit, TIntermSwitch *node) override; + bool visitCase(Visit visit, TIntermCase *node) override; + void visitFunctionPrototype(TIntermFunctionPrototype *node) override; + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + bool visitBlock(Visit visit, TIntermBlock *node) override; + bool visitGlobalQualifierDeclaration(Visit visit, + TIntermGlobalQualifierDeclaration *node) override; + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; + bool visitLoop(Visit visit, TIntermLoop *node) override; + bool visitBranch(Visit visit, TIntermBranch *node) override; + void visitPreprocessorDirective(TIntermPreprocessorDirective *node) override; + + private: + ValidateAST(TIntermNode *root, TDiagnostics *diagnostics, const ValidateASTOptions &options); + + // Visit as a generic node + void visitNode(Visit visit, TIntermNode *node); + // Visit a structure or interface block, and recursively visit its fields of structure type. + void visitStructOrInterfaceBlockDeclaration(const TType &type, const TSourceLoc &location); + void visitStructUsage(const TType &type, const TSourceLoc &location); + // Visit a unary or aggregate node and validate its built-in op against its built-in function. + void visitBuiltInFunction(TIntermOperator *op, const TFunction *function); + // Visit an aggregate node and validate its function call is to one that's already defined. + void visitFunctionCall(TIntermAggregate *node); + // Visit a binary node and validate its type against its operands. + void validateExpressionTypeBinary(TIntermBinary *node); + // Visit a switch node and validate its selector type is integer. + void validateExpressionTypeSwitch(TIntermSwitch *node); + // Visit a symbol node and validate it's declared previously. + void visitVariableNeedingDeclaration(TIntermSymbol *node); + // Visit a built-in symbol node and validate it's consistently used across the tree. + void visitBuiltInVariable(TIntermSymbol *node); + + void scope(Visit visit); + bool isVariableDeclared(const TVariable *variable); + bool variableNeedsDeclaration(const TVariable *variable); + const TFieldListCollection *getStructOrInterfaceBlock(const TType &type, + ImmutableString *typeNameOut); + + void expectNonNullChildren(Visit visit, TIntermNode *node, size_t least_count); + + bool validateInternal(); + + ValidateASTOptions mOptions; + TDiagnostics *mDiagnostics; + + // For validateSingleParent: + std::map mParent; + bool mSingleParentFailed = false; + + // For validateVariableReferences: + std::vector> mDeclaredVariables; + std::set mNamelessInterfaceBlocks; + std::map mReferencedBuiltIns; + bool mVariableReferencesFailed = false; + + // For validateBuiltInOps: + bool mBuiltInOpsFailed = false; + + // For validateFunctionCall: + std::set mDeclaredFunctions; + bool mFunctionCallFailed = false; + + // For validateNoRawFunctionCalls: + bool mNoRawFunctionCallsFailed = false; + + // For validateNullNodes: + bool mNullNodesFailed = false; + + // For validateQualifiers: + bool mQualifiersFailed = false; + + // For validatePrecision: + bool mPrecisionFailed = false; + + // For validateStructUsage: + std::vector> mStructsAndBlocksByName; + bool mStructUsageFailed = false; + + // For validateExpressionTypes: + bool mExpressionTypesFailed = false; + + // For validateMultiDeclarations: + bool mMultiDeclarationsFailed = false; + + // For validateNoSwizzleOfSwizzle: + bool mNoSwizzleOfSwizzleFailed = false; + + // For validateNoStatementsAfterBranch: + bool mIsBranchVisitedInBlock = false; + bool mNoStatementsAfterBranchFailed = false; +}; + +bool IsSameType(const TType &a, const TType &b) +{ + return a.getBasicType() == b.getBasicType() && a.getNominalSize() == b.getNominalSize() && + a.getSecondarySize() == b.getSecondarySize() && a.getArraySizes() == b.getArraySizes() && + a.getStruct() == b.getStruct() && + (!a.isInterfaceBlock() || a.getInterfaceBlock() == b.getInterfaceBlock()); +} + +bool ValidateAST::validate(TIntermNode *root, + TDiagnostics *diagnostics, + const ValidateASTOptions &options) +{ + ValidateAST validate(root, diagnostics, options); + root->traverse(&validate); + return validate.validateInternal(); +} + +ValidateAST::ValidateAST(TIntermNode *root, + TDiagnostics *diagnostics, + const ValidateASTOptions &options) + : TIntermTraverser(true, false, true, nullptr), mOptions(options), mDiagnostics(diagnostics) +{ + bool isTreeRoot = root->getAsBlock() && root->getAsBlock()->isTreeRoot(); + + // Some validations are not applicable unless run on the entire tree. + if (!isTreeRoot) + { + mOptions.validateVariableReferences = false; + mOptions.validateFunctionCall = false; + mOptions.validateStructUsage = false; + } + + if (mOptions.validateSingleParent) + { + mParent[root] = nullptr; + } +} + +void ValidateAST::visitNode(Visit visit, TIntermNode *node) +{ + if (visit == PreVisit && mOptions.validateSingleParent) + { + size_t childCount = node->getChildCount(); + for (size_t i = 0; i < childCount; ++i) + { + TIntermNode *child = node->getChildNode(i); + if (mParent.find(child) != mParent.end()) + { + // If child is visited twice but through the same parent, the problem is in one of + // the ancestors. + if (mParent[child] != node) + { + mDiagnostics->error(node->getLine(), "Found child with two parents", + ""); + mSingleParentFailed = true; + } + } + + mParent[child] = node; + } + } + + if (visit == PreVisit && mOptions.validateNoStatementsAfterBranch) + { + // If a branch has already been visited in this block, there should be no statements that + // follow. Only expected node visit should be PostVisit of the block. + if (mIsBranchVisitedInBlock) + { + mDiagnostics->error(node->getLine(), "Found dead code after branch", + ""); + mNoStatementsAfterBranchFailed = true; + } + } +} + +void ValidateAST::visitStructOrInterfaceBlockDeclaration(const TType &type, + const TSourceLoc &location) +{ + if (type.getStruct() == nullptr && type.getInterfaceBlock() == nullptr) + { + return; + } + + // Make sure the structure or interface block is not doubly defined. + ImmutableString typeName(""); + const TFieldListCollection *namedStructOrBlock = getStructOrInterfaceBlock(type, &typeName); + + // Recurse the fields of the structure or interface block and check members of structure type. + // This is done before visiting the struct itself, because if the fields refer to a struct with + // the same name, they would be referencing the struct declared in an outer scope. + { + // Note that structOrBlock was previously only set for named structures, so make sure + // nameless structs are also recursed. + const TFieldListCollection *structOrBlock = namedStructOrBlock; + if (structOrBlock == nullptr) + { + structOrBlock = type.getStruct(); + } + ASSERT(structOrBlock != nullptr); + + for (const TField *field : structOrBlock->fields()) + { + visitStructUsage(*field->type(), field->line()); + } + } + + if (namedStructOrBlock) + { + ASSERT(!typeName.empty()); + // Structures are not allowed to be doubly defined + if (type.getStruct() == nullptr) + { + // Allow interfaces to be doubly-defined. + std::string name(typeName.data()); + + if (IsShaderIn(type.getQualifier())) + { + typeName = ImmutableString(name + ""); + } + else if (IsShaderOut(type.getQualifier())) + { + typeName = ImmutableString(name + ""); + } + else if (IsStorageBuffer(type.getQualifier())) + { + typeName = ImmutableString(name + ""); + } + else if (type.getQualifier() == EvqUniform) + { + typeName = ImmutableString(name + ""); + } + } + + if (mStructsAndBlocksByName.back().find(typeName) != mStructsAndBlocksByName.back().end()) + { + mDiagnostics->error(location, + "Found redeclaration of struct or interface block with the same " + "name in the same scope ", + typeName.data()); + mStructUsageFailed = true; + } + else + { + // First encounter. + mStructsAndBlocksByName.back()[typeName] = namedStructOrBlock; + } + } +} + +void ValidateAST::visitStructUsage(const TType &type, const TSourceLoc &location) +{ + if (type.getStruct() == nullptr) + { + return; + } + + // Make sure the structure being referenced has the same pointer as the closest (in scope) + // definition. + const TStructure *structure = type.getStruct(); + const ImmutableString &typeName = structure->name(); + + bool foundDeclaration = false; + for (size_t scopeIndex = mStructsAndBlocksByName.size(); scopeIndex > 0; --scopeIndex) + { + const std::map &scopeDecls = + mStructsAndBlocksByName[scopeIndex - 1]; + + auto iter = scopeDecls.find(typeName); + if (iter != scopeDecls.end()) + { + foundDeclaration = true; + + if (iter->second != structure) + { + mDiagnostics->error(location, + "Found reference to struct or interface block with doubly " + "created type ", + typeName.data()); + mStructUsageFailed = true; + } + + break; + } + } + + if (!foundDeclaration) + { + mDiagnostics->error(location, + "Found reference to struct or interface block with no declaration " + "", + typeName.data()); + mStructUsageFailed = true; + } +} + +void ValidateAST::visitBuiltInFunction(TIntermOperator *node, const TFunction *function) +{ + const TOperator op = node->getOp(); + if (!BuiltInGroup::IsBuiltIn(op)) + { + return; + } + + ImmutableStringBuilder opValueBuilder(16); + opValueBuilder << "op: "; + opValueBuilder.appendDecimal(op); + + ImmutableString opValue = opValueBuilder; + + if (function == nullptr) + { + mDiagnostics->error(node->getLine(), + "Found node calling built-in without a reference to the built-in " + "function ", + opValue.data()); + mVariableReferencesFailed = true; + } + else if (function->getBuiltInOp() != op) + { + mDiagnostics->error(node->getLine(), + "Found node calling built-in with a reference to a different function " + "", + opValue.data()); + mVariableReferencesFailed = true; + } +} + +void ValidateAST::visitFunctionCall(TIntermAggregate *node) +{ + if (node->getOp() != EOpCallFunctionInAST) + { + return; + } + + const TFunction *function = node->getFunction(); + + if (function == nullptr) + { + mDiagnostics->error(node->getLine(), + "Found node calling function without a reference to it", + ""); + mFunctionCallFailed = true; + } + else if (mDeclaredFunctions.find(function) == mDeclaredFunctions.end()) + { + mDiagnostics->error(node->getLine(), + "Found node calling previously undeclared function " + "", + function->name().data()); + mFunctionCallFailed = true; + } +} + +void ValidateAST::validateExpressionTypeBinary(TIntermBinary *node) +{ + switch (node->getOp()) + { + case EOpIndexDirect: + case EOpIndexIndirect: + { + TType expectedType(node->getLeft()->getType()); + if (!expectedType.isArray()) + { + // TODO: Validate matrix column selection and vector component selection. + // http://anglebug.com/2733 + break; + } + + expectedType.toArrayElementType(); + + if (!IsSameType(node->getType(), expectedType)) + { + const TSymbol *symbol = expectedType.getStruct(); + if (symbol == nullptr) + { + symbol = expectedType.getInterfaceBlock(); + } + const char *name = nullptr; + if (symbol) + { + name = symbol->name().data(); + } + else if (expectedType.isScalar()) + { + name = ""; + } + else if (expectedType.isVector()) + { + name = ""; + } + else + { + ASSERT(expectedType.isMatrix()); + name = ""; + } + + mDiagnostics->error( + node->getLine(), + "Found index node with type that is inconsistent with the array being indexed " + "", + name); + mExpressionTypesFailed = true; + } + } + break; + default: + // TODO: Validate other expressions. http://anglebug.com/2733 + break; + } + + switch (node->getOp()) + { + case EOpIndexDirect: + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: + if (node->getRight()->getAsConstantUnion() == nullptr) + { + mDiagnostics->error(node->getLine(), + "Found direct index node with a non-constant index", + ""); + mExpressionTypesFailed = true; + } + break; + default: + break; + } +} + +void ValidateAST::validateExpressionTypeSwitch(TIntermSwitch *node) +{ + const TType &selectorType = node->getInit()->getType(); + + if (selectorType.getBasicType() != EbtYuvCscStandardEXT && + selectorType.getBasicType() != EbtInt && selectorType.getBasicType() != EbtUInt) + { + mDiagnostics->error(node->getLine(), "Found switch selector expression that is not integer", + ""); + mExpressionTypesFailed = true; + } + else if (!selectorType.isScalar()) + { + mDiagnostics->error(node->getLine(), "Found switch selector expression that is not scalar", + ""); + mExpressionTypesFailed = true; + } +} + +void ValidateAST::visitVariableNeedingDeclaration(TIntermSymbol *node) +{ + const TVariable *variable = &node->variable(); + const TType &type = node->getType(); + + // If it's a reference to a field of a nameless interface block, match it by index and name. + if (type.getInterfaceBlock() && !type.isInterfaceBlock()) + { + const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + const TFieldList &fieldList = interfaceBlock->fields(); + const size_t fieldIndex = type.getInterfaceBlockFieldIndex(); + + if (mNamelessInterfaceBlocks.count(interfaceBlock) == 0) + { + mDiagnostics->error(node->getLine(), + "Found reference to undeclared or inconsistenly transformed " + "nameless interface block ", + node->getName().data()); + mVariableReferencesFailed = true; + } + else if (fieldIndex >= fieldList.size() || node->getName() != fieldList[fieldIndex]->name()) + { + mDiagnostics->error(node->getLine(), + "Found reference to inconsistenly transformed nameless " + "interface block field ", + node->getName().data()); + mVariableReferencesFailed = true; + } + return; + } + + const bool isStructDeclaration = + type.isStructSpecifier() && variable->symbolType() == SymbolType::Empty; + + if (!isStructDeclaration && !isVariableDeclared(variable)) + { + mDiagnostics->error(node->getLine(), + "Found reference to undeclared or inconsistently transformed " + "variable ", + node->getName().data()); + mVariableReferencesFailed = true; + } +} + +void ValidateAST::visitBuiltInVariable(TIntermSymbol *node) +{ + const TVariable *variable = &node->variable(); + ImmutableString name = variable->name(); + + if (mOptions.validateVariableReferences) + { + auto iter = mReferencedBuiltIns.find(name); + if (iter == mReferencedBuiltIns.end()) + { + mReferencedBuiltIns[name] = variable; + return; + } + + if (variable != iter->second) + { + mDiagnostics->error( + node->getLine(), + "Found inconsistent references to built-in variable ", + name.data()); + mVariableReferencesFailed = true; + } + } + + if (mOptions.validateQualifiers) + { + TQualifier qualifier = variable->getType().getQualifier(); + + if ((name == "gl_ClipDistance" && qualifier != EvqClipDistance) || + (name == "gl_CullDistance" && qualifier != EvqCullDistance) || + (name == "gl_LastFragData" && qualifier != EvqLastFragData)) + { + mDiagnostics->error( + node->getLine(), + "Incorrect qualifier applied to redeclared built-in ", + name.data()); + mQualifiersFailed = true; + } + } +} + +void ValidateAST::scope(Visit visit) +{ + if (mOptions.validateVariableReferences) + { + if (visit == PreVisit) + { + mDeclaredVariables.push_back({}); + } + else if (visit == PostVisit) + { + mDeclaredVariables.pop_back(); + } + } + + if (mOptions.validateStructUsage) + { + if (visit == PreVisit) + { + mStructsAndBlocksByName.push_back({}); + } + else if (visit == PostVisit) + { + mStructsAndBlocksByName.pop_back(); + } + } +} + +bool ValidateAST::isVariableDeclared(const TVariable *variable) +{ + ASSERT(mOptions.validateVariableReferences); + + for (const std::set &scopeVariables : mDeclaredVariables) + { + if (scopeVariables.count(variable) > 0) + { + return true; + } + } + + return false; +} + +bool ValidateAST::variableNeedsDeclaration(const TVariable *variable) +{ + // Don't expect declaration for built-in variables. + if (gl::IsBuiltInName(variable->name().data())) + { + return false; + } + + // Additionally, don't expect declaration for Vulkan specialization constants if not enabled. + // The declaration of these variables is deferred. + if (variable->getType().getQualifier() == EvqSpecConst) + { + return mOptions.validateSpecConstReferences; + } + + return true; +} + +const TFieldListCollection *ValidateAST::getStructOrInterfaceBlock(const TType &type, + ImmutableString *typeNameOut) +{ + const TStructure *structure = type.getStruct(); + const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + + ASSERT(structure != nullptr || interfaceBlock != nullptr); + + // Make sure the structure or interface block is not doubly defined. + const TFieldListCollection *structOrBlock = nullptr; + if (structure != nullptr && structure->symbolType() != SymbolType::Empty) + { + structOrBlock = structure; + *typeNameOut = structure->name(); + } + else if (interfaceBlock != nullptr) + { + structOrBlock = interfaceBlock; + *typeNameOut = interfaceBlock->name(); + } + + return structOrBlock; +} + +void ValidateAST::expectNonNullChildren(Visit visit, TIntermNode *node, size_t least_count) +{ + if (visit == PreVisit && mOptions.validateNullNodes) + { + size_t childCount = node->getChildCount(); + if (childCount < least_count) + { + mDiagnostics->error(node->getLine(), "Too few children", ""); + mNullNodesFailed = true; + } + + for (size_t i = 0; i < childCount; ++i) + { + if (node->getChildNode(i) == nullptr) + { + mDiagnostics->error(node->getLine(), "Found nullptr child", ""); + mNullNodesFailed = true; + } + } + } +} + +void ValidateAST::visitSymbol(TIntermSymbol *node) +{ + visitNode(PreVisit, node); + + const TVariable *variable = &node->variable(); + + if (mOptions.validateVariableReferences) + { + if (variableNeedsDeclaration(variable)) + { + visitVariableNeedingDeclaration(node); + } + } + + const bool isBuiltIn = gl::IsBuiltInName(variable->name().data()); + if (isBuiltIn) + { + visitBuiltInVariable(node); + } + + if (mOptions.validatePrecision) + { + if (!isBuiltIn && IsPrecisionApplicableToType(node->getBasicType()) && + node->getType().getPrecision() == EbpUndefined) + { + // Note that some built-ins don't have a precision. + mDiagnostics->error(node->getLine(), + "Found symbol with undefined precision ", + variable->name().data()); + mPrecisionFailed = true; + } + } +} + +void ValidateAST::visitConstantUnion(TIntermConstantUnion *node) +{ + visitNode(PreVisit, node); +} + +bool ValidateAST::visitSwizzle(Visit visit, TIntermSwizzle *node) +{ + visitNode(visit, node); + + if (mOptions.validateNoSwizzleOfSwizzle) + { + if (node->getOperand()->getAsSwizzleNode() != nullptr) + { + mDiagnostics->error(node->getLine(), "Found swizzle applied to swizzle", + ""); + mNoSwizzleOfSwizzleFailed = true; + } + } + + return true; +} + +bool ValidateAST::visitBinary(Visit visit, TIntermBinary *node) +{ + visitNode(visit, node); + + if (mOptions.validateExpressionTypes && visit == PreVisit) + { + validateExpressionTypeBinary(node); + } + + return true; +} + +bool ValidateAST::visitUnary(Visit visit, TIntermUnary *node) +{ + visitNode(visit, node); + + if (visit == PreVisit && mOptions.validateBuiltInOps) + { + visitBuiltInFunction(node, node->getFunction()); + } + + return true; +} + +bool ValidateAST::visitTernary(Visit visit, TIntermTernary *node) +{ + visitNode(visit, node); + return true; +} + +bool ValidateAST::visitIfElse(Visit visit, TIntermIfElse *node) +{ + visitNode(visit, node); + return true; +} + +bool ValidateAST::visitSwitch(Visit visit, TIntermSwitch *node) +{ + visitNode(visit, node); + + if (mOptions.validateExpressionTypes && visit == PreVisit) + { + validateExpressionTypeSwitch(node); + } + + return true; +} + +bool ValidateAST::visitCase(Visit visit, TIntermCase *node) +{ + // Case is allowed to come after a branch, and for dead-code-elimination purposes acts as if a + // new block is started. + mIsBranchVisitedInBlock = false; + + visitNode(visit, node); + + return true; +} + +void ValidateAST::visitFunctionPrototype(TIntermFunctionPrototype *node) +{ + visitNode(PreVisit, node); + + if (mOptions.validateFunctionCall) + { + const TFunction *function = node->getFunction(); + mDeclaredFunctions.insert(function); + } + + const TFunction *function = node->getFunction(); + const TType &returnType = function->getReturnType(); + if (mOptions.validatePrecision && IsPrecisionApplicableToType(returnType.getBasicType()) && + returnType.getPrecision() == EbpUndefined) + { + mDiagnostics->error( + node->getLine(), + "Found function with undefined precision on return value ", + function->name().data()); + mPrecisionFailed = true; + } + + if (mOptions.validateStructUsage) + { + if (returnType.isStructSpecifier()) + { + visitStructOrInterfaceBlockDeclaration(returnType, node->getLine()); + } + else + { + visitStructUsage(returnType, node->getLine()); + } + } + + for (size_t paramIndex = 0; paramIndex < function->getParamCount(); ++paramIndex) + { + const TVariable *param = function->getParam(paramIndex); + const TType ¶mType = param->getType(); + + if (mOptions.validateStructUsage) + { + visitStructUsage(paramType, node->getLine()); + } + + if (mOptions.validateQualifiers) + { + TQualifier qualifier = paramType.getQualifier(); + if (qualifier != EvqParamIn && qualifier != EvqParamOut && qualifier != EvqParamInOut && + qualifier != EvqParamConst) + { + mDiagnostics->error(node->getLine(), + "Found function prototype with an invalid qualifier " + "", + param->name().data()); + mQualifiersFailed = true; + } + + if (IsOpaqueType(paramType.getBasicType()) && qualifier != EvqParamIn) + { + mDiagnostics->error( + node->getLine(), + "Found function prototype with an invalid qualifier on opaque parameter " + "", + param->name().data()); + mQualifiersFailed = true; + } + } + + if (mOptions.validatePrecision && IsPrecisionApplicableToType(paramType.getBasicType()) && + paramType.getPrecision() == EbpUndefined) + { + mDiagnostics->error( + node->getLine(), + "Found function parameter with undefined precision ", + param->name().data()); + mPrecisionFailed = true; + } + } +} + +bool ValidateAST::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) +{ + visitNode(visit, node); + scope(visit); + + if (mOptions.validateVariableReferences && visit == PreVisit) + { + const TFunction *function = node->getFunction(); + + size_t paramCount = function->getParamCount(); + for (size_t paramIndex = 0; paramIndex < paramCount; ++paramIndex) + { + const TVariable *variable = function->getParam(paramIndex); + + if (isVariableDeclared(variable)) + { + mDiagnostics->error(node->getLine(), + "Found two declarations of the same function argument " + "", + variable->name().data()); + mVariableReferencesFailed = true; + break; + } + + mDeclaredVariables.back().insert(variable); + } + } + + return true; +} + +bool ValidateAST::visitAggregate(Visit visit, TIntermAggregate *node) +{ + visitNode(visit, node); + expectNonNullChildren(visit, node, 0); + + if (visit == PreVisit && mOptions.validateBuiltInOps) + { + visitBuiltInFunction(node, node->getFunction()); + } + + if (visit == PreVisit && mOptions.validateFunctionCall) + { + visitFunctionCall(node); + } + + if (visit == PreVisit && mOptions.validateNoRawFunctionCalls) + { + if (node->getOp() == EOpCallInternalRawFunction) + { + mDiagnostics->error(node->getLine(), + "Found node calling a raw function (deprecated) " + "", + node->getFunction()->name().data()); + mNoRawFunctionCallsFailed = true; + } + } + + return true; +} + +bool ValidateAST::visitBlock(Visit visit, TIntermBlock *node) +{ + visitNode(visit, node); + scope(visit); + expectNonNullChildren(visit, node, 0); + + if (visit == PostVisit) + { + // If the parent is a block and mIsBranchVisitedInBlock is set, this is a nested block + // without any condition (like if, loop or switch), so the rest of the parent block is also + // dead code. Otherwise the parent block can contain code after this. + if (getParentNode() == nullptr || getParentNode()->getAsBlock() == nullptr) + { + mIsBranchVisitedInBlock = false; + } + } + + return true; +} + +bool ValidateAST::visitGlobalQualifierDeclaration(Visit visit, + TIntermGlobalQualifierDeclaration *node) +{ + visitNode(visit, node); + + const TVariable *variable = &node->getSymbol()->variable(); + + if (mOptions.validateVariableReferences && variableNeedsDeclaration(variable)) + { + if (!isVariableDeclared(variable)) + { + mDiagnostics->error(node->getLine(), + "Found reference to undeclared or inconsistently transformed " + "variable ", + variable->name().data()); + mVariableReferencesFailed = true; + } + } + return true; +} + +bool ValidateAST::visitDeclaration(Visit visit, TIntermDeclaration *node) +{ + visitNode(visit, node); + expectNonNullChildren(visit, node, 0); + + const TIntermSequence &sequence = *(node->getSequence()); + + if (mOptions.validateMultiDeclarations && sequence.size() > 1) + { + TIntermSymbol *symbol = sequence[1]->getAsSymbolNode(); + if (symbol == nullptr) + { + TIntermBinary *init = sequence[1]->getAsBinaryNode(); + ASSERT(init && init->getOp() == EOpInitialize); + symbol = init->getLeft()->getAsSymbolNode(); + } + ASSERT(symbol); + + mDiagnostics->error(node->getLine(), + "Found multiple declarations where SeparateDeclarations should have " + "separated them ", + symbol->variable().name().data()); + mMultiDeclarationsFailed = true; + } + + if (visit == PreVisit) + { + bool validateStructUsage = mOptions.validateStructUsage; + + for (TIntermNode *instance : sequence) + { + TIntermSymbol *symbol = instance->getAsSymbolNode(); + if (symbol == nullptr) + { + TIntermBinary *init = instance->getAsBinaryNode(); + ASSERT(init && init->getOp() == EOpInitialize); + symbol = init->getLeft()->getAsSymbolNode(); + } + ASSERT(symbol); + + const TVariable *variable = &symbol->variable(); + const TType &type = variable->getType(); + + if (mOptions.validateVariableReferences) + { + if (isVariableDeclared(variable)) + { + mDiagnostics->error( + node->getLine(), + "Found two declarations of the same variable ", + variable->name().data()); + mVariableReferencesFailed = true; + break; + } + + mDeclaredVariables.back().insert(variable); + + const TInterfaceBlock *interfaceBlock = variable->getType().getInterfaceBlock(); + + if (variable->symbolType() == SymbolType::Empty && interfaceBlock != nullptr) + { + // Nameless interface blocks can only be declared at the top level. Their + // fields are matched by field index, and then verified to match by name. + // Conflict in names should have already generated a compile error. + ASSERT(mDeclaredVariables.size() == 1); + ASSERT(mNamelessInterfaceBlocks.count(interfaceBlock) == 0); + + mNamelessInterfaceBlocks.insert(interfaceBlock); + } + } + + if (validateStructUsage) + { + // Only declare and/or validate the struct once. + validateStructUsage = false; + + if (type.isStructSpecifier() || type.isInterfaceBlock()) + { + visitStructOrInterfaceBlockDeclaration(type, node->getLine()); + } + else + { + visitStructUsage(type, node->getLine()); + } + } + + if (gl::IsBuiltInName(variable->name().data())) + { + visitBuiltInVariable(symbol); + } + + if (mOptions.validatePrecision && (type.isStructSpecifier() || type.isInterfaceBlock())) + { + const TFieldListCollection *structOrBlock = type.getStruct(); + if (structOrBlock == nullptr) + { + structOrBlock = type.getInterfaceBlock(); + } + + for (const TField *field : structOrBlock->fields()) + { + const TType *fieldType = field->type(); + if (IsPrecisionApplicableToType(fieldType->getBasicType()) && + fieldType->getPrecision() == EbpUndefined) + { + mDiagnostics->error( + node->getLine(), + "Found block field with undefined precision ", + field->name().data()); + mPrecisionFailed = true; + } + } + } + } + } + + return true; +} + +bool ValidateAST::visitLoop(Visit visit, TIntermLoop *node) +{ + visitNode(visit, node); + return true; +} + +bool ValidateAST::visitBranch(Visit visit, TIntermBranch *node) +{ + visitNode(visit, node); + + if (visit == PostVisit) + { + mIsBranchVisitedInBlock = true; + } + + return true; +} + +void ValidateAST::visitPreprocessorDirective(TIntermPreprocessorDirective *node) +{ + visitNode(PreVisit, node); +} + +bool ValidateAST::validateInternal() +{ + return !mSingleParentFailed && !mVariableReferencesFailed && !mBuiltInOpsFailed && + !mFunctionCallFailed && !mNoRawFunctionCallsFailed && !mNullNodesFailed && + !mQualifiersFailed && !mPrecisionFailed && !mStructUsageFailed && + !mExpressionTypesFailed && !mMultiDeclarationsFailed && !mNoSwizzleOfSwizzleFailed && + !mNoStatementsAfterBranchFailed; +} + +} // anonymous namespace + +bool ValidateAST(TIntermNode *root, TDiagnostics *diagnostics, const ValidateASTOptions &options) +{ + // ValidateAST is called after transformations, so if |validateNoMoreTransformations| is set, + // it's immediately an error. + if (options.validateNoMoreTransformations) + { + diagnostics->error(kNoSourceLoc, "Unexpected transformation after AST post-processing", + ""); + return false; + } + + return ValidateAST::validate(root, diagnostics, options); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateAST.h b/gfx/angle/checkout/src/compiler/translator/ValidateAST.h new file mode 100644 index 0000000000..2fa73db9fb --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateAST.h @@ -0,0 +1,108 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_VALIDATEAST_H_ +#define COMPILER_TRANSLATOR_VALIDATEAST_H_ + +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/Common.h" + +namespace sh +{ +class TDiagnostics; +class TIntermNode; + +// The following options (stored in Compiler) tell the validator what to validate. Some validations +// are conditional to certain passes. +struct ValidateASTOptions +{ + // TODO: add support for the flags marked with TODO. http://anglebug.com/2733 + + // Check that every node always has only one parent, + bool validateSingleParent = true; + // Check that all symbols reference TVariables that have been declared. For built-ins, this + // makes sure that the same GLSL built-in uses the same TVariable consistently. + bool validateVariableReferences = true; + // Whether validateVariableReferences should also include specialization constants. Their + // declaration is output after their usage is discovered, so this is disabled until then. + bool validateSpecConstReferences = false; + // Check that TIntermUnary and TIntermAggregate nodes with a built-in op reference a function + // with said op. + bool validateBuiltInOps = true; + // Check that all EOpCallFunctionInAST have their corresponding function definitions in the AST, + // with matching symbol ids. There should also be at least a prototype declaration before the + // function is called. + bool validateFunctionCall = true; + // Check that EOpCallInternalRawFunction is not used. This OP is deprecated and needs to be + // removed. http://anglebug.com/6059 + bool validateNoRawFunctionCalls = true; + // Check that there are no null nodes where they are not allowed, for example as children of + // TIntermDeclaration or TIntermBlock. + bool validateNullNodes = true; + // Check that symbols that reference variables have consistent qualifiers and symbol ids with + // the variable declaration. The following needs to be validated: + // + // Implemented: + // + // - Function parameters having one of EvqParam* qualifiers. + // - No const qualifier on opaque function parameters. + // - gl_ClipDistance, gl_CullDistance and gl_LastFragData are correctly qualified even when + // redeclared in the shader. + // + // TODO: + // + // - Function-local variables must have the EvqTemporary qualifier. + // - Symbol references and declarations have identical qualifiers. + bool validateQualifiers = true; + // Check that every symbol has its precision specified. That includes variables, block members, + // function parameters and return values. + bool validatePrecision = true; + // Check that variable declarations that can't have initializers don't have initializers + // (varyings, uniforms for example). + bool validateInitializers = true; // TODO + // Check that there is only one TFunction with each function name referenced in the nodes (no + // two TFunctions with the same name, taking internal/non-internal namespaces into account). + bool validateUniqueFunctions = true; // TODO + // Check that references to structs are matched with the corresponding struct declaration. + bool validateStructUsage = true; + // Check that expression nodes have the correct type considering their operand(s). The + // following validation is possible: + // + // Implemented: + // + // - Binary node that indexes T[] should have type T + // - Binary nodes with EOpIndexDirect* should have a constant as the right node + // - Switch nodes should have an integer type in the selector + // + // TODO: + // + // - Function calls (including built-ins) have the same return type in the node and function. + // - Unary and binary operators have the correct type based on operands + // - Swizzle result has same type as the operand except for vector size + // - Ternary operator has the same type as the operands + // - Case expressions have the same type as the switch selector + bool validateExpressionTypes = true; + // If SeparateDeclarations has been run, check for the absence of multi declarations as well. + bool validateMultiDeclarations = false; + // If PruneNoOps has been run, check that no statements are ever added after branches in the + // same block. Those statements would be dead code. + bool validateNoStatementsAfterBranch = false; + // Check that swizzle is not applied to swizzle. Swizzles of swizzles are folded in + // TIntermSwizzle::fold. + bool validateNoSwizzleOfSwizzle = true; + + // Once set, disallows any further transformations on the tree. Used before AST post-processing + // which requires that the tree remains unmodified. + bool validateNoMoreTransformations = false; +}; + +// Check for errors and output error messages on the context. +// Returns true if there are no errors. +bool ValidateAST(TIntermNode *root, TDiagnostics *diagnostics, const ValidateASTOptions &options); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_VALIDATESWITCH_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateBarrierFunctionCall.cpp b/gfx/angle/checkout/src/compiler/translator/ValidateBarrierFunctionCall.cpp new file mode 100644 index 0000000000..c36406ea59 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateBarrierFunctionCall.cpp @@ -0,0 +1,100 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ValidateBarrierFunctionCalls: +// Runs compilation checks related to the "barrier built-in function. + +#include "compiler/translator/ValidateBarrierFunctionCall.h" + +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ +namespace +{ +class Traverser : public TIntermTraverser +{ + public: + Traverser(TDiagnostics *diagnostics) + : TIntermTraverser(true, false, true), mDiagnostics(diagnostics) + {} + + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override + { + if (!node->getFunction()->isMain()) + { + return false; + } + + mInMain = visit == PreVisit; + return true; + } + + bool visitBranch(Visit visit, TIntermBranch *branch) override + { + if (branch->getFlowOp() == EOpReturn) + { + mSeenReturn = true; + } + + return true; + } + + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + if (node->getOp() != EOpBarrierTCS) + { + return true; + } + + if (mSeenReturn) + { + mDiagnostics->error(node->getLine(), + "barrier() may not be called at any point after a return statement " + "in the function main().", + "barrier"); + mValid = false; + return false; + } + + // TODO(anglebug.com/5557): Determine if we should check loops as well. + if (mBranchCount > 0) + { + mDiagnostics->error( + node->getLine(), + "barrier() may not be called in potentially divergent flow control.", "barrier"); + mValid = false; + return false; + } + + return true; + } + + bool visitIfElse(Visit visit, TIntermIfElse *node) override + { + mBranchCount += ((visit == PreVisit) ? 1 : -1); + return true; + } + + bool valid() const { return mValid; } + + private: + TDiagnostics *mDiagnostics = nullptr; + bool mInMain = false; + bool mSeenReturn = false; + bool mValid = true; + uint32_t mBranchCount = 0; +}; +} // anonymous namespace + +bool ValidateBarrierFunctionCall(TIntermBlock *root, TDiagnostics *diagnostics) +{ + Traverser traverser(diagnostics); + root->traverse(&traverser); + return traverser.valid(); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateBarrierFunctionCall.h b/gfx/angle/checkout/src/compiler/translator/ValidateBarrierFunctionCall.h new file mode 100644 index 0000000000..6b91eb456a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateBarrierFunctionCall.h @@ -0,0 +1,22 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ValidateBarrierFunctionCalls: +// Runs compilation checks related to the "barrier built-in function. + +#ifndef COMPILER_TRANSLATOR_VALIDATEBARRIERFUNCTIONCALL_H_ +#define COMPILER_TRANSLATOR_VALIDATEBARRIERFUNCTIONCALL_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TDiagnostics; +class TIntermBlock; + +[[nodiscard]] bool ValidateBarrierFunctionCall(TIntermBlock *root, TDiagnostics *diagnostics); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_VALIDATEBARRIERFUNCTIONCALL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateClipCullDistance.cpp b/gfx/angle/checkout/src/compiler/translator/ValidateClipCullDistance.cpp new file mode 100644 index 0000000000..3ecd8b4295 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateClipCullDistance.cpp @@ -0,0 +1,200 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// The ValidateClipCullDistance function checks if the sum of array sizes for gl_ClipDistance and +// gl_CullDistance exceeds gl_MaxCombinedClipAndCullDistances +// + +#include "ValidateClipCullDistance.h" + +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics) +{ + diagnostics->error(symbol.getLine(), reason, symbol.getName().data()); +} + +class ValidateClipCullDistanceTraverser : public TIntermTraverser +{ + public: + ValidateClipCullDistanceTraverser(); + void validate(TDiagnostics *diagnostics, const unsigned int maxCombinedClipAndCullDistances); + + private: + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; + bool visitBinary(Visit visit, TIntermBinary *node) override; + + unsigned int mClipDistanceSize; + unsigned int mCullDistanceSize; + + unsigned int mMaxClipDistanceIndex; + unsigned int mMaxCullDistanceIndex; + + const TIntermSymbol *mClipDistance; + const TIntermSymbol *mCullDistance; +}; + +ValidateClipCullDistanceTraverser::ValidateClipCullDistanceTraverser() + : TIntermTraverser(true, false, false), + mClipDistanceSize(0), + mCullDistanceSize(0), + mMaxClipDistanceIndex(0), + mMaxCullDistanceIndex(0), + mClipDistance(nullptr), + mCullDistance(nullptr) +{} + +bool ValidateClipCullDistanceTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) +{ + const TIntermSequence &sequence = *(node->getSequence()); + + if (sequence.size() != 1) + { + return true; + } + + const TIntermSymbol *symbol = sequence.front()->getAsSymbolNode(); + if (symbol == nullptr) + { + return true; + } + + if (symbol->getName() == "gl_ClipDistance") + { + mClipDistanceSize = symbol->getOutermostArraySize(); + mClipDistance = symbol; + } + else if (symbol->getName() == "gl_CullDistance") + { + mCullDistanceSize = symbol->getOutermostArraySize(); + mCullDistance = symbol; + } + + return true; +} + +bool ValidateClipCullDistanceTraverser::visitBinary(Visit visit, TIntermBinary *node) +{ + TOperator op = node->getOp(); + if (op != EOpIndexDirect && op != EOpIndexIndirect) + { + return true; + } + + TIntermSymbol *left = node->getLeft()->getAsSymbolNode(); + if (!left) + { + return true; + } + + ImmutableString varName(left->getName()); + if (varName != "gl_ClipDistance" && varName != "gl_CullDistance") + { + return true; + } + + const TConstantUnion *constIdx = node->getRight()->getConstantValue(); + if (constIdx) + { + unsigned int idx = 0; + switch (constIdx->getType()) + { + case EbtInt: + idx = constIdx->getIConst(); + break; + case EbtUInt: + idx = constIdx->getUConst(); + break; + case EbtFloat: + idx = static_cast(constIdx->getFConst()); + break; + case EbtBool: + idx = constIdx->getBConst() ? 1 : 0; + break; + default: + UNREACHABLE(); + break; + } + + if (varName == "gl_ClipDistance") + { + if (idx > mMaxClipDistanceIndex) + { + mMaxClipDistanceIndex = idx; + if (!mClipDistance) + { + mClipDistance = left; + } + } + } + else + { + ASSERT(varName == "gl_CullDistance"); + if (idx > mMaxCullDistanceIndex) + { + mMaxCullDistanceIndex = idx; + if (!mCullDistance) + { + mCullDistance = left; + } + } + } + } + + return true; +} + +void ValidateClipCullDistanceTraverser::validate(TDiagnostics *diagnostics, + const unsigned int maxCombinedClipAndCullDistances) +{ + ASSERT(diagnostics); + + unsigned int enabledClipDistances = + (mClipDistanceSize > 0 ? mClipDistanceSize + : (mClipDistance ? mMaxClipDistanceIndex + 1 : 0)); + unsigned int enabledCullDistances = + (mCullDistanceSize > 0 ? mCullDistanceSize + : (mCullDistance ? mMaxCullDistanceIndex + 1 : 0)); + unsigned int combinedClipAndCullDistances = + (enabledClipDistances > 0 && enabledCullDistances > 0 + ? enabledClipDistances + enabledCullDistances + : 0); + + if (combinedClipAndCullDistances > maxCombinedClipAndCullDistances) + { + const TIntermSymbol *greaterSymbol = + (enabledClipDistances >= enabledCullDistances ? mClipDistance : mCullDistance); + + std::stringstream strstr = sh::InitializeStream(); + strstr << "The sum of 'gl_ClipDistance' and 'gl_CullDistance' size is greater than " + "gl_MaxCombinedClipAndCullDistances (" + << combinedClipAndCullDistances << " > " << maxCombinedClipAndCullDistances << ")"; + error(*greaterSymbol, strstr.str().c_str(), diagnostics); + } +} + +} // anonymous namespace + +bool ValidateClipCullDistance(TIntermBlock *root, + TDiagnostics *diagnostics, + const unsigned int maxCombinedClipAndCullDistances) +{ + ValidateClipCullDistanceTraverser varyingValidator; + root->traverse(&varyingValidator); + int numErrorsBefore = diagnostics->numErrors(); + varyingValidator.validate(diagnostics, maxCombinedClipAndCullDistances); + return (diagnostics->numErrors() == numErrorsBefore); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateClipCullDistance.h b/gfx/angle/checkout/src/compiler/translator/ValidateClipCullDistance.h new file mode 100644 index 0000000000..31ea890cd7 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateClipCullDistance.h @@ -0,0 +1,27 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// The ValidateClipCullDistance function checks if the sum of array sizes for gl_ClipDistance and +// gl_CullDistance exceeds gl_MaxCombinedClipAndCullDistances +// + +#ifndef COMPILER_TRANSLATOR_VALIDATECLIPCULLDISTANCE_H_ +#define COMPILER_TRANSLATOR_VALIDATECLIPCULLDISTANCE_H_ + +#include "GLSLANG/ShaderVars.h" + +namespace sh +{ + +class TIntermBlock; +class TDiagnostics; + +bool ValidateClipCullDistance(TIntermBlock *root, + TDiagnostics *diagnostics, + const unsigned int maxCombinedClipAndCullDistances); + +} // namespace sh + +#endif diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateGlobalInitializer.cpp b/gfx/angle/checkout/src/compiler/translator/ValidateGlobalInitializer.cpp new file mode 100644 index 0000000000..126e8d7854 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateGlobalInitializer.cpp @@ -0,0 +1,157 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/ValidateGlobalInitializer.h" + +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +const int kMaxAllowedTraversalDepth = 256; + +class ValidateGlobalInitializerTraverser : public TIntermTraverser +{ + public: + ValidateGlobalInitializerTraverser(int shaderVersion, + bool isWebGL, + bool hasExtNonConstGlobalInitializers); + + void visitSymbol(TIntermSymbol *node) override; + void visitConstantUnion(TIntermConstantUnion *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + bool visitBinary(Visit visit, TIntermBinary *node) override; + bool visitUnary(Visit visit, TIntermUnary *node) override; + + bool isValid() const { return mIsValid && mMaxDepth < mMaxAllowedDepth; } + bool issueWarning() const { return mIssueWarning; } + + private: + ANGLE_INLINE void onNonConstInitializerVisit(bool accept) + { + if (accept) + { + if (!mExtNonConstGlobalInitializers) + { + mIssueWarning = true; + } + } + else + { + mIsValid = false; + } + } + + int mShaderVersion; + bool mIsWebGL; + bool mExtNonConstGlobalInitializers; + bool mIsValid; + bool mIssueWarning; +}; + +void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node) +{ + // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3): + // Global initializers must be constant expressions. + switch (node->getType().getQualifier()) + { + case EvqConst: + break; + case EvqGlobal: + case EvqTemporary: + case EvqUniform: + // We allow these cases to be compatible with legacy ESSL 1.00 content. + // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal + // with. + onNonConstInitializerVisit(mExtNonConstGlobalInitializers || + ((mShaderVersion < 300) && mIsWebGL)); + break; + default: + mIsValid = false; + } +} + +void ValidateGlobalInitializerTraverser::visitConstantUnion(TIntermConstantUnion *node) +{ + // Constant unions that are not constant expressions may result from folding a ternary + // expression. + switch (node->getType().getQualifier()) + { + case EvqConst: + break; + case EvqTemporary: + onNonConstInitializerVisit(mExtNonConstGlobalInitializers || + ((mShaderVersion < 300) && mIsWebGL)); + break; + default: + UNREACHABLE(); + } +} + +bool ValidateGlobalInitializerTraverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + // Disallow calls to user-defined functions and texture lookup functions in global variable + // initializers. For simplicity, all non-math built-in calls are disallowed. + if (node->isFunctionCall() || + (BuiltInGroup::IsBuiltIn(node->getOp()) && !BuiltInGroup::IsMath(node->getOp()))) + { + onNonConstInitializerVisit(mExtNonConstGlobalInitializers); + } + return true; +} + +bool ValidateGlobalInitializerTraverser::visitBinary(Visit visit, TIntermBinary *node) +{ + if (node->isAssignment()) + { + onNonConstInitializerVisit(mExtNonConstGlobalInitializers); + } + return true; +} + +bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *node) +{ + if (node->isAssignment()) + { + onNonConstInitializerVisit(mExtNonConstGlobalInitializers); + } + return true; +} + +ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser( + int shaderVersion, + bool isWebGL, + bool hasExtNonConstGlobalInitializers) + : TIntermTraverser(true, false, false, nullptr), + mShaderVersion(shaderVersion), + mIsWebGL(isWebGL), + mExtNonConstGlobalInitializers(hasExtNonConstGlobalInitializers), + mIsValid(true), + mIssueWarning(false) +{ + setMaxAllowedDepth(kMaxAllowedTraversalDepth); +} + +} // namespace + +bool ValidateGlobalInitializer(TIntermTyped *initializer, + int shaderVersion, + bool isWebGL, + bool hasExtNonConstGlobalInitializers, + bool *warning) +{ + ValidateGlobalInitializerTraverser validate(shaderVersion, isWebGL, + hasExtNonConstGlobalInitializers); + initializer->traverse(&validate); + ASSERT(warning != nullptr); + *warning = validate.issueWarning(); + return validate.isValid(); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateGlobalInitializer.h b/gfx/angle/checkout/src/compiler/translator/ValidateGlobalInitializer.h new file mode 100644 index 0000000000..cb4b652b18 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateGlobalInitializer.h @@ -0,0 +1,24 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ +#define COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ + +namespace sh +{ + +class TIntermTyped; + +// Returns true if the initializer is valid. +bool ValidateGlobalInitializer(TIntermTyped *initializer, + int shaderVersion, + bool isWebGL, + bool hasExtNonConstGlobalInitializers, + bool *warning); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateLimitations.cpp b/gfx/angle/checkout/src/compiler/translator/ValidateLimitations.cpp new file mode 100644 index 0000000000..5ca3daca0f --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateLimitations.cpp @@ -0,0 +1,452 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/ValidateLimitations.h" + +#include "angle_gl.h" +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/ParseContext.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +int GetLoopSymbolId(TIntermLoop *loop) +{ + // Here we assume all the operations are valid, because the loop node is + // already validated before this call. + TIntermSequence *declSeq = loop->getInit()->getAsDeclarationNode()->getSequence(); + TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); + TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); + + return symbol->uniqueId().get(); +} + +// Traverses a node to check if it represents a constant index expression. +// Definition: +// constant-index-expressions are a superset of constant-expressions. +// Constant-index-expressions can include loop indices as defined in +// GLSL ES 1.0 spec, Appendix A, section 4. +// The following are constant-index-expressions: +// - Constant expressions +// - Loop indices as defined in section 4 +// - Expressions composed of both of the above +class ValidateConstIndexExpr : public TIntermTraverser +{ + public: + ValidateConstIndexExpr(const std::vector &loopSymbols) + : TIntermTraverser(true, false, false), mValid(true), mLoopSymbolIds(loopSymbols) + {} + + // Returns true if the parsed node represents a constant index expression. + bool isValid() const { return mValid; } + + void visitSymbol(TIntermSymbol *symbol) override + { + // Only constants and loop indices are allowed in a + // constant index expression. + if (mValid) + { + bool isLoopSymbol = std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(), + symbol->uniqueId().get()) != mLoopSymbolIds.end(); + mValid = (symbol->getQualifier() == EvqConst) || isLoopSymbol; + } + } + + private: + bool mValid; + const std::vector mLoopSymbolIds; +}; + +// Traverses intermediate tree to ensure that the shader does not exceed the +// minimum functionality mandated in GLSL 1.0 spec, Appendix A. +class ValidateLimitationsTraverser : public TLValueTrackingTraverser +{ + public: + ValidateLimitationsTraverser(sh::GLenum shaderType, + TSymbolTable *symbolTable, + TDiagnostics *diagnostics); + + void visitSymbol(TIntermSymbol *node) override; + bool visitBinary(Visit, TIntermBinary *) override; + bool visitLoop(Visit, TIntermLoop *) override; + + private: + void error(TSourceLoc loc, const char *reason, const char *token); + void error(TSourceLoc loc, const char *reason, const ImmutableString &token); + + bool isLoopIndex(TIntermSymbol *symbol); + bool validateLoopType(TIntermLoop *node); + + bool validateForLoopHeader(TIntermLoop *node); + // If valid, return the index symbol id; Otherwise, return -1. + int validateForLoopInit(TIntermLoop *node); + bool validateForLoopCond(TIntermLoop *node, int indexSymbolId); + bool validateForLoopExpr(TIntermLoop *node, int indexSymbolId); + + // Returns true if indexing does not exceed the minimum functionality + // mandated in GLSL 1.0 spec, Appendix A, Section 5. + bool isConstExpr(TIntermNode *node); + bool isConstIndexExpr(TIntermNode *node); + bool validateIndexing(TIntermBinary *node); + + sh::GLenum mShaderType; + TDiagnostics *mDiagnostics; + std::vector mLoopSymbolIds; +}; + +ValidateLimitationsTraverser::ValidateLimitationsTraverser(sh::GLenum shaderType, + TSymbolTable *symbolTable, + TDiagnostics *diagnostics) + : TLValueTrackingTraverser(true, false, false, symbolTable), + mShaderType(shaderType), + mDiagnostics(diagnostics) +{ + ASSERT(diagnostics); +} + +void ValidateLimitationsTraverser::visitSymbol(TIntermSymbol *node) +{ + if (isLoopIndex(node) && isLValueRequiredHere()) + { + error(node->getLine(), + "Loop index cannot be statically assigned to within the body of the loop", + node->getName()); + } +} + +bool ValidateLimitationsTraverser::visitBinary(Visit, TIntermBinary *node) +{ + // Check indexing. + switch (node->getOp()) + { + case EOpIndexDirect: + case EOpIndexIndirect: + validateIndexing(node); + break; + default: + break; + } + return true; +} + +bool ValidateLimitationsTraverser::visitLoop(Visit, TIntermLoop *node) +{ + if (!validateLoopType(node)) + return false; + + if (!validateForLoopHeader(node)) + return false; + + TIntermNode *body = node->getBody(); + if (body != nullptr) + { + mLoopSymbolIds.push_back(GetLoopSymbolId(node)); + body->traverse(this); + mLoopSymbolIds.pop_back(); + } + + // The loop is fully processed - no need to visit children. + return false; +} + +void ValidateLimitationsTraverser::error(TSourceLoc loc, const char *reason, const char *token) +{ + mDiagnostics->error(loc, reason, token); +} + +void ValidateLimitationsTraverser::error(TSourceLoc loc, + const char *reason, + const ImmutableString &token) +{ + error(loc, reason, token.data()); +} + +bool ValidateLimitationsTraverser::isLoopIndex(TIntermSymbol *symbol) +{ + return std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(), symbol->uniqueId().get()) != + mLoopSymbolIds.end(); +} + +bool ValidateLimitationsTraverser::validateLoopType(TIntermLoop *node) +{ + TLoopType type = node->getType(); + if (type == ELoopFor) + return true; + + // Reject while and do-while loops. + error(node->getLine(), "This type of loop is not allowed", type == ELoopWhile ? "while" : "do"); + return false; +} + +bool ValidateLimitationsTraverser::validateForLoopHeader(TIntermLoop *node) +{ + ASSERT(node->getType() == ELoopFor); + + // + // The for statement has the form: + // for ( init-declaration ; condition ; expression ) statement + // + int indexSymbolId = validateForLoopInit(node); + if (indexSymbolId < 0) + return false; + if (!validateForLoopCond(node, indexSymbolId)) + return false; + if (!validateForLoopExpr(node, indexSymbolId)) + return false; + + return true; +} + +int ValidateLimitationsTraverser::validateForLoopInit(TIntermLoop *node) +{ + TIntermNode *init = node->getInit(); + if (init == nullptr) + { + error(node->getLine(), "Missing init declaration", "for"); + return -1; + } + + // + // init-declaration has the form: + // type-specifier identifier = constant-expression + // + TIntermDeclaration *decl = init->getAsDeclarationNode(); + if (decl == nullptr) + { + error(init->getLine(), "Invalid init declaration", "for"); + return -1; + } + // To keep things simple do not allow declaration list. + TIntermSequence *declSeq = decl->getSequence(); + if (declSeq->size() != 1) + { + error(decl->getLine(), "Invalid init declaration", "for"); + return -1; + } + TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); + if ((declInit == nullptr) || (declInit->getOp() != EOpInitialize)) + { + error(decl->getLine(), "Invalid init declaration", "for"); + return -1; + } + TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); + if (symbol == nullptr) + { + error(declInit->getLine(), "Invalid init declaration", "for"); + return -1; + } + // The loop index has type int or float. + TBasicType type = symbol->getBasicType(); + if ((type != EbtInt) && (type != EbtUInt) && (type != EbtFloat)) + { + error(symbol->getLine(), "Invalid type for loop index", getBasicString(type)); + return -1; + } + // The loop index is initialized with constant expression. + if (!isConstExpr(declInit->getRight())) + { + error(declInit->getLine(), "Loop index cannot be initialized with non-constant expression", + symbol->getName()); + return -1; + } + + return symbol->uniqueId().get(); +} + +bool ValidateLimitationsTraverser::validateForLoopCond(TIntermLoop *node, int indexSymbolId) +{ + TIntermNode *cond = node->getCondition(); + if (cond == nullptr) + { + error(node->getLine(), "Missing condition", "for"); + return false; + } + // + // condition has the form: + // loop_index relational_operator constant_expression + // + TIntermBinary *binOp = cond->getAsBinaryNode(); + if (binOp == nullptr) + { + error(node->getLine(), "Invalid condition", "for"); + return false; + } + // Loop index should be to the left of relational operator. + TIntermSymbol *symbol = binOp->getLeft()->getAsSymbolNode(); + if (symbol == nullptr) + { + error(binOp->getLine(), "Invalid condition", "for"); + return false; + } + if (symbol->uniqueId().get() != indexSymbolId) + { + error(symbol->getLine(), "Expected loop index", symbol->getName()); + return false; + } + // Relational operator is one of: > >= < <= == or !=. + switch (binOp->getOp()) + { + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + break; + default: + error(binOp->getLine(), "Invalid relational operator", + GetOperatorString(binOp->getOp())); + break; + } + // Loop index must be compared with a constant. + if (!isConstExpr(binOp->getRight())) + { + error(binOp->getLine(), "Loop index cannot be compared with non-constant expression", + symbol->getName()); + return false; + } + + return true; +} + +bool ValidateLimitationsTraverser::validateForLoopExpr(TIntermLoop *node, int indexSymbolId) +{ + TIntermNode *expr = node->getExpression(); + if (expr == nullptr) + { + error(node->getLine(), "Missing expression", "for"); + return false; + } + + // for expression has one of the following forms: + // loop_index++ + // loop_index-- + // loop_index += constant_expression + // loop_index -= constant_expression + // ++loop_index + // --loop_index + // The last two forms are not specified in the spec, but I am assuming + // its an oversight. + TIntermUnary *unOp = expr->getAsUnaryNode(); + TIntermBinary *binOp = unOp ? nullptr : expr->getAsBinaryNode(); + + TOperator op = EOpNull; + const TFunction *opFunc = nullptr; + TIntermSymbol *symbol = nullptr; + if (unOp != nullptr) + { + op = unOp->getOp(); + opFunc = unOp->getFunction(); + symbol = unOp->getOperand()->getAsSymbolNode(); + } + else if (binOp != nullptr) + { + op = binOp->getOp(); + symbol = binOp->getLeft()->getAsSymbolNode(); + } + + // The operand must be loop index. + if (symbol == nullptr) + { + error(expr->getLine(), "Invalid expression", "for"); + return false; + } + if (symbol->uniqueId().get() != indexSymbolId) + { + error(symbol->getLine(), "Expected loop index", symbol->getName()); + return false; + } + + // The operator is one of: ++ -- += -=. + switch (op) + { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + ASSERT((unOp != nullptr) && (binOp == nullptr)); + break; + case EOpAddAssign: + case EOpSubAssign: + ASSERT((unOp == nullptr) && (binOp != nullptr)); + break; + default: + if (BuiltInGroup::IsBuiltIn(op)) + { + ASSERT(opFunc != nullptr); + error(expr->getLine(), "Invalid built-in call", opFunc->name().data()); + } + else + { + error(expr->getLine(), "Invalid operator", GetOperatorString(op)); + } + return false; + } + + // Loop index must be incremented/decremented with a constant. + if (binOp != nullptr) + { + if (!isConstExpr(binOp->getRight())) + { + error(binOp->getLine(), "Loop index cannot be modified by non-constant expression", + symbol->getName()); + return false; + } + } + + return true; +} + +bool ValidateLimitationsTraverser::isConstExpr(TIntermNode *node) +{ + ASSERT(node != nullptr); + return node->getAsConstantUnion() != nullptr && node->getAsTyped()->getQualifier() == EvqConst; +} + +bool ValidateLimitationsTraverser::isConstIndexExpr(TIntermNode *node) +{ + ASSERT(node != nullptr); + + ValidateConstIndexExpr validate(mLoopSymbolIds); + node->traverse(&validate); + return validate.isValid(); +} + +bool ValidateLimitationsTraverser::validateIndexing(TIntermBinary *node) +{ + ASSERT((node->getOp() == EOpIndexDirect) || (node->getOp() == EOpIndexIndirect)); + + bool valid = true; + TIntermTyped *index = node->getRight(); + // The index expession must be a constant-index-expression unless + // the operand is a uniform in a vertex shader. + TIntermTyped *operand = node->getLeft(); + bool skip = (mShaderType == GL_VERTEX_SHADER) && (operand->getQualifier() == EvqUniform); + if (!skip && !isConstIndexExpr(index)) + { + error(index->getLine(), "Index expression must be constant", "[]"); + valid = false; + } + return valid; +} + +} // namespace + +bool ValidateLimitations(TIntermNode *root, + GLenum shaderType, + TSymbolTable *symbolTable, + TDiagnostics *diagnostics) +{ + ValidateLimitationsTraverser validate(shaderType, symbolTable, diagnostics); + root->traverse(&validate); + return diagnostics->numErrors() == 0; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateLimitations.h b/gfx/angle/checkout/src/compiler/translator/ValidateLimitations.h new file mode 100644 index 0000000000..00f26b53f5 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateLimitations.h @@ -0,0 +1,26 @@ +// +// Copyright 2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ +#define COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ + +#include "compiler/translator/IntermNode.h" + +namespace sh +{ + +class TDiagnostics; + +// Returns true if the given shader does not exceed the minimum functionality mandated in GLSL ES +// 1.00 spec Appendix A. +bool ValidateLimitations(TIntermNode *root, + GLenum shaderType, + TSymbolTable *symbolTable, + TDiagnostics *diagnostics); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateMaxParameters.cpp b/gfx/angle/checkout/src/compiler/translator/ValidateMaxParameters.cpp new file mode 100644 index 0000000000..b3f53e27fa --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateMaxParameters.cpp @@ -0,0 +1,30 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ValidateMaxParameters checks if function definitions have more than a set number of parameters. + +#include "compiler/translator/ValidateMaxParameters.h" + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Symbol.h" + +namespace sh +{ + +bool ValidateMaxParameters(TIntermBlock *root, unsigned int maxParameters) +{ + for (TIntermNode *node : *root->getSequence()) + { + TIntermFunctionDefinition *definition = node->getAsFunctionDefinition(); + if (definition != nullptr && + definition->getFunctionPrototype()->getFunction()->getParamCount() > maxParameters) + { + return false; + } + } + return true; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateMaxParameters.h b/gfx/angle/checkout/src/compiler/translator/ValidateMaxParameters.h new file mode 100644 index 0000000000..73cdb992d3 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateMaxParameters.h @@ -0,0 +1,21 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ValidateMaxParameters checks if function definitions have more than a set number of parameters. + +#ifndef COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_ +#define COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_ + +namespace sh +{ + +class TIntermBlock; + +// Return true if valid. +bool ValidateMaxParameters(TIntermBlock *root, unsigned int maxParameters); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateOutputs.cpp b/gfx/angle/checkout/src/compiler/translator/ValidateOutputs.cpp new file mode 100644 index 0000000000..5ba70c4de1 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateOutputs.cpp @@ -0,0 +1,184 @@ +// +// Copyright 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ValidateOutputs validates fragment shader outputs. It checks for conflicting locations, +// out-of-range locations, that locations are specified when using multiple outputs, and YUV output +// validity. + +#include "compiler/translator/ValidateOutputs.h" + +#include + +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/ParseContext.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics) +{ + diagnostics->error(symbol.getLine(), reason, symbol.getName().data()); +} + +class ValidateOutputsTraverser : public TIntermTraverser +{ + public: + ValidateOutputsTraverser(const TExtensionBehavior &extBehavior, int maxDrawBuffers); + + void validate(TDiagnostics *diagnostics) const; + + void visitSymbol(TIntermSymbol *) override; + + private: + int mMaxDrawBuffers; + bool mAllowUnspecifiedOutputLocationResolution; + bool mUsesFragDepth; + + typedef std::vector OutputVector; + OutputVector mOutputs; + OutputVector mUnspecifiedLocationOutputs; + OutputVector mYuvOutputs; + std::set mVisitedSymbols; // Visited symbol ids. +}; + +ValidateOutputsTraverser::ValidateOutputsTraverser(const TExtensionBehavior &extBehavior, + int maxDrawBuffers) + : TIntermTraverser(true, false, false), + mMaxDrawBuffers(maxDrawBuffers), + mAllowUnspecifiedOutputLocationResolution( + IsExtensionEnabled(extBehavior, TExtension::EXT_blend_func_extended)), + mUsesFragDepth(false) +{} + +void ValidateOutputsTraverser::visitSymbol(TIntermSymbol *symbol) +{ + if (symbol->variable().symbolType() == SymbolType::Empty) + return; + + if (mVisitedSymbols.count(symbol->uniqueId().get()) == 1) + return; + + mVisitedSymbols.insert(symbol->uniqueId().get()); + + TQualifier qualifier = symbol->getQualifier(); + if (qualifier == EvqFragmentOut) + { + if (symbol->getType().getLayoutQualifier().location != -1) + { + mOutputs.push_back(symbol); + } + else if (symbol->getType().getLayoutQualifier().yuv == true) + { + mYuvOutputs.push_back(symbol); + } + else + { + mUnspecifiedLocationOutputs.push_back(symbol); + } + } + else if (qualifier == EvqFragDepth) + { + mUsesFragDepth = true; + } +} + +void ValidateOutputsTraverser::validate(TDiagnostics *diagnostics) const +{ + ASSERT(diagnostics); + OutputVector validOutputs(mMaxDrawBuffers, nullptr); + OutputVector validSecondaryOutputs(mMaxDrawBuffers, nullptr); + + for (const auto &symbol : mOutputs) + { + const TType &type = symbol->getType(); + ASSERT(!type.isArrayOfArrays()); // Disallowed in GLSL ES 3.10 section 4.3.6. + const size_t elementCount = + static_cast(type.isArray() ? type.getOutermostArraySize() : 1u); + const size_t location = static_cast(type.getLayoutQualifier().location); + + ASSERT(type.getLayoutQualifier().location != -1); + + OutputVector *validOutputsToUse = &validOutputs; + // The default index is 0, so we only assign the output to secondary outputs in case the + // index is explicitly set to 1. + if (type.getLayoutQualifier().index == 1) + { + validOutputsToUse = &validSecondaryOutputs; + } + + if (location + elementCount <= validOutputsToUse->size()) + { + for (size_t elementIndex = 0; elementIndex < elementCount; elementIndex++) + { + const size_t offsetLocation = location + elementIndex; + if ((*validOutputsToUse)[offsetLocation]) + { + std::stringstream strstr = sh::InitializeStream(); + strstr << "conflicting output locations with previously defined output '" + << (*validOutputsToUse)[offsetLocation]->getName() << "'"; + error(*symbol, strstr.str().c_str(), diagnostics); + } + else + { + (*validOutputsToUse)[offsetLocation] = symbol; + } + } + } + else + { + if (elementCount > 0) + { + error(*symbol, + elementCount > 1 ? "output array locations would exceed MAX_DRAW_BUFFERS" + : "output location must be < MAX_DRAW_BUFFERS", + diagnostics); + } + } + } + + if (!mAllowUnspecifiedOutputLocationResolution && + ((!mOutputs.empty() && !mUnspecifiedLocationOutputs.empty()) || + mUnspecifiedLocationOutputs.size() > 1)) + { + for (const auto &symbol : mUnspecifiedLocationOutputs) + { + error(*symbol, + "must explicitly specify all locations when using multiple fragment outputs", + diagnostics); + } + } + + if (!mYuvOutputs.empty() && (mYuvOutputs.size() > 1 || mUsesFragDepth || !mOutputs.empty() || + !mUnspecifiedLocationOutputs.empty())) + { + for (const auto &symbol : mYuvOutputs) + { + error(*symbol, + "not allowed to specify yuv qualifier when using depth or multiple color " + "fragment outputs", + diagnostics); + } + } +} + +} // anonymous namespace + +bool ValidateOutputs(TIntermBlock *root, + const TExtensionBehavior &extBehavior, + int maxDrawBuffers, + TDiagnostics *diagnostics) +{ + ValidateOutputsTraverser validateOutputs(extBehavior, maxDrawBuffers); + root->traverse(&validateOutputs); + int numErrorsBefore = diagnostics->numErrors(); + validateOutputs.validate(diagnostics); + return (diagnostics->numErrors() == numErrorsBefore); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateOutputs.h b/gfx/angle/checkout/src/compiler/translator/ValidateOutputs.h new file mode 100644 index 0000000000..136288bb50 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateOutputs.h @@ -0,0 +1,30 @@ +// +// Copyright 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ValidateOutputs validates fragment shader outputs. It checks for conflicting locations, +// out-of-range locations, that locations are specified when using multiple outputs, and YUV output +// validity. +// + +#ifndef COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ +#define COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ + +#include "compiler/translator/ExtensionBehavior.h" + +namespace sh +{ + +class TIntermBlock; +class TDiagnostics; + +// Returns true if the shader has no conflicting or otherwise erroneous fragment outputs. +bool ValidateOutputs(TIntermBlock *root, + const TExtensionBehavior &extBehavior, + int maxDrawBuffers, + TDiagnostics *diagnostics); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateSwitch.cpp b/gfx/angle/checkout/src/compiler/translator/ValidateSwitch.cpp new file mode 100644 index 0000000000..8a9e7b22a1 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateSwitch.cpp @@ -0,0 +1,315 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/ValidateSwitch.h" + +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +const int kMaxAllowedTraversalDepth = 256; + +class ValidateSwitch : public TIntermTraverser +{ + public: + static bool validate(TBasicType switchType, + TDiagnostics *diagnostics, + TIntermBlock *statementList, + const TSourceLoc &loc); + + void visitSymbol(TIntermSymbol *) override; + void visitConstantUnion(TIntermConstantUnion *) override; + bool visitDeclaration(Visit, TIntermDeclaration *) override; + bool visitBlock(Visit visit, TIntermBlock *) override; + bool visitBinary(Visit, TIntermBinary *) override; + bool visitUnary(Visit, TIntermUnary *) override; + bool visitTernary(Visit, TIntermTernary *) override; + bool visitSwizzle(Visit, TIntermSwizzle *) override; + bool visitIfElse(Visit visit, TIntermIfElse *) override; + bool visitSwitch(Visit, TIntermSwitch *) override; + bool visitCase(Visit, TIntermCase *node) override; + bool visitAggregate(Visit, TIntermAggregate *) override; + bool visitLoop(Visit visit, TIntermLoop *) override; + bool visitBranch(Visit, TIntermBranch *) override; + + private: + ValidateSwitch(TBasicType switchType, TDiagnostics *context); + + bool validateInternal(const TSourceLoc &loc); + + TBasicType mSwitchType; + TDiagnostics *mDiagnostics; + bool mCaseTypeMismatch; + bool mFirstCaseFound; + bool mStatementBeforeCase; + bool mLastStatementWasCase; + int mControlFlowDepth; + bool mCaseInsideControlFlow; + int mDefaultCount; + std::set mCasesSigned; + std::set mCasesUnsigned; + bool mDuplicateCases; +}; + +bool ValidateSwitch::validate(TBasicType switchType, + TDiagnostics *diagnostics, + TIntermBlock *statementList, + const TSourceLoc &loc) +{ + ValidateSwitch validate(switchType, diagnostics); + ASSERT(statementList); + statementList->traverse(&validate); + return validate.validateInternal(loc); +} + +ValidateSwitch::ValidateSwitch(TBasicType switchType, TDiagnostics *diagnostics) + : TIntermTraverser(true, false, true, nullptr), + mSwitchType(switchType), + mDiagnostics(diagnostics), + mCaseTypeMismatch(false), + mFirstCaseFound(false), + mStatementBeforeCase(false), + mLastStatementWasCase(false), + mControlFlowDepth(0), + mCaseInsideControlFlow(false), + mDefaultCount(0), + mDuplicateCases(false) +{ + setMaxAllowedDepth(kMaxAllowedTraversalDepth); +} + +void ValidateSwitch::visitSymbol(TIntermSymbol *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; +} + +void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *) +{ + // Conditions of case labels are not traversed, so this is some other constant + // Could be just a statement like "0;" + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; +} + +bool ValidateSwitch::visitDeclaration(Visit, TIntermDeclaration *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitBlock(Visit visit, TIntermBlock *) +{ + if (getParentNode() != nullptr) + { + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + if (visit == PreVisit) + ++mControlFlowDepth; + if (visit == PostVisit) + --mControlFlowDepth; + } + return true; +} + +bool ValidateSwitch::visitBinary(Visit, TIntermBinary *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitUnary(Visit, TIntermUnary *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitTernary(Visit, TIntermTernary *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitSwizzle(Visit, TIntermSwizzle *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitIfElse(Visit visit, TIntermIfElse *) +{ + if (visit == PreVisit) + ++mControlFlowDepth; + if (visit == PostVisit) + --mControlFlowDepth; + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitSwitch(Visit, TIntermSwitch *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + // Don't go into nested switch statements + return false; +} + +bool ValidateSwitch::visitCase(Visit, TIntermCase *node) +{ + const char *nodeStr = node->hasCondition() ? "case" : "default"; + if (mControlFlowDepth > 0) + { + mDiagnostics->error(node->getLine(), "label statement nested inside control flow", nodeStr); + mCaseInsideControlFlow = true; + } + mFirstCaseFound = true; + mLastStatementWasCase = true; + if (!node->hasCondition()) + { + ++mDefaultCount; + if (mDefaultCount > 1) + { + mDiagnostics->error(node->getLine(), "duplicate default label", nodeStr); + } + } + else + { + TIntermConstantUnion *condition = node->getCondition()->getAsConstantUnion(); + if (condition == nullptr) + { + // This can happen in error cases. + return false; + } + TBasicType conditionType = condition->getBasicType(); + if (conditionType != mSwitchType) + { + mDiagnostics->error(condition->getLine(), + "case label type does not match switch init-expression type", + nodeStr); + mCaseTypeMismatch = true; + } + + if (conditionType == EbtInt) + { + int iConst = condition->getIConst(0); + if (mCasesSigned.find(iConst) != mCasesSigned.end()) + { + mDiagnostics->error(condition->getLine(), "duplicate case label", nodeStr); + mDuplicateCases = true; + } + else + { + mCasesSigned.insert(iConst); + } + } + else if (conditionType == EbtUInt) + { + unsigned int uConst = condition->getUConst(0); + if (mCasesUnsigned.find(uConst) != mCasesUnsigned.end()) + { + mDiagnostics->error(condition->getLine(), "duplicate case label", nodeStr); + mDuplicateCases = true; + } + else + { + mCasesUnsigned.insert(uConst); + } + } + // Other types are possible only in error cases, where the error has already been generated + // when parsing the case statement. + } + // Don't traverse the condition of the case statement + return false; +} + +bool ValidateSwitch::visitAggregate(Visit visit, TIntermAggregate *) +{ + if (getParentNode() != nullptr) + { + // This is not the statementList node, but some other node. + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + } + return true; +} + +bool ValidateSwitch::visitLoop(Visit visit, TIntermLoop *) +{ + if (visit == PreVisit) + ++mControlFlowDepth; + if (visit == PostVisit) + --mControlFlowDepth; + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitBranch(Visit, TIntermBranch *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::validateInternal(const TSourceLoc &loc) +{ + if (mStatementBeforeCase) + { + mDiagnostics->error(loc, "statement before the first label", "switch"); + } + if (mLastStatementWasCase) + { + // There have been some differences between versions of GLSL ES specs on whether this should + // be an error or not, but as of early 2018 the latest discussion is that this is an error + // also on GLSL ES versions newer than 3.00. + mDiagnostics->error( + loc, "no statement between the last label and the end of the switch statement", + "switch"); + } + if (getMaxDepth() >= kMaxAllowedTraversalDepth) + { + mDiagnostics->error(loc, "too complex expressions inside a switch statement", "switch"); + } + return !mStatementBeforeCase && !mLastStatementWasCase && !mCaseInsideControlFlow && + !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases && + getMaxDepth() < kMaxAllowedTraversalDepth; +} + +} // anonymous namespace + +bool ValidateSwitchStatementList(TBasicType switchType, + TDiagnostics *diagnostics, + TIntermBlock *statementList, + const TSourceLoc &loc) +{ + return ValidateSwitch::validate(switchType, diagnostics, statementList, loc); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateSwitch.h b/gfx/angle/checkout/src/compiler/translator/ValidateSwitch.h new file mode 100644 index 0000000000..828faac98a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateSwitch.h @@ -0,0 +1,27 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_VALIDATESWITCH_H_ +#define COMPILER_TRANSLATOR_VALIDATESWITCH_H_ + +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/Common.h" + +namespace sh +{ +class TDiagnostics; +class TIntermBlock; + +// Check for errors and output error messages on the context. +// Returns true if there are no errors. +bool ValidateSwitchStatementList(TBasicType switchType, + TDiagnostics *diagnostics, + TIntermBlock *statementList, + const TSourceLoc &loc); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_VALIDATESWITCH_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateTypeSizeLimitations.cpp b/gfx/angle/checkout/src/compiler/translator/ValidateTypeSizeLimitations.cpp new file mode 100644 index 0000000000..6097b6d236 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateTypeSizeLimitations.cpp @@ -0,0 +1,229 @@ +// +// Copyright 2021 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/ValidateTypeSizeLimitations.h" + +#include "angle_gl.h" +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/blocklayout.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +// Arbitrarily enforce that all types declared with a size in bytes of over 2 GB will cause +// compilation failure. +// +// For local and global variables, the limit is much lower (1MB) as that much memory won't fit in +// the GPU registers anyway. +constexpr size_t kMaxVariableSizeInBytes = static_cast(2) * 1024 * 1024 * 1024; +constexpr size_t kMaxPrivateVariableSizeInBytes = static_cast(1) * 1024 * 1024; + +// Traverses intermediate tree to ensure that the shader does not +// exceed certain implementation-defined limits on the sizes of types. +// Some code was copied from the CollectVariables pass. +class ValidateTypeSizeLimitationsTraverser : public TIntermTraverser +{ + public: + ValidateTypeSizeLimitationsTraverser(TSymbolTable *symbolTable, TDiagnostics *diagnostics) + : TIntermTraverser(true, false, false, symbolTable), mDiagnostics(diagnostics) + { + ASSERT(diagnostics); + } + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + const TIntermSequence &sequence = *(node->getSequence()); + + for (TIntermNode *variableNode : sequence) + { + // See CollectVariablesTraverser::visitDeclaration for a + // deeper analysis of the AST structures that might be + // encountered. + TIntermSymbol *asSymbol = variableNode->getAsSymbolNode(); + TIntermBinary *asBinary = variableNode->getAsBinaryNode(); + + if (asBinary != nullptr) + { + ASSERT(asBinary->getOp() == EOpInitialize); + asSymbol = asBinary->getLeft()->getAsSymbolNode(); + } + + ASSERT(asSymbol); + + const TVariable &variable = asSymbol->variable(); + if (variable.symbolType() == SymbolType::AngleInternal) + { + // Ignore internal variables. + continue; + } + + const TType &variableType = asSymbol->getType(); + + // Create a ShaderVariable from which to compute + // (conservative) sizing information. + ShaderVariable shaderVar; + setCommonVariableProperties(variableType, variable, &shaderVar); + + // Compute the std140 layout of this variable, assuming + // it's a member of a block (which it might not be). + Std140BlockEncoder layoutEncoder; + BlockEncoderVisitor visitor("", "", &layoutEncoder); + // Since the size limit's arbitrary, it doesn't matter + // whether the row-major layout is correctly determined. + bool isRowMajorLayout = false; + TraverseShaderVariable(shaderVar, isRowMajorLayout, &visitor); + if (layoutEncoder.getCurrentOffset() > kMaxVariableSizeInBytes) + { + error(asSymbol->getLine(), + "Size of declared variable exceeds implementation-defined limit", + asSymbol->getName()); + return false; + } + + const bool isPrivate = variableType.getQualifier() == EvqTemporary || + variableType.getQualifier() == EvqGlobal || + variableType.getQualifier() == EvqConst; + if (layoutEncoder.getCurrentOffset() > kMaxPrivateVariableSizeInBytes && isPrivate) + { + error(asSymbol->getLine(), + "Size of declared private variable exceeds implementation-defined limit", + asSymbol->getName()); + return false; + } + } + + return true; + } + + private: + void error(TSourceLoc loc, const char *reason, const ImmutableString &token) + { + mDiagnostics->error(loc, reason, token.data()); + } + + void setFieldOrVariableProperties(const TType &type, + bool staticUse, + bool isShaderIOBlock, + bool isPatch, + ShaderVariable *variableOut) const + { + ASSERT(variableOut); + + variableOut->staticUse = staticUse; + variableOut->isShaderIOBlock = isShaderIOBlock; + variableOut->isPatch = isPatch; + + const TStructure *structure = type.getStruct(); + const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + if (structure) + { + // Structures use a NONE type that isn't exposed outside ANGLE. + variableOut->type = GL_NONE; + if (structure->symbolType() != SymbolType::Empty) + { + variableOut->structOrBlockName = structure->name().data(); + } + + const TFieldList &fields = structure->fields(); + + for (const TField *field : fields) + { + // Regardless of the variable type (uniform, in/out etc.) its fields are always + // plain ShaderVariable objects. + ShaderVariable fieldVariable; + setFieldProperties(*field->type(), field->name(), staticUse, isShaderIOBlock, + isPatch, &fieldVariable); + variableOut->fields.push_back(fieldVariable); + } + } + else if (interfaceBlock && isShaderIOBlock) + { + variableOut->type = GL_NONE; + if (interfaceBlock->symbolType() != SymbolType::Empty) + { + variableOut->structOrBlockName = interfaceBlock->name().data(); + } + const TFieldList &fields = interfaceBlock->fields(); + for (const TField *field : fields) + { + ShaderVariable fieldVariable; + setFieldProperties(*field->type(), field->name(), staticUse, true, isPatch, + &fieldVariable); + fieldVariable.isShaderIOBlock = true; + variableOut->fields.push_back(fieldVariable); + } + } + else + { + variableOut->type = GLVariableType(type); + variableOut->precision = GLVariablePrecision(type); + } + + const TSpan &arraySizes = type.getArraySizes(); + if (!arraySizes.empty()) + { + variableOut->arraySizes.assign(arraySizes.begin(), arraySizes.end()); + // WebGL does not support tessellation shaders; removed + // code specific to that shader type. + } + } + + void setFieldProperties(const TType &type, + const ImmutableString &name, + bool staticUse, + bool isShaderIOBlock, + bool isPatch, + ShaderVariable *variableOut) const + { + ASSERT(variableOut); + setFieldOrVariableProperties(type, staticUse, isShaderIOBlock, isPatch, variableOut); + variableOut->name.assign(name.data(), name.length()); + } + + void setCommonVariableProperties(const TType &type, + const TVariable &variable, + ShaderVariable *variableOut) const + { + ASSERT(variableOut); + + // Shortcut some processing that's unnecessary for this analysis. + const bool staticUse = true; + const bool isShaderIOBlock = type.getInterfaceBlock() != nullptr; + const bool isPatch = false; + + setFieldOrVariableProperties(type, staticUse, isShaderIOBlock, isPatch, variableOut); + + const bool isNamed = variable.symbolType() != SymbolType::Empty; + + if (isNamed) + { + variableOut->name.assign(variable.name().data(), variable.name().length()); + } + } + + TDiagnostics *mDiagnostics; + std::vector mLoopSymbolIds; +}; + +} // namespace + +bool ValidateTypeSizeLimitations(TIntermNode *root, + TSymbolTable *symbolTable, + TDiagnostics *diagnostics) +{ + ValidateTypeSizeLimitationsTraverser validate(symbolTable, diagnostics); + root->traverse(&validate); + return diagnostics->numErrors() == 0; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateTypeSizeLimitations.h b/gfx/angle/checkout/src/compiler/translator/ValidateTypeSizeLimitations.h new file mode 100644 index 0000000000..defa39876d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateTypeSizeLimitations.h @@ -0,0 +1,25 @@ +// +// Copyright 2021 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_VALIDATETYPESIZELIMITATIONS_H_ +#define COMPILER_TRANSLATOR_VALIDATETYPESIZELIMITATIONS_H_ + +#include "compiler/translator/IntermNode.h" + +namespace sh +{ + +class TDiagnostics; + +// Returns true if the given shader does not violate certain +// implementation-defined limits on the size of variables' types. +bool ValidateTypeSizeLimitations(TIntermNode *root, + TSymbolTable *symbolTable, + TDiagnostics *diagnostics); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_VALIDATETYPESIZELIMITATIONS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateVaryingLocations.cpp b/gfx/angle/checkout/src/compiler/translator/ValidateVaryingLocations.cpp new file mode 100644 index 0000000000..3c2eeeb5bc --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateVaryingLocations.cpp @@ -0,0 +1,368 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// The ValidateVaryingLocations function checks if there exists location conflicts on shader +// varyings. +// + +#include "ValidateVaryingLocations.h" + +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics) +{ + diagnostics->error(symbol.getLine(), reason, symbol.getName().data()); +} + +int GetStructLocationCount(const TStructure *structure); + +int GetFieldLocationCount(const TField *field) +{ + int field_size = 0; + const TType *fieldType = field->type(); + + if (fieldType->getStruct() != nullptr) + { + field_size = GetStructLocationCount(fieldType->getStruct()); + } + else if (fieldType->isMatrix()) + { + field_size = fieldType->getNominalSize(); + } + else + { + ASSERT(fieldType->getSecondarySize() == 1); + field_size = 1; + } + + if (fieldType->isArray()) + { + field_size *= fieldType->getArraySizeProduct(); + } + + return field_size; +} + +int GetStructLocationCount(const TStructure *structure) +{ + int totalLocation = 0; + for (const TField *field : structure->fields()) + { + totalLocation += GetFieldLocationCount(field); + } + return totalLocation; +} + +int GetInterfaceBlockLocationCount(const TType &varyingType, bool ignoreVaryingArraySize) +{ + int totalLocation = 0; + for (const TField *field : varyingType.getInterfaceBlock()->fields()) + { + totalLocation += GetFieldLocationCount(field); + } + + if (!ignoreVaryingArraySize && varyingType.isArray()) + { + totalLocation *= varyingType.getArraySizeProduct(); + } + return totalLocation; +} + +int GetLocationCount(const TType &varyingType, bool ignoreVaryingArraySize) +{ + ASSERT(!varyingType.isInterfaceBlock()); + + if (varyingType.getStruct() != nullptr) + { + int totalLocation = 0; + for (const TField *field : varyingType.getStruct()->fields()) + { + const TType *fieldType = field->type(); + ASSERT(fieldType->getStruct() == nullptr && !fieldType->isArray()); + + totalLocation += GetFieldLocationCount(field); + } + return totalLocation; + } + + ASSERT(varyingType.isMatrix() || varyingType.getSecondarySize() == 1); + int elementLocationCount = varyingType.isMatrix() ? varyingType.getNominalSize() : 1; + + // [GL_EXT_shader_io_blocks SPEC Chapter 4.4.1] + // Geometry shader inputs, tessellation control shader inputs and outputs, and tessellation + // evaluation inputs all have an additional level of arrayness relative to other shader inputs + // and outputs. This outer array level is removed from the type before considering how many + // locations the type consumes. + if (ignoreVaryingArraySize) + { + // Array-of-arrays cannot be inputs or outputs of a geometry shader. + // (GL_EXT_geometry_shader SPEC issues(5)) + ASSERT(!varyingType.isArrayOfArrays()); + return elementLocationCount; + } + + return elementLocationCount * varyingType.getArraySizeProduct(); +} + +bool ShouldIgnoreVaryingArraySize(TQualifier qualifier, GLenum shaderType) +{ + bool isVaryingIn = IsShaderIn(qualifier) && qualifier != EvqPatchIn; + + switch (shaderType) + { + case GL_GEOMETRY_SHADER: + case GL_TESS_EVALUATION_SHADER: + return isVaryingIn; + case GL_TESS_CONTROL_SHADER: + return (IsShaderOut(qualifier) && qualifier != EvqPatchOut) || isVaryingIn; + default: + return false; + } +} + +struct SymbolAndField +{ + const TIntermSymbol *symbol; + const TField *field; +}; +using LocationMap = std::map; + +void MarkVaryingLocations(TDiagnostics *diagnostics, + const TIntermSymbol *varying, + const TField *field, + int location, + int elementCount, + LocationMap *locationMap) +{ + for (int elementIndex = 0; elementIndex < elementCount; ++elementIndex) + { + const int offsetLocation = location + elementIndex; + auto conflict = locationMap->find(offsetLocation); + if (conflict != locationMap->end()) + { + std::stringstream strstr = sh::InitializeStream(); + strstr << "'" << varying->getName(); + if (field) + { + strstr << "." << field->name(); + } + strstr << "' conflicting location with '" << conflict->second.symbol->getName(); + if (conflict->second.field) + { + strstr << "." << conflict->second.field->name(); + } + strstr << "'"; + error(*varying, strstr.str().c_str(), diagnostics); + } + else + { + (*locationMap)[offsetLocation] = {varying, field}; + } + } +} + +using VaryingVector = std::vector; + +void ValidateShaderInterfaceAndAssignLocations(TDiagnostics *diagnostics, + const VaryingVector &varyingVector, + GLenum shaderType) +{ + // Location conflicts can only happen when there are two or more varyings in varyingVector. + if (varyingVector.size() <= 1) + { + return; + } + + LocationMap locationMap; + for (const TIntermSymbol *varying : varyingVector) + { + const TType &varyingType = varying->getType(); + const int location = varyingType.getLayoutQualifier().location; + ASSERT(location >= 0); + + bool ignoreVaryingArraySize = + ShouldIgnoreVaryingArraySize(varying->getQualifier(), shaderType); + + // A varying is either: + // + // - A vector or matrix, which can take a number of contiguous locations + // - A struct, which also takes a number of contiguous locations + // - An interface block. + // + // Interface blocks can assign arbitrary locations to their fields, for example: + // + // layout(location = 4) in block { + // vec4 a; // gets location 4 + // vec4 b; // gets location 5 + // layout(location = 7) vec4 c; // gets location 7 + // vec4 d; // gets location 8 + // layout (location = 1) vec4 e; // gets location 1 + // vec4 f; // gets location 2 + // }; + // + // The following code therefore takes two paths. For non-interface-block types, the number + // of locations for the varying is calculated (elementCount), and all locations in + // [location, location + elementCount) are marked as occupied. + // + // For interface blocks, a similar algorithm is implemented except each field is + // individually marked with the location either advancing automatically or taking its value + // from the field's layout qualifier. + + if (varyingType.isInterfaceBlock()) + { + int currentLocation = location; + bool anyFieldWithLocation = false; + + for (const TField *field : varyingType.getInterfaceBlock()->fields()) + { + const int fieldLocation = field->type()->getLayoutQualifier().location; + if (fieldLocation >= 0) + { + currentLocation = fieldLocation; + anyFieldWithLocation = true; + } + + const int fieldLocationCount = GetFieldLocationCount(field); + MarkVaryingLocations(diagnostics, varying, field, currentLocation, + fieldLocationCount, &locationMap); + + currentLocation += fieldLocationCount; + } + + // Array interface blocks can't have location qualifiers on fields. + ASSERT(ignoreVaryingArraySize || !anyFieldWithLocation || !varyingType.isArray()); + + if (!ignoreVaryingArraySize && varyingType.isArray()) + { + // This is only reached if the varying is an array of interface blocks, with only a + // layout qualifier on the block itself, for example: + // + // layout(location = 4) in block { + // vec4 a; + // vec4 b; + // vec4 c; + // vec4 d; + // } instance[N]; + // + // The locations for instance[0] are already marked by the above code, so we need to + // further mark locations occupied by instances [1, N). |currentLocation| is + // already just past the end of instance[0], which is the beginning of instance[1]. + // + int remainingLocations = currentLocation * (varyingType.getArraySizeProduct() - 1); + MarkVaryingLocations(diagnostics, varying, nullptr, currentLocation, + remainingLocations, &locationMap); + } + } + else + { + const int elementCount = GetLocationCount(varying->getType(), ignoreVaryingArraySize); + MarkVaryingLocations(diagnostics, varying, nullptr, location, elementCount, + &locationMap); + } + } +} + +class ValidateVaryingLocationsTraverser : public TIntermTraverser +{ + public: + ValidateVaryingLocationsTraverser(GLenum shaderType); + void validate(TDiagnostics *diagnostics); + + private: + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; + + VaryingVector mInputVaryingsWithLocation; + VaryingVector mOutputVaryingsWithLocation; + GLenum mShaderType; +}; + +ValidateVaryingLocationsTraverser::ValidateVaryingLocationsTraverser(GLenum shaderType) + : TIntermTraverser(true, false, false), mShaderType(shaderType) +{} + +bool ValidateVaryingLocationsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) +{ + const TIntermSequence &sequence = *(node->getSequence()); + ASSERT(!sequence.empty()); + + const TIntermSymbol *symbol = sequence.front()->getAsSymbolNode(); + if (symbol == nullptr) + { + return false; + } + + if (symbol->variable().symbolType() == SymbolType::Empty) + { + return false; + } + + // Collect varyings that have explicit 'location' qualifiers. + const TQualifier qualifier = symbol->getQualifier(); + if (symbol->getType().getLayoutQualifier().location != -1) + { + if (IsVaryingIn(qualifier)) + { + mInputVaryingsWithLocation.push_back(symbol); + } + else if (IsVaryingOut(qualifier)) + { + mOutputVaryingsWithLocation.push_back(symbol); + } + } + + return false; +} + +bool ValidateVaryingLocationsTraverser::visitFunctionDefinition(Visit visit, + TIntermFunctionDefinition *node) +{ + // We stop traversing function definitions because varyings cannot be defined in a function. + return false; +} + +void ValidateVaryingLocationsTraverser::validate(TDiagnostics *diagnostics) +{ + ASSERT(diagnostics); + + ValidateShaderInterfaceAndAssignLocations(diagnostics, mInputVaryingsWithLocation, mShaderType); + ValidateShaderInterfaceAndAssignLocations(diagnostics, mOutputVaryingsWithLocation, + mShaderType); +} + +} // anonymous namespace + +unsigned int CalculateVaryingLocationCount(const TType &varyingType, GLenum shaderType) +{ + const TQualifier qualifier = varyingType.getQualifier(); + const bool ignoreVaryingArraySize = ShouldIgnoreVaryingArraySize(qualifier, shaderType); + + if (varyingType.isInterfaceBlock()) + { + return GetInterfaceBlockLocationCount(varyingType, ignoreVaryingArraySize); + } + + return GetLocationCount(varyingType, ignoreVaryingArraySize); +} + +bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType) +{ + ValidateVaryingLocationsTraverser varyingValidator(shaderType); + root->traverse(&varyingValidator); + int numErrorsBefore = diagnostics->numErrors(); + varyingValidator.validate(diagnostics); + return (diagnostics->numErrors() == numErrorsBefore); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateVaryingLocations.h b/gfx/angle/checkout/src/compiler/translator/ValidateVaryingLocations.h new file mode 100644 index 0000000000..5ce43c91c4 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateVaryingLocations.h @@ -0,0 +1,28 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// The ValidateVaryingLocations function checks if there exists location conflicts on shader +// varyings. +// + +#ifndef COMPILER_TRANSLATOR_VALIDATEVARYINGLOCATIONS_H_ +#define COMPILER_TRANSLATOR_VALIDATEVARYINGLOCATIONS_H_ + +#include "GLSLANG/ShaderVars.h" + +namespace sh +{ + +class TIntermBlock; +class TIntermSymbol; +class TDiagnostics; +class TType; + +unsigned int CalculateVaryingLocationCount(const TType &varyingType, GLenum shaderType); +bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType); + +} // namespace sh + +#endif diff --git a/gfx/angle/checkout/src/compiler/translator/VariablePacker.cpp b/gfx/angle/checkout/src/compiler/translator/VariablePacker.cpp new file mode 100644 index 0000000000..347395d382 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/VariablePacker.cpp @@ -0,0 +1,409 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Check whether variables fit within packing limits according to the packing rules from the GLSL ES +// 1.00.17 spec, Appendix A, section 7. + +#include + +#include "angle_gl.h" + +#include "common/utilities.h" +#include "compiler/translator/VariablePacker.h" + +namespace sh +{ + +namespace +{ + +// Expand the variable so that struct variables are split into their individual fields. +// Will not set the mappedName or staticUse fields on the expanded variables. +void ExpandVariable(const ShaderVariable &variable, + const std::string &name, + std::vector *expanded); + +void ExpandStructVariable(const ShaderVariable &variable, + const std::string &name, + std::vector *expanded) +{ + ASSERT(variable.isStruct()); + + const std::vector &fields = variable.fields; + + for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) + { + const ShaderVariable &field = fields[fieldIndex]; + ExpandVariable(field, name + "." + field.name, expanded); + } +} + +void ExpandStructArrayVariable(const ShaderVariable &variable, + unsigned int arrayNestingIndex, + const std::string &name, + std::vector *expanded) +{ + // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the + // innermost. + const unsigned int currentArraySize = variable.getNestedArraySize(arrayNestingIndex); + for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement) + { + const std::string elementName = name + ArrayString(arrayElement); + if (arrayNestingIndex + 1u < variable.arraySizes.size()) + { + ExpandStructArrayVariable(variable, arrayNestingIndex + 1u, elementName, expanded); + } + else + { + ExpandStructVariable(variable, elementName, expanded); + } + } +} + +void ExpandVariable(const ShaderVariable &variable, + const std::string &name, + std::vector *expanded) +{ + if (variable.isStruct()) + { + if (variable.isArray()) + { + ExpandStructArrayVariable(variable, 0u, name, expanded); + } + else + { + ExpandStructVariable(variable, name, expanded); + } + } + else + { + ShaderVariable expandedVar = variable; + expandedVar.name = name; + + expanded->push_back(expandedVar); + } +} + +int GetVariablePackingRows(const ShaderVariable &variable) +{ + return GetTypePackingRows(variable.type) * variable.getArraySizeProduct(); +} + +class VariablePacker +{ + public: + bool checkExpandedVariablesWithinPackingLimits(unsigned int maxVectors, + std::vector *variables); + + private: + static const int kNumColumns = 4; + static const unsigned kColumnMask = (1 << kNumColumns) - 1; + + unsigned makeColumnFlags(int column, int numComponentsPerRow); + void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow); + bool searchColumn(int column, int numRows, int *destRow, int *destSize); + + int topNonFullRow_; + int bottomNonFullRow_; + int maxRows_; + std::vector rows_; +}; + +struct TVariableInfoComparer +{ + bool operator()(const sh::ShaderVariable &lhs, const sh::ShaderVariable &rhs) const + { + int lhsSortOrder = gl::VariableSortOrder(lhs.type); + int rhsSortOrder = gl::VariableSortOrder(rhs.type); + if (lhsSortOrder != rhsSortOrder) + { + return lhsSortOrder < rhsSortOrder; + } + // Sort by largest first. + return lhs.getArraySizeProduct() > rhs.getArraySizeProduct(); + } +}; + +unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow) +{ + return ((kColumnMask << (kNumColumns - numComponentsPerRow)) & kColumnMask) >> column; +} + +void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow) +{ + unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow); + for (int r = 0; r < numRows; ++r) + { + int row = topRow + r; + ASSERT((rows_[row] & columnFlags) == 0); + rows_[row] |= columnFlags; + } +} + +bool VariablePacker::searchColumn(int column, int numRows, int *destRow, int *destSize) +{ + ASSERT(destRow); + + for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask; ++topNonFullRow_) + { + } + + for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask; --bottomNonFullRow_) + { + } + + if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) + { + return false; + } + + unsigned columnFlags = makeColumnFlags(column, 1); + int topGoodRow = 0; + int smallestGoodTop = -1; + int smallestGoodSize = maxRows_ + 1; + int bottomRow = bottomNonFullRow_ + 1; + bool found = false; + for (int row = topNonFullRow_; row <= bottomRow; ++row) + { + bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false; + if (rowEmpty) + { + if (!found) + { + topGoodRow = row; + found = true; + } + } + else + { + if (found) + { + int size = row - topGoodRow; + if (size >= numRows && size < smallestGoodSize) + { + smallestGoodSize = size; + smallestGoodTop = topGoodRow; + } + } + found = false; + } + } + if (smallestGoodTop < 0) + { + return false; + } + + *destRow = smallestGoodTop; + if (destSize) + { + *destSize = smallestGoodSize; + } + return true; +} + +bool VariablePacker::checkExpandedVariablesWithinPackingLimits( + unsigned int maxVectors, + std::vector *variables) +{ + ASSERT(maxVectors > 0); + maxRows_ = maxVectors; + topNonFullRow_ = 0; + bottomNonFullRow_ = maxRows_ - 1; + + // Check whether each variable fits in the available vectors. + for (const sh::ShaderVariable &variable : *variables) + { + // Structs should have been expanded before reaching here. + ASSERT(!variable.isStruct()); + if (variable.getArraySizeProduct() > maxVectors / GetTypePackingRows(variable.type)) + { + return false; + } + } + + // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific + // order by type, then by size of array, largest first. + std::sort(variables->begin(), variables->end(), TVariableInfoComparer()); + rows_.clear(); + rows_.resize(maxVectors, 0); + + // Packs the 4 column variables. + size_t ii = 0; + for (; ii < variables->size(); ++ii) + { + const sh::ShaderVariable &variable = (*variables)[ii]; + if (GetTypePackingComponentsPerRow(variable.type) != 4) + { + break; + } + topNonFullRow_ += GetVariablePackingRows(variable); + if (topNonFullRow_ > maxRows_) + { + return false; + } + } + + // Packs the 3 column variables. + int num3ColumnRows = 0; + for (; ii < variables->size(); ++ii) + { + const sh::ShaderVariable &variable = (*variables)[ii]; + if (GetTypePackingComponentsPerRow(variable.type) != 3) + { + break; + } + + num3ColumnRows += GetVariablePackingRows(variable); + if (topNonFullRow_ + num3ColumnRows > maxRows_) + { + return false; + } + } + + fillColumns(topNonFullRow_, num3ColumnRows, 0, 3); + + // Packs the 2 column variables. + int top2ColumnRow = topNonFullRow_ + num3ColumnRows; + int twoColumnRowsAvailable = maxRows_ - top2ColumnRow; + int rowsAvailableInColumns01 = twoColumnRowsAvailable; + int rowsAvailableInColumns23 = twoColumnRowsAvailable; + for (; ii < variables->size(); ++ii) + { + const sh::ShaderVariable &variable = (*variables)[ii]; + if (GetTypePackingComponentsPerRow(variable.type) != 2) + { + break; + } + int numRows = GetVariablePackingRows(variable); + if (numRows <= rowsAvailableInColumns01) + { + rowsAvailableInColumns01 -= numRows; + } + else if (numRows <= rowsAvailableInColumns23) + { + rowsAvailableInColumns23 -= numRows; + } + else + { + return false; + } + } + + int numRowsUsedInColumns01 = twoColumnRowsAvailable - rowsAvailableInColumns01; + int numRowsUsedInColumns23 = twoColumnRowsAvailable - rowsAvailableInColumns23; + fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2); + fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23, 2, 2); + + // Packs the 1 column variables. + for (; ii < variables->size(); ++ii) + { + const sh::ShaderVariable &variable = (*variables)[ii]; + ASSERT(1 == GetTypePackingComponentsPerRow(variable.type)); + int numRows = GetVariablePackingRows(variable); + int smallestColumn = -1; + int smallestSize = maxRows_ + 1; + int topRow = -1; + for (int column = 0; column < kNumColumns; ++column) + { + int row = 0; + int size = 0; + if (searchColumn(column, numRows, &row, &size)) + { + if (size < smallestSize) + { + smallestSize = size; + smallestColumn = column; + topRow = row; + } + } + } + + if (smallestColumn < 0) + { + return false; + } + + fillColumns(topRow, numRows, smallestColumn, 1); + } + + ASSERT(variables->size() == ii); + + return true; +} + +} // anonymous namespace + +int GetTypePackingComponentsPerRow(sh::GLenum type) +{ + switch (type) + { + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_BOOL_VEC4: + case GL_UNSIGNED_INT_VEC4: + return 4; + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_BOOL_VEC3: + case GL_UNSIGNED_INT_VEC3: + return 3; + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_BOOL_VEC2: + case GL_UNSIGNED_INT_VEC2: + return 2; + default: + ASSERT(gl::VariableComponentCount(type) == 1); + return 1; + } +} + +int GetTypePackingRows(sh::GLenum type) +{ + switch (type) + { + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x3: + case GL_FLOAT_MAT4x2: + return 4; + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT3x2: + return 3; + case GL_FLOAT_MAT2: + return 2; + default: + ASSERT(gl::VariableRowCount(type) == 1); + return 1; + } +} + +bool CheckVariablesInPackingLimits(unsigned int maxVectors, + const std::vector &variables) +{ + VariablePacker packer; + std::vector expandedVariables; + for (const ShaderVariable &variable : variables) + { + ExpandVariable(variable, variable.name, &expandedVariables); + } + return packer.checkExpandedVariablesWithinPackingLimits(maxVectors, &expandedVariables); +} + +bool CheckVariablesInPackingLimits(unsigned int maxVectors, + const std::vector &variables); + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/VariablePacker.h b/gfx/angle/checkout/src/compiler/translator/VariablePacker.h new file mode 100644 index 0000000000..8cf621f168 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/VariablePacker.h @@ -0,0 +1,32 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Check whether variables fit within packing limits according to the packing rules from the GLSL ES +// 1.00.17 spec, Appendix A, section 7. + +#ifndef COMPILER_TRANSLATOR_VARIABLEPACKER_H_ +#define COMPILER_TRANSLATOR_VARIABLEPACKER_H_ + +#include + +#include + +namespace sh +{ + +// Gets how many components in a row a data type takes. +int GetTypePackingComponentsPerRow(sh::GLenum type); + +// Gets how many rows a data type takes. +int GetTypePackingRows(sh::GLenum type); + +// Returns true if the passed in variables pack in maxVectors. +// T should be ShaderVariable or one of the subclasses of ShaderVariable. +bool CheckVariablesInPackingLimits(unsigned int maxVectors, + const std::vector &variables); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_VARIABLEPACKER_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/VersionGLSL.cpp b/gfx/angle/checkout/src/compiler/translator/VersionGLSL.cpp new file mode 100644 index 0000000000..3ff4216a0d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/VersionGLSL.cpp @@ -0,0 +1,156 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/VersionGLSL.h" + +#include "angle_gl.h" +#include "compiler/translator/Symbol.h" + +namespace sh +{ + +namespace +{ +constexpr const ImmutableString kGlPointCoordString("gl_PointCoord"); +} // anonymous namespace + +int ShaderOutputTypeToGLSLVersion(ShShaderOutput output) +{ + switch (output) + { + case SH_GLSL_130_OUTPUT: + return GLSL_VERSION_130; + case SH_GLSL_140_OUTPUT: + return GLSL_VERSION_140; + case SH_GLSL_150_CORE_OUTPUT: + return GLSL_VERSION_150; + case SH_GLSL_330_CORE_OUTPUT: + return GLSL_VERSION_330; + case SH_GLSL_400_CORE_OUTPUT: + return GLSL_VERSION_400; + case SH_GLSL_410_CORE_OUTPUT: + return GLSL_VERSION_410; + case SH_GLSL_420_CORE_OUTPUT: + return GLSL_VERSION_420; + case SH_GLSL_430_CORE_OUTPUT: + return GLSL_VERSION_430; + case SH_GLSL_440_CORE_OUTPUT: + return GLSL_VERSION_440; + case SH_GLSL_450_CORE_OUTPUT: + return GLSL_VERSION_450; + case SH_GLSL_COMPATIBILITY_OUTPUT: + return GLSL_VERSION_110; + default: + UNREACHABLE(); + return 0; + } +} + +// We need to scan for the following: +// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders +// but only at the global scope. +// 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader +// but inside any scope. +// 3. Call to a matrix constructor with another matrix as argument. +// (These constructors were reserved in GLSL version 1.10.) +// 4. Arrays as "out" function parameters. +// GLSL spec section 6.1.1: "When calling a function, expressions that do +// not evaluate to l-values cannot be passed to parameters declared as +// out or inout." +// GLSL 1.1 section 5.8: "Other binary or unary expressions, +// non-dereferenced arrays, function names, swizzles with repeated fields, +// and constants cannot be l-values." +// GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that +// are built-in types, entire structures or arrays... are all l-values." +// +TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutput output) + : TIntermTraverser(true, false, false) +{ + mVersion = ShaderOutputTypeToGLSLVersion(output); + if (pragma.stdgl.invariantAll) + { + ensureVersionIsAtLeast(GLSL_VERSION_120); + } + if (type == GL_COMPUTE_SHADER) + { + ensureVersionIsAtLeast(GLSL_VERSION_430); + } +} + +void TVersionGLSL::visitSymbol(TIntermSymbol *node) +{ + if (node->variable().symbolType() == SymbolType::BuiltIn && + node->getName() == kGlPointCoordString) + { + ensureVersionIsAtLeast(GLSL_VERSION_120); + } +} + +bool TVersionGLSL::visitDeclaration(Visit, TIntermDeclaration *node) +{ + const TIntermSequence &sequence = *(node->getSequence()); + if (sequence.front()->getAsTyped()->getType().isInvariant()) + { + ensureVersionIsAtLeast(GLSL_VERSION_120); + } + return true; +} + +bool TVersionGLSL::visitGlobalQualifierDeclaration(Visit, TIntermGlobalQualifierDeclaration *node) +{ + if (node->isPrecise()) + { + ensureVersionIsAtLeast(GLSL_VERSION_420); + } + else + { + ensureVersionIsAtLeast(GLSL_VERSION_120); + } + return true; +} + +void TVersionGLSL::visitFunctionPrototype(TIntermFunctionPrototype *node) +{ + size_t paramCount = node->getFunction()->getParamCount(); + for (size_t i = 0; i < paramCount; ++i) + { + const TVariable *param = node->getFunction()->getParam(i); + const TType &type = param->getType(); + if (type.isArray()) + { + TQualifier qualifier = type.getQualifier(); + if ((qualifier == EvqParamOut) || (qualifier == EvqParamInOut)) + { + ensureVersionIsAtLeast(GLSL_VERSION_120); + break; + } + } + } +} + +bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node) +{ + if (node->getOp() == EOpConstruct && node->getType().isMatrix()) + { + const TIntermSequence &sequence = *(node->getSequence()); + if (sequence.size() == 1) + { + TIntermTyped *typed = sequence.front()->getAsTyped(); + if (typed && typed->isMatrix()) + { + ensureVersionIsAtLeast(GLSL_VERSION_120); + } + } + } + return true; +} + +void TVersionGLSL::ensureVersionIsAtLeast(int version) +{ + mVersion = std::max(version, mVersion); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/VersionGLSL.h b/gfx/angle/checkout/src/compiler/translator/VersionGLSL.h new file mode 100644 index 0000000000..706e9125e1 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/VersionGLSL.h @@ -0,0 +1,76 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_VERSIONGLSL_H_ +#define COMPILER_TRANSLATOR_VERSIONGLSL_H_ + +#include "compiler/translator/tree_util/IntermTraverse.h" + +#include "compiler/translator/Pragma.h" + +namespace sh +{ + +static const int GLSL_VERSION_110 = 110; +static const int GLSL_VERSION_120 = 120; +static const int GLSL_VERSION_130 = 130; +static const int GLSL_VERSION_140 = 140; +static const int GLSL_VERSION_150 = 150; +static const int GLSL_VERSION_330 = 330; +static const int GLSL_VERSION_400 = 400; +static const int GLSL_VERSION_410 = 410; +static const int GLSL_VERSION_420 = 420; +static const int GLSL_VERSION_430 = 430; +static const int GLSL_VERSION_440 = 440; +static const int GLSL_VERSION_450 = 450; + +int ShaderOutputTypeToGLSLVersion(ShShaderOutput output); + +// Traverses the intermediate tree to return the minimum GLSL version +// required to legally access all built-in features used in the shader. +// GLSL 1.1 which is mandated by OpenGL 2.0 provides: +// - #version and #extension to declare version and extensions. +// - built-in functions refract, exp, and log. +// - updated step() to compare x < edge instead of x <= edge. +// GLSL 1.2 which is mandated by OpenGL 2.1 provides: +// - many changes to reduce differences when compared to the ES specification. +// - invariant keyword and its support. +// - c++ style name hiding rules. +// - built-in variable gl_PointCoord for fragment shaders. +// - matrix constructors taking matrix as argument. +// - array as "out" function parameters +// +// TODO: ES3 equivalent versions of GLSL +class TVersionGLSL : public TIntermTraverser +{ + public: + TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutput output); + + // If output is core profile, returns 150. + // If output is legacy profile, + // Returns 120 if the following is used the shader: + // - "invariant", + // - "gl_PointCoord", + // - matrix/matrix constructors + // - array "out" parameters + // Else 110 is returned. + int getVersion() const { return mVersion; } + + void visitSymbol(TIntermSymbol *node) override; + bool visitAggregate(Visit, TIntermAggregate *node) override; + bool visitGlobalQualifierDeclaration(Visit, TIntermGlobalQualifierDeclaration *node) override; + void visitFunctionPrototype(TIntermFunctionPrototype *node) override; + bool visitDeclaration(Visit, TIntermDeclaration *node) override; + + private: + void ensureVersionIsAtLeast(int version); + + int mVersion; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_VERSIONGLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/blocklayout.cpp b/gfx/angle/checkout/src/compiler/translator/blocklayout.cpp new file mode 100644 index 0000000000..24a2640dca --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/blocklayout.cpp @@ -0,0 +1,666 @@ +// +// Copyright 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// blocklayout.cpp: +// Implementation for block layout classes and methods. +// + +#include "compiler/translator/blocklayout.h" + +#include "common/mathutil.h" +#include "common/utilities.h" +#include "compiler/translator/Common.h" + +namespace sh +{ + +namespace +{ +class BlockLayoutMapVisitor : public BlockEncoderVisitor +{ + public: + BlockLayoutMapVisitor(BlockLayoutMap *blockInfoOut, + const std::string &instanceName, + BlockLayoutEncoder *encoder) + : BlockEncoderVisitor(instanceName, instanceName, encoder), mInfoOut(blockInfoOut) + {} + + void encodeVariable(const ShaderVariable &variable, + const BlockMemberInfo &variableInfo, + const std::string &name, + const std::string &mappedName) override + { + ASSERT(!gl::IsSamplerType(variable.type)); + if (!gl::IsOpaqueType(variable.type)) + { + (*mInfoOut)[name] = variableInfo; + } + } + + private: + BlockLayoutMap *mInfoOut; +}; + +template +void GetInterfaceBlockInfo(const std::vector &fields, + const std::string &prefix, + BlockLayoutEncoder *encoder, + bool inRowMajorLayout, + bool onlyActiveVariables, + BlockLayoutMap *blockInfoOut) +{ + BlockLayoutMapVisitor visitor(blockInfoOut, prefix, encoder); + if (onlyActiveVariables) + { + TraverseActiveShaderVariables(fields, inRowMajorLayout, &visitor); + } + else + { + TraverseShaderVariables(fields, inRowMajorLayout, &visitor); + } +} + +void TraverseStructVariable(const ShaderVariable &variable, + bool isRowMajorLayout, + ShaderVariableVisitor *visitor) +{ + const std::vector &fields = variable.fields; + + visitor->enterStructAccess(variable, isRowMajorLayout); + TraverseShaderVariables(fields, isRowMajorLayout, visitor); + visitor->exitStructAccess(variable, isRowMajorLayout); +} + +void TraverseStructArrayVariable(const ShaderVariable &variable, + bool inRowMajorLayout, + ShaderVariableVisitor *visitor) +{ + visitor->enterArray(variable); + + // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the + // innermost. We make a special case for unsized arrays. + const unsigned int currentArraySize = variable.getNestedArraySize(0); + for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement) + { + visitor->enterArrayElement(variable, arrayElement); + ShaderVariable elementVar = variable; + elementVar.indexIntoArray(arrayElement); + + if (variable.arraySizes.size() > 1u) + { + TraverseStructArrayVariable(elementVar, inRowMajorLayout, visitor); + } + else + { + TraverseStructVariable(elementVar, inRowMajorLayout, visitor); + } + + visitor->exitArrayElement(variable, arrayElement); + } + + visitor->exitArray(variable); +} + +void TraverseArrayOfArraysVariable(const ShaderVariable &variable, + unsigned int arrayNestingIndex, + bool isRowMajorMatrix, + ShaderVariableVisitor *visitor) +{ + visitor->enterArray(variable); + + const unsigned int currentArraySize = variable.getNestedArraySize(arrayNestingIndex); + unsigned int count = std::max(currentArraySize, 1u); + for (unsigned int arrayElement = 0u; arrayElement < count; ++arrayElement) + { + visitor->enterArrayElement(variable, arrayElement); + + ShaderVariable elementVar = variable; + elementVar.indexIntoArray(arrayElement); + + if (arrayNestingIndex + 2u < variable.arraySizes.size()) + { + TraverseArrayOfArraysVariable(elementVar, arrayNestingIndex, isRowMajorMatrix, visitor); + } + else + { + if (gl::IsSamplerType(variable.type) || gl::IsImageType(variable.type) || + variable.isFragmentInOut) + { + visitor->visitOpaqueObject(elementVar); + } + else + { + visitor->visitVariable(elementVar, isRowMajorMatrix); + } + } + + visitor->exitArrayElement(variable, arrayElement); + } + + visitor->exitArray(variable); +} + +std::string CollapseNameStack(const std::vector &nameStack) +{ + std::stringstream strstr = sh::InitializeStream(); + for (const std::string &part : nameStack) + { + strstr << part; + } + return strstr.str(); +} + +size_t GetStd430BaseAlignment(GLenum variableType, bool isRowMajor) +{ + GLenum flippedType = isRowMajor ? variableType : gl::TransposeMatrixType(variableType); + size_t numComponents = static_cast(gl::VariableColumnCount(flippedType)); + return ComponentAlignment(numComponents); +} + +class BaseAlignmentVisitor : public ShaderVariableVisitor +{ + public: + BaseAlignmentVisitor() = default; + void visitVariable(const ShaderVariable &variable, bool isRowMajor) override + { + size_t baseAlignment = GetStd430BaseAlignment(variable.type, isRowMajor); + mCurrentAlignment = std::max(mCurrentAlignment, baseAlignment); + } + + // This is in components rather than bytes. + size_t getBaseAlignment() const { return mCurrentAlignment; } + + private: + size_t mCurrentAlignment = 0; +}; +} // anonymous namespace + +// BlockLayoutEncoder implementation. +BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0) {} + +BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, + const std::vector &arraySizes, + bool isRowMajorMatrix) +{ + int arrayStride; + int matrixStride; + + getBlockLayoutInfo(type, arraySizes, isRowMajorMatrix, &arrayStride, &matrixStride); + + const BlockMemberInfo memberInfo(static_cast(mCurrentOffset * kBytesPerComponent), + static_cast(arrayStride * kBytesPerComponent), + static_cast(matrixStride * kBytesPerComponent), + isRowMajorMatrix); + + advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride, matrixStride); + + return memberInfo; +} + +BlockMemberInfo BlockLayoutEncoder::encodeArrayOfPreEncodedStructs( + size_t size, + const std::vector &arraySizes) +{ + const unsigned int innerArraySizeProduct = gl::InnerArraySizeProduct(arraySizes); + const unsigned int outermostArraySize = gl::OutermostArraySize(arraySizes); + + // The size of struct is expected to be already aligned appropriately. + const size_t arrayStride = size * innerArraySizeProduct; + + const BlockMemberInfo memberInfo(static_cast(mCurrentOffset * kBytesPerComponent), + static_cast(arrayStride), -1, false); + + angle::base::CheckedNumeric checkedOffset(arrayStride); + checkedOffset *= outermostArraySize; + checkedOffset /= kBytesPerComponent; + checkedOffset += mCurrentOffset; + mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits::max()); + + return memberInfo; +} + +size_t BlockLayoutEncoder::getCurrentOffset() const +{ + angle::base::CheckedNumeric checkedOffset(mCurrentOffset); + checkedOffset *= kBytesPerComponent; + return checkedOffset.ValueOrDefault(std::numeric_limits::max()); +} + +size_t BlockLayoutEncoder::getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor) +{ + size_t currentOffset = mCurrentOffset; + mCurrentOffset = 0; + BlockEncoderVisitor visitor("", "", this); + enterAggregateType(structVar); + TraverseShaderVariables(structVar.fields, isRowMajor, &visitor); + exitAggregateType(structVar); + size_t structVarSize = getCurrentOffset(); + mCurrentOffset = currentOffset; + return structVarSize; +} + +// static +size_t BlockLayoutEncoder::GetBlockRegister(const BlockMemberInfo &info) +{ + return (info.offset / kBytesPerComponent) / kComponentsPerRegister; +} + +// static +size_t BlockLayoutEncoder::GetBlockRegisterElement(const BlockMemberInfo &info) +{ + return (info.offset / kBytesPerComponent) % kComponentsPerRegister; +} + +void BlockLayoutEncoder::align(size_t baseAlignment) +{ + angle::base::CheckedNumeric checkedOffset(mCurrentOffset); + checkedOffset += baseAlignment; + checkedOffset -= 1; + angle::base::CheckedNumeric checkedAlignmentOffset = checkedOffset; + checkedAlignmentOffset %= baseAlignment; + checkedOffset -= checkedAlignmentOffset.ValueOrDefault(std::numeric_limits::max()); + mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits::max()); +} + +// StubBlockEncoder implementation. +void StubBlockEncoder::getBlockLayoutInfo(GLenum type, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int *arrayStrideOut, + int *matrixStrideOut) +{ + *arrayStrideOut = 0; + *matrixStrideOut = 0; +} + +// Std140BlockEncoder implementation. +Std140BlockEncoder::Std140BlockEncoder() {} + +void Std140BlockEncoder::enterAggregateType(const ShaderVariable &structVar) +{ + align(getBaseAlignment(structVar)); +} + +void Std140BlockEncoder::exitAggregateType(const ShaderVariable &structVar) +{ + align(getBaseAlignment(structVar)); +} + +void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int *arrayStrideOut, + int *matrixStrideOut) +{ + // We assume we are only dealing with 4 byte components (no doubles or half-words currently) + ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == kBytesPerComponent); + + size_t baseAlignment = 0; + int matrixStride = 0; + int arrayStride = 0; + + if (gl::IsMatrixType(type)) + { + baseAlignment = getTypeBaseAlignment(type, isRowMajorMatrix); + matrixStride = static_cast(getTypeBaseAlignment(type, isRowMajorMatrix)); + + if (!arraySizes.empty()) + { + const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); + arrayStride = + static_cast(getTypeBaseAlignment(type, isRowMajorMatrix) * numRegisters); + } + } + else if (!arraySizes.empty()) + { + baseAlignment = static_cast(getTypeBaseAlignment(type, false)); + arrayStride = static_cast(getTypeBaseAlignment(type, false)); + } + else + { + const size_t numComponents = static_cast(gl::VariableComponentCount(type)); + baseAlignment = ComponentAlignment(numComponents); + } + + align(baseAlignment); + + *matrixStrideOut = matrixStride; + *arrayStrideOut = arrayStride; +} + +void Std140BlockEncoder::advanceOffset(GLenum type, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int arrayStride, + int matrixStride) +{ + if (!arraySizes.empty()) + { + angle::base::CheckedNumeric checkedOffset(arrayStride); + checkedOffset *= gl::ArraySizeProduct(arraySizes); + checkedOffset += mCurrentOffset; + mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits::max()); + } + else if (gl::IsMatrixType(type)) + { + angle::base::CheckedNumeric checkedOffset(matrixStride); + checkedOffset *= gl::MatrixRegisterCount(type, isRowMajorMatrix); + checkedOffset += mCurrentOffset; + mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits::max()); + } + else + { + angle::base::CheckedNumeric checkedOffset(mCurrentOffset); + checkedOffset += gl::VariableComponentCount(type); + mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits::max()); + } +} + +size_t Std140BlockEncoder::getBaseAlignment(const ShaderVariable &variable) const +{ + return kComponentsPerRegister; +} + +size_t Std140BlockEncoder::getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const +{ + return kComponentsPerRegister; +} + +// Std430BlockEncoder implementation. +Std430BlockEncoder::Std430BlockEncoder() {} + +size_t Std430BlockEncoder::getBaseAlignment(const ShaderVariable &shaderVar) const +{ + if (shaderVar.isStruct()) + { + BaseAlignmentVisitor visitor; + TraverseShaderVariables(shaderVar.fields, false, &visitor); + return visitor.getBaseAlignment(); + } + + return GetStd430BaseAlignment(shaderVar.type, shaderVar.isRowMajorLayout); +} + +size_t Std430BlockEncoder::getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const +{ + return GetStd430BaseAlignment(type, isRowMajorMatrix); +} + +void GetInterfaceBlockInfo(const std::vector &fields, + const std::string &prefix, + BlockLayoutEncoder *encoder, + BlockLayoutMap *blockInfoOut) +{ + // Matrix packing is always recorded in individual fields, so they'll set the row major layout + // flag to true if needed. + // Iterates over all variables. + GetInterfaceBlockInfo(fields, prefix, encoder, false, false, blockInfoOut); +} + +void GetActiveUniformBlockInfo(const std::vector &uniforms, + const std::string &prefix, + BlockLayoutEncoder *encoder, + BlockLayoutMap *blockInfoOut) +{ + // Matrix packing is always recorded in individual fields, so they'll set the row major layout + // flag to true if needed. + // Iterates only over the active variables. + GetInterfaceBlockInfo(uniforms, prefix, encoder, false, true, blockInfoOut); +} + +// VariableNameVisitor implementation. +VariableNameVisitor::VariableNameVisitor(const std::string &namePrefix, + const std::string &mappedNamePrefix) +{ + if (!namePrefix.empty()) + { + mNameStack.push_back(namePrefix + "."); + } + + if (!mappedNamePrefix.empty()) + { + mMappedNameStack.push_back(mappedNamePrefix + "."); + } +} + +VariableNameVisitor::~VariableNameVisitor() = default; + +void VariableNameVisitor::enterStruct(const ShaderVariable &structVar) +{ + mNameStack.push_back(structVar.name); + mMappedNameStack.push_back(structVar.mappedName); +} + +void VariableNameVisitor::exitStruct(const ShaderVariable &structVar) +{ + mNameStack.pop_back(); + mMappedNameStack.pop_back(); +} + +void VariableNameVisitor::enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) +{ + mNameStack.push_back("."); + mMappedNameStack.push_back("."); +} + +void VariableNameVisitor::exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) +{ + mNameStack.pop_back(); + mMappedNameStack.pop_back(); +} + +void VariableNameVisitor::enterArray(const ShaderVariable &arrayVar) +{ + if (!arrayVar.hasParentArrayIndex() && !arrayVar.isStruct()) + { + mNameStack.push_back(arrayVar.name); + mMappedNameStack.push_back(arrayVar.mappedName); + } + mArraySizeStack.push_back(arrayVar.getOutermostArraySize()); +} + +void VariableNameVisitor::exitArray(const ShaderVariable &arrayVar) +{ + if (!arrayVar.hasParentArrayIndex() && !arrayVar.isStruct()) + { + mNameStack.pop_back(); + mMappedNameStack.pop_back(); + } + mArraySizeStack.pop_back(); +} + +void VariableNameVisitor::enterArrayElement(const ShaderVariable &arrayVar, + unsigned int arrayElement) +{ + std::stringstream strstr = sh::InitializeStream(); + strstr << "[" << arrayElement << "]"; + std::string elementString = strstr.str(); + mNameStack.push_back(elementString); + mMappedNameStack.push_back(elementString); +} + +void VariableNameVisitor::exitArrayElement(const ShaderVariable &arrayVar, + unsigned int arrayElement) +{ + mNameStack.pop_back(); + mMappedNameStack.pop_back(); +} + +std::string VariableNameVisitor::collapseNameStack() const +{ + return CollapseNameStack(mNameStack); +} + +std::string VariableNameVisitor::collapseMappedNameStack() const +{ + return CollapseNameStack(mMappedNameStack); +} + +void VariableNameVisitor::visitOpaqueObject(const sh::ShaderVariable &variable) +{ + if (!variable.hasParentArrayIndex()) + { + mNameStack.push_back(variable.name); + mMappedNameStack.push_back(variable.mappedName); + } + + std::string name = collapseNameStack(); + std::string mappedName = collapseMappedNameStack(); + + if (!variable.hasParentArrayIndex()) + { + mNameStack.pop_back(); + mMappedNameStack.pop_back(); + } + + visitNamedOpaqueObject(variable, name, mappedName, mArraySizeStack); +} + +void VariableNameVisitor::visitVariable(const ShaderVariable &variable, bool isRowMajor) +{ + if (!variable.hasParentArrayIndex()) + { + mNameStack.push_back(variable.name); + mMappedNameStack.push_back(variable.mappedName); + } + + std::string name = collapseNameStack(); + std::string mappedName = collapseMappedNameStack(); + + if (!variable.hasParentArrayIndex()) + { + mNameStack.pop_back(); + mMappedNameStack.pop_back(); + } + + visitNamedVariable(variable, isRowMajor, name, mappedName, mArraySizeStack); +} + +// BlockEncoderVisitor implementation. +BlockEncoderVisitor::BlockEncoderVisitor(const std::string &namePrefix, + const std::string &mappedNamePrefix, + BlockLayoutEncoder *encoder) + : VariableNameVisitor(namePrefix, mappedNamePrefix), mEncoder(encoder) +{} + +BlockEncoderVisitor::~BlockEncoderVisitor() = default; + +void BlockEncoderVisitor::enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) +{ + mStructStackSize++; + if (!mIsTopLevelArrayStrideReady) + { + size_t structSize = mEncoder->getShaderVariableSize(structVar, isRowMajor); + mTopLevelArrayStride *= structSize; + mIsTopLevelArrayStrideReady = true; + } + + VariableNameVisitor::enterStructAccess(structVar, isRowMajor); + mEncoder->enterAggregateType(structVar); +} + +void BlockEncoderVisitor::exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) +{ + mStructStackSize--; + mEncoder->exitAggregateType(structVar); + VariableNameVisitor::exitStructAccess(structVar, isRowMajor); +} + +void BlockEncoderVisitor::enterArrayElement(const sh::ShaderVariable &arrayVar, + unsigned int arrayElement) +{ + if (mStructStackSize == 0 && !arrayVar.hasParentArrayIndex()) + { + // From the ES 3.1 spec "7.3.1.1 Naming Active Resources": + // For an active shader storage block member declared as an array of an aggregate type, + // an entry will be generated only for the first array element, regardless of its type. + // Such block members are referred to as top-level arrays. If the block member is an + // aggregate type, the enumeration rules are then applied recursively. + if (arrayElement == 0) + { + mTopLevelArraySize = arrayVar.getOutermostArraySize(); + mTopLevelArrayStride = arrayVar.getInnerArraySizeProduct(); + mIsTopLevelArrayStrideReady = false; + } + else + { + mSkipEnabled = true; + } + } + VariableNameVisitor::enterArrayElement(arrayVar, arrayElement); +} + +void BlockEncoderVisitor::exitArrayElement(const sh::ShaderVariable &arrayVar, + unsigned int arrayElement) +{ + if (mStructStackSize == 0 && !arrayVar.hasParentArrayIndex()) + { + mTopLevelArraySize = 1; + mTopLevelArrayStride = 0; + mIsTopLevelArrayStrideReady = true; + mSkipEnabled = false; + } + VariableNameVisitor::exitArrayElement(arrayVar, arrayElement); +} + +void BlockEncoderVisitor::visitNamedVariable(const ShaderVariable &variable, + bool isRowMajor, + const std::string &name, + const std::string &mappedName, + const std::vector &arraySizes) +{ + std::vector innermostArraySize; + + if (variable.isArray()) + { + innermostArraySize.push_back(variable.getNestedArraySize(0)); + } + BlockMemberInfo variableInfo = + mEncoder->encodeType(variable.type, innermostArraySize, isRowMajor); + if (!mIsTopLevelArrayStrideReady) + { + ASSERT(mTopLevelArrayStride); + mTopLevelArrayStride *= variableInfo.arrayStride; + mIsTopLevelArrayStrideReady = true; + } + variableInfo.topLevelArrayStride = mTopLevelArrayStride; + encodeVariable(variable, variableInfo, name, mappedName); +} + +void TraverseShaderVariable(const ShaderVariable &variable, + bool isRowMajorLayout, + ShaderVariableVisitor *visitor) +{ + bool rowMajorLayout = (isRowMajorLayout || variable.isRowMajorLayout); + bool isRowMajor = rowMajorLayout && gl::IsMatrixType(variable.type); + + if (variable.isStruct()) + { + visitor->enterStruct(variable); + if (variable.isArray()) + { + TraverseStructArrayVariable(variable, rowMajorLayout, visitor); + } + else + { + TraverseStructVariable(variable, rowMajorLayout, visitor); + } + visitor->exitStruct(variable); + } + else if (variable.isArrayOfArrays()) + { + TraverseArrayOfArraysVariable(variable, 0u, isRowMajor, visitor); + } + else if (gl::IsSamplerType(variable.type) || gl::IsImageType(variable.type) || + variable.isFragmentInOut) + { + visitor->visitOpaqueObject(variable); + } + else + { + visitor->visitVariable(variable, isRowMajor); + } +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/blocklayout.h b/gfx/angle/checkout/src/compiler/translator/blocklayout.h new file mode 100644 index 0000000000..97f9daa251 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/blocklayout.h @@ -0,0 +1,322 @@ +// +// Copyright 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// blocklayout.h: +// Methods and classes related to uniform layout and packing in GLSL and HLSL. +// + +#ifndef COMMON_BLOCKLAYOUT_H_ +#define COMMON_BLOCKLAYOUT_H_ + +#include +#include +#include + +#include +#include "angle_gl.h" + +namespace sh +{ +struct ShaderVariable; +struct InterfaceBlock; + +struct BlockMemberInfo +{ + constexpr BlockMemberInfo() = default; + + constexpr BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix) + : offset(offset), + arrayStride(arrayStride), + matrixStride(matrixStride), + isRowMajorMatrix(isRowMajorMatrix) + {} + + constexpr BlockMemberInfo(int offset, + int arrayStride, + int matrixStride, + bool isRowMajorMatrix, + int topLevelArrayStride) + : offset(offset), + arrayStride(arrayStride), + matrixStride(matrixStride), + isRowMajorMatrix(isRowMajorMatrix), + topLevelArrayStride(topLevelArrayStride) + {} + + // A single integer identifying the offset of an active variable. + int offset = -1; + + // A single integer identifying the stride between array elements in an active variable. + int arrayStride = -1; + + // A single integer identifying the stride between columns of a column-major matrix or rows of a + // row-major matrix. + int matrixStride = -1; + + // A single integer identifying whether an active variable is a row-major matrix. + bool isRowMajorMatrix = false; + + // A single integer identifying the number of active array elements of the top-level shader + // storage block member containing the active variable. + int topLevelArrayStride = -1; +}; + +constexpr size_t ComponentAlignment(size_t numComponents) +{ + return (numComponents == 3u ? 4u : numComponents); +} + +constexpr BlockMemberInfo kDefaultBlockMemberInfo; + +class BlockLayoutEncoder +{ + public: + BlockLayoutEncoder(); + virtual ~BlockLayoutEncoder() {} + + BlockMemberInfo encodeType(GLenum type, + const std::vector &arraySizes, + bool isRowMajorMatrix); + // Advance the offset based on struct size and array dimensions. Size can be calculated with + // getShaderVariableSize() or equivalent. |enterAggregateType|/|exitAggregateType| is necessary + // around this call. + BlockMemberInfo encodeArrayOfPreEncodedStructs(size_t size, + const std::vector &arraySizes); + + size_t getCurrentOffset() const; + size_t getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor); + + // Called when entering/exiting a structure variable. + virtual void enterAggregateType(const ShaderVariable &structVar) = 0; + virtual void exitAggregateType(const ShaderVariable &structVar) = 0; + + static constexpr size_t kBytesPerComponent = 4u; + static constexpr unsigned int kComponentsPerRegister = 4u; + + static size_t GetBlockRegister(const BlockMemberInfo &info); + static size_t GetBlockRegisterElement(const BlockMemberInfo &info); + + protected: + void align(size_t baseAlignment); + + virtual void getBlockLayoutInfo(GLenum type, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int *arrayStrideOut, + int *matrixStrideOut) = 0; + virtual void advanceOffset(GLenum type, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int arrayStride, + int matrixStride) = 0; + + size_t mCurrentOffset; +}; + +// Will return default values for everything. +class StubBlockEncoder : public BlockLayoutEncoder +{ + public: + StubBlockEncoder() = default; + + void enterAggregateType(const ShaderVariable &structVar) override {} + void exitAggregateType(const ShaderVariable &structVar) override {} + + protected: + void getBlockLayoutInfo(GLenum type, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int *arrayStrideOut, + int *matrixStrideOut) override; + + void advanceOffset(GLenum type, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int arrayStride, + int matrixStride) override + {} +}; + +// Block layout according to the std140 block layout +// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification + +class Std140BlockEncoder : public BlockLayoutEncoder +{ + public: + Std140BlockEncoder(); + + void enterAggregateType(const ShaderVariable &structVar) override; + void exitAggregateType(const ShaderVariable &structVar) override; + + protected: + void getBlockLayoutInfo(GLenum type, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int *arrayStrideOut, + int *matrixStrideOut) override; + void advanceOffset(GLenum type, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int arrayStride, + int matrixStride) override; + + virtual size_t getBaseAlignment(const ShaderVariable &variable) const; + virtual size_t getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const; +}; + +class Std430BlockEncoder : public Std140BlockEncoder +{ + public: + Std430BlockEncoder(); + + protected: + size_t getBaseAlignment(const ShaderVariable &variable) const override; + size_t getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const override; +}; + +using BlockLayoutMap = std::map; + +void GetInterfaceBlockInfo(const std::vector &fields, + const std::string &prefix, + BlockLayoutEncoder *encoder, + BlockLayoutMap *blockInfoOut); + +// Used for laying out the default uniform block on the Vulkan backend. +void GetActiveUniformBlockInfo(const std::vector &uniforms, + const std::string &prefix, + BlockLayoutEncoder *encoder, + BlockLayoutMap *blockInfoOut); + +class ShaderVariableVisitor +{ + public: + virtual ~ShaderVariableVisitor() {} + + virtual void enterStruct(const ShaderVariable &structVar) {} + virtual void exitStruct(const ShaderVariable &structVar) {} + + virtual void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) {} + virtual void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) {} + + virtual void enterArray(const ShaderVariable &arrayVar) {} + virtual void exitArray(const ShaderVariable &arrayVar) {} + + virtual void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) {} + virtual void exitArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) {} + + virtual void visitOpaqueObject(const sh::ShaderVariable &variable) {} + + virtual void visitVariable(const ShaderVariable &variable, bool isRowMajor) = 0; + + protected: + ShaderVariableVisitor() {} +}; + +class VariableNameVisitor : public ShaderVariableVisitor +{ + public: + VariableNameVisitor(const std::string &namePrefix, const std::string &mappedNamePrefix); + ~VariableNameVisitor() override; + + void enterStruct(const ShaderVariable &structVar) override; + void exitStruct(const ShaderVariable &structVar) override; + void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override; + void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) override; + void enterArray(const ShaderVariable &arrayVar) override; + void exitArray(const ShaderVariable &arrayVar) override; + void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override; + void exitArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override; + + protected: + virtual void visitNamedOpaqueObject(const sh::ShaderVariable &variable, + const std::string &name, + const std::string &mappedName, + const std::vector &arraySizes) + {} + virtual void visitNamedVariable(const ShaderVariable &variable, + bool isRowMajor, + const std::string &name, + const std::string &mappedName, + const std::vector &arraySizes) = 0; + + std::string collapseNameStack() const; + std::string collapseMappedNameStack() const; + + private: + void visitOpaqueObject(const sh::ShaderVariable &variable) final; + void visitVariable(const ShaderVariable &variable, bool isRowMajor) final; + + std::vector mNameStack; + std::vector mMappedNameStack; + std::vector mArraySizeStack; +}; + +class BlockEncoderVisitor : public VariableNameVisitor +{ + public: + BlockEncoderVisitor(const std::string &namePrefix, + const std::string &mappedNamePrefix, + BlockLayoutEncoder *encoder); + ~BlockEncoderVisitor() override; + + void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override; + void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) override; + void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override; + void exitArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override; + + void visitNamedVariable(const ShaderVariable &variable, + bool isRowMajor, + const std::string &name, + const std::string &mappedName, + const std::vector &arraySizes) override; + + virtual void encodeVariable(const ShaderVariable &variable, + const BlockMemberInfo &variableInfo, + const std::string &name, + const std::string &mappedName) + {} + + protected: + int mTopLevelArraySize = 1; + int mTopLevelArrayStride = 0; + bool mIsTopLevelArrayStrideReady = true; + bool mSkipEnabled = false; + + private: + BlockLayoutEncoder *mEncoder; + unsigned int mStructStackSize = 0; +}; + +void TraverseShaderVariable(const ShaderVariable &variable, + bool isRowMajorLayout, + ShaderVariableVisitor *visitor); + +template +void TraverseShaderVariables(const std::vector &vars, + bool isRowMajorLayout, + ShaderVariableVisitor *visitor) +{ + for (const T &var : vars) + { + TraverseShaderVariable(var, isRowMajorLayout, visitor); + } +} + +template +void TraverseActiveShaderVariables(const std::vector &vars, + bool isRowMajorLayout, + ShaderVariableVisitor *visitor) +{ + for (const T &var : vars) + { + if (var.active) + { + TraverseShaderVariable(var, isRowMajorLayout, visitor); + } + } +} +} // namespace sh + +#endif // COMMON_BLOCKLAYOUT_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/blocklayoutHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/blocklayoutHLSL.cpp new file mode 100644 index 0000000000..9030c7f370 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/blocklayoutHLSL.cpp @@ -0,0 +1,167 @@ +// +// Copyright 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// blocklayout.cpp: +// Implementation for block layout classes and methods. +// + +#include "compiler/translator/blocklayoutHLSL.h" + +#include "common/mathutil.h" +#include "common/utilities.h" + +namespace sh +{ + +HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices) + : mEncoderStrategy(strategy), mTransposeMatrices(transposeMatrices) +{} + +void HLSLBlockEncoder::enterAggregateType(const ShaderVariable &structVar) +{ + align(kComponentsPerRegister); +} + +void HLSLBlockEncoder::exitAggregateType(const ShaderVariable &structVar) {} + +void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int *arrayStrideOut, + int *matrixStrideOut) +{ + GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn); + + // We assume we are only dealing with 4 byte components (no doubles or half-words currently) + ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == kBytesPerComponent); + + int matrixStride = 0; + int arrayStride = 0; + + // if variables are not to be packed, or we're about to + // pack a matrix or array, skip to the start of the next + // register + if (!isPacked() || gl::IsMatrixType(type) || !arraySizes.empty()) + { + align(kComponentsPerRegister); + } + + if (gl::IsMatrixType(type)) + { + matrixStride = kComponentsPerRegister; + + if (!arraySizes.empty()) + { + const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); + arrayStride = kComponentsPerRegister * numRegisters; + } + } + else if (!arraySizes.empty()) + { + arrayStride = kComponentsPerRegister; + } + else if (isPacked()) + { + int numComponents = gl::VariableComponentCount(type); + if ((numComponents + (mCurrentOffset % kComponentsPerRegister)) > kComponentsPerRegister) + { + align(kComponentsPerRegister); + } + } + + *matrixStrideOut = matrixStride; + *arrayStrideOut = arrayStride; +} + +void HLSLBlockEncoder::advanceOffset(GLenum typeIn, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int arrayStride, + int matrixStride) +{ + GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn); + + if (!arraySizes.empty()) + { + unsigned int arraySize = gl::ArraySizeProduct(arraySizes); + if (arraySize > 0) + { + mCurrentOffset += arrayStride * (arraySize - 1); + } + } + + if (gl::IsMatrixType(type)) + { + ASSERT(matrixStride == kComponentsPerRegister); + const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); + const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix); + mCurrentOffset += kComponentsPerRegister * (numRegisters - 1); + mCurrentOffset += numComponents; + } + else if (isPacked()) + { + mCurrentOffset += gl::VariableComponentCount(type); + } + else + { + mCurrentOffset += kComponentsPerRegister; + } +} + +void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters) +{ + mCurrentOffset += (numRegisters * kComponentsPerRegister); +} + +HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor( + ShShaderOutput outputType) +{ + switch (outputType) + { + case SH_HLSL_3_0_OUTPUT: + return ENCODE_LOOSE; + case SH_HLSL_4_1_OUTPUT: + case SH_HLSL_4_0_FL9_3_OUTPUT: + return ENCODE_PACKED; + default: + UNREACHABLE(); + return ENCODE_PACKED; + } +} + +template +void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder) +{ + if (variable.isStruct()) + { + for (size_t arrayElement = 0; arrayElement < variable.getArraySizeProduct(); arrayElement++) + { + encoder->enterAggregateType(variable); + + for (const ShaderVariable &field : variable.fields) + { + HLSLVariableRegisterCount(field, encoder); + } + + encoder->exitAggregateType(variable); + } + } + else + { + // We operate only on varyings and uniforms, which do not have matrix layout qualifiers + encoder->encodeType(variable.type, variable.arraySizes, false); + } +} + +unsigned int HLSLVariableRegisterCount(const ShaderVariable &variable, ShShaderOutput outputType) +{ + HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType), true); + HLSLVariableRegisterCount(variable, &encoder); + + const size_t registerBytes = (encoder.kBytesPerComponent * encoder.kComponentsPerRegister); + return static_cast( + rx::roundUp(encoder.getCurrentOffset(), registerBytes) / registerBytes); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/blocklayoutHLSL.h b/gfx/angle/checkout/src/compiler/translator/blocklayoutHLSL.h new file mode 100644 index 0000000000..8ed46b7728 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/blocklayoutHLSL.h @@ -0,0 +1,68 @@ +// +// Copyright 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// blocklayout.h: +// Methods and classes related to uniform layout and packing in GLSL and HLSL. +// + +#ifndef COMMON_BLOCKLAYOUTHLSL_H_ +#define COMMON_BLOCKLAYOUTHLSL_H_ + +#include +#include + +#include +#include "angle_gl.h" +#include "blocklayout.h" + +namespace sh +{ +// Block layout packed according to the D3D9 or default D3D10+ register packing rules +// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx +// The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED +// for everything else (D3D10+ constant blocks and all attributes/varyings). + +class HLSLBlockEncoder : public BlockLayoutEncoder +{ + public: + enum HLSLBlockEncoderStrategy + { + ENCODE_PACKED, + ENCODE_LOOSE + }; + + HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices); + + void enterAggregateType(const ShaderVariable &structVar) override; + void exitAggregateType(const ShaderVariable &structVar) override; + void skipRegisters(unsigned int numRegisters); + + bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; } + + static HLSLBlockEncoderStrategy GetStrategyFor(ShShaderOutput outputType); + + protected: + void getBlockLayoutInfo(GLenum type, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int *arrayStrideOut, + int *matrixStrideOut) override; + void advanceOffset(GLenum type, + const std::vector &arraySizes, + bool isRowMajorMatrix, + int arrayStride, + int matrixStride) override; + + HLSLBlockEncoderStrategy mEncoderStrategy; + bool mTransposeMatrices; +}; + +// This method returns the number of used registers for a ShaderVariable. It is dependent on the +// HLSLBlockEncoder class to count the number of used registers in a struct (which are individually +// packed according to the same rules). +unsigned int HLSLVariableRegisterCount(const ShaderVariable &variable, ShShaderOutput outputType); +} // namespace sh + +#endif // COMMON_BLOCKLAYOUTHLSL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp b/gfx/angle/checkout/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp new file mode 100644 index 0000000000..5b81f13869 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp @@ -0,0 +1,881 @@ +// GENERATED FILE - DO NOT EDIT. +// Generated by gen_emulated_builtin_function_tables.py using data from +// emulated_builtin_function_data_hlsl.json. +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// emulated_builtin_functions_hlsl: +// HLSL code for emulating GLSL builtin functions not present in HLSL. + +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/tree_util/BuiltIn.h" + +namespace sh +{ + +namespace +{ + +struct FunctionPair +{ + constexpr FunctionPair(const TSymbolUniqueId &idIn, const char *bodyIn) + : id(idIn.get()), body(bodyIn) + {} + + int id; + const char *body; +}; + +constexpr FunctionPair g_hlslFunctions[] = { + {BuiltInId::mod_Float1_Float1, + "float mod_emu(float x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n"}, + {BuiltInId::mod_Float2_Float2, + "float2 mod_emu(float2 x, float2 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n"}, + {BuiltInId::mod_Float2_Float1, + "float2 mod_emu(float2 x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n"}, + {BuiltInId::mod_Float3_Float3, + "float3 mod_emu(float3 x, float3 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n"}, + {BuiltInId::mod_Float3_Float1, + "float3 mod_emu(float3 x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n"}, + {BuiltInId::mod_Float4_Float4, + "float4 mod_emu(float4 x, float4 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n"}, + {BuiltInId::mod_Float4_Float1, + "float4 mod_emu(float4 x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n"}, + {BuiltInId::frexp_Float1_Int1, + "float frexp_emu(float x, out int exp)\n" + "{\n" + " float fexp;\n" + " float mantissa = frexp(abs(x), fexp) * sign(x);\n" + " exp = int(fexp);\n" + " return mantissa;\n" + "}\n"}, + {BuiltInId::frexp_Float2_Int2, + "float2 frexp_emu(float2 x, out int2 exp)\n" + "{\n" + " float2 fexp;\n" + " float2 mantissa = frexp(abs(x), fexp) * sign(x);\n" + " exp = int2(fexp);\n" + " return mantissa;\n" + "}\n"}, + {BuiltInId::frexp_Float3_Int3, + "float3 frexp_emu(float3 x, out int3 exp)\n" + "{\n" + " float3 fexp;\n" + " float3 mantissa = frexp(abs(x), fexp) * sign(x);\n" + " exp = int3(fexp);\n" + " return mantissa;\n" + "}\n"}, + {BuiltInId::frexp_Float4_Int4, + "float4 frexp_emu(float4 x, out int4 exp)\n" + "{\n" + " float4 fexp;\n" + " float4 mantissa = frexp(abs(x), fexp) * sign(x);\n" + " exp = int4(fexp);\n" + " return mantissa;\n" + "}\n"}, + {BuiltInId::ldexp_Float1_Int1, + "float ldexp_emu(float x, int exp)\n" + "{\n" + " return ldexp(x, float(exp));\n" + "}\n"}, + {BuiltInId::ldexp_Float2_Int2, + "float2 ldexp_emu(float2 x, int2 exp)\n" + "{\n" + " return ldexp(x, float2(exp));\n" + "}\n"}, + {BuiltInId::ldexp_Float3_Int3, + "float3 ldexp_emu(float3 x, int3 exp)\n" + "{\n" + " return ldexp(x, float3(exp));\n" + "}\n"}, + {BuiltInId::ldexp_Float4_Int4, + "float4 ldexp_emu(float4 x, int4 exp)\n" + "{\n" + " return ldexp(x, float4(exp));\n" + "}\n"}, + {BuiltInId::faceforward_Float1_Float1_Float1, + "float faceforward_emu(float N, float I, float Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n"}, + {BuiltInId::faceforward_Float2_Float2_Float2, + "float2 faceforward_emu(float2 N, float2 I, float2 Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n"}, + {BuiltInId::faceforward_Float3_Float3_Float3, + "float3 faceforward_emu(float3 N, float3 I, float3 Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n"}, + {BuiltInId::faceforward_Float4_Float4_Float4, + "float4 faceforward_emu(float4 N, float4 I, float4 Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n"}, + {BuiltInId::atan_Float1_Float1, + "float atan_emu(float y, float x)\n" + "{\n" + " if(x == 0 && y == 0) x = 1;\n" + " return atan2(y, x);\n" + "}\n"}, + {BuiltInId::atan_Float2_Float2, + "float2 atan_emu(float2 y, float2 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n" + "}\n"}, + {BuiltInId::atan_Float3_Float3, + "float3 atan_emu(float3 y, float3 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" + " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n" + "}\n"}, + {BuiltInId::atan_Float4_Float4, + "float4 atan_emu(float4 y, float4 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" + " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n" + " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], \n" + " x[2]), atan2(y[3], x[3]));\n" + "}\n"}, + {BuiltInId::asinh_Float1, + "float asinh_emu(in float x)\n" + "{\n" + " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" + "}\n"}, + {BuiltInId::asinh_Float2, + "float2 asinh_emu(in float2 x)\n" + "{\n" + " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" + "}\n"}, + {BuiltInId::asinh_Float3, + "float3 asinh_emu(in float3 x)\n" + "{\n" + " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" + "}\n"}, + {BuiltInId::asinh_Float4, + "float4 asinh_emu(in float4 x)\n" + "{\n" + " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" + "}\n"}, + {BuiltInId::acosh_Float1, + "float acosh_emu(in float x)\n" + "{\n" + " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" + "}\n"}, + {BuiltInId::acosh_Float2, + "float2 acosh_emu(in float2 x)\n" + "{\n" + " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" + "}\n"}, + {BuiltInId::acosh_Float3, + "float3 acosh_emu(in float3 x)\n" + "{\n" + " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" + "}\n"}, + {BuiltInId::acosh_Float4, + "float4 acosh_emu(in float4 x)\n" + "{\n" + " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" + "}\n"}, + {BuiltInId::atanh_Float1, + "float atanh_emu(in float x)\n" + "{\n" + " return 0.5 * log((1.0 + x) / (1.0 - x));\n" + "}\n"}, + {BuiltInId::atanh_Float2, + "float2 atanh_emu(in float2 x)\n" + "{\n" + " return 0.5 * log((1.0 + x) / (1.0 - x));\n" + "}\n"}, + {BuiltInId::atanh_Float3, + "float3 atanh_emu(in float3 x)\n" + "{\n" + " return 0.5 * log((1.0 + x) / (1.0 - x));\n" + "}\n"}, + {BuiltInId::atanh_Float4, + "float4 atanh_emu(in float4 x)\n" + "{\n" + " return 0.5 * log((1.0 + x) / (1.0 - x));\n" + "}\n"}, + {BuiltInId::roundEven_Float1, + "float roundEven_emu(in float x)\n" + "{\n" + " return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n" + "}\n"}, + {BuiltInId::roundEven_Float2, + "float2 roundEven_emu(in float2 x)\n" + "{\n" + " float2 v;\n" + " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" + " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" + " return v;\n" + "}\n"}, + {BuiltInId::roundEven_Float3, + "float3 roundEven_emu(in float3 x)\n" + "{\n" + " float3 v;\n" + " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" + " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" + " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n" + " return v;\n" + "}\n"}, + {BuiltInId::roundEven_Float4, + "float4 roundEven_emu(in float4 x)\n" + "{\n" + " float4 v;\n" + " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" + " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" + " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n" + " v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n" + " return v;\n" + "}\n"}, + {BuiltInId::packSnorm2x16_Float2, + "int webgl_toSnorm16(in float x) {\n" + " return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n" + "}\n" + "uint packSnorm2x16_emu(in float2 v)\n" + "{\n" + " int x = webgl_toSnorm16(v.x);\n" + " int y = webgl_toSnorm16(v.y);\n" + " return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n" + "}\n"}, + {BuiltInId::packUnorm2x16_Float2, + "uint webgl_toUnorm16(in float x) {\n" + " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n" + "}\n" + "uint packUnorm2x16_emu(in float2 v)\n" + "{\n" + " uint x = webgl_toUnorm16(v.x);\n" + " uint y = webgl_toUnorm16(v.y);\n" + " return (y << 16) | x;\n" + "}\n"}, + {BuiltInId::packHalf2x16_Float2, + "uint packHalf2x16_emu(in float2 v)\n" + "{\n" + " uint x = f32tof16(v.x);\n" + " uint y = f32tof16(v.y);\n" + " return (y << 16) | x;\n" + "}\n"}, + {BuiltInId::unpackSnorm2x16_UInt1, + "float webgl_fromSnorm16(in uint x) {\n" + " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n" + " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n" + "}\n" + "float2 unpackSnorm2x16_emu(in uint u)\n" + "{\n" + " uint y = (u >> 16);\n" + " uint x = u;\n" + " return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));\n" + "}\n"}, + {BuiltInId::unpackUnorm2x16_UInt1, + "float webgl_fromUnorm16(in uint x) {\n" + " return float(x) / 65535.0;\n" + "}\n" + "float2 unpackUnorm2x16_emu(in uint u)\n" + "{\n" + " uint y = (u >> 16);\n" + " uint x = u & 0xffffu;\n" + " return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));\n" + "}\n"}, + {BuiltInId::unpackHalf2x16_UInt1, + "float2 unpackHalf2x16_emu(in uint u)\n" + "{\n" + " uint y = (u >> 16);\n" + " uint x = u & 0xffffu;\n" + " return float2(f16tof32(x), f16tof32(y));\n" + "}\n"}, + {BuiltInId::packSnorm4x8_Float4, + "int webgl_toSnorm8(in float x) {\n" + " return int(round(clamp(x, -1.0, 1.0) * 127.0));\n" + "}\n" + "uint packSnorm4x8_emu(in float4 v)\n" + "{\n" + " int x = webgl_toSnorm8(v.x);\n" + " int y = webgl_toSnorm8(v.y);\n" + " int z = webgl_toSnorm8(v.z);\n" + " int w = webgl_toSnorm8(v.w);\n" + " return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) \n" + " | ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);\n" + "}\n"}, + {BuiltInId::packUnorm4x8_Float4, + "uint webgl_toUnorm8(in float x) {\n" + " return uint(round(clamp(x, 0.0, 1.0) * 255.0));\n" + "}\n" + "uint packUnorm4x8_emu(in float4 v)\n" + "{\n" + " uint x = webgl_toUnorm8(v.x);\n" + " uint y = webgl_toUnorm8(v.y);\n" + " uint z = webgl_toUnorm8(v.z);\n" + " uint w = webgl_toUnorm8(v.w);\n" + " return (w << 24) | (z << 16) | (y << 8) | x;\n" + "}\n"}, + {BuiltInId::unpackSnorm4x8_UInt1, + "float webgl_fromSnorm8(in uint x) {\n" + " int xi = asint(x & 0x7fu) - asint(x & 0x80u);\n" + " return clamp(float(xi) / 127.0, -1.0, 1.0);\n" + "}\n" + "float4 unpackSnorm4x8_emu(in uint u)\n" + "{\n" + " uint w = (u >> 24);\n" + " uint z = (u >> 16);\n" + " uint y = (u >> 8);\n" + " uint x = u;\n" + " return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), \n" + " webgl_fromSnorm8(z), webgl_fromSnorm8(w));\n" + "}\n"}, + {BuiltInId::unpackUnorm4x8_UInt1, + "float webgl_fromUnorm8(in uint x) {\n" + " return float(x) / 255.0;\n" + "}\n" + "float4 unpackUnorm4x8_emu(in uint u)\n" + "{\n" + " uint w = (u >> 24) & 0xffu;\n" + " uint z = (u >> 16) & 0xffu;\n" + " uint y = (u >> 8) & 0xffu;\n" + " uint x = u & 0xffu;\n" + " return float4(webgl_fromUnorm8(x), webgl_fromUnorm8(y), \n" + " webgl_fromUnorm8(z), webgl_fromUnorm8(w));\n" + "}\n"}, + // The matrix resulting from outer product needs to be transposed + // (matrices are stored as transposed to simplify element access in HLSL). + // So the function should return transpose(c * r) where c is a column vector + // and r is a row vector. This can be simplified by using the following + // formula: + // transpose(c * r) = transpose(r) * transpose(c) + // transpose(r) and transpose(c) are in a sense free, since to get the + // transpose of r, we simply can build a column matrix out of the original + // vector instead of a row matrix. + {BuiltInId::outerProduct_Float2_Float2, + "float2x2 outerProduct_emu(in float2 c, in float2 r)\n" + "{\n" + " return mul(float2x1(r), float1x2(c));\n" + "}\n"}, + {BuiltInId::outerProduct_Float3_Float3, + "float3x3 outerProduct_emu(in float3 c, in float3 r)\n" + "{\n" + " return mul(float3x1(r), float1x3(c));\n" + "}\n"}, + {BuiltInId::outerProduct_Float4_Float4, + "float4x4 outerProduct_emu(in float4 c, in float4 r)\n" + "{\n" + " return mul(float4x1(r), float1x4(c));\n" + "}\n"}, + {BuiltInId::outerProduct_Float3_Float2, + "float2x3 outerProduct_emu(in float3 c, in float2 r)\n" + "{\n" + " return mul(float2x1(r), float1x3(c));\n" + "}\n"}, + {BuiltInId::outerProduct_Float2_Float3, + "float3x2 outerProduct_emu(in float2 c, in float3 r)\n" + "{\n" + " return mul(float3x1(r), float1x2(c));\n" + "}\n"}, + {BuiltInId::outerProduct_Float4_Float2, + "float2x4 outerProduct_emu(in float4 c, in float2 r)\n" + "{\n" + " return mul(float2x1(r), float1x4(c));\n" + "}\n"}, + {BuiltInId::outerProduct_Float2_Float4, + "float4x2 outerProduct_emu(in float2 c, in float4 r)\n" + "{\n" + " return mul(float4x1(r), float1x2(c));\n" + "}\n"}, + {BuiltInId::outerProduct_Float4_Float3, + "float3x4 outerProduct_emu(in float4 c, in float3 r)\n" + "{\n" + " return mul(float3x1(r), float1x4(c));\n" + "}\n"}, + {BuiltInId::outerProduct_Float3_Float4, + "float4x3 outerProduct_emu(in float3 c, in float4 r)\n" + "{\n" + " return mul(float4x1(r), float1x3(c));\n" + "}\n"}, + // Remember here that the parameter matrix is actually the transpose + // of the matrix that we're trying to invert, and the resulting matrix + // should also be the transpose of the inverse. + // When accessing the parameter matrix with m[a][b] it can be thought of so + // that a is the column and b is the row of the matrix that we're inverting. + // We calculate the inverse as the adjugate matrix divided by the + // determinant of the matrix being inverted. However, as the result needs + // to be transposed, we actually use of the transpose of the adjugate matrix + // which happens to be the cofactor matrix. That's stored in 'cof'. + // We don't need to care about divide-by-zero since results are undefined + // for singular or poorly-conditioned matrices. + {BuiltInId::inverse_Float2x2, + "float2x2 inverse_emu(in float2x2 m)\n" + "{\n" + " float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n" + " return cof / determinant(transpose(m));\n" + "}\n"}, + // cofAB is the cofactor for column A and row B. + {BuiltInId::inverse_Float3x3, + "float3x3 inverse_emu(in float3x3 m)\n" + "{\n" + " float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n" + " float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n" + " float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];\n" + " float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n" + " float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];\n" + " float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n" + " float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];\n" + " float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n" + " float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];\n" + " float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n" + " return cof / determinant(transpose(m));\n" + "}\n"}, + {BuiltInId::inverse_Float4x4, + "float4x4 inverse_emu(in float4x4 m)\n" + "{\n" + " float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * \n" + " m[1][2] * m[2][3]\n" + " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * \n" + " m[1][3];\n" + " float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * \n" + " m[1][2] * m[2][3]\n" + " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * \n" + " m[1][3]);\n" + " float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * \n" + " m[1][1] * m[2][3]\n" + " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * \n" + " m[1][3];\n" + " float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * \n" + " m[1][1] * m[2][2]\n" + " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * \n" + " m[1][2]);\n" + " float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * \n" + " m[0][2] * m[2][3]\n" + " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * \n" + " m[0][3]);\n" + " float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * \n" + " m[0][2] * m[2][3]\n" + " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * \n" + " m[0][3];\n" + " float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * \n" + " m[0][1] * m[2][3]\n" + " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * \n" + " m[0][3]);\n" + " float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * \n" + " m[0][1] * m[2][2]\n" + " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * \n" + " m[0][2];\n" + " float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * \n" + " m[0][2] * m[1][3]\n" + " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * \n" + " m[0][3];\n" + " float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * \n" + " m[0][2] * m[1][3]\n" + " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * \n" + " m[0][3]);\n" + " float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * \n" + " m[0][1] * m[1][3]\n" + " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * \n" + " m[0][3];\n" + " float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * \n" + " m[0][1] * m[1][2]\n" + " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * \n" + " m[0][2]);\n" + " float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * \n" + " m[0][2] * m[1][3]\n" + " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * \n" + " m[0][3]);\n" + " float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * \n" + " m[0][2] * m[1][3]\n" + " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * \n" + " m[0][3];\n" + " float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * \n" + " m[0][1] * m[1][3]\n" + " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * \n" + " m[0][3]);\n" + " float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * \n" + " m[0][1] * m[1][2]\n" + " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * \n" + " m[0][2];\n" + " float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,\n" + " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n" + " return cof / determinant(transpose(m));\n" + "}\n"}, + // Emulate ESSL3 variant of mix that takes last argument as boolean vector. + // genType mix(genType x, genType y, genBType a): Selects which vector each returned component + // comes from. For a component of 'a' that is false, the corresponding component of 'x' is + // returned. For a component of 'a' that is true, the corresponding component of 'y' is + // returned. + {BuiltInId::mix_Float1_Float1_Bool1, + "float mix_emu(float x, float y, bool a)\n" + "{\n" + " return a ? y : x;\n" + "}\n"}, + {BuiltInId::mix_Float2_Float2_Bool2, + "float2 mix_emu(float2 x, float2 y, bool2 a)\n" + "{\n" + " return a ? y : x;\n" + "}\n"}, + {BuiltInId::mix_Float3_Float3_Bool3, + "float3 mix_emu(float3 x, float3 y, bool3 a)\n" + "{\n" + " return a ? y : x;\n" + "}\n"}, + {BuiltInId::mix_Float4_Float4_Bool4, + "float4 mix_emu(float4 x, float4 y, bool4 a)\n" + "{\n" + " return a ? y : x;\n" + "}\n"}, + {BuiltInId::bitfieldExtract_UInt1_Int1_Int1, + "uint bitfieldExtract_emu(uint value, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return 0u;\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " return (value & mask) >> offset;\n" + "}\n"}, + {BuiltInId::bitfieldExtract_UInt2_Int1_Int1, + "uint2 bitfieldExtract_emu(uint2 value, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return uint2(0u, 0u);\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " return (value & mask) >> offset;\n" + "}\n"}, + {BuiltInId::bitfieldExtract_UInt3_Int1_Int1, + "uint3 bitfieldExtract_emu(uint3 value, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return uint3(0u, 0u, 0u);\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " return (value & mask) >> offset;\n" + "}\n"}, + {BuiltInId::bitfieldExtract_UInt4_Int1_Int1, + "uint4 bitfieldExtract_emu(uint4 value, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return uint4(0u, 0u, 0u, 0u);\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " return (value & mask) >> offset;\n" + "}\n"}, + {BuiltInId::bitfieldExtract_Int1_Int1_Int1, + "int bitfieldExtract_emu(int value, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return 0;\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " uint resultUnsigned = (asuint(value) & mask) >> offset;\n" + " if (bits != 32 && (resultUnsigned & maskMsb) != 0)\n" + " {\n" + " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n" + " resultUnsigned |= higherBitsMask;\n" + " }\n" + " return asint(resultUnsigned);\n" + "}\n"}, + {BuiltInId::bitfieldExtract_Int2_Int1_Int1, + "int2 bitfieldExtract_emu(int2 value, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return int2(0, 0);\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " uint2 resultUnsigned = (asuint(value) & mask) >> offset;\n" + " if (bits != 32)\n" + " {\n" + " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n" + " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n" + " }\n" + " return asint(resultUnsigned);\n" + "}\n"}, + {BuiltInId::bitfieldExtract_Int3_Int1_Int1, + "int3 bitfieldExtract_emu(int3 value, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return int3(0, 0, 0);\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " uint3 resultUnsigned = (asuint(value) & mask) >> offset;\n" + " if (bits != 32)\n" + " {\n" + " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n" + " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n" + " }\n" + " return asint(resultUnsigned);\n" + "}\n"}, + {BuiltInId::bitfieldExtract_Int4_Int1_Int1, + "int4 bitfieldExtract_emu(int4 value, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return int4(0, 0, 0, 0);\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " uint4 resultUnsigned = (asuint(value) & mask) >> offset;\n" + " if (bits != 32)\n" + " {\n" + " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n" + " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n" + " }\n" + " return asint(resultUnsigned);\n" + "}\n"}, + {BuiltInId::bitfieldInsert_UInt1_UInt1_Int1_Int1, + "uint bitfieldInsert_emu(uint base, uint insert, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return base;\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " uint baseMask = ~insertMask;\n" + " return (base & baseMask) | ((insert << offset) & insertMask);\n" + "}\n"}, + {BuiltInId::bitfieldInsert_UInt2_UInt2_Int1_Int1, + "uint2 bitfieldInsert_emu(uint2 base, uint2 insert, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return base;\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " uint baseMask = ~insertMask;\n" + " return (base & baseMask) | ((insert << offset) & insertMask);\n" + "}\n"}, + {BuiltInId::bitfieldInsert_UInt3_UInt3_Int1_Int1, + "uint3 bitfieldInsert_emu(uint3 base, uint3 insert, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return base;\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " uint baseMask = ~insertMask;\n" + " return (base & baseMask) | ((insert << offset) & insertMask);\n" + "}\n"}, + {BuiltInId::bitfieldInsert_UInt4_UInt4_Int1_Int1, + "uint4 bitfieldInsert_emu(uint4 base, uint4 insert, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return base;\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " uint baseMask = ~insertMask;\n" + " return (base & baseMask) | ((insert << offset) & insertMask);\n" + "}\n"}, + {BuiltInId::bitfieldInsert_Int1_Int1_Int1_Int1, + "int bitfieldInsert_emu(int base, int insert, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return base;\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " uint baseMask = ~insertMask;\n" + " uint resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n" + " insertMask);\n" + " return asint(resultUnsigned);\n" + "}\n"}, + {BuiltInId::bitfieldInsert_Int2_Int2_Int1_Int1, + "int2 bitfieldInsert_emu(int2 base, int2 insert, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return base;\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " uint baseMask = ~insertMask;\n" + " uint2 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n" + " insertMask);\n" + " return asint(resultUnsigned);\n" + "}\n"}, + {BuiltInId::bitfieldInsert_Int3_Int3_Int1_Int1, + "int3 bitfieldInsert_emu(int3 base, int3 insert, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return base;\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " uint baseMask = ~insertMask;\n" + " uint3 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n" + " insertMask);\n" + " return asint(resultUnsigned);\n" + "}\n"}, + {BuiltInId::bitfieldInsert_Int4_Int4_Int1_Int1, + "int4 bitfieldInsert_emu(int4 base, int4 insert, int offset, int bits)\n" + "{\n" + " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" + " {\n" + " return base;\n" + " }\n" + " uint maskMsb = (1u << (bits - 1));\n" + " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" + " uint baseMask = ~insertMask;\n" + " uint4 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n" + " insertMask);\n" + " return asint(resultUnsigned);\n" + "}\n"}, + {BuiltInId::uaddCarry_UInt1_UInt1_UInt1, + "uint uaddCarry_emu(uint x, uint y, out uint carry)\n" + "{\n" + " carry = uint(x > (0xffffffffu - y));\n" + " return x + y;\n" + "}\n"}, + {BuiltInId::uaddCarry_UInt2_UInt2_UInt2, + "uint2 uaddCarry_emu(uint2 x, uint2 y, out uint2 carry)\n" + "{\n" + " carry = uint2(x > (0xffffffffu - y));\n" + " return x + y;\n" + "}\n"}, + {BuiltInId::uaddCarry_UInt3_UInt3_UInt3, + "uint3 uaddCarry_emu(uint3 x, uint3 y, out uint3 carry)\n" + "{\n" + " carry = uint3(x > (0xffffffffu - y));\n" + " return x + y;\n" + "}\n"}, + {BuiltInId::uaddCarry_UInt4_UInt4_UInt4, + "uint4 uaddCarry_emu(uint4 x, uint4 y, out uint4 carry)\n" + "{\n" + " carry = uint4(x > (0xffffffffu - y));\n" + " return x + y;\n" + "}\n"}, + {BuiltInId::usubBorrow_UInt1_UInt1_UInt1, + "uint usubBorrow_emu(uint x, uint y, out uint borrow)\n" + "{\n" + " borrow = uint(x < y);\n" + " return x - y;\n" + "}\n"}, + {BuiltInId::usubBorrow_UInt2_UInt2_UInt2, + "uint2 usubBorrow_emu(uint2 x, uint2 y, out uint2 borrow)\n" + "{\n" + " borrow = uint2(x < y);\n" + " return x - y;\n" + "}\n"}, + {BuiltInId::usubBorrow_UInt3_UInt3_UInt3, + "uint3 usubBorrow_emu(uint3 x, uint3 y, out uint3 borrow)\n" + "{\n" + " borrow = uint3(x < y);\n" + " return x - y;\n" + "}\n"}, + {BuiltInId::usubBorrow_UInt4_UInt4_UInt4, + "uint4 usubBorrow_emu(uint4 x, uint4 y, out uint4 borrow)\n" + "{\n" + " borrow = uint4(x < y);\n" + " return x - y;\n" + "}\n"}, + // We emulate tanh just to avoid overflow on large arguments. + {BuiltInId::tanh_Float1, + "float tanh_emu(float x)\n" + "{\n" + " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n" + "}\n"}, + {BuiltInId::tanh_Float2, + "float2 tanh_emu(float2 x)\n" + "{\n" + " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n" + "}\n"}, + {BuiltInId::tanh_Float3, + "float3 tanh_emu(float3 x)\n" + "{\n" + " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n" + "}\n"}, + {BuiltInId::tanh_Float4, + "float4 tanh_emu(float4 x)\n" + "{\n" + " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n" + "}\n"}, +}; +} // anonymous namespace + +const char *FindHLSLFunction(int uniqueId) +{ + for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index) + { + const auto &function = g_hlslFunctions[index]; + if (function.id == uniqueId) + { + return function.body; + } + } + + return nullptr; +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/glslang.h b/gfx/angle/checkout/src/compiler/translator/glslang.h new file mode 100644 index 0000000000..301da81cca --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/glslang.h @@ -0,0 +1,24 @@ +// +// Copyright 2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_GLSLANG_H_ +#define COMPILER_TRANSLATOR_GLSLANG_H_ + +namespace sh +{ +class TParseContext; +} + +extern int glslang_initialize(sh::TParseContext *context); +extern int glslang_finalize(sh::TParseContext *context); + +extern int glslang_scan(size_t count, + const char *const string[], + const int length[], + sh::TParseContext *context); +extern int glslang_parse(sh::TParseContext *context); + +#endif // COMPILER_TRANSLATOR_GLSLANG_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/glslang_lex_autogen.cpp b/gfx/angle/checkout/src/compiler/translator/glslang_lex_autogen.cpp new file mode 100644 index 0000000000..c806fd8e3a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/glslang_lex_autogen.cpp @@ -0,0 +1,4326 @@ +#line 17 "glslang.l" +// GENERATED FILE - DO NOT EDIT. +// Generated by generate_parser.py from glslang.l +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// glslang.l: +// Lexer for the OpenGL shading language. + +// Ignore errors in auto-generated code. +#if defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wswitch-enum" +# pragma GCC diagnostic ignored "-Wunused-function" +# pragma GCC diagnostic ignored "-Wunused-variable" +#elif defined(_MSC_VER) +# pragma warning(disable : 4005) +# pragma warning(disable : 4065) +# pragma warning(disable : 4189) +# pragma warning(disable : 4244) +# pragma warning(disable : 4505) +# pragma warning(disable : 4701) +# pragma warning(disable : 4702) +#endif +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wimplicit-fallthrough" +# if defined(__APPLE__) +// Older clang versions don't have -Wextra-semi-stmt, and detecting Apple clang versions is +// difficult because they use different yet overlapping version numbers vs. regular clang. +# pragma clang diagnostic ignored "-Wunknown-warning-option" +# endif +// Flex isn't semi-colon clean. +# pragma clang diagnostic ignored "-Wextra-semi-stmt" +# pragma clang diagnostic ignored "-Wunreachable-code" +#endif + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +# define FLEX_BETA +#endif + +#ifdef yyget_lval +# define yyget_lval_ALREADY_DEFINED +#else +# define yyget_lval yyget_lval +#endif + +#ifdef yyset_lval +# define yyset_lval_ALREADY_DEFINED +#else +# define yyset_lval yyset_lval +#endif + +#ifdef yyget_lloc +# define yyget_lloc_ALREADY_DEFINED +#else +# define yyget_lloc yyget_lloc +#endif + +#ifdef yyset_lloc +# define yyset_lloc_ALREADY_DEFINED +#else +# define yyset_lloc yyset_lloc +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +# define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +# ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS 1 +# endif + +# include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +# else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +# ifndef INT8_MIN +# define INT8_MIN (-128) +# endif +# ifndef INT16_MIN +# define INT16_MIN (-32767 - 1) +# endif +# ifndef INT32_MIN +# define INT32_MIN (-2147483647 - 1) +# endif +# ifndef INT8_MAX +# define INT8_MAX (127) +# endif +# ifndef INT16_MAX +# define INT16_MAX (32767) +# endif +# ifndef INT32_MAX +# define INT32_MAX (2147483647) +# endif +# ifndef UINT8_MAX +# define UINT8_MAX (255U) +# endif +# ifndef UINT16_MAX +# define UINT16_MAX (65535U) +# endif +# ifndef UINT32_MAX +# define UINT32_MAX (4294967295U) +# endif + +# ifndef SIZE_MAX +# define SIZE_MAX (~(size_t)0) +# endif + +# endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +# define yynoreturn __attribute__((__noreturn__)) +#else +# define yynoreturn +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an + * integer in range [0..255] for use as an array index. + */ +#define YY_SC_TO_UI(c) ((YY_CHAR)(c)) + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +# define YY_TYPEDEF_YY_SCANNER_T +typedef void *yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin, yyscanner) +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +# ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +# define YY_BUF_SIZE 32768 +# else +# define YY_BUF_SIZE 16384 +# endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +# define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +# define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* Note: We specifically omit the test for yy_rule_can_match_eol because it requires + * access to the local variable yy_act. Since yyless() is a macro, it would break + * existing scanners that call yyless() from OUTSIDE yylex. + * One obvious solution it to make yy_act a global. I tried that, and saw + * a 5% performance hit in a non-yylineno scanner, because yy_act is + * normally declared as a register variable-- so it is not worth it. + */ +#define YY_LESS_LINENO(n) \ + do \ + { \ + int yyl; \ + for (yyl = n; yyl < yyleng; ++yyl) \ + if (yytext[yyl] == '\n') \ + --yylineno; \ + } while (0) +#define YY_LINENO_REWIND_TO(dst) \ + do \ + { \ + const char *p; \ + for (p = yy_cp - 1; p >= (dst); --p) \ + if (*p == '\n') \ + --yylineno; \ + } while (0) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg); \ + *yy_cp = yyg->yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } while (0) +#define unput(c) yyunput(c, yyg->yytext_ptr, yyscanner) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +# define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state +{ + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +# define YY_BUFFER_NEW 0 +# define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +# define YY_BUFFER_EOF_PENDING 2 +}; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER \ + (yyg->yy_buffer_stack ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] : NULL) +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +void yyrestart(FILE *input_file, yyscan_t yyscanner); +void yy_switch_to_buffer(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner); +YY_BUFFER_STATE yy_create_buffer(FILE *file, int size, yyscan_t yyscanner); +void yy_delete_buffer(YY_BUFFER_STATE b, yyscan_t yyscanner); +void yy_flush_buffer(YY_BUFFER_STATE b, yyscan_t yyscanner); +void yypush_buffer_state(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner); +void yypop_buffer_state(yyscan_t yyscanner); + +static void yyensure_buffer_stack(yyscan_t yyscanner); +static void yy_load_buffer_state(yyscan_t yyscanner); +static void yy_init_buffer(YY_BUFFER_STATE b, FILE *file, yyscan_t yyscanner); +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER, yyscanner) + +YY_BUFFER_STATE yy_scan_buffer(char *base, yy_size_t size, yyscan_t yyscanner); +YY_BUFFER_STATE yy_scan_string(const char *yy_str, yyscan_t yyscanner); +YY_BUFFER_STATE yy_scan_bytes(const char *bytes, int len, yyscan_t yyscanner); + +void *yyalloc(yy_size_t, yyscan_t yyscanner); +void *yyrealloc(void *, yy_size_t, yyscan_t yyscanner); +void yyfree(void *, yyscan_t yyscanner); + +#define yy_new_buffer yy_create_buffer +#define yy_set_interactive(is_interactive) \ + { \ + if (!YY_CURRENT_BUFFER) \ + { \ + yyensure_buffer_stack(yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } +#define yy_set_bol(at_bol) \ + { \ + if (!YY_CURRENT_BUFFER) \ + { \ + yyensure_buffer_stack(yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define yywrap(yyscanner) (/*CONSTCOND*/ 1) +#define YY_SKIP_YYWRAP +typedef flex_uint8_t YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +static yy_state_type yy_get_previous_state(yyscan_t yyscanner); +static yy_state_type yy_try_NUL_trans(yy_state_type current_state, yyscan_t yyscanner); +static int yy_get_next_buffer(yyscan_t yyscanner); +static void yynoreturn yy_fatal_error(const char *msg, yyscan_t yyscanner); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ + yyleng = (int)(yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yyg->yy_c_buf_p = yy_cp; +#define YY_NUM_RULES 259 +#define YY_END_OF_BUFFER 260 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info +{ + flex_int32_t yy_verify; + flex_int32_t yy_nxt; +}; +static const flex_int16_t yy_accept[982] = { + 0, 0, 0, 0, 0, 260, 258, 257, 257, 241, 247, 252, 236, 237, 245, 244, 233, + 242, 240, 246, 199, 199, 234, 230, 248, 235, 249, 253, 196, 238, 239, 251, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 231, 250, 232, 243, 256, 255, 259, 254, 227, 213, 232, 221, 216, 211, + 219, 209, 220, 210, 205, 212, 204, 198, 199, 0, 202, 0, 239, 231, 238, 228, 224, + 226, 225, 229, 196, 217, 223, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + + 196, 196, 196, 196, 13, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 16, 196, 196, 26, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 218, 222, 254, 0, 208, 204, 0, 207, + 201, 0, 203, 197, 214, 215, 196, 196, 156, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + + 196, 14, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 31, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 27, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 0, 205, 0, + 204, 206, 200, 196, 196, 196, 196, 34, 196, 196, 196, 19, 193, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 17, 159, 196, 196, 196, 196, 22, 196, 196, + + 163, 174, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 171, + 4, 39, 40, 41, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 162, 35, 196, 196, + 32, 196, 196, 196, 196, 196, 196, 196, 196, 51, 52, 53, 33, 196, 196, 196, 196, + 196, 196, 196, 196, 11, 196, 57, 58, 59, 196, 157, 196, 196, 7, 196, 196, 196, + 196, 183, 184, 185, 196, 36, 196, 175, 30, 186, 187, 188, 2, 180, 181, + + 182, 196, 196, 196, 28, 178, 196, 196, 196, 196, 196, 196, 54, 55, 56, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 25, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 172, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 158, 196, 196, + 196, 195, 60, 61, 62, 196, 196, 15, 196, 196, 196, 135, 196, 196, 9, 196, 196, + 133, 196, 196, 196, 173, 168, 136, 196, 196, 196, 196, 196, 196, 164, 196, 196, 196, + 196, 196, 196, 97, 42, 45, 47, 46, 43, 49, 48, 50, 44, 196, 196, + + 196, 196, 179, 155, 196, 196, 196, 166, 196, 196, 196, 38, 126, 29, 192, 23, 167, + 96, 196, 177, 18, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 20, 37, 196, 196, 196, 196, 196, 196, 137, 102, 108, 196, 196, + 196, 196, 196, 196, 99, 101, 3, 196, 196, 196, 196, 196, 127, 196, 196, 196, 196, + 196, 196, 196, 160, 196, 196, 196, 196, 196, 8, 196, 196, 196, 10, 196, 196, 196, + 196, 196, 196, 21, 122, 12, 169, 138, 103, 110, 196, 196, 196, 196, 196, + + 196, 196, 196, 196, 196, 196, 196, 196, 196, 165, 196, 196, 196, 196, 120, 131, 123, + 196, 196, 196, 196, 196, 196, 196, 196, 161, 139, 104, 109, 196, 196, 176, 196, 196, + 124, 196, 196, 196, 196, 6, 196, 196, 196, 196, 196, 196, 196, 196, 196, 113, 170, + 1, 196, 196, 196, 196, 196, 196, 196, 194, 196, 134, 196, 5, 189, 63, 66, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 121, 196, 196, + 196, 196, 196, 196, 111, 196, 196, 196, 196, 196, 196, 196, 149, 71, 72, + + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 132, + 196, 196, 196, 112, 196, 151, 76, 77, 196, 196, 196, 196, 125, 196, 196, 196, 196, + 196, 196, 196, 196, 117, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 70, 196, 196, 196, 196, 64, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 118, 196, 140, 196, 105, 196, 196, 196, 196, + 196, 75, 196, 196, 73, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + + 196, 196, 196, 196, 196, 196, 196, 119, 196, 196, 196, 196, 80, 196, 196, 78, 196, + 196, 141, 106, 196, 196, 143, 196, 144, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 24, 196, 196, 196, 196, 196, 68, 196, 67, 89, 196, 196, 196, 196, 142, 107, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 114, 196, 196, 196, 196, + 153, 92, 196, 196, 196, 147, 196, 69, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 154, 94, 196, 196, 196, 115, 196, 196, 196, 150, 74, 196, + + 196, 196, 128, 196, 190, 196, 196, 196, 81, 196, 196, 196, 196, 116, 196, 152, 79, + 196, 196, 196, 196, 196, 196, 129, 196, 196, 196, 196, 196, 85, 196, 88, 196, 196, + 196, 130, 196, 196, 196, 196, 196, 196, 86, 91, 196, 196, 196, 196, 196, 82, 196, + 95, 87, 93, 98, 196, 145, 146, 100, 196, 196, 196, 196, 65, 196, 196, 196, 191, + 196, 196, 148, 83, 196, 196, 196, 196, 90, 196, 196, 84, 0}; + +static const YY_CHAR yy_ec[256] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 1, 1, 1, 5, 6, 1, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 1, 31, 32, 33, 34, 35, 36, 37, 38, 38, 38, 38, 39, 40, 41, 42, 38, 38, 43, 44, + 45, 46, 47, 48, 49, 50, 38, 51, 1, 52, 53, 54, 1, 55, 56, 57, 58, + + 59, 60, 61, 62, 63, 38, 64, 65, 66, 67, 68, 69, 38, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + +static const YY_CHAR yy_meta[83] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 3, 5, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 7, 6, 6, 6, 6, 1, 1, 1, 6, 4, 4, 4, 4, 3, 5, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 1, 1, 1, 1}; + +static const flex_int16_t yy_base[988] = { + 0, 0, 0, 82, 0, 1237, 1238, 1238, 1238, 1208, 137, 161, 1238, 1238, 1207, + 158, 1238, 157, 155, 1206, 177, 168, 1204, 1238, 177, 1204, 155, 1238, 0, 1238, + 1238, 160, 1177, 149, 160, 170, 148, 143, 177, 1162, 184, 194, 163, 132, 169, + 1156, 189, 1169, 209, 208, 220, 218, 147, 1154, 1238, 215, 1238, 1238, 1238, 1238, + 1238, 0, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 220, 1238, 257, + 250, 263, 322, 1238, 0, 1238, 1238, 1238, 1198, 1238, 1238, 1238, 1197, 0, 1238, + 1238, 1153, 1151, 1156, 229, 1153, 1161, 1159, 1159, 1146, 1149, + + 1160, 238, 1154, 1142, 1139, 1152, 1139, 1136, 1136, 1142, 237, 235, 1136, 1146, 1132, + 1138, 1141, 1142, 0, 1134, 1144, 246, 1135, 1142, 1123, 1136, 1117, 252, 1121, 1134, + 1125, 243, 1118, 278, 1113, 1129, 1131, 253, 1120, 292, 1107, 1116, 294, 296, 1120, + 1116, 1118, 1107, 1110, 182, 258, 1115, 296, 1118, 1106, 1118, 265, 1111, 1110, 1098, + 1238, 1238, 0, 351, 1238, 318, 369, 1238, 1238, 379, 389, 285, 1238, 1238, 1116, + 1107, 0, 1103, 1098, 1102, 1111, 1105, 1107, 355, 1091, 1091, 1102, 1094, 284, 1104, + 1101, 1101, 1099, 1096, 1088, 1094, 1081, 1079, 1091, 1077, + + 1093, 0, 1090, 1078, 1085, 1082, 1086, 1087, 1080, 1077, 1066, 1065, 1078, 1081, 1059, + 1068, 1079, 1075, 1063, 1069, 1060, 398, 1065, 1068, 1059, 1066, 1055, 1059, 1050, 1064, + 1061, 1062, 1053, 1059, 308, 1043, 1046, 1044, 1043, 1053, 1043, 1038, 1036, 1038, 1048, + 1034, 1036, 1033, 1044, 1043, 1046, 1028, 358, 1036, 1022, 1031, 1029, 1038, 1017, 402, + 1035, 1037, 1026, 1018, 1056, 413, 423, 445, 455, 1238, 1238, 1022, 1013, 1023, 1022, + 0, 1020, 1024, 405, 0, 0, 1012, 1010, 1010, 1011, 1006, 1014, 1003, 1020, 1009, + 433, 0, 0, 1003, 1013, 1012, 1012, 0, 997, 436, + + 0, 0, 999, 439, 1006, 1007, 998, 992, 991, 992, 991, 1001, 990, 361, 463, + 985, 0, 0, 981, 980, 979, 981, 982, 987, 981, 977, 990, 985, 985, 981, + 982, 981, 975, 969, 971, 970, 974, 979, 965, 968, 963, 971, 976, 964, 961, + 973, 964, 0, 0, 970, 966, 0, 958, 958, 963, 964, 953, 960, 467, 957, + 0, 0, 0, 0, 947, 959, 958, 945, 946, 955, 956, 956, 0, 941, 0, + 0, 0, 942, 0, 950, 941, 0, 940, 941, 935, 945, 0, 0, 0, 936, + 0, 932, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 942, 471, 941, 0, 0, 939, 935, 932, 931, 980, 979, 0, 0, 0, + 921, 475, 478, 481, 926, 922, 927, 918, 916, 929, 914, 0, 946, 913, 926, + 915, 911, 917, 912, 919, 919, 0, 916, 913, 917, 901, 899, 902, 908, 914, + 909, 908, 896, 0, 898, 899, 898, 0, 0, 0, 0, 895, 898, 0, 892, + 902, 893, 0, 903, 883, 0, 892, 887, 0, 880, 880, 893, 0, 895, 0, + 489, 915, 914, 913, 873, 872, 0, 889, 888, 903, 882, 924, 915, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 869, 882, + + 869, 866, 0, 0, 871, 865, 449, 0, 867, 874, 873, 0, 859, 0, 0, + 0, 0, 0, 856, 0, 0, 855, 866, 493, 859, 865, 884, 863, 860, 855, + 852, 874, 858, 843, 843, 856, 841, 853, 0, 0, 846, 876, 875, 874, 834, + 833, 470, 485, 0, 845, 848, 846, 835, 833, 830, 845, 0, 0, 841, 838, + 837, 827, 837, 0, 825, 815, 832, 818, 501, 826, 829, 0, 853, 852, 851, + 811, 810, 0, 824, 813, 810, 0, 820, 813, 805, 806, 812, 815, 0, 0, + 0, 0, 842, 841, 0, 811, 814, 799, 806, 797, + + 804, 805, 805, 804, 790, 804, 514, 800, 800, 0, 801, 790, 801, 788, 0, + 0, 0, 820, 819, 818, 778, 777, 773, 785, 780, 0, 815, 814, 0, 784, + 787, 0, 785, 521, 0, 764, 785, 804, 771, 0, 767, 766, 775, 775, 763, + 777, 761, 775, 770, 797, 0, 0, 772, 792, 791, 790, 750, 749, 748, 0, + 748, 0, 754, 0, 496, 512, 775, 757, 760, 743, 756, 754, 742, 741, 750, + 750, 753, 773, 772, 771, 731, 730, 0, 735, 725, 728, 729, 728, 738, 765, + 740, 736, 738, 734, 721, 720, 724, 757, 518, 0, + + 727, 730, 720, 721, 752, 712, 719, 710, 735, 719, 715, 717, 715, 715, 714, + 713, 0, 701, 700, 710, 737, 702, 735, 519, 0, 705, 708, 705, 690, 0, + 706, 705, 689, 688, 680, 688, 678, 686, 0, 683, 721, 681, 680, 705, 689, + 687, 687, 680, 670, 698, 666, 668, 652, 690, 123, 160, 189, 210, 497, 204, + 220, 252, 255, 263, 287, 331, 378, 420, 458, 454, 460, 464, 469, 476, 465, + 467, 0, 475, 507, 482, 516, 488, 509, 524, 496, 497, 537, 512, 511, 540, + 518, 514, 537, 520, 518, 522, 508, 507, 522, 509, + + 512, 513, 522, 518, 538, 510, 511, 0, 519, 549, 521, 522, 562, 537, 536, + 565, 527, 528, 0, 0, 544, 538, 0, 539, 0, 525, 566, 549, 550, 536, + 535, 538, 539, 540, 0, 572, 535, 545, 537, 545, 572, 549, 0, 0, 548, + 564, 565, 586, 0, 0, 567, 586, 569, 570, 556, 555, 558, 559, 572, 564, + 555, 578, 579, 0, 596, 559, 560, 568, 0, 0, 569, 585, 606, 598, 568, + 600, 590, 584, 572, 593, 591, 585, 619, 575, 614, 577, 578, 586, 0, 0, + 587, 623, 604, 0, 602, 603, 627, 0, 0, 608, + + 609, 598, 0, 604, 0, 605, 591, 614, 0, 593, 603, 630, 636, 0, 639, + 0, 0, 620, 621, 628, 613, 611, 612, 0, 604, 605, 622, 629, 630, 0, + 628, 643, 613, 654, 651, 0, 614, 615, 648, 677, 620, 621, 0, 0, 638, + 640, 641, 632, 639, 0, 658, 0, 0, 0, 0, 669, 0, 0, 0, 636, + 637, 631, 652, 0, 658, 634, 635, 0, 653, 695, 0, 0, 645, 664, 640, + 681, 0, 668, 673, 0, 1238, 717, 722, 727, 732, 735, 738}; + +static const flex_int16_t yy_def[988] = { + 0, 981, 1, 981, 3, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, + 981, 981, 981, 982, 981, 981, 981, 981, 981, 981, 983, 981, 981, 981, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 981, 981, 981, 981, 981, 981, 981, 984, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, + 985, 981, 986, 20, 982, 981, 981, 987, 981, 981, 981, 981, 981, 981, 981, 981, 983, 981, + 981, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 981, 981, 984, 981, 981, 986, 981, 981, 981, 981, 981, 987, + 981, 981, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 981, 981, 981, 981, 981, 981, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 0, 981, 981, 981, 981, 981, 981}; + +static const flex_int16_t yy_nxt[1321] = { + 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 22, 23, 24, 25, 26, 27, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 28, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 28, 53, 28, 54, 55, 56, 57, 58, 59, + 60, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 58, 58, + 58, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 58, 58, 58, 58, 63, 64, 65, 68, + 70, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 798, 74, 81, 86, 87, 71, + 69, 129, 89, 66, 74, 130, 75, 75, 75, 75, 75, 75, 75, 75, 76, + + 76, 82, 77, 83, 84, 92, 103, 107, 158, 108, 104, 77, 90, 78, 799, 105, 159, + 127, 109, 93, 94, 106, 78, 131, 99, 79, 77, 95, 100, 96, 128, 110, 97, 98, + 101, 77, 132, 102, 116, 111, 78, 112, 161, 134, 113, 800, 117, 251, 252, 78, 114, + 135, 79, 119, 164, 165, 120, 118, 136, 121, 122, 137, 123, 139, 124, 125, 146, 126, + 801, 147, 140, 141, 155, 804, 142, 74, 156, 148, 164, 165, 143, 144, 150, 145, 149, + 157, 151, 805, 152, 200, 153, 167, 168, 154, 162, 169, 178, 77, 981, 187, + + 179, 198, 201, 188, 189, 225, 806, 234, 78, 807, 210, 226, 199, 211, 212, 167, 168, + 213, 220, 214, 253, 77, 169, 235, 236, 981, 221, 261, 254, 262, 271, 170, 808, 170, + 228, 78, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 238, 229, 242, 230, 256, + 244, 167, 168, 286, 287, 809, 271, 257, 239, 266, 810, 266, 243, 245, 267, 267, 267, + 267, 267, 267, 267, 267, 267, 267, 334, 167, 168, 268, 335, 268, 411, 412, 269, 269, + 269, 269, 269, 269, 269, 269, 269, 269, 171, 171, 171, 171, 171, 171, 171, + + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 280, 319, 320, 321, + 353, 361, 362, 363, 375, 376, 377, 270, 354, 281, 267, 267, 267, 267, 267, 267, 267, + 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 811, 270, 387, 388, + 389, 395, 396, 397, 399, 400, 401, 165, 269, 269, 269, 269, 269, 269, 269, 269, 269, + 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 413, 414, 415, 165, 454, 455, + 456, 477, 478, 479, 812, 168, 490, 491, 492, 493, 494, 495, 496, 497, 498, + + 598, 813, 480, 481, 542, 543, 544, 564, 573, 574, 575, 565, 814, 599, 168, 600, 618, + 619, 620, 815, 545, 546, 816, 817, 576, 577, 706, 802, 601, 654, 655, 656, 621, 622, + 818, 623, 678, 679, 680, 707, 803, 819, 708, 820, 821, 657, 658, 624, 743, 768, 822, + 709, 681, 682, 710, 711, 823, 744, 769, 824, 745, 770, 825, 826, 827, 828, 829, 830, + 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, + 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, + + 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, + 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, + 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, + 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, + 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, + 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, + + 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, + 980, 76, 76, 797, 796, 795, 76, 88, 88, 88, 88, 88, 163, 163, 163, 163, 163, + 72, 794, 72, 166, 793, 166, 172, 172, 172, 792, 791, 790, 789, 788, 787, 786, 785, + 784, 783, 782, 781, 780, 779, 778, 777, 776, 775, 774, 773, 772, 771, 767, 766, 765, + 764, 763, 762, 761, 760, 759, 758, 757, 756, 755, 754, 753, 752, 751, 750, 749, 748, + 747, 746, 742, 741, 740, 739, 738, 737, 736, 735, 734, 733, 732, 731, 730, + + 729, 728, 727, 726, 725, 724, 723, 722, 721, 720, 719, 718, 717, 716, 715, 714, 713, + 712, 705, 704, 703, 702, 701, 700, 699, 698, 697, 696, 695, 694, 693, 692, 691, 690, + 689, 688, 687, 686, 685, 684, 683, 677, 676, 675, 674, 673, 672, 671, 670, 669, 668, + 667, 666, 665, 664, 663, 662, 661, 660, 659, 653, 652, 651, 650, 649, 648, 647, 646, + 645, 644, 643, 642, 641, 640, 639, 638, 637, 636, 635, 634, 633, 632, 631, 630, 629, + 628, 627, 626, 625, 617, 616, 615, 614, 613, 612, 611, 610, 609, 608, 607, + + 606, 605, 604, 603, 602, 597, 596, 595, 594, 593, 592, 591, 590, 589, 588, 587, 586, + 585, 584, 583, 582, 581, 580, 579, 578, 572, 571, 570, 569, 568, 567, 566, 563, 562, + 561, 560, 559, 558, 557, 556, 555, 554, 553, 552, 551, 550, 549, 548, 547, 541, 540, + 539, 538, 537, 536, 535, 534, 533, 532, 531, 530, 529, 528, 527, 526, 525, 524, 523, + 522, 521, 520, 519, 518, 517, 516, 515, 514, 513, 512, 511, 510, 509, 508, 507, 506, + 505, 504, 503, 502, 501, 500, 499, 489, 488, 487, 486, 485, 484, 483, 482, + + 476, 475, 474, 473, 472, 471, 470, 469, 468, 467, 466, 465, 464, 463, 462, 461, 460, + 459, 458, 457, 453, 452, 451, 450, 449, 448, 447, 446, 445, 444, 443, 442, 441, 440, + 439, 438, 437, 436, 435, 434, 433, 432, 431, 430, 429, 428, 427, 426, 425, 424, 423, + 422, 421, 420, 419, 418, 417, 416, 410, 409, 408, 407, 406, 405, 404, 403, 402, 398, + 394, 393, 392, 391, 390, 386, 385, 384, 383, 382, 381, 380, 379, 378, 374, 373, 372, + 371, 370, 369, 368, 367, 366, 365, 364, 360, 359, 358, 357, 356, 355, 352, + + 351, 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, 340, 339, 338, 337, 336, 333, + 332, 331, 330, 329, 328, 327, 326, 325, 324, 323, 322, 318, 317, 316, 315, 314, 313, + 312, 311, 310, 309, 308, 307, 306, 305, 304, 303, 302, 301, 300, 299, 298, 297, 296, + 295, 294, 293, 292, 291, 290, 289, 288, 285, 284, 283, 282, 279, 278, 277, 276, 275, + 274, 273, 272, 265, 264, 263, 260, 259, 258, 255, 250, 249, 248, 247, 246, 241, 240, + 237, 233, 232, 231, 227, 224, 223, 222, 219, 218, 217, 216, 215, 209, 208, + + 207, 206, 205, 204, 203, 202, 197, 196, 195, 194, 193, 192, 191, 190, 186, 185, 184, + 183, 182, 181, 180, 177, 176, 175, 174, 173, 160, 138, 133, 115, 91, 85, 80, 73, + 67, 62, 981, 5, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, + 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, + 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, + 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, + + 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, + 981, 981, 981}; + +static const flex_int16_t yy_chk[1321] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10, 10, 11, 15, + 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 755, 21, 24, 26, 26, 17, + 15, 43, 31, 11, 20, 43, 20, 20, 20, 20, 20, 20, 20, 20, 20, + + 20, 24, 21, 24, 24, 33, 36, 37, 52, 37, 36, 20, 31, 21, 756, 36, 52, + 42, 37, 33, 33, 36, 20, 44, 35, 20, 21, 34, 35, 34, 42, 38, 34, 34, + 35, 20, 44, 35, 40, 38, 21, 38, 55, 46, 38, 757, 40, 150, 150, 20, 38, + 46, 20, 41, 72, 72, 41, 40, 46, 41, 41, 46, 41, 48, 41, 41, 49, 41, + 758, 49, 48, 48, 51, 760, 48, 76, 51, 49, 72, 72, 48, 48, 50, 48, 49, + 51, 50, 761, 50, 112, 50, 74, 74, 50, 55, 75, 94, 76, 75, 102, + + 94, 111, 112, 102, 102, 132, 762, 138, 76, 763, 122, 132, 111, 122, 122, 74, 74, + 122, 128, 122, 151, 76, 75, 138, 138, 75, 128, 157, 151, 157, 172, 77, 764, 77, + 134, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 140, 134, 143, 134, 153, + 144, 166, 166, 189, 189, 765, 172, 153, 140, 164, 766, 164, 143, 144, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 235, 166, 166, 167, 235, 167, 314, 314, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, 170, 170, 170, 170, 170, 170, 170, + + 170, 170, 170, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 184, 222, 222, 222, + 253, 260, 260, 260, 279, 279, 279, 171, 253, 184, 266, 266, 266, 266, 266, 266, 266, + 266, 266, 266, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 767, 171, 291, 291, + 291, 300, 300, 300, 304, 304, 304, 267, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 315, 315, 315, 267, 359, 359, + 359, 403, 403, 403, 768, 269, 417, 417, 417, 418, 418, 418, 419, 419, 419, + + 547, 769, 403, 403, 476, 476, 476, 507, 524, 524, 524, 507, 770, 547, 269, 548, 569, + 569, 569, 771, 476, 476, 772, 773, 524, 524, 665, 759, 548, 607, 607, 607, 569, 569, + 774, 569, 634, 634, 634, 665, 759, 775, 666, 776, 778, 607, 607, 569, 699, 724, 779, + 666, 634, 634, 666, 666, 780, 699, 724, 781, 699, 724, 782, 783, 784, 785, 786, 787, + 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, + 805, 806, 807, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 821, 822, + + 824, 826, 827, 828, 829, 830, 831, 832, 833, 834, 836, 837, 838, 839, 840, 841, 842, + 845, 846, 847, 848, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, + 865, 866, 867, 868, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, + 884, 885, 886, 887, 888, 891, 892, 893, 895, 896, 897, 900, 901, 902, 904, 906, 907, + 908, 910, 911, 912, 913, 915, 918, 919, 920, 921, 922, 923, 925, 926, 927, 928, 929, + 931, 932, 933, 934, 935, 937, 938, 939, 940, 941, 942, 945, 946, 947, 948, + + 949, 951, 956, 960, 961, 962, 963, 965, 966, 967, 969, 970, 973, 974, 975, 976, 978, + 979, 982, 982, 754, 753, 752, 982, 983, 983, 983, 983, 983, 984, 984, 984, 984, 984, + 985, 751, 985, 986, 750, 986, 987, 987, 987, 749, 748, 747, 746, 745, 744, 743, 742, + 741, 740, 738, 737, 736, 735, 734, 733, 732, 731, 729, 728, 727, 726, 723, 722, 721, + 720, 719, 718, 716, 715, 714, 713, 712, 711, 710, 709, 708, 707, 706, 705, 704, 703, + 702, 701, 698, 697, 696, 695, 694, 693, 692, 691, 690, 689, 688, 687, 686, + + 685, 684, 682, 681, 680, 679, 678, 677, 676, 675, 674, 673, 672, 671, 670, 669, 668, + 667, 663, 661, 659, 658, 657, 656, 655, 654, 653, 650, 649, 648, 647, 646, 645, 644, + 643, 642, 641, 639, 638, 637, 636, 633, 631, 630, 628, 627, 625, 624, 623, 622, 621, + 620, 619, 618, 614, 613, 612, 611, 609, 608, 606, 605, 604, 603, 602, 601, 600, 599, + 598, 597, 596, 594, 593, 588, 587, 586, 585, 584, 583, 581, 580, 579, 577, 576, 575, + 574, 573, 571, 570, 568, 567, 566, 565, 563, 562, 561, 560, 559, 556, 555, + + 554, 553, 552, 551, 550, 546, 545, 544, 543, 542, 541, 538, 537, 536, 535, 534, 533, + 532, 531, 530, 529, 528, 527, 526, 525, 523, 522, 519, 513, 511, 510, 509, 506, 505, + 502, 501, 500, 499, 488, 487, 486, 485, 484, 483, 481, 480, 479, 478, 477, 474, 472, + 471, 470, 468, 467, 465, 464, 462, 461, 460, 458, 457, 452, 451, 450, 448, 447, 446, + 445, 444, 443, 442, 441, 440, 439, 438, 436, 435, 434, 433, 432, 431, 430, 429, 428, + 426, 425, 424, 423, 422, 421, 420, 416, 412, 411, 410, 409, 408, 407, 404, + + 402, 392, 390, 386, 385, 384, 383, 381, 380, 378, 374, 372, 371, 370, 369, 368, 367, + 366, 365, 360, 358, 357, 356, 355, 354, 353, 351, 350, 347, 346, 345, 344, 343, 342, + 341, 340, 339, 338, 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, 327, 326, 325, + 324, 323, 322, 321, 320, 319, 316, 313, 312, 311, 310, 309, 308, 307, 306, 305, 303, + 299, 297, 296, 295, 294, 290, 289, 288, 287, 286, 285, 284, 283, 282, 278, 277, 275, + 274, 273, 272, 265, 264, 263, 262, 261, 259, 258, 257, 256, 255, 254, 252, + + 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 234, + 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 221, 220, 219, 218, 217, 216, + 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 201, 200, 199, 198, + 197, 196, 195, 194, 193, 192, 191, 190, 188, 187, 186, 185, 183, 182, 181, 180, 179, + 178, 176, 175, 160, 159, 158, 156, 155, 154, 152, 149, 148, 147, 146, 145, 142, 141, + 139, 137, 136, 135, 133, 131, 130, 129, 127, 126, 125, 124, 123, 121, 120, + + 118, 117, 116, 115, 114, 113, 110, 109, 108, 107, 106, 105, 104, 103, 101, 100, 99, + 98, 97, 96, 95, 93, 92, 91, 87, 83, 53, 47, 45, 39, 32, 25, 22, 19, + 14, 9, 5, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, + 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, + 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, + 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, + + 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, + 981, 981, 981}; + +/* Table of booleans, true if rule could match eol. */ +static const flex_int32_t yy_rule_can_match_eol[260] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, +}; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +/* +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +This file contains the Lex specification for GLSL ES. +Based on ANSI C grammar, Lex specification: +http://www.lysator.liu.se/c/ANSI-C-grammar-l.html + +IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN scripts/run_code_generation.py +WHICH GENERATES THE GLSL ES LEXER (glslang_lex_autogen.cpp). +*/ + +#include "compiler/preprocessor/Token.h" +#include "compiler/translator/ParseContext.h" +#include "compiler/translator/glslang.h" +#include "compiler/translator/length_limits.h" +#include "compiler/translator/util.h" + +using namespace sh; + +#include "glslang_tab_autogen.h" + +/* windows only pragma */ +#ifdef _MSC_VER +# pragma warning(disable : 4102) +#endif + +// Workaround for flex using the register keyword, deprecated in C++11. +#ifdef __cplusplus +# if __cplusplus > 199711L +# define register +# endif +#endif + +#define YY_NO_INPUT +#define YY_USER_ACTION \ + yylloc->first_file = yylloc->last_file = yycolumn; \ + yylloc->first_line = yylloc->last_line = yylineno; + +#define YY_INPUT(buf, result, max_size) result = string_input(buf, max_size, yyscanner); + +static yy_size_t string_input(char *buf, yy_size_t max_size, yyscan_t yyscanner); +static int check_type(yyscan_t yyscanner); +static int reserved_word(yyscan_t yyscanner); +// Tests if an extension is enabled. If the extension is promoted to core, this function returns +// true. +static bool is_extension_enabled_or_is_core(TParseContext *context, + int extension_version, + TExtension extension, + int promotion_version); +// Helpers to determine if a symbol is reserved, keyword in extension or core, or identifier. +// Formatted as: +// +// [V1_reserved_][V2_extension_][V3_keyword] +// +// which means in version V1, the symbol is reserved, and remains reserved until V3. From versions +// V2 until V3, it's a keyword if the extension is enabled. From version V3 on, it's a keyword in +// the spec itself. Prior to V1, the symbol can be used as identifier. +static int ES2_extensions_ES3_keyword(TParseContext *context, + TExtension extension1, + TExtension extension2, + TExtension extension3, + int token); +static int ES2_reserved_ES3_keyword(TParseContext *context, int token); +static int ES2_keyword_ES3_reserved(TParseContext *context, int token); +static int ES3_keyword(TParseContext *context, int token); +static int ES3_reserved_ES3_1_keyword(TParseContext *context, int token); +static int ES2_reserved_ES3_1_keyword(TParseContext *context, int token); +static int ES3_1_keyword(TParseContext *context, int token); +static int ES2_reserved_ES2_extension_ES3_keyword(TParseContext *context, + TExtension extension, + int token); +static int ES3_extension(TParseContext *context, TExtension extension, int token); +static int ES3_reserved_ES3_1_extension_ES3_2_keyword(TParseContext *context, + TExtension extension, + int token); +static int ES3_reserved_ES3_extension(TParseContext *context, TExtension extension, int token); +static int ES3_reserved_ES3_extension_ES3_1_keyword(TParseContext *context, + TExtension extension, + int token); +static int ES3_reserved_ES3_extension_ES3_2_keyword(TParseContext *context, + TExtension extension, + int token); +static int ES3_1_reserved_ES3_1_extension_ES3_2_keyword(TParseContext *context, + TExtension extension, + int token); +static int ES3_1_reserved_ES3_1_extension_ES3_2_keyword_2(TParseContext *context, + TExtension extension1, + TExtension extension2, + int token1, + int token2); +static int ES3_and_3_1_reserved_ES3_1_extension_ES3_2_keyword_2(TParseContext *context, + TExtension extension1, + TExtension extension2, + int token1, + int token2); +static int WEBGL_video_texture_extension(TParseContext *context, int token); +static int uint_constant(TParseContext *context); +static int int_constant(TParseContext *context); +static int float_constant(yyscan_t yyscanner); +static int floatsuffix_check(TParseContext *context); +static int yuvcscstandardext_constant(TParseContext *context); + +#define INITIAL 0 +#define FIELDS 1 + +#define YY_EXTRA_TYPE TParseContext * + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t +{ + + /* User-defined. Not touched by flex. */ + YY_EXTRA_TYPE yyextra_r; + + /* The rest are the same as the globals declared in the non-reentrant scanner. */ + FILE *yyin_r, *yyout_r; + size_t yy_buffer_stack_top; /**< index of top of stack. */ + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE *yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; + int yy_n_chars; + int yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; + int yy_did_buffer_switch_on_eof; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; + yy_state_type yy_last_accepting_state; + char *yy_last_accepting_cpos; + + int yylineno_r; + int yy_flex_debug_r; + + char *yytext_r; + int yy_more_flag; + int yy_more_len; + + YYSTYPE *yylval_r; + + YYLTYPE *yylloc_r; + +}; /* end struct yyguts_t */ + +static int yy_init_globals(yyscan_t yyscanner); + +/* This must go here because YYSTYPE and YYLTYPE are included + * from bison output in section 1.*/ +#define yylval yyg->yylval_r + +#define yylloc yyg->yylloc_r + +int yylex_init(yyscan_t *scanner); + +int yylex_init_extra(YY_EXTRA_TYPE user_defined, yyscan_t *scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy(yyscan_t yyscanner); + +int yyget_debug(yyscan_t yyscanner); + +void yyset_debug(int debug_flag, yyscan_t yyscanner); + +YY_EXTRA_TYPE yyget_extra(yyscan_t yyscanner); + +void yyset_extra(YY_EXTRA_TYPE user_defined, yyscan_t yyscanner); + +FILE *yyget_in(yyscan_t yyscanner); + +void yyset_in(FILE *_in_str, yyscan_t yyscanner); + +FILE *yyget_out(yyscan_t yyscanner); + +void yyset_out(FILE *_out_str, yyscan_t yyscanner); + +int yyget_leng(yyscan_t yyscanner); + +char *yyget_text(yyscan_t yyscanner); + +int yyget_lineno(yyscan_t yyscanner); + +void yyset_lineno(int _line_number, yyscan_t yyscanner); + +int yyget_column(yyscan_t yyscanner); + +void yyset_column(int _column_no, yyscan_t yyscanner); + +YYSTYPE *yyget_lval(yyscan_t yyscanner); + +void yyset_lval(YYSTYPE *yylval_param, yyscan_t yyscanner); + +YYLTYPE *yyget_lloc(yyscan_t yyscanner); + +void yyset_lloc(YYLTYPE *yylloc_param, yyscan_t yyscanner); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +# ifdef __cplusplus +extern "C" int yywrap(yyscan_t yyscanner); +# else +extern int yywrap(yyscan_t yyscanner); +# endif +#endif + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy(char *, const char *, int, yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen(const char *, yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT +# ifdef __cplusplus +static int yyinput(yyscan_t yyscanner); +# else +static int input(yyscan_t yyscanner); +# endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +# ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +# define YY_READ_BUF_SIZE 16384 +# else +# define YY_READ_BUF_SIZE 8192 +# endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +# define ECHO \ + do \ + { \ + if (fwrite(yytext, (size_t)yyleng, 1, yyout)) \ + {} \ + } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +# define YY_INPUT(buf, result, max_size) \ + if (YY_CURRENT_BUFFER_LVALUE->yy_is_interactive) \ + { \ + int c = '*'; \ + int n; \ + for (n = 0; n < max_size && (c = getc(yyin)) != EOF && c != '\n'; ++n) \ + buf[n] = (char)c; \ + if (c == '\n') \ + buf[n++] = (char)c; \ + if (c == EOF && ferror(yyin)) \ + YY_FATAL_ERROR("input in flex scanner failed"); \ + result = n; \ + } \ + else \ + { \ + errno = 0; \ + while ((result = (int)fread(buf, 1, (yy_size_t)max_size, yyin)) == 0 && ferror(yyin)) \ + { \ + if (errno != EINTR) \ + { \ + YY_FATAL_ERROR("input in flex scanner failed"); \ + break; \ + } \ + errno = 0; \ + clearerr(yyin); \ + } \ + } + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +# define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +# define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +# define YY_FATAL_ERROR(msg) yy_fatal_error(msg, yyscanner) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +# define YY_DECL_IS_OURS 1 + +extern int yylex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner); + +# define YY_DECL int yylex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +# define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +# define YY_BREAK /*LINTED*/ break; +#endif + +#define YY_RULE_SETUP YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + yylval = yylval_param; + + yylloc = yylloc_param; + + if (!yyg->yy_init) + { + yyg->yy_init = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if (!yyg->yy_start) + yyg->yy_start = 1; /* first start state */ + + if (!yyin) + yyin = stdin; + + if (!yyout) + yyout = stdout; + + if (!YY_CURRENT_BUFFER) + { + yyensure_buffer_stack(yyscanner); + YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner); + } + + yy_load_buffer_state(yyscanner); + } + + { + + TParseContext *context = yyextra; + + while (/*CONSTCOND*/ 1) /* loops until end-of-file is reached */ + { + yy_cp = yyg->yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yyg->yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yyg->yy_start; + yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if (yy_accept[yy_current_state]) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) + { + yy_current_state = (int)yy_def[yy_current_state]; + if (yy_current_state >= 982) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + ++yy_cp; + } while (yy_current_state != 981); + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + + yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + + if (yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act]) + { + int yyl; + for (yyl = 0; yyl < yyleng; ++yyl) + if (yytext[yyl] == '\n') + + do + { + yylineno++; + yycolumn = 0; + } while (0); + } + + do_action: /* This label is used only to access EOF actions. */ + + switch (yy_act) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yyg->yy_hold_char; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + + case 1: + YY_RULE_SETUP + { + return INVARIANT; + } + YY_BREAK + case 2: + YY_RULE_SETUP + { + return HIGH_PRECISION; + } + YY_BREAK + case 3: + YY_RULE_SETUP + { + return MEDIUM_PRECISION; + } + YY_BREAK + case 4: + YY_RULE_SETUP + { + return LOW_PRECISION; + } + YY_BREAK + case 5: + YY_RULE_SETUP + { + return PRECISION; + } + YY_BREAK + case 6: + YY_RULE_SETUP + { + return ES2_keyword_ES3_reserved(context, ATTRIBUTE); + } + YY_BREAK + case 7: + YY_RULE_SETUP + { + return CONST_QUAL; + } + YY_BREAK + case 8: + YY_RULE_SETUP + { + return UNIFORM; + } + YY_BREAK + case 9: + YY_RULE_SETUP + { + return ES3_1_keyword(context, BUFFER); + } + YY_BREAK + case 10: + YY_RULE_SETUP + { + return ES2_keyword_ES3_reserved(context, VARYING); + } + YY_BREAK + case 11: + YY_RULE_SETUP + { + return BREAK; + } + YY_BREAK + case 12: + YY_RULE_SETUP + { + return CONTINUE; + } + YY_BREAK + case 13: + YY_RULE_SETUP + { + return DO; + } + YY_BREAK + case 14: + YY_RULE_SETUP + { + return FOR; + } + YY_BREAK + case 15: + YY_RULE_SETUP + { + return WHILE; + } + YY_BREAK + case 16: + YY_RULE_SETUP + { + return IF; + } + YY_BREAK + case 17: + YY_RULE_SETUP + { + return ELSE; + } + YY_BREAK + case 18: + YY_RULE_SETUP + { + return ES2_reserved_ES3_keyword(context, SWITCH); + } + YY_BREAK + case 19: + YY_RULE_SETUP + { + return ES3_keyword(context, CASE); + } + YY_BREAK + case 20: + YY_RULE_SETUP + { + return ES2_reserved_ES3_keyword(context, DEFAULT); + } + YY_BREAK + case 21: + YY_RULE_SETUP + { + return ES3_keyword(context, CENTROID); + } + YY_BREAK + case 22: + YY_RULE_SETUP + { + return ES2_reserved_ES3_keyword(context, FLAT); + } + YY_BREAK + case 23: + YY_RULE_SETUP + { + return ES3_keyword(context, SMOOTH); + } + YY_BREAK + case 24: + YY_RULE_SETUP + { + return ES3_reserved_ES3_extension( + context, TExtension::NV_shader_noperspective_interpolation, + NOPERSPECTIVE); + } + YY_BREAK + case 25: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_extension_ES3_2_keyword( + context, TExtension::EXT_tessellation_shader, PATCH); + } + YY_BREAK + case 26: + YY_RULE_SETUP + { + return IN_QUAL; + } + YY_BREAK + case 27: + YY_RULE_SETUP + { + return OUT_QUAL; + } + YY_BREAK + case 28: + YY_RULE_SETUP + { + return INOUT_QUAL; + } + YY_BREAK + case 29: + YY_RULE_SETUP + { + return ES3_1_keyword(context, SHARED); + } + YY_BREAK + case 30: + YY_RULE_SETUP + { + return FLOAT_TYPE; + } + YY_BREAK + case 31: + YY_RULE_SETUP + { + return INT_TYPE; + } + YY_BREAK + case 32: + YY_RULE_SETUP + { + return ES3_keyword(context, UINT_TYPE); + } + YY_BREAK + case 33: + YY_RULE_SETUP + { + return VOID_TYPE; + } + YY_BREAK + case 34: + YY_RULE_SETUP + { + return BOOL_TYPE; + } + YY_BREAK + case 35: + YY_RULE_SETUP + { + yylval->lex.b = true; + return BOOLCONSTANT; + } + YY_BREAK + case 36: + YY_RULE_SETUP + { + yylval->lex.b = false; + return BOOLCONSTANT; + } + YY_BREAK + case 37: + YY_RULE_SETUP + { + return DISCARD; + } + YY_BREAK + case 38: + YY_RULE_SETUP + { + return RETURN; + } + YY_BREAK + case 39: + YY_RULE_SETUP + { + return MATRIX2; + } + YY_BREAK + case 40: + YY_RULE_SETUP + { + return MATRIX3; + } + YY_BREAK + case 41: + YY_RULE_SETUP + { + return MATRIX4; + } + YY_BREAK + case 42: + YY_RULE_SETUP + { + return ES3_keyword(context, MATRIX2); + } + YY_BREAK + case 43: + YY_RULE_SETUP + { + return ES3_keyword(context, MATRIX3); + } + YY_BREAK + case 44: + YY_RULE_SETUP + { + return ES3_keyword(context, MATRIX4); + } + YY_BREAK + case 45: + YY_RULE_SETUP + { + return ES3_keyword(context, MATRIX2x3); + } + YY_BREAK + case 46: + YY_RULE_SETUP + { + return ES3_keyword(context, MATRIX3x2); + } + YY_BREAK + case 47: + YY_RULE_SETUP + { + return ES3_keyword(context, MATRIX2x4); + } + YY_BREAK + case 48: + YY_RULE_SETUP + { + return ES3_keyword(context, MATRIX4x2); + } + YY_BREAK + case 49: + YY_RULE_SETUP + { + return ES3_keyword(context, MATRIX3x4); + } + YY_BREAK + case 50: + YY_RULE_SETUP + { + return ES3_keyword(context, MATRIX4x3); + } + YY_BREAK + case 51: + YY_RULE_SETUP + { + return VEC2; + } + YY_BREAK + case 52: + YY_RULE_SETUP + { + return VEC3; + } + YY_BREAK + case 53: + YY_RULE_SETUP + { + return VEC4; + } + YY_BREAK + case 54: + YY_RULE_SETUP + { + return IVEC2; + } + YY_BREAK + case 55: + YY_RULE_SETUP + { + return IVEC3; + } + YY_BREAK + case 56: + YY_RULE_SETUP + { + return IVEC4; + } + YY_BREAK + case 57: + YY_RULE_SETUP + { + return BVEC2; + } + YY_BREAK + case 58: + YY_RULE_SETUP + { + return BVEC3; + } + YY_BREAK + case 59: + YY_RULE_SETUP + { + return BVEC4; + } + YY_BREAK + case 60: + YY_RULE_SETUP + { + return ES3_keyword(context, UVEC2); + } + YY_BREAK + case 61: + YY_RULE_SETUP + { + return ES3_keyword(context, UVEC3); + } + YY_BREAK + case 62: + YY_RULE_SETUP + { + return ES3_keyword(context, UVEC4); + } + YY_BREAK + case 63: + YY_RULE_SETUP + { + return SAMPLER2D; + } + YY_BREAK + case 64: + YY_RULE_SETUP + { + return SAMPLERCUBE; + } + YY_BREAK + case 65: + YY_RULE_SETUP + { + return SAMPLER_EXTERNAL_OES; + } + YY_BREAK + case 66: + YY_RULE_SETUP + { + return ES2_reserved_ES2_extension_ES3_keyword( + context, TExtension::OES_texture_3D, SAMPLER3D); + } + YY_BREAK + case 67: + YY_RULE_SETUP + { + return ES2_reserved_ES3_keyword(context, SAMPLER3DRECT); + } + YY_BREAK + case 68: + YY_RULE_SETUP + { + return SAMPLER2DRECT; + } + YY_BREAK + case 69: + YY_RULE_SETUP + { + return ES3_keyword(context, SAMPLER2DARRAY); + } + YY_BREAK + case 70: + YY_RULE_SETUP + { + return ES3_reserved_ES3_extension_ES3_1_keyword( + context, TExtension::ANGLE_texture_multisample, SAMPLER2DMS); + } + YY_BREAK + case 71: + YY_RULE_SETUP + { + return ES3_keyword(context, ISAMPLER2D); + } + YY_BREAK + case 72: + YY_RULE_SETUP + { + return ES3_keyword(context, ISAMPLER3D); + } + YY_BREAK + case 73: + YY_RULE_SETUP + { + return ES3_keyword(context, ISAMPLERCUBE); + } + YY_BREAK + case 74: + YY_RULE_SETUP + { + return ES3_keyword(context, ISAMPLER2DARRAY); + } + YY_BREAK + case 75: + YY_RULE_SETUP + { + return ES3_reserved_ES3_extension_ES3_1_keyword( + context, TExtension::ANGLE_texture_multisample, ISAMPLER2DMS); + } + YY_BREAK + case 76: + YY_RULE_SETUP + { + return ES3_keyword(context, USAMPLER2D); + } + YY_BREAK + case 77: + YY_RULE_SETUP + { + return ES3_keyword(context, USAMPLER3D); + } + YY_BREAK + case 78: + YY_RULE_SETUP + { + return ES3_keyword(context, USAMPLERCUBE); + } + YY_BREAK + case 79: + YY_RULE_SETUP + { + return ES3_keyword(context, USAMPLER2DARRAY); + } + YY_BREAK + case 80: + YY_RULE_SETUP + { + return ES3_reserved_ES3_extension_ES3_1_keyword( + context, TExtension::ANGLE_texture_multisample, USAMPLER2DMS); + } + YY_BREAK + case 81: + YY_RULE_SETUP + { + return ES2_reserved_ES2_extension_ES3_keyword( + context, TExtension::EXT_shadow_samplers, SAMPLER2DSHADOW); + } + YY_BREAK + case 82: + YY_RULE_SETUP + { + return ES3_keyword(context, SAMPLERCUBESHADOW); + } + YY_BREAK + case 83: + YY_RULE_SETUP + { + return ES3_keyword(context, SAMPLER2DARRAYSHADOW); + } + YY_BREAK + case 84: + YY_RULE_SETUP + { + return ES3_extension(context, TExtension::EXT_YUV_target, + SAMPLEREXTERNAL2DY2YEXT); + } + YY_BREAK + case 85: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_extension_ES3_2_keyword( + context, TExtension::OES_texture_storage_multisample_2d_array, + SAMPLER2DMSARRAY); + } + YY_BREAK + case 86: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_extension_ES3_2_keyword( + context, TExtension::OES_texture_storage_multisample_2d_array, + ISAMPLER2DMSARRAY); + } + YY_BREAK + case 87: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_extension_ES3_2_keyword( + context, TExtension::OES_texture_storage_multisample_2d_array, + USAMPLER2DMSARRAY); + } + YY_BREAK + case 88: + YY_RULE_SETUP + { + return ES3_1_reserved_ES3_1_extension_ES3_2_keyword_2( + context, TExtension::OES_texture_cube_map_array, + TExtension::EXT_texture_cube_map_array, SAMPLERCUBEARRAYOES, + SAMPLERCUBEARRAYEXT); + } + YY_BREAK + case 89: + YY_RULE_SETUP + { + return ES3_and_3_1_reserved_ES3_1_extension_ES3_2_keyword_2( + context, TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer, + SAMPLERBUFFER, SAMPLERBUFFER); + } + YY_BREAK + case 90: + YY_RULE_SETUP + { + return ES3_1_reserved_ES3_1_extension_ES3_2_keyword_2( + context, TExtension::OES_texture_cube_map_array, + TExtension::EXT_texture_cube_map_array, SAMPLERCUBEARRAYSHADOWOES, + SAMPLERCUBEARRAYSHADOWEXT); + } + YY_BREAK + case 91: + YY_RULE_SETUP + { + return ES3_1_reserved_ES3_1_extension_ES3_2_keyword_2( + context, TExtension::OES_texture_cube_map_array, + TExtension::EXT_texture_cube_map_array, ISAMPLERCUBEARRAYOES, + ISAMPLERCUBEARRAYEXT); + } + YY_BREAK + case 92: + YY_RULE_SETUP + { + return ES3_and_3_1_reserved_ES3_1_extension_ES3_2_keyword_2( + context, TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer, + ISAMPLERBUFFER, ISAMPLERBUFFER); + } + YY_BREAK + case 93: + YY_RULE_SETUP + { + return ES3_1_reserved_ES3_1_extension_ES3_2_keyword_2( + context, TExtension::OES_texture_cube_map_array, + TExtension::EXT_texture_cube_map_array, USAMPLERCUBEARRAYOES, + USAMPLERCUBEARRAYEXT); + } + YY_BREAK + case 94: + YY_RULE_SETUP + { + return ES3_and_3_1_reserved_ES3_1_extension_ES3_2_keyword_2( + context, TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer, + USAMPLERBUFFER, USAMPLERBUFFER); + } + YY_BREAK + case 95: + YY_RULE_SETUP + { + return WEBGL_video_texture_extension(context, SAMPLERVIDEOWEBGL); + } + YY_BREAK + case 96: + YY_RULE_SETUP + { + return STRUCT; + } + YY_BREAK + case 97: + YY_RULE_SETUP + { + return ES2_extensions_ES3_keyword( + context, TExtension::EXT_shader_framebuffer_fetch, + TExtension::EXT_shader_framebuffer_fetch_non_coherent, + TExtension::KHR_blend_equation_advanced, LAYOUT); + } + YY_BREAK + case 98: + YY_RULE_SETUP + { + return ES3_extension(context, TExtension::EXT_YUV_target, + YUVCSCSTANDARDEXT); + } + YY_BREAK + case 99: + YY_RULE_SETUP + { + return yuvcscstandardext_constant(context); + } + YY_BREAK + case 100: + YY_RULE_SETUP + { + return yuvcscstandardext_constant(context); + } + YY_BREAK + case 101: + YY_RULE_SETUP + { + return yuvcscstandardext_constant(context); + } + YY_BREAK + case 102: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, IMAGE2D); + } + YY_BREAK + case 103: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, IIMAGE2D); + } + YY_BREAK + case 104: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, UIMAGE2D); + } + YY_BREAK + case 105: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, IMAGE2DARRAY); + } + YY_BREAK + case 106: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, IIMAGE2DARRAY); + } + YY_BREAK + case 107: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, UIMAGE2DARRAY); + } + YY_BREAK + case 108: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, IMAGE3D); + } + YY_BREAK + case 109: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, UIMAGE3D); + } + YY_BREAK + case 110: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, IIMAGE3D); + } + YY_BREAK + case 111: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, IIMAGECUBE); + } + YY_BREAK + case 112: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, UIMAGECUBE); + } + YY_BREAK + case 113: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, IMAGECUBE); + } + YY_BREAK + case 114: + YY_RULE_SETUP + { + return ES3_1_reserved_ES3_1_extension_ES3_2_keyword_2( + context, TExtension::OES_texture_cube_map_array, + TExtension::EXT_texture_cube_map_array, IMAGECUBEARRAYOES, + IMAGECUBEARRAYEXT); + } + YY_BREAK + case 115: + YY_RULE_SETUP + { + return ES3_1_reserved_ES3_1_extension_ES3_2_keyword_2( + context, TExtension::OES_texture_cube_map_array, + TExtension::EXT_texture_cube_map_array, IIMAGECUBEARRAYOES, + IIMAGECUBEARRAYEXT); + } + YY_BREAK + case 116: + YY_RULE_SETUP + { + return ES3_1_reserved_ES3_1_extension_ES3_2_keyword_2( + context, TExtension::OES_texture_cube_map_array, + TExtension::EXT_texture_cube_map_array, UIMAGECUBEARRAYOES, + UIMAGECUBEARRAYEXT); + } + YY_BREAK + case 117: + YY_RULE_SETUP + { + return ES3_and_3_1_reserved_ES3_1_extension_ES3_2_keyword_2( + context, TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer, + IMAGEBUFFER, IMAGEBUFFER); + } + YY_BREAK + case 118: + YY_RULE_SETUP + { + return ES3_and_3_1_reserved_ES3_1_extension_ES3_2_keyword_2( + context, TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer, + IIMAGEBUFFER, IIMAGEBUFFER); + } + YY_BREAK + case 119: + YY_RULE_SETUP + { + return ES3_and_3_1_reserved_ES3_1_extension_ES3_2_keyword_2( + context, TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer, + UIMAGEBUFFER, UIMAGEBUFFER); + } + YY_BREAK + case 120: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, READONLY); + } + YY_BREAK + case 121: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, WRITEONLY); + } + YY_BREAK + case 122: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, COHERENT); + } + YY_BREAK + case 123: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, RESTRICT); + } + YY_BREAK + case 124: + YY_RULE_SETUP + { + return ES2_reserved_ES3_1_keyword(context, VOLATILE); + } + YY_BREAK + case 125: + YY_RULE_SETUP + { + return ES3_reserved_ES3_1_keyword(context, ATOMICUINT); + } + YY_BREAK + case 126: + YY_RULE_SETUP + { + return ES3_reserved_ES3_extension_ES3_2_keyword( + context, TExtension::OES_shader_multisample_interpolation, SAMPLE); + } + YY_BREAK + case 127: + YY_RULE_SETUP + { + return ES3_1_reserved_ES3_1_extension_ES3_2_keyword( + context, TExtension::EXT_gpu_shader5, PRECISE); + } + YY_BREAK + /* ANGLE_shader_pixel_local_storage */ + case 128: + YY_RULE_SETUP + { + return ES3_extension(context, TExtension::ANGLE_shader_pixel_local_storage, + PIXELLOCALANGLE); + } + YY_BREAK + case 129: + YY_RULE_SETUP + { + return ES3_extension(context, TExtension::ANGLE_shader_pixel_local_storage, + IPIXELLOCALANGLE); + } + YY_BREAK + case 130: + YY_RULE_SETUP + { + return ES3_extension(context, TExtension::ANGLE_shader_pixel_local_storage, + UPIXELLOCALANGLE); + } + YY_BREAK + /* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */ + case 131: + case 132: + case 133: + case 134: + case 135: + case 136: + case 137: + case 138: + case 139: + case 140: + case 141: + case 142: + case 143: + case 144: + case 145: + case 146: + case 147: + case 148: + case 149: + case 150: + case 151: + case 152: + case 153: + case 154: + YY_RULE_SETUP + { + if (context->getShaderVersion() < 300) + { + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); + } + return reserved_word(yyscanner); + } + YY_BREAK + /* Reserved keywords in GLSL ES 1.00 that are not reserved in GLSL ES 3.00 */ + case 155: + YY_RULE_SETUP + { + if (context->getShaderVersion() >= 300) + { + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); + } + + return reserved_word(yyscanner); + } + YY_BREAK + /* Reserved keywords */ + case 156: + case 157: + case 158: + case 159: + case 160: + case 161: + case 162: + case 163: + case 164: + case 165: + case 166: + case 167: + case 168: + case 169: + case 170: + case 171: + case 172: + case 173: + case 174: + case 175: + case 176: + case 177: + case 178: + case 179: + case 180: + case 181: + case 182: + case 183: + case 184: + case 185: + case 186: + case 187: + case 188: + case 189: + case 190: + case 191: + case 192: + case 193: + case 194: + case 195: + YY_RULE_SETUP + { + return reserved_word(yyscanner); + } + YY_BREAK + case 196: + YY_RULE_SETUP + { + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); + } + YY_BREAK + case 197: + YY_RULE_SETUP + { + return int_constant(context); + } + YY_BREAK + case 198: + YY_RULE_SETUP + { + return int_constant(context); + } + YY_BREAK + case 199: + YY_RULE_SETUP + { + return int_constant(context); + } + YY_BREAK + case 200: + YY_RULE_SETUP + { + return uint_constant(context); + } + YY_BREAK + case 201: + YY_RULE_SETUP + { + return uint_constant(context); + } + YY_BREAK + case 202: + YY_RULE_SETUP + { + return uint_constant(context); + } + YY_BREAK + case 203: + YY_RULE_SETUP + { + return float_constant(yyscanner); + } + YY_BREAK + case 204: + YY_RULE_SETUP + { + return float_constant(yyscanner); + } + YY_BREAK + case 205: + YY_RULE_SETUP + { + return float_constant(yyscanner); + } + YY_BREAK + case 206: + YY_RULE_SETUP + { + return floatsuffix_check(context); + } + YY_BREAK + case 207: + YY_RULE_SETUP + { + return floatsuffix_check(context); + } + YY_BREAK + case 208: + YY_RULE_SETUP + { + return floatsuffix_check(context); + } + YY_BREAK + case 209: + YY_RULE_SETUP + { + return ADD_ASSIGN; + } + YY_BREAK + case 210: + YY_RULE_SETUP + { + return SUB_ASSIGN; + } + YY_BREAK + case 211: + YY_RULE_SETUP + { + return MUL_ASSIGN; + } + YY_BREAK + case 212: + YY_RULE_SETUP + { + return DIV_ASSIGN; + } + YY_BREAK + case 213: + YY_RULE_SETUP + { + return MOD_ASSIGN; + } + YY_BREAK + case 214: + YY_RULE_SETUP + { + return LEFT_ASSIGN; + } + YY_BREAK + case 215: + YY_RULE_SETUP + { + return RIGHT_ASSIGN; + } + YY_BREAK + case 216: + YY_RULE_SETUP + { + return AND_ASSIGN; + } + YY_BREAK + case 217: + YY_RULE_SETUP + { + return XOR_ASSIGN; + } + YY_BREAK + case 218: + YY_RULE_SETUP + { + return OR_ASSIGN; + } + YY_BREAK + case 219: + YY_RULE_SETUP + { + return INC_OP; + } + YY_BREAK + case 220: + YY_RULE_SETUP + { + return DEC_OP; + } + YY_BREAK + case 221: + YY_RULE_SETUP + { + return AND_OP; + } + YY_BREAK + case 222: + YY_RULE_SETUP + { + return OR_OP; + } + YY_BREAK + case 223: + YY_RULE_SETUP + { + return XOR_OP; + } + YY_BREAK + case 224: + YY_RULE_SETUP + { + return LE_OP; + } + YY_BREAK + case 225: + YY_RULE_SETUP + { + return GE_OP; + } + YY_BREAK + case 226: + YY_RULE_SETUP + { + return EQ_OP; + } + YY_BREAK + case 227: + YY_RULE_SETUP + { + return NE_OP; + } + YY_BREAK + case 228: + YY_RULE_SETUP + { + return LEFT_OP; + } + YY_BREAK + case 229: + YY_RULE_SETUP + { + return RIGHT_OP; + } + YY_BREAK + case 230: + YY_RULE_SETUP + { + return SEMICOLON; + } + YY_BREAK + case 231: + YY_RULE_SETUP + { + return LEFT_BRACE; + } + YY_BREAK + case 232: + YY_RULE_SETUP + { + return RIGHT_BRACE; + } + YY_BREAK + case 233: + YY_RULE_SETUP + { + return COMMA; + } + YY_BREAK + case 234: + YY_RULE_SETUP + { + return COLON; + } + YY_BREAK + case 235: + YY_RULE_SETUP + { + return EQUAL; + } + YY_BREAK + case 236: + YY_RULE_SETUP + { + return LEFT_PAREN; + } + YY_BREAK + case 237: + YY_RULE_SETUP + { + return RIGHT_PAREN; + } + YY_BREAK + case 238: + YY_RULE_SETUP + { + return LEFT_BRACKET; + } + YY_BREAK + case 239: + YY_RULE_SETUP + { + return RIGHT_BRACKET; + } + YY_BREAK + case 240: + YY_RULE_SETUP + { + BEGIN(FIELDS); + return DOT; + } + YY_BREAK + case 241: + YY_RULE_SETUP + { + return BANG; + } + YY_BREAK + case 242: + YY_RULE_SETUP + { + return DASH; + } + YY_BREAK + case 243: + YY_RULE_SETUP + { + return TILDE; + } + YY_BREAK + case 244: + YY_RULE_SETUP + { + return PLUS; + } + YY_BREAK + case 245: + YY_RULE_SETUP + { + return STAR; + } + YY_BREAK + case 246: + YY_RULE_SETUP + { + return SLASH; + } + YY_BREAK + case 247: + YY_RULE_SETUP + { + return PERCENT; + } + YY_BREAK + case 248: + YY_RULE_SETUP + { + return LEFT_ANGLE; + } + YY_BREAK + case 249: + YY_RULE_SETUP + { + return RIGHT_ANGLE; + } + YY_BREAK + case 250: + YY_RULE_SETUP + { + return VERTICAL_BAR; + } + YY_BREAK + case 251: + YY_RULE_SETUP + { + return CARET; + } + YY_BREAK + case 252: + YY_RULE_SETUP + { + return AMPERSAND; + } + YY_BREAK + case 253: + YY_RULE_SETUP + { + return QUESTION; + } + YY_BREAK + case 254: + YY_RULE_SETUP + { + BEGIN(INITIAL); + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return FIELD_SELECTION; + } + YY_BREAK + case 255: + YY_RULE_SETUP {} + YY_BREAK + case 256: + YY_RULE_SETUP + { + yyextra->error(*yylloc, "Illegal character at fieldname start", yytext); + return 0; + } + YY_BREAK + case 257: + /* rule 257 can match eol */ + YY_RULE_SETUP {} + YY_BREAK + case YY_STATE_EOF(INITIAL): + case YY_STATE_EOF(FIELDS): + { + yyterminate(); + } + YY_BREAK + case 258: + YY_RULE_SETUP + { + assert(false); + return 0; + } + YY_BREAK + case 259: + YY_RULE_SETUP + ECHO; + YY_BREAK + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int)(yy_cp - yyg->yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yyg->yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if (YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if (yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(yyscanner); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans(yy_current_state, yyscanner); + + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + + if (yy_next_state) + { + /* Consume the NUL. */ + yy_cp = ++yyg->yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + } + } + + else + switch (yy_get_next_buffer(yyscanner)) + { + case EOB_ACT_END_OF_FILE: + { + yyg->yy_did_buffer_switch_on_eof = 0; + + if (yywrap(yyscanner)) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if (!yyg->yy_did_buffer_switch_on_eof) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(yyscanner); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yyg->yy_c_buf_p = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + + yy_current_state = yy_get_previous_state(yyscanner); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR("fatal flex scanner internal error--no action found"); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = yyg->yytext_ptr; + int number_to_move, i; + int ret_val; + + if (yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1]) + YY_FATAL_ERROR("fatal flex scanner internal error--end of buffer missed"); + + if (YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0) + { /* Don't try to fill the buffer, so this is an EOF. */ + if (yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int)(yyg->yy_c_buf_p - yyg->yytext_ptr - 1); + + for (i = 0; i < number_to_move; ++i) + *(dest++) = *(source++); + + if (YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + + else + { + int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while (num_to_read <= 0) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = (int)(yyg->yy_c_buf_p - b->yy_ch_buf); + + if (b->yy_is_our_buffer) + { + int new_size = b->yy_buf_size * 2; + + if (new_size <= 0) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *)b->yy_ch_buf, (yy_size_t)(b->yy_buf_size + 2), yyscanner); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = NULL; + + if (!b->yy_ch_buf) + YY_FATAL_ERROR("fatal error - scanner input buffer overflow"); + + yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + } + + if (num_to_read > YY_READ_BUF_SIZE) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + yy_size_t ret = 0; + YY_INPUT((&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), ret, num_to_read); + yyg->yy_n_chars = static_cast(ret); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + if (yyg->yy_n_chars == 0) + { + if (number_to_move == YY_MORE_ADJ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin, yyscanner); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) + { + /* Extend the array by 50%, plus the number we really need. */ + int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *)yyrealloc( + (void *)YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t)new_size, yyscanner); + if (!YY_CURRENT_BUFFER_LVALUE->yy_ch_buf) + YY_FATAL_ERROR("out of dynamic memory in yy_get_next_buffer()"); + /* "- 2" to take care of EOB's */ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int)(new_size - 2); + } + + yyg->yy_n_chars += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state(yyscan_t yyscanner) +{ + yy_state_type yy_current_state; + char *yy_cp; + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + yy_current_state = yyg->yy_start; + + for (yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp) + { + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if (yy_accept[yy_current_state]) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) + { + yy_current_state = (int)yy_def[yy_current_state]; + if (yy_current_state >= 982) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ +static yy_state_type yy_try_NUL_trans(yy_state_type yy_current_state, yyscan_t yyscanner) +{ + int yy_is_jam; + struct yyguts_t *yyg = + (struct yyguts_t *)yyscanner; /* This var may be unused depending upon options. */ + char *yy_cp = yyg->yy_c_buf_p; + + YY_CHAR yy_c = 1; + if (yy_accept[yy_current_state]) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) + { + yy_current_state = (int)yy_def[yy_current_state]; + if (yy_current_state >= 982) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + yy_is_jam = (yy_current_state == 981); + + (void)yyg; + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef YY_NO_INPUT +# ifdef __cplusplus +static int yyinput(yyscan_t yyscanner) +# else +static int input(yyscan_t yyscanner) +# endif + +{ + int c; + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + *yyg->yy_c_buf_p = yyg->yy_hold_char; + + if (*yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if (yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]) + /* This was really a NUL. */ + *yyg->yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = (int)(yyg->yy_c_buf_p - yyg->yytext_ptr); + ++yyg->yy_c_buf_p; + + switch (yy_get_next_buffer(yyscanner)) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin, yyscanner); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if (yywrap(yyscanner)) + return 0; + + if (!yyg->yy_did_buffer_switch_on_eof) + YY_NEW_FILE; +# ifdef __cplusplus + return yyinput(yyscanner); +# else + return input(yyscanner); +# endif + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *)yyg->yy_c_buf_p; /* cast for 8-bit char's */ + *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ + yyg->yy_hold_char = *++yyg->yy_c_buf_p; + + if (c == '\n') + + do + { + yylineno++; + yycolumn = 0; + } while (0); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ +void yyrestart(FILE *input_file, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + if (!YY_CURRENT_BUFFER) + { + yyensure_buffer_stack(yyscanner); + YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner); + } + + yy_init_buffer(YY_CURRENT_BUFFER, input_file, yyscanner); + yy_load_buffer_state(yyscanner); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ +void yy_switch_to_buffer(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack(yyscanner); + if (YY_CURRENT_BUFFER == new_buffer) + return; + + if (YY_CURRENT_BUFFER) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state(yyscanner); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yyg->yy_did_buffer_switch_on_eof = 1; +} + +static void yy_load_buffer_state(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ +YY_BUFFER_STATE yy_create_buffer(FILE *file, int size, yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE)yyalloc(sizeof(struct yy_buffer_state), yyscanner); + if (!b) + YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()"); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *)yyalloc((yy_size_t)(b->yy_buf_size + 2), yyscanner); + if (!b->yy_ch_buf) + YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()"); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b, file, yyscanner); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * @param yyscanner The scanner object. + */ +void yy_delete_buffer(YY_BUFFER_STATE b, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + if (!b) + return; + + if (b == YY_CURRENT_BUFFER) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE)0; + + if (b->yy_is_our_buffer) + yyfree((void *)b->yy_ch_buf, yyscanner); + + yyfree((void *)b, yyscanner); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ +static void yy_init_buffer(YY_BUFFER_STATE b, FILE *file, yyscan_t yyscanner) + +{ + int oerrno = errno; + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + yy_flush_buffer(b, yyscanner); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER) + { + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ +void yy_flush_buffer(YY_BUFFER_STATE b, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + if (!b) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if (b == YY_CURRENT_BUFFER) + yy_load_buffer_state(yyscanner); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * @param yyscanner The scanner object. + */ +void yypush_buffer_state(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(yyscanner); + + /* This block is copied from yy_switch_to_buffer. */ + if (YY_CURRENT_BUFFER) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + yyg->yy_buffer_stack_top++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state(yyscanner); + yyg->yy_did_buffer_switch_on_eof = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * @param yyscanner The scanner object. + */ +void yypop_buffer_state(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + if (yyg->yy_buffer_stack_top > 0) + --yyg->yy_buffer_stack_top; + + if (YY_CURRENT_BUFFER) + { + yy_load_buffer_state(yyscanner); + yyg->yy_did_buffer_switch_on_eof = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack(yyscan_t yyscanner) +{ + yy_size_t num_to_alloc; + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + if (!yyg->yy_buffer_stack) + { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + yyg->yy_buffer_stack = (struct yy_buffer_state **)yyalloc( + num_to_alloc * sizeof(struct yy_buffer_state *), yyscanner); + if (!yyg->yy_buffer_stack) + YY_FATAL_ERROR("out of dynamic memory in yyensure_buffer_stack()"); + + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state *)); + + yyg->yy_buffer_stack_max = num_to_alloc; + yyg->yy_buffer_stack_top = 0; + return; + } + + if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1) + { + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; + yyg->yy_buffer_stack = (struct yy_buffer_state **)yyrealloc( + yyg->yy_buffer_stack, num_to_alloc * sizeof(struct yy_buffer_state *), yyscanner); + if (!yyg->yy_buffer_stack) + YY_FATAL_ERROR("out of dynamic memory in yyensure_buffer_stack()"); + + /* zero only the new slots.*/ + memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, + grow_size * sizeof(struct yy_buffer_state *)); + yyg->yy_buffer_stack_max = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer(char *base, yy_size_t size, yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + if (size < 2 || base[size - 2] != YY_END_OF_BUFFER_CHAR || + base[size - 1] != YY_END_OF_BUFFER_CHAR) + /* They forgot to leave room for the EOB's. */ + return NULL; + + b = (YY_BUFFER_STATE)yyalloc(sizeof(struct yy_buffer_state), yyscanner); + if (!b) + YY_FATAL_ERROR("out of dynamic memory in yy_scan_buffer()"); + + b->yy_buf_size = (int)(size - 2); /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = NULL; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b, yyscanner); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string(const char *yystr, yyscan_t yyscanner) +{ + + return yy_scan_bytes(yystr, (int)strlen(yystr), yyscanner); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes(const char *yybytes, int _yybytes_len, yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = (yy_size_t)(_yybytes_len + 2); + buf = (char *)yyalloc(n, yyscanner); + if (!buf) + YY_FATAL_ERROR("out of dynamic memory in yy_scan_bytes()"); + + for (i = 0; i < _yybytes_len; ++i) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len + 1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf, n, yyscanner); + if (!b) + YY_FATAL_ERROR("bad buffer in yy_scan_bytes()"); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +# define YY_EXIT_FAILURE 2 +#endif + +static void yynoreturn yy_fatal_error(const char *msg, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + (void)yyg; + fprintf(stderr, "%s\n", msg); + exit(YY_EXIT_FAILURE); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg); \ + yytext[yyleng] = yyg->yy_hold_char; \ + yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ + yyg->yy_hold_char = *yyg->yy_c_buf_p; \ + *yyg->yy_c_buf_p = '\0'; \ + yyleng = yyless_macro_arg; \ + } while (0) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE yyget_extra(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + return yyextra; +} + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int yyget_lineno(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + if (!YY_CURRENT_BUFFER) + return 0; + + return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int yyget_column(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + if (!YY_CURRENT_BUFFER) + return 0; + + return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_in(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_out(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +int yyget_leng(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *yyget_text(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + return yytext; +} + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void yyset_extra(YY_EXTRA_TYPE user_defined, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + yyextra = user_defined; +} + +/** Set the current line number. + * @param _line_number line number + * @param yyscanner The scanner object. + */ +void yyset_lineno(int _line_number, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + /* lineno is only valid if an input buffer exists. */ + if (!YY_CURRENT_BUFFER) + YY_FATAL_ERROR("yyset_lineno called with no buffer"); + + yylineno = _line_number; +} + +/** Set the current column. + * @param _column_no column number + * @param yyscanner The scanner object. + */ +void yyset_column(int _column_no, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + /* column is only valid if an input buffer exists. */ + if (!YY_CURRENT_BUFFER) + YY_FATAL_ERROR("yyset_column called with no buffer"); + + yycolumn = _column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * @param yyscanner The scanner object. + * @see yy_switch_to_buffer + */ +void yyset_in(FILE *_in_str, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + yyin = _in_str; +} + +void yyset_out(FILE *_out_str, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + yyout = _out_str; +} + +int yyget_debug(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + return yy_flex_debug; +} + +void yyset_debug(int _bdebug, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + yy_flex_debug = _bdebug; +} + +/* Accessor methods for yylval and yylloc */ + +YYSTYPE *yyget_lval(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + return yylval; +} + +void yyset_lval(YYSTYPE *yylval_param, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + yylval = yylval_param; +} + +YYLTYPE *yyget_lloc(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + return yylloc; +} + +void yyset_lloc(YYLTYPE *yylloc_param, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + yylloc = yylloc_param; +} + +/* User-visible API */ + +/* yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ +int yylex_init(yyscan_t *ptr_yy_globals) +{ + if (ptr_yy_globals == NULL) + { + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t)yyalloc(sizeof(struct yyguts_t), NULL); + + if (*ptr_yy_globals == NULL) + { + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals, 0x00, sizeof(struct yyguts_t)); + + return yy_init_globals(*ptr_yy_globals); +} + +/* yylex_init_extra has the same functionality as yylex_init, but follows the + * convention of taking the scanner as the last argument. Note however, that + * this is a *pointer* to a scanner, as it will be allocated by this call (and + * is the reason, too, why this function also must handle its own declaration). + * The user defined value in the first argument will be available to yyalloc in + * the yyextra field. + */ +int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined, yyscan_t *ptr_yy_globals) +{ + struct yyguts_t dummy_yyguts; + + yyset_extra(yy_user_defined, &dummy_yyguts); + + if (ptr_yy_globals == NULL) + { + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t)yyalloc(sizeof(struct yyguts_t), &dummy_yyguts); + + if (*ptr_yy_globals == NULL) + { + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in + yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals, 0x00, sizeof(struct yyguts_t)); + + yyset_extra(yy_user_defined, *ptr_yy_globals); + + return yy_init_globals(*ptr_yy_globals); +} + +static int yy_init_globals(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + yyg->yy_buffer_stack = NULL; + yyg->yy_buffer_stack_top = 0; + yyg->yy_buffer_stack_max = 0; + yyg->yy_c_buf_p = NULL; + yyg->yy_init = 0; + yyg->yy_start = 0; + + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = NULL; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = NULL; + yyout = NULL; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + /* Pop the buffer stack, destroying each element. */ + while (YY_CURRENT_BUFFER) + { + yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(yyscanner); + } + + /* Destroy the stack itself. */ + yyfree(yyg->yy_buffer_stack, yyscanner); + yyg->yy_buffer_stack = NULL; + + /* Destroy the start condition stack. */ + yyfree(yyg->yy_start_stack, yyscanner); + yyg->yy_start_stack = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals(yyscanner); + + /* Destroy the main struct (reentrant only). */ + yyfree(yyscanner, yyscanner); + yyscanner = NULL; + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy(char *s1, const char *s2, int n, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + (void)yyg; + + int i; + for (i = 0; i < n; ++i) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen(const char *s, yyscan_t yyscanner) +{ + int n; + for (n = 0; s[n]; ++n) + ; + + return n; +} +#endif + +void *yyalloc(yy_size_t size, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + (void)yyg; + return malloc(size); +} + +void *yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + (void)yyg; + + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return realloc(ptr, size); +} + +void yyfree(void *ptr, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + (void)yyg; + free((char *)ptr); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +yy_size_t string_input(char *buf, yy_size_t max_size, yyscan_t yyscanner) +{ + angle::pp::Token token; + yyget_extra(yyscanner)->getPreprocessor().lex(&token); + yy_size_t len = token.type == angle::pp::Token::LAST ? 0 : token.text.size(); + if (len < max_size) + memcpy(buf, token.text.c_str(), len); + yyset_column(token.location.file, yyscanner); + yyset_lineno(token.location.line, yyscanner); + + if (len >= max_size) + YY_FATAL_ERROR("Input buffer overflow"); + else if (len > 0) + buf[len++] = ' '; + return len; +} + +int check_type(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + int token = IDENTIFIER; + // Note that the ImmutableString used here isn't static or pool allocated - but it's fine since + // yytext is valid for the duration of its use. + const TSymbol *symbol = + yyextra->symbolTable.find(ImmutableString(yytext, yyleng), yyextra->getShaderVersion()); + if (symbol && symbol->isStruct()) + { + token = TYPE_NAME; + } + yylval->lex.symbol = symbol; + return token; +} + +int reserved_word(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + yyextra->error(*yylloc, "Illegal use of reserved word", yytext); + return 0; +} + +static bool is_extension_enabled_or_is_core(TParseContext *context, + int extension_version, + TExtension extension, + int promotion_version) +{ + int version = context->getShaderVersion(); + + // If version is at least promotion_version, symbol is definitely keyword. Otherwise it's a + // keyword if version is at least extension_version (where the extension was introduced) and + // the extension is enabled. + return version >= promotion_version || + (version >= extension_version && context->isExtensionEnabled(extension)); +} + +int ES2_reserved_ES3_keyword(TParseContext *context, int token) +{ + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + if (context->getShaderVersion() < 300) + { + return reserved_word(yyscanner); + } + + return token; +} + +int ES2_keyword_ES3_reserved(TParseContext *context, int token) +{ + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + if (context->getShaderVersion() >= 300) + { + return reserved_word(yyscanner); + } + + return token; +} + +int ES3_reserved_ES3_1_keyword(TParseContext *context, int token) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + if (context->getShaderVersion() < 300) + { + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); + } + else if (context->getShaderVersion() == 300) + { + return reserved_word(yyscanner); + } + + return token; +} + +int ES3_keyword(TParseContext *context, int token) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name + if (context->getShaderVersion() < 300) + { + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); + } + + return token; +} + +int ES2_reserved_ES3_1_keyword(TParseContext *context, int token) +{ + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + if (context->getShaderVersion() < 310) + { + return reserved_word(yyscanner); + } + + return token; +} + +int ES3_1_keyword(TParseContext *context, int token) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + // A keyword in GLSL ES 3.10. + if (context->getShaderVersion() >= 310) + { + return token; + } + + // Otherwise can be used as an identifier/type name + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); +} + +int WEBGL_video_texture_extension(TParseContext *context, int token) +{ + // Available with WEBGL_video_texture_extension + if (context->isExtensionEnabled(TExtension::WEBGL_video_texture)) + { + return token; + } + + // Otherwise can be used as an identifier/type name + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); +} + +int ES2_extensions_ES3_keyword(TParseContext *context, + TExtension extension1, + TExtension extension2, + TExtension extension3, + int token) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + // A keyword in GLSL ES 3.00 or GLSL ES 1.00 with enabled extension. + if (is_extension_enabled_or_is_core(context, 100, extension1, 300)) + { + return token; + } + else if (is_extension_enabled_or_is_core(context, 100, extension2, 300)) + { + return token; + } + else if (is_extension_enabled_or_is_core(context, 100, extension3, 300)) + { + return token; + } + + // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); +} + +int ES2_reserved_ES2_extension_ES3_keyword(TParseContext *context, TExtension extension, int token) +{ + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + // A keyword in GLSL ES 3.00 or GLSL ES 1.00 with enabled extension. + if (is_extension_enabled_or_is_core(context, 100, extension, 300)) + { + return token; + } + + // Reserved otherwise. + return reserved_word(yyscanner); +} + +int ES3_extension(TParseContext *context, TExtension extension, int token) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + // a keyword word in GLSL ES 3.00 with enabled extension. + if (context->getShaderVersion() >= 300 && context->isExtensionEnabled(extension)) + { + return token; + } + + // Otherwise can be used as an identifier/type name + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); +} + +int ES3_reserved_ES3_1_extension_ES3_2_keyword(TParseContext *context, + TExtension extension, + int token) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + // a keyword in GLSL ES 3.10 with enabled extension + if (is_extension_enabled_or_is_core(context, 310, extension, 320)) + { + return token; + } + // a reserved word in GLSL ES 3.00+ + if (context->getShaderVersion() >= 300) + { + return reserved_word(yyscanner); + } + + // Otherwise can be used as an identifier/type name + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); +} + +int ES3_reserved_ES3_extension(TParseContext *context, TExtension extension, int token) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + if (context->getShaderVersion() >= 300) + { + if (context->isExtensionEnabled(extension)) + { + return token; + } + else + { + return reserved_word(yyscanner); + } + } + + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); +} + +int ES3_reserved_ES3_extension_ES3_1_keyword(TParseContext *context, + TExtension extension, + int token) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + // A keyword in GLSL ES 3.00 with enabled extension or in GLSL ES 3.10 + if (is_extension_enabled_or_is_core(context, 300, extension, 310)) + { + return token; + } + + if (context->getShaderVersion() == 300) + { + return reserved_word(yyscanner); + } + + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); +} + +int ES3_reserved_ES3_extension_ES3_2_keyword(TParseContext *context, + TExtension extension, + int token) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + // A keyword in GLSL ES 3.00 with enabled extension or in GLSL ES 3.20 + if (is_extension_enabled_or_is_core(context, 300, extension, 320)) + { + return token; + } + + if (context->getShaderVersion() == 300 || context->getShaderVersion() == 310) + { + return reserved_word(yyscanner); + } + + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); +} + +static int ES3_1_reserved_ES3_1_extension_ES3_2_keyword(TParseContext *context, + TExtension extension, + int token) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + // A keyword in GLSL ES 3.20 or GLSL ES 3.10 with enabled extension. + if (is_extension_enabled_or_is_core(context, 310, extension, 320)) + { + return token; + } + + // A reserved word in GLSL ES 3.10 + if (context->getShaderVersion() == 310) + { + return reserved_word(yyscanner); + } + + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); +} + +static int ES3_1_reserved_ES3_1_extension_ES3_2_keyword_2(TParseContext *context, + TExtension extension1, + TExtension extension2, + int token1, + int token2) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + // A keyword in GLSL ES 3.20 or GLSL ES 3.10 with enabled extension. + if (is_extension_enabled_or_is_core(context, 310, extension1, 320)) + { + return token1; + } + else if (is_extension_enabled_or_is_core(context, 310, extension2, 320)) + { + return token2; + } + + // A reserved word in GLSL ES 3.10 + if (context->getShaderVersion() == 310) + { + return reserved_word(yyscanner); + } + + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); +} + +static int ES3_and_3_1_reserved_ES3_1_extension_ES3_2_keyword_2(TParseContext *context, + TExtension extension1, + TExtension extension2, + int token1, + int token2) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + // A keyword in GLSL ES 3.20 or GLSL ES 3.10 with enabled extension. + if (is_extension_enabled_or_is_core(context, 310, extension1, 320)) + { + return token1; + } + else if (is_extension_enabled_or_is_core(context, 310, extension2, 320)) + { + return token2; + } + + // A reserved word in GLSL ES 3.00 and 3.10 + if (context->getShaderVersion() >= 300) + { + return reserved_word(yyscanner); + } + + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); +} + +int uint_constant(TParseContext *context) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + + if (context->getShaderVersion() < 300) + { + context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext); + return 0; + } + + if (!atoi_clamp(yytext, &(yylval->lex.u))) + yyextra->error(*yylloc, "Integer overflow", yytext); + + return UINTCONSTANT; +} + +int floatsuffix_check(TParseContext *context) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + + if (context->getShaderVersion() < 300) + { + context->error(*yylloc, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext); + return 0; + } + + std::string text = yytext; + text.resize(text.size() - 1); + if (!strtof_clamp(text, &(yylval->lex.f))) + yyextra->warning(*yylloc, "Float overflow", yytext); + + return (FLOATCONSTANT); +} + +void yyerror(YYLTYPE *lloc, TParseContext *context, void *scanner, const char *reason) +{ + context->error(*lloc, reason, yyget_text(scanner)); +} + +int int_constant(TParseContext *context) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + + unsigned int u; + if (!atoi_clamp(yytext, &u)) + { + if (context->getShaderVersion() >= 300) + yyextra->error(*yylloc, "Integer overflow", yytext); + else + yyextra->warning(*yylloc, "Integer overflow", yytext); + } + yylval->lex.i = static_cast(u); + return INTCONSTANT; +} + +int float_constant(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t *)yyscanner; + + if (!strtof_clamp(yytext, &(yylval->lex.f))) + yyextra->warning(*yylloc, "Float overflow", yytext); + return FLOATCONSTANT; +} + +int yuvcscstandardext_constant(TParseContext *context) +{ + struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner(); + yyscan_t yyscanner = (yyscan_t)context->getScanner(); + + // a reserved word in GLSL ES 3.00 with enabled extension, otherwise could be used as an + // identifier/type name + if (context->getShaderVersion() >= 300 && + context->isExtensionEnabled(TExtension::EXT_YUV_target)) + { + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return YUVCSCSTANDARDEXTCONSTANT; + } + + yylval->lex.string = AllocatePoolCharArray(yytext, yyleng); + return check_type(yyscanner); +} + +int glslang_initialize(TParseContext *context) +{ + yyscan_t scanner = NULL; + if (yylex_init_extra(context, &scanner)) + return 1; + + context->setScanner(scanner); + return 0; +} + +int glslang_finalize(TParseContext *context) +{ + yyscan_t scanner = context->getScanner(); + if (scanner == NULL) + return 0; + + context->setScanner(NULL); + yylex_destroy(scanner); + + return 0; +} + +int glslang_scan(size_t count, + const char *const string[], + const int length[], + TParseContext *context) +{ + yyrestart(NULL, context->getScanner()); + yyset_column(0, context->getScanner()); + yyset_lineno(1, context->getScanner()); + + // Initialize preprocessor. + angle::pp::Preprocessor *preprocessor = &context->getPreprocessor(); + + if (!preprocessor->init(count, string, length)) + return 1; + + // Define extension macros. + const TExtensionBehavior &extBehavior = context->extensionBehavior(); + for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); iter != extBehavior.end(); + ++iter) + { + // OVR_multiview should not be defined for WebGL spec'ed shaders. + if (sh::IsWebGLBasedSpec(context->getShaderSpec()) && + iter->first == TExtension::OVR_multiview) + { + continue; + } + preprocessor->predefineMacro(GetExtensionNameString(iter->first), 1); + } + if (context->getFragmentPrecisionHigh()) + preprocessor->predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1); + + preprocessor->setMaxTokenSize(sh::GetGlobalMaxTokenSize(context->getShaderSpec())); + + return 0; +} diff --git a/gfx/angle/checkout/src/compiler/translator/glslang_tab_autogen.cpp b/gfx/angle/checkout/src/compiler/translator/glslang_tab_autogen.cpp new file mode 100644 index 0000000000..233b571b79 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/glslang_tab_autogen.cpp @@ -0,0 +1,4909 @@ +/* A Bison parser, made by GNU Bison 3.8.2. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output, and Bison version. */ +#define YYBISON 30802 + +/* Bison version string. */ +#define YYBISON_VERSION "3.8.2" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 2 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* First part of user prologue. */ + +// GENERATED FILE - DO NOT EDIT. +// Generated by generate_parser.py from glslang.y +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// glslang.y: +// Parser for the OpenGL shading language. + +// Ignore errors in auto-generated code. +#if defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wunused-function" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic ignored "-Wswitch-enum" +#elif defined(_MSC_VER) +# pragma warning(disable : 4065) +# pragma warning(disable : 4189) +# pragma warning(disable : 4244) +# pragma warning(disable : 4505) +# pragma warning(disable : 4701) +# pragma warning(disable : 4702) +#endif +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunreachable-code" +# pragma clang diagnostic ignored "-Wunused-but-set-variable" +#endif + +#include "GLSLANG/ShaderLang.h" +#include "angle_gl.h" +#include "compiler/translator/Declarator.h" +#include "compiler/translator/ParseContext.h" +#include "compiler/translator/SymbolTable.h" + +#define YYENABLE_NLS 0 + +using namespace sh; + +#ifndef YY_CAST +# ifdef __cplusplus +# define YY_CAST(Type, Val) static_cast(Val) +# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast(Val) +# else +# define YY_CAST(Type, Val) ((Type)(Val)) +# define YY_REINTERPRET_CAST(Type, Val) ((Type)(Val)) +# endif +#endif +#ifndef YY_NULLPTR +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# else +# define YY_NULLPTR ((void *)0) +# endif +#endif + +#include "glslang_tab_autogen.h" +/* Symbol kind. */ +enum yysymbol_kind_t +{ + YYSYMBOL_YYEMPTY = -2, + YYSYMBOL_YYEOF = 0, /* "end of file" */ + YYSYMBOL_YYerror = 1, /* error */ + YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ + YYSYMBOL_INVARIANT = 3, /* INVARIANT */ + YYSYMBOL_PRECISE = 4, /* PRECISE */ + YYSYMBOL_HIGH_PRECISION = 5, /* HIGH_PRECISION */ + YYSYMBOL_MEDIUM_PRECISION = 6, /* MEDIUM_PRECISION */ + YYSYMBOL_LOW_PRECISION = 7, /* LOW_PRECISION */ + YYSYMBOL_PRECISION = 8, /* PRECISION */ + YYSYMBOL_ATTRIBUTE = 9, /* ATTRIBUTE */ + YYSYMBOL_CONST_QUAL = 10, /* CONST_QUAL */ + YYSYMBOL_BOOL_TYPE = 11, /* BOOL_TYPE */ + YYSYMBOL_FLOAT_TYPE = 12, /* FLOAT_TYPE */ + YYSYMBOL_INT_TYPE = 13, /* INT_TYPE */ + YYSYMBOL_UINT_TYPE = 14, /* UINT_TYPE */ + YYSYMBOL_BREAK = 15, /* BREAK */ + YYSYMBOL_CONTINUE = 16, /* CONTINUE */ + YYSYMBOL_DO = 17, /* DO */ + YYSYMBOL_ELSE = 18, /* ELSE */ + YYSYMBOL_FOR = 19, /* FOR */ + YYSYMBOL_IF = 20, /* IF */ + YYSYMBOL_DISCARD = 21, /* DISCARD */ + YYSYMBOL_RETURN = 22, /* RETURN */ + YYSYMBOL_SWITCH = 23, /* SWITCH */ + YYSYMBOL_CASE = 24, /* CASE */ + YYSYMBOL_DEFAULT = 25, /* DEFAULT */ + YYSYMBOL_BVEC2 = 26, /* BVEC2 */ + YYSYMBOL_BVEC3 = 27, /* BVEC3 */ + YYSYMBOL_BVEC4 = 28, /* BVEC4 */ + YYSYMBOL_IVEC2 = 29, /* IVEC2 */ + YYSYMBOL_IVEC3 = 30, /* IVEC3 */ + YYSYMBOL_IVEC4 = 31, /* IVEC4 */ + YYSYMBOL_VEC2 = 32, /* VEC2 */ + YYSYMBOL_VEC3 = 33, /* VEC3 */ + YYSYMBOL_VEC4 = 34, /* VEC4 */ + YYSYMBOL_UVEC2 = 35, /* UVEC2 */ + YYSYMBOL_UVEC3 = 36, /* UVEC3 */ + YYSYMBOL_UVEC4 = 37, /* UVEC4 */ + YYSYMBOL_MATRIX2 = 38, /* MATRIX2 */ + YYSYMBOL_MATRIX3 = 39, /* MATRIX3 */ + YYSYMBOL_MATRIX4 = 40, /* MATRIX4 */ + YYSYMBOL_IN_QUAL = 41, /* IN_QUAL */ + YYSYMBOL_OUT_QUAL = 42, /* OUT_QUAL */ + YYSYMBOL_INOUT_QUAL = 43, /* INOUT_QUAL */ + YYSYMBOL_UNIFORM = 44, /* UNIFORM */ + YYSYMBOL_BUFFER = 45, /* BUFFER */ + YYSYMBOL_VARYING = 46, /* VARYING */ + YYSYMBOL_MATRIX2x3 = 47, /* MATRIX2x3 */ + YYSYMBOL_MATRIX3x2 = 48, /* MATRIX3x2 */ + YYSYMBOL_MATRIX2x4 = 49, /* MATRIX2x4 */ + YYSYMBOL_MATRIX4x2 = 50, /* MATRIX4x2 */ + YYSYMBOL_MATRIX3x4 = 51, /* MATRIX3x4 */ + YYSYMBOL_MATRIX4x3 = 52, /* MATRIX4x3 */ + YYSYMBOL_SAMPLE = 53, /* SAMPLE */ + YYSYMBOL_CENTROID = 54, /* CENTROID */ + YYSYMBOL_FLAT = 55, /* FLAT */ + YYSYMBOL_SMOOTH = 56, /* SMOOTH */ + YYSYMBOL_NOPERSPECTIVE = 57, /* NOPERSPECTIVE */ + YYSYMBOL_PATCH = 58, /* PATCH */ + YYSYMBOL_READONLY = 59, /* READONLY */ + YYSYMBOL_WRITEONLY = 60, /* WRITEONLY */ + YYSYMBOL_COHERENT = 61, /* COHERENT */ + YYSYMBOL_RESTRICT = 62, /* RESTRICT */ + YYSYMBOL_VOLATILE = 63, /* VOLATILE */ + YYSYMBOL_SHARED = 64, /* SHARED */ + YYSYMBOL_STRUCT = 65, /* STRUCT */ + YYSYMBOL_VOID_TYPE = 66, /* VOID_TYPE */ + YYSYMBOL_WHILE = 67, /* WHILE */ + YYSYMBOL_SAMPLER2D = 68, /* SAMPLER2D */ + YYSYMBOL_SAMPLERCUBE = 69, /* SAMPLERCUBE */ + YYSYMBOL_SAMPLER_EXTERNAL_OES = 70, /* SAMPLER_EXTERNAL_OES */ + YYSYMBOL_SAMPLER2DRECT = 71, /* SAMPLER2DRECT */ + YYSYMBOL_SAMPLER2DARRAY = 72, /* SAMPLER2DARRAY */ + YYSYMBOL_ISAMPLER2D = 73, /* ISAMPLER2D */ + YYSYMBOL_ISAMPLER3D = 74, /* ISAMPLER3D */ + YYSYMBOL_ISAMPLERCUBE = 75, /* ISAMPLERCUBE */ + YYSYMBOL_ISAMPLER2DARRAY = 76, /* ISAMPLER2DARRAY */ + YYSYMBOL_USAMPLER2D = 77, /* USAMPLER2D */ + YYSYMBOL_USAMPLER3D = 78, /* USAMPLER3D */ + YYSYMBOL_USAMPLERCUBE = 79, /* USAMPLERCUBE */ + YYSYMBOL_USAMPLER2DARRAY = 80, /* USAMPLER2DARRAY */ + YYSYMBOL_SAMPLER2DMS = 81, /* SAMPLER2DMS */ + YYSYMBOL_ISAMPLER2DMS = 82, /* ISAMPLER2DMS */ + YYSYMBOL_USAMPLER2DMS = 83, /* USAMPLER2DMS */ + YYSYMBOL_SAMPLER2DMSARRAY = 84, /* SAMPLER2DMSARRAY */ + YYSYMBOL_ISAMPLER2DMSARRAY = 85, /* ISAMPLER2DMSARRAY */ + YYSYMBOL_USAMPLER2DMSARRAY = 86, /* USAMPLER2DMSARRAY */ + YYSYMBOL_SAMPLER3D = 87, /* SAMPLER3D */ + YYSYMBOL_SAMPLER3DRECT = 88, /* SAMPLER3DRECT */ + YYSYMBOL_SAMPLER2DSHADOW = 89, /* SAMPLER2DSHADOW */ + YYSYMBOL_SAMPLERCUBESHADOW = 90, /* SAMPLERCUBESHADOW */ + YYSYMBOL_SAMPLER2DARRAYSHADOW = 91, /* SAMPLER2DARRAYSHADOW */ + YYSYMBOL_SAMPLERVIDEOWEBGL = 92, /* SAMPLERVIDEOWEBGL */ + YYSYMBOL_SAMPLERCUBEARRAYOES = 93, /* SAMPLERCUBEARRAYOES */ + YYSYMBOL_SAMPLERCUBEARRAYSHADOWOES = 94, /* SAMPLERCUBEARRAYSHADOWOES */ + YYSYMBOL_ISAMPLERCUBEARRAYOES = 95, /* ISAMPLERCUBEARRAYOES */ + YYSYMBOL_USAMPLERCUBEARRAYOES = 96, /* USAMPLERCUBEARRAYOES */ + YYSYMBOL_SAMPLERCUBEARRAYEXT = 97, /* SAMPLERCUBEARRAYEXT */ + YYSYMBOL_SAMPLERCUBEARRAYSHADOWEXT = 98, /* SAMPLERCUBEARRAYSHADOWEXT */ + YYSYMBOL_ISAMPLERCUBEARRAYEXT = 99, /* ISAMPLERCUBEARRAYEXT */ + YYSYMBOL_USAMPLERCUBEARRAYEXT = 100, /* USAMPLERCUBEARRAYEXT */ + YYSYMBOL_SAMPLERBUFFER = 101, /* SAMPLERBUFFER */ + YYSYMBOL_ISAMPLERBUFFER = 102, /* ISAMPLERBUFFER */ + YYSYMBOL_USAMPLERBUFFER = 103, /* USAMPLERBUFFER */ + YYSYMBOL_SAMPLEREXTERNAL2DY2YEXT = 104, /* SAMPLEREXTERNAL2DY2YEXT */ + YYSYMBOL_IMAGE2D = 105, /* IMAGE2D */ + YYSYMBOL_IIMAGE2D = 106, /* IIMAGE2D */ + YYSYMBOL_UIMAGE2D = 107, /* UIMAGE2D */ + YYSYMBOL_IMAGE3D = 108, /* IMAGE3D */ + YYSYMBOL_IIMAGE3D = 109, /* IIMAGE3D */ + YYSYMBOL_UIMAGE3D = 110, /* UIMAGE3D */ + YYSYMBOL_IMAGE2DARRAY = 111, /* IMAGE2DARRAY */ + YYSYMBOL_IIMAGE2DARRAY = 112, /* IIMAGE2DARRAY */ + YYSYMBOL_UIMAGE2DARRAY = 113, /* UIMAGE2DARRAY */ + YYSYMBOL_IMAGECUBE = 114, /* IMAGECUBE */ + YYSYMBOL_IIMAGECUBE = 115, /* IIMAGECUBE */ + YYSYMBOL_UIMAGECUBE = 116, /* UIMAGECUBE */ + YYSYMBOL_IMAGECUBEARRAYOES = 117, /* IMAGECUBEARRAYOES */ + YYSYMBOL_IIMAGECUBEARRAYOES = 118, /* IIMAGECUBEARRAYOES */ + YYSYMBOL_UIMAGECUBEARRAYOES = 119, /* UIMAGECUBEARRAYOES */ + YYSYMBOL_IMAGECUBEARRAYEXT = 120, /* IMAGECUBEARRAYEXT */ + YYSYMBOL_IIMAGECUBEARRAYEXT = 121, /* IIMAGECUBEARRAYEXT */ + YYSYMBOL_UIMAGECUBEARRAYEXT = 122, /* UIMAGECUBEARRAYEXT */ + YYSYMBOL_IMAGEBUFFER = 123, /* IMAGEBUFFER */ + YYSYMBOL_IIMAGEBUFFER = 124, /* IIMAGEBUFFER */ + YYSYMBOL_UIMAGEBUFFER = 125, /* UIMAGEBUFFER */ + YYSYMBOL_ATOMICUINT = 126, /* ATOMICUINT */ + YYSYMBOL_PIXELLOCALANGLE = 127, /* PIXELLOCALANGLE */ + YYSYMBOL_IPIXELLOCALANGLE = 128, /* IPIXELLOCALANGLE */ + YYSYMBOL_UPIXELLOCALANGLE = 129, /* UPIXELLOCALANGLE */ + YYSYMBOL_LAYOUT = 130, /* LAYOUT */ + YYSYMBOL_YUVCSCSTANDARDEXT = 131, /* YUVCSCSTANDARDEXT */ + YYSYMBOL_YUVCSCSTANDARDEXTCONSTANT = 132, /* YUVCSCSTANDARDEXTCONSTANT */ + YYSYMBOL_IDENTIFIER = 133, /* IDENTIFIER */ + YYSYMBOL_TYPE_NAME = 134, /* TYPE_NAME */ + YYSYMBOL_FLOATCONSTANT = 135, /* FLOATCONSTANT */ + YYSYMBOL_INTCONSTANT = 136, /* INTCONSTANT */ + YYSYMBOL_UINTCONSTANT = 137, /* UINTCONSTANT */ + YYSYMBOL_BOOLCONSTANT = 138, /* BOOLCONSTANT */ + YYSYMBOL_FIELD_SELECTION = 139, /* FIELD_SELECTION */ + YYSYMBOL_LEFT_OP = 140, /* LEFT_OP */ + YYSYMBOL_RIGHT_OP = 141, /* RIGHT_OP */ + YYSYMBOL_INC_OP = 142, /* INC_OP */ + YYSYMBOL_DEC_OP = 143, /* DEC_OP */ + YYSYMBOL_LE_OP = 144, /* LE_OP */ + YYSYMBOL_GE_OP = 145, /* GE_OP */ + YYSYMBOL_EQ_OP = 146, /* EQ_OP */ + YYSYMBOL_NE_OP = 147, /* NE_OP */ + YYSYMBOL_AND_OP = 148, /* AND_OP */ + YYSYMBOL_OR_OP = 149, /* OR_OP */ + YYSYMBOL_XOR_OP = 150, /* XOR_OP */ + YYSYMBOL_MUL_ASSIGN = 151, /* MUL_ASSIGN */ + YYSYMBOL_DIV_ASSIGN = 152, /* DIV_ASSIGN */ + YYSYMBOL_ADD_ASSIGN = 153, /* ADD_ASSIGN */ + YYSYMBOL_MOD_ASSIGN = 154, /* MOD_ASSIGN */ + YYSYMBOL_LEFT_ASSIGN = 155, /* LEFT_ASSIGN */ + YYSYMBOL_RIGHT_ASSIGN = 156, /* RIGHT_ASSIGN */ + YYSYMBOL_AND_ASSIGN = 157, /* AND_ASSIGN */ + YYSYMBOL_XOR_ASSIGN = 158, /* XOR_ASSIGN */ + YYSYMBOL_OR_ASSIGN = 159, /* OR_ASSIGN */ + YYSYMBOL_SUB_ASSIGN = 160, /* SUB_ASSIGN */ + YYSYMBOL_LEFT_PAREN = 161, /* LEFT_PAREN */ + YYSYMBOL_RIGHT_PAREN = 162, /* RIGHT_PAREN */ + YYSYMBOL_LEFT_BRACKET = 163, /* LEFT_BRACKET */ + YYSYMBOL_RIGHT_BRACKET = 164, /* RIGHT_BRACKET */ + YYSYMBOL_LEFT_BRACE = 165, /* LEFT_BRACE */ + YYSYMBOL_RIGHT_BRACE = 166, /* RIGHT_BRACE */ + YYSYMBOL_DOT = 167, /* DOT */ + YYSYMBOL_COMMA = 168, /* COMMA */ + YYSYMBOL_COLON = 169, /* COLON */ + YYSYMBOL_EQUAL = 170, /* EQUAL */ + YYSYMBOL_SEMICOLON = 171, /* SEMICOLON */ + YYSYMBOL_BANG = 172, /* BANG */ + YYSYMBOL_DASH = 173, /* DASH */ + YYSYMBOL_TILDE = 174, /* TILDE */ + YYSYMBOL_PLUS = 175, /* PLUS */ + YYSYMBOL_STAR = 176, /* STAR */ + YYSYMBOL_SLASH = 177, /* SLASH */ + YYSYMBOL_PERCENT = 178, /* PERCENT */ + YYSYMBOL_LEFT_ANGLE = 179, /* LEFT_ANGLE */ + YYSYMBOL_RIGHT_ANGLE = 180, /* RIGHT_ANGLE */ + YYSYMBOL_VERTICAL_BAR = 181, /* VERTICAL_BAR */ + YYSYMBOL_CARET = 182, /* CARET */ + YYSYMBOL_AMPERSAND = 183, /* AMPERSAND */ + YYSYMBOL_QUESTION = 184, /* QUESTION */ + YYSYMBOL_YYACCEPT = 185, /* $accept */ + YYSYMBOL_identifier = 186, /* identifier */ + YYSYMBOL_variable_identifier = 187, /* variable_identifier */ + YYSYMBOL_primary_expression = 188, /* primary_expression */ + YYSYMBOL_postfix_expression = 189, /* postfix_expression */ + YYSYMBOL_integer_expression = 190, /* integer_expression */ + YYSYMBOL_function_call = 191, /* function_call */ + YYSYMBOL_function_call_or_method = 192, /* function_call_or_method */ + YYSYMBOL_function_call_generic = 193, /* function_call_generic */ + YYSYMBOL_function_call_header_no_parameters = 194, /* function_call_header_no_parameters */ + YYSYMBOL_function_call_header_with_parameters = 195, /* function_call_header_with_parameters */ + YYSYMBOL_function_call_header = 196, /* function_call_header */ + YYSYMBOL_function_identifier = 197, /* function_identifier */ + YYSYMBOL_unary_expression = 198, /* unary_expression */ + YYSYMBOL_unary_operator = 199, /* unary_operator */ + YYSYMBOL_multiplicative_expression = 200, /* multiplicative_expression */ + YYSYMBOL_additive_expression = 201, /* additive_expression */ + YYSYMBOL_shift_expression = 202, /* shift_expression */ + YYSYMBOL_relational_expression = 203, /* relational_expression */ + YYSYMBOL_equality_expression = 204, /* equality_expression */ + YYSYMBOL_and_expression = 205, /* and_expression */ + YYSYMBOL_exclusive_or_expression = 206, /* exclusive_or_expression */ + YYSYMBOL_inclusive_or_expression = 207, /* inclusive_or_expression */ + YYSYMBOL_logical_and_expression = 208, /* logical_and_expression */ + YYSYMBOL_logical_xor_expression = 209, /* logical_xor_expression */ + YYSYMBOL_logical_or_expression = 210, /* logical_or_expression */ + YYSYMBOL_conditional_expression = 211, /* conditional_expression */ + YYSYMBOL_assignment_expression = 212, /* assignment_expression */ + YYSYMBOL_assignment_operator = 213, /* assignment_operator */ + YYSYMBOL_expression = 214, /* expression */ + YYSYMBOL_constant_expression = 215, /* constant_expression */ + YYSYMBOL_enter_struct = 216, /* enter_struct */ + YYSYMBOL_declaration = 217, /* declaration */ + YYSYMBOL_function_prototype = 218, /* function_prototype */ + YYSYMBOL_function_declarator = 219, /* function_declarator */ + YYSYMBOL_function_header_with_parameters = 220, /* function_header_with_parameters */ + YYSYMBOL_function_header = 221, /* function_header */ + YYSYMBOL_parameter_declarator = 222, /* parameter_declarator */ + YYSYMBOL_parameter_declaration = 223, /* parameter_declaration */ + YYSYMBOL_parameter_type_specifier = 224, /* parameter_type_specifier */ + YYSYMBOL_init_declarator_list = 225, /* init_declarator_list */ + YYSYMBOL_single_declaration = 226, /* single_declaration */ + YYSYMBOL_fully_specified_type = 227, /* fully_specified_type */ + YYSYMBOL_interpolation_qualifier = 228, /* interpolation_qualifier */ + YYSYMBOL_type_qualifier = 229, /* type_qualifier */ + YYSYMBOL_invariant_qualifier = 230, /* invariant_qualifier */ + YYSYMBOL_precise_qualifier = 231, /* precise_qualifier */ + YYSYMBOL_single_type_qualifier = 232, /* single_type_qualifier */ + YYSYMBOL_storage_qualifier = 233, /* storage_qualifier */ + YYSYMBOL_type_specifier = 234, /* type_specifier */ + YYSYMBOL_precision_qualifier = 235, /* precision_qualifier */ + YYSYMBOL_layout_qualifier = 236, /* layout_qualifier */ + YYSYMBOL_layout_qualifier_id_list = 237, /* layout_qualifier_id_list */ + YYSYMBOL_layout_qualifier_id = 238, /* layout_qualifier_id */ + YYSYMBOL_type_specifier_no_prec = 239, /* type_specifier_no_prec */ + YYSYMBOL_array_specifier = 240, /* array_specifier */ + YYSYMBOL_type_specifier_nonarray = 241, /* type_specifier_nonarray */ + YYSYMBOL_struct_specifier = 242, /* struct_specifier */ + YYSYMBOL_243_1 = 243, /* $@1 */ + YYSYMBOL_244_2 = 244, /* $@2 */ + YYSYMBOL_struct_declaration_list = 245, /* struct_declaration_list */ + YYSYMBOL_struct_declaration = 246, /* struct_declaration */ + YYSYMBOL_struct_declarator_list = 247, /* struct_declarator_list */ + YYSYMBOL_struct_declarator = 248, /* struct_declarator */ + YYSYMBOL_initializer = 249, /* initializer */ + YYSYMBOL_declaration_statement = 250, /* declaration_statement */ + YYSYMBOL_statement = 251, /* statement */ + YYSYMBOL_simple_statement = 252, /* simple_statement */ + YYSYMBOL_compound_statement_with_scope = 253, /* compound_statement_with_scope */ + YYSYMBOL_254_3 = 254, /* $@3 */ + YYSYMBOL_255_4 = 255, /* $@4 */ + YYSYMBOL_statement_no_new_scope = 256, /* statement_no_new_scope */ + YYSYMBOL_statement_with_scope = 257, /* statement_with_scope */ + YYSYMBOL_258_5 = 258, /* $@5 */ + YYSYMBOL_259_6 = 259, /* $@6 */ + YYSYMBOL_compound_statement_no_new_scope = 260, /* compound_statement_no_new_scope */ + YYSYMBOL_statement_list = 261, /* statement_list */ + YYSYMBOL_expression_statement = 262, /* expression_statement */ + YYSYMBOL_selection_statement = 263, /* selection_statement */ + YYSYMBOL_selection_rest_statement = 264, /* selection_rest_statement */ + YYSYMBOL_switch_statement = 265, /* switch_statement */ + YYSYMBOL_266_7 = 266, /* $@7 */ + YYSYMBOL_case_label = 267, /* case_label */ + YYSYMBOL_condition = 268, /* condition */ + YYSYMBOL_iteration_statement = 269, /* iteration_statement */ + YYSYMBOL_270_8 = 270, /* $@8 */ + YYSYMBOL_271_9 = 271, /* $@9 */ + YYSYMBOL_272_10 = 272, /* $@10 */ + YYSYMBOL_for_init_statement = 273, /* for_init_statement */ + YYSYMBOL_conditionopt = 274, /* conditionopt */ + YYSYMBOL_for_rest_statement = 275, /* for_rest_statement */ + YYSYMBOL_jump_statement = 276, /* jump_statement */ + YYSYMBOL_translation_unit = 277, /* translation_unit */ + YYSYMBOL_external_declaration = 278, /* external_declaration */ + YYSYMBOL_function_definition = 279, /* function_definition */ + YYSYMBOL_280_11 = 280 /* $@11 */ +}; +typedef enum yysymbol_kind_t yysymbol_kind_t; + +/* Second part of user prologue. */ + +extern int yylex(YYSTYPE *yylval, YYLTYPE *yylloc, void *yyscanner); +extern void yyerror(YYLTYPE *yylloc, TParseContext *context, void *scanner, const char *reason); + +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + { \ + if (N) \ + { \ + (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \ + (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ + (Current).last_file = YYRHSLOC(Rhs, N).last_file; \ + (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ + } \ + else \ + { \ + (Current).first_file = YYRHSLOC(Rhs, 0).last_file; \ + (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \ + (Current).last_file = YYRHSLOC(Rhs, 0).last_file; \ + (Current).last_line = YYRHSLOC(Rhs, 0).last_line; \ + } \ + } while (0) + +#define VERTEX_ONLY(S, L) \ + do \ + { \ + if (context->getShaderType() != GL_VERTEX_SHADER) \ + { \ + context->error(L, " supported in vertex shaders only", S); \ + } \ + } while (0) + +#define COMPUTE_ONLY(S, L) \ + do \ + { \ + if (context->getShaderType() != GL_COMPUTE_SHADER) \ + { \ + context->error(L, " supported in compute shaders only", S); \ + } \ + } while (0) + +#define ES2_ONLY(S, L) \ + do \ + { \ + if (context->getShaderVersion() != 100) \ + { \ + context->error(L, " supported in GLSL ES 1.00 only", S); \ + } \ + } while (0) + +#define ES3_OR_NEWER(TOKEN, LINE, REASON) \ + do \ + { \ + if (context->getShaderVersion() < 300) \ + { \ + context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN); \ + } \ + } while (0) + +#define ES3_1_OR_NEWER(TOKEN, LINE, REASON) \ + do \ + { \ + if (context->getShaderVersion() < 310) \ + { \ + context->error(LINE, REASON " supported in GLSL ES 3.10 and above only", TOKEN); \ + } \ + } while (0) + +#ifdef short +# undef short +#endif + +/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure + and (if available) are included + so that the code can choose integer types of a good width. */ + +#ifndef __PTRDIFF_MAX__ +# include /* INFRINGES ON USER NAME SPACE */ +# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_STDINT_H +# endif +#endif + +/* Narrow types that promote to a signed type and that can represent a + signed or unsigned integer of at least N bits. In tables they can + save space and decrease cache pressure. Promoting to a signed type + helps avoid bugs in integer arithmetic. */ + +#ifdef __INT_LEAST8_MAX__ +typedef __INT_LEAST8_TYPE__ yytype_int8; +#elif defined YY_STDINT_H +typedef int_least8_t yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef __INT_LEAST16_MAX__ +typedef __INT_LEAST16_TYPE__ yytype_int16; +#elif defined YY_STDINT_H +typedef int_least16_t yytype_int16; +#else +typedef short yytype_int16; +#endif + +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + . */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + +#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST8_TYPE__ yytype_uint8; +#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H && UINT_LEAST8_MAX <= INT_MAX) +typedef uint_least8_t yytype_uint8; +#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX +typedef unsigned char yytype_uint8; +#else +typedef short yytype_uint8; +#endif + +#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST16_TYPE__ yytype_uint16; +#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H && UINT_LEAST16_MAX <= INT_MAX) +typedef uint_least16_t yytype_uint16; +#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX +typedef unsigned short yytype_uint16; +#else +typedef int yytype_uint16; +#endif + +#ifndef YYPTRDIFF_T +# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ +# define YYPTRDIFF_T __PTRDIFF_TYPE__ +# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ +# elif defined PTRDIFF_MAX +# ifndef ptrdiff_t +# include /* INFRINGES ON USER NAME SPACE */ +# endif +# define YYPTRDIFF_T ptrdiff_t +# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX +# else +# define YYPTRDIFF_T long +# define YYPTRDIFF_MAXIMUM LONG_MAX +# endif +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned +# endif +#endif + +#define YYSIZE_MAXIMUM \ + YY_CAST(YYPTRDIFF_T, (YYPTRDIFF_MAXIMUM < YY_CAST(YYSIZE_T, -1) ? YYPTRDIFF_MAXIMUM \ + : YY_CAST(YYSIZE_T, -1))) + +#define YYSIZEOF(X) YY_CAST(YYPTRDIFF_T, sizeof(X)) + +/* Stored state numbers (used for stacks). */ +typedef yytype_int16 yy_state_t; + +/* State numbers in computations. */ +typedef int yy_state_fast_t; + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_PURE __attribute__((__pure__)) +# else +# define YY_ATTRIBUTE_PURE +# endif +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_UNUSED __attribute__((__unused__)) +# else +# define YY_ATTRIBUTE_UNUSED +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if !defined lint || defined __GNUC__ +# define YY_USE(E) ((void)(E)) +#else +# define YY_USE(E) /* empty */ +#endif + +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +#if defined __GNUC__ && !defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wuninitialized\"") +# else +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# endif +# define YY_IGNORE_MAYBE_UNINITIALIZED_END _Pragma("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + +#if defined __cplusplus && defined __GNUC__ && !defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END _Pragma("GCC diagnostic pop") +#endif +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END +#endif + +#define YY_ASSERT(E) ((void)(0 && (E))) + +#if !defined yyoverflow + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if !defined _ALLOCA_H && !defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ +/* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC +/* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) \ + do \ + { /* empty */ \ + ; \ + } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM +/* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && !defined EXIT_SUCCESS && \ + !((defined YYMALLOC || defined malloc) && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if !defined malloc && !defined EXIT_SUCCESS +void *malloc(YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if !defined free && !defined EXIT_SUCCESS +void free(void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* !defined yyoverflow */ + +#if (!defined yyoverflow && \ + (!defined __cplusplus || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL && \ + defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yy_state_t yyss_alloc; + YYSTYPE yyvs_alloc; + YYLTYPE yyls_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (YYSIZEOF(union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (YYSIZEOF(yy_state_t) + YYSIZEOF(YYSTYPE) + YYSIZEOF(YYLTYPE)) + \ + 2 * YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYPTRDIFF_T yynewbytes; \ + YYCOPY(&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * YYSIZEOF(*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / YYSIZEOF(*yyptr); \ + } while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy(Dst, Src, YY_CAST(YYSIZE_T, (Count)) * sizeof(*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYPTRDIFF_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 167 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 3566 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 185 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 96 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 329 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 453 + +/* YYMAXUTOK -- Last valid token kind. */ +#define YYMAXUTOK 439 + +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ +#define YYTRANSLATE(YYX) \ + (0 <= (YYX) && (YYX) <= YYMAXUTOK ? YY_CAST(yysymbol_kind_t, yytranslate[YYX]) \ + : YYSYMBOL_YYUNDEF) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex. */ +static const yytype_uint8 yytranslate[] = { + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, + 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, + 182, 183, 184}; + +#if YYDEBUG +/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_int16 yyrline[] = { + 0, 259, 259, 260, 263, 270, 273, 278, 283, 288, 293, 302, 308, 311, 314, 317, + 320, 323, 329, 336, 342, 345, 353, 356, 362, 365, 371, 375, 382, 390, 393, 396, + 402, 405, 408, 411, 418, 419, 420, 421, 429, 430, 433, 436, 443, 444, 447, 453, + 454, 458, 465, 466, 469, 472, 475, 481, 482, 485, 491, 492, 499, 500, 507, 508, + 515, 516, 522, 523, 529, 530, 536, 537, 543, 544, 550, 551, 552, 553, 557, 558, + 559, 563, 567, 571, 575, 582, 585, 591, 598, 605, 608, 611, 615, 619, 623, 627, + 631, 638, 645, 648, 655, 668, 691, 701, 704, 710, 714, 718, 722, 729, 736, 739, + 743, 747, 752, 759, 763, 767, 771, 776, 783, 787, 793, 796, 799, 809, 813, 820, + 826, 832, 836, 840, 843, 846, 850, 858, 863, 867, 870, 873, 876, 879, 883, 891, + 894, 898, 901, 904, 907, 910, 913, 917, 924, 931, 934, 937, 943, 950, 953, 959, + 962, 965, 968, 974, 977, 984, 989, 996, 1001, 1012, 1015, 1018, 1021, 1024, 1027, 1031, + 1035, 1039, 1043, 1047, 1051, 1055, 1059, 1063, 1067, 1071, 1075, 1079, 1083, 1087, 1091, 1095, + 1099, 1103, 1107, 1111, 1118, 1121, 1124, 1127, 1130, 1133, 1136, 1144, 1152, 1162, 1165, 1168, + 1171, 1174, 1177, 1180, 1188, 1196, 1206, 1209, 1212, 1215, 1218, 1221, 1224, 1232, 1240, 1250, + 1253, 1256, 1259, 1267, 1275, 1282, 1292, 1299, 1306, 1309, 1312, 1315, 1318, 1321, 1324, 1327, + 1330, 1333, 1336, 1339, 1342, 1350, 1358, 1366, 1374, 1382, 1390, 1400, 1410, 1420, 1423, 1430, + 1437, 1444, 1447, 1455, 1455, 1458, 1458, 1464, 1467, 1473, 1476, 1483, 1487, 1493, 1496, 1502, + 1506, 1510, 1511, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1527, 1531, 1531, 1531, 1538, 1539, + 1543, 1543, 1544, 1544, 1549, 1553, 1560, 1564, 1571, 1572, 1576, 1582, 1586, 1595, 1595, 1602, + 1605, 1611, 1615, 1621, 1621, 1626, 1626, 1630, 1630, 1638, 1641, 1647, 1650, 1656, 1660, 1667, + 1670, 1673, 1676, 1679, 1687, 1693, 1699, 1702, 1708, 1708}; +#endif + +/** Accessing symbol of state STATE. */ +#define YY_ACCESSING_SYMBOL(State) YY_CAST(yysymbol_kind_t, yystos[State]) + +#if YYDEBUG || 0 +/* The user-facing name of the symbol whose (internal) number is + YYSYMBOL. No bounds checking. */ +static const char *yysymbol_name(yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; + +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = {"\"end of file\"", + "error", + "\"invalid token\"", + "INVARIANT", + "PRECISE", + "HIGH_PRECISION", + "MEDIUM_PRECISION", + "LOW_PRECISION", + "PRECISION", + "ATTRIBUTE", + "CONST_QUAL", + "BOOL_TYPE", + "FLOAT_TYPE", + "INT_TYPE", + "UINT_TYPE", + "BREAK", + "CONTINUE", + "DO", + "ELSE", + "FOR", + "IF", + "DISCARD", + "RETURN", + "SWITCH", + "CASE", + "DEFAULT", + "BVEC2", + "BVEC3", + "BVEC4", + "IVEC2", + "IVEC3", + "IVEC4", + "VEC2", + "VEC3", + "VEC4", + "UVEC2", + "UVEC3", + "UVEC4", + "MATRIX2", + "MATRIX3", + "MATRIX4", + "IN_QUAL", + "OUT_QUAL", + "INOUT_QUAL", + "UNIFORM", + "BUFFER", + "VARYING", + "MATRIX2x3", + "MATRIX3x2", + "MATRIX2x4", + "MATRIX4x2", + "MATRIX3x4", + "MATRIX4x3", + "SAMPLE", + "CENTROID", + "FLAT", + "SMOOTH", + "NOPERSPECTIVE", + "PATCH", + "READONLY", + "WRITEONLY", + "COHERENT", + "RESTRICT", + "VOLATILE", + "SHARED", + "STRUCT", + "VOID_TYPE", + "WHILE", + "SAMPLER2D", + "SAMPLERCUBE", + "SAMPLER_EXTERNAL_OES", + "SAMPLER2DRECT", + "SAMPLER2DARRAY", + "ISAMPLER2D", + "ISAMPLER3D", + "ISAMPLERCUBE", + "ISAMPLER2DARRAY", + "USAMPLER2D", + "USAMPLER3D", + "USAMPLERCUBE", + "USAMPLER2DARRAY", + "SAMPLER2DMS", + "ISAMPLER2DMS", + "USAMPLER2DMS", + "SAMPLER2DMSARRAY", + "ISAMPLER2DMSARRAY", + "USAMPLER2DMSARRAY", + "SAMPLER3D", + "SAMPLER3DRECT", + "SAMPLER2DSHADOW", + "SAMPLERCUBESHADOW", + "SAMPLER2DARRAYSHADOW", + "SAMPLERVIDEOWEBGL", + "SAMPLERCUBEARRAYOES", + "SAMPLERCUBEARRAYSHADOWOES", + "ISAMPLERCUBEARRAYOES", + "USAMPLERCUBEARRAYOES", + "SAMPLERCUBEARRAYEXT", + "SAMPLERCUBEARRAYSHADOWEXT", + "ISAMPLERCUBEARRAYEXT", + "USAMPLERCUBEARRAYEXT", + "SAMPLERBUFFER", + "ISAMPLERBUFFER", + "USAMPLERBUFFER", + "SAMPLEREXTERNAL2DY2YEXT", + "IMAGE2D", + "IIMAGE2D", + "UIMAGE2D", + "IMAGE3D", + "IIMAGE3D", + "UIMAGE3D", + "IMAGE2DARRAY", + "IIMAGE2DARRAY", + "UIMAGE2DARRAY", + "IMAGECUBE", + "IIMAGECUBE", + "UIMAGECUBE", + "IMAGECUBEARRAYOES", + "IIMAGECUBEARRAYOES", + "UIMAGECUBEARRAYOES", + "IMAGECUBEARRAYEXT", + "IIMAGECUBEARRAYEXT", + "UIMAGECUBEARRAYEXT", + "IMAGEBUFFER", + "IIMAGEBUFFER", + "UIMAGEBUFFER", + "ATOMICUINT", + "PIXELLOCALANGLE", + "IPIXELLOCALANGLE", + "UPIXELLOCALANGLE", + "LAYOUT", + "YUVCSCSTANDARDEXT", + "YUVCSCSTANDARDEXTCONSTANT", + "IDENTIFIER", + "TYPE_NAME", + "FLOATCONSTANT", + "INTCONSTANT", + "UINTCONSTANT", + "BOOLCONSTANT", + "FIELD_SELECTION", + "LEFT_OP", + "RIGHT_OP", + "INC_OP", + "DEC_OP", + "LE_OP", + "GE_OP", + "EQ_OP", + "NE_OP", + "AND_OP", + "OR_OP", + "XOR_OP", + "MUL_ASSIGN", + "DIV_ASSIGN", + "ADD_ASSIGN", + "MOD_ASSIGN", + "LEFT_ASSIGN", + "RIGHT_ASSIGN", + "AND_ASSIGN", + "XOR_ASSIGN", + "OR_ASSIGN", + "SUB_ASSIGN", + "LEFT_PAREN", + "RIGHT_PAREN", + "LEFT_BRACKET", + "RIGHT_BRACKET", + "LEFT_BRACE", + "RIGHT_BRACE", + "DOT", + "COMMA", + "COLON", + "EQUAL", + "SEMICOLON", + "BANG", + "DASH", + "TILDE", + "PLUS", + "STAR", + "SLASH", + "PERCENT", + "LEFT_ANGLE", + "RIGHT_ANGLE", + "VERTICAL_BAR", + "CARET", + "AMPERSAND", + "QUESTION", + "$accept", + "identifier", + "variable_identifier", + "primary_expression", + "postfix_expression", + "integer_expression", + "function_call", + "function_call_or_method", + "function_call_generic", + "function_call_header_no_parameters", + "function_call_header_with_parameters", + "function_call_header", + "function_identifier", + "unary_expression", + "unary_operator", + "multiplicative_expression", + "additive_expression", + "shift_expression", + "relational_expression", + "equality_expression", + "and_expression", + "exclusive_or_expression", + "inclusive_or_expression", + "logical_and_expression", + "logical_xor_expression", + "logical_or_expression", + "conditional_expression", + "assignment_expression", + "assignment_operator", + "expression", + "constant_expression", + "enter_struct", + "declaration", + "function_prototype", + "function_declarator", + "function_header_with_parameters", + "function_header", + "parameter_declarator", + "parameter_declaration", + "parameter_type_specifier", + "init_declarator_list", + "single_declaration", + "fully_specified_type", + "interpolation_qualifier", + "type_qualifier", + "invariant_qualifier", + "precise_qualifier", + "single_type_qualifier", + "storage_qualifier", + "type_specifier", + "precision_qualifier", + "layout_qualifier", + "layout_qualifier_id_list", + "layout_qualifier_id", + "type_specifier_no_prec", + "array_specifier", + "type_specifier_nonarray", + "struct_specifier", + "$@1", + "$@2", + "struct_declaration_list", + "struct_declaration", + "struct_declarator_list", + "struct_declarator", + "initializer", + "declaration_statement", + "statement", + "simple_statement", + "compound_statement_with_scope", + "$@3", + "$@4", + "statement_no_new_scope", + "statement_with_scope", + "$@5", + "$@6", + "compound_statement_no_new_scope", + "statement_list", + "expression_statement", + "selection_statement", + "selection_rest_statement", + "switch_statement", + "$@7", + "case_label", + "condition", + "iteration_statement", + "$@8", + "$@9", + "$@10", + "for_init_statement", + "conditionopt", + "for_rest_statement", + "jump_statement", + "translation_unit", + "external_declaration", + "function_definition", + "$@11", + YY_NULLPTR}; + +static const char *yysymbol_name(yysymbol_kind_t yysymbol) +{ + return yytname[yysymbol]; +} +#endif + +#define YYPACT_NINF (-397) + +#define yypact_value_is_default(Yyn) ((Yyn) == YYPACT_NINF) + +#define YYTABLE_NINF (-289) + +#define yytable_value_is_error(Yyn) 0 + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int16 yypact[] = { + 3052, -397, -397, -397, -397, -397, 105, -397, -397, -397, -397, -397, -397, -397, -397, -397, + -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, + -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, + -397, -397, -397, -397, -94, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, + -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, + -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, + -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, + -397, -397, -397, -132, -397, -397, -397, -81, -41, -49, 3184, -90, -397, -86, -397, 1609, + -397, -397, -397, -397, -397, -397, -397, -397, -39, -397, 2920, -397, -397, 3432, -397, -397, + -397, -31, -47, -397, -26, -397, 3184, -397, -397, -397, 3184, 3, 3, -397, -35, -135, + -114, -397, 3184, -397, -397, 1734, -10, -397, -397, -6, 3184, -397, -397, -9, -93, -397, + 438, -397, -397, -397, -397, -39, -97, -397, 2193, -87, -397, -397, 3184, 3, 2497, -397, + -397, 7, -397, -397, -397, -397, -397, 2193, 2193, 2193, -397, -397, -397, -397, -397, -397, + -397, -78, -397, -397, -397, 12, -69, 2344, 8, -397, 2193, -33, -96, -116, -124, 5, + -12, -7, -4, 31, 30, -123, -397, 17, -397, 1888, -397, 2638, 3184, 19, -397, -47, + 13, 14, -397, 22, 25, 16, 2042, 28, 2193, 32, 44, 37, -397, -397, 40, -397, + -397, -80, -397, -81, 45, -397, -397, -397, -397, 611, -397, -397, -397, -397, -397, -397, + -10, 2193, -83, -397, -397, 2193, 3, -39, -76, -397, -111, -397, -397, -397, -62, -397, + -397, 2193, 3308, -397, -397, 2193, 46, -397, -397, -397, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, -397, -397, + 47, -397, 2779, -397, -397, -397, -397, -397, 48, -397, 2193, -397, -397, -48, 2193, 43, + -397, -397, -397, 784, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, -397, 2193, + 2193, -397, -397, -397, -397, 2193, -397, -43, -10, 3, -397, -122, -397, -397, 51, 41, + -397, 55, -397, -397, -397, -397, -397, -33, -33, -96, -96, -116, -116, -116, -116, -124, + -124, 5, -12, -7, -4, 31, 30, -11, -397, -397, 150, -26, 1130, 1303, -60, -397, + -59, -397, 1456, 784, -397, -397, -397, -397, -397, -397, -109, -397, 2193, 57, -397, -397, + -397, -397, 1456, 48, -397, 41, 3, 3184, 58, 56, -397, -397, 2193, -397, 50, 61, + 206, -397, 60, 59, 957, -397, -55, 2193, 957, 48, -397, 2193, -397, -397, -397, 63, + 41, -397, -397, -397, -397}; + +/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_int16 yydefact[] = { + 0, 127, 128, 153, 154, 155, 0, 135, 137, 173, 170, 171, 172, 177, 178, 179, 180, 181, 182, + 174, 175, 176, 183, 184, 185, 186, 187, 188, 138, 139, 140, 143, 144, 136, 189, 190, 191, 192, + 193, 194, 151, 141, 123, 122, 124, 142, 145, 146, 147, 148, 149, 150, 0, 169, 196, 198, 229, + 231, 199, 205, 206, 207, 208, 214, 215, 216, 217, 200, 209, 218, 201, 210, 219, 197, 223, 224, + 225, 228, 202, 226, 211, 220, 203, 227, 212, 221, 204, 213, 222, 230, 232, 233, 234, 235, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 246, 248, 245, 247, 249, 250, 251, 252, 253, 254, 255, + 256, 0, 195, 258, 327, 328, 0, 99, 98, 0, 110, 115, 132, 0, 133, 134, 125, 129, 120, + 131, 130, 152, 163, 257, 0, 324, 326, 0, 2, 3, 261, 0, 0, 89, 0, 97, 0, 106, + 100, 108, 0, 109, 0, 90, 2, 116, 0, 95, 0, 126, 121, 0, 164, 1, 325, 0, 0, + 259, 162, 159, 0, 157, 0, 329, 101, 105, 107, 103, 111, 102, 0, 117, 88, 96, 0, 0, + 0, 263, 10, 4, 8, 6, 7, 9, 31, 0, 0, 0, 165, 38, 37, 39, 36, 5, 12, + 32, 14, 19, 20, 0, 0, 25, 0, 40, 0, 44, 47, 50, 55, 58, 60, 62, 64, 66, + 68, 70, 87, 0, 29, 0, 91, 0, 0, 0, 156, 0, 0, 0, 309, 0, 0, 0, 0, + 0, 0, 0, 0, 283, 292, 296, 40, 72, 85, 0, 272, 0, 152, 275, 294, 274, 273, 0, + 276, 277, 278, 279, 280, 281, 104, 0, 112, 271, 119, 0, 0, 269, 0, 267, 0, 264, 33, + 34, 0, 16, 17, 0, 0, 23, 22, 0, 169, 26, 28, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 167, 0, 262, 0, + 160, 161, 158, 320, 319, 290, 311, 0, 323, 321, 0, 0, 0, 304, 307, 282, 0, 75, 76, + 78, 77, 80, 81, 82, 83, 84, 79, 74, 0, 0, 297, 293, 295, 114, 0, 118, 0, 270, + 0, 265, 0, 92, 11, 0, 18, 30, 15, 21, 27, 41, 42, 43, 46, 45, 48, 49, 53, + 54, 51, 52, 56, 57, 59, 61, 63, 65, 67, 69, 0, 168, 260, 0, 0, 0, 0, 0, + 322, 0, 303, 0, 284, 73, 86, 113, 266, 268, 93, 0, 13, 0, 0, 289, 291, 314, 313, + 316, 290, 301, 305, 0, 0, 0, 0, 94, 71, 0, 315, 0, 0, 300, 298, 0, 0, 0, + 285, 0, 317, 0, 290, 302, 0, 287, 308, 286, 0, 318, 312, 299, 306, 310}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = { + -397, -51, -397, -397, -397, -397, -397, -397, -64, -397, -397, -397, -397, 42, -397, -142, + -140, -175, -143, -84, -75, -85, -82, -77, -73, -397, -151, -179, -397, -188, -202, -397, + 9, 10, -397, -397, -397, 77, 89, 90, -397, -397, -375, -397, -118, -397, -397, -121, + -397, -120, 239, -397, -397, 15, 0, -144, -397, -397, -397, -397, -152, -182, -32, -113, + -261, -150, -254, -377, -185, -397, -397, -187, -396, -397, -397, -145, -72, -141, -397, -397, + -397, -397, -397, -166, -397, -397, -397, -397, -397, -397, -397, -397, -397, 117, -397, -397}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = { + 0, 279, 207, 208, 209, 366, 210, 211, 212, 213, 214, 215, 216, 254, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 255, 256, 351, 257, 231, 162, + 258, 259, 120, 121, 122, 151, 152, 153, 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 174, 175, 232, 166, 136, 137, 236, 170, 190, 191, 280, 281, + 276, 261, 262, 263, 264, 339, 425, 445, 394, 395, 396, 446, 265, 266, 267, 433, + 268, 434, 269, 424, 270, 402, 328, 397, 418, 430, 431, 271, 138, 139, 140, 148}; + +/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int16 yytable[] = { + 135, 145, 155, 177, 154, 275, 163, 164, 283, 118, 119, 355, 356, 286, 230, 185, 358, 172, 235, + 415, 305, 306, 363, 432, 303, 304, 316, 422, 165, 146, 155, 320, 154, 163, 155, 184, 295, 272, + 274, 142, 143, 165, 189, 422, 188, 450, 335, 158, 143, 409, 189, 186, 188, 283, 233, 307, 308, + 187, 333, 444, 364, 317, 426, 444, 287, 288, 165, 163, 278, 238, 189, 144, 188, 273, 159, 239, + 233, 301, 156, 302, 233, 157, 230, 277, 322, 289, 173, 357, 352, 290, 147, 353, 361, 292, 275, + 362, 406, 230, 275, 293, 365, 367, 419, 420, 181, 182, 352, 447, 352, 352, 3, 4, 5, 352, + 371, 189, 189, 188, 188, 150, 352, 149, 135, 399, 165, 361, 183, 135, 407, 391, 379, 380, 381, + 382, 171, 360, 142, 143, 135, 176, 283, 169, 398, 298, 299, 300, 400, 118, 119, 355, 135, 309, + 310, 233, 135, 323, 324, 352, 412, 375, 376, 237, 135, 377, 378, 234, 383, 384, -30, 296, 135, + 311, 404, 405, 291, 312, 260, 313, 275, 314, 315, 318, 451, 329, 326, 327, 330, 331, 135, 334, + 135, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 336, 189, 338, 188, 337, -29, 217, -24, + 352, 350, 392, 401, -288, 421, 411, -31, 413, 428, 410, 436, 439, 437, 440, 441, 251, 370, 385, + 387, 443, 421, 179, 388, 427, 452, 135, 135, 386, 389, 178, 438, 284, 285, 390, 180, 141, 359, + 416, 408, 442, 414, 448, 429, 449, 325, 168, 417, 0, 0, 0, 297, 0, 0, 0, 275, 260, + 0, 403, 0, 0, 0, 0, 0, 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, 423, + 0, 0, 0, 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, 423, 0, 163, 164, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 260, 372, 373, + 374, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 435, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 260, 260, 0, + 0, 0, 0, 260, 260, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 260, 0, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 260, + 0, 0, 0, 260, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 240, 241, 242, + 0, 243, 244, 245, 246, 247, 248, 249, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 250, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, 0, 251, 252, 0, 0, 0, + 0, 253, 203, 204, 205, 206, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 240, + 241, 242, 0, 243, 244, 245, 246, 247, 248, 249, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 250, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, 0, 251, 354, 0, + 0, 0, 0, 253, 203, 204, 205, 206, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 240, 241, 242, 0, 243, 244, 245, 246, 247, 248, 249, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 250, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, 0, 251, + 0, 0, 0, 0, 0, 253, 203, 204, 205, 206, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 240, 241, 242, 0, 243, 244, 245, 246, 247, 248, 249, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 250, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, + 0, 176, 0, 0, 0, 0, 0, 253, 203, 204, 205, 206, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 240, 241, 242, 0, 243, 244, 245, 246, 247, 248, 249, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 250, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, + 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 203, 204, 205, 206, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, + 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, + 5, 201, 7, 8, 9, 10, 11, 12, 0, 0, 0, 253, 203, 204, 205, 206, 0, 0, 0, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 192, 193, 117, 194, 195, 196, 197, 198, + 0, 0, 199, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, + 4, 5, 201, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, 203, 204, 205, 206, 0, 0, + 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 0, 160, 117, 0, 9, 10, 11, + 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, 0, 161, 34, 35, 36, 37, 38, + 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 0, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 0, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, 202, 9, + 10, 11, 12, 0, 0, 0, 203, 204, 205, 206, 0, 0, 0, 0, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, 0, 0, 34, 35, 36, + 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 0, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 0, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, + 319, 9, 10, 11, 12, 0, 0, 0, 203, 204, 205, 206, 0, 0, 0, 0, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, 0, 0, 34, + 35, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, + 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 0, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, + 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, + 9, 10, 11, 12, 0, 0, 0, 0, 0, 332, 203, 204, 205, 206, 0, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, 0, 0, 34, 35, + 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 0, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 0, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 9, + 10, 11, 12, 0, 0, 0, 0, 0, 0, 203, 204, 205, 206, 0, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, 0, 0, 34, 35, 36, + 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 294, 0, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 0, 116, 192, 193, 117, 194, 195, 196, 197, 198, 0, 0, 199, 200, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 201, 7, 8, + 9, 10, 11, 12, 0, 0, 0, 0, 203, 204, 205, 206, 0, 0, 0, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 0, 0, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 0, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 282, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 0, 0, 117, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 0, 7, 8, 9, 10, 11, + 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 321, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 0, 0, 117, 0, 0, 0, 0, 0, 0, 167, 0, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 393, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 0, 0, 117, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 0, 0, 117, 1, 2, 3, 4, 5, + 0, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 0, 0, 117, 9, 10, 11, 12, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 0, 0, 0, 0, 0, 0, 34, 35, 36, 37, 38, 39, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 0, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 0, + 116, 0, 368, 117, 9, 10, 11, 12, 369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, + 0, 0, 34, 35, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 52, 53, 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 0, 116, 0, 0, 117}; + +static const yytype_int16 yycheck[] = { + 0, 52, 122, 148, 122, 184, 127, 127, 190, 0, 0, 265, 273, 201, 165, 159, 277, 64, 170, + 396, 144, 145, 133, 419, 140, 141, 149, 402, 163, 161, 150, 233, 150, 154, 154, 170, 215, 181, + 182, 133, 134, 163, 162, 418, 162, 441, 248, 133, 134, 171, 170, 165, 170, 235, 163, 179, 180, + 171, 246, 436, 171, 184, 171, 440, 142, 143, 163, 188, 188, 162, 190, 165, 190, 170, 125, 168, + 163, 173, 168, 175, 163, 171, 233, 170, 236, 163, 133, 170, 168, 167, 171, 171, 168, 162, 273, + 171, 357, 248, 277, 168, 162, 289, 162, 162, 155, 156, 168, 162, 168, 168, 5, 6, 7, 168, + 293, 235, 236, 235, 236, 168, 168, 162, 122, 171, 163, 168, 161, 127, 171, 317, 305, 306, 307, + 308, 165, 279, 133, 134, 138, 165, 322, 141, 330, 176, 177, 178, 334, 138, 138, 403, 150, 146, + 147, 163, 154, 136, 137, 168, 169, 301, 302, 170, 162, 303, 304, 171, 309, 310, 161, 161, 170, + 183, 351, 352, 162, 182, 176, 181, 357, 148, 150, 164, 443, 161, 171, 171, 161, 171, 188, 161, + 190, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 169, 322, 166, 322, 161, 161, 165, 162, + 168, 170, 164, 169, 165, 402, 164, 161, 67, 161, 363, 162, 171, 166, 162, 18, 165, 290, 311, + 313, 170, 418, 154, 314, 412, 171, 235, 236, 312, 315, 150, 428, 199, 200, 316, 154, 6, 278, + 397, 361, 434, 395, 439, 418, 440, 239, 138, 397, -1, -1, -1, 218, -1, -1, -1, 443, 265, + -1, 339, -1, -1, -1, -1, -1, -1, -1, 233, -1, -1, -1, -1, -1, -1, -1, -1, 402, + -1, -1, -1, -1, -1, 248, -1, -1, -1, -1, -1, -1, -1, -1, -1, 418, -1, 423, 423, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 322, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 339, 298, 299, + 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 422, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 396, 397, -1, + -1, -1, -1, 402, 403, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 418, -1, -1, -1, -1, 423, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 436, + -1, -1, -1, 440, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, -1, 165, 166, -1, -1, -1, + -1, 171, 172, 173, 174, 175, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, -1, 165, 166, -1, + -1, -1, -1, 171, 172, 173, 174, 175, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, -1, 165, + -1, -1, -1, -1, -1, 171, 172, 173, 174, 175, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, + -1, 165, -1, -1, -1, -1, -1, 171, 172, 173, 174, 175, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, + 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, + 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 171, 172, 173, 174, 175, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, + -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, + 7, 161, 9, 10, 11, 12, 13, 14, -1, -1, -1, 171, 172, 173, 174, 175, -1, -1, -1, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + -1, -1, 142, 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, + 6, 7, 161, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, 172, 173, 174, 175, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, -1, 133, 134, -1, 11, 12, 13, + 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, 171, 47, 48, 49, 50, 51, + 52, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, -1, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, 164, 11, + 12, 13, 14, -1, -1, -1, 172, 173, 174, 175, -1, -1, -1, -1, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, 47, 48, 49, + 50, 51, 52, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, -1, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, + 164, 11, 12, 13, 14, -1, -1, -1, 172, 173, 174, 175, -1, -1, -1, -1, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, 47, + 48, 49, 50, 51, 52, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, + -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, + 124, 125, 126, 127, 128, 129, -1, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, + 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, + 11, 12, 13, 14, -1, -1, -1, -1, -1, 171, 172, 173, 174, 175, -1, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, 47, 48, + 49, 50, 51, 52, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, -1, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, 11, + 12, 13, 14, -1, -1, -1, -1, -1, -1, 172, 173, 174, 175, -1, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, 47, 48, 49, + 50, 51, 52, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, -1, 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, 161, 9, 10, + 11, 12, 13, 14, -1, -1, -1, -1, 172, 173, 174, 175, -1, -1, -1, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, -1, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, -1, -1, 134, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 3, 4, 5, 6, 7, -1, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 166, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, -1, -1, 134, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, -1, 9, 10, 11, 12, 13, + 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 166, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, -1, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, -1, -1, 134, -1, -1, -1, -1, -1, -1, 0, -1, -1, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 166, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, -1, -1, 134, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, -1, -1, 134, 3, 4, 5, 6, 7, + -1, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, -1, -1, 134, 11, 12, 13, 14, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, 47, 48, 49, 50, 51, 52, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, -1, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, -1, + 131, -1, 133, 134, 11, 12, 13, 14, 139, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, + -1, -1, 47, 48, 49, 50, 51, 52, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, -1, 131, -1, -1, 134}; + +/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of + state STATE-NUM. */ +static const yytype_int16 yystos[] = { + 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 130, 131, 134, 217, 218, 219, 220, 221, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 235, 236, 239, 241, 242, 277, 278, 279, 235, 133, 134, 165, 186, 161, 171, 280, 162, 168, 222, + 223, 224, 229, 234, 168, 171, 133, 186, 133, 171, 216, 232, 234, 163, 240, 0, 278, 239, 244, + 165, 64, 133, 237, 238, 165, 260, 223, 222, 224, 186, 186, 161, 170, 240, 165, 171, 229, 234, + 245, 246, 132, 133, 135, 136, 137, 138, 139, 142, 143, 161, 164, 172, 173, 174, 175, 187, 188, + 189, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, + 209, 210, 211, 215, 239, 163, 171, 245, 243, 170, 162, 168, 15, 16, 17, 19, 20, 21, 22, + 23, 24, 25, 67, 165, 166, 171, 198, 211, 212, 214, 217, 218, 239, 250, 251, 252, 253, 261, + 262, 263, 265, 267, 269, 276, 240, 170, 240, 212, 249, 170, 234, 186, 247, 248, 166, 246, 198, + 198, 214, 142, 143, 163, 167, 162, 162, 168, 66, 212, 161, 198, 176, 177, 178, 173, 175, 140, + 141, 144, 145, 179, 180, 146, 147, 183, 182, 181, 148, 150, 149, 184, 164, 164, 215, 166, 245, + 136, 137, 238, 171, 171, 271, 161, 161, 171, 171, 214, 161, 215, 169, 161, 166, 254, 151, 152, + 153, 154, 155, 156, 157, 158, 159, 160, 170, 213, 168, 171, 166, 251, 249, 170, 249, 247, 240, + 168, 171, 133, 171, 162, 190, 214, 133, 139, 193, 212, 198, 198, 198, 200, 200, 201, 201, 202, + 202, 202, 202, 203, 203, 204, 205, 206, 207, 208, 209, 214, 164, 166, 257, 258, 259, 272, 214, + 171, 214, 169, 270, 261, 212, 212, 249, 171, 248, 171, 240, 164, 169, 67, 260, 252, 250, 262, + 273, 162, 162, 214, 227, 229, 268, 255, 171, 212, 161, 268, 274, 275, 257, 264, 266, 186, 162, + 166, 214, 171, 162, 18, 253, 170, 252, 256, 260, 162, 214, 256, 257, 249, 171}; + +/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ +static const yytype_int16 yyr1[] = { + 0, 185, 186, 186, 187, 188, 188, 188, 188, 188, 188, 188, 189, 189, 189, 189, 189, 189, 190, + 191, 192, 192, 193, 193, 194, 194, 195, 195, 196, 197, 197, 197, 198, 198, 198, 198, 199, 199, + 199, 199, 200, 200, 200, 200, 201, 201, 201, 202, 202, 202, 203, 203, 203, 203, 203, 204, 204, + 204, 205, 205, 206, 206, 207, 207, 208, 208, 209, 209, 210, 210, 211, 211, 212, 212, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 213, 213, 214, 214, 215, 216, 217, 217, 217, 217, 217, 217, + 217, 217, 218, 219, 219, 220, 220, 221, 222, 222, 223, 223, 223, 223, 224, 225, 225, 225, 225, + 225, 226, 226, 226, 226, 226, 227, 227, 228, 228, 228, 229, 229, 230, 231, 232, 232, 232, 232, + 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, + 234, 235, 235, 235, 236, 237, 237, 238, 238, 238, 238, 239, 239, 240, 240, 240, 240, 241, 241, + 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, + 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, + 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, + 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, + 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 243, 242, 244, 242, 245, 245, 246, + 246, 247, 247, 248, 248, 249, 250, 251, 251, 252, 252, 252, 252, 252, 252, 252, 253, 254, 255, + 253, 256, 256, 258, 257, 259, 257, 260, 260, 261, 261, 262, 262, 263, 264, 264, 266, 265, 267, + 267, 268, 268, 270, 269, 271, 269, 272, 269, 273, 273, 274, 274, 275, 275, 276, 276, 276, 276, + 276, 277, 277, 278, 278, 280, 279}; + +/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ +static const yytype_int8 yyr2[] = { + 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 4, 1, 3, 2, 2, 1, 1, 1, 3, 2, 2, 2, 1, 2, 3, 2, 1, + 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 3, 3, 3, 1, 3, 3, 1, 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, 1, 3, + 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 5, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 2, + 2, 4, 5, 6, 7, 2, 3, 2, 1, 1, 2, 3, 3, 2, 3, 2, 1, 2, 1, 1, 1, 3, 4, 6, 5, 1, 2, 3, 5, 4, + 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 4, 1, 3, 1, 3, 3, 1, 1, 2, 2, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 6, 0, 5, 1, 2, 3, 4, 1, 3, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 5, 1, 1, 0, 2, 0, 2, 2, 3, 1, 2, 1, 2, 5, 3, + 1, 0, 6, 3, 2, 1, 4, 0, 6, 0, 8, 0, 7, 1, 1, 1, 0, 2, 3, 2, 2, 2, 3, 2, 1, 2, 1, 1, 0, 3}; + +enum +{ + YYENOMEM = -2 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab +#define YYNOMEM goto yyexhaustedlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK(yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror(&yylloc, context, scanner, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) + +/* Backward compatibility with an undocumented macro. + Use YYerror or YYUNDEF. */ +#define YYERRCODE YYUNDEF + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) \ + { \ + (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC(Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = YYRHSLOC(Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = YYRHSLOC(Rhs, 0).last_column; \ + } \ + while (0) +#endif + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ + do \ + { \ + if (yydebug) \ + YYFPRINTF Args; \ + } while (0) + +/* YYLOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +# ifndef YYLOCATION_PRINT + +# if defined YY_LOCATION_PRINT + +/* Temporary convenience wrapper in case some people defined the + undocumented and private YY_LOCATION_PRINT macros. */ +# define YYLOCATION_PRINT(File, Loc) YY_LOCATION_PRINT(File, *(Loc)) + +# elif defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL + +/* Print *YYLOCP on YYO. Private, do not rely on its existence. */ + +YY_ATTRIBUTE_UNUSED +static int yy_location_print_(FILE *yyo, YYLTYPE const *const yylocp) +{ + int res = 0; + int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; + if (0 <= yylocp->first_line) + { + res += YYFPRINTF(yyo, "%d", yylocp->first_line); + if (0 <= yylocp->first_column) + res += YYFPRINTF(yyo, ".%d", yylocp->first_column); + } + if (0 <= yylocp->last_line) + { + if (yylocp->first_line < yylocp->last_line) + { + res += YYFPRINTF(yyo, "-%d", yylocp->last_line); + if (0 <= end_col) + res += YYFPRINTF(yyo, ".%d", end_col); + } + else if (0 <= end_col && yylocp->first_column < end_col) + res += YYFPRINTF(yyo, "-%d", end_col); + } + return res; +} + +# define YYLOCATION_PRINT yy_location_print_ + +/* Temporary convenience wrapper in case some people defined the + undocumented and private YY_LOCATION_PRINT macros. */ +# define YY_LOCATION_PRINT(File, Loc) YYLOCATION_PRINT(File, &(Loc)) + +# else + +# define YYLOCATION_PRINT(File, Loc) ((void)0) +/* Temporary convenience wrapper in case some people defined the + undocumented and private YY_LOCATION_PRINT macros. */ +# define YY_LOCATION_PRINT YYLOCATION_PRINT + +# endif +# endif /* !defined YYLOCATION_PRINT */ + +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ + do \ + { \ + if (yydebug) \ + { \ + YYFPRINTF(stderr, "%s ", Title); \ + yy_symbol_print(stderr, Kind, Value, Location, context, scanner); \ + YYFPRINTF(stderr, "\n"); \ + } \ + } while (0) + +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ + +static void yy_symbol_value_print(FILE *yyo, + yysymbol_kind_t yykind, + YYSTYPE const *const yyvaluep, + YYLTYPE const *const yylocationp, + TParseContext *context, + void *scanner) +{ + FILE *yyoutput = yyo; + YY_USE(yyoutput); + YY_USE(yylocationp); + YY_USE(context); + YY_USE(scanner); + if (!yyvaluep) + return; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YY_USE(yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ + +static void yy_symbol_print(FILE *yyo, + yysymbol_kind_t yykind, + YYSTYPE const *const yyvaluep, + YYLTYPE const *const yylocationp, + TParseContext *context, + void *scanner) +{ + YYFPRINTF(yyo, "%s %s (", yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name(yykind)); + + YYLOCATION_PRINT(yyo, yylocationp); + YYFPRINTF(yyo, ": "); + yy_symbol_value_print(yyo, yykind, yyvaluep, yylocationp, context, scanner); + YYFPRINTF(yyo, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void yy_stack_print(yy_state_t *yybottom, yy_state_t *yytop) +{ + YYFPRINTF(stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF(stderr, " %d", yybot); + } + YYFPRINTF(stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ + do \ + { \ + if (yydebug) \ + yy_stack_print((Bottom), (Top)); \ + } while (0) + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void yy_reduce_print(yy_state_t *yyssp, + YYSTYPE *yyvsp, + YYLTYPE *yylsp, + int yyrule, + TParseContext *context, + void *scanner) +{ + int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF(stderr, "Reducing stack by rule %d (line %d):\n", yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF(stderr, " $%d = ", yyi + 1); + yy_symbol_print(stderr, YY_ACCESSING_SYMBOL(+yyssp[yyi + 1 - yynrhs]), + &yyvsp[(yyi + 1) - (yynrhs)], &(yylsp[(yyi + 1) - (yynrhs)]), context, + scanner); + YYFPRINTF(stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ + do \ + { \ + if (yydebug) \ + yy_reduce_print(yyssp, yyvsp, yylsp, Rule, context, scanner); \ + } while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) ((void)0) +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void yydestruct(const char *yymsg, + yysymbol_kind_t yykind, + YYSTYPE *yyvaluep, + YYLTYPE *yylocationp, + TParseContext *context, + void *scanner) +{ + YY_USE(yyvaluep); + YY_USE(yylocationp); + YY_USE(context); + YY_USE(scanner); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT(yymsg, yykind, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YY_USE(yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + +/*----------. +| yyparse. | +`----------*/ + +int yyparse(TParseContext *context, void *scanner) +{ + /* Lookahead token kind. */ + int yychar; + + /* The semantic value of the lookahead symbol. */ + /* Default value used for initialization, for pacifying older GCCs + or non-GCC compilers. */ + YY_INITIAL_VALUE(static YYSTYPE yyval_default;) + YYSTYPE yylval YY_INITIAL_VALUE(= yyval_default); + + /* Location data for the lookahead symbol. */ + static YYLTYPE yyloc_default +#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL + = {1, 1, 1, 1} +#endif + ; + YYLTYPE yylloc = yyloc_default; + + /* Number of syntax errors so far. */ + int yynerrs = 0; + + yy_state_fast_t yystate = 0; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus = 0; + + /* Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* Their size. */ + YYPTRDIFF_T yystacksize = YYINITDEPTH; + + /* The state stack: array, bottom, top. */ + yy_state_t yyssa[YYINITDEPTH]; + yy_state_t *yyss = yyssa; + yy_state_t *yyssp = yyss; + + /* The semantic value stack: array, bottom, top. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp = yyvs; + + /* The location stack: array, bottom, top. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp = yyls; + + int yyn; + /* The return value of yyparse. */ + int yyresult; + /* Lookahead symbol kind. */ + yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + YYLTYPE yyloc; + + /* The locations where the error started and ended. */ + YYLTYPE yyerror_range[3]; + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF((stderr, "Starting parse\n")); + + yychar = YYEMPTY; /* Cause a token to be read. */ + + yylsp[0] = yylloc; + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- push a new state, which is found in yystate. | +`------------------------------------------------------------*/ +yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + +/*--------------------------------------------------------------------. +| yysetstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + YYDPRINTF((stderr, "Entering state %d\n", yystate)); + YY_ASSERT(0 <= yystate && yystate < YYNSTATES); + YY_IGNORE_USELESS_CAST_BEGIN + *yyssp = YY_CAST(yy_state_t, yystate); + YY_IGNORE_USELESS_CAST_END + YY_STACK_PRINT(yyss, yyssp); + + if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + YYNOMEM; +#else + { + /* Get the current used size of the three stacks, in elements. */ + YYPTRDIFF_T yysize = yyssp - yyss + 1; + +# if defined yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + yy_state_t *yyss1 = yyss; + YYSTYPE *yyvs1 = yyvs; + YYLTYPE *yyls1 = yyls; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow(YY_("memory exhausted"), &yyss1, yysize * YYSIZEOF(*yyssp), &yyvs1, + yysize * YYSIZEOF(*yyvsp), &yyls1, yysize * YYSIZEOF(*yylsp), &yystacksize); + yyss = yyss1; + yyvs = yyvs1; + yyls = yyls1; + } +# else /* defined YYSTACK_RELOCATE */ + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + YYNOMEM; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yy_state_t *yyss1 = yyss; + union yyalloc *yyptr = YY_CAST( + union yyalloc *, YYSTACK_ALLOC(YY_CAST(YYSIZE_T, YYSTACK_BYTES(yystacksize)))); + if (!yyptr) + YYNOMEM; + YYSTACK_RELOCATE(yyss_alloc, yyss); + YYSTACK_RELOCATE(yyvs_alloc, yyvs); + YYSTACK_RELOCATE(yyls_alloc, yyls); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE(yyss1); + } +# endif + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + yylsp = yyls + yysize - 1; + + YY_IGNORE_USELESS_CAST_BEGIN + YYDPRINTF((stderr, "Stack size increased to %ld\n", YY_CAST(long, yystacksize))); + YY_IGNORE_USELESS_CAST_END + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default(yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ + if (yychar == YYEMPTY) + { + YYDPRINTF((stderr, "Reading a token\n")); + yychar = yylex(&yylval, &yylloc, scanner); + } + + if (yychar <= YYEOF) + { + yychar = YYEOF; + yytoken = YYSYMBOL_YYEOF; + YYDPRINTF((stderr, "Now at end of input.\n")); + } + else if (yychar == YYerror) + { + /* The scanner already issued an error message, process directly + to error recovery. But do not keep the error token as + lookahead, it is too special and may lead us to an endless + loop in error recovery. */ + yychar = YYUNDEF; + yytoken = YYSYMBOL_YYerror; + yyerror_range[1] = yylloc; + goto yyerrlab1; + } + else + { + yytoken = YYTRANSLATE(yychar); + YY_SYMBOL_PRINT("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error(yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT("Shifting", yytoken, &yylval, &yylloc); + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + *++yylsp = yylloc; + + /* Discard the shifted token. */ + yychar = YYEMPTY; + goto yynewstate; + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + +/*-----------------------------. +| yyreduce -- do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1 - yylen]; + + /* Default location. */ + YYLLOC_DEFAULT(yyloc, (yylsp - yylen), yylen); + yyerror_range[1] = yyloc; + YY_REDUCE_PRINT(yyn); + switch (yyn) + { + case 4: /* variable_identifier: IDENTIFIER */ + { + // The symbol table search was done in the lexical phase + (yyval.interm.intermTypedNode) = context->parseVariableIdentifier( + (yylsp[0]), ImmutableString((yyvsp[0].lex).string), (yyvsp[0].lex).symbol); + } + break; + + case 5: /* primary_expression: variable_identifier */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 6: /* primary_expression: INTCONSTANT */ + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray->setIConst((yyvsp[0].lex).i); + (yyval.interm.intermTypedNode) = context->addScalarLiteral(unionArray, (yylsp[0])); + } + break; + + case 7: /* primary_expression: UINTCONSTANT */ + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray->setUConst((yyvsp[0].lex).u); + (yyval.interm.intermTypedNode) = context->addScalarLiteral(unionArray, (yylsp[0])); + } + break; + + case 8: /* primary_expression: FLOATCONSTANT */ + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray->setFConst((yyvsp[0].lex).f); + (yyval.interm.intermTypedNode) = context->addScalarLiteral(unionArray, (yylsp[0])); + } + break; + + case 9: /* primary_expression: BOOLCONSTANT */ + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray->setBConst((yyvsp[0].lex).b); + (yyval.interm.intermTypedNode) = context->addScalarLiteral(unionArray, (yylsp[0])); + } + break; + + case 10: /* primary_expression: YUVCSCSTANDARDEXTCONSTANT */ + { + if (!context->checkCanUseExtension((yylsp[0]), TExtension::EXT_YUV_target)) + { + context->error((yylsp[0]), "unsupported value", + ImmutableString((yyvsp[0].lex).string)); + } + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray->setYuvCscStandardEXTConst( + getYuvCscStandardEXT(ImmutableString((yyvsp[0].lex).string))); + (yyval.interm.intermTypedNode) = context->addScalarLiteral(unionArray, (yylsp[0])); + } + break; + + case 11: /* primary_expression: LEFT_PAREN expression RIGHT_PAREN */ + { + (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode); + } + break; + + case 12: /* postfix_expression: primary_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 13: /* postfix_expression: postfix_expression LEFT_BRACKET integer_expression + RIGHT_BRACKET */ + { + (yyval.interm.intermTypedNode) = + context->addIndexExpression((yyvsp[-3].interm.intermTypedNode), (yylsp[-2]), + (yyvsp[-1].interm.intermTypedNode)); + } + break; + + case 14: /* postfix_expression: function_call */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 15: /* postfix_expression: postfix_expression DOT FIELD_SELECTION */ + { + (yyval.interm.intermTypedNode) = context->addFieldSelectionExpression( + (yyvsp[-2].interm.intermTypedNode), (yylsp[-1]), + ImmutableString((yyvsp[0].lex).string), (yylsp[0])); + } + break; + + case 16: /* postfix_expression: postfix_expression INC_OP */ + { + (yyval.interm.intermTypedNode) = context->addUnaryMathLValue( + EOpPostIncrement, (yyvsp[-1].interm.intermTypedNode), (yylsp[0])); + } + break; + + case 17: /* postfix_expression: postfix_expression DEC_OP */ + { + (yyval.interm.intermTypedNode) = context->addUnaryMathLValue( + EOpPostDecrement, (yyvsp[-1].interm.intermTypedNode), (yylsp[0])); + } + break; + + case 18: /* integer_expression: expression */ + { + context->checkIsScalarInteger((yyvsp[0].interm.intermTypedNode), "[]"); + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 19: /* function_call: function_call_or_method */ + { + (yyval.interm.intermTypedNode) = + context->addFunctionCallOrMethod((yyvsp[0].interm.functionLookup), (yylsp[0])); + } + break; + + case 20: /* function_call_or_method: function_call_generic */ + { + (yyval.interm.functionLookup) = (yyvsp[0].interm.functionLookup); + } + break; + + case 21: /* function_call_or_method: postfix_expression DOT function_call_generic */ + { + ES3_OR_NEWER("", (yylsp[0]), "methods"); + (yyval.interm.functionLookup) = (yyvsp[0].interm.functionLookup); + (yyval.interm.functionLookup)->setThisNode((yyvsp[-2].interm.intermTypedNode)); + } + break; + + case 22: /* function_call_generic: function_call_header_with_parameters RIGHT_PAREN */ + { + (yyval.interm.functionLookup) = (yyvsp[-1].interm.functionLookup); + } + break; + + case 23: /* function_call_generic: function_call_header_no_parameters RIGHT_PAREN */ + { + (yyval.interm.functionLookup) = (yyvsp[-1].interm.functionLookup); + } + break; + + case 24: /* function_call_header_no_parameters: function_call_header VOID_TYPE */ + { + (yyval.interm.functionLookup) = (yyvsp[-1].interm.functionLookup); + } + break; + + case 25: /* function_call_header_no_parameters: function_call_header */ + { + (yyval.interm.functionLookup) = (yyvsp[0].interm.functionLookup); + } + break; + + case 26: /* function_call_header_with_parameters: function_call_header assignment_expression + */ + { + (yyval.interm.functionLookup) = (yyvsp[-1].interm.functionLookup); + (yyval.interm.functionLookup)->addArgument((yyvsp[0].interm.intermTypedNode)); + } + break; + + case 27: /* function_call_header_with_parameters: function_call_header_with_parameters COMMA + assignment_expression */ + { + (yyval.interm.functionLookup) = (yyvsp[-2].interm.functionLookup); + (yyval.interm.functionLookup)->addArgument((yyvsp[0].interm.intermTypedNode)); + } + break; + + case 28: /* function_call_header: function_identifier LEFT_PAREN */ + { + (yyval.interm.functionLookup) = (yyvsp[-1].interm.functionLookup); + } + break; + + case 29: /* function_identifier: type_specifier_no_prec */ + { + (yyval.interm.functionLookup) = context->addConstructorFunc((yyvsp[0].interm.type)); + } + break; + + case 30: /* function_identifier: IDENTIFIER */ + { + (yyval.interm.functionLookup) = context->addNonConstructorFunc( + ImmutableString((yyvsp[0].lex).string), (yyvsp[0].lex).symbol); + } + break; + + case 31: /* function_identifier: FIELD_SELECTION */ + { + (yyval.interm.functionLookup) = context->addNonConstructorFunc( + ImmutableString((yyvsp[0].lex).string), (yyvsp[0].lex).symbol); + } + break; + + case 32: /* unary_expression: postfix_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 33: /* unary_expression: INC_OP unary_expression */ + { + (yyval.interm.intermTypedNode) = context->addUnaryMathLValue( + EOpPreIncrement, (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 34: /* unary_expression: DEC_OP unary_expression */ + { + (yyval.interm.intermTypedNode) = context->addUnaryMathLValue( + EOpPreDecrement, (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 35: /* unary_expression: unary_operator unary_expression */ + { + (yyval.interm.intermTypedNode) = context->addUnaryMath( + (yyvsp[-1].interm.op), (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 36: /* unary_operator: PLUS */ + { + (yyval.interm.op) = EOpPositive; + } + break; + + case 37: /* unary_operator: DASH */ + { + (yyval.interm.op) = EOpNegative; + } + break; + + case 38: /* unary_operator: BANG */ + { + (yyval.interm.op) = EOpLogicalNot; + } + break; + + case 39: /* unary_operator: TILDE */ + { + ES3_OR_NEWER("~", (yyloc), "bit-wise operator"); + (yyval.interm.op) = EOpBitwiseNot; + } + break; + + case 40: /* multiplicative_expression: unary_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 41: /* multiplicative_expression: multiplicative_expression STAR unary_expression */ + { + (yyval.interm.intermTypedNode) = + context->addBinaryMath(EOpMul, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 42: /* multiplicative_expression: multiplicative_expression SLASH unary_expression */ + { + (yyval.interm.intermTypedNode) = + context->addBinaryMath(EOpDiv, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 43: /* multiplicative_expression: multiplicative_expression PERCENT unary_expression */ + { + ES3_OR_NEWER("%", (yylsp[-1]), "integer modulus operator"); + (yyval.interm.intermTypedNode) = + context->addBinaryMath(EOpIMod, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 44: /* additive_expression: multiplicative_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 45: /* additive_expression: additive_expression PLUS multiplicative_expression */ + { + (yyval.interm.intermTypedNode) = + context->addBinaryMath(EOpAdd, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 46: /* additive_expression: additive_expression DASH multiplicative_expression */ + { + (yyval.interm.intermTypedNode) = + context->addBinaryMath(EOpSub, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 47: /* shift_expression: additive_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 48: /* shift_expression: shift_expression LEFT_OP additive_expression */ + { + ES3_OR_NEWER("<<", (yylsp[-1]), "bit-wise operator"); + (yyval.interm.intermTypedNode) = + context->addBinaryMath(EOpBitShiftLeft, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 49: /* shift_expression: shift_expression RIGHT_OP additive_expression */ + { + ES3_OR_NEWER(">>", (yylsp[-1]), "bit-wise operator"); + (yyval.interm.intermTypedNode) = + context->addBinaryMath(EOpBitShiftRight, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 50: /* relational_expression: shift_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 51: /* relational_expression: relational_expression LEFT_ANGLE shift_expression */ + { + (yyval.interm.intermTypedNode) = + context->addBinaryMathBooleanResult(EOpLessThan, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 52: /* relational_expression: relational_expression RIGHT_ANGLE shift_expression */ + { + (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult( + EOpGreaterThan, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 53: /* relational_expression: relational_expression LE_OP shift_expression */ + { + (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult( + EOpLessThanEqual, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 54: /* relational_expression: relational_expression GE_OP shift_expression */ + { + (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult( + EOpGreaterThanEqual, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 55: /* equality_expression: relational_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 56: /* equality_expression: equality_expression EQ_OP relational_expression */ + { + (yyval.interm.intermTypedNode) = + context->addBinaryMathBooleanResult(EOpEqual, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 57: /* equality_expression: equality_expression NE_OP relational_expression */ + { + (yyval.interm.intermTypedNode) = + context->addBinaryMathBooleanResult(EOpNotEqual, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 58: /* and_expression: equality_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 59: /* and_expression: and_expression AMPERSAND equality_expression */ + { + ES3_OR_NEWER("&", (yylsp[-1]), "bit-wise operator"); + (yyval.interm.intermTypedNode) = + context->addBinaryMath(EOpBitwiseAnd, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 60: /* exclusive_or_expression: and_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 61: /* exclusive_or_expression: exclusive_or_expression CARET and_expression */ + { + ES3_OR_NEWER("^", (yylsp[-1]), "bit-wise operator"); + (yyval.interm.intermTypedNode) = + context->addBinaryMath(EOpBitwiseXor, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 62: /* inclusive_or_expression: exclusive_or_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 63: /* inclusive_or_expression: inclusive_or_expression VERTICAL_BAR + exclusive_or_expression */ + { + ES3_OR_NEWER("|", (yylsp[-1]), "bit-wise operator"); + (yyval.interm.intermTypedNode) = + context->addBinaryMath(EOpBitwiseOr, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 64: /* logical_and_expression: inclusive_or_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 65: /* logical_and_expression: logical_and_expression AND_OP inclusive_or_expression */ + { + (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult( + EOpLogicalAnd, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 66: /* logical_xor_expression: logical_and_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 67: /* logical_xor_expression: logical_xor_expression XOR_OP logical_and_expression */ + { + (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult( + EOpLogicalXor, (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 68: /* logical_or_expression: logical_xor_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 69: /* logical_or_expression: logical_or_expression OR_OP logical_xor_expression */ + { + (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult( + EOpLogicalOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), + (yylsp[-1])); + } + break; + + case 70: /* conditional_expression: logical_or_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 71: /* conditional_expression: logical_or_expression QUESTION expression COLON + assignment_expression */ + { + (yyval.interm.intermTypedNode) = context->addTernarySelection( + (yyvsp[-4].interm.intermTypedNode), (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-3])); + } + break; + + case 72: /* assignment_expression: conditional_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 73: /* assignment_expression: unary_expression assignment_operator + assignment_expression */ + { + (yyval.interm.intermTypedNode) = + context->addAssign((yyvsp[-1].interm.op), (yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 74: /* assignment_operator: EQUAL */ + { + (yyval.interm.op) = EOpAssign; + } + break; + + case 75: /* assignment_operator: MUL_ASSIGN */ + { + (yyval.interm.op) = EOpMulAssign; + } + break; + + case 76: /* assignment_operator: DIV_ASSIGN */ + { + (yyval.interm.op) = EOpDivAssign; + } + break; + + case 77: /* assignment_operator: MOD_ASSIGN */ + { + ES3_OR_NEWER("%=", (yyloc), "integer modulus operator"); + (yyval.interm.op) = EOpIModAssign; + } + break; + + case 78: /* assignment_operator: ADD_ASSIGN */ + { + (yyval.interm.op) = EOpAddAssign; + } + break; + + case 79: /* assignment_operator: SUB_ASSIGN */ + { + (yyval.interm.op) = EOpSubAssign; + } + break; + + case 80: /* assignment_operator: LEFT_ASSIGN */ + { + ES3_OR_NEWER("<<=", (yyloc), "bit-wise operator"); + (yyval.interm.op) = EOpBitShiftLeftAssign; + } + break; + + case 81: /* assignment_operator: RIGHT_ASSIGN */ + { + ES3_OR_NEWER(">>=", (yyloc), "bit-wise operator"); + (yyval.interm.op) = EOpBitShiftRightAssign; + } + break; + + case 82: /* assignment_operator: AND_ASSIGN */ + { + ES3_OR_NEWER("&=", (yyloc), "bit-wise operator"); + (yyval.interm.op) = EOpBitwiseAndAssign; + } + break; + + case 83: /* assignment_operator: XOR_ASSIGN */ + { + ES3_OR_NEWER("^=", (yyloc), "bit-wise operator"); + (yyval.interm.op) = EOpBitwiseXorAssign; + } + break; + + case 84: /* assignment_operator: OR_ASSIGN */ + { + ES3_OR_NEWER("|=", (yyloc), "bit-wise operator"); + (yyval.interm.op) = EOpBitwiseOrAssign; + } + break; + + case 85: /* expression: assignment_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 86: /* expression: expression COMMA assignment_expression */ + { + (yyval.interm.intermTypedNode) = context->addComma( + (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); + } + break; + + case 87: /* constant_expression: conditional_expression */ + { + context->checkIsConst((yyvsp[0].interm.intermTypedNode)); + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 88: /* enter_struct: IDENTIFIER LEFT_BRACE */ + { + context->enterStructDeclaration((yylsp[-1]), ImmutableString((yyvsp[-1].lex).string)); + (yyval.lex) = (yyvsp[-1].lex); + } + break; + + case 89: /* declaration: function_prototype SEMICOLON */ + { + (yyval.interm.intermNode) = context->addFunctionPrototypeDeclaration( + *((yyvsp[-1].interm).function), (yylsp[-1])); + } + break; + + case 90: /* declaration: init_declarator_list SEMICOLON */ + { + (yyval.interm.intermNode) = (yyvsp[-1].interm).intermDeclaration; + } + break; + + case 91: /* declaration: PRECISION precision_qualifier type_specifier_no_prec SEMICOLON */ + { + context->parseDefaultPrecisionQualifier((yyvsp[-2].interm.precision), + (yyvsp[-1].interm.type), (yylsp[-3])); + (yyval.interm.intermNode) = nullptr; + } + break; + + case 92: /* declaration: type_qualifier enter_struct struct_declaration_list RIGHT_BRACE + SEMICOLON */ + { + ES3_OR_NEWER(ImmutableString((yyvsp[-3].lex).string), (yylsp[-4]), "interface blocks"); + (yyval.interm.intermNode) = context->addInterfaceBlock( + *(yyvsp[-4].interm.typeQualifierBuilder), (yylsp[-3]), + ImmutableString((yyvsp[-3].lex).string), (yyvsp[-2].interm.fieldList), + kEmptyImmutableString, (yyloc), NULL, (yyloc)); + } + break; + + case 93: /* declaration: type_qualifier enter_struct struct_declaration_list RIGHT_BRACE + IDENTIFIER SEMICOLON */ + { + ES3_OR_NEWER(ImmutableString((yyvsp[-4].lex).string), (yylsp[-5]), "interface blocks"); + (yyval.interm.intermNode) = context->addInterfaceBlock( + *(yyvsp[-5].interm.typeQualifierBuilder), (yylsp[-4]), + ImmutableString((yyvsp[-4].lex).string), (yyvsp[-3].interm.fieldList), + ImmutableString((yyvsp[-1].lex).string), (yylsp[-1]), NULL, (yyloc)); + } + break; + + case 94: /* declaration: type_qualifier enter_struct struct_declaration_list RIGHT_BRACE + IDENTIFIER array_specifier SEMICOLON */ + { + ES3_OR_NEWER(ImmutableString((yyvsp[-5].lex).string), (yylsp[-6]), "interface blocks"); + (yyval.interm.intermNode) = context->addInterfaceBlock( + *(yyvsp[-6].interm.typeQualifierBuilder), (yylsp[-5]), + ImmutableString((yyvsp[-5].lex).string), (yyvsp[-4].interm.fieldList), + ImmutableString((yyvsp[-2].lex).string), (yylsp[-2]), (yyvsp[-1].interm.arraySizes), + (yylsp[-1])); + } + break; + + case 95: /* declaration: type_qualifier SEMICOLON */ + { + context->parseGlobalLayoutQualifier(*(yyvsp[-1].interm.typeQualifierBuilder)); + (yyval.interm.intermNode) = nullptr; + } + break; + + case 96: /* declaration: type_qualifier IDENTIFIER SEMICOLON */ + { + (yyval.interm.intermNode) = context->parseGlobalQualifierDeclaration( + *(yyvsp[-2].interm.typeQualifierBuilder), (yylsp[-1]), + ImmutableString((yyvsp[-1].lex).string), (yyvsp[-1].lex).symbol); + } + break; + + case 97: /* function_prototype: function_declarator RIGHT_PAREN */ + { + (yyval.interm).function = + context->parseFunctionDeclarator((yylsp[0]), (yyvsp[-1].interm.function)); + context->exitFunctionDeclaration(); + } + break; + + case 98: /* function_declarator: function_header */ + { + (yyval.interm.function) = (yyvsp[0].interm.function); + } + break; + + case 99: /* function_declarator: function_header_with_parameters */ + { + (yyval.interm.function) = (yyvsp[0].interm.function); + } + break; + + case 100: /* function_header_with_parameters: function_header parameter_declaration */ + { + // Add the parameter + (yyval.interm.function) = (yyvsp[-1].interm.function); + if ((yyvsp[0].interm.param).type->getBasicType() != EbtVoid) + { + (yyvsp[-1].interm.function) + ->addParameter((yyvsp[0].interm.param).createVariable(&context->symbolTable)); + } + else + { + // Remember that void was seen, so error can be generated if another parameter is + // seen. + (yyvsp[-1].interm.function)->setHasVoidParameter(); + } + } + break; + + case 101: /* function_header_with_parameters: function_header_with_parameters COMMA + parameter_declaration */ + { + (yyval.interm.function) = (yyvsp[-2].interm.function); + // Only first parameter of one-parameter functions can be void + // The check for named parameters not being void is done in parameter_declarator + if ((yyvsp[0].interm.param).type->getBasicType() == EbtVoid) + { + // This parameter > first is void + context->error((yylsp[-1]), "cannot be a parameter type except for '(void)'", + "void"); + } + else + { + if ((yyvsp[-2].interm.function)->hasVoidParameter()) + { + // Only first parameter of one-parameter functions can be void. This check + // prevents (void, non_void) parameters. + context->error((yylsp[-1]), "cannot be a parameter type except for '(void)'", + "void"); + } + (yyvsp[-2].interm.function) + ->addParameter((yyvsp[0].interm.param).createVariable(&context->symbolTable)); + } + } + break; + + case 102: /* function_header: fully_specified_type IDENTIFIER LEFT_PAREN */ + { + (yyval.interm.function) = context->parseFunctionHeader( + (yyvsp[-2].interm.type), ImmutableString((yyvsp[-1].lex).string), (yylsp[-1])); + + context->symbolTable.push(); + context->enterFunctionDeclaration(); + } + break; + + case 103: /* parameter_declarator: type_specifier identifier */ + { + (yyval.interm.param) = context->parseParameterDeclarator( + (yyvsp[-1].interm.type), ImmutableString((yyvsp[0].lex).string), (yylsp[0])); + } + break; + + case 104: /* parameter_declarator: type_specifier identifier array_specifier */ + { + (yyval.interm.param) = context->parseParameterArrayDeclarator( + ImmutableString((yyvsp[-1].lex).string), (yylsp[-1]), + *((yyvsp[0].interm.arraySizes)), (yylsp[0]), &(yyvsp[-2].interm.type)); + } + break; + + case 105: /* parameter_declaration: type_qualifier parameter_declarator */ + { + (yyval.interm.param) = (yyvsp[0].interm.param); + context->checkIsParameterQualifierValid( + (yylsp[0]), *(yyvsp[-1].interm.typeQualifierBuilder), (yyvsp[0].interm.param).type); + } + break; + + case 106: /* parameter_declaration: parameter_declarator */ + { + (yyval.interm.param) = (yyvsp[0].interm.param); + (yyval.interm.param).type->setQualifier(EvqParamIn); + } + break; + + case 107: /* parameter_declaration: type_qualifier parameter_type_specifier */ + { + (yyval.interm.param) = (yyvsp[0].interm.param); + context->checkIsParameterQualifierValid( + (yylsp[0]), *(yyvsp[-1].interm.typeQualifierBuilder), (yyvsp[0].interm.param).type); + } + break; + + case 108: /* parameter_declaration: parameter_type_specifier */ + { + (yyval.interm.param) = (yyvsp[0].interm.param); + (yyval.interm.param).type->setQualifier(EvqParamIn); + } + break; + + case 109: /* parameter_type_specifier: type_specifier */ + { + TParameter param = {0, new TType((yyvsp[0].interm.type))}; + (yyval.interm.param) = param; + } + break; + + case 110: /* init_declarator_list: single_declaration */ + { + (yyval.interm) = (yyvsp[0].interm); + } + break; + + case 111: /* init_declarator_list: init_declarator_list COMMA identifier */ + { + (yyval.interm) = (yyvsp[-2].interm); + context->parseDeclarator((yyval.interm).type, (yylsp[0]), + ImmutableString((yyvsp[0].lex).string), + (yyval.interm).intermDeclaration); + } + break; + + case 112: /* init_declarator_list: init_declarator_list COMMA identifier array_specifier */ + { + (yyval.interm) = (yyvsp[-3].interm); + context->parseArrayDeclarator( + (yyval.interm).type, (yylsp[-1]), ImmutableString((yyvsp[-1].lex).string), + (yylsp[0]), *((yyvsp[0].interm.arraySizes)), (yyval.interm).intermDeclaration); + } + break; + + case 113: /* init_declarator_list: init_declarator_list COMMA identifier array_specifier + EQUAL initializer */ + { + ES3_OR_NEWER("=", (yylsp[-1]), "first-class arrays (array initializer)"); + (yyval.interm) = (yyvsp[-5].interm); + context->parseArrayInitDeclarator( + (yyval.interm).type, (yylsp[-3]), ImmutableString((yyvsp[-3].lex).string), + (yylsp[-2]), *((yyvsp[-2].interm.arraySizes)), (yylsp[-1]), + (yyvsp[0].interm.intermTypedNode), (yyval.interm).intermDeclaration); + } + break; + + case 114: /* init_declarator_list: init_declarator_list COMMA identifier EQUAL initializer + */ + { + (yyval.interm) = (yyvsp[-4].interm); + context->parseInitDeclarator( + (yyval.interm).type, (yylsp[-2]), ImmutableString((yyvsp[-2].lex).string), + (yylsp[-1]), (yyvsp[0].interm.intermTypedNode), (yyval.interm).intermDeclaration); + } + break; + + case 115: /* single_declaration: fully_specified_type */ + { + (yyval.interm).type = (yyvsp[0].interm.type); + (yyval.interm).intermDeclaration = context->parseSingleDeclaration( + (yyval.interm).type, (yylsp[0]), kEmptyImmutableString); + } + break; + + case 116: /* single_declaration: fully_specified_type identifier */ + { + (yyval.interm).type = (yyvsp[-1].interm.type); + (yyval.interm).intermDeclaration = context->parseSingleDeclaration( + (yyval.interm).type, (yylsp[0]), ImmutableString((yyvsp[0].lex).string)); + } + break; + + case 117: /* single_declaration: fully_specified_type identifier array_specifier */ + { + (yyval.interm).type = (yyvsp[-2].interm.type); + (yyval.interm).intermDeclaration = context->parseSingleArrayDeclaration( + (yyval.interm).type, (yylsp[-1]), ImmutableString((yyvsp[-1].lex).string), + (yylsp[0]), *((yyvsp[0].interm.arraySizes))); + } + break; + + case 118: /* single_declaration: fully_specified_type identifier array_specifier EQUAL + initializer */ + { + ES3_OR_NEWER("[]", (yylsp[-2]), "first-class arrays (array initializer)"); + (yyval.interm).type = (yyvsp[-4].interm.type); + (yyval.interm).intermDeclaration = context->parseSingleArrayInitDeclaration( + (yyval.interm).type, (yylsp[-3]), ImmutableString((yyvsp[-3].lex).string), + (yylsp[-2]), *((yyvsp[-2].interm.arraySizes)), (yylsp[-1]), + (yyvsp[0].interm.intermTypedNode)); + } + break; + + case 119: /* single_declaration: fully_specified_type identifier EQUAL initializer */ + { + (yyval.interm).type = (yyvsp[-3].interm.type); + (yyval.interm).intermDeclaration = context->parseSingleInitDeclaration( + (yyval.interm).type, (yylsp[-2]), ImmutableString((yyvsp[-2].lex).string), + (yylsp[-1]), (yyvsp[0].interm.intermTypedNode)); + } + break; + + case 120: /* fully_specified_type: type_specifier */ + { + context->addFullySpecifiedType(&(yyvsp[0].interm.type)); + (yyval.interm.type) = (yyvsp[0].interm.type); + } + break; + + case 121: /* fully_specified_type: type_qualifier type_specifier */ + { + (yyval.interm.type) = context->addFullySpecifiedType( + *(yyvsp[-1].interm.typeQualifierBuilder), (yyvsp[0].interm.type)); + } + break; + + case 122: /* interpolation_qualifier: SMOOTH */ + { + (yyval.interm.qualifier) = EvqSmooth; + } + break; + + case 123: /* interpolation_qualifier: FLAT */ + { + (yyval.interm.qualifier) = EvqFlat; + } + break; + + case 124: /* interpolation_qualifier: NOPERSPECTIVE */ + { + if (!context->checkCanUseExtension((yylsp[0]), + TExtension::NV_shader_noperspective_interpolation)) + { + context->error((yylsp[0]), "unsupported interpolation qualifier", "noperspective"); + } + (yyval.interm.qualifier) = EvqNoPerspective; + } + break; + + case 125: /* type_qualifier: single_type_qualifier */ + { + (yyval.interm.typeQualifierBuilder) = context->createTypeQualifierBuilder((yylsp[0])); + (yyval.interm.typeQualifierBuilder) + ->appendQualifier((yyvsp[0].interm.qualifierWrapper)); + } + break; + + case 126: /* type_qualifier: type_qualifier single_type_qualifier */ + { + (yyval.interm.typeQualifierBuilder) = (yyvsp[-1].interm.typeQualifierBuilder); + (yyval.interm.typeQualifierBuilder) + ->appendQualifier((yyvsp[0].interm.qualifierWrapper)); + } + break; + + case 127: /* invariant_qualifier: INVARIANT */ + { + // empty + } + break; + + case 128: /* precise_qualifier: PRECISE */ + { + context->markShaderHasPrecise(); + } + break; + + case 129: /* single_type_qualifier: storage_qualifier */ + { + context->checkLocalVariableConstStorageQualifier(*(yyvsp[0].interm.qualifierWrapper)); + (yyval.interm.qualifierWrapper) = (yyvsp[0].interm.qualifierWrapper); + } + break; + + case 130: /* single_type_qualifier: layout_qualifier */ + { + context->checkIsAtGlobalLevel((yylsp[0]), "layout"); + (yyval.interm.qualifierWrapper) = + new TLayoutQualifierWrapper((yyvsp[0].interm.layoutQualifier), (yylsp[0])); + } + break; + + case 131: /* single_type_qualifier: precision_qualifier */ + { + (yyval.interm.qualifierWrapper) = + new TPrecisionQualifierWrapper((yyvsp[0].interm.precision), (yylsp[0])); + } + break; + + case 132: /* single_type_qualifier: interpolation_qualifier */ + { + (yyval.interm.qualifierWrapper) = + new TInterpolationQualifierWrapper((yyvsp[0].interm.qualifier), (yylsp[0])); + } + break; + + case 133: /* single_type_qualifier: invariant_qualifier */ + { + context->checkIsAtGlobalLevel((yylsp[0]), "invariant"); + (yyval.interm.qualifierWrapper) = new TInvariantQualifierWrapper((yylsp[0])); + } + break; + + case 134: /* single_type_qualifier: precise_qualifier */ + { + (yyval.interm.qualifierWrapper) = new TPreciseQualifierWrapper((yylsp[0])); + } + break; + + case 135: /* storage_qualifier: ATTRIBUTE */ + { + VERTEX_ONLY("attribute", (yylsp[0])); + ES2_ONLY("attribute", (yylsp[0])); + (yyval.interm.qualifierWrapper) = + context->parseGlobalStorageQualifier(EvqAttribute, (yylsp[0])); + } + break; + + case 136: /* storage_qualifier: VARYING */ + { + ES2_ONLY("varying", (yylsp[0])); + (yyval.interm.qualifierWrapper) = context->parseVaryingQualifier((yylsp[0])); + } + break; + + case 137: /* storage_qualifier: CONST_QUAL */ + { + (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqConst, (yylsp[0])); + } + break; + + case 138: /* storage_qualifier: IN_QUAL */ + { + (yyval.interm.qualifierWrapper) = context->parseInQualifier((yylsp[0])); + } + break; + + case 139: /* storage_qualifier: OUT_QUAL */ + { + (yyval.interm.qualifierWrapper) = context->parseOutQualifier((yylsp[0])); + } + break; + + case 140: /* storage_qualifier: INOUT_QUAL */ + { + (yyval.interm.qualifierWrapper) = context->parseInOutQualifier((yylsp[0])); + } + break; + + case 141: /* storage_qualifier: CENTROID */ + { + ES3_OR_NEWER("centroid", (yylsp[0]), "storage qualifier"); + (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqCentroid, (yylsp[0])); + } + break; + + case 142: /* storage_qualifier: PATCH */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_tessellation_shader)) + { + context->error((yylsp[0]), "unsupported storage qualifier", "patch"); + } + (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqPatch, (yylsp[0])); + } + break; + + case 143: /* storage_qualifier: UNIFORM */ + { + (yyval.interm.qualifierWrapper) = + context->parseGlobalStorageQualifier(EvqUniform, (yylsp[0])); + } + break; + + case 144: /* storage_qualifier: BUFFER */ + { + ES3_1_OR_NEWER("buffer", (yylsp[0]), "storage qualifier"); + (yyval.interm.qualifierWrapper) = + context->parseGlobalStorageQualifier(EvqBuffer, (yylsp[0])); + } + break; + + case 145: /* storage_qualifier: READONLY */ + { + (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqReadOnly, (yylsp[0])); + } + break; + + case 146: /* storage_qualifier: WRITEONLY */ + { + (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqWriteOnly, (yylsp[0])); + } + break; + + case 147: /* storage_qualifier: COHERENT */ + { + (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqCoherent, (yylsp[0])); + } + break; + + case 148: /* storage_qualifier: RESTRICT */ + { + (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqRestrict, (yylsp[0])); + } + break; + + case 149: /* storage_qualifier: VOLATILE */ + { + (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqVolatile, (yylsp[0])); + } + break; + + case 150: /* storage_qualifier: SHARED */ + { + COMPUTE_ONLY("shared", (yylsp[0])); + (yyval.interm.qualifierWrapper) = + context->parseGlobalStorageQualifier(EvqShared, (yylsp[0])); + } + break; + + case 151: /* storage_qualifier: SAMPLE */ + { + ES3_OR_NEWER("sample", (yylsp[0]), "storage qualifier"); + (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqSample, (yylsp[0])); + } + break; + + case 152: /* type_specifier: type_specifier_no_prec */ + { + (yyval.interm.type) = (yyvsp[0].interm.type); + (yyval.interm.type).precision = + context->symbolTable.getDefaultPrecision((yyvsp[0].interm.type).getBasicType()); + } + break; + + case 153: /* precision_qualifier: HIGH_PRECISION */ + { + (yyval.interm.precision) = EbpHigh; + } + break; + + case 154: /* precision_qualifier: MEDIUM_PRECISION */ + { + (yyval.interm.precision) = EbpMedium; + } + break; + + case 155: /* precision_qualifier: LOW_PRECISION */ + { + (yyval.interm.precision) = EbpLow; + } + break; + + case 156: /* layout_qualifier: LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN */ + { + context->checkCanUseLayoutQualifier((yylsp[-3])); + (yyval.interm.layoutQualifier) = (yyvsp[-1].interm.layoutQualifier); + } + break; + + case 157: /* layout_qualifier_id_list: layout_qualifier_id */ + { + (yyval.interm.layoutQualifier) = (yyvsp[0].interm.layoutQualifier); + } + break; + + case 158: /* layout_qualifier_id_list: layout_qualifier_id_list COMMA layout_qualifier_id */ + { + (yyval.interm.layoutQualifier) = context->joinLayoutQualifiers( + (yyvsp[-2].interm.layoutQualifier), (yyvsp[0].interm.layoutQualifier), (yylsp[0])); + } + break; + + case 159: /* layout_qualifier_id: IDENTIFIER */ + { + (yyval.interm.layoutQualifier) = + context->parseLayoutQualifier(ImmutableString((yyvsp[0].lex).string), (yylsp[0])); + } + break; + + case 160: /* layout_qualifier_id: IDENTIFIER EQUAL INTCONSTANT */ + { + (yyval.interm.layoutQualifier) = context->parseLayoutQualifier( + ImmutableString((yyvsp[-2].lex).string), (yylsp[-2]), (yyvsp[0].lex).i, (yylsp[0])); + } + break; + + case 161: /* layout_qualifier_id: IDENTIFIER EQUAL UINTCONSTANT */ + { + (yyval.interm.layoutQualifier) = context->parseLayoutQualifier( + ImmutableString((yyvsp[-2].lex).string), (yylsp[-2]), (yyvsp[0].lex).i, (yylsp[0])); + } + break; + + case 162: /* layout_qualifier_id: SHARED */ + { + (yyval.interm.layoutQualifier) = + context->parseLayoutQualifier(ImmutableString("shared"), (yylsp[0])); + } + break; + + case 163: /* type_specifier_no_prec: type_specifier_nonarray */ + { + (yyval.interm.type) + .initialize((yyvsp[0].interm.typeSpecifierNonArray), + (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary)); + } + break; + + case 164: /* type_specifier_no_prec: type_specifier_nonarray array_specifier */ + { + (yyval.interm.type) + .initialize((yyvsp[-1].interm.typeSpecifierNonArray), + (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary)); + (yyval.interm.type).setArraySizes((yyvsp[0].interm.arraySizes)); + } + break; + + case 165: /* array_specifier: LEFT_BRACKET RIGHT_BRACKET */ + { + ES3_OR_NEWER("[]", (yylsp[-1]), "implicitly sized array"); + (yyval.interm.arraySizes) = new TVector(); + (yyval.interm.arraySizes)->push_back(0u); + } + break; + + case 166: /* array_specifier: LEFT_BRACKET constant_expression RIGHT_BRACKET */ + { + (yyval.interm.arraySizes) = new TVector(); + unsigned int size = + context->checkIsValidArraySize((yylsp[-2]), (yyvsp[-1].interm.intermTypedNode)); + // Make the type an array even if size check failed. + // This ensures useless error messages regarding a variable's non-arrayness won't + // follow. + (yyval.interm.arraySizes)->push_back(size); + } + break; + + case 167: /* array_specifier: array_specifier LEFT_BRACKET RIGHT_BRACKET */ + { + ES3_1_OR_NEWER("[]", (yylsp[-1]), "arrays of arrays"); + (yyval.interm.arraySizes) = (yyvsp[-2].interm.arraySizes); + (yyval.interm.arraySizes)->insert((yyval.interm.arraySizes)->begin(), 0u); + } + break; + + case 168: /* array_specifier: array_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET + */ + { + ES3_1_OR_NEWER("[]", (yylsp[-2]), "arrays of arrays"); + (yyval.interm.arraySizes) = (yyvsp[-3].interm.arraySizes); + unsigned int size = + context->checkIsValidArraySize((yylsp[-2]), (yyvsp[-1].interm.intermTypedNode)); + // Make the type an array even if size check failed. + // This ensures useless error messages regarding a variable's non-arrayness won't + // follow. + (yyval.interm.arraySizes)->insert((yyval.interm.arraySizes)->begin(), size); + } + break; + + case 169: /* type_specifier_nonarray: VOID_TYPE */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtVoid, (yylsp[0])); + } + break; + + case 170: /* type_specifier_nonarray: FLOAT_TYPE */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); + } + break; + + case 171: /* type_specifier_nonarray: INT_TYPE */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0])); + } + break; + + case 172: /* type_specifier_nonarray: UINT_TYPE */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0])); + } + break; + + case 173: /* type_specifier_nonarray: BOOL_TYPE */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0])); + } + break; + + case 174: /* type_specifier_nonarray: VEC2 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setAggregate(2); + } + break; + + case 175: /* type_specifier_nonarray: VEC3 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setAggregate(3); + } + break; + + case 176: /* type_specifier_nonarray: VEC4 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setAggregate(4); + } + break; + + case 177: /* type_specifier_nonarray: BVEC2 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setAggregate(2); + } + break; + + case 178: /* type_specifier_nonarray: BVEC3 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setAggregate(3); + } + break; + + case 179: /* type_specifier_nonarray: BVEC4 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setAggregate(4); + } + break; + + case 180: /* type_specifier_nonarray: IVEC2 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setAggregate(2); + } + break; + + case 181: /* type_specifier_nonarray: IVEC3 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setAggregate(3); + } + break; + + case 182: /* type_specifier_nonarray: IVEC4 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setAggregate(4); + } + break; + + case 183: /* type_specifier_nonarray: UVEC2 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setAggregate(2); + } + break; + + case 184: /* type_specifier_nonarray: UVEC3 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setAggregate(3); + } + break; + + case 185: /* type_specifier_nonarray: UVEC4 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setAggregate(4); + } + break; + + case 186: /* type_specifier_nonarray: MATRIX2 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setMatrix(2, 2); + } + break; + + case 187: /* type_specifier_nonarray: MATRIX3 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setMatrix(3, 3); + } + break; + + case 188: /* type_specifier_nonarray: MATRIX4 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setMatrix(4, 4); + } + break; + + case 189: /* type_specifier_nonarray: MATRIX2x3 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setMatrix(2, 3); + } + break; + + case 190: /* type_specifier_nonarray: MATRIX3x2 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setMatrix(3, 2); + } + break; + + case 191: /* type_specifier_nonarray: MATRIX2x4 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setMatrix(2, 4); + } + break; + + case 192: /* type_specifier_nonarray: MATRIX4x2 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setMatrix(4, 2); + } + break; + + case 193: /* type_specifier_nonarray: MATRIX3x4 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setMatrix(3, 4); + } + break; + + case 194: /* type_specifier_nonarray: MATRIX4x3 */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); + (yyval.interm.typeSpecifierNonArray).setMatrix(4, 3); + } + break; + + case 195: /* type_specifier_nonarray: YUVCSCSTANDARDEXT */ + { + if (!context->checkCanUseExtension((yylsp[0]), TExtension::EXT_YUV_target)) + { + context->error((yylsp[0]), "unsupported type", "yuvCscStandardEXT"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtYuvCscStandardEXT, (yylsp[0])); + } + break; + + case 196: /* type_specifier_nonarray: SAMPLER2D */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2D, (yylsp[0])); + } + break; + + case 197: /* type_specifier_nonarray: SAMPLER3D */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler3D, (yylsp[0])); + } + break; + + case 198: /* type_specifier_nonarray: SAMPLERCUBE */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCube, (yylsp[0])); + } + break; + + case 199: /* type_specifier_nonarray: SAMPLER2DARRAY */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DArray, (yylsp[0])); + } + break; + + case 200: /* type_specifier_nonarray: SAMPLER2DMS */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DMS, (yylsp[0])); + } + break; + + case 201: /* type_specifier_nonarray: SAMPLER2DMSARRAY */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DMSArray, (yylsp[0])); + } + break; + + case 202: /* type_specifier_nonarray: SAMPLERCUBEARRAYOES */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::OES_texture_cube_map_array)) + { + context->error((yylsp[0]), "unsupported type", "__samplerCubeArray"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCubeArray, (yylsp[0])); + } + break; + + case 203: /* type_specifier_nonarray: SAMPLERCUBEARRAYEXT */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_texture_cube_map_array)) + { + context->error((yylsp[0]), "unsupported type", "__samplerCubeArray"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCubeArray, (yylsp[0])); + } + break; + + case 204: /* type_specifier_nonarray: SAMPLERBUFFER */ + { + constexpr std::array extensions{ + {TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}; + if (context->getShaderVersion() < 320 && + !context->checkCanUseOneOfExtensions((yylsp[0]), extensions)) + { + context->error((yylsp[0]), "unsupported type", "__samplerBuffer"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerBuffer, (yylsp[0])); + } + break; + + case 205: /* type_specifier_nonarray: ISAMPLER2D */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2D, (yylsp[0])); + } + break; + + case 206: /* type_specifier_nonarray: ISAMPLER3D */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler3D, (yylsp[0])); + } + break; + + case 207: /* type_specifier_nonarray: ISAMPLERCUBE */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtISamplerCube, (yylsp[0])); + } + break; + + case 208: /* type_specifier_nonarray: ISAMPLER2DARRAY */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2DArray, (yylsp[0])); + } + break; + + case 209: /* type_specifier_nonarray: ISAMPLER2DMS */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2DMS, (yylsp[0])); + } + break; + + case 210: /* type_specifier_nonarray: ISAMPLER2DMSARRAY */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2DMSArray, (yylsp[0])); + } + break; + + case 211: /* type_specifier_nonarray: ISAMPLERCUBEARRAYOES */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::OES_texture_cube_map_array)) + { + context->error((yylsp[0]), "unsupported type", "__isamplerCubeArray"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtISamplerCubeArray, (yylsp[0])); + } + break; + + case 212: /* type_specifier_nonarray: ISAMPLERCUBEARRAYEXT */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_texture_cube_map_array)) + { + context->error((yylsp[0]), "unsupported type", "__isamplerCubeArray"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtISamplerCubeArray, (yylsp[0])); + } + break; + + case 213: /* type_specifier_nonarray: ISAMPLERBUFFER */ + { + constexpr std::array extensions{ + {TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}; + if (context->getShaderVersion() < 320 && + !context->checkCanUseOneOfExtensions((yylsp[0]), extensions)) + { + context->error((yylsp[0]), "unsupported type", "__isamplerBuffer"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtISamplerBuffer, (yylsp[0])); + } + break; + + case 214: /* type_specifier_nonarray: USAMPLER2D */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2D, (yylsp[0])); + } + break; + + case 215: /* type_specifier_nonarray: USAMPLER3D */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler3D, (yylsp[0])); + } + break; + + case 216: /* type_specifier_nonarray: USAMPLERCUBE */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtUSamplerCube, (yylsp[0])); + } + break; + + case 217: /* type_specifier_nonarray: USAMPLER2DARRAY */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2DArray, (yylsp[0])); + } + break; + + case 218: /* type_specifier_nonarray: USAMPLER2DMS */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2DMS, (yylsp[0])); + } + break; + + case 219: /* type_specifier_nonarray: USAMPLER2DMSARRAY */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2DMSArray, (yylsp[0])); + } + break; + + case 220: /* type_specifier_nonarray: USAMPLERCUBEARRAYOES */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::OES_texture_cube_map_array)) + { + context->error((yylsp[0]), "unsupported type", "__usamplerCubeArray"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtUSamplerCubeArray, (yylsp[0])); + } + break; + + case 221: /* type_specifier_nonarray: USAMPLERCUBEARRAYEXT */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_texture_cube_map_array)) + { + context->error((yylsp[0]), "unsupported type", "__usamplerCubeArray"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtUSamplerCubeArray, (yylsp[0])); + } + break; + + case 222: /* type_specifier_nonarray: USAMPLERBUFFER */ + { + constexpr std::array extensions{ + {TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}; + if (context->getShaderVersion() < 320 && + !context->checkCanUseOneOfExtensions((yylsp[0]), extensions)) + { + context->error((yylsp[0]), "unsupported type", "__usamplerBuffer"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtUSamplerBuffer, (yylsp[0])); + } + break; + + case 223: /* type_specifier_nonarray: SAMPLER2DSHADOW */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DShadow, (yylsp[0])); + } + break; + + case 224: /* type_specifier_nonarray: SAMPLERCUBESHADOW */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCubeShadow, (yylsp[0])); + } + break; + + case 225: /* type_specifier_nonarray: SAMPLER2DARRAYSHADOW */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DArrayShadow, (yylsp[0])); + } + break; + + case 226: /* type_specifier_nonarray: SAMPLERCUBEARRAYSHADOWOES */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::OES_texture_cube_map_array)) + { + context->error((yylsp[0]), "unsupported type", "__samplerCubeArrayShadow"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCubeArrayShadow, (yylsp[0])); + } + break; + + case 227: /* type_specifier_nonarray: SAMPLERCUBEARRAYSHADOWEXT */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_texture_cube_map_array)) + { + context->error((yylsp[0]), "unsupported type", "__samplerCubeArrayShadow"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCubeArrayShadow, (yylsp[0])); + } + break; + + case 228: /* type_specifier_nonarray: SAMPLERVIDEOWEBGL */ + { + if (!context->checkCanUseExtension((yylsp[0]), TExtension::WEBGL_video_texture)) + { + context->error((yylsp[0]), "unsupported type", "samplerVideoWEBGL"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerVideoWEBGL, (yylsp[0])); + } + break; + + case 229: /* type_specifier_nonarray: SAMPLER_EXTERNAL_OES */ + { + constexpr std::array extensions{ + {TExtension::NV_EGL_stream_consumer_external, + TExtension::OES_EGL_image_external_essl3, TExtension::OES_EGL_image_external}}; + if (!context->checkCanUseOneOfExtensions((yylsp[0]), extensions)) + { + context->error((yylsp[0]), "unsupported type", "samplerExternalOES"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerExternalOES, (yylsp[0])); + } + break; + + case 230: /* type_specifier_nonarray: SAMPLEREXTERNAL2DY2YEXT */ + { + if (!context->checkCanUseExtension((yylsp[0]), TExtension::EXT_YUV_target)) + { + context->error((yylsp[0]), "unsupported type", "__samplerExternal2DY2YEXT"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerExternal2DY2YEXT, (yylsp[0])); + } + break; + + case 231: /* type_specifier_nonarray: SAMPLER2DRECT */ + { + if (!context->checkCanUseExtension((yylsp[0]), TExtension::ARB_texture_rectangle)) + { + context->error((yylsp[0]), "unsupported type", "sampler2DRect"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DRect, (yylsp[0])); + } + break; + + case 232: /* type_specifier_nonarray: IMAGE2D */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtImage2D, (yylsp[0])); + } + break; + + case 233: /* type_specifier_nonarray: IIMAGE2D */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage2D, (yylsp[0])); + } + break; + + case 234: /* type_specifier_nonarray: UIMAGE2D */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage2D, (yylsp[0])); + } + break; + + case 235: /* type_specifier_nonarray: IMAGE3D */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtImage3D, (yylsp[0])); + } + break; + + case 236: /* type_specifier_nonarray: IIMAGE3D */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage3D, (yylsp[0])); + } + break; + + case 237: /* type_specifier_nonarray: UIMAGE3D */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage3D, (yylsp[0])); + } + break; + + case 238: /* type_specifier_nonarray: IMAGE2DARRAY */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtImage2DArray, (yylsp[0])); + } + break; + + case 239: /* type_specifier_nonarray: IIMAGE2DARRAY */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage2DArray, (yylsp[0])); + } + break; + + case 240: /* type_specifier_nonarray: UIMAGE2DARRAY */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage2DArray, (yylsp[0])); + } + break; + + case 241: /* type_specifier_nonarray: IMAGECUBE */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtImageCube, (yylsp[0])); + } + break; + + case 242: /* type_specifier_nonarray: IIMAGECUBE */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtIImageCube, (yylsp[0])); + } + break; + + case 243: /* type_specifier_nonarray: UIMAGECUBE */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtUImageCube, (yylsp[0])); + } + break; + + case 244: /* type_specifier_nonarray: IMAGECUBEARRAYOES */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::OES_texture_cube_map_array)) + { + context->error((yylsp[0]), "unsupported type", "__imageCubeArray"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtImageCubeArray, (yylsp[0])); + } + break; + + case 245: /* type_specifier_nonarray: IMAGECUBEARRAYEXT */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_texture_cube_map_array)) + { + context->error((yylsp[0]), "unsupported type", "__imageCubeArray"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtImageCubeArray, (yylsp[0])); + } + break; + + case 246: /* type_specifier_nonarray: IIMAGECUBEARRAYOES */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::OES_texture_cube_map_array)) + { + context->error((yylsp[0]), "unsupported type", "__iimageCubeArray"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtIImageCubeArray, (yylsp[0])); + } + break; + + case 247: /* type_specifier_nonarray: IIMAGECUBEARRAYEXT */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_texture_cube_map_array)) + { + context->error((yylsp[0]), "unsupported type", "__iimageCubeArray"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtIImageCubeArray, (yylsp[0])); + } + break; + + case 248: /* type_specifier_nonarray: UIMAGECUBEARRAYOES */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::OES_texture_cube_map_array)) + { + context->error((yylsp[0]), "unsupported type", "__uimageCubeArray"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtUImageCubeArray, (yylsp[0])); + } + break; + + case 249: /* type_specifier_nonarray: UIMAGECUBEARRAYEXT */ + { + if (context->getShaderVersion() < 320 && + !context->checkCanUseExtension((yylsp[0]), TExtension::EXT_texture_cube_map_array)) + { + context->error((yylsp[0]), "unsupported type", "__uimageCubeArray"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtUImageCubeArray, (yylsp[0])); + } + break; + + case 250: /* type_specifier_nonarray: IMAGEBUFFER */ + { + constexpr std::array extensions{ + {TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}; + if (context->getShaderVersion() < 320 && + !context->checkCanUseOneOfExtensions((yylsp[0]), extensions)) + { + context->error((yylsp[0]), "unsupported type", "__imageBuffer"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtImageBuffer, (yylsp[0])); + } + break; + + case 251: /* type_specifier_nonarray: IIMAGEBUFFER */ + { + constexpr std::array extensions{ + {TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}; + if (context->getShaderVersion() < 320 && + !context->checkCanUseOneOfExtensions((yylsp[0]), extensions)) + { + context->error((yylsp[0]), "unsupported type", "__iimageBuffer"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtIImageBuffer, (yylsp[0])); + } + break; + + case 252: /* type_specifier_nonarray: UIMAGEBUFFER */ + { + constexpr std::array extensions{ + {TExtension::OES_texture_buffer, TExtension::EXT_texture_buffer}}; + if (context->getShaderVersion() < 320 && + !context->checkCanUseOneOfExtensions((yylsp[0]), extensions)) + { + context->error((yylsp[0]), "unsupported type", "__uimageBuffer"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtUImageBuffer, (yylsp[0])); + } + break; + + case 253: /* type_specifier_nonarray: ATOMICUINT */ + { + (yyval.interm.typeSpecifierNonArray).initialize(EbtAtomicCounter, (yylsp[0])); + } + break; + + case 254: /* type_specifier_nonarray: PIXELLOCALANGLE */ + { + if (!context->checkCanUseExtension((yylsp[0]), + TExtension::ANGLE_shader_pixel_local_storage)) + { + context->error((yylsp[0]), "unsupported type", "__pixelLocalANGLE"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtPixelLocalANGLE, (yylsp[0])); + } + break; + + case 255: /* type_specifier_nonarray: IPIXELLOCALANGLE */ + { + if (!context->checkCanUseExtension((yylsp[0]), + TExtension::ANGLE_shader_pixel_local_storage)) + { + context->error((yylsp[0]), "unsupported type", "__ipixelLocalANGLE"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtIPixelLocalANGLE, (yylsp[0])); + } + break; + + case 256: /* type_specifier_nonarray: UPIXELLOCALANGLE */ + { + if (!context->checkCanUseExtension((yylsp[0]), + TExtension::ANGLE_shader_pixel_local_storage)) + { + context->error((yylsp[0]), "unsupported type", "__upixelLocalANGLE"); + } + (yyval.interm.typeSpecifierNonArray).initialize(EbtUPixelLocalANGLE, (yylsp[0])); + } + break; + + case 257: /* type_specifier_nonarray: struct_specifier */ + { + (yyval.interm.typeSpecifierNonArray) = (yyvsp[0].interm.typeSpecifierNonArray); + } + break; + + case 258: /* type_specifier_nonarray: TYPE_NAME */ + { + // This is for user defined type names. The lexical phase looked up the type. + const TStructure *structure = static_cast((yyvsp[0].lex).symbol); + (yyval.interm.typeSpecifierNonArray).initializeStruct(structure, false, (yylsp[0])); + } + break; + + case 259: /* $@1: %empty */ + { + context->enterStructDeclaration((yylsp[-1]), ImmutableString((yyvsp[-1].lex).string)); + } + break; + + case 260: /* struct_specifier: STRUCT identifier LEFT_BRACE $@1 struct_declaration_list + RIGHT_BRACE */ + { + (yyval.interm.typeSpecifierNonArray) = context->addStructure( + (yylsp[-5]), (yylsp[-4]), ImmutableString((yyvsp[-4].lex).string), + (yyvsp[-1].interm.fieldList)); + } + break; + + case 261: /* $@2: %empty */ + { + context->enterStructDeclaration((yylsp[0]), kEmptyImmutableString); + } + break; + + case 262: /* struct_specifier: STRUCT LEFT_BRACE $@2 struct_declaration_list RIGHT_BRACE */ + { + (yyval.interm.typeSpecifierNonArray) = context->addStructure( + (yylsp[-4]), (yyloc), kEmptyImmutableString, (yyvsp[-1].interm.fieldList)); + } + break; + + case 263: /* struct_declaration_list: struct_declaration */ + { + (yyval.interm.fieldList) = + context->addStructFieldList((yyvsp[0].interm.fieldList), (yylsp[0])); + } + break; + + case 264: /* struct_declaration_list: struct_declaration_list struct_declaration */ + { + (yyval.interm.fieldList) = context->combineStructFieldLists( + (yyvsp[-1].interm.fieldList), (yyvsp[0].interm.fieldList), (yylsp[0])); + } + break; + + case 265: /* struct_declaration: type_specifier struct_declarator_list SEMICOLON */ + { + (yyval.interm.fieldList) = context->addStructDeclaratorList( + (yyvsp[-2].interm.type), (yyvsp[-1].interm.declaratorList)); + } + break; + + case 266: /* struct_declaration: type_qualifier type_specifier struct_declarator_list + SEMICOLON */ + { + // ES3 Only, but errors should be handled elsewhere + (yyval.interm.fieldList) = context->addStructDeclaratorListWithQualifiers( + *(yyvsp[-3].interm.typeQualifierBuilder), &(yyvsp[-2].interm.type), + (yyvsp[-1].interm.declaratorList)); + } + break; + + case 267: /* struct_declarator_list: struct_declarator */ + { + (yyval.interm.declaratorList) = new TDeclaratorList(); + (yyval.interm.declaratorList)->push_back((yyvsp[0].interm.declarator)); + } + break; + + case 268: /* struct_declarator_list: struct_declarator_list COMMA struct_declarator */ + { + (yyval.interm.declaratorList)->push_back((yyvsp[0].interm.declarator)); + } + break; + + case 269: /* struct_declarator: identifier */ + { + (yyval.interm.declarator) = + context->parseStructDeclarator(ImmutableString((yyvsp[0].lex).string), (yylsp[0])); + } + break; + + case 270: /* struct_declarator: identifier array_specifier */ + { + (yyval.interm.declarator) = context->parseStructArrayDeclarator( + ImmutableString((yyvsp[-1].lex).string), (yylsp[-1]), (yyvsp[0].interm.arraySizes)); + } + break; + + case 271: /* initializer: assignment_expression */ + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 272: /* declaration_statement: declaration */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } + break; + + case 273: /* statement: compound_statement_with_scope */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock); + } + break; + + case 274: /* statement: simple_statement */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } + break; + + case 275: /* simple_statement: declaration_statement */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } + break; + + case 276: /* simple_statement: expression_statement */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } + break; + + case 277: /* simple_statement: selection_statement */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } + break; + + case 278: /* simple_statement: switch_statement */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermSwitch); + } + break; + + case 279: /* simple_statement: case_label */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermCase); + } + break; + + case 280: /* simple_statement: iteration_statement */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } + break; + + case 281: /* simple_statement: jump_statement */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } + break; + + case 282: /* compound_statement_with_scope: LEFT_BRACE RIGHT_BRACE */ + { + (yyval.interm.intermBlock) = new TIntermBlock(); + (yyval.interm.intermBlock)->setLine((yyloc)); + } + break; + + case 283: /* $@3: %empty */ + { + context->symbolTable.push(); + } + break; + + case 284: /* $@4: %empty */ + { + context->symbolTable.pop(); + } + break; + + case 285: /* compound_statement_with_scope: LEFT_BRACE $@3 statement_list $@4 RIGHT_BRACE */ + { + (yyvsp[-2].interm.intermBlock)->setLine((yyloc)); + (yyval.interm.intermBlock) = (yyvsp[-2].interm.intermBlock); + } + break; + + case 286: /* statement_no_new_scope: compound_statement_no_new_scope */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock); + } + break; + + case 287: /* statement_no_new_scope: simple_statement */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } + break; + + case 288: /* $@5: %empty */ + { + context->symbolTable.push(); + } + break; + + case 289: /* statement_with_scope: $@5 compound_statement_no_new_scope */ + { + context->symbolTable.pop(); + (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock); + } + break; + + case 290: /* $@6: %empty */ + { + context->symbolTable.push(); + } + break; + + case 291: /* statement_with_scope: $@6 simple_statement */ + { + context->symbolTable.pop(); + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } + break; + + case 292: /* compound_statement_no_new_scope: LEFT_BRACE RIGHT_BRACE */ + { + (yyval.interm.intermBlock) = new TIntermBlock(); + (yyval.interm.intermBlock)->setLine((yyloc)); + } + break; + + case 293: /* compound_statement_no_new_scope: LEFT_BRACE statement_list RIGHT_BRACE */ + { + (yyvsp[-1].interm.intermBlock)->setLine((yyloc)); + (yyval.interm.intermBlock) = (yyvsp[-1].interm.intermBlock); + } + break; + + case 294: /* statement_list: statement */ + { + (yyval.interm.intermBlock) = new TIntermBlock(); + context->appendStatement((yyval.interm.intermBlock), (yyvsp[0].interm.intermNode)); + } + break; + + case 295: /* statement_list: statement_list statement */ + { + (yyval.interm.intermBlock) = (yyvsp[-1].interm.intermBlock); + context->appendStatement((yyval.interm.intermBlock), (yyvsp[0].interm.intermNode)); + } + break; + + case 296: /* expression_statement: SEMICOLON */ + { + (yyval.interm.intermNode) = context->addEmptyStatement((yyloc)); + } + break; + + case 297: /* expression_statement: expression SEMICOLON */ + { + (yyval.interm.intermNode) = (yyvsp[-1].interm.intermTypedNode); + } + break; + + case 298: /* selection_statement: IF LEFT_PAREN expression RIGHT_PAREN + selection_rest_statement */ + { + (yyval.interm.intermNode) = context->addIfElse((yyvsp[-2].interm.intermTypedNode), + (yyvsp[0].interm.nodePair), (yylsp[-4])); + } + break; + + case 299: /* selection_rest_statement: statement_with_scope ELSE statement_with_scope */ + { + (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode); + (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermNode); + } + break; + + case 300: /* selection_rest_statement: statement_with_scope */ + { + (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode); + (yyval.interm.nodePair).node2 = nullptr; + } + break; + + case 301: /* $@7: %empty */ + { + context->incrSwitchNestingLevel(); + } + break; + + case 302: /* switch_statement: SWITCH LEFT_PAREN expression RIGHT_PAREN $@7 + compound_statement_with_scope */ + { + (yyval.interm.intermSwitch) = context->addSwitch( + (yyvsp[-3].interm.intermTypedNode), (yyvsp[0].interm.intermBlock), (yylsp[-5])); + context->decrSwitchNestingLevel(); + } + break; + + case 303: /* case_label: CASE constant_expression COLON */ + { + (yyval.interm.intermCase) = + context->addCase((yyvsp[-1].interm.intermTypedNode), (yylsp[-2])); + } + break; + + case 304: /* case_label: DEFAULT COLON */ + { + (yyval.interm.intermCase) = context->addDefault((yylsp[-1])); + } + break; + + case 305: /* condition: expression */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermTypedNode); + context->checkIsScalarBool((yyvsp[0].interm.intermTypedNode)->getLine(), + (yyvsp[0].interm.intermTypedNode)); + } + break; + + case 306: /* condition: fully_specified_type identifier EQUAL initializer */ + { + (yyval.interm.intermNode) = context->addConditionInitializer( + (yyvsp[-3].interm.type), ImmutableString((yyvsp[-2].lex).string), + (yyvsp[0].interm.intermTypedNode), (yylsp[-2])); + } + break; + + case 307: /* $@8: %empty */ + { + context->symbolTable.push(); + context->incrLoopNestingLevel(); + } + break; + + case 308: /* iteration_statement: WHILE LEFT_PAREN $@8 condition RIGHT_PAREN + statement_no_new_scope */ + { + context->symbolTable.pop(); + (yyval.interm.intermNode) = + context->addLoop(ELoopWhile, 0, (yyvsp[-2].interm.intermNode), 0, + (yyvsp[0].interm.intermNode), (yylsp[-5])); + context->decrLoopNestingLevel(); + } + break; + + case 309: /* $@9: %empty */ + { + context->incrLoopNestingLevel(); + } + break; + + case 310: /* iteration_statement: DO $@9 statement_with_scope WHILE LEFT_PAREN expression + RIGHT_PAREN SEMICOLON */ + { + (yyval.interm.intermNode) = + context->addLoop(ELoopDoWhile, 0, (yyvsp[-2].interm.intermTypedNode), 0, + (yyvsp[-5].interm.intermNode), (yylsp[-4])); + context->decrLoopNestingLevel(); + } + break; + + case 311: /* $@10: %empty */ + { + context->symbolTable.push(); + context->incrLoopNestingLevel(); + } + break; + + case 312: /* iteration_statement: FOR LEFT_PAREN $@10 for_init_statement for_rest_statement + RIGHT_PAREN statement_no_new_scope */ + { + context->symbolTable.pop(); + (yyval.interm.intermNode) = context->addLoop( + ELoopFor, (yyvsp[-3].interm.intermNode), (yyvsp[-2].interm.nodePair).node1, + reinterpret_cast((yyvsp[-2].interm.nodePair).node2), + (yyvsp[0].interm.intermNode), (yylsp[-6])); + context->decrLoopNestingLevel(); + } + break; + + case 313: /* for_init_statement: expression_statement */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } + break; + + case 314: /* for_init_statement: declaration_statement */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } + break; + + case 315: /* conditionopt: condition */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } + break; + + case 316: /* conditionopt: %empty */ + { + (yyval.interm.intermNode) = nullptr; + } + break; + + case 317: /* for_rest_statement: conditionopt SEMICOLON */ + { + (yyval.interm.nodePair).node1 = (yyvsp[-1].interm.intermNode); + (yyval.interm.nodePair).node2 = 0; + } + break; + + case 318: /* for_rest_statement: conditionopt SEMICOLON expression */ + { + (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode); + (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermTypedNode); + } + break; + + case 319: /* jump_statement: CONTINUE SEMICOLON */ + { + (yyval.interm.intermNode) = context->addBranch(EOpContinue, (yylsp[-1])); + } + break; + + case 320: /* jump_statement: BREAK SEMICOLON */ + { + (yyval.interm.intermNode) = context->addBranch(EOpBreak, (yylsp[-1])); + } + break; + + case 321: /* jump_statement: RETURN SEMICOLON */ + { + (yyval.interm.intermNode) = context->addBranch(EOpReturn, (yylsp[-1])); + } + break; + + case 322: /* jump_statement: RETURN expression SEMICOLON */ + { + (yyval.interm.intermNode) = + context->addBranch(EOpReturn, (yyvsp[-1].interm.intermTypedNode), (yylsp[-2])); + } + break; + + case 323: /* jump_statement: DISCARD SEMICOLON */ + { + (yyval.interm.intermNode) = context->addBranch(EOpKill, (yylsp[-1])); + } + break; + + case 324: /* translation_unit: external_declaration */ + { + (yyval.interm.intermBlock) = new TIntermBlock(); + (yyval.interm.intermBlock)->setLine((yyloc)); + (yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode)); + context->setTreeRoot((yyval.interm.intermBlock)); + } + break; + + case 325: /* translation_unit: translation_unit external_declaration */ + { + (yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode)); + } + break; + + case 326: /* external_declaration: function_definition */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } + break; + + case 327: /* external_declaration: declaration */ + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } + break; + + case 328: /* $@11: %empty */ + { + context->parseFunctionDefinitionHeader((yylsp[0]), (yyvsp[0].interm).function, + &((yyvsp[0].interm).intermFunctionPrototype)); + } + break; + + case 329: /* function_definition: function_prototype $@11 compound_statement_no_new_scope */ + { + (yyval.interm.intermNode) = + context->addFunctionDefinition((yyvsp[-2].interm).intermFunctionPrototype, + (yyvsp[0].interm.intermBlock), (yylsp[-2])); + } + break; + + default: + break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT("-> $$ =", YY_CAST(yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); + + YYPOPSTACK(yylen); + yylen = 0; + + *++yyvsp = yyval; + *++yylsp = yyloc; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = + (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp ? yytable[yyi] : yydefgoto[yylhs]); + } + + goto yynewstate; + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE(yychar); + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; + yyerror(&yylloc, context, scanner, YY_("syntax error")); + } + + yyerror_range[1] = yylloc; + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct("Error: discarding", yytoken, &yylval, &yylloc, context, scanner); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; + ++yynerrs; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK(yylen); + yylen = 0; + YY_STACK_PRINT(yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + /* Pop stack until we find a state that shifts the error token. */ + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default(yyn)) + { + yyn += YYSYMBOL_YYerror; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + yyerror_range[1] = *yylsp; + yydestruct("Error: popping", YY_ACCESSING_SYMBOL(yystate), yyvsp, yylsp, context, scanner); + YYPOPSTACK(1); + yystate = *yyssp; + YY_STACK_PRINT(yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + yyerror_range[2] = yylloc; + ++yylsp; + YYLLOC_DEFAULT(*yylsp, yyerror_range, 2); + + /* Shift the error token. */ + YY_SYMBOL_PRINT("Shifting", YY_ACCESSING_SYMBOL(yyn), yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturnlab; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturnlab; + +/*-----------------------------------------------------------. +| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | +`-----------------------------------------------------------*/ +yyexhaustedlab: + yyerror(&yylloc, context, scanner, YY_("memory exhausted")); + yyresult = 2; + goto yyreturnlab; + +/*----------------------------------------------------------. +| yyreturnlab -- parsing is finished, clean up and return. | +`----------------------------------------------------------*/ +yyreturnlab: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE(yychar); + yydestruct("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc, context, scanner); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK(yylen); + YY_STACK_PRINT(yyss, yyssp); + while (yyssp != yyss) + { + yydestruct("Cleanup: popping", YY_ACCESSING_SYMBOL(+*yyssp), yyvsp, yylsp, context, + scanner); + YYPOPSTACK(1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE(yyss); +#endif + + return yyresult; +} + +int glslang_parse(TParseContext *context) +{ + return yyparse(context, context->getScanner()); +} diff --git a/gfx/angle/checkout/src/compiler/translator/glslang_tab_autogen.h b/gfx/angle/checkout/src/compiler/translator/glslang_tab_autogen.h new file mode 100644 index 0000000000..d5a48edd40 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/glslang_tab_autogen.h @@ -0,0 +1,320 @@ +/* A Bison parser, made by GNU Bison 3.8.2. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + +#ifndef YY_YY_GLSLANG_TAB_AUTOGEN_H_INCLUDED +#define YY_YY_GLSLANG_TAB_AUTOGEN_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif +/* "%code requires" blocks. */ + +#define YYLTYPE TSourceLoc +#define YYLTYPE_IS_DECLARED 1 +#define YYLTYPE_IS_TRIVIAL 1 + +/* Token kinds. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE +enum yytokentype +{ + YYEMPTY = -2, + YYEOF = 0, /* "end of file" */ + YYerror = 256, /* error */ + YYUNDEF = 257, /* "invalid token" */ + INVARIANT = 258, /* INVARIANT */ + PRECISE = 259, /* PRECISE */ + HIGH_PRECISION = 260, /* HIGH_PRECISION */ + MEDIUM_PRECISION = 261, /* MEDIUM_PRECISION */ + LOW_PRECISION = 262, /* LOW_PRECISION */ + PRECISION = 263, /* PRECISION */ + ATTRIBUTE = 264, /* ATTRIBUTE */ + CONST_QUAL = 265, /* CONST_QUAL */ + BOOL_TYPE = 266, /* BOOL_TYPE */ + FLOAT_TYPE = 267, /* FLOAT_TYPE */ + INT_TYPE = 268, /* INT_TYPE */ + UINT_TYPE = 269, /* UINT_TYPE */ + BREAK = 270, /* BREAK */ + CONTINUE = 271, /* CONTINUE */ + DO = 272, /* DO */ + ELSE = 273, /* ELSE */ + FOR = 274, /* FOR */ + IF = 275, /* IF */ + DISCARD = 276, /* DISCARD */ + RETURN = 277, /* RETURN */ + SWITCH = 278, /* SWITCH */ + CASE = 279, /* CASE */ + DEFAULT = 280, /* DEFAULT */ + BVEC2 = 281, /* BVEC2 */ + BVEC3 = 282, /* BVEC3 */ + BVEC4 = 283, /* BVEC4 */ + IVEC2 = 284, /* IVEC2 */ + IVEC3 = 285, /* IVEC3 */ + IVEC4 = 286, /* IVEC4 */ + VEC2 = 287, /* VEC2 */ + VEC3 = 288, /* VEC3 */ + VEC4 = 289, /* VEC4 */ + UVEC2 = 290, /* UVEC2 */ + UVEC3 = 291, /* UVEC3 */ + UVEC4 = 292, /* UVEC4 */ + MATRIX2 = 293, /* MATRIX2 */ + MATRIX3 = 294, /* MATRIX3 */ + MATRIX4 = 295, /* MATRIX4 */ + IN_QUAL = 296, /* IN_QUAL */ + OUT_QUAL = 297, /* OUT_QUAL */ + INOUT_QUAL = 298, /* INOUT_QUAL */ + UNIFORM = 299, /* UNIFORM */ + BUFFER = 300, /* BUFFER */ + VARYING = 301, /* VARYING */ + MATRIX2x3 = 302, /* MATRIX2x3 */ + MATRIX3x2 = 303, /* MATRIX3x2 */ + MATRIX2x4 = 304, /* MATRIX2x4 */ + MATRIX4x2 = 305, /* MATRIX4x2 */ + MATRIX3x4 = 306, /* MATRIX3x4 */ + MATRIX4x3 = 307, /* MATRIX4x3 */ + SAMPLE = 308, /* SAMPLE */ + CENTROID = 309, /* CENTROID */ + FLAT = 310, /* FLAT */ + SMOOTH = 311, /* SMOOTH */ + NOPERSPECTIVE = 312, /* NOPERSPECTIVE */ + PATCH = 313, /* PATCH */ + READONLY = 314, /* READONLY */ + WRITEONLY = 315, /* WRITEONLY */ + COHERENT = 316, /* COHERENT */ + RESTRICT = 317, /* RESTRICT */ + VOLATILE = 318, /* VOLATILE */ + SHARED = 319, /* SHARED */ + STRUCT = 320, /* STRUCT */ + VOID_TYPE = 321, /* VOID_TYPE */ + WHILE = 322, /* WHILE */ + SAMPLER2D = 323, /* SAMPLER2D */ + SAMPLERCUBE = 324, /* SAMPLERCUBE */ + SAMPLER_EXTERNAL_OES = 325, /* SAMPLER_EXTERNAL_OES */ + SAMPLER2DRECT = 326, /* SAMPLER2DRECT */ + SAMPLER2DARRAY = 327, /* SAMPLER2DARRAY */ + ISAMPLER2D = 328, /* ISAMPLER2D */ + ISAMPLER3D = 329, /* ISAMPLER3D */ + ISAMPLERCUBE = 330, /* ISAMPLERCUBE */ + ISAMPLER2DARRAY = 331, /* ISAMPLER2DARRAY */ + USAMPLER2D = 332, /* USAMPLER2D */ + USAMPLER3D = 333, /* USAMPLER3D */ + USAMPLERCUBE = 334, /* USAMPLERCUBE */ + USAMPLER2DARRAY = 335, /* USAMPLER2DARRAY */ + SAMPLER2DMS = 336, /* SAMPLER2DMS */ + ISAMPLER2DMS = 337, /* ISAMPLER2DMS */ + USAMPLER2DMS = 338, /* USAMPLER2DMS */ + SAMPLER2DMSARRAY = 339, /* SAMPLER2DMSARRAY */ + ISAMPLER2DMSARRAY = 340, /* ISAMPLER2DMSARRAY */ + USAMPLER2DMSARRAY = 341, /* USAMPLER2DMSARRAY */ + SAMPLER3D = 342, /* SAMPLER3D */ + SAMPLER3DRECT = 343, /* SAMPLER3DRECT */ + SAMPLER2DSHADOW = 344, /* SAMPLER2DSHADOW */ + SAMPLERCUBESHADOW = 345, /* SAMPLERCUBESHADOW */ + SAMPLER2DARRAYSHADOW = 346, /* SAMPLER2DARRAYSHADOW */ + SAMPLERVIDEOWEBGL = 347, /* SAMPLERVIDEOWEBGL */ + SAMPLERCUBEARRAYOES = 348, /* SAMPLERCUBEARRAYOES */ + SAMPLERCUBEARRAYSHADOWOES = 349, /* SAMPLERCUBEARRAYSHADOWOES */ + ISAMPLERCUBEARRAYOES = 350, /* ISAMPLERCUBEARRAYOES */ + USAMPLERCUBEARRAYOES = 351, /* USAMPLERCUBEARRAYOES */ + SAMPLERCUBEARRAYEXT = 352, /* SAMPLERCUBEARRAYEXT */ + SAMPLERCUBEARRAYSHADOWEXT = 353, /* SAMPLERCUBEARRAYSHADOWEXT */ + ISAMPLERCUBEARRAYEXT = 354, /* ISAMPLERCUBEARRAYEXT */ + USAMPLERCUBEARRAYEXT = 355, /* USAMPLERCUBEARRAYEXT */ + SAMPLERBUFFER = 356, /* SAMPLERBUFFER */ + ISAMPLERBUFFER = 357, /* ISAMPLERBUFFER */ + USAMPLERBUFFER = 358, /* USAMPLERBUFFER */ + SAMPLEREXTERNAL2DY2YEXT = 359, /* SAMPLEREXTERNAL2DY2YEXT */ + IMAGE2D = 360, /* IMAGE2D */ + IIMAGE2D = 361, /* IIMAGE2D */ + UIMAGE2D = 362, /* UIMAGE2D */ + IMAGE3D = 363, /* IMAGE3D */ + IIMAGE3D = 364, /* IIMAGE3D */ + UIMAGE3D = 365, /* UIMAGE3D */ + IMAGE2DARRAY = 366, /* IMAGE2DARRAY */ + IIMAGE2DARRAY = 367, /* IIMAGE2DARRAY */ + UIMAGE2DARRAY = 368, /* UIMAGE2DARRAY */ + IMAGECUBE = 369, /* IMAGECUBE */ + IIMAGECUBE = 370, /* IIMAGECUBE */ + UIMAGECUBE = 371, /* UIMAGECUBE */ + IMAGECUBEARRAYOES = 372, /* IMAGECUBEARRAYOES */ + IIMAGECUBEARRAYOES = 373, /* IIMAGECUBEARRAYOES */ + UIMAGECUBEARRAYOES = 374, /* UIMAGECUBEARRAYOES */ + IMAGECUBEARRAYEXT = 375, /* IMAGECUBEARRAYEXT */ + IIMAGECUBEARRAYEXT = 376, /* IIMAGECUBEARRAYEXT */ + UIMAGECUBEARRAYEXT = 377, /* UIMAGECUBEARRAYEXT */ + IMAGEBUFFER = 378, /* IMAGEBUFFER */ + IIMAGEBUFFER = 379, /* IIMAGEBUFFER */ + UIMAGEBUFFER = 380, /* UIMAGEBUFFER */ + ATOMICUINT = 381, /* ATOMICUINT */ + PIXELLOCALANGLE = 382, /* PIXELLOCALANGLE */ + IPIXELLOCALANGLE = 383, /* IPIXELLOCALANGLE */ + UPIXELLOCALANGLE = 384, /* UPIXELLOCALANGLE */ + LAYOUT = 385, /* LAYOUT */ + YUVCSCSTANDARDEXT = 386, /* YUVCSCSTANDARDEXT */ + YUVCSCSTANDARDEXTCONSTANT = 387, /* YUVCSCSTANDARDEXTCONSTANT */ + IDENTIFIER = 388, /* IDENTIFIER */ + TYPE_NAME = 389, /* TYPE_NAME */ + FLOATCONSTANT = 390, /* FLOATCONSTANT */ + INTCONSTANT = 391, /* INTCONSTANT */ + UINTCONSTANT = 392, /* UINTCONSTANT */ + BOOLCONSTANT = 393, /* BOOLCONSTANT */ + FIELD_SELECTION = 394, /* FIELD_SELECTION */ + LEFT_OP = 395, /* LEFT_OP */ + RIGHT_OP = 396, /* RIGHT_OP */ + INC_OP = 397, /* INC_OP */ + DEC_OP = 398, /* DEC_OP */ + LE_OP = 399, /* LE_OP */ + GE_OP = 400, /* GE_OP */ + EQ_OP = 401, /* EQ_OP */ + NE_OP = 402, /* NE_OP */ + AND_OP = 403, /* AND_OP */ + OR_OP = 404, /* OR_OP */ + XOR_OP = 405, /* XOR_OP */ + MUL_ASSIGN = 406, /* MUL_ASSIGN */ + DIV_ASSIGN = 407, /* DIV_ASSIGN */ + ADD_ASSIGN = 408, /* ADD_ASSIGN */ + MOD_ASSIGN = 409, /* MOD_ASSIGN */ + LEFT_ASSIGN = 410, /* LEFT_ASSIGN */ + RIGHT_ASSIGN = 411, /* RIGHT_ASSIGN */ + AND_ASSIGN = 412, /* AND_ASSIGN */ + XOR_ASSIGN = 413, /* XOR_ASSIGN */ + OR_ASSIGN = 414, /* OR_ASSIGN */ + SUB_ASSIGN = 415, /* SUB_ASSIGN */ + LEFT_PAREN = 416, /* LEFT_PAREN */ + RIGHT_PAREN = 417, /* RIGHT_PAREN */ + LEFT_BRACKET = 418, /* LEFT_BRACKET */ + RIGHT_BRACKET = 419, /* RIGHT_BRACKET */ + LEFT_BRACE = 420, /* LEFT_BRACE */ + RIGHT_BRACE = 421, /* RIGHT_BRACE */ + DOT = 422, /* DOT */ + COMMA = 423, /* COMMA */ + COLON = 424, /* COLON */ + EQUAL = 425, /* EQUAL */ + SEMICOLON = 426, /* SEMICOLON */ + BANG = 427, /* BANG */ + DASH = 428, /* DASH */ + TILDE = 429, /* TILDE */ + PLUS = 430, /* PLUS */ + STAR = 431, /* STAR */ + SLASH = 432, /* SLASH */ + PERCENT = 433, /* PERCENT */ + LEFT_ANGLE = 434, /* LEFT_ANGLE */ + RIGHT_ANGLE = 435, /* RIGHT_ANGLE */ + VERTICAL_BAR = 436, /* VERTICAL_BAR */ + CARET = 437, /* CARET */ + AMPERSAND = 438, /* AMPERSAND */ + QUESTION = 439 /* QUESTION */ +}; +typedef enum yytokentype yytoken_kind_t; +#endif + +/* Value type. */ +#if !defined YYSTYPE && !defined YYSTYPE_IS_DECLARED +union YYSTYPE +{ + + struct + { + union + { + const char *string; // pool allocated. + float f; + int i; + unsigned int u; + bool b; + }; + const TSymbol *symbol; + } lex; + struct + { + TOperator op; + union + { + TIntermNode *intermNode; + TIntermNodePair nodePair; + TIntermTyped *intermTypedNode; + TIntermAggregate *intermAggregate; + TIntermBlock *intermBlock; + TIntermDeclaration *intermDeclaration; + TIntermFunctionPrototype *intermFunctionPrototype; + TIntermSwitch *intermSwitch; + TIntermCase *intermCase; + }; + union + { + TVector *arraySizes; + TTypeSpecifierNonArray typeSpecifierNonArray; + TPublicType type; + TPrecision precision; + TLayoutQualifier layoutQualifier; + TQualifier qualifier; + TFunction *function; + TFunctionLookup *functionLookup; + TParameter param; + TDeclarator *declarator; + TDeclaratorList *declaratorList; + TFieldList *fieldList; + TQualifierWrapperBase *qualifierWrapper; + TTypeQualifierBuilder *typeQualifierBuilder; + }; + } interm; +}; +typedef union YYSTYPE YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + +/* Location type. */ +#if !defined YYLTYPE && !defined YYLTYPE_IS_DECLARED +typedef struct YYLTYPE YYLTYPE; +struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +}; +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif + +int yyparse(TParseContext *context, void *scanner); + +#endif /* !YY_YY_GLSLANG_TAB_AUTOGEN_H_INCLUDED */ diff --git a/gfx/angle/checkout/src/compiler/translator/glslang_wrapper.h b/gfx/angle/checkout/src/compiler/translator/glslang_wrapper.h new file mode 100644 index 0000000000..a5cd49bcbb --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/glslang_wrapper.h @@ -0,0 +1,46 @@ +// +// Copyright 2021 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// glslang_wrapper: +// A wrapper to compile GLSL strings to SPIR-V blobs. glslang here refers to the Khronos +// compiler. +// + +#ifndef COMPILER_TRANSLATOR_GLSLANG_WRAPPER_H_ +#define COMPILER_TRANSLATOR_GLSLANG_WRAPPER_H_ + +#include "GLSLANG/ShaderLang.h" +#include "common/PackedEnums.h" +#include "common/spirv/spirv_types.h" + +#include +#include + +namespace sh +{ +#if defined(ANGLE_ENABLE_SPIRV_GENERATION_THROUGH_GLSLANG) +void GlslangInitialize(); +void GlslangFinalize(); + +// Generate SPIR-V out of intermediate GLSL through glslang. +[[nodiscard]] bool GlslangCompileToSpirv(const ShBuiltInResources &resources, + sh::GLenum shaderType, + const std::string &shaderSource, + angle::spirv::Blob *spirvBlobOut); +#else +ANGLE_INLINE void GlslangInitialize() {} +ANGLE_INLINE void GlslangFinalize() {} +ANGLE_INLINE bool GlslangCompileToSpirv(const ShBuiltInResources &resources, + sh::GLenum shaderType, + const std::string &shaderSource, + angle::spirv::Blob *spirvBlobOut) +{ + UNREACHABLE(); + return false; +} +#endif // defined(ANGLE_ENABLE_VULKAN) || defined(ANGLE_ENABLE_METAL) +} // namespace sh + +#endif // COMPILER_TRANSLATOR_GLSLANG_WRAPPER_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/length_limits.h b/gfx/angle/checkout/src/compiler/translator/length_limits.h new file mode 100644 index 0000000000..a7d95db135 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/length_limits.h @@ -0,0 +1,26 @@ +// +// Copyright 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// length_limits.h +// + +#ifndef COMPILER_TRANSLATOR_LENGTHLIMITS_H_ +#define COMPILER_TRANSLATOR_LENGTHLIMITS_H_ + +#include "GLSLANG/ShaderLang.h" + +// These constants are factored out from the rest of the headers to +// make it easier to reference them from the compiler sources. + +namespace sh +{ + +size_t GetGlobalMaxTokenSize(ShShaderSpec spec); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_LENGTHLIMITS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampIndirectIndices.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampIndirectIndices.cpp new file mode 100644 index 0000000000..bd1997a21d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampIndirectIndices.cpp @@ -0,0 +1,136 @@ +// +// Copyright 2021 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ClampIndirectIndices.h: Add clamp to the indirect indices used on arrays. +// + +#include "compiler/translator/tree_ops/ClampIndirectIndices.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ +namespace +{ +// Traverser that finds EOpIndexIndirect nodes and applies a clamp to their right-hand side +// expression. +class ClampIndirectIndicesTraverser : public TIntermTraverser +{ + public: + ClampIndirectIndicesTraverser(TCompiler *compiler, TSymbolTable *symbolTable) + : TIntermTraverser(true, false, false, symbolTable), mCompiler(compiler) + {} + + bool visitBinary(Visit visit, TIntermBinary *node) override + { + ASSERT(visit == PreVisit); + + // Only interested in EOpIndexIndirect nodes. + if (node->getOp() != EOpIndexIndirect) + { + return true; + } + + // Apply the transformation to the left and right nodes + bool valid = ClampIndirectIndices(mCompiler, node->getLeft(), mSymbolTable); + ASSERT(valid); + valid = ClampIndirectIndices(mCompiler, node->getRight(), mSymbolTable); + ASSERT(valid); + + // Generate clamp(right, 0, N), where N is the size of the array being indexed minus 1. If + // the array is runtime-sized, the length() method is called on it. + const TType &leftType = node->getLeft()->getType(); + const TType &rightType = node->getRight()->getType(); + + // Don't clamp indirect indices on unsized arrays in buffer blocks. They are covered by the + // relevant robust access behavior of the backend. + if (leftType.isUnsizedArray()) + { + return true; + } + + // On GLSL es 100, clamp is only defined for float, so float arguments are used. + // + // However, float clamp is unconditionally emitted to workaround driver bugs with integer + // clamp on Qualcomm. http://crbug.com/1217167 + // + // const bool useFloatClamp = mCompiler->getShaderVersion() == 100; + const bool useFloatClamp = true; + + TIntermConstantUnion *zero = createClampValue(0, useFloatClamp); + TIntermTyped *max; + + if (leftType.isArray()) + { + max = createClampValue(static_cast(leftType.getOutermostArraySize()) - 1, + useFloatClamp); + } + else + { + ASSERT(leftType.isVector() || leftType.isMatrix()); + max = createClampValue(leftType.getNominalSize() - 1, useFloatClamp); + } + + TIntermTyped *index = node->getRight(); + // If the index node is not an int (i.e. it's a uint), or a float (if using float clamp), + // cast it. + const TBasicType requiredBasicType = useFloatClamp ? EbtFloat : EbtInt; + if (rightType.getBasicType() != requiredBasicType) + { + const TType *clampType = useFloatClamp ? StaticType::GetBasic() + : StaticType::GetBasic(); + TIntermSequence constructorArgs = {index}; + index = TIntermAggregate::CreateConstructor(*clampType, &constructorArgs); + } + + // min(gl_PointSize, maxPointSize) + TIntermSequence args; + args.push_back(index); + args.push_back(zero); + args.push_back(max); + TIntermTyped *clamped = + CreateBuiltInFunctionCallNode("clamp", &args, *mSymbolTable, useFloatClamp ? 100 : 300); + + // Cast back to int if float clamp was used. + if (useFloatClamp) + { + TIntermSequence constructorArgs = {clamped}; + clamped = TIntermAggregate::CreateConstructor(*StaticType::GetBasic(), + &constructorArgs); + } + + // Replace the right node (the index) with the clamped result. + queueReplacementWithParent(node, node->getRight(), clamped, OriginalNode::IS_DROPPED); + + // Don't recurse as left and right nodes are already processed. + return false; + } + + private: + TIntermConstantUnion *createClampValue(int value, bool useFloat) + { + if (useFloat) + { + return CreateFloatNode(static_cast(value), EbpHigh); + } + return CreateIndexNode(value); + } + + TCompiler *mCompiler; +}; +} // anonymous namespace + +bool ClampIndirectIndices(TCompiler *compiler, TIntermNode *root, TSymbolTable *symbolTable) +{ + ClampIndirectIndicesTraverser traverser(compiler, symbolTable); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampIndirectIndices.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampIndirectIndices.h new file mode 100644 index 0000000000..eebbab02e6 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampIndirectIndices.h @@ -0,0 +1,27 @@ +// +// Copyright 2021 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ClampIndirectIndices.h: Add clamp to the indirect indices used on arrays. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_CLAMPINDIRECTINDICES_H_ +#define COMPILER_TRANSLATOR_TREEOPS_CLAMPINDIRECTINDICES_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermNode; +class TSymbolTable; + +[[nodiscard]] bool ClampIndirectIndices(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_CLAMPINDIRECTINDICES_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampPointSize.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampPointSize.cpp new file mode 100644 index 0000000000..db006989e9 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampPointSize.cpp @@ -0,0 +1,52 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ClampPointSize.cpp: Limit the value that is written to gl_PointSize. +// + +#include "compiler/translator/tree_ops/ClampPointSize.h" + +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/BuiltIn.h" +#include "compiler/translator/tree_util/FindSymbolNode.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/RunAtTheEndOfShader.h" + +namespace sh +{ + +bool ClampPointSize(TCompiler *compiler, + TIntermBlock *root, + float maxPointSize, + TSymbolTable *symbolTable) +{ + // Only clamp gl_PointSize if it's used in the shader. + const TIntermSymbol *glPointSize = FindSymbolNode(root, ImmutableString("gl_PointSize")); + if (glPointSize == nullptr) + { + return true; + } + + TIntermTyped *pointSizeNode = glPointSize->deepCopy(); + + TConstantUnion *maxPointSizeConstant = new TConstantUnion(); + maxPointSizeConstant->setFConst(maxPointSize); + TIntermConstantUnion *maxPointSizeNode = + new TIntermConstantUnion(maxPointSizeConstant, TType(EbtFloat, EbpHigh, EvqConst)); + + // min(gl_PointSize, maxPointSize) + TIntermSequence minArguments; + minArguments.push_back(pointSizeNode->deepCopy()); + minArguments.push_back(maxPointSizeNode); + TIntermTyped *clampedPointSize = + CreateBuiltInFunctionCallNode("min", &minArguments, *symbolTable, 100); + + // gl_PointSize = min(gl_PointSize, maxPointSize) + TIntermBinary *assignPointSize = new TIntermBinary(EOpAssign, pointSizeNode, clampedPointSize); + + return RunAtTheEndOfShader(compiler, root, assignPointSize, symbolTable); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampPointSize.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampPointSize.h new file mode 100644 index 0000000000..c42f32bde2 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampPointSize.h @@ -0,0 +1,28 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ClampPointSize.h: Limit the value that is written to gl_PointSize. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_CLAMPPOINTSIZE_H_ +#define COMPILER_TRANSLATOR_TREEOPS_CLAMPPOINTSIZE_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool ClampPointSize(TCompiler *compiler, + TIntermBlock *root, + float maxPointSize, + TSymbolTable *symbolTable); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_CLAMPPOINTSIZE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/ConvertUnsupportedConstructorsToFunctionCalls.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/ConvertUnsupportedConstructorsToFunctionCalls.cpp new file mode 100644 index 0000000000..5c45e1fb59 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/ConvertUnsupportedConstructorsToFunctionCalls.cpp @@ -0,0 +1,335 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/tree_ops/ConvertUnsupportedConstructorsToFunctionCalls.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/tree_util/FindFunction.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermRebuild.h" + +using namespace sh; + +namespace +{ + +void AppendMatrixElementArgument(TIntermSymbol *parameter, + int colIndex, + int rowIndex, + TIntermSequence *returnCtorArgs) +{ + TIntermBinary *matColN = + new TIntermBinary(EOpIndexDirect, parameter->deepCopy(), CreateIndexNode(colIndex)); + TIntermSwizzle *matElem = new TIntermSwizzle(matColN, {rowIndex}); + returnCtorArgs->push_back(matElem); +} + +// Adds the argument to sequence for a scalar constructor. +// Given scalar(scalarA) appends scalarA +// Given scalar(vecA) appends vecA.x +// Given scalar(matA) appends matA[0].x +void AppendScalarFromNonScalarArguments(TFunction &function, TIntermSequence *returnCtorArgs) +{ + const TVariable *var = function.getParam(0); + TIntermSymbol *arg0 = new TIntermSymbol(var); + + const TType &type = arg0->getType(); + + if (type.isScalar()) + { + returnCtorArgs->push_back(arg0); + } + else if (type.isVector()) + { + TIntermSwizzle *vecX = new TIntermSwizzle(arg0, {0}); + returnCtorArgs->push_back(vecX); + } + else if (type.isMatrix()) + { + AppendMatrixElementArgument(arg0, 0, 0, returnCtorArgs); + } +} + +// Adds the arguments to sequence for a vector constructor from a scalar. +// Given vecN(scalarA) appends scalarA, scalarA, ... n times +void AppendVectorFromScalarArgument(const TType &type, + TFunction &function, + TIntermSequence *returnCtorArgs) +{ + const uint8_t vectorSize = type.getNominalSize(); + const TVariable *var = function.getParam(0); + TIntermSymbol *v = new TIntermSymbol(var); + for (uint8_t i = 0; i < vectorSize; ++i) + { + returnCtorArgs->push_back(v->deepCopy()); + } +} + +// Adds the arguments to sequence for a vector or matrix constructor from the available arguments +// applying arguments in order until the requested number of values have been extracted from the +// given arguments or until there are no more arguments. +void AppendValuesFromMultipleArguments(int numValuesNeeded, + TFunction &function, + TIntermSequence *returnCtorArgs) +{ + size_t numParameters = function.getParamCount(); + size_t paramIndex = 0; + uint8_t colIndex = 0; + uint8_t rowIndex = 0; + + for (int i = 0; i < numValuesNeeded && paramIndex < numParameters; ++i) + { + const TVariable *p = function.getParam(paramIndex); + TIntermSymbol *parameter = new TIntermSymbol(p); + if (parameter->isScalar()) + { + returnCtorArgs->push_back(parameter); + ++paramIndex; + } + else if (parameter->isVector()) + { + TIntermSwizzle *vecS = new TIntermSwizzle(parameter->deepCopy(), {rowIndex++}); + returnCtorArgs->push_back(vecS); + if (rowIndex == parameter->getNominalSize()) + { + ++paramIndex; + rowIndex = 0; + } + } + else if (parameter->isMatrix()) + { + AppendMatrixElementArgument(parameter, colIndex, rowIndex++, returnCtorArgs); + if (rowIndex == parameter->getSecondarySize()) + { + rowIndex = 0; + ++colIndex; + if (colIndex == parameter->getNominalSize()) + { + colIndex = 0; + ++paramIndex; + } + } + } + } +} + +// Adds the arguments for a matrix constructor from a scalar +// putting the scalar along the diagonal and 0 everywhere else. +void AppendMatrixFromScalarArgument(const TType &type, + TFunction &function, + TIntermSequence *returnCtorArgs) +{ + const TVariable *var = function.getParam(0); + TIntermSymbol *v = new TIntermSymbol(var); + const uint8_t numCols = type.getNominalSize(); + const uint8_t numRows = type.getSecondarySize(); + for (uint8_t col = 0; col < numCols; ++col) + { + for (uint8_t row = 0; row < numRows; ++row) + { + if (col == row) + { + returnCtorArgs->push_back(v->deepCopy()); + } + else + { + returnCtorArgs->push_back(CreateFloatNode(0.0f, sh::EbpUndefined)); + } + } + } +} + +// Add the argument for a matrix constructor from a matrix +// copying elements from the same column/row and otherwise +// initialize to the identity matrix. +void AppendMatrixFromMatrixArgument(const TType &type, + TFunction &function, + TIntermSequence *returnCtorArgs) +{ + const TVariable *var = function.getParam(0); + TIntermSymbol *v = new TIntermSymbol(var); + const uint8_t dstCols = type.getNominalSize(); + const uint8_t dstRows = type.getSecondarySize(); + const uint8_t srcCols = v->getNominalSize(); + const uint8_t srcRows = v->getSecondarySize(); + for (uint8_t dstCol = 0; dstCol < dstCols; ++dstCol) + { + for (uint8_t dstRow = 0; dstRow < dstRows; ++dstRow) + { + if (dstRow < srcRows && dstCol < srcCols) + { + AppendMatrixElementArgument(v, dstCol, dstRow, returnCtorArgs); + } + else + { + returnCtorArgs->push_back( + CreateFloatNode(dstRow == dstCol ? 1.0f : 0.0f, sh::EbpUndefined)); + } + } + } +} + +class Rebuild : public TIntermRebuild +{ + public: + explicit Rebuild(TCompiler &compiler) : TIntermRebuild(compiler, false, true) {} + PostResult visitAggregatePost(TIntermAggregate &node) override + { + if (!node.isConstructor()) + { + return node; + } + + TIntermSequence &arguments = *node.getSequence(); + if (arguments.empty()) + { + return node; + } + + const TType &type = node.getType(); + const TType &arg0Type = arguments[0]->getAsTyped()->getType(); + + if (!type.isScalar() && !type.isVector() && !type.isMatrix()) + { + return node; + } + + if (type.isArray()) + { + return node; + } + + // check for type_ctor(sameType) + // scalar(scalar) -> passthrough + // vecN(vecN) -> passthrough + // matN(matN) -> passthrough + if (arguments.size() == 1 && arg0Type == type) + { + return node; + } + + // The following are simple casts: + // + // - basic(s) (where basic is int, uint, float or bool, and s is scalar). + // - gvecN(vN) (where the argument is a single vector with the same number of components). + // - matNxM(mNxM) (where the argument is a single matrix with the same dimensions). Note + // that + // matrices are always float, so there's no actual cast and this would be a no-op. + // + const bool isSingleScalarCast = + arguments.size() == 1 && type.isScalar() && arg0Type.isScalar(); + const bool isSingleVectorCast = arguments.size() == 1 && type.isVector() && + arg0Type.isVector() && + type.getNominalSize() == arg0Type.getNominalSize(); + const bool isSingleMatrixCast = + arguments.size() == 1 && type.isMatrix() && arg0Type.isMatrix() && + type.getCols() == arg0Type.getCols() && type.getRows() == arg0Type.getRows(); + if (isSingleScalarCast || isSingleVectorCast || isSingleMatrixCast) + { + return node; + } + + // Cases we need to handle: + // scalar(vec) + // scalar(mat) + // vecN(scalar) + // vecN(vecM) + // vecN(a,...) + // matN(scalar) -> diag + // matN(vec) -> fail! + // manN(matM) -> corner + ident + // matN(a, ...) + + // Build a function and pass all the constructor's arguments to it. + TIntermBlock *body = new TIntermBlock; + TFunction *function = new TFunction(&mSymbolTable, ImmutableString(""), + SymbolType::AngleInternal, &type, true); + + for (size_t i = 0; i < arguments.size(); ++i) + { + TIntermTyped &arg = *arguments[i]->getAsTyped(); + TType *argType = new TType(arg.getBasicType(), arg.getPrecision(), EvqParamIn, + arg.getNominalSize(), arg.getSecondarySize()); + TVariable *var = CreateTempVariable(&mSymbolTable, argType); + function->addParameter(var); + } + + // Build a return statement for the function that + // converts the arguments into the required type. + TIntermSequence *returnCtorArgs = new TIntermSequence(); + + if (type.isScalar()) + { + AppendScalarFromNonScalarArguments(*function, returnCtorArgs); + } + else if (type.isVector()) + { + if (arguments.size() == 1 && arg0Type.isScalar()) + { + AppendVectorFromScalarArgument(type, *function, returnCtorArgs); + } + else + { + AppendValuesFromMultipleArguments(type.getNominalSize(), *function, returnCtorArgs); + } + } + else if (type.isMatrix()) + { + if (arguments.size() == 1 && arg0Type.isScalar()) + { + // MSL already handles this case + AppendMatrixFromScalarArgument(type, *function, returnCtorArgs); + } + else if (arg0Type.isMatrix()) + { + AppendMatrixFromMatrixArgument(type, *function, returnCtorArgs); + } + else + { + AppendValuesFromMultipleArguments(type.getNominalSize() * type.getSecondarySize(), + *function, returnCtorArgs); + } + } + + TIntermBranch *returnStatement = + new TIntermBranch(EOpReturn, TIntermAggregate::CreateConstructor(type, returnCtorArgs)); + body->appendStatement(returnStatement); + + TIntermFunctionDefinition *functionDefinition = + CreateInternalFunctionDefinitionNode(*function, body); + mFunctionDefs.push_back(functionDefinition); + + TIntermTyped *functionCall = TIntermAggregate::CreateFunctionCall(*function, &arguments); + + return *functionCall; + } + + bool rewrite(TIntermBlock &root) + { + if (!rebuildInPlace(root)) + { + return true; + } + + size_t firstFunctionIndex = FindFirstFunctionDefinitionIndex(&root); + for (TIntermFunctionDefinition *functionDefinition : mFunctionDefs) + { + root.insertChildNodes(firstFunctionIndex, TIntermSequence({functionDefinition})); + } + + return mCompiler.validateAST(&root); + } + + private: + TVector mFunctionDefs; +}; + +} // anonymous namespace + +bool sh::ConvertUnsupportedConstructorsToFunctionCalls(TCompiler &compiler, TIntermBlock &root) +{ + return Rebuild(compiler).rewrite(root); +} diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/ConvertUnsupportedConstructorsToFunctionCalls.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/ConvertUnsupportedConstructorsToFunctionCalls.h new file mode 100644 index 0000000000..720a02c9a6 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/ConvertUnsupportedConstructorsToFunctionCalls.h @@ -0,0 +1,25 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TREE_OPS_CONVERTUNSUPPORTEDCONSTRUCTORSTOFUNCTIONCALLS_H_ +#define COMPILER_TRANSLATOR_TREE_OPS_CONVERTUNSUPPORTEDCONSTRUCTORSTOFUNCTIONCALLS_H_ + +#include "compiler/translator/Compiler.h" + +namespace sh +{ + +class TCompiler; +class TInterBlock; +class SymbolEnv; + +// Adds explicit type casts into the AST where casting is done implicitly. +[[nodiscard]] bool ConvertUnsupportedConstructorsToFunctionCalls(TCompiler &compiler, + TIntermBlock &root); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREE_OPS_CONVERTUNSUPPORTEDCONSTRUCTORSTOFUNCTIONCALLS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.cpp new file mode 100644 index 0000000000..8c2925949d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.cpp @@ -0,0 +1,196 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Applies the necessary AST transformations to support multiview rendering through instancing. +// Check the header file For more information. +// + +#include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_ops/InitializeVariables.h" +#include "compiler/translator/tree_util/BuiltIn.h" +#include "compiler/translator/tree_util/FindMain.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +constexpr const ImmutableString kViewIDVariableName("ViewID_OVR"); +constexpr const ImmutableString kInstanceIDVariableName("InstanceID"); +constexpr const ImmutableString kMultiviewBaseViewLayerIndexVariableName( + "multiviewBaseViewLayerIndex"); + +// Adds the InstanceID and ViewID_OVR initializers to the end of the initializers' sequence. +void InitializeViewIDAndInstanceID(const TVariable *viewID, + const TVariable *instanceID, + unsigned numberOfViews, + const TSymbolTable &symbolTable, + TIntermSequence *initializers) +{ + // Create an unsigned numberOfViews node. + TConstantUnion *numberOfViewsUnsignedConstant = new TConstantUnion(); + numberOfViewsUnsignedConstant->setUConst(numberOfViews); + TIntermConstantUnion *numberOfViewsUint = + new TIntermConstantUnion(numberOfViewsUnsignedConstant, TType(EbtUInt, EbpLow, EvqConst)); + + // Create a uint(gl_InstanceID) node. + TIntermSequence glInstanceIDSymbolCastArguments; + glInstanceIDSymbolCastArguments.push_back(new TIntermSymbol(BuiltInVariable::gl_InstanceID())); + TIntermAggregate *glInstanceIDAsUint = TIntermAggregate::CreateConstructor( + TType(EbtUInt, EbpHigh, EvqTemporary), &glInstanceIDSymbolCastArguments); + + // Create a uint(gl_InstanceID) / numberOfViews node. + TIntermBinary *normalizedInstanceID = + new TIntermBinary(EOpDiv, glInstanceIDAsUint, numberOfViewsUint); + + // Create an int(uint(gl_InstanceID) / numberOfViews) node. + TIntermSequence normalizedInstanceIDCastArguments; + normalizedInstanceIDCastArguments.push_back(normalizedInstanceID); + TIntermAggregate *normalizedInstanceIDAsInt = TIntermAggregate::CreateConstructor( + TType(EbtInt, EbpHigh, EvqTemporary), &normalizedInstanceIDCastArguments); + + // Create an InstanceID = int(uint(gl_InstanceID) / numberOfViews) node. + TIntermBinary *instanceIDInitializer = + new TIntermBinary(EOpAssign, new TIntermSymbol(instanceID), normalizedInstanceIDAsInt); + initializers->push_back(instanceIDInitializer); + + // Create a uint(gl_InstanceID) % numberOfViews node. + TIntermBinary *normalizedViewID = + new TIntermBinary(EOpIMod, glInstanceIDAsUint->deepCopy(), numberOfViewsUint->deepCopy()); + + // Create a ViewID_OVR = uint(gl_InstanceID) % numberOfViews node. + TIntermBinary *viewIDInitializer = + new TIntermBinary(EOpAssign, new TIntermSymbol(viewID), normalizedViewID); + initializers->push_back(viewIDInitializer); +} + +// Adds a branch to write int(ViewID_OVR) to either gl_ViewportIndex or gl_Layer. The branch is +// added to the end of the initializers' sequence. +void SelectViewIndexInVertexShader(const TVariable *viewID, + const TVariable *multiviewBaseViewLayerIndex, + TIntermSequence *initializers, + const TSymbolTable &symbolTable) +{ + // Create an int(ViewID_OVR) node. + TIntermSequence viewIDSymbolCastArguments; + viewIDSymbolCastArguments.push_back(new TIntermSymbol(viewID)); + TIntermAggregate *viewIDAsInt = TIntermAggregate::CreateConstructor( + TType(EbtInt, EbpHigh, EvqTemporary), &viewIDSymbolCastArguments); + + // Create a gl_ViewportIndex node. + TIntermSymbol *viewportIndexSymbol = new TIntermSymbol(BuiltInVariable::gl_ViewportIndex()); + + // Create a { gl_ViewportIndex = int(ViewID_OVR) } node. + TIntermBlock *viewportIndexInitializerInBlock = new TIntermBlock(); + viewportIndexInitializerInBlock->appendStatement( + new TIntermBinary(EOpAssign, viewportIndexSymbol, viewIDAsInt)); + + // Create a gl_Layer node. + TIntermSymbol *layerSymbol = new TIntermSymbol(BuiltInVariable::gl_LayerVS()); + + // Create an int(ViewID_OVR) + multiviewBaseViewLayerIndex node + TIntermBinary *sumOfViewIDAndBaseViewIndex = new TIntermBinary( + EOpAdd, viewIDAsInt->deepCopy(), new TIntermSymbol(multiviewBaseViewLayerIndex)); + + // Create a { gl_Layer = int(ViewID_OVR) + multiviewBaseViewLayerIndex } node. + TIntermBlock *layerInitializerInBlock = new TIntermBlock(); + layerInitializerInBlock->appendStatement( + new TIntermBinary(EOpAssign, layerSymbol, sumOfViewIDAndBaseViewIndex)); + + // Create a node to compare whether the base view index uniform is less than zero. + TIntermBinary *multiviewBaseViewLayerIndexZeroComparison = + new TIntermBinary(EOpLessThan, new TIntermSymbol(multiviewBaseViewLayerIndex), + CreateZeroNode(TType(EbtInt, EbpHigh, EvqConst))); + + // Create an if-else statement to select the code path. + TIntermIfElse *multiviewBranch = + new TIntermIfElse(multiviewBaseViewLayerIndexZeroComparison, + viewportIndexInitializerInBlock, layerInitializerInBlock); + + initializers->push_back(multiviewBranch); +} + +} // namespace + +bool DeclareAndInitBuiltinsForInstancedMultiview(TCompiler *compiler, + TIntermBlock *root, + unsigned numberOfViews, + GLenum shaderType, + const ShCompileOptions &compileOptions, + ShShaderOutput shaderOutput, + TSymbolTable *symbolTable) +{ + ASSERT(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER); + + TQualifier viewIDQualifier = (shaderType == GL_VERTEX_SHADER) ? EvqFlatOut : EvqFlatIn; + const TVariable *viewID = + new TVariable(symbolTable, kViewIDVariableName, + new TType(EbtUInt, EbpHigh, viewIDQualifier), SymbolType::AngleInternal); + + DeclareGlobalVariable(root, viewID); + if (!ReplaceVariable(compiler, root, BuiltInVariable::gl_ViewID_OVR(), viewID)) + { + return false; + } + if (shaderType == GL_VERTEX_SHADER) + { + // Replacing gl_InstanceID with InstanceID should happen before adding the initializers of + // InstanceID and ViewID. + const TType *instanceIDVariableType = StaticType::Get(); + const TVariable *instanceID = + new TVariable(symbolTable, kInstanceIDVariableName, instanceIDVariableType, + SymbolType::AngleInternal); + DeclareGlobalVariable(root, instanceID); + if (!ReplaceVariable(compiler, root, BuiltInVariable::gl_InstanceID(), instanceID)) + { + return false; + } + + TIntermSequence initializers; + InitializeViewIDAndInstanceID(viewID, instanceID, numberOfViews, *symbolTable, + &initializers); + + // The AST transformation which adds the expression to select the viewport index should + // be done only for the GLSL and ESSL output. + const bool selectView = compileOptions.selectViewInNvGLSLVertexShader; + // Assert that if the view is selected in the vertex shader, then the output is + // either GLSL or ESSL. + ASSERT(!selectView || IsOutputGLSL(shaderOutput) || IsOutputESSL(shaderOutput)); + if (selectView) + { + // Add a uniform to switch between side-by-side and layered rendering. + const TType *baseLayerIndexVariableType = + StaticType::Get(); + const TVariable *multiviewBaseViewLayerIndex = + new TVariable(symbolTable, kMultiviewBaseViewLayerIndexVariableName, + baseLayerIndexVariableType, SymbolType::AngleInternal); + DeclareGlobalVariable(root, multiviewBaseViewLayerIndex); + + // Setting a value to gl_ViewportIndex or gl_Layer should happen after ViewID_OVR's + // initialization. + SelectViewIndexInVertexShader(viewID, multiviewBaseViewLayerIndex, &initializers, + *symbolTable); + } + + // Insert initializers at the beginning of main(). + TIntermBlock *initializersBlock = new TIntermBlock(); + initializersBlock->getSequence()->swap(initializers); + TIntermBlock *mainBody = FindMainBody(root); + mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initializersBlock); + } + + return compiler->validateAST(root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h new file mode 100644 index 0000000000..49a964d234 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h @@ -0,0 +1,52 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Regardless of the shader type, the following AST transformations are applied: +// - Add declaration of View_ID_OVR. +// - Replace every occurrence of gl_ViewID_OVR with ViewID_OVR, mark ViewID_OVR as internal and +// declare it as a flat varying. +// +// If the shader type is a vertex shader, the following AST transformations are applied: +// - Replace every occurrence of gl_InstanceID with InstanceID, mark InstanceID as internal and set +// its qualifier to EvqTemporary. +// - Add initializers of ViewID_OVR and InstanceID to the beginning of the body of main. The pass +// should be executed before any variables get collected so that usage of gl_InstanceID is recorded. +// - If the output is ESSL or GLSL and the selectViewInNvGLSLVertexShader option is +// enabled, the expression +// "if (multiviewBaseViewLayerIndex < 0) { +// gl_ViewportIndex = int(ViewID_OVR); +// } else { +// gl_Layer = int(ViewID_OVR) + multiviewBaseViewLayerIndex; +// }" +// is added after ViewID and InstanceID are initialized. Also, MultiviewRenderPath is added as a +// uniform. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_ +#define COMPILER_TRANSLATOR_TREEOPS_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_ + +#include "GLSLANG/ShaderLang.h" +#include "angle_gl.h" +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool DeclareAndInitBuiltinsForInstancedMultiview( + TCompiler *compiler, + TIntermBlock *root, + unsigned numberOfViews, + GLenum shaderType, + const ShCompileOptions &compileOptions, + ShShaderOutput shaderOutput, + TSymbolTable *symbolTable); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp new file mode 100644 index 0000000000..035de73431 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp @@ -0,0 +1,180 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// DeferGlobalInitializers is an AST traverser that moves global initializers into a separate +// function that is called in the beginning of main(). This enables initialization of globals with +// uniforms or non-constant globals, as allowed by the WebGL spec. Some initializers referencing +// non-constants may need to be unfolded into if statements in HLSL - this kind of steps should be +// done after DeferGlobalInitializers is run. Note that it's important that the function definition +// is at the end of the shader, as some globals may be declared after main(). +// +// It can also initialize all uninitialized globals. +// + +#include "compiler/translator/tree_ops/DeferGlobalInitializers.h" + +#include + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_ops/InitializeVariables.h" +#include "compiler/translator/tree_util/FindMain.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" + +namespace sh +{ + +namespace +{ + +constexpr const ImmutableString kInitGlobalsString("initGlobals"); + +void GetDeferredInitializers(TIntermDeclaration *declaration, + bool initializeUninitializedGlobals, + bool canUseLoopsToInitialize, + bool highPrecisionSupported, + bool forceDeferGlobalInitializers, + TIntermSequence *deferredInitializersOut, + std::vector *variablesToReplaceOut, + TSymbolTable *symbolTable) +{ + // SeparateDeclarations should have already been run. + ASSERT(declaration->getSequence()->size() == 1); + + TIntermNode *declarator = declaration->getSequence()->back(); + TIntermBinary *init = declarator->getAsBinaryNode(); + if (init) + { + TIntermSymbol *symbolNode = init->getLeft()->getAsSymbolNode(); + ASSERT(symbolNode); + TIntermTyped *expression = init->getRight(); + + if (expression->getQualifier() != EvqConst || !expression->hasConstantValue() || + forceDeferGlobalInitializers) + { + // For variables which are not constant, defer their real initialization until + // after we initialize uniforms. + // Deferral is done also in any cases where the variable can not be converted to a + // constant union, since otherwise there's a chance that HLSL output will generate extra + // statements from the initializer expression. + + // Change const global to a regular global if its initialization is deferred. + // This can happen if ANGLE has not been able to fold the constant expression used + // as an initializer. + ASSERT(symbolNode->getQualifier() == EvqConst || + symbolNode->getQualifier() == EvqGlobal); + if (symbolNode->getQualifier() == EvqConst) + { + variablesToReplaceOut->push_back(&symbolNode->variable()); + } + + TIntermBinary *deferredInit = + new TIntermBinary(EOpAssign, symbolNode->deepCopy(), init->getRight()); + deferredInitializersOut->push_back(deferredInit); + + // Remove the initializer from the global scope and just declare the global instead. + declaration->replaceChildNode(init, symbolNode); + } + } + else if (initializeUninitializedGlobals) + { + TIntermSymbol *symbolNode = declarator->getAsSymbolNode(); + ASSERT(symbolNode); + + // Ignore ANGLE internal variables and nameless declarations. + if (symbolNode->variable().symbolType() == SymbolType::AngleInternal || + symbolNode->variable().symbolType() == SymbolType::Empty) + return; + + if (symbolNode->getQualifier() == EvqGlobal) + { + TIntermSequence initCode; + CreateInitCode(symbolNode, canUseLoopsToInitialize, highPrecisionSupported, &initCode, + symbolTable); + deferredInitializersOut->insert(deferredInitializersOut->end(), initCode.begin(), + initCode.end()); + } + } +} + +void InsertInitCallToMain(TIntermBlock *root, + TIntermSequence *deferredInitializers, + TSymbolTable *symbolTable) +{ + TIntermBlock *initGlobalsBlock = new TIntermBlock(); + initGlobalsBlock->getSequence()->swap(*deferredInitializers); + + TFunction *initGlobalsFunction = + new TFunction(symbolTable, kInitGlobalsString, SymbolType::AngleInternal, + StaticType::GetBasic(), false); + + TIntermFunctionPrototype *initGlobalsFunctionPrototype = + CreateInternalFunctionPrototypeNode(*initGlobalsFunction); + root->getSequence()->insert(root->getSequence()->begin(), initGlobalsFunctionPrototype); + TIntermFunctionDefinition *initGlobalsFunctionDefinition = + CreateInternalFunctionDefinitionNode(*initGlobalsFunction, initGlobalsBlock); + root->appendStatement(initGlobalsFunctionDefinition); + + TIntermSequence emptySequence; + TIntermAggregate *initGlobalsCall = + TIntermAggregate::CreateFunctionCall(*initGlobalsFunction, &emptySequence); + + TIntermBlock *mainBody = FindMainBody(root); + mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initGlobalsCall); +} + +} // namespace + +bool DeferGlobalInitializers(TCompiler *compiler, + TIntermBlock *root, + bool initializeUninitializedGlobals, + bool canUseLoopsToInitialize, + bool highPrecisionSupported, + bool forceDeferGlobalInitializers, + TSymbolTable *symbolTable) +{ + TIntermSequence deferredInitializers; + std::vector variablesToReplace; + + // Loop over all global statements and process the declarations. This is simpler than using a + // traverser. + for (TIntermNode *statement : *root->getSequence()) + { + TIntermDeclaration *declaration = statement->getAsDeclarationNode(); + if (declaration) + { + GetDeferredInitializers(declaration, initializeUninitializedGlobals, + canUseLoopsToInitialize, highPrecisionSupported, + forceDeferGlobalInitializers, &deferredInitializers, + &variablesToReplace, symbolTable); + } + } + + // Add the function with initialization and the call to that. + if (!deferredInitializers.empty()) + { + InsertInitCallToMain(root, &deferredInitializers, symbolTable); + } + + // Replace constant variables with non-constant global variables. + for (const TVariable *var : variablesToReplace) + { + TType *replacementType = new TType(var->getType()); + replacementType->setQualifier(EvqGlobal); + TVariable *replacement = + new TVariable(symbolTable, var->name(), replacementType, var->symbolType()); + if (!ReplaceVariable(compiler, root, var, replacement)) + { + return false; + } + } + + return true; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/DeferGlobalInitializers.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/DeferGlobalInitializers.h new file mode 100644 index 0000000000..58a38a982b --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/DeferGlobalInitializers.h @@ -0,0 +1,38 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// DeferGlobalInitializers is an AST traverser that moves global initializers into a separate +// function that is called in the beginning of main(). This enables initialization of globals with +// uniforms or non-constant globals, as allowed by the WebGL spec. Some initializers referencing +// non-constants may need to be unfolded into if statements in HLSL - this kind of steps should be +// done after DeferGlobalInitializers is run. Note that it's important that the function definition +// is at the end of the shader, as some globals may be declared after main(). +// +// It can also initialize all uninitialized globals. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_DEFERGLOBALINITIALIZERS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_DEFERGLOBALINITIALIZERS_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool DeferGlobalInitializers(TCompiler *compiler, + TIntermBlock *root, + bool initializeUninitializedGlobals, + bool canUseLoopsToInitialize, + bool highPrecisionSupported, + bool forceDeferGlobalInitializers, + TSymbolTable *symbolTable); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_DEFERGLOBALINITIALIZERS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.cpp new file mode 100644 index 0000000000..25e1fde29a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.cpp @@ -0,0 +1,142 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// gl_FragColor needs to broadcast to all color buffers in ES2 if +// GL_EXT_draw_buffers is explicitly enabled in a fragment shader. +// +// We emulate this by replacing all gl_FragColor with gl_FragData[0], and in the end +// of main() function, assigning gl_FragData[1], ..., gl_FragData[maxDrawBuffers-1] +// with gl_FragData[0]. +// + +#include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/RunAtTheEndOfShader.h" + +namespace sh +{ + +namespace +{ + +constexpr const ImmutableString kGlFragDataString("gl_FragData"); + +class GLFragColorBroadcastTraverser : public TIntermTraverser +{ + public: + GLFragColorBroadcastTraverser(int maxDrawBuffers, TSymbolTable *symbolTable, int shaderVersion) + : TIntermTraverser(true, false, false, symbolTable), + mGLFragColorUsed(false), + mMaxDrawBuffers(maxDrawBuffers), + mShaderVersion(shaderVersion) + {} + + [[nodiscard]] bool broadcastGLFragColor(TCompiler *compiler, TIntermBlock *root); + + bool isGLFragColorUsed() const { return mGLFragColorUsed; } + + protected: + void visitSymbol(TIntermSymbol *node) override; + + TIntermBinary *constructGLFragDataNode(int index) const; + TIntermBinary *constructGLFragDataAssignNode(int index) const; + + private: + bool mGLFragColorUsed; + int mMaxDrawBuffers; + const int mShaderVersion; +}; + +TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataNode(int index) const +{ + TIntermSymbol *symbol = + ReferenceBuiltInVariable(kGlFragDataString, *mSymbolTable, mShaderVersion); + TIntermTyped *indexNode = CreateIndexNode(index); + + TIntermBinary *binary = new TIntermBinary(EOpIndexDirect, symbol, indexNode); + return binary; +} + +TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataAssignNode(int index) const +{ + TIntermTyped *fragDataIndex = constructGLFragDataNode(index); + TIntermTyped *fragDataZero = constructGLFragDataNode(0); + + return new TIntermBinary(EOpAssign, fragDataIndex, fragDataZero); +} + +void GLFragColorBroadcastTraverser::visitSymbol(TIntermSymbol *node) +{ + if (node->variable().symbolType() == SymbolType::BuiltIn && node->getName() == "gl_FragColor") + { + queueReplacement(constructGLFragDataNode(0), OriginalNode::IS_DROPPED); + mGLFragColorUsed = true; + } +} + +bool GLFragColorBroadcastTraverser::broadcastGLFragColor(TCompiler *compiler, TIntermBlock *root) +{ + ASSERT(mMaxDrawBuffers > 1); + if (!mGLFragColorUsed) + { + return true; + } + + TIntermBlock *broadcastBlock = new TIntermBlock(); + // Now insert statements + // gl_FragData[1] = gl_FragData[0]; + // ... + // gl_FragData[maxDrawBuffers - 1] = gl_FragData[0]; + for (int colorIndex = 1; colorIndex < mMaxDrawBuffers; ++colorIndex) + { + broadcastBlock->appendStatement(constructGLFragDataAssignNode(colorIndex)); + } + return RunAtTheEndOfShader(compiler, root, broadcastBlock, mSymbolTable); +} + +} // namespace + +bool EmulateGLFragColorBroadcast(TCompiler *compiler, + TIntermBlock *root, + int maxDrawBuffers, + std::vector *outputVariables, + TSymbolTable *symbolTable, + int shaderVersion) +{ + ASSERT(maxDrawBuffers > 1); + GLFragColorBroadcastTraverser traverser(maxDrawBuffers, symbolTable, shaderVersion); + root->traverse(&traverser); + if (traverser.isGLFragColorUsed()) + { + if (!traverser.updateTree(compiler, root)) + { + return false; + } + if (!traverser.broadcastGLFragColor(compiler, root)) + { + return false; + } + + for (auto &var : *outputVariables) + { + if (var.name == "gl_FragColor") + { + // TODO(zmo): Find a way to keep the original variable information. + var.name = "gl_FragData"; + var.mappedName = "gl_FragData"; + var.arraySizes.push_back(maxDrawBuffers); + ASSERT(var.arraySizes.size() == 1u); + } + } + } + + return true; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h new file mode 100644 index 0000000000..c71ba7c2be --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h @@ -0,0 +1,35 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Emulate gl_FragColor broadcast behaviors in ES2 where +// GL_EXT_draw_buffers is explicitly enabled in a fragment shader. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_EMULATEGLFRAGCOLORBROADCAST_H_ +#define COMPILER_TRANSLATOR_TREEOPS_EMULATEGLFRAGCOLORBROADCAST_H_ + +#include + +#include "common/angleutils.h" + +namespace sh +{ +struct ShaderVariable; +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +// Replace all gl_FragColor with gl_FragData[0], and in the end of main() function, +// assign gl_FragData[1] ... gl_FragData[maxDrawBuffers - 1] with gl_FragData[0]. +// If gl_FragColor is in outputVariables, it is replaced by gl_FragData. +[[nodiscard]] bool EmulateGLFragColorBroadcast(TCompiler *compiler, + TIntermBlock *root, + int maxDrawBuffers, + std::vector *outputVariables, + TSymbolTable *symbolTable, + int shaderVersion); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_EMULATEGLFRAGCOLORBROADCAST_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp new file mode 100644 index 0000000000..dfa36ad145 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp @@ -0,0 +1,274 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// EmulateGLDrawID is an AST traverser to convert the gl_DrawID builtin +// to a uniform int +// +// EmulateGLBaseVertex is an AST traverser to convert the gl_BaseVertex builtin +// to a uniform int +// +// EmulateGLBaseInstance is an AST traverser to convert the gl_BaseInstance builtin +// to a uniform int +// + +#include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h" + +#include "angle_gl.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/BuiltIn.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +constexpr const ImmutableString kEmulatedGLDrawIDName("angle_DrawID"); + +class FindGLDrawIDTraverser : public TIntermTraverser +{ + public: + FindGLDrawIDTraverser() : TIntermTraverser(true, false, false), mVariable(nullptr) {} + + const TVariable *getGLDrawIDBuiltinVariable() { return mVariable; } + + protected: + void visitSymbol(TIntermSymbol *node) override + { + if (&node->variable() == BuiltInVariable::gl_DrawID()) + { + mVariable = &node->variable(); + } + } + + private: + const TVariable *mVariable; +}; + +class AddBaseVertexToGLVertexIDTraverser : public TIntermTraverser +{ + public: + AddBaseVertexToGLVertexIDTraverser() : TIntermTraverser(true, false, false) {} + + protected: + void visitSymbol(TIntermSymbol *node) override + { + if (&node->variable() == BuiltInVariable::gl_VertexID()) + { + + TIntermSymbol *baseVertexRef = new TIntermSymbol(BuiltInVariable::gl_BaseVertex()); + + TIntermBinary *addBaseVertex = new TIntermBinary(EOpAdd, node, baseVertexRef); + queueReplacement(addBaseVertex, OriginalNode::BECOMES_CHILD); + } + } +}; + +constexpr const ImmutableString kEmulatedGLBaseVertexName("angle_BaseVertex"); + +class FindGLBaseVertexTraverser : public TIntermTraverser +{ + public: + FindGLBaseVertexTraverser() : TIntermTraverser(true, false, false), mVariable(nullptr) {} + + const TVariable *getGLBaseVertexBuiltinVariable() { return mVariable; } + + protected: + void visitSymbol(TIntermSymbol *node) override + { + if (&node->variable() == BuiltInVariable::gl_BaseVertex()) + { + mVariable = &node->variable(); + } + } + + private: + const TVariable *mVariable; +}; + +constexpr const ImmutableString kEmulatedGLBaseInstanceName("angle_BaseInstance"); + +class FindGLBaseInstanceTraverser : public TIntermTraverser +{ + public: + FindGLBaseInstanceTraverser() : TIntermTraverser(true, false, false), mVariable(nullptr) {} + + const TVariable *getGLBaseInstanceBuiltinVariable() { return mVariable; } + + protected: + void visitSymbol(TIntermSymbol *node) override + { + if (&node->variable() == BuiltInVariable::gl_BaseInstance()) + { + mVariable = &node->variable(); + } + } + + private: + const TVariable *mVariable; +}; + +} // namespace + +bool EmulateGLDrawID(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + std::vector *uniforms, + bool shouldCollect) +{ + FindGLDrawIDTraverser traverser; + root->traverse(&traverser); + const TVariable *builtInVariable = traverser.getGLDrawIDBuiltinVariable(); + if (builtInVariable) + { + const TType *type = StaticType::Get(); + const TVariable *drawID = + new TVariable(symbolTable, kEmulatedGLDrawIDName, type, SymbolType::AngleInternal); + const TIntermSymbol *drawIDSymbol = new TIntermSymbol(drawID); + + // AngleInternal variables don't get collected + if (shouldCollect) + { + ShaderVariable uniform; + uniform.name = kEmulatedGLDrawIDName.data(); + uniform.mappedName = kEmulatedGLDrawIDName.data(); + uniform.type = GLVariableType(*type); + uniform.precision = GLVariablePrecision(*type); + uniform.staticUse = symbolTable->isStaticallyUsed(*builtInVariable); + uniform.active = true; + uniform.binding = type->getLayoutQualifier().binding; + uniform.location = type->getLayoutQualifier().location; + uniform.offset = type->getLayoutQualifier().offset; + uniform.rasterOrdered = type->getLayoutQualifier().rasterOrdered; + uniform.readonly = type->getMemoryQualifier().readonly; + uniform.writeonly = type->getMemoryQualifier().writeonly; + uniforms->push_back(uniform); + } + + DeclareGlobalVariable(root, drawID); + if (!ReplaceVariableWithTyped(compiler, root, builtInVariable, drawIDSymbol)) + { + return false; + } + } + + return true; +} + +bool EmulateGLBaseVertexBaseInstance(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + std::vector *uniforms, + bool shouldCollect, + bool addBaseVertexToVertexID) +{ + bool addBaseVertex = false, addBaseInstance = false; + ShaderVariable uniformBaseVertex, uniformBaseInstance; + + if (addBaseVertexToVertexID) + { + // This is a workaround for Mac AMD GPU + // Replace gl_VertexID with (gl_VertexID + gl_BaseVertex) + AddBaseVertexToGLVertexIDTraverser traverserVertexID; + root->traverse(&traverserVertexID); + if (!traverserVertexID.updateTree(compiler, root)) + { + return false; + } + } + + FindGLBaseVertexTraverser traverserBaseVertex; + root->traverse(&traverserBaseVertex); + const TVariable *builtInVariableBaseVertex = + traverserBaseVertex.getGLBaseVertexBuiltinVariable(); + + if (builtInVariableBaseVertex) + { + const TVariable *baseVertex = BuiltInVariable::angle_BaseVertex(); + const TType &type = baseVertex->getType(); + const TIntermSymbol *baseVertexSymbol = new TIntermSymbol(baseVertex); + + // AngleInternal variables don't get collected + if (shouldCollect) + { + uniformBaseVertex.name = kEmulatedGLBaseVertexName.data(); + uniformBaseVertex.mappedName = kEmulatedGLBaseVertexName.data(); + uniformBaseVertex.type = GLVariableType(type); + uniformBaseVertex.precision = GLVariablePrecision(type); + uniformBaseVertex.staticUse = symbolTable->isStaticallyUsed(*builtInVariableBaseVertex); + uniformBaseVertex.active = true; + uniformBaseVertex.binding = type.getLayoutQualifier().binding; + uniformBaseVertex.location = type.getLayoutQualifier().location; + uniformBaseVertex.offset = type.getLayoutQualifier().offset; + uniformBaseVertex.rasterOrdered = type.getLayoutQualifier().rasterOrdered; + uniformBaseVertex.readonly = type.getMemoryQualifier().readonly; + uniformBaseVertex.writeonly = type.getMemoryQualifier().writeonly; + addBaseVertex = true; + } + + DeclareGlobalVariable(root, baseVertex); + if (!ReplaceVariableWithTyped(compiler, root, builtInVariableBaseVertex, baseVertexSymbol)) + { + return false; + } + } + + FindGLBaseInstanceTraverser traverserInstance; + root->traverse(&traverserInstance); + const TVariable *builtInVariableBaseInstance = + traverserInstance.getGLBaseInstanceBuiltinVariable(); + + if (builtInVariableBaseInstance) + { + const TVariable *baseInstance = BuiltInVariable::angle_BaseInstance(); + const TType &type = baseInstance->getType(); + const TIntermSymbol *baseInstanceSymbol = new TIntermSymbol(baseInstance); + + // AngleInternal variables don't get collected + if (shouldCollect) + { + uniformBaseInstance.name = kEmulatedGLBaseInstanceName.data(); + uniformBaseInstance.mappedName = kEmulatedGLBaseInstanceName.data(); + uniformBaseInstance.type = GLVariableType(type); + uniformBaseInstance.precision = GLVariablePrecision(type); + uniformBaseInstance.staticUse = + symbolTable->isStaticallyUsed(*builtInVariableBaseInstance); + uniformBaseInstance.active = true; + uniformBaseInstance.binding = type.getLayoutQualifier().binding; + uniformBaseInstance.location = type.getLayoutQualifier().location; + uniformBaseInstance.offset = type.getLayoutQualifier().offset; + uniformBaseInstance.rasterOrdered = type.getLayoutQualifier().rasterOrdered; + uniformBaseInstance.readonly = type.getMemoryQualifier().readonly; + uniformBaseInstance.writeonly = type.getMemoryQualifier().writeonly; + addBaseInstance = true; + } + + DeclareGlobalVariable(root, baseInstance); + if (!ReplaceVariableWithTyped(compiler, root, builtInVariableBaseInstance, + baseInstanceSymbol)) + { + return false; + } + } + + // Make sure the order in uniforms is the same as the traverse order + if (addBaseInstance) + { + uniforms->push_back(uniformBaseInstance); + } + if (addBaseVertex) + { + uniforms->push_back(uniformBaseVertex); + } + + return true; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h new file mode 100644 index 0000000000..792a7c96b2 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h @@ -0,0 +1,47 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// EmulateGLDrawID is an AST traverser to convert the gl_DrawID builtin +// to a uniform int +// +// EmulateGLBaseVertexBaseInstance is an AST traverser to convert the gl_BaseVertex and +// gl_BaseInstance builtin to uniform ints +// +// EmulateGLBaseInstance is an AST traverser to convert the gl_BaseInstance builtin +// to a uniform int +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_EMULATEMULTIDRAWSHADERBUILTINS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_EMULATEMULTIDRAWSHADERBUILTINS_H_ + +#include +#include + +#include "common/angleutils.h" +#include "compiler/translator/HashNames.h" + +namespace sh +{ +struct ShaderVariable; +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool EmulateGLDrawID(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + std::vector *uniforms, + bool shouldCollect); + +[[nodiscard]] bool EmulateGLBaseVertexBaseInstance(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + std::vector *uniforms, + bool shouldCollect, + bool addBaseVertexToVertexID); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_EMULATEMULTIDRAWSHADERBUILTINS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/FoldExpressions.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/FoldExpressions.cpp new file mode 100644 index 0000000000..1ede8c1a46 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/FoldExpressions.cpp @@ -0,0 +1,120 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// FoldExpressions.cpp: Fold expressions. This may fold expressions so that the qualifier of the +// folded node differs from the qualifier of the original expression, so it needs to be done after +// parsing and validation of qualifiers is complete. Expressions that are folded: +// 1. Ternary ops with a constant condition. +// 2. Sequence aka comma ops where the left side has no side effects. +// 3. Any expressions containing any of the above. + +#include "compiler/translator/tree_ops/FoldExpressions.h" + +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class FoldExpressionsTraverser : public TIntermTraverser +{ + public: + FoldExpressionsTraverser(TDiagnostics *diagnostics) + : TIntermTraverser(true, false, false), mDiagnostics(diagnostics), mDidReplace(false) + {} + + bool didReplace() { return mDidReplace; } + + void nextIteration() { mDidReplace = false; } + + protected: + bool visitTernary(Visit visit, TIntermTernary *node) override + { + TIntermTyped *folded = node->fold(mDiagnostics); + if (folded != node) + { + queueReplacement(folded, OriginalNode::IS_DROPPED); + mDidReplace = true; + return false; + } + return true; + } + + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + TIntermTyped *folded = node->fold(mDiagnostics); + if (folded != node) + { + queueReplacement(folded, OriginalNode::IS_DROPPED); + mDidReplace = true; + return false; + } + return true; + } + + bool visitBinary(Visit visit, TIntermBinary *node) override + { + TIntermTyped *folded = node->fold(mDiagnostics); + if (folded != node) + { + queueReplacement(folded, OriginalNode::IS_DROPPED); + mDidReplace = true; + return false; + } + return true; + } + + bool visitUnary(Visit visit, TIntermUnary *node) override + { + TIntermTyped *folded = node->fold(mDiagnostics); + if (folded != node) + { + queueReplacement(folded, OriginalNode::IS_DROPPED); + mDidReplace = true; + return false; + } + return true; + } + + bool visitSwizzle(Visit visit, TIntermSwizzle *node) override + { + TIntermTyped *folded = node->fold(mDiagnostics); + if (folded != node) + { + queueReplacement(folded, OriginalNode::IS_DROPPED); + mDidReplace = true; + return false; + } + return true; + } + + private: + TDiagnostics *mDiagnostics; + bool mDidReplace; +}; + +} // anonymous namespace + +bool FoldExpressions(TCompiler *compiler, TIntermBlock *root, TDiagnostics *diagnostics) +{ + FoldExpressionsTraverser traverser(diagnostics); + do + { + traverser.nextIteration(); + root->traverse(&traverser); + if (!traverser.updateTree(compiler, root)) + { + return false; + } + } while (traverser.didReplace()); + + return true; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/FoldExpressions.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/FoldExpressions.h new file mode 100644 index 0000000000..1592444c50 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/FoldExpressions.h @@ -0,0 +1,29 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// FoldExpressions.h: Fold expressions. This may fold expressions so that the qualifier of the +// folded node differs from the qualifier of the original expression, so it needs to be done after +// parsing and validation of qualifiers is complete. Expressions that are folded: 1. Ternary ops +// with a constant condition. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_FOLDEXPRESSIONS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_FOLDEXPRESSIONS_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TDiagnostics; + +[[nodiscard]] bool FoldExpressions(TCompiler *compiler, + TIntermBlock *root, + TDiagnostics *diagnostics); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_FOLDEXPRESSIONS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/ForcePrecisionQualifier.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/ForcePrecisionQualifier.cpp new file mode 100644 index 0000000000..00dd0131c6 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/ForcePrecisionQualifier.cpp @@ -0,0 +1,101 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/tree_ops/ForcePrecisionQualifier.h" +#include "angle_gl.h" +#include "common/debug.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ +class TPrecisionTraverser : public TIntermTraverser +{ + public: + TPrecisionTraverser(TSymbolTable *symbolTable); + + protected: + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; + + void overwriteVariablePrecision(TType *type) const; +}; + +TPrecisionTraverser::TPrecisionTraverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, true, true, symbolTable) +{} + +void TPrecisionTraverser::overwriteVariablePrecision(TType *type) const +{ + if (type->getPrecision() == EbpHigh) + { + type->setPrecision(EbpMedium); + } +} + +bool TPrecisionTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) +{ + // Variable declaration. + if (visit == PreVisit) + { + const TIntermSequence &sequence = *(node->getSequence()); + TIntermTyped *variable = sequence.front()->getAsTyped(); + const TType &type = variable->getType(); + TQualifier qualifier = variable->getQualifier(); + + // Don't modify uniform since it might be shared between vertex and fragment shader + if (qualifier == EvqUniform) + { + return true; + } + + // Visit the struct. + if (type.isStructSpecifier()) + { + const TStructure *structure = type.getStruct(); + const TFieldList &fields = structure->fields(); + for (size_t i = 0; i < fields.size(); ++i) + { + const TField *field = fields[i]; + const TType *fieldType = field->type(); + overwriteVariablePrecision((TType *)fieldType); + } + } + else if (type.getBasicType() == EbtInterfaceBlock) + { + const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + const TFieldList &fields = interfaceBlock->fields(); + for (const TField *field : fields) + { + const TType *fieldType = field->type(); + overwriteVariablePrecision((TType *)fieldType); + } + } + else + { + overwriteVariablePrecision((TType *)&type); + } + } + return true; +} +} // namespace + +bool ForceShaderPrecisionToMediump(TIntermNode *root, TSymbolTable *symbolTable, GLenum shaderType) +{ + if (shaderType != GL_FRAGMENT_SHADER) + { + return true; + } + + TPrecisionTraverser traverser(symbolTable); + root->traverse(&traverser); + return true; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/ForcePrecisionQualifier.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/ForcePrecisionQualifier.h new file mode 100644 index 0000000000..c4cde25415 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/ForcePrecisionQualifier.h @@ -0,0 +1,17 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_FORCEPRECISIONQUALIFIER_H_ +#define COMPILER_TRANSLATOR_TREEOPS_FORCEPRECISIONQUALIFIER_H_ + +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ +bool ForceShaderPrecisionToMediump(TIntermNode *root, TSymbolTable *symbolTable, GLenum shaderType); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_FORCEPRECISIONQUALIFIER_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/InitializeVariables.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/InitializeVariables.cpp new file mode 100644 index 0000000000..789610ecc0 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/InitializeVariables.cpp @@ -0,0 +1,359 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/tree_ops/InitializeVariables.h" + +#include "angle_gl.h" +#include "common/debug.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/FindMain.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +void AddArrayZeroInitSequence(const TIntermTyped *initializedNode, + bool canUseLoopsToInitialize, + bool highPrecisionSupported, + TIntermSequence *initSequenceOut, + TSymbolTable *symbolTable); + +void AddStructZeroInitSequence(const TIntermTyped *initializedNode, + bool canUseLoopsToInitialize, + bool highPrecisionSupported, + TIntermSequence *initSequenceOut, + TSymbolTable *symbolTable); + +TIntermBinary *CreateZeroInitAssignment(const TIntermTyped *initializedNode) +{ + TIntermTyped *zero = CreateZeroNode(initializedNode->getType()); + return new TIntermBinary(EOpAssign, initializedNode->deepCopy(), zero); +} + +void AddZeroInitSequence(const TIntermTyped *initializedNode, + bool canUseLoopsToInitialize, + bool highPrecisionSupported, + TIntermSequence *initSequenceOut, + TSymbolTable *symbolTable) +{ + if (initializedNode->isArray()) + { + AddArrayZeroInitSequence(initializedNode, canUseLoopsToInitialize, highPrecisionSupported, + initSequenceOut, symbolTable); + } + else if (initializedNode->getType().isStructureContainingArrays() || + initializedNode->getType().isNamelessStruct()) + { + AddStructZeroInitSequence(initializedNode, canUseLoopsToInitialize, highPrecisionSupported, + initSequenceOut, symbolTable); + } + else if (initializedNode->getType().isInterfaceBlock()) + { + const TType &type = initializedNode->getType(); + const TInterfaceBlock &interfaceBlock = *type.getInterfaceBlock(); + const TFieldList &fieldList = interfaceBlock.fields(); + for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex) + { + const TField &field = *fieldList[fieldIndex]; + TIntermTyped *fieldIndexRef = CreateIndexNode(static_cast(fieldIndex)); + TIntermTyped *fieldReference = + new TIntermBinary(TOperator::EOpIndexDirectInterfaceBlock, + initializedNode->deepCopy(), fieldIndexRef); + TIntermTyped *fieldZero = CreateZeroNode(*field.type()); + TIntermTyped *assignment = + new TIntermBinary(TOperator::EOpAssign, fieldReference, fieldZero); + initSequenceOut->push_back(assignment); + } + } + else + { + initSequenceOut->push_back(CreateZeroInitAssignment(initializedNode)); + } +} + +void AddStructZeroInitSequence(const TIntermTyped *initializedNode, + bool canUseLoopsToInitialize, + bool highPrecisionSupported, + TIntermSequence *initSequenceOut, + TSymbolTable *symbolTable) +{ + ASSERT(initializedNode->getBasicType() == EbtStruct); + const TStructure *structType = initializedNode->getType().getStruct(); + for (int i = 0; i < static_cast(structType->fields().size()); ++i) + { + TIntermBinary *element = new TIntermBinary(EOpIndexDirectStruct, + initializedNode->deepCopy(), CreateIndexNode(i)); + // Structs can't be defined inside structs, so the type of a struct field can't be a + // nameless struct. + ASSERT(!element->getType().isNamelessStruct()); + AddZeroInitSequence(element, canUseLoopsToInitialize, highPrecisionSupported, + initSequenceOut, symbolTable); + } +} + +void AddArrayZeroInitStatementList(const TIntermTyped *initializedNode, + bool canUseLoopsToInitialize, + bool highPrecisionSupported, + TIntermSequence *initSequenceOut, + TSymbolTable *symbolTable) +{ + for (unsigned int i = 0; i < initializedNode->getOutermostArraySize(); ++i) + { + TIntermBinary *element = + new TIntermBinary(EOpIndexDirect, initializedNode->deepCopy(), CreateIndexNode(i)); + AddZeroInitSequence(element, canUseLoopsToInitialize, highPrecisionSupported, + initSequenceOut, symbolTable); + } +} + +void AddArrayZeroInitForLoop(const TIntermTyped *initializedNode, + bool highPrecisionSupported, + TIntermSequence *initSequenceOut, + TSymbolTable *symbolTable) +{ + ASSERT(initializedNode->isArray()); + const TType *mediumpIndexType = StaticType::Get(); + const TType *highpIndexType = StaticType::Get(); + TVariable *indexVariable = + CreateTempVariable(symbolTable, highPrecisionSupported ? highpIndexType : mediumpIndexType); + + TIntermSymbol *indexSymbolNode = CreateTempSymbolNode(indexVariable); + TIntermDeclaration *indexInit = + CreateTempInitDeclarationNode(indexVariable, CreateZeroNode(indexVariable->getType())); + TIntermConstantUnion *arraySizeNode = CreateIndexNode(initializedNode->getOutermostArraySize()); + TIntermBinary *indexSmallerThanSize = + new TIntermBinary(EOpLessThan, indexSymbolNode->deepCopy(), arraySizeNode); + TIntermUnary *indexIncrement = + new TIntermUnary(EOpPreIncrement, indexSymbolNode->deepCopy(), nullptr); + + TIntermBlock *forLoopBody = new TIntermBlock(); + TIntermSequence *forLoopBodySeq = forLoopBody->getSequence(); + + TIntermBinary *element = new TIntermBinary(EOpIndexIndirect, initializedNode->deepCopy(), + indexSymbolNode->deepCopy()); + AddZeroInitSequence(element, true, highPrecisionSupported, forLoopBodySeq, symbolTable); + + TIntermLoop *forLoop = + new TIntermLoop(ELoopFor, indexInit, indexSmallerThanSize, indexIncrement, forLoopBody); + initSequenceOut->push_back(forLoop); +} + +void AddArrayZeroInitSequence(const TIntermTyped *initializedNode, + bool canUseLoopsToInitialize, + bool highPrecisionSupported, + TIntermSequence *initSequenceOut, + TSymbolTable *symbolTable) +{ + // The array elements are assigned one by one to keep the AST compatible with ESSL 1.00 which + // doesn't have array assignment. We'll do this either with a for loop or just a list of + // statements assigning to each array index. Note that it is important to have the array init in + // the right order to workaround http://crbug.com/709317 + bool isSmallArray = initializedNode->getOutermostArraySize() <= 1u || + (initializedNode->getBasicType() != EbtStruct && + !initializedNode->getType().isArrayOfArrays() && + initializedNode->getOutermostArraySize() <= 3u); + if (initializedNode->getQualifier() == EvqFragData || + initializedNode->getQualifier() == EvqFragmentOut || isSmallArray || + !canUseLoopsToInitialize) + { + // Fragment outputs should not be indexed by non-constant indices. + // Also it doesn't make sense to use loops to initialize very small arrays. + AddArrayZeroInitStatementList(initializedNode, canUseLoopsToInitialize, + highPrecisionSupported, initSequenceOut, symbolTable); + } + else + { + AddArrayZeroInitForLoop(initializedNode, highPrecisionSupported, initSequenceOut, + symbolTable); + } +} + +void InsertInitCode(TCompiler *compiler, + TIntermSequence *mainBody, + const InitVariableList &variables, + TSymbolTable *symbolTable, + int shaderVersion, + const TExtensionBehavior &extensionBehavior, + bool canUseLoopsToInitialize, + bool highPrecisionSupported) +{ + for (const ShaderVariable &var : variables) + { + // Note that tempVariableName will reference a short-lived char array here - that's fine + // since we're only using it to find symbols. + ImmutableString tempVariableName(var.name.c_str(), var.name.length()); + + TIntermTyped *initializedSymbol = nullptr; + if (var.isBuiltIn() && !symbolTable->findUserDefined(tempVariableName)) + { + initializedSymbol = + ReferenceBuiltInVariable(tempVariableName, *symbolTable, shaderVersion); + if (initializedSymbol->getQualifier() == EvqFragData && + !IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers)) + { + // If GL_EXT_draw_buffers is disabled, only the 0th index of gl_FragData can be + // written to. + // TODO(oetuaho): This is a bit hacky and would be better to remove, if we came up + // with a good way to do it. Right now "gl_FragData" in symbol table is initialized + // to have the array size of MaxDrawBuffers, and the initialization happens before + // the shader sets the extensions it is using. + initializedSymbol = + new TIntermBinary(EOpIndexDirect, initializedSymbol, CreateIndexNode(0)); + } + } + else + { + if (tempVariableName != "") + { + initializedSymbol = ReferenceGlobalVariable(tempVariableName, *symbolTable); + } + else + { + // Must be a nameless interface block. + ASSERT(var.structOrBlockName != ""); + const TSymbol *symbol = symbolTable->findGlobal(var.structOrBlockName); + ASSERT(symbol && symbol->isInterfaceBlock()); + const TInterfaceBlock *block = static_cast(symbol); + + for (const TField *field : block->fields()) + { + initializedSymbol = ReferenceGlobalVariable(field->name(), *symbolTable); + + TIntermSequence initCode; + CreateInitCode(initializedSymbol, canUseLoopsToInitialize, + highPrecisionSupported, &initCode, symbolTable); + mainBody->insert(mainBody->begin(), initCode.begin(), initCode.end()); + } + // Already inserted init code in this case + continue; + } + } + ASSERT(initializedSymbol != nullptr); + + TIntermSequence initCode; + CreateInitCode(initializedSymbol, canUseLoopsToInitialize, highPrecisionSupported, + &initCode, symbolTable); + mainBody->insert(mainBody->begin(), initCode.begin(), initCode.end()); + } +} + +class InitializeLocalsTraverser : public TIntermTraverser +{ + public: + InitializeLocalsTraverser(int shaderVersion, + TSymbolTable *symbolTable, + bool canUseLoopsToInitialize, + bool highPrecisionSupported) + : TIntermTraverser(true, false, false, symbolTable), + mShaderVersion(shaderVersion), + mCanUseLoopsToInitialize(canUseLoopsToInitialize), + mHighPrecisionSupported(highPrecisionSupported) + {} + + protected: + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + for (TIntermNode *declarator : *node->getSequence()) + { + if (!mInGlobalScope && !declarator->getAsBinaryNode()) + { + TIntermSymbol *symbol = declarator->getAsSymbolNode(); + ASSERT(symbol); + if (symbol->variable().symbolType() == SymbolType::Empty) + { + continue; + } + + // Arrays may need to be initialized one element at a time, since ESSL 1.00 does not + // support array constructors or assigning arrays. + bool arrayConstructorUnavailable = + (symbol->isArray() || symbol->getType().isStructureContainingArrays()) && + mShaderVersion == 100; + // Nameless struct constructors can't be referred to, so they also need to be + // initialized one element at a time. + // TODO(oetuaho): Check if it makes sense to initialize using a loop, even if we + // could use an initializer. It could at least reduce code size for very large + // arrays, but could hurt runtime performance. + if (arrayConstructorUnavailable || symbol->getType().isNamelessStruct()) + { + // SimplifyLoopConditions should have been run so the parent node of this node + // should not be a loop. + ASSERT(getParentNode()->getAsLoopNode() == nullptr); + // SeparateDeclarations should have already been run, so we don't need to worry + // about further declarators in this declaration depending on the effects of + // this declarator. + ASSERT(node->getSequence()->size() == 1); + TIntermSequence initCode; + CreateInitCode(symbol, mCanUseLoopsToInitialize, mHighPrecisionSupported, + &initCode, mSymbolTable); + insertStatementsInParentBlock(TIntermSequence(), initCode); + } + else + { + TIntermBinary *init = + new TIntermBinary(EOpInitialize, symbol, CreateZeroNode(symbol->getType())); + queueReplacementWithParent(node, symbol, init, OriginalNode::BECOMES_CHILD); + } + } + } + return false; + } + + private: + int mShaderVersion; + bool mCanUseLoopsToInitialize; + bool mHighPrecisionSupported; +}; + +} // namespace + +void CreateInitCode(const TIntermTyped *initializedSymbol, + bool canUseLoopsToInitialize, + bool highPrecisionSupported, + TIntermSequence *initCode, + TSymbolTable *symbolTable) +{ + AddZeroInitSequence(initializedSymbol, canUseLoopsToInitialize, highPrecisionSupported, + initCode, symbolTable); +} + +bool InitializeUninitializedLocals(TCompiler *compiler, + TIntermBlock *root, + int shaderVersion, + bool canUseLoopsToInitialize, + bool highPrecisionSupported, + TSymbolTable *symbolTable) +{ + InitializeLocalsTraverser traverser(shaderVersion, symbolTable, canUseLoopsToInitialize, + highPrecisionSupported); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +bool InitializeVariables(TCompiler *compiler, + TIntermBlock *root, + const InitVariableList &vars, + TSymbolTable *symbolTable, + int shaderVersion, + const TExtensionBehavior &extensionBehavior, + bool canUseLoopsToInitialize, + bool highPrecisionSupported) +{ + TIntermBlock *body = FindMainBody(root); + InsertInitCode(compiler, body->getSequence(), vars, symbolTable, shaderVersion, + extensionBehavior, canUseLoopsToInitialize, highPrecisionSupported); + + return compiler->validateAST(root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/InitializeVariables.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/InitializeVariables.h new file mode 100644 index 0000000000..755b8d72eb --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/InitializeVariables.h @@ -0,0 +1,60 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_INITIALIZEVARIABLES_H_ +#define COMPILER_TRANSLATOR_TREEOPS_INITIALIZEVARIABLES_H_ + +#include + +#include "compiler/translator/ExtensionBehavior.h" +#include "compiler/translator/IntermNode.h" + +namespace sh +{ +class TCompiler; +class TSymbolTable; + +typedef std::vector InitVariableList; + +// For all of the functions below: If canUseLoopsToInitialize is set, for loops are used instead of +// a large number of initializers where it can make sense, such as for initializing large arrays. + +// Populate a sequence of assignment operations to initialize "initializedSymbol". initializedSymbol +// may be an array, struct or any combination of these, as long as it contains only basic types. +void CreateInitCode(const TIntermTyped *initializedSymbol, + bool canUseLoopsToInitialize, + bool highPrecisionSupported, + TIntermSequence *initCode, + TSymbolTable *symbolTable); + +// Initialize all uninitialized local variables, so that undefined behavior is avoided. +[[nodiscard]] bool InitializeUninitializedLocals(TCompiler *compiler, + TIntermBlock *root, + int shaderVersion, + bool canUseLoopsToInitialize, + bool highPrecisionSupported, + TSymbolTable *symbolTable); + +// This function can initialize all the types that CreateInitCode is able to initialize. All +// variables must be globals which can be found in the symbol table. For now it is used for the +// following two scenarios: +// 1. Initializing gl_Position; +// 2. Initializing output variables referred to in the shader source. +// Note: The type of each lvalue in an initializer is retrieved from the symbol table. gl_FragData +// requires special handling because the number of indices which can be initialized is determined by +// enabled extensions. +[[nodiscard]] bool InitializeVariables(TCompiler *compiler, + TIntermBlock *root, + const InitVariableList &vars, + TSymbolTable *symbolTable, + int shaderVersion, + const TExtensionBehavior &extensionBehavior, + bool canUseLoopsToInitialize, + bool highPrecisionSupported); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_INITIALIZEVARIABLES_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.cpp new file mode 100644 index 0000000000..11c8b72002 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.cpp @@ -0,0 +1,613 @@ +// +// Copyright 2021 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// MonomorphizeUnsupportedFunctions: Monomorphize functions that are called with +// parameters that are incompatible with both Vulkan GLSL and Metal. +// + +#include "compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.h" + +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" + +namespace sh +{ +namespace +{ +struct Argument +{ + size_t argumentIndex; + TIntermTyped *argument; +}; + +struct FunctionData +{ + // Whether the original function is used. If this is false, the function can be removed because + // all callers have been modified. + bool isOriginalUsed; + // The original definition of the function, used to create the monomorphized version. + TIntermFunctionDefinition *originalDefinition; + // List of monomorphized versions of this function. They will be added next to the original + // version (or replace it). + TVector monomorphizedDefinitions; +}; + +using FunctionMap = angle::HashMap; + +// Traverse the function definitions and initialize the map. Allows visitAggregate to have access +// to TIntermFunctionDefinition even when the function is only forward declared at that point. +void InitializeFunctionMap(TIntermBlock *root, FunctionMap *functionMapOut) +{ + TIntermSequence &sequence = *root->getSequence(); + + for (TIntermNode *node : sequence) + { + TIntermFunctionDefinition *asFuncDef = node->getAsFunctionDefinition(); + if (asFuncDef != nullptr) + { + const TFunction *function = asFuncDef->getFunction(); + ASSERT(function && functionMapOut->find(function) == functionMapOut->end()); + (*functionMapOut)[function] = FunctionData{false, asFuncDef, {}}; + } + } +} + +const TVariable *GetBaseUniform(TIntermTyped *node, bool *isSamplerInStructOut) +{ + *isSamplerInStructOut = false; + + while (node->getAsBinaryNode()) + { + TIntermBinary *asBinary = node->getAsBinaryNode(); + + TOperator op = asBinary->getOp(); + + // No opaque uniform can be inside an interface block. + if (op == EOpIndexDirectInterfaceBlock) + { + return nullptr; + } + + if (op == EOpIndexDirectStruct) + { + *isSamplerInStructOut = true; + } + + node = asBinary->getLeft(); + } + + // Only interested in uniform opaque types. If a function call within another function uses + // opaque uniforms in an unsupported way, it will be replaced in a follow up pass after the + // calling function is monomorphized. + if (node->getType().getQualifier() != EvqUniform) + { + return nullptr; + } + + ASSERT(IsOpaqueType(node->getType().getBasicType()) || + node->getType().isStructureContainingSamplers()); + + TIntermSymbol *asSymbol = node->getAsSymbolNode(); + ASSERT(asSymbol); + + return &asSymbol->variable(); +} + +TIntermTyped *ExtractSideEffects(TSymbolTable *symbolTable, + TIntermTyped *node, + TIntermSequence *replacementIndices) +{ + TIntermTyped *withoutSideEffects = node->deepCopy(); + + for (TIntermBinary *asBinary = withoutSideEffects->getAsBinaryNode(); asBinary; + asBinary = asBinary->getLeft()->getAsBinaryNode()) + { + TOperator op = asBinary->getOp(); + TIntermTyped *index = asBinary->getRight(); + + if (op == EOpIndexDirectStruct) + { + break; + } + + // No side effects with constant expressions. + if (op == EOpIndexDirect) + { + ASSERT(index->getAsConstantUnion()); + continue; + } + + ASSERT(op == EOpIndexIndirect); + + // If the index is a symbol, there's no side effect, so leave it as-is. + if (index->getAsSymbolNode()) + { + continue; + } + + // Otherwise create a temp variable initialized with the index and use that temp variable as + // the index. + TIntermDeclaration *tempDecl = nullptr; + TVariable *tempVar = DeclareTempVariable(symbolTable, index, EvqTemporary, &tempDecl); + + replacementIndices->push_back(tempDecl); + asBinary->replaceChildNode(index, new TIntermSymbol(tempVar)); + } + + return withoutSideEffects; +} + +void CreateMonomorphizedFunctionCallArgs(const TIntermSequence &originalCallArguments, + const TVector &replacedArguments, + TIntermSequence *substituteArgsOut) +{ + size_t nextReplacedArg = 0; + for (size_t argIndex = 0; argIndex < originalCallArguments.size(); ++argIndex) + { + if (nextReplacedArg >= replacedArguments.size() || + argIndex != replacedArguments[nextReplacedArg].argumentIndex) + { + // Not replaced, keep argument as is. + substituteArgsOut->push_back(originalCallArguments[argIndex]); + } + else + { + TIntermTyped *argument = replacedArguments[nextReplacedArg].argument; + + // Iterate over indices of the argument and create a new arg for every non-const + // index. Note that the index itself may be an expression, and it may require further + // substitution in the next pass. + while (argument->getAsBinaryNode()) + { + TIntermBinary *asBinary = argument->getAsBinaryNode(); + if (asBinary->getOp() == EOpIndexIndirect) + { + TIntermTyped *index = asBinary->getRight(); + substituteArgsOut->push_back(index->deepCopy()); + } + argument = asBinary->getLeft(); + } + + ++nextReplacedArg; + } + } +} + +const TFunction *MonomorphizeFunction(TSymbolTable *symbolTable, + const TFunction *original, + TVector *replacedArguments, + VariableReplacementMap *argumentMapOut) +{ + TFunction *substituteFunction = + new TFunction(symbolTable, kEmptyImmutableString, SymbolType::AngleInternal, + &original->getReturnType(), original->isKnownToNotHaveSideEffects()); + + size_t nextReplacedArg = 0; + for (size_t paramIndex = 0; paramIndex < original->getParamCount(); ++paramIndex) + { + const TVariable *originalParam = original->getParam(paramIndex); + + if (nextReplacedArg >= replacedArguments->size() || + paramIndex != (*replacedArguments)[nextReplacedArg].argumentIndex) + { + TVariable *substituteArgument = + new TVariable(symbolTable, originalParam->name(), &originalParam->getType(), + originalParam->symbolType()); + // Not replaced, add an identical parameter. + substituteFunction->addParameter(substituteArgument); + (*argumentMapOut)[originalParam] = new TIntermSymbol(substituteArgument); + } + else + { + TIntermTyped *substituteArgument = (*replacedArguments)[nextReplacedArg].argument; + (*argumentMapOut)[originalParam] = substituteArgument; + + // Iterate over indices of the argument and create a new parameter for every non-const + // index (which may be an expression). Replace the symbol in the argument with a + // variable of the index type. This is later used to replace the parameter in the + // function body. + while (substituteArgument->getAsBinaryNode()) + { + TIntermBinary *asBinary = substituteArgument->getAsBinaryNode(); + if (asBinary->getOp() == EOpIndexIndirect) + { + TIntermTyped *index = asBinary->getRight(); + TType *indexType = new TType(index->getType()); + indexType->setQualifier(EvqParamIn); + + TVariable *param = new TVariable(symbolTable, kEmptyImmutableString, indexType, + SymbolType::AngleInternal); + substituteFunction->addParameter(param); + + // The argument now uses the function parameters as indices. + asBinary->replaceChildNode(asBinary->getRight(), new TIntermSymbol(param)); + } + substituteArgument = asBinary->getLeft(); + } + + ++nextReplacedArg; + } + } + + return substituteFunction; +} + +class MonomorphizeTraverser final : public TIntermTraverser +{ + public: + explicit MonomorphizeTraverser(TCompiler *compiler, + TSymbolTable *symbolTable, + const ShCompileOptions &compileOptions, + UnsupportedFunctionArgsBitSet unsupportedFunctionArgs, + FunctionMap *functionMap) + : TIntermTraverser(true, false, false, symbolTable), + mCompiler(compiler), + mCompileOptions(compileOptions), + mUnsupportedFunctionArgs(unsupportedFunctionArgs), + mFunctionMap(functionMap) + {} + + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + if (node->getOp() != EOpCallFunctionInAST) + { + return true; + } + + const TFunction *function = node->getFunction(); + ASSERT(function && mFunctionMap->find(function) != mFunctionMap->end()); + + FunctionData &data = (*mFunctionMap)[function]; + + TIntermFunctionDefinition *monomorphized = + processFunctionCall(node, data.originalDefinition, &data.isOriginalUsed); + if (monomorphized) + { + data.monomorphizedDefinitions.push_back(monomorphized); + } + + return true; + } + + bool getAnyMonomorphized() const { return mAnyMonomorphized; } + + private: + bool isUnsupportedArgument(TIntermTyped *callArgument, const TVariable *funcArgument) const + { + // Only interested in opaque uniforms and structs that contain samplers. + const bool isOpaqueType = IsOpaqueType(funcArgument->getType().getBasicType()); + const bool isStructContainingSamplers = + funcArgument->getType().isStructureContainingSamplers(); + if (!isOpaqueType && !isStructContainingSamplers) + { + return false; + } + + // If not uniform (the variable was itself a function parameter), don't process it in + // this pass, as we don't know which actual uniform it corresponds to. + bool isSamplerInStruct = false; + const TVariable *uniform = GetBaseUniform(callArgument, &isSamplerInStruct); + if (uniform == nullptr) + { + return false; + } + + const TType &type = uniform->getType(); + + if (mUnsupportedFunctionArgs[UnsupportedFunctionArgs::StructContainingSamplers]) + { + // Monomorphize if the parameter is a structure that contains samplers (so in + // RewriteStructSamplers we don't need to rewrite the functions to accept multiple + // parameters split from the struct). + if (isStructContainingSamplers) + { + return true; + } + } + + if (mUnsupportedFunctionArgs[UnsupportedFunctionArgs::ArrayOfArrayOfSamplerOrImage]) + { + // Monomorphize if: + // + // - The opaque uniform is a sampler in a struct (which can create an array-of-array + // situation), and the function expects an array of samplers, or + // + // - The opaque uniform is an array of array of sampler or image, and it's partially + // subscripted (i.e. the function itself expects an array) + // + const bool isParameterArrayOfOpaqueType = funcArgument->getType().isArray(); + const bool isArrayOfArrayOfSamplerOrImage = + (type.isSampler() || type.isImage()) && type.isArrayOfArrays(); + if (isSamplerInStruct && isParameterArrayOfOpaqueType) + { + return true; + } + if (isArrayOfArrayOfSamplerOrImage && isParameterArrayOfOpaqueType) + { + return true; + } + } + + if (mUnsupportedFunctionArgs[UnsupportedFunctionArgs::AtomicCounter]) + { + if (type.isAtomicCounter()) + { + return true; + } + } + + if (mUnsupportedFunctionArgs[UnsupportedFunctionArgs::SamplerCubeEmulation]) + { + // Monomorphize if the opaque uniform is a samplerCube and ES2's cube sampling emulation + // is requested. + if (type.isSamplerCube() && mCompileOptions.emulateSeamfulCubeMapSampling) + { + return true; + } + } + + if (mUnsupportedFunctionArgs[UnsupportedFunctionArgs::Image]) + { + if (type.isImage()) + { + return true; + } + } + + if (mUnsupportedFunctionArgs[UnsupportedFunctionArgs::PixelLocalStorage]) + { + if (type.isPixelLocal()) + { + return true; + } + } + + return false; + } + + TIntermFunctionDefinition *processFunctionCall(TIntermAggregate *functionCall, + TIntermFunctionDefinition *originalDefinition, + bool *isOriginalUsedOut) + { + const TFunction *function = functionCall->getFunction(); + const TIntermSequence &callArguments = *functionCall->getSequence(); + + TVector replacedArguments; + TIntermSequence replacementIndices; + + // Go through function call arguments, and see if any is used in an unsupported way. + for (size_t argIndex = 0; argIndex < callArguments.size(); ++argIndex) + { + TIntermTyped *callArgument = callArguments[argIndex]->getAsTyped(); + const TVariable *funcArgument = function->getParam(argIndex); + if (isUnsupportedArgument(callArgument, funcArgument)) + { + // Copy the argument and extract the side effects. + TIntermTyped *argument = + ExtractSideEffects(mSymbolTable, callArgument, &replacementIndices); + + replacedArguments.push_back({argIndex, argument}); + } + } + + if (replacedArguments.empty()) + { + *isOriginalUsedOut = true; + return nullptr; + } + + mAnyMonomorphized = true; + + insertStatementsInParentBlock(replacementIndices); + + // Create the arguments for the substitute function call. Done before monomorphizing the + // function, which transforms the arguments to what needs to be replaced in the function + // body. + TIntermSequence newCallArgs; + CreateMonomorphizedFunctionCallArgs(callArguments, replacedArguments, &newCallArgs); + + // Duplicate the function and substitute the replaced arguments with only the non-const + // indices. Additionally, substitute the non-const indices of arguments with the new + // function parameters. + VariableReplacementMap argumentMap; + const TFunction *monomorphized = + MonomorphizeFunction(mSymbolTable, function, &replacedArguments, &argumentMap); + + // Replace this function call with a call to the new one. + queueReplacement(TIntermAggregate::CreateFunctionCall(*monomorphized, &newCallArgs), + OriginalNode::IS_DROPPED); + + // Create a new function definition, with the body of the old function but with the replaced + // parameters substituted with the calling expressions. + TIntermFunctionPrototype *substitutePrototype = new TIntermFunctionPrototype(monomorphized); + TIntermBlock *substituteBlock = originalDefinition->getBody()->deepCopy(); + GetDeclaratorReplacements(mSymbolTable, substituteBlock, &argumentMap); + bool valid = ReplaceVariables(mCompiler, substituteBlock, argumentMap); + ASSERT(valid); + + return new TIntermFunctionDefinition(substitutePrototype, substituteBlock); + } + + TCompiler *mCompiler; + const ShCompileOptions &mCompileOptions; + UnsupportedFunctionArgsBitSet mUnsupportedFunctionArgs; + bool mAnyMonomorphized = false; + + // Map of original to monomorphized functions. + FunctionMap *mFunctionMap; +}; + +class UpdateFunctionsDefinitionsTraverser final : public TIntermTraverser +{ + public: + explicit UpdateFunctionsDefinitionsTraverser(TSymbolTable *symbolTable, + const FunctionMap &functionMap) + : TIntermTraverser(true, false, false, symbolTable), mFunctionMap(functionMap) + {} + + void visitFunctionPrototype(TIntermFunctionPrototype *node) override + { + const bool isInFunctionDefinition = getParentNode()->getAsFunctionDefinition() != nullptr; + if (isInFunctionDefinition) + { + return; + } + + // Add to and possibly replace the function prototype with replacement prototypes. + const TFunction *function = node->getFunction(); + ASSERT(function && mFunctionMap.find(function) != mFunctionMap.end()); + + const FunctionData &data = mFunctionMap.at(function); + + // If nothing to do, leave it be. + if (data.monomorphizedDefinitions.empty()) + { + ASSERT(data.isOriginalUsed); + return; + } + + // Replace the prototype with itself (if function is still used) as well as any + // monomorphized versions. + TIntermSequence replacement; + if (data.isOriginalUsed) + { + replacement.push_back(node); + } + for (TIntermFunctionDefinition *monomorphizedDefinition : data.monomorphizedDefinitions) + { + replacement.push_back(new TIntermFunctionPrototype( + monomorphizedDefinition->getFunctionPrototype()->getFunction())); + } + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, + std::move(replacement)); + } + + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override + { + // Add to and possibly replace the function definition with replacement definitions. + const TFunction *function = node->getFunction(); + ASSERT(function && mFunctionMap.find(function) != mFunctionMap.end()); + + const FunctionData &data = mFunctionMap.at(function); + + // If nothing to do, leave it be. + if (data.monomorphizedDefinitions.empty()) + { + ASSERT(data.isOriginalUsed || function->name() == "main"); + return false; + } + + // Replace the definition with itself (if function is still used) as well as any + // monomorphized versions. + TIntermSequence replacement; + if (data.isOriginalUsed) + { + replacement.push_back(node); + } + for (TIntermFunctionDefinition *monomorphizedDefinition : data.monomorphizedDefinitions) + { + replacement.push_back(monomorphizedDefinition); + } + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, + std::move(replacement)); + + return false; + } + + private: + const FunctionMap &mFunctionMap; +}; + +void SortDeclarations(TIntermBlock *root) +{ + TIntermSequence *original = root->getSequence(); + + TIntermSequence replacement; + TIntermSequence functionDefs; + + // Accumulate non-function-definition declarations in |replacement| and function definitions in + // |functionDefs|. + for (TIntermNode *node : *original) + { + if (node->getAsFunctionDefinition() || node->getAsFunctionPrototypeNode()) + { + functionDefs.push_back(node); + } + else + { + replacement.push_back(node); + } + } + + // Append function definitions to |replacement|. + replacement.insert(replacement.end(), functionDefs.begin(), functionDefs.end()); + + // Replace root's sequence with |replacement|. + root->replaceAllChildren(replacement); +} + +bool MonomorphizeUnsupportedFunctionsImpl(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const ShCompileOptions &compileOptions, + UnsupportedFunctionArgsBitSet unsupportedFunctionArgs) +{ + // First, sort out the declarations such that all non-function declarations are placed before + // function definitions. This way when the function is replaced with one that references said + // declarations (i.e. uniforms), the uniform declaration is already present above it. + SortDeclarations(root); + + while (true) + { + FunctionMap functionMap; + InitializeFunctionMap(root, &functionMap); + + MonomorphizeTraverser monomorphizer(compiler, symbolTable, compileOptions, + unsupportedFunctionArgs, &functionMap); + root->traverse(&monomorphizer); + + if (!monomorphizer.getAnyMonomorphized()) + { + break; + } + + if (!monomorphizer.updateTree(compiler, root)) + { + return false; + } + + UpdateFunctionsDefinitionsTraverser functionUpdater(symbolTable, functionMap); + root->traverse(&functionUpdater); + + if (!functionUpdater.updateTree(compiler, root)) + { + return false; + } + } + + return true; +} +} // anonymous namespace + +bool MonomorphizeUnsupportedFunctions(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const ShCompileOptions &compileOptions, + UnsupportedFunctionArgsBitSet unsupportedFunctionArgs) +{ + // This function actually applies multiple transformation, and the AST may not be valid until + // the transformations are entirely done. Some validation is momentarily disabled. + bool enableValidateFunctionCall = compiler->disableValidateFunctionCall(); + + bool result = MonomorphizeUnsupportedFunctionsImpl(compiler, root, symbolTable, compileOptions, + unsupportedFunctionArgs); + + compiler->restoreValidateFunctionCall(enableValidateFunctionCall); + return result && compiler->validateAST(root); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.h new file mode 100644 index 0000000000..a9a212704b --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.h @@ -0,0 +1,54 @@ +// +// Copyright 2021 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// MonomorphizeUnsupportedFunctions: Monomorphize functions that are called with +// parameters that are incompatible with both Vulkan GLSL and Metal: +// +// - Samplers in structs +// - Structs that have samplers +// - Partially subscripted array of array of samplers +// - Partially subscripted array of array of images +// - Atomic counters +// - samplerCube variables when emulating ES2's cube map sampling +// - image* variables with r32f formats (to emulate imageAtomicExchange) +// +// This transformation basically duplicates such functions, removes the +// sampler/image/atomic_counter parameters and uses the opaque uniforms used by the caller. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_VULKAN_MONOMORPHIZEUNSUPPORTEDFUNCTIONS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_VULKAN_MONOMORPHIZEUNSUPPORTEDFUNCTIONS_H_ + +#include "common/angleutils.h" +#include "compiler/translator/Compiler.h" + +namespace sh +{ +class TIntermBlock; +class TSymbolTable; + +// Types of function prameters that should trigger monomorphization. +enum class UnsupportedFunctionArgs +{ + StructContainingSamplers = 0, + ArrayOfArrayOfSamplerOrImage = 1, + AtomicCounter = 2, + SamplerCubeEmulation = 3, + Image = 4, + PixelLocalStorage = 5, + + InvalidEnum = 6, + EnumCount = 6, +}; + +using UnsupportedFunctionArgsBitSet = angle::PackedEnumBitSet; + +[[nodiscard]] bool MonomorphizeUnsupportedFunctions(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const ShCompileOptions &compileOptions, + UnsupportedFunctionArgsBitSet); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_VULKAN_MONOMORPHIZEUNSUPPORTEDFUNCTIONS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/NameNamelessUniformBuffers.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/NameNamelessUniformBuffers.cpp new file mode 100644 index 0000000000..a23d0770ef --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/NameNamelessUniformBuffers.cpp @@ -0,0 +1,127 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// NameNamelessUniformBuffers: Gives nameless uniform buffer variables internal names. +// + +#include "compiler/translator/tree_ops/NameNamelessUniformBuffers.h" + +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ +namespace +{ +// Traverse uniform buffer declarations and give name to nameless declarations. Keeps track of +// the interface fields which will be used in the source without the interface block variable name +// and replaces them with name.field. +class NameUniformBufferVariablesTraverser : public TIntermTraverser +{ + public: + explicit NameUniformBufferVariablesTraverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, false, false, symbolTable) + {} + + bool visitDeclaration(Visit visit, TIntermDeclaration *decl) override + { + ASSERT(visit == PreVisit); + + const TIntermSequence &sequence = *(decl->getSequence()); + + TIntermTyped *variableNode = sequence.front()->getAsTyped(); + const TType &type = variableNode->getType(); + + // If it's an interface block, it may have to be converted if it contains any row-major + // fields. + if (!type.isInterfaceBlock()) + { + return true; + } + + // Multi declaration statements are already separated, so there can only be one variable + // here. + ASSERT(sequence.size() == 1); + const TVariable *variable = &variableNode->getAsSymbolNode()->variable(); + if (variable->symbolType() != SymbolType::Empty) + { + return false; + } + + TIntermDeclaration *newDeclaration = new TIntermDeclaration; + TVariable *newVariable = new TVariable(mSymbolTable, kEmptyImmutableString, &type, + SymbolType::AngleInternal, variable->extensions()); + newDeclaration->appendDeclarator(new TIntermSymbol(newVariable)); + + queueReplacement(newDeclaration, OriginalNode::IS_DROPPED); + + // It's safe to key the map with the interface block, as there couldn't have been multiple + // declarations with this interface block (as the variable is nameless), so for nameless + // uniform buffers, the interface block is unique. + mNamelessUniformBuffersMap[type.getInterfaceBlock()] = newVariable; + + return false; + } + + void visitSymbol(TIntermSymbol *symbol) override + { + const TType &type = symbol->getType(); + + // The symbols we are looking for have the interface block pointer set, but are not + // interface blocks. These are references to fields of nameless uniform buffers. + if (type.isInterfaceBlock() || type.getInterfaceBlock() == nullptr) + { + return; + } + + const TInterfaceBlock *block = type.getInterfaceBlock(); + + // If block variable is not nameless, there's nothing to do. + if (mNamelessUniformBuffersMap.count(block) == 0) + { + return; + } + + const ImmutableString symbolName = symbol->getName(); + + // Find which field it is + const TVector fields = block->fields(); + for (size_t fieldIndex = 0; fieldIndex < fields.size(); ++fieldIndex) + { + const TField *field = fields[fieldIndex]; + if (field->name() != symbolName) + { + continue; + } + + // Replace this node with a binary node that indexes the named uniform buffer. + TIntermSymbol *namedUniformBuffer = + new TIntermSymbol(mNamelessUniformBuffersMap[block]); + TIntermBinary *replacement = + new TIntermBinary(EOpIndexDirectInterfaceBlock, namedUniformBuffer, + CreateIndexNode(static_cast(fieldIndex))); + + queueReplacement(replacement, OriginalNode::IS_DROPPED); + + return; + } + + UNREACHABLE(); + } + + private: + // A map from nameless uniform buffers to their named replacements. + std::unordered_map mNamelessUniformBuffersMap; +}; +} // anonymous namespace + +bool NameNamelessUniformBuffers(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable) +{ + NameUniformBufferVariablesTraverser nameUniformBufferVariables(symbolTable); + root->traverse(&nameUniformBufferVariables); + return nameUniformBufferVariables.updateTree(compiler, root); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/NameNamelessUniformBuffers.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/NameNamelessUniformBuffers.h new file mode 100644 index 0000000000..23964a5846 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/NameNamelessUniformBuffers.h @@ -0,0 +1,32 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// NameNamelessUniformBuffers: Gives nameless uniform buffer variables internal names. +// +// For example: +// uniform UniformBuffer { int a; }; +// x = a; +// becomes: +// uniform UniformBuffer { int a; } s123; +// x = s123.a; +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_NAMENAMELESSUNIFORMBUFFERS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_NAMENAMELESSUNIFORMBUFFERS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool NameNamelessUniformBuffers(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_NAMENAMELESSUNIFORMBUFFERS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/PruneEmptyCases.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/PruneEmptyCases.cpp new file mode 100644 index 0000000000..276c8c98ed --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/PruneEmptyCases.cpp @@ -0,0 +1,127 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// PruneEmptyCases.cpp: The PruneEmptyCases function prunes cases that are followed by nothing from +// the AST. + +#include "compiler/translator/tree_ops/PruneEmptyCases.h" + +#include "compiler/translator/Symbol.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +bool AreEmptyBlocks(const TIntermSequence *statements); + +bool IsEmptyBlock(TIntermNode *node) +{ + TIntermBlock *asBlock = node->getAsBlock(); + if (asBlock) + { + return AreEmptyBlocks(asBlock->getSequence()); + } + // Empty declarations should have already been pruned, otherwise they would need to be handled + // here. Note that declarations for struct types do contain a nameless child node. + ASSERT(node->getAsDeclarationNode() == nullptr || + !node->getAsDeclarationNode()->getSequence()->empty()); + // Pure literal statements should also already be pruned. + ASSERT(node->getAsConstantUnion() == nullptr); + return false; +} + +// Return true if all statements in "statements" consist only of empty blocks and no-op statements. +// Returns true also if there are no statements. +bool AreEmptyBlocks(const TIntermSequence *statements) +{ + for (size_t i = 0u; i < statements->size(); ++i) + { + if (!IsEmptyBlock(statements->at(i))) + { + return false; + } + } + return true; +} + +class PruneEmptyCasesTraverser : private TIntermTraverser +{ + public: + [[nodiscard]] static bool apply(TCompiler *compiler, TIntermBlock *root); + + private: + PruneEmptyCasesTraverser(); + bool visitSwitch(Visit visit, TIntermSwitch *node) override; +}; + +bool PruneEmptyCasesTraverser::apply(TCompiler *compiler, TIntermBlock *root) +{ + PruneEmptyCasesTraverser prune; + root->traverse(&prune); + return prune.updateTree(compiler, root); +} + +PruneEmptyCasesTraverser::PruneEmptyCasesTraverser() : TIntermTraverser(true, false, false) {} + +bool PruneEmptyCasesTraverser::visitSwitch(Visit visit, TIntermSwitch *node) +{ + // This may mutate the statementList, but that's okay, since traversal has not yet reached + // there. + TIntermBlock *statementList = node->getStatementList(); + TIntermSequence *statements = statementList->getSequence(); + + // Iterate block children in reverse order. Cases that are only followed by other cases or empty + // blocks are marked for pruning. + size_t i = statements->size(); + size_t lastNoOpInStatementList = i; + while (i > 0) + { + --i; + TIntermNode *statement = statements->at(i); + if (statement->getAsCaseNode() || IsEmptyBlock(statement)) + { + lastNoOpInStatementList = i; + } + else + { + break; + } + } + if (lastNoOpInStatementList == 0) + { + // Remove the entire switch statement, extracting the init expression if needed. + TIntermTyped *init = node->getInit(); + if (init->hasSideEffects()) + { + queueReplacement(init, OriginalNode::IS_DROPPED); + } + else + { + TIntermSequence emptyReplacement; + ASSERT(getParentNode()->getAsBlock()); + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, + std::move(emptyReplacement)); + } + return false; + } + if (lastNoOpInStatementList < statements->size()) + { + statements->erase(statements->begin() + lastNoOpInStatementList, statements->end()); + } + + return true; +} + +} // namespace + +bool PruneEmptyCases(TCompiler *compiler, TIntermBlock *root) +{ + return PruneEmptyCasesTraverser::apply(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/PruneEmptyCases.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/PruneEmptyCases.h new file mode 100644 index 0000000000..5098fec9b7 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/PruneEmptyCases.h @@ -0,0 +1,22 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// PruneEmptyCases.h: The PruneEmptyCases function prunes cases that are followed by nothing from +// the AST. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_PRUNEEMPTYCASES_H_ +#define COMPILER_TRANSLATOR_TREEOPS_PRUNEEMPTYCASES_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; + +[[nodiscard]] bool PruneEmptyCases(TCompiler *compiler, TIntermBlock *root); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_PRUNEEMPTYCASES_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/PruneNoOps.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/PruneNoOps.cpp new file mode 100644 index 0000000000..fdc6070660 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/PruneNoOps.cpp @@ -0,0 +1,215 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// PruneNoOps.cpp: The PruneNoOps function prunes: +// 1. Empty declarations "int;". Empty declarators will be pruned as well, so for example: +// int , a; +// is turned into +// int a; +// 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision for float, +// so float literal statements would end up with no precision which is invalid ESSL. +// 3. Statements after discard, return, break and continue. + +#include "compiler/translator/tree_ops/PruneNoOps.h" + +#include "compiler/translator/Symbol.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +bool IsNoOp(TIntermNode *node) +{ + if (node->getAsConstantUnion() != nullptr) + { + return true; + } + bool isEmptyDeclaration = node->getAsDeclarationNode() != nullptr && + node->getAsDeclarationNode()->getSequence()->empty(); + if (isEmptyDeclaration) + { + return true; + } + return false; +} + +class PruneNoOpsTraverser : private TIntermTraverser +{ + public: + [[nodiscard]] static bool apply(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); + + private: + PruneNoOpsTraverser(TSymbolTable *symbolTable); + bool visitDeclaration(Visit, TIntermDeclaration *node) override; + bool visitBlock(Visit visit, TIntermBlock *node) override; + bool visitLoop(Visit visit, TIntermLoop *loop) override; + bool visitBranch(Visit visit, TIntermBranch *node) override; + + bool mIsBranchVisited = false; +}; + +bool PruneNoOpsTraverser::apply(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable) +{ + PruneNoOpsTraverser prune(symbolTable); + root->traverse(&prune); + return prune.updateTree(compiler, root); +} + +PruneNoOpsTraverser::PruneNoOpsTraverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, true, true, symbolTable) +{} + +bool PruneNoOpsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) +{ + if (visit != PreVisit) + { + return true; + } + + TIntermSequence *sequence = node->getSequence(); + if (sequence->size() >= 1) + { + TIntermSymbol *declaratorSymbol = sequence->front()->getAsSymbolNode(); + // Prune declarations without a variable name, unless it's an interface block declaration. + if (declaratorSymbol != nullptr && + declaratorSymbol->variable().symbolType() == SymbolType::Empty && + !declaratorSymbol->isInterfaceBlock()) + { + if (sequence->size() > 1) + { + // Generate a replacement that will remove the empty declarator in the beginning of + // a declarator list. Example of a declaration that will be changed: + // float, a; + // will be changed to + // float a; + // This applies also to struct declarations. + TIntermSequence emptyReplacement; + mMultiReplacements.emplace_back(node, declaratorSymbol, + std::move(emptyReplacement)); + } + else if (declaratorSymbol->getBasicType() != EbtStruct) + { + // If there are entirely empty non-struct declarations, they result in + // TIntermDeclaration nodes without any children in the parsing stage. These are + // handled in visitBlock and visitLoop. + UNREACHABLE(); + } + else if (declaratorSymbol->getQualifier() != EvqGlobal && + declaratorSymbol->getQualifier() != EvqTemporary) + { + // Single struct declarations may just declare the struct type and no variables, so + // they should not be pruned. Here we handle an empty struct declaration with a + // qualifier, for example like this: + // const struct a { int i; }; + // NVIDIA GL driver version 367.27 doesn't accept this kind of declarations, so we + // convert the declaration to a regular struct declaration. This is okay, since ESSL + // 1.00 spec section 4.1.8 says about structs that "The optional qualifiers only + // apply to any declarators, and are not part of the type being defined for name." + + // Create a new variable to use in the declarator so that the variable and node + // types are kept consistent. + TType *type = new TType(declaratorSymbol->getType()); + if (mInGlobalScope) + { + type->setQualifier(EvqGlobal); + } + else + { + type->setQualifier(EvqTemporary); + } + TVariable *variable = + new TVariable(mSymbolTable, kEmptyImmutableString, type, SymbolType::Empty); + queueReplacementWithParent(node, declaratorSymbol, new TIntermSymbol(variable), + OriginalNode::IS_DROPPED); + } + } + } + return false; +} + +bool PruneNoOpsTraverser::visitBlock(Visit visit, TIntermBlock *node) +{ + ASSERT(visit == PreVisit); + + TIntermSequence &statements = *node->getSequence(); + + // Visit each statement in the block one by one. Once a branch is visited (break, continue, + // return or discard), drop the rest of the statements. + for (size_t statementIndex = 0; statementIndex < statements.size(); ++statementIndex) + { + TIntermNode *statement = statements[statementIndex]; + + // If the statement is a switch case label, stop pruning and continue visiting the children. + if (statement->getAsCaseNode() != nullptr) + { + mIsBranchVisited = false; + } + + // If a branch is visited, prune the statement. If the statement is a no-op, also prune it. + if (mIsBranchVisited || IsNoOp(statement)) + { + TIntermSequence emptyReplacement; + mMultiReplacements.emplace_back(node, statement, std::move(emptyReplacement)); + continue; + } + + // Visit the statement if not pruned. + statement->traverse(this); + } + + // If the parent is a block and mIsBranchVisited is set, this is a nested block without any + // condition (like if, loop or switch), so the rest of the parent block should also be pruned. + // Otherwise the parent block should be unaffected. + if (mIsBranchVisited && getParentNode()->getAsBlock() == nullptr) + { + mIsBranchVisited = false; + } + + return false; +} + +bool PruneNoOpsTraverser::visitLoop(Visit visit, TIntermLoop *loop) +{ + if (visit != PreVisit) + { + return true; + } + + TIntermTyped *expr = loop->getExpression(); + if (expr != nullptr && IsNoOp(expr)) + { + loop->setExpression(nullptr); + } + TIntermNode *init = loop->getInit(); + if (init != nullptr && IsNoOp(init)) + { + loop->setInit(nullptr); + } + + return true; +} + +bool PruneNoOpsTraverser::visitBranch(Visit visit, TIntermBranch *node) +{ + ASSERT(visit == PreVisit); + + mIsBranchVisited = true; + + // Only possible child is the value of a return statement, which has nothing to prune. + return false; +} +} // namespace + +bool PruneNoOps(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable) +{ + return PruneNoOpsTraverser::apply(compiler, root, symbolTable); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/PruneNoOps.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/PruneNoOps.h new file mode 100644 index 0000000000..a73cb71d08 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/PruneNoOps.h @@ -0,0 +1,29 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// PruneNoOps.h: The PruneNoOps function prunes: +// 1. Empty declarations "int;". Empty declarators will be pruned as well, so for example: +// int , a; +// is turned into +// int a; +// 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision for float, +// so float literal statements would end up with no precision which is invalid ESSL. +// 3. Statements after discard, return, break and continue. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_PRUNENOOPS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_PRUNENOOPS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool PruneNoOps(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_PRUNENOOPS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RecordConstantPrecision.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/RecordConstantPrecision.cpp new file mode 100644 index 0000000000..ea15ab7844 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RecordConstantPrecision.cpp @@ -0,0 +1,119 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// During parsing, all constant expressions are folded to constant union nodes. The expressions that +// have been folded may have had precision qualifiers, which should affect the precision of the +// consuming operation. If the folded constant union nodes are written to output as such they won't +// have any precision qualifiers, and their effect on the precision of the consuming operation is +// lost. +// +// RecordConstantPrecision is an AST traverser that inspects the precision qualifiers of constants +// and hoists the constants outside the containing expression as precision qualified named variables +// in case that is required for correct precision propagation. +// + +#include "compiler/translator/tree_ops/RecordConstantPrecision.h" + +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class RecordConstantPrecisionTraverser : public TIntermTraverser +{ + public: + RecordConstantPrecisionTraverser(TSymbolTable *symbolTable); + + void visitConstantUnion(TIntermConstantUnion *node) override; + + protected: + bool operandAffectsParentOperationPrecision(TIntermTyped *operand); +}; + +RecordConstantPrecisionTraverser::RecordConstantPrecisionTraverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, false, true, symbolTable) +{} + +bool RecordConstantPrecisionTraverser::operandAffectsParentOperationPrecision(TIntermTyped *operand) +{ + if (getParentNode()->getAsCaseNode() || getParentNode()->getAsBlock()) + { + return false; + } + + if (operand->getBasicType() == EbtBool || operand->getBasicType() == EbtStruct) + { + return false; + } + + const TIntermBinary *parentAsBinary = getParentNode()->getAsBinaryNode(); + if (parentAsBinary != nullptr) + { + // If the constant is assigned or is used to initialize a variable, or if it's an index, + // its precision has no effect. + switch (parentAsBinary->getOp()) + { + case EOpInitialize: + case EOpAssign: + case EOpIndexDirect: + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: + case EOpIndexIndirect: + return false; + default: + return true; + } + } + + TIntermAggregate *parentAsAggregate = getParentNode()->getAsAggregate(); + if (parentAsAggregate != nullptr) + { + // The precision of an aggregate is derived from children only in the following conditions: + // + // - Built-in math operations + // - Constructors + // + return parentAsAggregate->isConstructor() || + BuiltInGroup::IsMath(parentAsAggregate->getOp()); + } + + return true; +} + +void RecordConstantPrecisionTraverser::visitConstantUnion(TIntermConstantUnion *node) +{ + // If the constant has lowp or undefined precision, it can't increase the precision of consuming + // operations. + if (node->getPrecision() < EbpMedium) + return; + + // It's possible the node has no effect on the precision of the consuming expression, depending + // on the consuming expression, and the precision of the other parameters of the expression. + if (!operandAffectsParentOperationPrecision(node)) + return; + + // Make the constant a precision-qualified named variable to make sure it affects the precision + // of the consuming expression. + TIntermDeclaration *variableDeclaration = nullptr; + TVariable *variable = DeclareTempVariable(mSymbolTable, node, EvqConst, &variableDeclaration); + insertStatementInParentBlock(variableDeclaration); + queueReplacement(CreateTempSymbolNode(variable), OriginalNode::IS_DROPPED); +} + +} // namespace + +bool RecordConstantPrecision(TCompiler *compiler, TIntermNode *root, TSymbolTable *symbolTable) +{ + RecordConstantPrecisionTraverser traverser(symbolTable); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RecordConstantPrecision.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/RecordConstantPrecision.h new file mode 100644 index 0000000000..f615b11221 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RecordConstantPrecision.h @@ -0,0 +1,33 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// During parsing, all constant expressions are folded to constant union nodes. The expressions that +// have been folded may have had precision qualifiers, which should affect the precision of the +// consuming operation. If the folded constant union nodes are written to output as such they won't +// have any precision qualifiers, and their effect on the precision of the consuming operation is +// lost. +// +// RecordConstantPrecision is an AST traverser that inspects the precision qualifiers of constants +// and hoists the constants outside the containing expression as precision qualified named variables +// in case that is required for correct precision propagation. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_RECORDCONSTANTPRECISION_H_ +#define COMPILER_TRANSLATOR_TREEOPS_RECORDCONSTANTPRECISION_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermNode; +class TSymbolTable; + +[[nodiscard]] bool RecordConstantPrecision(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_RECORDCONSTANTPRECISION_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveArrayLengthMethod.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveArrayLengthMethod.cpp new file mode 100644 index 0000000000..85ecb9346b --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveArrayLengthMethod.cpp @@ -0,0 +1,109 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RemoveArrayLengthMethod.cpp: +// Fold array length expressions, including cases where the "this" node has side effects. +// Example: +// int i = (a = b).length(); +// int j = (func()).length(); +// becomes: +// (a = b); +// int i = ; +// func(); +// int j = ; +// +// Must be run after SplitSequenceOperator, SimplifyLoopConditions and SeparateDeclarations steps +// have been done to expressions containing calls of the array length method. +// +// Does nothing to length method calls done on runtime-sized arrays. + +#include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h" + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class RemoveArrayLengthTraverser : public TIntermTraverser +{ + public: + RemoveArrayLengthTraverser() : TIntermTraverser(true, false, false), mFoundArrayLength(false) {} + + bool visitUnary(Visit visit, TIntermUnary *node) override; + + void nextIteration() { mFoundArrayLength = false; } + + bool foundArrayLength() const { return mFoundArrayLength; } + + private: + void insertSideEffectsInParentBlock(TIntermTyped *node); + + bool mFoundArrayLength; +}; + +bool RemoveArrayLengthTraverser::visitUnary(Visit visit, TIntermUnary *node) +{ + // The only case where we leave array length() in place is for runtime-sized arrays. + if (node->getOp() == EOpArrayLength && !node->getOperand()->getType().isUnsizedArray()) + { + mFoundArrayLength = true; + insertSideEffectsInParentBlock(node->getOperand()); + TConstantUnion *constArray = new TConstantUnion[1]; + constArray->setIConst(node->getOperand()->getOutermostArraySize()); + queueReplacement(new TIntermConstantUnion(constArray, node->getType()), + OriginalNode::IS_DROPPED); + return false; + } + return true; +} + +void RemoveArrayLengthTraverser::insertSideEffectsInParentBlock(TIntermTyped *node) +{ + // If the node is an index type, traverse it and add the indices as side effects. If at the end + // an expression without side effect is encountered, such as an opaque uniform or a lone symbol, + // don't generate a statement for it. + if (!node->hasSideEffects()) + { + return; + } + + TIntermBinary *asBinary = node->getAsBinaryNode(); + if (asBinary && !asBinary->isAssignment()) + { + insertSideEffectsInParentBlock(asBinary->getLeft()); + insertSideEffectsInParentBlock(asBinary->getRight()); + } + else + { + insertStatementInParentBlock(node); + } +} + +} // anonymous namespace + +bool RemoveArrayLengthMethod(TCompiler *compiler, TIntermBlock *root) +{ + RemoveArrayLengthTraverser traverser; + do + { + traverser.nextIteration(); + root->traverse(&traverser); + if (traverser.foundArrayLength()) + { + if (!traverser.updateTree(compiler, root)) + { + return false; + } + } + } while (traverser.foundArrayLength()); + + return true; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveArrayLengthMethod.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveArrayLengthMethod.h new file mode 100644 index 0000000000..8468e1e635 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveArrayLengthMethod.h @@ -0,0 +1,37 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RemoveArrayLengthMethod.h: +// Fold array length expressions, including cases where the "this" node has side effects. +// Example: +// int i = (a = b).length(); +// int j = (func()).length(); +// becomes: +// (a = b); +// int i = ; +// func(); +// int j = ; +// +// Must be run after SplitSequenceOperator, SimplifyLoopConditions and SeparateDeclarations steps +// have been done to expressions containing calls of the array length method. +// +// Does nothing to length method calls done on runtime-sized arrays. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_REMOVEARRAYLENGTHMETHOD_H_ +#define COMPILER_TRANSLATOR_TREEOPS_REMOVEARRAYLENGTHMETHOD_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; + +[[nodiscard]] bool RemoveArrayLengthMethod(TCompiler *compiler, TIntermBlock *root); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_REMOVEARRAYLENGTHMETHOD_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveAtomicCounterBuiltins.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveAtomicCounterBuiltins.cpp new file mode 100644 index 0000000000..ed0ba3fed8 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveAtomicCounterBuiltins.cpp @@ -0,0 +1,74 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RemoveAtomicCounterBuiltins: Remove atomic counter builtins. +// + +#include "compiler/translator/tree_ops/RemoveAtomicCounterBuiltins.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ +namespace +{ + +bool IsAtomicCounterDecl(const TIntermDeclaration *node) +{ + const TIntermSequence &sequence = *(node->getSequence()); + TIntermTyped *variable = sequence.front()->getAsTyped(); + const TType &type = variable->getType(); + return type.getQualifier() == EvqUniform && type.isAtomicCounter(); +} + +// Traverser that removes all GLSL built-ins that use AtomicCounters +// Only called when the builtins are in use, but no atomic counters have been declared +class RemoveAtomicCounterBuiltinsTraverser : public TIntermTraverser +{ + public: + RemoveAtomicCounterBuiltinsTraverser() : TIntermTraverser(true, false, false) {} + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + ASSERT(visit == PreVisit); + + // Active atomic counters should have been removed by RewriteAtomicCounters, and this + // traversal should not have been invoked + ASSERT(!IsAtomicCounterDecl(node)); + return false; + } + + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + if (node->getOp() == EOpMemoryBarrierAtomicCounter) + { + // Vulkan does not support atomic counters, so if this builtin finds its way here, + // we need to remove it. + TIntermSequence emptySequence; + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, + std::move(emptySequence)); + return true; + } + + // We shouldn't see any other builtins because they cannot be present without an active + // atomic counter, and should have been removed by RewriteAtomicCounters. If this fires, + // this traversal should not have been called. + ASSERT(!(BuiltInGroup::IsBuiltIn(node->getOp()) && + node->getFunction()->isAtomicCounterFunction())); + + return false; + } +}; + +} // anonymous namespace + +bool RemoveAtomicCounterBuiltins(TCompiler *compiler, TIntermBlock *root) +{ + RemoveAtomicCounterBuiltinsTraverser traverser; + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveAtomicCounterBuiltins.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveAtomicCounterBuiltins.h new file mode 100644 index 0000000000..efe8a53595 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveAtomicCounterBuiltins.h @@ -0,0 +1,24 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RemoveAtomicCounterBuiltins: Remove atomic counter builtins. +// Normally handled by RewriteAtomicCounters, but that is only invoked when +// atomic counters are actually in use. This pass removes the builtins and +// asserts no atomic counters are declared. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_REMOVEATOMICCOUNTERBUILTINS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_REMOVEATOMICCOUNTERBUILTINS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; + +[[nodiscard]] bool RemoveAtomicCounterBuiltins(TCompiler *compiler, TIntermBlock *root); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_REMOVEATOMICCOUNTERBUILTINS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveDynamicIndexing.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveDynamicIndexing.cpp new file mode 100644 index 0000000000..fda6de6f48 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveDynamicIndexing.cpp @@ -0,0 +1,597 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RemoveDynamicIndexing is an AST traverser to remove dynamic indexing of non-SSBO vectors and +// matrices, replacing them with calls to functions that choose which component to return or write. +// We don't need to consider dynamic indexing in SSBO since it can be directly as part of the offset +// of RWByteAddressBuffer. +// + +#include "compiler/translator/tree_ops/RemoveDynamicIndexing.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNodePatternMatcher.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +using DynamicIndexingNodeMatcher = std::function; + +const TType *kIndexType = StaticType::Get(); + +constexpr const ImmutableString kBaseName("base"); +constexpr const ImmutableString kIndexName("index"); +constexpr const ImmutableString kValueName("value"); + +std::string GetIndexFunctionName(const TType &type, bool write) +{ + TInfoSinkBase nameSink; + nameSink << "dyn_index_"; + if (write) + { + nameSink << "write_"; + } + if (type.isMatrix()) + { + nameSink << "mat" << static_cast(type.getCols()) << "x" + << static_cast(type.getRows()); + } + else + { + switch (type.getBasicType()) + { + case EbtInt: + nameSink << "ivec"; + break; + case EbtBool: + nameSink << "bvec"; + break; + case EbtUInt: + nameSink << "uvec"; + break; + case EbtFloat: + nameSink << "vec"; + break; + default: + UNREACHABLE(); + } + nameSink << static_cast(type.getNominalSize()); + } + return nameSink.str(); +} + +TIntermConstantUnion *CreateIntConstantNode(int i) +{ + TConstantUnion *constant = new TConstantUnion(); + constant->setIConst(i); + return new TIntermConstantUnion(constant, TType(EbtInt, EbpHigh)); +} + +TIntermTyped *EnsureSignedInt(TIntermTyped *node) +{ + if (node->getBasicType() == EbtInt) + return node; + + TIntermSequence arguments; + arguments.push_back(node); + return TIntermAggregate::CreateConstructor(TType(EbtInt), &arguments); +} + +TType *GetFieldType(const TType &indexedType) +{ + TType *fieldType = new TType(indexedType); + if (indexedType.isMatrix()) + { + fieldType->toMatrixColumnType(); + } + else + { + ASSERT(indexedType.isVector()); + fieldType->toComponentType(); + } + // Default precision to highp if not specified. For example in |vec3(0)[i], i < 0|, there is no + // precision assigned to vec3(0). + if (fieldType->getPrecision() == EbpUndefined) + { + fieldType->setPrecision(EbpHigh); + } + return fieldType; +} + +const TType *GetBaseType(const TType &type, bool write) +{ + TType *baseType = new TType(type); + // Conservatively use highp here, even if the indexed type is not highp. That way the code can't + // end up using mediump version of an indexing function for a highp value, if both mediump and + // highp values are being indexed in the shader. For HLSL precision doesn't matter, but in + // principle this code could be used with multiple backends. + baseType->setPrecision(EbpHigh); + baseType->setQualifier(EvqParamInOut); + if (!write) + baseType->setQualifier(EvqParamIn); + return baseType; +} + +// Generate a read or write function for one field in a vector/matrix. +// Out-of-range indices are clamped. This is consistent with how ANGLE handles out-of-range +// indices in other places. +// Note that indices can be either int or uint. We create only int versions of the functions, +// and convert uint indices to int at the call site. +// read function example: +// float dyn_index_vec2(in vec2 base, in int index) +// { +// switch(index) +// { +// case (0): +// return base[0]; +// case (1): +// return base[1]; +// default: +// break; +// } +// if (index < 0) +// return base[0]; +// return base[1]; +// } +// write function example: +// void dyn_index_write_vec2(inout vec2 base, in int index, in float value) +// { +// switch(index) +// { +// case (0): +// base[0] = value; +// return; +// case (1): +// base[1] = value; +// return; +// default: +// break; +// } +// if (index < 0) +// { +// base[0] = value; +// return; +// } +// base[1] = value; +// } +// Note that else is not used in above functions to avoid the RewriteElseBlocks transformation. +TIntermFunctionDefinition *GetIndexFunctionDefinition(const TType &type, + bool write, + const TFunction &func, + TSymbolTable *symbolTable) +{ + ASSERT(!type.isArray()); + + uint8_t numCases = 0; + if (type.isMatrix()) + { + numCases = type.getCols(); + } + else + { + numCases = type.getNominalSize(); + } + + std::string functionName = GetIndexFunctionName(type, write); + TIntermFunctionPrototype *prototypeNode = CreateInternalFunctionPrototypeNode(func); + + TIntermSymbol *baseParam = new TIntermSymbol(func.getParam(0)); + TIntermSymbol *indexParam = new TIntermSymbol(func.getParam(1)); + TIntermSymbol *valueParam = nullptr; + if (write) + { + valueParam = new TIntermSymbol(func.getParam(2)); + } + + TIntermBlock *statementList = new TIntermBlock(); + for (uint8_t i = 0; i < numCases; ++i) + { + TIntermCase *caseNode = new TIntermCase(CreateIntConstantNode(i)); + statementList->getSequence()->push_back(caseNode); + + TIntermBinary *indexNode = + new TIntermBinary(EOpIndexDirect, baseParam->deepCopy(), CreateIndexNode(i)); + if (write) + { + TIntermBinary *assignNode = + new TIntermBinary(EOpAssign, indexNode, valueParam->deepCopy()); + statementList->getSequence()->push_back(assignNode); + TIntermBranch *returnNode = new TIntermBranch(EOpReturn, nullptr); + statementList->getSequence()->push_back(returnNode); + } + else + { + TIntermBranch *returnNode = new TIntermBranch(EOpReturn, indexNode); + statementList->getSequence()->push_back(returnNode); + } + } + + // Default case + TIntermCase *defaultNode = new TIntermCase(nullptr); + statementList->getSequence()->push_back(defaultNode); + TIntermBranch *breakNode = new TIntermBranch(EOpBreak, nullptr); + statementList->getSequence()->push_back(breakNode); + + TIntermSwitch *switchNode = new TIntermSwitch(indexParam->deepCopy(), statementList); + + TIntermBlock *bodyNode = new TIntermBlock(); + bodyNode->getSequence()->push_back(switchNode); + + TIntermBinary *cond = + new TIntermBinary(EOpLessThan, indexParam->deepCopy(), CreateIntConstantNode(0)); + + // Two blocks: one accesses (either reads or writes) the first element and returns, + // the other accesses the last element. + TIntermBlock *useFirstBlock = new TIntermBlock(); + TIntermBlock *useLastBlock = new TIntermBlock(); + TIntermBinary *indexFirstNode = + new TIntermBinary(EOpIndexDirect, baseParam->deepCopy(), CreateIndexNode(0)); + TIntermBinary *indexLastNode = + new TIntermBinary(EOpIndexDirect, baseParam->deepCopy(), CreateIndexNode(numCases - 1)); + if (write) + { + TIntermBinary *assignFirstNode = + new TIntermBinary(EOpAssign, indexFirstNode, valueParam->deepCopy()); + useFirstBlock->getSequence()->push_back(assignFirstNode); + TIntermBranch *returnNode = new TIntermBranch(EOpReturn, nullptr); + useFirstBlock->getSequence()->push_back(returnNode); + + TIntermBinary *assignLastNode = + new TIntermBinary(EOpAssign, indexLastNode, valueParam->deepCopy()); + useLastBlock->getSequence()->push_back(assignLastNode); + } + else + { + TIntermBranch *returnFirstNode = new TIntermBranch(EOpReturn, indexFirstNode); + useFirstBlock->getSequence()->push_back(returnFirstNode); + + TIntermBranch *returnLastNode = new TIntermBranch(EOpReturn, indexLastNode); + useLastBlock->getSequence()->push_back(returnLastNode); + } + TIntermIfElse *ifNode = new TIntermIfElse(cond, useFirstBlock, nullptr); + bodyNode->getSequence()->push_back(ifNode); + bodyNode->getSequence()->push_back(useLastBlock); + + TIntermFunctionDefinition *indexingFunction = + new TIntermFunctionDefinition(prototypeNode, bodyNode); + return indexingFunction; +} + +class RemoveDynamicIndexingTraverser : public TLValueTrackingTraverser +{ + public: + RemoveDynamicIndexingTraverser(DynamicIndexingNodeMatcher &&matcher, + TSymbolTable *symbolTable, + PerformanceDiagnostics *perfDiagnostics); + + bool visitBinary(Visit visit, TIntermBinary *node) override; + + void insertHelperDefinitions(TIntermNode *root); + + void nextIteration(); + + bool usedTreeInsertion() const { return mUsedTreeInsertion; } + + protected: + // Maps of types that are indexed to the indexing function ids used for them. Note that these + // can not store multiple variants of the same type with different precisions - only one + // precision gets stored. + std::map mIndexedVecAndMatrixTypes; + std::map mWrittenVecAndMatrixTypes; + + bool mUsedTreeInsertion; + + // When true, the traverser will remove side effects from any indexing expression. + // This is done so that in code like + // V[j++][i]++. + // where V is an array of vectors, j++ will only be evaluated once. + bool mRemoveIndexSideEffectsInSubtree; + + DynamicIndexingNodeMatcher mMatcher; + PerformanceDiagnostics *mPerfDiagnostics; +}; + +RemoveDynamicIndexingTraverser::RemoveDynamicIndexingTraverser( + DynamicIndexingNodeMatcher &&matcher, + TSymbolTable *symbolTable, + PerformanceDiagnostics *perfDiagnostics) + : TLValueTrackingTraverser(true, false, false, symbolTable), + mUsedTreeInsertion(false), + mRemoveIndexSideEffectsInSubtree(false), + mMatcher(matcher), + mPerfDiagnostics(perfDiagnostics) +{} + +void RemoveDynamicIndexingTraverser::insertHelperDefinitions(TIntermNode *root) +{ + TIntermBlock *rootBlock = root->getAsBlock(); + ASSERT(rootBlock != nullptr); + TIntermSequence insertions; + for (auto &type : mIndexedVecAndMatrixTypes) + { + insertions.push_back( + GetIndexFunctionDefinition(type.first, false, *type.second, mSymbolTable)); + } + for (auto &type : mWrittenVecAndMatrixTypes) + { + insertions.push_back( + GetIndexFunctionDefinition(type.first, true, *type.second, mSymbolTable)); + } + rootBlock->insertChildNodes(0, insertions); +} + +// Create a call to dyn_index_*() based on an indirect indexing op node +TIntermAggregate *CreateIndexFunctionCall(TIntermBinary *node, + TIntermTyped *index, + TFunction *indexingFunction) +{ + ASSERT(node->getOp() == EOpIndexIndirect); + TIntermSequence arguments; + arguments.push_back(node->getLeft()); + arguments.push_back(index); + + TIntermAggregate *indexingCall = + TIntermAggregate::CreateFunctionCall(*indexingFunction, &arguments); + indexingCall->setLine(node->getLine()); + return indexingCall; +} + +TIntermAggregate *CreateIndexedWriteFunctionCall(TIntermBinary *node, + TVariable *index, + TVariable *writtenValue, + TFunction *indexedWriteFunction) +{ + ASSERT(node->getOp() == EOpIndexIndirect); + TIntermSequence arguments; + // Deep copy the child nodes so that two pointers to the same node don't end up in the tree. + arguments.push_back(node->getLeft()->deepCopy()); + arguments.push_back(CreateTempSymbolNode(index)); + arguments.push_back(CreateTempSymbolNode(writtenValue)); + + TIntermAggregate *indexedWriteCall = + TIntermAggregate::CreateFunctionCall(*indexedWriteFunction, &arguments); + indexedWriteCall->setLine(node->getLine()); + return indexedWriteCall; +} + +bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *node) +{ + if (mUsedTreeInsertion) + return false; + + if (node->getOp() == EOpIndexIndirect) + { + if (mRemoveIndexSideEffectsInSubtree) + { + ASSERT(node->getRight()->hasSideEffects()); + // In case we're just removing index side effects, convert + // v_expr[index_expr] + // to this: + // int s0 = index_expr; v_expr[s0]; + // Now v_expr[s0] can be safely executed several times without unintended side effects. + TIntermDeclaration *indexVariableDeclaration = nullptr; + TVariable *indexVariable = DeclareTempVariable(mSymbolTable, node->getRight(), + EvqTemporary, &indexVariableDeclaration); + insertStatementInParentBlock(indexVariableDeclaration); + mUsedTreeInsertion = true; + + // Replace the index with the temp variable + TIntermSymbol *tempIndex = CreateTempSymbolNode(indexVariable); + queueReplacementWithParent(node, node->getRight(), tempIndex, OriginalNode::IS_DROPPED); + } + else if (mMatcher(node)) + { + if (mPerfDiagnostics) + { + mPerfDiagnostics->warning(node->getLine(), + "Performance: dynamic indexing of vectors and " + "matrices is emulated and can be slow.", + "[]"); + } + bool write = isLValueRequiredHere(); + +#if defined(ANGLE_ENABLE_ASSERTS) + // Make sure that IntermNodePatternMatcher is consistent with the slightly differently + // implemented checks in this traverser. + IntermNodePatternMatcher matcher( + IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue); + ASSERT(matcher.match(node, getParentNode(), isLValueRequiredHere()) == write); +#endif + + const TType &type = node->getLeft()->getType(); + ImmutableString indexingFunctionName(GetIndexFunctionName(type, false)); + TFunction *indexingFunction = nullptr; + if (mIndexedVecAndMatrixTypes.find(type) == mIndexedVecAndMatrixTypes.end()) + { + indexingFunction = + new TFunction(mSymbolTable, indexingFunctionName, SymbolType::AngleInternal, + GetFieldType(type), true); + indexingFunction->addParameter(new TVariable( + mSymbolTable, kBaseName, GetBaseType(type, false), SymbolType::AngleInternal)); + indexingFunction->addParameter( + new TVariable(mSymbolTable, kIndexName, kIndexType, SymbolType::AngleInternal)); + mIndexedVecAndMatrixTypes[type] = indexingFunction; + } + else + { + indexingFunction = mIndexedVecAndMatrixTypes[type]; + } + + if (write) + { + // Convert: + // v_expr[index_expr]++; + // to this: + // int s0 = index_expr; float s1 = dyn_index(v_expr, s0); s1++; + // dyn_index_write(v_expr, s0, s1); + // This works even if index_expr has some side effects. + if (node->getLeft()->hasSideEffects()) + { + // If v_expr has side effects, those need to be removed before proceeding. + // Otherwise the side effects of v_expr would be evaluated twice. + // The only case where an l-value can have side effects is when it is + // indexing. For example, it can be V[j++] where V is an array of vectors. + mRemoveIndexSideEffectsInSubtree = true; + return true; + } + + TIntermBinary *leftBinary = node->getLeft()->getAsBinaryNode(); + if (leftBinary != nullptr && mMatcher(leftBinary)) + { + // This is a case like: + // mat2 m; + // m[a][b]++; + // Process the child node m[a] first. + return true; + } + + // TODO(oetuaho@nvidia.com): This is not optimal if the expression using the value + // only writes it and doesn't need the previous value. http://anglebug.com/1116 + + TFunction *indexedWriteFunction = nullptr; + if (mWrittenVecAndMatrixTypes.find(type) == mWrittenVecAndMatrixTypes.end()) + { + ImmutableString functionName( + GetIndexFunctionName(node->getLeft()->getType(), true)); + indexedWriteFunction = + new TFunction(mSymbolTable, functionName, SymbolType::AngleInternal, + StaticType::GetBasic(), false); + indexedWriteFunction->addParameter(new TVariable(mSymbolTable, kBaseName, + GetBaseType(type, true), + SymbolType::AngleInternal)); + indexedWriteFunction->addParameter(new TVariable( + mSymbolTable, kIndexName, kIndexType, SymbolType::AngleInternal)); + TType *valueType = GetFieldType(type); + valueType->setQualifier(EvqParamIn); + indexedWriteFunction->addParameter(new TVariable( + mSymbolTable, kValueName, static_cast(valueType), + SymbolType::AngleInternal)); + mWrittenVecAndMatrixTypes[type] = indexedWriteFunction; + } + else + { + indexedWriteFunction = mWrittenVecAndMatrixTypes[type]; + } + + TIntermSequence insertionsBefore; + TIntermSequence insertionsAfter; + + // Store the index in a temporary signed int variable. + // s0 = index_expr; + TIntermTyped *indexInitializer = EnsureSignedInt(node->getRight()); + TIntermDeclaration *indexVariableDeclaration = nullptr; + TVariable *indexVariable = DeclareTempVariable( + mSymbolTable, indexInitializer, EvqTemporary, &indexVariableDeclaration); + insertionsBefore.push_back(indexVariableDeclaration); + + // s1 = dyn_index(v_expr, s0); + TIntermAggregate *indexingCall = CreateIndexFunctionCall( + node, CreateTempSymbolNode(indexVariable), indexingFunction); + TIntermDeclaration *fieldVariableDeclaration = nullptr; + TVariable *fieldVariable = DeclareTempVariable( + mSymbolTable, indexingCall, EvqTemporary, &fieldVariableDeclaration); + insertionsBefore.push_back(fieldVariableDeclaration); + + // dyn_index_write(v_expr, s0, s1); + TIntermAggregate *indexedWriteCall = CreateIndexedWriteFunctionCall( + node, indexVariable, fieldVariable, indexedWriteFunction); + insertionsAfter.push_back(indexedWriteCall); + insertStatementsInParentBlock(insertionsBefore, insertionsAfter); + + // replace the node with s1 + queueReplacement(CreateTempSymbolNode(fieldVariable), OriginalNode::IS_DROPPED); + mUsedTreeInsertion = true; + } + else + { + // The indexed value is not being written, so we can simply convert + // v_expr[index_expr] + // into + // dyn_index(v_expr, index_expr) + // If the index_expr is unsigned, we'll convert it to signed. + ASSERT(!mRemoveIndexSideEffectsInSubtree); + TIntermAggregate *indexingCall = CreateIndexFunctionCall( + node, EnsureSignedInt(node->getRight()), indexingFunction); + queueReplacement(indexingCall, OriginalNode::IS_DROPPED); + } + } + } + return !mUsedTreeInsertion; +} + +void RemoveDynamicIndexingTraverser::nextIteration() +{ + mUsedTreeInsertion = false; + mRemoveIndexSideEffectsInSubtree = false; +} + +bool RemoveDynamicIndexingIf(DynamicIndexingNodeMatcher &&matcher, + TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable, + PerformanceDiagnostics *perfDiagnostics) +{ + // This transformation adds function declarations after the fact and so some validation is + // momentarily disabled. + bool enableValidateFunctionCall = compiler->disableValidateFunctionCall(); + + RemoveDynamicIndexingTraverser traverser(std::move(matcher), symbolTable, perfDiagnostics); + do + { + traverser.nextIteration(); + root->traverse(&traverser); + if (!traverser.updateTree(compiler, root)) + { + return false; + } + } while (traverser.usedTreeInsertion()); + // TODO(oetuaho@nvidia.com): It might be nicer to add the helper definitions also in the middle + // of traversal. Now the tree ends up in an inconsistent state in the middle, since there are + // function call nodes with no corresponding definition nodes. This needs special handling in + // TIntermLValueTrackingTraverser, and creates intricacies that are not easily apparent from a + // superficial reading of the code. + traverser.insertHelperDefinitions(root); + + compiler->restoreValidateFunctionCall(enableValidateFunctionCall); + return compiler->validateAST(root); +} + +} // namespace + +[[nodiscard]] bool RemoveDynamicIndexingOfNonSSBOVectorOrMatrix( + TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable, + PerformanceDiagnostics *perfDiagnostics) +{ + DynamicIndexingNodeMatcher matcher = [](TIntermBinary *node) { + return IntermNodePatternMatcher::IsDynamicIndexingOfNonSSBOVectorOrMatrix(node); + }; + return RemoveDynamicIndexingIf(std::move(matcher), compiler, root, symbolTable, + perfDiagnostics); +} + +[[nodiscard]] bool RemoveDynamicIndexingOfSwizzledVector(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable, + PerformanceDiagnostics *perfDiagnostics) +{ + DynamicIndexingNodeMatcher matcher = [](TIntermBinary *node) { + return IntermNodePatternMatcher::IsDynamicIndexingOfSwizzledVector(node); + }; + return RemoveDynamicIndexingIf(std::move(matcher), compiler, root, symbolTable, + perfDiagnostics); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveDynamicIndexing.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveDynamicIndexing.h new file mode 100644 index 0000000000..9693f55c40 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveDynamicIndexing.h @@ -0,0 +1,41 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RemoveDynamicIndexing is an AST traverser to remove dynamic indexing of non-SSBO vectors and +// matrices, replacing them with calls to functions that choose which component to return or write. +// We don't need to consider dynamic indexing in SSBO since it can be directly as part of the offset +// of RWByteAddressBuffer. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_REMOVEDYNAMICINDEXING_H_ +#define COMPILER_TRANSLATOR_TREEOPS_REMOVEDYNAMICINDEXING_H_ + +#include "common/angleutils.h" + +#include + +namespace sh +{ + +class TCompiler; +class TIntermNode; +class TIntermBinary; +class TSymbolTable; +class PerformanceDiagnostics; + +[[nodiscard]] bool RemoveDynamicIndexingOfNonSSBOVectorOrMatrix( + TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable, + PerformanceDiagnostics *perfDiagnostics); + +[[nodiscard]] bool RemoveDynamicIndexingOfSwizzledVector(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable, + PerformanceDiagnostics *perfDiagnostics); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_REMOVEDYNAMICINDEXING_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.cpp new file mode 100644 index 0000000000..a5e20ebcb0 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.cpp @@ -0,0 +1,209 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RemoveInactiveInterfaceVariables.h: +// Drop shader interface variable declarations for those that are inactive. +// + +#include "compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.h" + +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +// Traverser that removes all declarations that correspond to inactive variables. +class RemoveInactiveInterfaceVariablesTraverser : public TIntermTraverser +{ + public: + RemoveInactiveInterfaceVariablesTraverser( + TSymbolTable *symbolTable, + const std::vector &attributes, + const std::vector &inputVaryings, + const std::vector &outputVariables, + const std::vector &uniforms, + const std::vector &interfaceBlocks, + bool removeFragmentOutputs); + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; + bool visitBinary(Visit visit, TIntermBinary *node) override; + + private: + const std::vector &mAttributes; + const std::vector &mInputVaryings; + const std::vector &mOutputVariables; + const std::vector &mUniforms; + const std::vector &mInterfaceBlocks; + bool mRemoveFragmentOutputs; +}; + +RemoveInactiveInterfaceVariablesTraverser::RemoveInactiveInterfaceVariablesTraverser( + TSymbolTable *symbolTable, + const std::vector &attributes, + const std::vector &inputVaryings, + const std::vector &outputVariables, + const std::vector &uniforms, + const std::vector &interfaceBlocks, + bool removeFragmentOutputs) + : TIntermTraverser(true, false, false, symbolTable), + mAttributes(attributes), + mInputVaryings(inputVaryings), + mOutputVariables(outputVariables), + mUniforms(uniforms), + mInterfaceBlocks(interfaceBlocks), + mRemoveFragmentOutputs(removeFragmentOutputs) +{} + +template +bool IsVariableActive(const std::vector &mVars, const ImmutableString &name) +{ + for (const Variable &var : mVars) + { + if (name == var.name) + { + return var.active; + } + } + UNREACHABLE(); + return true; +} + +bool RemoveInactiveInterfaceVariablesTraverser::visitDeclaration(Visit visit, + TIntermDeclaration *node) +{ + // SeparateDeclarations should have already been run. + ASSERT(node->getSequence()->size() == 1u); + + TIntermTyped *declarator = node->getSequence()->front()->getAsTyped(); + ASSERT(declarator); + + TIntermSymbol *asSymbol = declarator->getAsSymbolNode(); + if (!asSymbol) + { + return false; + } + + const TType &type = declarator->getType(); + + // Remove all shader interface variables except outputs, i.e. uniforms, interface blocks and + // inputs. + // + // Imagine a situation where the VS doesn't write to a varying but the FS reads from it. This + // is allowed, though the value of the varying is undefined. If the varying is removed here, + // the situation is changed to VS not declaring the varying, but the FS reading from it, which + // is not allowed. That's why inactive shader outputs are not removed. + // + // Inactive fragment shader outputs can be removed though, as there is no next stage. + bool removeDeclaration = false; + const TQualifier qualifier = type.getQualifier(); + + if (type.isInterfaceBlock()) + { + // When a member has an explicit location, interface block should not be removed. + // If the member or interface would be removed, GetProgramResource could not return the + // location. + if (!IsShaderIoBlock(type.getQualifier()) && type.getQualifier() != EvqPatchIn && + type.getQualifier() != EvqPatchOut) + { + removeDeclaration = + !IsVariableActive(mInterfaceBlocks, type.getInterfaceBlock()->name()); + } + } + else if (qualifier == EvqUniform) + { + removeDeclaration = !IsVariableActive(mUniforms, asSymbol->getName()); + } + else if (qualifier == EvqAttribute || qualifier == EvqVertexIn) + { + removeDeclaration = !IsVariableActive(mAttributes, asSymbol->getName()); + } + else if (IsShaderIn(qualifier)) + { + removeDeclaration = !IsVariableActive(mInputVaryings, asSymbol->getName()); + } + else if (qualifier == EvqFragmentOut) + { + removeDeclaration = + !IsVariableActive(mOutputVariables, asSymbol->getName()) && mRemoveFragmentOutputs; + } + + if (removeDeclaration) + { + TIntermSequence replacement; + + // If the declaration was of a struct, keep the struct declaration itself. + if (type.isStructSpecifier()) + { + TType *structSpecifierType = new TType(type.getStruct(), true); + TVariable *emptyVariable = new TVariable(mSymbolTable, kEmptyImmutableString, + structSpecifierType, SymbolType::Empty); + TIntermDeclaration *declaration = new TIntermDeclaration(); + declaration->appendDeclarator(new TIntermSymbol(emptyVariable)); + replacement.push_back(declaration); + } + + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, + std::move(replacement)); + } + + return false; +} + +bool RemoveInactiveInterfaceVariablesTraverser::visitBinary(Visit visit, TIntermBinary *node) +{ + // Remove any code that initOutputVariables might have added corresponding to inactive + // output variables. This code is always in the form of `variable = ...;`. + if (node->getOp() != EOpAssign) + { + // Don't recurse, won't find the initialization nested in another expression. + return false; + } + + // Get the symbol being initialized, and check if it's an inactive output. If it is, this must + // necessarily be initialization code that ANGLE has added (and wasn't there in the original + // shader; if it was, the symbol wouldn't have been inactive). + TIntermSymbol *symbol = node->getLeft()->getAsSymbolNode(); + if (symbol == nullptr) + { + return false; + } + + const TQualifier qualifier = symbol->getType().getQualifier(); + if (qualifier != EvqFragmentOut || IsVariableActive(mOutputVariables, symbol->getName())) + { + return false; + } + + // Drop the initialization code. + TIntermSequence replacement; + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, std::move(replacement)); + return false; +} + +} // namespace + +bool RemoveInactiveInterfaceVariables(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const std::vector &attributes, + const std::vector &inputVaryings, + const std::vector &outputVariables, + const std::vector &uniforms, + const std::vector &interfaceBlocks, + bool removeFragmentOutputs) +{ + RemoveInactiveInterfaceVariablesTraverser traverser(symbolTable, attributes, inputVaryings, + outputVariables, uniforms, interfaceBlocks, + removeFragmentOutputs); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.h new file mode 100644 index 0000000000..ddbdea2ced --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.h @@ -0,0 +1,42 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RemoveInactiveInterfaceVariables.h: +// Drop shader interface variable declarations for those that are inactive. This step needs to be +// done after CollectVariables. This avoids having to emulate them (e.g. atomic counters for +// Vulkan) or remove them in glslang wrapper (again, for Vulkan). +// +// Shouldn't be run for the GL backend, as it queries shader interface variables from GL itself, +// instead of relying on what was gathered during CollectVariables. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_REMOVEINACTIVEVARIABLES_H_ +#define COMPILER_TRANSLATOR_TREEOPS_REMOVEINACTIVEVARIABLES_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +struct InterfaceBlock; +struct ShaderVariable; +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool RemoveInactiveInterfaceVariables( + TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const std::vector &attributes, + const std::vector &inputVaryings, + const std::vector &outputVariables, + const std::vector &uniforms, + const std::vector &interfaceBlocks, + bool removeFragmentOutputs); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_REMOVEINACTIVEVARIABLES_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInvariantDeclaration.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInvariantDeclaration.cpp new file mode 100644 index 0000000000..5a8ca44150 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInvariantDeclaration.cpp @@ -0,0 +1,47 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/tree_ops/RemoveInvariantDeclaration.h" + +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +// An AST traverser that removes invariant declaration for input in fragment shader +// when GLSL >= 4.20 and for output in vertex shader when GLSL < 4.2. +class RemoveInvariantDeclarationTraverser : public TIntermTraverser +{ + public: + RemoveInvariantDeclarationTraverser() : TIntermTraverser(true, false, false) {} + + private: + bool visitGlobalQualifierDeclaration(Visit visit, + TIntermGlobalQualifierDeclaration *node) override + { + if (node->isInvariant()) + { + TIntermSequence emptyReplacement; + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, + std::move(emptyReplacement)); + } + return false; + } +}; + +} // anonymous namespace + +bool RemoveInvariantDeclaration(TCompiler *compiler, TIntermNode *root) +{ + RemoveInvariantDeclarationTraverser traverser; + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInvariantDeclaration.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInvariantDeclaration.h new file mode 100644 index 0000000000..0fee87b3b1 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveInvariantDeclaration.h @@ -0,0 +1,21 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_REMOVEINVARIANTDECLARATION_H_ +#define COMPILER_TRANSLATOR_TREEOPS_REMOVEINVARIANTDECLARATION_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermNode; + +[[nodiscard]] bool RemoveInvariantDeclaration(TCompiler *compiler, TIntermNode *root); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_REMOVEINVARIANTDECLARATION_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveUnreferencedVariables.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveUnreferencedVariables.cpp new file mode 100644 index 0000000000..b87ad33633 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveUnreferencedVariables.cpp @@ -0,0 +1,371 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RemoveUnreferencedVariables.cpp: +// Drop variables that are declared but never referenced in the AST. This avoids adding unnecessary +// initialization code for them. Also removes unreferenced struct types. +// + +#include "compiler/translator/tree_ops/RemoveUnreferencedVariables.h" + +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class CollectVariableRefCountsTraverser : public TIntermTraverser +{ + public: + CollectVariableRefCountsTraverser(); + + using RefCountMap = angle::HashMap; + RefCountMap &getSymbolIdRefCounts() { return mSymbolIdRefCounts; } + RefCountMap &getStructIdRefCounts() { return mStructIdRefCounts; } + + void visitSymbol(TIntermSymbol *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + void visitFunctionPrototype(TIntermFunctionPrototype *node) override; + + private: + void incrementStructTypeRefCount(const TType &type); + + RefCountMap mSymbolIdRefCounts; + + // Structure reference counts are counted from symbols, constructors, function calls, function + // return values and from interface block and structure fields. We need to track both function + // calls and function return values since there's a compiler option not to prune unused + // functions. The type of a constant union may also be a struct, but statements that are just a + // constant union are always pruned, and if the constant union is used somehow it will get + // counted by something else. + RefCountMap mStructIdRefCounts; +}; + +CollectVariableRefCountsTraverser::CollectVariableRefCountsTraverser() + : TIntermTraverser(true, false, false) +{} + +void CollectVariableRefCountsTraverser::incrementStructTypeRefCount(const TType &type) +{ + if (type.isInterfaceBlock()) + { + const auto *block = type.getInterfaceBlock(); + ASSERT(block); + + // We can end up incrementing ref counts of struct types referenced from an interface block + // multiple times for the same block. This doesn't matter, because interface blocks can't be + // pruned so we'll never do the reverse operation. + for (const auto &field : block->fields()) + { + ASSERT(!field->type()->isInterfaceBlock()); + incrementStructTypeRefCount(*field->type()); + } + return; + } + + const auto *structure = type.getStruct(); + if (structure != nullptr) + { + auto structIter = mStructIdRefCounts.find(structure->uniqueId().get()); + if (structIter == mStructIdRefCounts.end()) + { + mStructIdRefCounts[structure->uniqueId().get()] = 1u; + + for (const auto &field : structure->fields()) + { + incrementStructTypeRefCount(*field->type()); + } + + return; + } + ++(structIter->second); + } +} + +void CollectVariableRefCountsTraverser::visitSymbol(TIntermSymbol *node) +{ + incrementStructTypeRefCount(node->getType()); + + auto iter = mSymbolIdRefCounts.find(node->uniqueId().get()); + if (iter == mSymbolIdRefCounts.end()) + { + mSymbolIdRefCounts[node->uniqueId().get()] = 1u; + return; + } + ++(iter->second); +} + +bool CollectVariableRefCountsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + // This tracks struct references in both function calls and constructors. + incrementStructTypeRefCount(node->getType()); + return true; +} + +void CollectVariableRefCountsTraverser::visitFunctionPrototype(TIntermFunctionPrototype *node) +{ + incrementStructTypeRefCount(node->getType()); + size_t paramCount = node->getFunction()->getParamCount(); + for (size_t i = 0; i < paramCount; ++i) + { + incrementStructTypeRefCount(node->getFunction()->getParam(i)->getType()); + } +} + +// Traverser that removes all unreferenced variables on one traversal. +class RemoveUnreferencedVariablesTraverser : public TIntermTraverser +{ + public: + RemoveUnreferencedVariablesTraverser( + CollectVariableRefCountsTraverser::RefCountMap *symbolIdRefCounts, + CollectVariableRefCountsTraverser::RefCountMap *structIdRefCounts, + TSymbolTable *symbolTable); + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; + void visitSymbol(TIntermSymbol *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + + // Traverse loop and block nodes in reverse order. Note that this traverser does not track + // parent block positions, so insertStatementInParentBlock is unusable! + void traverseBlock(TIntermBlock *block) override; + void traverseLoop(TIntermLoop *loop) override; + + private: + void removeVariableDeclaration(TIntermDeclaration *node, TIntermTyped *declarator); + void decrementStructTypeRefCount(const TType &type); + + CollectVariableRefCountsTraverser::RefCountMap *mSymbolIdRefCounts; + CollectVariableRefCountsTraverser::RefCountMap *mStructIdRefCounts; + bool mRemoveReferences; +}; + +RemoveUnreferencedVariablesTraverser::RemoveUnreferencedVariablesTraverser( + CollectVariableRefCountsTraverser::RefCountMap *symbolIdRefCounts, + CollectVariableRefCountsTraverser::RefCountMap *structIdRefCounts, + TSymbolTable *symbolTable) + : TIntermTraverser(true, false, true, symbolTable), + mSymbolIdRefCounts(symbolIdRefCounts), + mStructIdRefCounts(structIdRefCounts), + mRemoveReferences(false) +{} + +void RemoveUnreferencedVariablesTraverser::decrementStructTypeRefCount(const TType &type) +{ + auto *structure = type.getStruct(); + if (structure != nullptr) + { + ASSERT(mStructIdRefCounts->find(structure->uniqueId().get()) != mStructIdRefCounts->end()); + unsigned int structRefCount = --(*mStructIdRefCounts)[structure->uniqueId().get()]; + + if (structRefCount == 0) + { + for (const auto &field : structure->fields()) + { + decrementStructTypeRefCount(*field->type()); + } + } + } +} + +void RemoveUnreferencedVariablesTraverser::removeVariableDeclaration(TIntermDeclaration *node, + TIntermTyped *declarator) +{ + if (declarator->getType().isStructSpecifier() && !declarator->getType().isNamelessStruct()) + { + unsigned int structId = declarator->getType().getStruct()->uniqueId().get(); + unsigned int structRefCountInThisDeclarator = 1u; + if (declarator->getAsBinaryNode() && + declarator->getAsBinaryNode()->getRight()->getAsAggregate()) + { + ASSERT(declarator->getAsBinaryNode()->getLeft()->getType().getStruct() == + declarator->getType().getStruct()); + ASSERT(declarator->getAsBinaryNode()->getRight()->getType().getStruct() == + declarator->getType().getStruct()); + structRefCountInThisDeclarator = 2u; + } + if ((*mStructIdRefCounts)[structId] > structRefCountInThisDeclarator) + { + // If this declaration declares a named struct type that is used elsewhere, we need to + // keep it. We can still change the declarator though so that it doesn't declare an + // unreferenced variable. + + // Note that since we're not removing the entire declaration, the struct's reference + // count will end up being one less than the correct refcount. But since the struct + // declaration is kept, the incorrect refcount can't cause any other problems. + + if (declarator->getAsSymbolNode() && + declarator->getAsSymbolNode()->variable().symbolType() == SymbolType::Empty) + { + // Already an empty declaration - nothing to do. + return; + } + TVariable *emptyVariable = + new TVariable(mSymbolTable, kEmptyImmutableString, new TType(declarator->getType()), + SymbolType::Empty); + queueReplacementWithParent(node, declarator, new TIntermSymbol(emptyVariable), + OriginalNode::IS_DROPPED); + return; + } + } + + if (getParentNode()->getAsBlock()) + { + TIntermSequence emptyReplacement; + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, + std::move(emptyReplacement)); + } + else + { + ASSERT(getParentNode()->getAsLoopNode()); + queueReplacement(nullptr, OriginalNode::IS_DROPPED); + } +} + +bool RemoveUnreferencedVariablesTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) +{ + if (visit == PreVisit) + { + // SeparateDeclarations should have already been run. + ASSERT(node->getSequence()->size() == 1u); + + TIntermTyped *declarator = node->getSequence()->back()->getAsTyped(); + ASSERT(declarator); + + // We can only remove variables that are not a part of the shader interface. + TQualifier qualifier = declarator->getQualifier(); + if (qualifier != EvqTemporary && qualifier != EvqGlobal && qualifier != EvqConst) + { + return true; + } + + bool canRemoveVariable = false; + TIntermSymbol *symbolNode = declarator->getAsSymbolNode(); + if (symbolNode != nullptr) + { + canRemoveVariable = (*mSymbolIdRefCounts)[symbolNode->uniqueId().get()] == 1u || + symbolNode->variable().symbolType() == SymbolType::Empty; + } + TIntermBinary *initNode = declarator->getAsBinaryNode(); + if (initNode != nullptr) + { + ASSERT(initNode->getLeft()->getAsSymbolNode()); + int symbolId = initNode->getLeft()->getAsSymbolNode()->uniqueId().get(); + canRemoveVariable = + (*mSymbolIdRefCounts)[symbolId] == 1u && !initNode->getRight()->hasSideEffects(); + } + + if (canRemoveVariable) + { + removeVariableDeclaration(node, declarator); + mRemoveReferences = true; + } + return true; + } + ASSERT(visit == PostVisit); + mRemoveReferences = false; + return true; +} + +void RemoveUnreferencedVariablesTraverser::visitSymbol(TIntermSymbol *node) +{ + if (mRemoveReferences) + { + ASSERT(mSymbolIdRefCounts->find(node->uniqueId().get()) != mSymbolIdRefCounts->end()); + --(*mSymbolIdRefCounts)[node->uniqueId().get()]; + + decrementStructTypeRefCount(node->getType()); + } +} + +bool RemoveUnreferencedVariablesTraverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + if (visit == PreVisit && mRemoveReferences) + { + decrementStructTypeRefCount(node->getType()); + } + return true; +} + +void RemoveUnreferencedVariablesTraverser::traverseBlock(TIntermBlock *node) +{ + // We traverse blocks in reverse order. This way reference counts can be decremented when + // removing initializers, and variables that become unused when initializers are removed can be + // removed on the same traversal. + + ScopedNodeInTraversalPath addToPath(this, node); + + bool visit = true; + + TIntermSequence *sequence = node->getSequence(); + + if (preVisit) + visit = visitBlock(PreVisit, node); + + if (visit) + { + for (auto iter = sequence->rbegin(); iter != sequence->rend(); ++iter) + { + (*iter)->traverse(this); + if (visit && inVisit) + { + if ((iter + 1) != sequence->rend()) + visit = visitBlock(InVisit, node); + } + } + } + + if (visit && postVisit) + visitBlock(PostVisit, node); +} + +void RemoveUnreferencedVariablesTraverser::traverseLoop(TIntermLoop *node) +{ + // We traverse loops in reverse order as well. The loop body gets traversed before the init + // node. + + ScopedNodeInTraversalPath addToPath(this, node); + + bool visit = true; + + if (preVisit) + visit = visitLoop(PreVisit, node); + + if (visit) + { + // We don't need to traverse loop expressions or conditions since they can't be declarations + // in the AST (loops which have a declaration in their condition get transformed in the + // parsing stage). + ASSERT(node->getExpression() == nullptr || + node->getExpression()->getAsDeclarationNode() == nullptr); + ASSERT(node->getCondition() == nullptr || + node->getCondition()->getAsDeclarationNode() == nullptr); + + if (node->getBody()) + node->getBody()->traverse(this); + + if (node->getInit()) + node->getInit()->traverse(this); + } + + if (visit && postVisit) + visitLoop(PostVisit, node); +} + +} // namespace + +bool RemoveUnreferencedVariables(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable) +{ + CollectVariableRefCountsTraverser collector; + root->traverse(&collector); + RemoveUnreferencedVariablesTraverser traverser(&collector.getSymbolIdRefCounts(), + &collector.getStructIdRefCounts(), symbolTable); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveUnreferencedVariables.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveUnreferencedVariables.h new file mode 100644 index 0000000000..071d19e51e --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RemoveUnreferencedVariables.h @@ -0,0 +1,29 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RemoveUnreferencedVariables.h: +// Drop variables that are declared but never referenced in the AST. This avoids adding unnecessary +// initialization code for them. Also removes unreferenced struct types. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_REMOVEUNREFERENCEDVARIABLES_H_ +#define COMPILER_TRANSLATOR_TREEOPS_REMOVEUNREFERENCEDVARIABLES_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool RemoveUnreferencedVariables(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_REMOVEUNREFERENCEDVARIABLES_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.cpp new file mode 100644 index 0000000000..bd12cd1006 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.cpp @@ -0,0 +1,348 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteAtomicCounters: Emulate atomic counter buffers with storage buffers. +// + +#include "compiler/translator/tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" + +namespace sh +{ +namespace +{ +struct UniformData +{ + // Corresponding to an array of array of opaque uniform variable, this is the flattened variable + // that is replacing it. + const TVariable *flattened; + // Assume a general case of array declaration with N dimensions: + // + // uniform type u[Dn]..[D2][D1]; + // + // Let's define + // + // Pn = D(n-1)*...*D2*D1 + // + // In that case, we have: + // + // u[In] = ac + In*Pn + // u[In][I(n-1)] = ac + In*Pn + I(n-1)*P(n-1) + // u[In]...[Ii] = ac + In*Pn + ... + Ii*Pi + // + // This array contains Pi. Note that the like TType::mArraySizes, the last element is the + // outermost dimension. Element 0 is necessarily 1. + TVector mSubArraySizes; +}; + +using UniformMap = angle::HashMap; + +TIntermTyped *RewriteArrayOfArraySubscriptExpression(TCompiler *compiler, + TIntermBinary *node, + const UniformMap &uniformMap); + +// Given an expression, this traverser calculates a new expression where array of array of opaque +// uniforms are replaced with their flattened ones. In particular, this is run on the right node of +// EOpIndexIndirect binary nodes, so that the expression in the index gets a chance to go through +// this transformation. +class RewriteExpressionTraverser final : public TIntermTraverser +{ + public: + explicit RewriteExpressionTraverser(TCompiler *compiler, const UniformMap &uniformMap) + : TIntermTraverser(true, false, false), mCompiler(compiler), mUniformMap(uniformMap) + {} + + bool visitBinary(Visit visit, TIntermBinary *node) override + { + TIntermTyped *rewritten = + RewriteArrayOfArraySubscriptExpression(mCompiler, node, mUniformMap); + if (rewritten == nullptr) + { + return true; + } + + queueReplacement(rewritten, OriginalNode::IS_DROPPED); + + // Don't iterate as the expression is rewritten. + return false; + } + + void visitSymbol(TIntermSymbol *node) override + { + // We cannot reach here for an opaque uniform that is being replaced. visitBinary should + // have taken care of it. + ASSERT(!IsOpaqueType(node->getType().getBasicType()) || + mUniformMap.find(&node->variable()) == mUniformMap.end()); + } + + private: + TCompiler *mCompiler; + + const UniformMap &mUniformMap; +}; + +// Rewrite the index of an EOpIndexIndirect expression. The root can never need replacing, because +// it cannot be an opaque uniform itself. +void RewriteIndexExpression(TCompiler *compiler, + TIntermTyped *expression, + const UniformMap &uniformMap) +{ + RewriteExpressionTraverser traverser(compiler, uniformMap); + expression->traverse(&traverser); + bool valid = traverser.updateTree(compiler, expression); + ASSERT(valid); +} + +// Given an expression such as the following: +// +// EOpIndex(In)Direct (opaque uniform) +// / \ +// EOpIndex(In)Direct I1 +// / \ +// ... I2 +// / +// EOpIndex(In)Direct +// / \ +// uniform In +// +// produces: +// +// EOpIndex(In)Direct +// / \ +// uniform In*Pn + ... + I2*P2 + I1*P1 +// +TIntermTyped *RewriteArrayOfArraySubscriptExpression(TCompiler *compiler, + TIntermBinary *node, + const UniformMap &uniformMap) +{ + // Only interested in opaque uniforms. + if (!IsOpaqueType(node->getType().getBasicType())) + { + return nullptr; + } + + TIntermSymbol *opaqueUniform = nullptr; + + // Iterate once and find the opaque uniform that's being indexed. + TIntermBinary *iter = node; + while (opaqueUniform == nullptr) + { + ASSERT(iter->getOp() == EOpIndexDirect || iter->getOp() == EOpIndexIndirect); + + opaqueUniform = iter->getLeft()->getAsSymbolNode(); + iter = iter->getLeft()->getAsBinaryNode(); + } + + // If not being replaced, there's nothing to do. + auto flattenedIter = uniformMap.find(&opaqueUniform->variable()); + if (flattenedIter == uniformMap.end()) + { + return nullptr; + } + + const UniformData &data = flattenedIter->second; + + // Iterate again and build the index expression. The index expression constitutes the sum of + // the variable indices plus a constant offset calculated from the constant indices. For + // example, smplr[1][x][2][y] will have an index of x*P3 + y*P1 + c, where c = (1*P4 + 2*P2). + unsigned int constantOffset = 0; + TIntermTyped *variableIndex = nullptr; + + // Since the opaque uniforms are fully subscripted, we know exactly how many EOpIndex* nodes + // there should be. + for (size_t dimIndex = 0; dimIndex < data.mSubArraySizes.size(); ++dimIndex) + { + ASSERT(node); + + unsigned int subArraySize = data.mSubArraySizes[dimIndex]; + + switch (node->getOp()) + { + case EOpIndexDirect: + // Accumulate the constant index. + constantOffset += + node->getRight()->getAsConstantUnion()->getIConst(0) * subArraySize; + break; + case EOpIndexIndirect: + { + // Run RewriteExpressionTraverser on the right node. It may itself be an expression + // with an array of array of opaque uniform inside that needs to be rewritten. + TIntermTyped *indexExpression = node->getRight(); + RewriteIndexExpression(compiler, indexExpression, uniformMap); + + // Scale and accumulate. + if (subArraySize != 1) + { + indexExpression = + new TIntermBinary(EOpMul, indexExpression, CreateIndexNode(subArraySize)); + } + + if (variableIndex == nullptr) + { + variableIndex = indexExpression; + } + else + { + variableIndex = new TIntermBinary(EOpAdd, variableIndex, indexExpression); + } + break; + } + default: + UNREACHABLE(); + break; + } + + node = node->getLeft()->getAsBinaryNode(); + } + + // Add the two accumulated indices together. + TIntermTyped *index = nullptr; + if (constantOffset == 0 && variableIndex != nullptr) + { + // No constant offset, but there's variable offset. Take that as offset. + index = variableIndex; + } + else + { + // Either the constant offset is non zero, or there's no variable offset (so constant 0 + // should be used). + index = CreateIndexNode(constantOffset); + + if (variableIndex) + { + index = new TIntermBinary(EOpAdd, index, variableIndex); + } + } + + // Create an index into the flattened uniform. + TOperator op = variableIndex ? EOpIndexIndirect : EOpIndexDirect; + return new TIntermBinary(op, new TIntermSymbol(data.flattened), index); +} + +// Traverser that takes: +// +// uniform sampler/image/atomic_uint u[N][M].. +// +// and transforms it to: +// +// uniform sampler/image/atomic_uint u[N * M * ..] +// +// MonomorphizeUnsupportedFunctions makes it impossible for this array to be partially +// subscripted, or passed as argument to a function unsubscripted. This means that every encounter +// of this uniform can be expected to be fully subscripted. +// +class RewriteArrayOfArrayOfOpaqueUniformsTraverser : public TIntermTraverser +{ + public: + RewriteArrayOfArrayOfOpaqueUniformsTraverser(TCompiler *compiler, TSymbolTable *symbolTable) + : TIntermTraverser(true, false, false, symbolTable), mCompiler(compiler) + {} + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + if (!mInGlobalScope) + { + return true; + } + + const TIntermSequence &sequence = *(node->getSequence()); + + TIntermTyped *variable = sequence.front()->getAsTyped(); + const TType &type = variable->getType(); + bool isOpaqueUniform = + type.getQualifier() == EvqUniform && IsOpaqueType(type.getBasicType()); + + // Only interested in array of array of opaque uniforms. + if (!isOpaqueUniform || !type.isArrayOfArrays()) + { + return false; + } + + // Opaque uniforms cannot have initializers, so the declaration must necessarily be a + // symbol. + TIntermSymbol *symbol = variable->getAsSymbolNode(); + ASSERT(symbol != nullptr); + + const TVariable *uniformVariable = &symbol->variable(); + + // Create an entry in the map. + ASSERT(mUniformMap.find(uniformVariable) == mUniformMap.end()); + UniformData &data = mUniformMap[uniformVariable]; + + // Calculate the accumulated dimension products. See UniformData::mSubArraySizes. + const TSpan &arraySizes = type.getArraySizes(); + mUniformMap[uniformVariable].mSubArraySizes.resize(arraySizes.size()); + unsigned int runningProduct = 1; + for (size_t dimension = 0; dimension < arraySizes.size(); ++dimension) + { + data.mSubArraySizes[dimension] = runningProduct; + runningProduct *= arraySizes[dimension]; + } + + // Create a replacement variable with the array flattened. + TType *newType = new TType(type); + newType->toArrayBaseType(); + newType->makeArray(runningProduct); + + data.flattened = new TVariable(mSymbolTable, uniformVariable->name(), newType, + uniformVariable->symbolType()); + + TIntermDeclaration *decl = new TIntermDeclaration; + decl->appendDeclarator(new TIntermSymbol(data.flattened)); + + queueReplacement(decl, OriginalNode::IS_DROPPED); + return false; + } + + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override + { + // As an optimization, don't bother inspecting functions if there aren't any opaque uniforms + // to replace. + return !mUniformMap.empty(); + } + + // Same implementation as in RewriteExpressionTraverser. That traverser cannot replace root. + bool visitBinary(Visit visit, TIntermBinary *node) override + { + TIntermTyped *rewritten = + RewriteArrayOfArraySubscriptExpression(mCompiler, node, mUniformMap); + if (rewritten == nullptr) + { + return true; + } + + queueReplacement(rewritten, OriginalNode::IS_DROPPED); + + // Don't iterate as the expression is rewritten. + return false; + } + + void visitSymbol(TIntermSymbol *node) override + { + ASSERT(!IsOpaqueType(node->getType().getBasicType()) || + mUniformMap.find(&node->variable()) == mUniformMap.end()); + } + + private: + TCompiler *mCompiler; + UniformMap mUniformMap; +}; +} // anonymous namespace + +bool RewriteArrayOfArrayOfOpaqueUniforms(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable) +{ + RewriteArrayOfArrayOfOpaqueUniformsTraverser traverser(compiler, symbolTable); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.h new file mode 100644 index 0000000000..859ce16dc8 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteArrayOfArrayOfOpaqueUniforms.h @@ -0,0 +1,25 @@ +// +// Copyright 2021 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteArrayOfArrayOfOpaqueUniforms: Flatten array of array of opaque uniforms. Requires +// MonomorphizeUnsupportedFunctions and RewriteStructSamplers to have been run. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_REWRITEARRAYOFARRAYOFOPAQUEUNIFORMS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_REWRITEARRAYOFARRAYOFOPAQUEUNIFORMS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool RewriteArrayOfArrayOfOpaqueUniforms(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_REWRITEARRAYOFARRAYOFOPAQUEUNIFORMS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteAtomicCounters.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteAtomicCounters.cpp new file mode 100644 index 0000000000..defc59bcc0 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteAtomicCounters.cpp @@ -0,0 +1,328 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteAtomicCounters: Emulate atomic counter buffers with storage buffers. +// + +#include "compiler/translator/tree_ops/RewriteAtomicCounters.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" + +namespace sh +{ +namespace +{ +constexpr ImmutableString kAtomicCountersVarName = ImmutableString("atomicCounters"); +constexpr ImmutableString kAtomicCounterFieldName = ImmutableString("counters"); + +// DeclareAtomicCountersBuffer adds a storage buffer array that's used with atomic counters. +const TVariable *DeclareAtomicCountersBuffers(TIntermBlock *root, TSymbolTable *symbolTable) +{ + // Define `uint counters[];` as the only field in the interface block. + TFieldList *fieldList = new TFieldList; + TType *counterType = new TType(EbtUInt, EbpHigh, EvqGlobal); + counterType->makeArray(0); + + TField *countersField = + new TField(counterType, kAtomicCounterFieldName, TSourceLoc(), SymbolType::AngleInternal); + + fieldList->push_back(countersField); + + TMemoryQualifier coherentMemory = TMemoryQualifier::Create(); + coherentMemory.coherent = true; + + // There are a maximum of 8 atomic counter buffers per IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS + // in libANGLE/Constants.h. + constexpr uint32_t kMaxAtomicCounterBuffers = 8; + + // Define a storage block "ANGLEAtomicCounters" with instance name "atomicCounters". + TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); + layoutQualifier.blockStorage = EbsStd430; + + return DeclareInterfaceBlock(root, symbolTable, fieldList, EvqBuffer, layoutQualifier, + coherentMemory, kMaxAtomicCounterBuffers, + ImmutableString(vk::kAtomicCountersBlockName), + kAtomicCountersVarName); +} + +TIntermTyped *CreateUniformBufferOffset(const TIntermTyped *uniformBufferOffsets, int binding) +{ + // Each uint in the |acbBufferOffsets| uniform contains offsets for 4 bindings. Therefore, the + // expression to get the uniform offset for the binding is: + // + // acbBufferOffsets[binding / 4] >> ((binding % 4) * 8) & 0xFF + + // acbBufferOffsets[binding / 4] + TIntermBinary *uniformBufferOffsetUint = new TIntermBinary( + EOpIndexDirect, uniformBufferOffsets->deepCopy(), CreateIndexNode(binding / 4)); + + // acbBufferOffsets[binding / 4] >> ((binding % 4) * 8) + TIntermBinary *uniformBufferOffsetShifted = uniformBufferOffsetUint; + if (binding % 4 != 0) + { + uniformBufferOffsetShifted = new TIntermBinary(EOpBitShiftRight, uniformBufferOffsetUint, + CreateUIntNode((binding % 4) * 8)); + } + + // acbBufferOffsets[binding / 4] >> ((binding % 4) * 8) & 0xFF + return new TIntermBinary(EOpBitwiseAnd, uniformBufferOffsetShifted, CreateUIntNode(0xFF)); +} + +TIntermBinary *CreateAtomicCounterRef(TIntermTyped *atomicCounterExpression, + const TVariable *atomicCounters, + const TIntermTyped *uniformBufferOffsets) +{ + // The atomic counters storage buffer declaration looks as such: + // + // layout(...) buffer ANGLEAtomicCounters + // { + // uint counters[]; + // } atomicCounters[N]; + // + // Where N is large enough to accommodate atomic counter buffer bindings used in the shader. + // + // This function takes an expression that uses an atomic counter, which can either be: + // + // - ac + // - acArray[index] + // + // Note that RewriteArrayOfArrayOfOpaqueUniforms has already flattened array of array of atomic + // counters. + // + // For the first case (ac), the following code is generated: + // + // atomicCounters[binding].counters[offset] + // + // For the second case (acArray[index]), the following code is generated: + // + // atomicCounters[binding].counters[offset + index] + // + // In either case, an offset given through uniforms is also added to |offset|. The binding is + // necessarily a constant thanks to MonomorphizeUnsupportedFunctions. + + // First determine if there's an index, and extract the atomic counter symbol out of the + // expression. + TIntermSymbol *atomicCounterSymbol = atomicCounterExpression->getAsSymbolNode(); + TIntermTyped *atomicCounterIndex = nullptr; + int atomicCounterConstIndex = 0; + TIntermBinary *asBinary = atomicCounterExpression->getAsBinaryNode(); + if (asBinary != nullptr) + { + atomicCounterSymbol = asBinary->getLeft()->getAsSymbolNode(); + + switch (asBinary->getOp()) + { + case EOpIndexDirect: + atomicCounterConstIndex = asBinary->getRight()->getAsConstantUnion()->getIConst(0); + break; + case EOpIndexIndirect: + atomicCounterIndex = asBinary->getRight(); + break; + default: + UNREACHABLE(); + } + } + + // Extract binding and offset information out of the atomic counter symbol. + ASSERT(atomicCounterSymbol); + const TVariable *atomicCounterVar = &atomicCounterSymbol->variable(); + const TType &atomicCounterType = atomicCounterVar->getType(); + + const int binding = atomicCounterType.getLayoutQualifier().binding; + int offset = atomicCounterType.getLayoutQualifier().offset / 4; + + // Create the expression: + // + // offset + arrayIndex + uniformOffset + // + // If arrayIndex is a constant, it's added with offset right here. + + offset += atomicCounterConstIndex; + + TIntermTyped *index = CreateUniformBufferOffset(uniformBufferOffsets, binding); + if (atomicCounterIndex != nullptr) + { + index = new TIntermBinary(EOpAdd, index, atomicCounterIndex); + } + if (offset != 0) + { + index = new TIntermBinary(EOpAdd, index, CreateIndexNode(offset)); + } + + // Finally, create the complete expression: + // + // atomicCounters[binding].counters[index] + + TIntermSymbol *atomicCountersRef = new TIntermSymbol(atomicCounters); + + // atomicCounters[binding] + TIntermBinary *countersBlock = + new TIntermBinary(EOpIndexDirect, atomicCountersRef, CreateIndexNode(binding)); + + // atomicCounters[binding].counters + TIntermBinary *counters = + new TIntermBinary(EOpIndexDirectInterfaceBlock, countersBlock, CreateIndexNode(0)); + + return new TIntermBinary(EOpIndexIndirect, counters, index); +} + +// Traverser that: +// +// 1. Removes the |uniform atomic_uint| declarations and remembers the binding and offset. +// 2. Substitutes |atomicVar[n]| with |buffer[binding].counters[offset + n]|. +class RewriteAtomicCountersTraverser : public TIntermTraverser +{ + public: + RewriteAtomicCountersTraverser(TSymbolTable *symbolTable, + const TVariable *atomicCounters, + const TIntermTyped *acbBufferOffsets) + : TIntermTraverser(true, false, false, symbolTable), + mAtomicCounters(atomicCounters), + mAcbBufferOffsets(acbBufferOffsets) + {} + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + if (!mInGlobalScope) + { + return true; + } + + const TIntermSequence &sequence = *(node->getSequence()); + + TIntermTyped *variable = sequence.front()->getAsTyped(); + const TType &type = variable->getType(); + bool isAtomicCounter = type.isAtomicCounter(); + + if (isAtomicCounter) + { + ASSERT(type.getQualifier() == EvqUniform); + TIntermSequence emptySequence; + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, + std::move(emptySequence)); + + return false; + } + + return true; + } + + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + if (BuiltInGroup::IsBuiltIn(node->getOp())) + { + bool converted = convertBuiltinFunction(node); + return !converted; + } + + // AST functions don't require modification as atomic counter function parameters are + // removed by MonomorphizeUnsupportedFunctions. + return true; + } + + void visitSymbol(TIntermSymbol *symbol) override + { + // Cannot encounter the atomic counter symbol directly. It can only be used with functions, + // and therefore it's handled by visitAggregate. + ASSERT(!symbol->getType().isAtomicCounter()); + } + + bool visitBinary(Visit visit, TIntermBinary *node) override + { + // Cannot encounter an atomic counter expression directly. It can only be used with + // functions, and therefore it's handled by visitAggregate. + ASSERT(!node->getType().isAtomicCounter()); + return true; + } + + private: + bool convertBuiltinFunction(TIntermAggregate *node) + { + const TOperator op = node->getOp(); + + // If the function is |memoryBarrierAtomicCounter|, simply replace it with + // |memoryBarrierBuffer|. + if (op == EOpMemoryBarrierAtomicCounter) + { + TIntermSequence emptySequence; + TIntermTyped *substituteCall = CreateBuiltInFunctionCallNode( + "memoryBarrierBuffer", &emptySequence, *mSymbolTable, 310); + queueReplacement(substituteCall, OriginalNode::IS_DROPPED); + return true; + } + + // If it's an |atomicCounter*| function, replace the function with an |atomic*| equivalent. + if (!node->getFunction()->isAtomicCounterFunction()) + { + return false; + } + + // Note: atomicAdd(0) is used for atomic reads. + uint32_t valueChange = 0; + constexpr char kAtomicAddFunction[] = "atomicAdd"; + bool isDecrement = false; + + if (op == EOpAtomicCounterIncrement) + { + valueChange = 1; + } + else if (op == EOpAtomicCounterDecrement) + { + // uint values are required to wrap around, so 0xFFFFFFFFu is used as -1. + valueChange = std::numeric_limits::max(); + static_assert(static_cast(-1) == std::numeric_limits::max(), + "uint32_t max is not -1"); + + isDecrement = true; + } + else + { + ASSERT(op == EOpAtomicCounter); + } + + TIntermTyped *param = (*node->getSequence())[0]->getAsTyped(); + + TIntermSequence substituteArguments; + substituteArguments.push_back( + CreateAtomicCounterRef(param, mAtomicCounters, mAcbBufferOffsets)); + substituteArguments.push_back(CreateUIntNode(valueChange)); + + TIntermTyped *substituteCall = CreateBuiltInFunctionCallNode( + kAtomicAddFunction, &substituteArguments, *mSymbolTable, 310); + + // Note that atomicCounterDecrement returns the *new* value instead of the prior value, + // unlike atomicAdd. So we need to do a -1 on the result as well. + if (isDecrement) + { + substituteCall = new TIntermBinary(EOpSub, substituteCall, CreateUIntNode(1)); + } + + queueReplacement(substituteCall, OriginalNode::IS_DROPPED); + return true; + } + + const TVariable *mAtomicCounters; + const TIntermTyped *mAcbBufferOffsets; +}; + +} // anonymous namespace + +bool RewriteAtomicCounters(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const TIntermTyped *acbBufferOffsets) +{ + const TVariable *atomicCounters = DeclareAtomicCountersBuffers(root, symbolTable); + + RewriteAtomicCountersTraverser traverser(symbolTable, atomicCounters, acbBufferOffsets); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteAtomicCounters.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteAtomicCounters.h new file mode 100644 index 0000000000..8a94f84b3a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteAtomicCounters.h @@ -0,0 +1,28 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteAtomicCounters: Change atomic counter buffers to storage buffers, with atomic counter +// variables being offsets into the uint array of that storage buffer. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_REWRITEATOMICCOUNTERS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_REWRITEATOMICCOUNTERS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TIntermTyped; +class TSymbolTable; +class TVariable; + +[[nodiscard]] bool RewriteAtomicCounters(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const TIntermTyped *acbBufferOffsets); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_REWRITEATOMICCOUNTERS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteCubeMapSamplersAs2DArray.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteCubeMapSamplersAs2DArray.cpp new file mode 100644 index 0000000000..f7e5814361 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteCubeMapSamplersAs2DArray.cpp @@ -0,0 +1,984 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteCubeMapSamplersAs2DArray: Change samplerCube samplers to sampler2DArray for seamful cube +// map emulation. +// +// Relies on MonomorphizeUnsupportedFunctions to ensure samplerCube variables are not +// passed to functions (for simplicity). +// + +#include "compiler/translator/tree_ops/RewriteCubeMapSamplersAs2DArray.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" + +namespace sh +{ +namespace +{ +constexpr ImmutableString kCoordTransformFuncName("ANGLECubeMapCoordTransform"); +constexpr ImmutableString kCoordTransformFuncNameImplicit("ANGLECubeMapCoordTransformImplicit"); + +TIntermTyped *DerivativeQuotient(TIntermTyped *u, + TIntermTyped *du, + TIntermTyped *v, + TIntermTyped *dv, + TIntermTyped *vRecip) +{ + // (du v - dv u) / v^2 + return new TIntermBinary( + EOpMul, + new TIntermBinary(EOpSub, new TIntermBinary(EOpMul, du->deepCopy(), v->deepCopy()), + new TIntermBinary(EOpMul, dv->deepCopy(), u->deepCopy())), + new TIntermBinary(EOpMul, vRecip->deepCopy(), vRecip->deepCopy())); +} + +TIntermTyped *Swizzle1(TIntermTyped *array, int i) +{ + return new TIntermSwizzle(array, {i}); +} + +TIntermTyped *IndexDirect(TIntermTyped *array, int i) +{ + return new TIntermBinary(EOpIndexDirect, array, CreateIndexNode(i)); +} + +// Generated the common transformation in each coord transformation case. See comment in +// declareCoordTranslationFunction(). Called with P, dPdx and dPdy. +void TransformXMajor(const TSymbolTable &symbolTable, + TIntermBlock *block, + TIntermTyped *x, + TIntermTyped *y, + TIntermTyped *z, + TIntermTyped *uc, + TIntermTyped *vc) +{ + // uc = -sign(x)*z + // vc = -y + TIntermTyped *signX = + CreateBuiltInUnaryFunctionCallNode("sign", x->deepCopy(), symbolTable, 100); + + TIntermTyped *ucValue = + new TIntermUnary(EOpNegative, new TIntermBinary(EOpMul, signX, z->deepCopy()), nullptr); + TIntermTyped *vcValue = new TIntermUnary(EOpNegative, y->deepCopy(), nullptr); + + block->appendStatement(new TIntermBinary(EOpAssign, uc->deepCopy(), ucValue)); + block->appendStatement(new TIntermBinary(EOpAssign, vc->deepCopy(), vcValue)); +} + +void TransformDerivativeXMajor(TIntermBlock *block, + TSymbolTable *symbolTable, + TIntermTyped *x, + TIntermTyped *y, + TIntermTyped *z, + TIntermTyped *dx, + TIntermTyped *dy, + TIntermTyped *dz, + TIntermTyped *du, + TIntermTyped *dv, + TIntermTyped *xRecip) +{ + // Only the magnitude of the derivative matters, so we ignore the sign(x) + // and the negations. + TIntermTyped *duValue = DerivativeQuotient(z, dz, x, dx, xRecip); + TIntermTyped *dvValue = DerivativeQuotient(y, dy, x, dx, xRecip); + duValue = new TIntermBinary(EOpMul, duValue, CreateFloatNode(0.5f, EbpMedium)); + dvValue = new TIntermBinary(EOpMul, dvValue, CreateFloatNode(0.5f, EbpMedium)); + block->appendStatement(new TIntermBinary(EOpAssign, du->deepCopy(), duValue)); + block->appendStatement(new TIntermBinary(EOpAssign, dv->deepCopy(), dvValue)); +} + +void TransformImplicitDerivativeXMajor(TIntermBlock *block, + TIntermTyped *dOuter, + TIntermTyped *du, + TIntermTyped *dv) +{ + block->appendStatement( + new TIntermBinary(EOpAssign, du->deepCopy(), Swizzle1(dOuter->deepCopy(), 2))); + block->appendStatement( + new TIntermBinary(EOpAssign, dv->deepCopy(), Swizzle1(dOuter->deepCopy(), 1))); +} + +void TransformYMajor(const TSymbolTable &symbolTable, + TIntermBlock *block, + TIntermTyped *x, + TIntermTyped *y, + TIntermTyped *z, + TIntermTyped *uc, + TIntermTyped *vc) +{ + // uc = x + // vc = sign(y)*z + TIntermTyped *signY = + CreateBuiltInUnaryFunctionCallNode("sign", y->deepCopy(), symbolTable, 100); + + TIntermTyped *ucValue = x->deepCopy(); + TIntermTyped *vcValue = new TIntermBinary(EOpMul, signY, z->deepCopy()); + + block->appendStatement(new TIntermBinary(EOpAssign, uc->deepCopy(), ucValue)); + block->appendStatement(new TIntermBinary(EOpAssign, vc->deepCopy(), vcValue)); +} + +void TransformDerivativeYMajor(TIntermBlock *block, + TSymbolTable *symbolTable, + TIntermTyped *x, + TIntermTyped *y, + TIntermTyped *z, + TIntermTyped *dx, + TIntermTyped *dy, + TIntermTyped *dz, + TIntermTyped *du, + TIntermTyped *dv, + TIntermTyped *yRecip) +{ + // Only the magnitude of the derivative matters, so we ignore the sign(x) + // and the negations. + TIntermTyped *duValue = DerivativeQuotient(x, dx, y, dy, yRecip); + TIntermTyped *dvValue = DerivativeQuotient(z, dz, y, dy, yRecip); + duValue = new TIntermBinary(EOpMul, duValue, CreateFloatNode(0.5f, EbpMedium)); + dvValue = new TIntermBinary(EOpMul, dvValue, CreateFloatNode(0.5f, EbpMedium)); + block->appendStatement(new TIntermBinary(EOpAssign, du->deepCopy(), duValue)); + block->appendStatement(new TIntermBinary(EOpAssign, dv->deepCopy(), dvValue)); +} + +void TransformImplicitDerivativeYMajor(TIntermBlock *block, + TIntermTyped *dOuter, + TIntermTyped *du, + TIntermTyped *dv) +{ + block->appendStatement( + new TIntermBinary(EOpAssign, du->deepCopy(), Swizzle1(dOuter->deepCopy(), 0))); + block->appendStatement( + new TIntermBinary(EOpAssign, dv->deepCopy(), Swizzle1(dOuter->deepCopy(), 2))); +} + +void TransformZMajor(const TSymbolTable &symbolTable, + TIntermBlock *block, + TIntermTyped *x, + TIntermTyped *y, + TIntermTyped *z, + TIntermTyped *uc, + TIntermTyped *vc) +{ + // uc = size(z)*x + // vc = -y + TIntermTyped *signZ = + CreateBuiltInUnaryFunctionCallNode("sign", z->deepCopy(), symbolTable, 100); + + TIntermTyped *ucValue = new TIntermBinary(EOpMul, signZ, x->deepCopy()); + TIntermTyped *vcValue = new TIntermUnary(EOpNegative, y->deepCopy(), nullptr); + + block->appendStatement(new TIntermBinary(EOpAssign, uc->deepCopy(), ucValue)); + block->appendStatement(new TIntermBinary(EOpAssign, vc->deepCopy(), vcValue)); +} + +void TransformDerivativeZMajor(TIntermBlock *block, + TSymbolTable *symbolTable, + TIntermTyped *x, + TIntermTyped *y, + TIntermTyped *z, + TIntermTyped *dx, + TIntermTyped *dy, + TIntermTyped *dz, + TIntermTyped *du, + TIntermTyped *dv, + TIntermTyped *zRecip) +{ + // Only the magnitude of the derivative matters, so we ignore the sign(x) + // and the negations. + TIntermTyped *duValue = DerivativeQuotient(x, dx, z, dz, zRecip); + TIntermTyped *dvValue = DerivativeQuotient(y, dy, z, dz, zRecip); + duValue = new TIntermBinary(EOpMul, duValue, CreateFloatNode(0.5f, EbpMedium)); + dvValue = new TIntermBinary(EOpMul, dvValue, CreateFloatNode(0.5f, EbpMedium)); + block->appendStatement(new TIntermBinary(EOpAssign, du->deepCopy(), duValue)); + block->appendStatement(new TIntermBinary(EOpAssign, dv->deepCopy(), dvValue)); +} + +void TransformImplicitDerivativeZMajor(TIntermBlock *block, + TIntermTyped *dOuter, + TIntermTyped *du, + TIntermTyped *dv) +{ + block->appendStatement( + new TIntermBinary(EOpAssign, du->deepCopy(), Swizzle1(dOuter->deepCopy(), 0))); + block->appendStatement( + new TIntermBinary(EOpAssign, dv->deepCopy(), Swizzle1(dOuter->deepCopy(), 1))); +} + +class RewriteCubeMapSamplersAs2DArrayTraverser : public TIntermTraverser +{ + public: + RewriteCubeMapSamplersAs2DArrayTraverser(TSymbolTable *symbolTable, bool isFragmentShader) + : TIntermTraverser(true, false, false, symbolTable), + mCubeXYZToArrayUVL(nullptr), + mCubeXYZToArrayUVLImplicit(nullptr), + mIsFragmentShader(isFragmentShader), + mCoordTranslationFunctionDecl(nullptr), + mCoordTranslationFunctionImplicitDecl(nullptr) + {} + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + const TIntermSequence &sequence = *(node->getSequence()); + + TIntermTyped *variable = sequence.front()->getAsTyped(); + const TType &type = variable->getType(); + bool isSamplerCube = type.getQualifier() == EvqUniform && type.isSamplerCube(); + + if (isSamplerCube) + { + // Samplers cannot have initializers, so the declaration must necessarily be a symbol. + TIntermSymbol *samplerVariable = variable->getAsSymbolNode(); + ASSERT(samplerVariable != nullptr); + + declareSampler2DArray(&samplerVariable->variable(), node); + return false; + } + + return true; + } + + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + if (BuiltInGroup::IsBuiltIn(node->getOp())) + { + bool converted = convertBuiltinFunction(node); + return !converted; + } + + // AST functions don't require modification as samplerCube function parameters are removed + // by MonomorphizeUnsupportedFunctions. + return true; + } + + TIntermFunctionDefinition *getCoordTranslationFunctionDecl() + { + return mCoordTranslationFunctionDecl; + } + + TIntermFunctionDefinition *getCoordTranslationFunctionDeclImplicit() + { + return mCoordTranslationFunctionImplicitDecl; + } + + private: + void declareSampler2DArray(const TVariable *samplerCubeVar, TIntermDeclaration *node) + { + if (mCubeXYZToArrayUVL == nullptr) + { + // If not done yet, declare the function that transforms cube map texture sampling + // coordinates to face index and uv coordinates. + declareCoordTranslationFunction(false, kCoordTransformFuncName, &mCubeXYZToArrayUVL, + &mCoordTranslationFunctionDecl); + } + if (mCubeXYZToArrayUVLImplicit == nullptr && mIsFragmentShader) + { + declareCoordTranslationFunction(true, kCoordTransformFuncNameImplicit, + &mCubeXYZToArrayUVLImplicit, + &mCoordTranslationFunctionImplicitDecl); + } + + TType *newType = new TType(samplerCubeVar->getType()); + newType->setBasicType(EbtSampler2DArray); + + TVariable *sampler2DArrayVar = new TVariable(mSymbolTable, samplerCubeVar->name(), newType, + samplerCubeVar->symbolType()); + + TIntermDeclaration *sampler2DArrayDecl = new TIntermDeclaration(); + sampler2DArrayDecl->appendDeclarator(new TIntermSymbol(sampler2DArrayVar)); + + queueReplacement(sampler2DArrayDecl, OriginalNode::IS_DROPPED); + + // Remember the sampler2DArray variable. + mSamplerMap[samplerCubeVar] = sampler2DArrayVar; + } + + void declareCoordTranslationFunction(bool implicit, + const ImmutableString &name, + TFunction **functionOut, + TIntermFunctionDefinition **declOut) + { + // GLES2.0 (as well as desktop OpenGL 2.0) define the coordination transformation as + // follows. Given xyz cube coordinates, where each channel is in [-1, 1], the following + // table calculates uc, vc and ma as well as the cube map face. + // + // Major Axis Direction Target uc vc ma + // +x TEXTURE_CUBE_MAP_POSITIVE_X -z -y |x| + // -x TEXTURE_CUBE_MAP_NEGATIVE_X z -y |x| + // +y TEXTURE_CUBE_MAP_POSITIVE_Y x z |y| + // -y TEXTURE_CUBE_MAP_NEGATIVE_Y x -z |y| + // +z TEXTURE_CUBE_MAP_POSITIVE_Z x -y |z| + // -z TEXTURE_CUBE_MAP_NEGATIVE_Z -x -y |z| + // + // "Major" is an indication of the axis with the largest value. The cube map face indicates + // the layer to sample from. The uv coordinates to sample from are calculated as, + // effectively transforming the uv values to [0, 1]: + // + // u = (1 + uc/ma) / 2 + // v = (1 + vc/ma) / 2 + // + // The function can be implemented as 6 ifs, though it would be far from efficient. The + // following calculations implement the table above in a smaller number of instructions. + // + // First, ma can be calculated as the max of the three axes. + // + // ma = max3(|x|, |y|, |z|) + // + // We have three cases: + // + // ma == |x|: uc = -sign(x)*z + // vc = -y + // layer = float(x < 0) + // + // ma == |y|: uc = x + // vc = sign(y)*z + // layer = 2 + float(y < 0) + // + // ma == |z|: uc = size(z)*x + // vc = -y + // layer = 4 + float(z < 0) + // + // This can be implemented with a number of ?: instructions or 3 ifs. ?: would require all + // expressions to be evaluated (vector ALU) while if would require exec mask and jumps + // (scalar operations). We implement this using ifs as there would otherwise be many vector + // operations and not much of anything else. + // + // If textureCubeGrad is used, we also need to transform the provided dPdx and dPdy (both + // vec3) to a dUVdx and dUVdy. Assume P=(r,s,t) and we are investigating dx (note the + // change from xyz to rst to not confuse with dx and dy): + // + // uv = (f(r,s,t)/ma + 1)/2 + // + // Where f is one of the transformations above for uc and vc. Between two neighbors along + // the x axis, we have P0=(r0,s0,t0) and P1=(r1,s1,t1) + // + // dP = (r1-r0, s1-s0, t1-t0) + // dUV = (f(r1,s1,t1)/ma1 - g(r0,s0,t0)/ma0) / 2 + // + // f and g may not necessarily be the same because the two points may have different major + // axes. Even with the same major access, the sign that's used in the formulas may not be + // the same. Furthermore, ma0 and ma1 may not be the same. This makes it impossible to + // derive dUV from dP exactly. + // + // However, gradient transformation is implementation dependant, so we will simplify and + // assume all the above complications are non-existent. We therefore have: + // + // dUV = (f(r1,s1,t1)/ma0 - f(r0,s0,t0)/ma0)/2 + // + // Given that we assumed the sign functions are returning identical results for the two + // points, f becomes a linear transformation. Thus: + // + // dUV = f(r1-r0,s1-0,t1-t0)/ma0/2 + // + // In other words, we use the same formulae that transform XYZ (RST here) to UV to + // transform the derivatives. + // + // ma == |x|: dUdx = -sign(x)*dPdx.z / ma / 2 + // dVdx = -dPdx.y / ma / 2 + // + // ma == |y|: dUdx = dPdx.x / ma / 2 + // dVdx = sign(y)*dPdx.z / ma / 2 + // + // ma == |z|: dUdx = size(z)*dPdx.x / ma / 2 + // dVdx = -dPdx.y / ma / 2 + // + // Similarly for dy. + + // Create the function parameters: vec3 P, vec3 dPdx, vec3 dPdy, + // out vec2 dUVdx, out vec2 dUVdy + const TType *vec3Type = StaticType::GetBasic(); + TType *inVec3Type = new TType(*vec3Type); + inVec3Type->setQualifier(EvqParamIn); + + TVariable *pVar = new TVariable(mSymbolTable, ImmutableString("P"), inVec3Type, + SymbolType::AngleInternal); + TVariable *dPdxVar = new TVariable(mSymbolTable, ImmutableString("dPdx"), inVec3Type, + SymbolType::AngleInternal); + TVariable *dPdyVar = new TVariable(mSymbolTable, ImmutableString("dPdy"), inVec3Type, + SymbolType::AngleInternal); + + const TType *vec2Type = StaticType::GetBasic(); + TType *outVec2Type = new TType(*vec2Type); + outVec2Type->setQualifier(EvqParamOut); + + TVariable *dUVdxVar = new TVariable(mSymbolTable, ImmutableString("dUVdx"), outVec2Type, + SymbolType::AngleInternal); + TVariable *dUVdyVar = new TVariable(mSymbolTable, ImmutableString("dUVdy"), outVec2Type, + SymbolType::AngleInternal); + + TIntermSymbol *p = new TIntermSymbol(pVar); + TIntermSymbol *dPdx = new TIntermSymbol(dPdxVar); + TIntermSymbol *dPdy = new TIntermSymbol(dPdyVar); + TIntermSymbol *dUVdx = new TIntermSymbol(dUVdxVar); + TIntermSymbol *dUVdy = new TIntermSymbol(dUVdyVar); + + // Create the function body as statements are generated. + TIntermBlock *body = new TIntermBlock; + + // Create the swizzle nodes that will be used in multiple expressions: + TIntermSwizzle *x = new TIntermSwizzle(p->deepCopy(), {0}); + TIntermSwizzle *y = new TIntermSwizzle(p->deepCopy(), {1}); + TIntermSwizzle *z = new TIntermSwizzle(p->deepCopy(), {2}); + + // Create abs and "< 0" expressions from the channels. + const TType *floatType = StaticType::GetBasic(); + + TIntermTyped *isNegX = new TIntermBinary(EOpLessThan, x, CreateZeroNode(*floatType)); + TIntermTyped *isNegY = new TIntermBinary(EOpLessThan, y, CreateZeroNode(*floatType)); + TIntermTyped *isNegZ = new TIntermBinary(EOpLessThan, z, CreateZeroNode(*floatType)); + + TIntermSymbol *absX = new TIntermSymbol(CreateTempVariable(mSymbolTable, floatType)); + TIntermSymbol *absY = new TIntermSymbol(CreateTempVariable(mSymbolTable, floatType)); + TIntermSymbol *absZ = new TIntermSymbol(CreateTempVariable(mSymbolTable, floatType)); + + TIntermDeclaration *absXDecl = CreateTempInitDeclarationNode( + &absX->variable(), + CreateBuiltInUnaryFunctionCallNode("abs", x->deepCopy(), *mSymbolTable, 100)); + TIntermDeclaration *absYDecl = CreateTempInitDeclarationNode( + &absY->variable(), + CreateBuiltInUnaryFunctionCallNode("abs", y->deepCopy(), *mSymbolTable, 100)); + TIntermDeclaration *absZDecl = CreateTempInitDeclarationNode( + &absZ->variable(), + CreateBuiltInUnaryFunctionCallNode("abs", z->deepCopy(), *mSymbolTable, 100)); + + body->appendStatement(absXDecl); + body->appendStatement(absYDecl); + body->appendStatement(absZDecl); + + // Create temporary variable for division outer product matrix and its + // derivatives. + // recipOuter[i][j] = 0.5 * P[j] / P[i] + const TType *mat3Type = StaticType::GetBasic(); + TIntermSymbol *recipOuter = new TIntermSymbol(CreateTempVariable(mSymbolTable, mat3Type)); + + TIntermTyped *pRecip = + new TIntermBinary(EOpDiv, CreateFloatNode(1.0, EbpMedium), p->deepCopy()); + TIntermSymbol *pRecipVar = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec3Type)); + + body->appendStatement(CreateTempInitDeclarationNode(&pRecipVar->variable(), pRecip)); + + TIntermSequence args = { + p->deepCopy(), new TIntermBinary(EOpVectorTimesScalar, CreateFloatNode(0.5, EbpMedium), + pRecipVar->deepCopy())}; + TIntermDeclaration *recipOuterDecl = CreateTempInitDeclarationNode( + &recipOuter->variable(), + CreateBuiltInFunctionCallNode("outerProduct", &args, *mSymbolTable, 300)); + body->appendStatement(recipOuterDecl); + + TIntermSymbol *dPDXdx = nullptr; + TIntermSymbol *dPDYdx = nullptr; + TIntermSymbol *dPDZdx = nullptr; + TIntermSymbol *dPDXdy = nullptr; + TIntermSymbol *dPDYdy = nullptr; + TIntermSymbol *dPDZdy = nullptr; + if (implicit) + { + dPDXdx = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec3Type)); + dPDYdx = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec3Type)); + dPDZdx = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec3Type)); + dPDXdy = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec3Type)); + dPDYdy = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec3Type)); + dPDZdy = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec3Type)); + + TIntermDeclaration *dPDXdxDecl = CreateTempInitDeclarationNode( + &dPDXdx->variable(), + CreateBuiltInUnaryFunctionCallNode("dFdx", IndexDirect(recipOuter, 0)->deepCopy(), + *mSymbolTable, 300)); + TIntermDeclaration *dPDYdxDecl = CreateTempInitDeclarationNode( + &dPDYdx->variable(), + CreateBuiltInUnaryFunctionCallNode("dFdx", IndexDirect(recipOuter, 1)->deepCopy(), + *mSymbolTable, 300)); + TIntermDeclaration *dPDZdxDecl = CreateTempInitDeclarationNode( + &dPDZdx->variable(), + CreateBuiltInUnaryFunctionCallNode("dFdx", IndexDirect(recipOuter, 2)->deepCopy(), + *mSymbolTable, 300)); + TIntermDeclaration *dPDXdyDecl = CreateTempInitDeclarationNode( + &dPDXdy->variable(), + CreateBuiltInUnaryFunctionCallNode("dFdy", IndexDirect(recipOuter, 0)->deepCopy(), + *mSymbolTable, 300)); + TIntermDeclaration *dPDYdyDecl = CreateTempInitDeclarationNode( + &dPDYdy->variable(), + CreateBuiltInUnaryFunctionCallNode("dFdy", IndexDirect(recipOuter, 1)->deepCopy(), + *mSymbolTable, 300)); + TIntermDeclaration *dPDZdyDecl = CreateTempInitDeclarationNode( + &dPDZdy->variable(), + CreateBuiltInUnaryFunctionCallNode("dFdy", IndexDirect(recipOuter, 2)->deepCopy(), + *mSymbolTable, 300)); + + body->appendStatement(dPDXdxDecl); + body->appendStatement(dPDYdxDecl); + body->appendStatement(dPDZdxDecl); + body->appendStatement(dPDXdyDecl); + body->appendStatement(dPDYdyDecl); + body->appendStatement(dPDZdyDecl); + } + + // Create temporary variables for ma, uc, vc, and l (layer), as well as dUdx, dVdx, dUdy + // and dVdy. + TIntermSymbol *ma = new TIntermSymbol(CreateTempVariable(mSymbolTable, floatType)); + TIntermSymbol *l = new TIntermSymbol(CreateTempVariable(mSymbolTable, floatType)); + TIntermSymbol *uc = new TIntermSymbol(CreateTempVariable(mSymbolTable, floatType)); + TIntermSymbol *vc = new TIntermSymbol(CreateTempVariable(mSymbolTable, floatType)); + TIntermSymbol *dUdx = new TIntermSymbol(CreateTempVariable(mSymbolTable, floatType)); + TIntermSymbol *dVdx = new TIntermSymbol(CreateTempVariable(mSymbolTable, floatType)); + TIntermSymbol *dUdy = new TIntermSymbol(CreateTempVariable(mSymbolTable, floatType)); + TIntermSymbol *dVdy = new TIntermSymbol(CreateTempVariable(mSymbolTable, floatType)); + + body->appendStatement(CreateTempDeclarationNode(&ma->variable())); + body->appendStatement(CreateTempDeclarationNode(&l->variable())); + body->appendStatement(CreateTempDeclarationNode(&uc->variable())); + body->appendStatement(CreateTempDeclarationNode(&vc->variable())); + body->appendStatement(CreateTempDeclarationNode(&dUdx->variable())); + body->appendStatement(CreateTempDeclarationNode(&dVdx->variable())); + body->appendStatement(CreateTempDeclarationNode(&dUdy->variable())); + body->appendStatement(CreateTempDeclarationNode(&dVdy->variable())); + + // ma = max(|x|, max(|y|, |z|)) + TIntermSequence argsMaxYZ = {absY->deepCopy(), absZ->deepCopy()}; + TIntermTyped *maxYZ = CreateBuiltInFunctionCallNode("max", &argsMaxYZ, *mSymbolTable, 100); + TIntermSequence argsMaxValue = {absX->deepCopy(), maxYZ}; + TIntermTyped *maValue = + CreateBuiltInFunctionCallNode("max", &argsMaxValue, *mSymbolTable, 100); + body->appendStatement(new TIntermBinary(EOpAssign, ma, maValue)); + + // ma == |x| and ma == |y| expressions + TIntermTyped *isXMajor = new TIntermBinary(EOpEqual, ma->deepCopy(), absX->deepCopy()); + TIntermTyped *isYMajor = new TIntermBinary(EOpEqual, ma->deepCopy(), absY->deepCopy()); + + // Determine the cube face: + + // The case where x is major: + // layer = float(x < 0) + TIntermSequence argsNegX = {isNegX}; + TIntermTyped *xl = TIntermAggregate::CreateConstructor(*floatType, &argsNegX); + + TIntermBlock *calculateXL = new TIntermBlock; + calculateXL->appendStatement(new TIntermBinary(EOpAssign, l->deepCopy(), xl)); + + // The case where y is major: + // layer = 2 + float(y < 0) + TIntermSequence argsNegY = {isNegY}; + TIntermTyped *yl = + new TIntermBinary(EOpAdd, CreateFloatNode(2.0f, EbpMedium), + TIntermAggregate::CreateConstructor(*floatType, &argsNegY)); + + TIntermBlock *calculateYL = new TIntermBlock; + calculateYL->appendStatement(new TIntermBinary(EOpAssign, l->deepCopy(), yl)); + + // The case where z is major: + // layer = 4 + float(z < 0) + TIntermSequence argsNegZ = {isNegZ}; + TIntermTyped *zl = + new TIntermBinary(EOpAdd, CreateFloatNode(4.0f, EbpMedium), + TIntermAggregate::CreateConstructor(*floatType, &argsNegZ)); + + TIntermBlock *calculateZL = new TIntermBlock; + calculateZL->appendStatement(new TIntermBinary(EOpAssign, l->deepCopy(), zl)); + + // Create the if-else paths: + TIntermIfElse *calculateYZL = new TIntermIfElse(isYMajor, calculateYL, calculateZL); + TIntermBlock *calculateYZLBlock = new TIntermBlock; + calculateYZLBlock->appendStatement(calculateYZL); + TIntermIfElse *calculateXYZL = new TIntermIfElse(isXMajor, calculateXL, calculateYZLBlock); + body->appendStatement(calculateXYZL); + + // layer < 1.5 (covering faces 0 and 1, corresponding to major axis being X) and layer < 3.5 + // (covering faces 2 and 3, corresponding to major axis being Y). Used to determine which + // of the three transformations to apply. Previously, ma == |X| and ma == |Y| was used, + // which is no longer correct for helper invocations. The value of ma is updated in each + // case for these invocations. + isXMajor = new TIntermBinary(EOpLessThan, l->deepCopy(), CreateFloatNode(1.5f, EbpMedium)); + isYMajor = new TIntermBinary(EOpLessThan, l->deepCopy(), CreateFloatNode(3.5f, EbpMedium)); + + TIntermSwizzle *dPdxX = new TIntermSwizzle(dPdx->deepCopy(), {0}); + TIntermSwizzle *dPdxY = new TIntermSwizzle(dPdx->deepCopy(), {1}); + TIntermSwizzle *dPdxZ = new TIntermSwizzle(dPdx->deepCopy(), {2}); + + TIntermSwizzle *dPdyX = new TIntermSwizzle(dPdy->deepCopy(), {0}); + TIntermSwizzle *dPdyY = new TIntermSwizzle(dPdy->deepCopy(), {1}); + TIntermSwizzle *dPdyZ = new TIntermSwizzle(dPdy->deepCopy(), {2}); + + TIntermBlock *calculateXUcVc = new TIntermBlock; + calculateXUcVc->appendStatement( + new TIntermBinary(EOpAssign, ma->deepCopy(), absX->deepCopy())); + TransformXMajor(*mSymbolTable, calculateXUcVc, x, y, z, uc, vc); + + TIntermBlock *calculateYUcVc = new TIntermBlock; + calculateYUcVc->appendStatement( + new TIntermBinary(EOpAssign, ma->deepCopy(), absY->deepCopy())); + TransformYMajor(*mSymbolTable, calculateYUcVc, x, y, z, uc, vc); + + TIntermBlock *calculateZUcVc = new TIntermBlock; + calculateZUcVc->appendStatement( + new TIntermBinary(EOpAssign, ma->deepCopy(), absZ->deepCopy())); + TransformZMajor(*mSymbolTable, calculateZUcVc, x, y, z, uc, vc); + + // Compute derivatives. + if (implicit) + { + TransformImplicitDerivativeXMajor(calculateXUcVc, dPDXdx, dUdx, dVdx); + TransformImplicitDerivativeXMajor(calculateXUcVc, dPDXdy, dUdy, dVdy); + TransformImplicitDerivativeYMajor(calculateYUcVc, dPDYdx, dUdx, dVdx); + TransformImplicitDerivativeYMajor(calculateYUcVc, dPDYdy, dUdy, dVdy); + TransformImplicitDerivativeZMajor(calculateZUcVc, dPDZdx, dUdx, dVdx); + TransformImplicitDerivativeZMajor(calculateZUcVc, dPDZdy, dUdy, dVdy); + } + else + { + TransformDerivativeXMajor(calculateXUcVc, mSymbolTable, x, y, z, dPdxX, dPdxY, dPdxZ, + dUdx, dVdx, Swizzle1(pRecipVar->deepCopy(), 0)); + TransformDerivativeXMajor(calculateXUcVc, mSymbolTable, x, y, z, dPdyX, dPdyY, dPdyZ, + dUdy, dVdy, Swizzle1(pRecipVar->deepCopy(), 0)); + TransformDerivativeYMajor(calculateYUcVc, mSymbolTable, x, y, z, dPdxX, dPdxY, dPdxZ, + dUdx, dVdx, Swizzle1(pRecipVar->deepCopy(), 1)); + TransformDerivativeYMajor(calculateYUcVc, mSymbolTable, x, y, z, dPdyX, dPdyY, dPdyZ, + dUdy, dVdy, Swizzle1(pRecipVar->deepCopy(), 1)); + TransformDerivativeZMajor(calculateZUcVc, mSymbolTable, x, y, z, dPdxX, dPdxY, dPdxZ, + dUdx, dVdx, Swizzle1(pRecipVar->deepCopy(), 2)); + TransformDerivativeZMajor(calculateZUcVc, mSymbolTable, x, y, z, dPdyX, dPdyY, dPdyZ, + dUdy, dVdy, Swizzle1(pRecipVar->deepCopy(), 2)); + } + + // Create the if-else paths: + TIntermIfElse *calculateYZUcVc = + new TIntermIfElse(isYMajor, calculateYUcVc, calculateZUcVc); + TIntermBlock *calculateYZUcVcBlock = new TIntermBlock; + calculateYZUcVcBlock->appendStatement(calculateYZUcVc); + TIntermIfElse *calculateXYZUcVc = + new TIntermIfElse(isXMajor, calculateXUcVc, calculateYZUcVcBlock); + body->appendStatement(calculateXYZUcVc); + + // u = (1 + uc/|ma|) / 2 + // v = (1 + vc/|ma|) / 2 + TIntermTyped *maTimesTwoRecip = new TIntermBinary( + EOpAssign, ma->deepCopy(), + new TIntermBinary(EOpDiv, CreateFloatNode(0.5f, EbpMedium), ma->deepCopy())); + body->appendStatement(maTimesTwoRecip); + + TIntermTyped *ucDivMa = new TIntermBinary(EOpMul, uc, ma->deepCopy()); + TIntermTyped *vcDivMa = new TIntermBinary(EOpMul, vc, ma->deepCopy()); + TIntermTyped *uNormalized = + new TIntermBinary(EOpAdd, CreateFloatNode(0.5f, EbpMedium), ucDivMa); + TIntermTyped *vNormalized = + new TIntermBinary(EOpAdd, CreateFloatNode(0.5f, EbpMedium), vcDivMa); + + body->appendStatement(new TIntermBinary(EOpAssign, uc->deepCopy(), uNormalized)); + body->appendStatement(new TIntermBinary(EOpAssign, vc->deepCopy(), vNormalized)); + + TIntermSequence argsDUVdx = {dUdx, dVdx}; + TIntermTyped *dUVdxValue = TIntermAggregate::CreateConstructor(*vec2Type, &argsDUVdx); + + TIntermSequence argsDUVdy = {dUdy, dVdy}; + TIntermTyped *dUVdyValue = TIntermAggregate::CreateConstructor(*vec2Type, &argsDUVdy); + + body->appendStatement(new TIntermBinary(EOpAssign, dUVdx, dUVdxValue)); + body->appendStatement(new TIntermBinary(EOpAssign, dUVdy, dUVdyValue)); + + // return vec3(u, v, l) + TIntermSequence argsUVL = {uc->deepCopy(), vc->deepCopy(), l}; + TIntermBranch *returnStatement = + new TIntermBranch(EOpReturn, TIntermAggregate::CreateConstructor(*vec3Type, &argsUVL)); + body->appendStatement(returnStatement); + + TFunction *function; + function = new TFunction(mSymbolTable, name, SymbolType::AngleInternal, vec3Type, true); + function->addParameter(pVar); + function->addParameter(dPdxVar); + function->addParameter(dPdyVar); + function->addParameter(dUVdxVar); + function->addParameter(dUVdyVar); + + *functionOut = function; + + *declOut = CreateInternalFunctionDefinitionNode(*function, body); + } + + TIntermTyped *createCoordTransformationCall(TIntermTyped *P, + TIntermTyped *dPdx, + TIntermTyped *dPdy, + TIntermTyped *dUVdx, + TIntermTyped *dUVdy) + { + TIntermSequence args = {P, dPdx, dPdy, dUVdx, dUVdy}; + return TIntermAggregate::CreateFunctionCall(*mCubeXYZToArrayUVL, &args); + } + + TIntermTyped *createImplicitCoordTransformationCall(TIntermTyped *P, + TIntermTyped *dUVdx, + TIntermTyped *dUVdy) + { + const TType *vec3Type = StaticType::GetBasic(); + TIntermTyped *dPdx = CreateZeroNode(*vec3Type); + TIntermTyped *dPdy = CreateZeroNode(*vec3Type); + TIntermSequence args = {P, dPdx, dPdy, dUVdx, dUVdy}; + return TIntermAggregate::CreateFunctionCall(*mCubeXYZToArrayUVLImplicit, &args); + } + + TIntermTyped *getMappedSamplerExpression(TIntermNode *samplerCubeExpression) + { + // The argument passed to a function can either be the sampler, if not array, or a subscript + // into the sampler array. + TIntermSymbol *asSymbol = samplerCubeExpression->getAsSymbolNode(); + TIntermBinary *asBinary = samplerCubeExpression->getAsBinaryNode(); + + if (asBinary) + { + // Only constant indexing is supported in ES2.0. + ASSERT(asBinary->getOp() == EOpIndexDirect); + asSymbol = asBinary->getLeft()->getAsSymbolNode(); + } + + // Arrays of arrays are not available in ES2.0. + ASSERT(asSymbol != nullptr); + const TVariable *samplerCubeVar = &asSymbol->variable(); + + ASSERT(mSamplerMap.find(samplerCubeVar) != mSamplerMap.end()); + const TVariable *mappedSamplerVar = mSamplerMap.at(samplerCubeVar); + + TIntermTyped *mappedExpression = new TIntermSymbol(mappedSamplerVar); + if (asBinary) + { + mappedExpression = + new TIntermBinary(asBinary->getOp(), mappedExpression, asBinary->getRight()); + } + + return mappedExpression; + } + + bool convertBuiltinFunction(TIntermAggregate *node) + { + const TFunction *function = node->getFunction(); + if (!function->name().beginsWith("textureCube")) + { + return false; + } + + // All textureCube* functions are in the form: + // + // textureCube??(samplerCube, vec3, ??) + // + // They should be converted to: + // + // texture??(sampler2DArray, convertCoords(vec3), ??) + // + // We assume the target platform supports texture() functions (currently only used in + // Vulkan). + // + // The intrinsics map as follows: + // + // textureCube -> textureGrad + // textureCubeLod -> textureLod + // textureCubeLodEXT -> textureLod + // textureCubeGrad -> textureGrad + // textureCubeGradEXT -> textureGrad + // + // Note that dPdx and dPdy in textureCubeGrad* are vec3, while the textureGrad equivalent + // for sampler2DArray is vec2. The EXT_shader_texture_lod that introduces thid function + // says: + // + // > For the "Grad" functions, dPdx is the explicit derivative of P with respect + // > to window x, and similarly dPdy with respect to window y. ... For a cube map texture, + // > dPdx and dPdy are vec3. + // > + // > Let + // > + // > dSdx = dPdx.s; + // > dSdy = dPdy.s; + // > dTdx = dPdx.t; + // > dTdy = dPdy.t; + // > + // > and + // > + // > / 0.0; for two-dimensional texture + // > dRdx = ( + // > \ dPdx.p; for cube map texture + // > + // > / 0.0; for two-dimensional texture + // > dRdy = ( + // > \ dPdy.p; for cube map texture + // > + // > (See equation 3.12a in The OpenGL ES 2.0 Specification.) + // + // It's unclear to me what dRdx and dRdy are. EXT_gpu_shader4 that promotes this function + // has the following additional information: + // + // > For the "Cube" versions, the partial + // > derivatives ddx and ddy are assumed to be in the coordinate system used + // > before texture coordinates are projected onto the appropriate cube + // > face. The partial derivatives of the post-projection texture coordinates, + // > which are used for level-of-detail and anisotropic filtering + // > calculations, are derived from coord, ddx and ddy in an + // > implementation-dependent manner. + // + // The calculation of dPdx and dPdy is declared as implementation-dependent, so we have + // freedom to calculate it as fit, even if not precisely the same as hardware might. + + const char *substituteFunctionName = "textureGrad"; + bool isGrad = false; + bool isTranslatedGrad = true; + bool hasBias = false; + if (function->name().beginsWith("textureCubeLod")) + { + substituteFunctionName = "textureLod"; + isTranslatedGrad = false; + } + else if (function->name().beginsWith("textureCubeGrad")) + { + isGrad = true; + } + else if (!mIsFragmentShader) + { + substituteFunctionName = "texture"; + isTranslatedGrad = false; + } + + TIntermSequence *arguments = node->getSequence(); + ASSERT(arguments->size() >= 2); + + const TType *vec2Type = StaticType::GetBasic(); + const TType *vec3Type = StaticType::GetBasic(); + TIntermSymbol *uvl = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec3Type)); + TIntermSymbol *dUVdx = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec2Type)); + TIntermSymbol *dUVdy = new TIntermSymbol(CreateTempVariable(mSymbolTable, vec2Type)); + + TIntermTyped *dPdx = nullptr; + TIntermTyped *dPdy = nullptr; + if (isGrad) + { + ASSERT(arguments->size() == 4); + dPdx = (*arguments)[2]->getAsTyped()->deepCopy(); + dPdy = (*arguments)[3]->getAsTyped()->deepCopy(); + } + else if (isTranslatedGrad && mIsFragmentShader && arguments->size() == 3) + { + hasBias = true; + } + else + { + dPdx = CreateZeroNode(*vec3Type); + dPdy = CreateZeroNode(*vec3Type); + } + + if (isTranslatedGrad && !mIsFragmentShader) + { + substituteFunctionName = "texture"; + isTranslatedGrad = false; + } + + // The function call to transform the coordinates, dPdx and dPdy. If not textureCubeGrad, + // the driver compiler will optimize out the unnecessary calculations. + TIntermSequence coordTransform; + coordTransform.push_back(CreateTempDeclarationNode(&dUVdx->variable())); + coordTransform.push_back(CreateTempDeclarationNode(&dUVdy->variable())); + TIntermTyped *coordTransformCall; + if (isGrad || !isTranslatedGrad) + { + coordTransformCall = createCoordTransformationCall( + (*arguments)[1]->getAsTyped()->deepCopy(), dPdx, dPdy, dUVdx, dUVdy); + } + else + { + coordTransformCall = createImplicitCoordTransformationCall( + (*arguments)[1]->getAsTyped()->deepCopy(), dUVdx, dUVdy); + } + coordTransform.push_back( + CreateTempInitDeclarationNode(&uvl->variable(), coordTransformCall)); + + TIntermTyped *dUVdxArg = dUVdx; + TIntermTyped *dUVdyArg = dUVdy; + if (hasBias) + { + const TType *floatType = StaticType::GetBasic(); + TIntermTyped *bias = (*arguments)[2]->getAsTyped()->deepCopy(); + TIntermSequence exp2Args = {bias}; + TIntermTyped *exp2Call = + CreateBuiltInFunctionCallNode("exp2", &exp2Args, *mSymbolTable, 100); + TIntermSymbol *biasFac = new TIntermSymbol(CreateTempVariable(mSymbolTable, floatType)); + coordTransform.push_back(CreateTempInitDeclarationNode(&biasFac->variable(), exp2Call)); + dUVdxArg = + new TIntermBinary(EOpVectorTimesScalar, biasFac->deepCopy(), dUVdx->deepCopy()); + dUVdyArg = + new TIntermBinary(EOpVectorTimesScalar, biasFac->deepCopy(), dUVdy->deepCopy()); + } + + insertStatementsInParentBlock(coordTransform); + + TIntermSequence substituteArguments; + // Replace the first argument (samplerCube) with the sampler2DArray. + substituteArguments.push_back(getMappedSamplerExpression((*arguments)[0])); + // Replace the second argument with the coordination transformation. + substituteArguments.push_back(uvl->deepCopy()); + if (isTranslatedGrad) + { + substituteArguments.push_back(dUVdxArg->deepCopy()); + substituteArguments.push_back(dUVdyArg->deepCopy()); + } + else + { + // Pass the rest of the parameters as is. + for (size_t argIndex = 2; argIndex < arguments->size(); ++argIndex) + { + substituteArguments.push_back((*arguments)[argIndex]->getAsTyped()->deepCopy()); + } + } + + TIntermTyped *substituteCall = CreateBuiltInFunctionCallNode( + substituteFunctionName, &substituteArguments, *mSymbolTable, 300); + + queueReplacement(substituteCall, OriginalNode::IS_DROPPED); + + return true; + } + + // A map from the samplerCube variable to the sampler2DArray one. + angle::HashMap mSamplerMap; + + // A helper function to convert xyz coordinates passed to a cube map sampling function into the + // array layer (cube map face) and uv coordinates. + TFunction *mCubeXYZToArrayUVL; + // A specialized version of the same function which uses implicit derivatives. + TFunction *mCubeXYZToArrayUVLImplicit; + + bool mIsFragmentShader; + + // Stored to be put before the first function after the pass. + TIntermFunctionDefinition *mCoordTranslationFunctionDecl; + TIntermFunctionDefinition *mCoordTranslationFunctionImplicitDecl; +}; +} // anonymous namespace + +bool RewriteCubeMapSamplersAs2DArray(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + bool isFragmentShader) +{ + RewriteCubeMapSamplersAs2DArrayTraverser traverser(symbolTable, isFragmentShader); + root->traverse(&traverser); + + TIntermFunctionDefinition *coordTranslationFunctionDecl = + traverser.getCoordTranslationFunctionDecl(); + TIntermFunctionDefinition *coordTranslationFunctionDeclImplicit = + traverser.getCoordTranslationFunctionDeclImplicit(); + size_t firstFunctionIndex = FindFirstFunctionDefinitionIndex(root); + if (coordTranslationFunctionDecl) + { + root->insertChildNodes(firstFunctionIndex, TIntermSequence({coordTranslationFunctionDecl})); + } + if (coordTranslationFunctionDeclImplicit) + { + root->insertChildNodes(firstFunctionIndex, + TIntermSequence({coordTranslationFunctionDeclImplicit})); + } + + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteCubeMapSamplersAs2DArray.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteCubeMapSamplersAs2DArray.h new file mode 100644 index 0000000000..515c1de103 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteCubeMapSamplersAs2DArray.h @@ -0,0 +1,29 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteCubeMapSamplersAs2DArray: Change samplerCube samplers to sampler2DArray, and the +// textureCube* function calls to calls to helper functions that select the cube map face and sample +// from the face as a 2D texture. This emulates seamful cube map sampling in ES2 (or desktop GL 2) +// and therefore only looks at samplerCube (i.e. not integer variants or cube arrays) and sampling +// functions that are defined in ES GLSL 1.0 (i.e. not the cube overload of texture()). + +#ifndef COMPILER_TRANSLATOR_TREEOPS_REWRITECUBEMAPSAMPLERSAS2DARRAY_H_ +#define COMPILER_TRANSLATOR_TREEOPS_REWRITECUBEMAPSAMPLERSAS2DARRAY_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool RewriteCubeMapSamplersAs2DArray(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + bool isFragmentShader); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_REWRITECUBEMAPSAMPLERSAS2DARRAY_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteDfdy.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteDfdy.cpp new file mode 100644 index 0000000000..1a2aabf7dc --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteDfdy.cpp @@ -0,0 +1,141 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Implementation of dFdy viewport transformation. +// See header for more info. + +#include "compiler/translator/tree_ops/RewriteDfdy.h" + +#include "common/angleutils.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/TranslatorVulkan.h" +#include "compiler/translator/tree_util/DriverUniform.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/SpecializationConstant.h" + +namespace sh +{ + +namespace +{ + +class Traverser : public TIntermTraverser +{ + public: + Traverser(TSymbolTable *symbolTable, SpecConst *specConst, const DriverUniform *driverUniforms); + + private: + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + + SpecConst *mSpecConst = nullptr; + const DriverUniform *mDriverUniforms = nullptr; +}; + +Traverser::Traverser(TSymbolTable *symbolTable, + SpecConst *specConst, + const DriverUniform *driverUniforms) + : TIntermTraverser(true, false, false, symbolTable), + mSpecConst(specConst), + mDriverUniforms(driverUniforms) +{} + +bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + // Decide if the node represents a call to dFdx() or dFdy() + if (node->getOp() != EOpDFdx && node->getOp() != EOpDFdy) + { + return true; + } + + const bool isDFdx = node->getOp() == EOpDFdx; + + // Two transformations are done on dFdx and dFdy: + // + // - If pre-rotation is applied, dFdx and dFdy may need to swap their axis based on the degree + // of rotation. dFdx becomes dFdy if rotation is 90 or 270 degrees. Similarly, dFdy becomes + // dFdx. + // - The result is potentially negated. This could be due to viewport y-flip or pre-rotation. + // + // Accordingly, there are two variables controlling the above transformations: + // + // - Rotation: A vec2 that is either (0, 1) or (1, 0). dFdx and dFdy are replaced with: + // + // dFdx * Rotation.x + dFdy * Rotation.y + // + // - Scale: A vec2 with -1 or 1 for either x or y components. The previous result is multiplied + // by this. + // + // Together, the above operations account for the combinations of 4 possible rotations and + // y-flip. + + // Get the results of dFdx(operand) and dFdy(operand), and multiply them by the swizzles + TIntermTyped *operand = node->getChildNode(0)->getAsTyped(); + + TIntermTyped *dFdx = CreateBuiltInUnaryFunctionCallNode("dFdx", operand, *mSymbolTable, 300); + TIntermTyped *dFdy = + CreateBuiltInUnaryFunctionCallNode("dFdy", operand->deepCopy(), *mSymbolTable, 300); + + // Get rotation multiplier + TIntermTyped *swapXY = mSpecConst->getSwapXY(); + if (swapXY == nullptr) + { + swapXY = mDriverUniforms->getSwapXY(); + } + + TIntermTyped *swapXMultiplier = MakeSwapXMultiplier(swapXY); + TIntermTyped *swapYMultiplier = MakeSwapYMultiplier(swapXY->deepCopy()); + + // Get flip multiplier + TIntermTyped *flipXY = mDriverUniforms->getFlipXY(mSymbolTable, DriverUniformFlip::Fragment); + + // Multiply the flip and rotation multipliers + TIntermTyped *xMultiplier = + new TIntermBinary(EOpMul, isDFdx ? swapXMultiplier : swapYMultiplier, + (new TIntermSwizzle(flipXY->deepCopy(), {0}))->fold(nullptr)); + TIntermTyped *yMultiplier = + new TIntermBinary(EOpMul, isDFdx ? swapYMultiplier : swapXMultiplier, + (new TIntermSwizzle(flipXY->deepCopy(), {1}))->fold(nullptr)); + + const TOperator mulOp = dFdx->getType().isVector() ? EOpVectorTimesScalar : EOpMul; + TIntermTyped *rotatedFlippedDfdx = new TIntermBinary(mulOp, dFdx, xMultiplier); + TIntermTyped *rotatedFlippedDfdy = new TIntermBinary(mulOp, dFdy, yMultiplier); + + // Sum them together into the result + TIntermBinary *rotatedFlippedResult = + new TIntermBinary(EOpAdd, rotatedFlippedDfdx, rotatedFlippedDfdy); + + // Replace the old dFdx() or dFdy() node with the new node that contains the corrected value + // + // Note the following bugs (anglebug.com/7346): + // + // - Side effects of operand are duplicated with the above + // - If the direct child of this node is itself dFdx/y, its queueReplacement will not be + // effective as the parent is also replaced. + queueReplacement(rotatedFlippedResult, OriginalNode::IS_DROPPED); + + return true; +} +} // anonymous namespace + +bool RewriteDfdy(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + int shaderVersion, + SpecConst *specConst, + const DriverUniform *driverUniforms) +{ + // dFdx/dFdy is only valid in GLSL 3.0 and later. + if (shaderVersion < 300) + { + return true; + } + + Traverser traverser(symbolTable, specConst, driverUniforms); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteDfdy.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteDfdy.h new file mode 100644 index 0000000000..d1a6399696 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteDfdy.h @@ -0,0 +1,32 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteDfdy: Transform dFdx and dFdy according to pre-rotation and viewport y-flip. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_REWRITEDFDY_H_ +#define COMPILER_TRANSLATOR_TREEOPS_REWRITEDFDY_H_ + +#include "common/angleutils.h" +#include "compiler/translator/Compiler.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TSymbolTable; +class SpecConst; +class DriverUniform; + +[[nodiscard]] bool RewriteDfdy(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + int shaderVersion, + SpecConst *specConst, + const DriverUniform *driverUniforms); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_REWRITEDFDY_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RewritePixelLocalStorage.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewritePixelLocalStorage.cpp new file mode 100644 index 0000000000..1c86cafe03 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewritePixelLocalStorage.cpp @@ -0,0 +1,861 @@ +// +// Copyright 2022 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/tree_ops/RewritePixelLocalStorage.h" + +#include "common/angleutils.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.h" +#include "compiler/translator/tree_util/BuiltIn.h" +#include "compiler/translator/tree_util/FindMain.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ +namespace +{ +constexpr static TBasicType DataTypeOfPLSType(TBasicType plsType) +{ + switch (plsType) + { + case EbtPixelLocalANGLE: + return EbtFloat; + case EbtIPixelLocalANGLE: + return EbtInt; + case EbtUPixelLocalANGLE: + return EbtUInt; + default: + UNREACHABLE(); + return EbtVoid; + } +} + +constexpr static TBasicType DataTypeOfImageType(TBasicType imageType) +{ + switch (imageType) + { + case EbtImage2D: + return EbtFloat; + case EbtIImage2D: + return EbtInt; + case EbtUImage2D: + return EbtUInt; + default: + UNREACHABLE(); + return EbtVoid; + } +} + +// Maps PLS symbols to a backing store. +template +class PLSBackingStoreMap +{ + public: + // Sets the given variable as the backing storage for the plsSymbol's binding point. An entry + // must not already exist in the map for this binding point. + void insertNew(TIntermSymbol *plsSymbol, const T &backingStore) + { + ASSERT(plsSymbol); + ASSERT(IsPixelLocal(plsSymbol->getBasicType())); + int binding = plsSymbol->getType().getLayoutQualifier().binding; + ASSERT(binding >= 0); + auto result = mMap.insert({binding, backingStore}); + ASSERT(result.second); // Ensure an image didn't already exist for this symbol. + } + + // Looks up the backing store for the given plsSymbol's binding point. An entry must already + // exist in the map for this binding point. + const T &find(TIntermSymbol *plsSymbol) + { + ASSERT(plsSymbol); + ASSERT(IsPixelLocal(plsSymbol->getBasicType())); + int binding = plsSymbol->getType().getLayoutQualifier().binding; + ASSERT(binding >= 0); + auto iter = mMap.find(binding); + ASSERT(iter != mMap.end()); // Ensure PLSImages already exist for this symbol. + return iter->second; + } + + const std::map &bindingOrderedMap() const { return mMap; } + + private: + // Use std::map so the backing stores are ordered by binding when we iterate. + std::map mMap; +}; + +// Base class for rewriting high level PLS operations to AST operations specified by +// ShPixelLocalStorageType. +class RewritePLSTraverser : public TIntermTraverser +{ + public: + RewritePLSTraverser(TCompiler *compiler, + TSymbolTable &symbolTable, + const ShCompileOptions &compileOptions, + int shaderVersion) + : TIntermTraverser(true, false, false, &symbolTable), + mCompiler(compiler), + mCompileOptions(&compileOptions), + mShaderVersion(shaderVersion) + {} + + bool visitDeclaration(Visit, TIntermDeclaration *decl) override + { + TIntermTyped *declVariable = (decl->getSequence())->front()->getAsTyped(); + ASSERT(declVariable); + + if (!IsPixelLocal(declVariable->getBasicType())) + { + return true; + } + + // PLS is not allowed in arrays. + ASSERT(!declVariable->isArray()); + + // This visitDeclaration doesn't get called for function arguments, and opaque types can + // otherwise only be uniforms. + ASSERT(declVariable->getQualifier() == EvqUniform); + + TIntermSymbol *plsSymbol = declVariable->getAsSymbolNode(); + ASSERT(plsSymbol); + + visitPLSDeclaration(plsSymbol); + + return false; + } + + bool visitAggregate(Visit, TIntermAggregate *aggregate) override + { + if (!BuiltInGroup::IsPixelLocal(aggregate->getOp())) + { + return true; + } + + const TIntermSequence &args = *aggregate->getSequence(); + ASSERT(args.size() >= 1); + TIntermSymbol *plsSymbol = args[0]->getAsSymbolNode(); + + // Rewrite pixelLocalLoadANGLE -> imageLoad. + if (aggregate->getOp() == EOpPixelLocalLoadANGLE) + { + visitPLSLoad(plsSymbol); + return false; // No need to recurse since this node is being dropped. + } + + // Rewrite pixelLocalStoreANGLE -> imageStore. + if (aggregate->getOp() == EOpPixelLocalStoreANGLE) + { + // Also hoist the 'value' expression into a temp. In the event of + // "pixelLocalStoreANGLE(..., pixelLocalLoadANGLE(...))", this ensures the load occurs + // _before_ any potential barriers required by the subclass. + // + // NOTE: It is generally unsafe to hoist function arguments due to short circuiting, + // e.g., "if (false && function(...))", but pixelLocalStoreANGLE returns type void, so + // it is safe in this particular case. + TType *valueType = new TType(DataTypeOfPLSType(plsSymbol->getBasicType()), + plsSymbol->getPrecision(), EvqTemporary, 4); + TVariable *valueVar = CreateTempVariable(mSymbolTable, valueType); + TIntermDeclaration *valueDecl = + CreateTempInitDeclarationNode(valueVar, args[1]->getAsTyped()); + valueDecl->traverse(this); // Rewrite any potential pixelLocalLoadANGLEs in valueDecl. + insertStatementInParentBlock(valueDecl); + + visitPLSStore(plsSymbol, valueVar); + return false; // No need to recurse since this node is being dropped. + } + + return true; + } + + // Called after rewrite. Injects one-time setup code that needs to run before any PLS accesses. + virtual void injectSetupCode(TCompiler *, + TSymbolTable &, + const ShCompileOptions &, + TIntermBlock *mainBody, + size_t plsBeginPosition) + {} + + // Called after rewrite. Injects one-time finalization code that needs to run after all PLS. + virtual void injectFinalizeCode(TCompiler *, + TSymbolTable &, + const ShCompileOptions &, + TIntermBlock *mainBody, + size_t plsEndPosition) + {} + + TVariable *globalPixelCoord() const { return mGlobalPixelCoord; } + + protected: + virtual void visitPLSDeclaration(TIntermSymbol *plsSymbol) = 0; + virtual void visitPLSLoad(TIntermSymbol *plsSymbol) = 0; + virtual void visitPLSStore(TIntermSymbol *plsSymbol, TVariable *value) = 0; + + void ensureGlobalPixelCoordDeclared() + { + // Insert a global to hold the pixel coordinate as soon as we see PLS declared. This will be + // initialized at the beginning of main(). + if (!mGlobalPixelCoord) + { + TType *coordType = new TType(EbtInt, EbpHigh, EvqGlobal, 2); + mGlobalPixelCoord = CreateTempVariable(mSymbolTable, coordType); + insertStatementInParentBlock(CreateTempDeclarationNode(mGlobalPixelCoord)); + } + } + + const TCompiler *const mCompiler; + const ShCompileOptions *const mCompileOptions; + const int mShaderVersion; + + // Stores the shader invocation's pixel coordinate as "ivec2(floor(gl_FragCoord.xy))". + TVariable *mGlobalPixelCoord = nullptr; +}; + +// Rewrites high level PLS operations to shader image operations. +class RewritePLSToImagesTraverser : public RewritePLSTraverser +{ + public: + RewritePLSToImagesTraverser(TCompiler *compiler, + TSymbolTable &symbolTable, + const ShCompileOptions &compileOptions, + int shaderVersion) + : RewritePLSTraverser(compiler, symbolTable, compileOptions, shaderVersion) + {} + + private: + void visitPLSDeclaration(TIntermSymbol *plsSymbol) override + { + // Replace the PLS declaration with an image2D. + ensureGlobalPixelCoordDeclared(); + TVariable *image2D = createPLSImageReplacement(plsSymbol); + mImages.insertNew(plsSymbol, image2D); + queueReplacement(new TIntermDeclaration({new TIntermSymbol(image2D)}), + OriginalNode::IS_DROPPED); + } + + // Do all PLS formats need to be packed into r32f, r32i, or r32ui image2Ds? + bool needsR32Packing() const + { + return mCompileOptions->pls.type == ShPixelLocalStorageType::ImageStoreR32PackedFormats; + } + + // Creates an image2D that replaces a pixel local storage handle. + TVariable *createPLSImageReplacement(const TIntermSymbol *plsSymbol) + { + ASSERT(plsSymbol); + ASSERT(IsPixelLocal(plsSymbol->getBasicType())); + + TType *imageType = new TType(plsSymbol->getType()); + + TLayoutQualifier layoutQualifier = imageType->getLayoutQualifier(); + switch (layoutQualifier.imageInternalFormat) + { + case TLayoutImageInternalFormat::EiifRGBA8: + if (needsR32Packing()) + { + layoutQualifier.imageInternalFormat = EiifR32UI; + imageType->setPrecision(EbpHigh); + imageType->setBasicType(EbtUImage2D); + } + else + { + imageType->setBasicType(EbtImage2D); + } + break; + case TLayoutImageInternalFormat::EiifRGBA8I: + if (needsR32Packing()) + { + layoutQualifier.imageInternalFormat = EiifR32I; + imageType->setPrecision(EbpHigh); + } + imageType->setBasicType(EbtIImage2D); + break; + case TLayoutImageInternalFormat::EiifRGBA8UI: + if (needsR32Packing()) + { + layoutQualifier.imageInternalFormat = EiifR32UI; + imageType->setPrecision(EbpHigh); + } + imageType->setBasicType(EbtUImage2D); + break; + case TLayoutImageInternalFormat::EiifR32F: + imageType->setBasicType(EbtImage2D); + break; + case TLayoutImageInternalFormat::EiifR32UI: + imageType->setBasicType(EbtUImage2D); + break; + default: + UNREACHABLE(); + } + layoutQualifier.rasterOrdered = mCompileOptions->pls.fragmentSynchronizationType == + ShFragmentSynchronizationType::RasterizerOrderViews_D3D; + imageType->setLayoutQualifier(layoutQualifier); + + TMemoryQualifier memoryQualifier{}; + memoryQualifier.coherent = true; + memoryQualifier.restrictQualifier = true; + memoryQualifier.volatileQualifier = false; + // TODO(anglebug.com/7279): Maybe we could walk the tree first and see which PLS is used + // how. If the PLS is never loaded, we could add a writeonly qualifier, for example. + memoryQualifier.readonly = false; + memoryQualifier.writeonly = false; + imageType->setMemoryQualifier(memoryQualifier); + + const TVariable &plsVar = plsSymbol->variable(); + return new TVariable(plsVar.uniqueId(), plsVar.name(), plsVar.symbolType(), + plsVar.extensions(), imageType); + } + + void visitPLSLoad(TIntermSymbol *plsSymbol) override + { + // Replace the pixelLocalLoadANGLE with imageLoad. + TVariable *image2D = mImages.find(plsSymbol); + ASSERT(mGlobalPixelCoord); + TIntermTyped *pls = CreateBuiltInFunctionCallNode( + "imageLoad", {new TIntermSymbol(image2D), new TIntermSymbol(mGlobalPixelCoord)}, + *mSymbolTable, 310); + pls = unpackImageDataIfNecessary(pls, plsSymbol, image2D); + queueReplacement(pls, OriginalNode::IS_DROPPED); + } + + // Unpacks the raw PLS data if the output shader language needs r32* packing. + TIntermTyped *unpackImageDataIfNecessary(TIntermTyped *data, + TIntermSymbol *plsSymbol, + TVariable *image2D) + { + TLayoutImageInternalFormat plsFormat = + plsSymbol->getType().getLayoutQualifier().imageInternalFormat; + TLayoutImageInternalFormat imageFormat = + image2D->getType().getLayoutQualifier().imageInternalFormat; + if (plsFormat == imageFormat) + { + return data; // This PLS storage isn't packed. + } + ASSERT(needsR32Packing()); + switch (plsFormat) + { + case EiifRGBA8: + // Unpack and normalize r,g,b,a from a single 32-bit unsigned int: + // + // unpackUnorm4x8(data.r) + // + data = CreateBuiltInFunctionCallNode("unpackUnorm4x8", {CreateSwizzle(data, 0)}, + *mSymbolTable, 310); + break; + case EiifRGBA8I: + case EiifRGBA8UI: + { + constexpr unsigned shifts[] = {24, 16, 8, 0}; + // Unpack r,g,b,a form a single (signed or unsigned) 32-bit int. Shift left, + // then right, to preserve the sign for ints. (highp integers are exactly + // 32-bit, two's compliment.) + // + // data.rrrr << uvec4(24, 16, 8, 0) >> 24u + // + data = CreateSwizzle(data, 0, 0, 0, 0); + data = new TIntermBinary(EOpBitShiftLeft, data, CreateUVecNode(shifts, 4, EbpHigh)); + data = new TIntermBinary(EOpBitShiftRight, data, CreateUIntNode(24)); + break; + } + default: + UNREACHABLE(); + } + return data; + } + + void visitPLSStore(TIntermSymbol *plsSymbol, TVariable *value) override + { + TVariable *image2D = mImages.find(plsSymbol); + TIntermTyped *packedData = clampAndPackPLSDataIfNecessary(value, plsSymbol, image2D); + + // Surround the store with memoryBarrierImage calls in order to ensure dependent stores and + // loads in a single shader invocation are coherent. From the ES 3.1 spec: + // + // Using variables declared as "coherent" guarantees only that the results of stores will + // be immediately visible to shader invocations using similarly-declared variables; + // calling MemoryBarrier is required to ensure that the stores are visible to other + // operations. + // + insertStatementsInParentBlock( + {CreateBuiltInFunctionCallNode("memoryBarrierImage", {}, *mSymbolTable, + 310)}, // Before. + {CreateBuiltInFunctionCallNode("memoryBarrierImage", {}, *mSymbolTable, + 310)}); // After. + + // Rewrite the pixelLocalStoreANGLE with imageStore. + ASSERT(mGlobalPixelCoord); + queueReplacement( + CreateBuiltInFunctionCallNode( + "imageStore", + {new TIntermSymbol(image2D), new TIntermSymbol(mGlobalPixelCoord), packedData}, + *mSymbolTable, 310), + OriginalNode::IS_DROPPED); + } + + // Packs the PLS to raw data if the output shader language needs r32* packing. + TIntermTyped *clampAndPackPLSDataIfNecessary(TVariable *plsVar, + TIntermSymbol *plsSymbol, + TVariable *image2D) + { + TLayoutImageInternalFormat plsFormat = + plsSymbol->getType().getLayoutQualifier().imageInternalFormat; + // anglebug.com/7524: Storing to integer formats with values larger than can be represented + // is specified differently on different APIs. Clamp integer formats here to make it uniform + // and more GL-like. + switch (plsFormat) + { + case EiifRGBA8I: + { + // Clamp r,g,b,a to their min/max 8-bit values: + // + // plsVar = clamp(plsVar, -128, 127) & 0xff + // + TIntermTyped *newPLSValue = CreateBuiltInFunctionCallNode( + "clamp", + {new TIntermSymbol(plsVar), CreateIndexNode(-128), CreateIndexNode(127)}, + *mSymbolTable, mShaderVersion); + insertStatementInParentBlock(CreateTempAssignmentNode(plsVar, newPLSValue)); + break; + } + case EiifRGBA8UI: + { + // Clamp r,g,b,a to their max 8-bit values: + // + // plsVar = min(plsVar, 255) + // + TIntermTyped *newPLSValue = CreateBuiltInFunctionCallNode( + "min", {new TIntermSymbol(plsVar), CreateUIntNode(255)}, *mSymbolTable, + mShaderVersion); + insertStatementInParentBlock(CreateTempAssignmentNode(plsVar, newPLSValue)); + break; + } + default: + break; + } + TIntermTyped *result = new TIntermSymbol(plsVar); + TLayoutImageInternalFormat imageFormat = + image2D->getType().getLayoutQualifier().imageInternalFormat; + if (plsFormat == imageFormat) + { + return result; // This PLS storage isn't packed. + } + ASSERT(needsR32Packing()); + switch (plsFormat) + { + case EiifRGBA8: + { + if (mCompileOptions->passHighpToPackUnormSnormBuiltins) + { + // anglebug.com/7527: unpackUnorm4x8 doesn't work on Pixel 4 when passed + // a mediump vec4. Use an intermediate highp vec4. + // + // It's safe to inject a variable here because it happens right before + // pixelLocalStoreANGLE, which returns type void. (See visitAggregate.) + TType *highpType = new TType(EbtFloat, EbpHigh, EvqTemporary, 4); + TVariable *workaroundHighpVar = CreateTempVariable(mSymbolTable, highpType); + insertStatementInParentBlock( + CreateTempInitDeclarationNode(workaroundHighpVar, result)); + result = new TIntermSymbol(workaroundHighpVar); + } + + // Denormalize and pack r,g,b,a into a single 32-bit unsigned int: + // + // packUnorm4x8(workaroundHighpVar) + // + result = + CreateBuiltInFunctionCallNode("packUnorm4x8", {result}, *mSymbolTable, 310); + break; + } + case EiifRGBA8I: + case EiifRGBA8UI: + { + if (plsFormat == EiifRGBA8I) + { + // Mask off extra sign bits beyond 8. + // + // plsVar &= 0xff + // + insertStatementInParentBlock(new TIntermBinary( + EOpBitwiseAndAssign, new TIntermSymbol(plsVar), CreateIndexNode(0xff))); + } + // Pack r,g,b,a into a single 32-bit (signed or unsigned) int: + // + // r | (g << 8) | (b << 16) | (a << 24) + // + auto shiftComponent = [=](int componentIdx) { + return new TIntermBinary(EOpBitShiftLeft, + CreateSwizzle(new TIntermSymbol(plsVar), componentIdx), + CreateUIntNode(componentIdx * 8)); + }; + result = CreateSwizzle(result, 0); + result = new TIntermBinary(EOpBitwiseOr, result, shiftComponent(1)); + result = new TIntermBinary(EOpBitwiseOr, result, shiftComponent(2)); + result = new TIntermBinary(EOpBitwiseOr, result, shiftComponent(3)); + break; + } + default: + UNREACHABLE(); + } + // Convert the packed data to a {u,i}vec4 for imageStore. + TType imageStoreType(DataTypeOfImageType(image2D->getType().getBasicType()), 4); + return TIntermAggregate::CreateConstructor(imageStoreType, {result}); + } + + void injectSetupCode(TCompiler *compiler, + TSymbolTable &symbolTable, + const ShCompileOptions &compileOptions, + TIntermBlock *mainBody, + size_t plsBeginPosition) override + { + // When PLS is implemented with images, early_fragment_tests ensure that depth/stencil + // can also block stores to PLS. + compiler->specifyEarlyFragmentTests(); + + // Delimit the beginning of a per-pixel critical section, if supported. This makes pixel + // local storage coherent. + // + // Either: GL_NV_fragment_shader_interlock + // GL_INTEL_fragment_shader_ordering + // GL_ARB_fragment_shader_interlock (may compile to + // SPV_EXT_fragment_shader_interlock) + switch (compileOptions.pls.fragmentSynchronizationType) + { + // ROVs don't need explicit synchronization calls. + case ShFragmentSynchronizationType::RasterizerOrderViews_D3D: + case ShFragmentSynchronizationType::NotSupported: + break; + case ShFragmentSynchronizationType::FragmentShaderInterlock_NV_GL: + mainBody->insertStatement( + plsBeginPosition, + CreateBuiltInFunctionCallNode("beginInvocationInterlockNV", {}, symbolTable, + kESSLInternalBackendBuiltIns)); + break; + case ShFragmentSynchronizationType::FragmentShaderOrdering_INTEL_GL: + mainBody->insertStatement( + plsBeginPosition, + CreateBuiltInFunctionCallNode("beginFragmentShaderOrderingINTEL", {}, + symbolTable, kESSLInternalBackendBuiltIns)); + break; + case ShFragmentSynchronizationType::FragmentShaderInterlock_ARB_GL: + mainBody->insertStatement( + plsBeginPosition, + CreateBuiltInFunctionCallNode("beginInvocationInterlockARB", {}, symbolTable, + kESSLInternalBackendBuiltIns)); + break; + default: + UNREACHABLE(); + } + } + + void injectFinalizeCode(TCompiler *, + TSymbolTable &symbolTable, + const ShCompileOptions &compileOptions, + TIntermBlock *mainBody, + size_t plsEndPosition) override + { + // Delimit the end of the PLS critical section, if required. + // + // Either: GL_NV_fragment_shader_interlock + // GL_ARB_fragment_shader_interlock (may compile to + // SPV_EXT_fragment_shader_interlock) + switch (compileOptions.pls.fragmentSynchronizationType) + { + // ROVs don't need explicit synchronization calls. + case ShFragmentSynchronizationType::RasterizerOrderViews_D3D: + // GL_INTEL_fragment_shader_ordering doesn't have an "end()" call. + case ShFragmentSynchronizationType::FragmentShaderOrdering_INTEL_GL: + case ShFragmentSynchronizationType::NotSupported: + break; + case ShFragmentSynchronizationType::FragmentShaderInterlock_NV_GL: + + mainBody->insertStatement( + plsEndPosition, + CreateBuiltInFunctionCallNode("endInvocationInterlockNV", {}, symbolTable, + kESSLInternalBackendBuiltIns)); + break; + case ShFragmentSynchronizationType::FragmentShaderInterlock_ARB_GL: + mainBody->insertStatement( + plsEndPosition, + CreateBuiltInFunctionCallNode("endInvocationInterlockARB", {}, symbolTable, + kESSLInternalBackendBuiltIns)); + break; + default: + UNREACHABLE(); + } + } + + PLSBackingStoreMap mImages; +}; + +// Rewrites high level PLS operations to framebuffer fetch operations. +class RewritePLSToFramebufferFetchTraverser : public RewritePLSTraverser +{ + public: + RewritePLSToFramebufferFetchTraverser(TCompiler *compiler, + TSymbolTable &symbolTable, + const ShCompileOptions &compileOptions, + int shaderVersion) + : RewritePLSTraverser(compiler, symbolTable, compileOptions, shaderVersion) + {} + + void visitPLSDeclaration(TIntermSymbol *plsSymbol) override + { + // Replace the PLS declaration with a framebuffer attachment. + PLSAttachment attachment(mCompiler, mSymbolTable, *mCompileOptions, plsSymbol->variable()); + mPLSAttachments.insertNew(plsSymbol, attachment); + insertStatementInParentBlock( + new TIntermDeclaration({new TIntermSymbol(attachment.fragmentVar)})); + queueReplacement(CreateTempDeclarationNode(attachment.accessVar), OriginalNode::IS_DROPPED); + } + + void visitPLSLoad(TIntermSymbol *plsSymbol) override + { + // Read our temporary accessVar. + const PLSAttachment &attachment = mPLSAttachments.find(plsSymbol); + queueReplacement(attachment.expandAccessVar(), OriginalNode::IS_DROPPED); + } + + void visitPLSStore(TIntermSymbol *plsSymbol, TVariable *value) override + { + // Set our temporary accessVar. + const PLSAttachment &attachment = mPLSAttachments.find(plsSymbol); + queueReplacement(CreateTempAssignmentNode(attachment.accessVar, attachment.swizzle(value)), + OriginalNode::IS_DROPPED); + } + + void injectSetupCode(TCompiler *compiler, + TSymbolTable &symbolTable, + const ShCompileOptions &compileOptions, + TIntermBlock *mainBody, + size_t plsBeginPosition) override + { + // [OpenGL ES Version 3.0.6, 3.9.2.3 "Shader Output"]: Any colors, or color components, + // associated with a fragment that are not written by the fragment shader are undefined. + // + // [EXT_shader_framebuffer_fetch]: Prior to fragment shading, fragment outputs declared + // inout are populated with the value last written to the framebuffer at the same(x, y, + // sample) position. + // + // It's unclear from the EXT_shader_framebuffer_fetch spec whether inout fragment variables + // become undefined if not explicitly written, but either way, when this compiles to subpass + // loads in Vulkan, we definitely get undefined behavior if PLS variables are not written. + // + // To make sure every PLS variable gets written, we read them all before PLS operations, + // then write them all back out after all PLS is complete. + std::vector plsPreloads; + plsPreloads.reserve(mPLSAttachments.bindingOrderedMap().size()); + for (const auto &entry : mPLSAttachments.bindingOrderedMap()) + { + const PLSAttachment &attachment = entry.second; + plsPreloads.push_back( + CreateTempAssignmentNode(attachment.accessVar, attachment.swizzleFragmentVar())); + } + mainBody->getSequence()->insert(mainBody->getSequence()->begin() + plsBeginPosition, + plsPreloads.begin(), plsPreloads.end()); + } + + void injectFinalizeCode(TCompiler *, + TSymbolTable &symbolTable, + const ShCompileOptions &compileOptions, + TIntermBlock *mainBody, + size_t plsEndPosition) override + { + std::vector plsWrites; + plsWrites.reserve(mPLSAttachments.bindingOrderedMap().size()); + for (const auto &entry : mPLSAttachments.bindingOrderedMap()) + { + const PLSAttachment &attachment = entry.second; + plsWrites.push_back(new TIntermBinary(EOpAssign, attachment.swizzleFragmentVar(), + new TIntermSymbol(attachment.accessVar))); + } + mainBody->getSequence()->insert(mainBody->getSequence()->begin() + plsEndPosition, + plsWrites.begin(), plsWrites.end()); + } + + private: + struct PLSAttachment + { + PLSAttachment(const TCompiler *compiler, + TSymbolTable *symbolTable, + const ShCompileOptions &compileOptions, + const TVariable &plsVar) + { + const TType &plsType = plsVar.getType(); + + TType *accessVarType; + switch (plsType.getLayoutQualifier().imageInternalFormat) + { + default: + UNREACHABLE(); + [[fallthrough]]; + case EiifRGBA8: + accessVarType = new TType(EbtFloat, 4); + break; + case EiifRGBA8I: + accessVarType = new TType(EbtInt, 4); + break; + case EiifRGBA8UI: + accessVarType = new TType(EbtUInt, 4); + break; + case EiifR32F: + accessVarType = new TType(EbtFloat, 1); + break; + case EiifR32UI: + accessVarType = new TType(EbtUInt, 1); + break; + } + accessVarType->setPrecision(plsType.getPrecision()); + accessVar = CreateTempVariable(symbolTable, accessVarType); + + // Qualcomm seems to want fragment outputs to be 4-component vectors, and produces a + // compile error from "inout uint". Our Metal translator also saturates color outputs to + // 4 components. And since the spec also seems silent on how many components an output + // must have, we always use 4. + TType *fragmentVarType = new TType(accessVarType->getBasicType(), 4); + fragmentVarType->setPrecision(plsType.getPrecision()); + fragmentVarType->setQualifier(EvqFragmentInOut); + + // PLS attachments are bound in reverse order from the rear. + TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); + layoutQualifier.location = + compiler->getResources().MaxCombinedDrawBuffersAndPixelLocalStoragePlanes - + plsType.getLayoutQualifier().binding - 1; + layoutQualifier.locationsSpecified = 1; + if (compileOptions.pls.fragmentSynchronizationType == + ShFragmentSynchronizationType::NotSupported) + { + // We're using EXT_shader_framebuffer_fetch_non_coherent, which requires the + // "noncoherent" qualifier. + layoutQualifier.noncoherent = true; + } + fragmentVarType->setLayoutQualifier(layoutQualifier); + + fragmentVar = new TVariable(plsVar.uniqueId(), plsVar.name(), plsVar.symbolType(), + plsVar.extensions(), fragmentVarType); + } + + // Expands our accessVar to 4 components, regardless of the size of the pixel local storage + // internalformat. + TIntermTyped *expandAccessVar() const + { + TIntermTyped *expanded = new TIntermSymbol(accessVar); + if (accessVar->getType().getNominalSize() == 1) + { + switch (accessVar->getType().getBasicType()) + { + case EbtFloat: + expanded = TIntermAggregate::CreateConstructor( // "vec4(r, 0, 0, 1)" + TType(EbtFloat, 4), + {expanded, CreateFloatNode(0, EbpHigh), CreateFloatNode(0, EbpHigh), + CreateFloatNode(1, EbpHigh)}); + break; + case EbtUInt: + expanded = TIntermAggregate::CreateConstructor( // "uvec4(r, 0, 0, 1)" + TType(EbtUInt, 4), + {expanded, CreateUIntNode(0), CreateUIntNode(0), CreateUIntNode(1)}); + break; + default: + UNREACHABLE(); + break; + } + } + return expanded; + } + + // Swizzles a variable down to the same number of components as the PLS internalformat. + TIntermTyped *swizzle(TVariable *var) const + { + TIntermTyped *swizzled = new TIntermSymbol(var); + if (var->getType().getNominalSize() != accessVar->getType().getNominalSize()) + { + ASSERT(var->getType().getNominalSize() > accessVar->getType().getNominalSize()); + TVector swizzleOffsets{0, 1, 2, 3}; + swizzleOffsets.resize(accessVar->getType().getNominalSize()); + swizzled = new TIntermSwizzle(swizzled, swizzleOffsets); + } + return swizzled; + } + + TIntermTyped *swizzleFragmentVar() const { return swizzle(fragmentVar); } + + TVariable *fragmentVar; + TVariable *accessVar; + }; + + PLSBackingStoreMap mPLSAttachments; +}; +} // anonymous namespace + +bool RewritePixelLocalStorage(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable &symbolTable, + const ShCompileOptions &compileOptions, + int shaderVersion) +{ + // If any functions take PLS arguments, monomorphize the functions by removing said parameters + // and making the PLS calls from main() instead, using the global uniform from the call site + // instead of the function argument. This is necessary because function arguments don't carry + // the necessary "binding" or "format" layout qualifiers. + if (!MonomorphizeUnsupportedFunctions( + compiler, root, &symbolTable, compileOptions, + UnsupportedFunctionArgsBitSet{UnsupportedFunctionArgs::PixelLocalStorage})) + { + return false; + } + + TIntermBlock *mainBody = FindMainBody(root); + + std::unique_ptr traverser; + switch (compileOptions.pls.type) + { + case ShPixelLocalStorageType::ImageStoreR32PackedFormats: + case ShPixelLocalStorageType::ImageStoreNativeFormats: + traverser = std::make_unique( + compiler, symbolTable, compileOptions, shaderVersion); + break; + case ShPixelLocalStorageType::FramebufferFetch: + traverser = std::make_unique( + compiler, symbolTable, compileOptions, shaderVersion); + break; + default: + UNREACHABLE(); + return false; + } + + // Rewrite PLS operations to image operations. + root->traverse(traverser.get()); + if (!traverser->updateTree(compiler, root)) + { + return false; + } + + // Inject the code that needs to run before and after all PLS operations. + // TODO(anglebug.com/7279): Inject these functions in a tight critical section, instead of + // just locking the entire main() function: + // - Monomorphize all PLS calls into main(). + // - Insert begin/end calls around the first/last PLS calls (and outside of flow control). + traverser->injectSetupCode(compiler, symbolTable, compileOptions, mainBody, 0); + traverser->injectFinalizeCode(compiler, symbolTable, compileOptions, mainBody, + mainBody->getChildCount()); + + if (traverser->globalPixelCoord()) + { + // Initialize the global pixel coord at the beginning of main(): + // + // pixelCoord = ivec2(floor(gl_FragCoord.xy)); + // + TIntermTyped *exp; + exp = ReferenceBuiltInVariable(ImmutableString("gl_FragCoord"), symbolTable, shaderVersion); + exp = CreateSwizzle(exp, 0, 1); + exp = CreateBuiltInFunctionCallNode("floor", {exp}, symbolTable, shaderVersion); + exp = TIntermAggregate::CreateConstructor(TType(EbtInt, 2), {exp}); + exp = CreateTempAssignmentNode(traverser->globalPixelCoord(), exp); + mainBody->insertStatement(0, exp); + } + + return compiler->validateAST(root); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RewritePixelLocalStorage.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewritePixelLocalStorage.h new file mode 100644 index 0000000000..9bcfcbb62e --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewritePixelLocalStorage.h @@ -0,0 +1,29 @@ +// +// Copyright 2022 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_REWRITE_PIXELLOCALSTORAGE_H_ +#define COMPILER_TRANSLATOR_TREEOPS_REWRITE_PIXELLOCALSTORAGE_H_ + +#include + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +// This mutating tree traversal rewrites high level ANGLE_shader_pixel_local_storage operations to +// the type of shader operations specified by ShPixelLocalStorageType, found in ShCompileOptions. +[[nodiscard]] bool RewritePixelLocalStorage(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable &symbolTable, + const ShCompileOptions &compileOptions, + int shaderVersion); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_REWRITE_PIXELLOCALSTORAGE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteStructSamplers.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteStructSamplers.cpp new file mode 100644 index 0000000000..219a6b31fc --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteStructSamplers.cpp @@ -0,0 +1,673 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteStructSamplers: Extract samplers from structs. +// + +#include "compiler/translator/tree_ops/RewriteStructSamplers.h" + +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ +namespace +{ + +// Used to map one structure type to another (one where the samplers are removed). +struct StructureData +{ + // The structure this was replaced with. If nullptr, it means the structure is removed (because + // it had all samplers). + const TStructure *modified; + // Indexed by the field index of original structure, to get the field index of the modified + // structure. For example: + // + // struct Original + // { + // sampler2D s1; + // vec4 f1; + // sampler2D s2; + // sampler2D s3; + // vec4 f2; + // }; + // + // struct Modified + // { + // vec4 f1; + // vec4 f2; + // }; + // + // fieldMap: + // 0 -> Invalid + // 1 -> 0 + // 2 -> Invalid + // 3 -> Invalid + // 4 -> 1 + // + TVector fieldMap; +}; + +using StructureMap = angle::HashMap; +using StructureUniformMap = angle::HashMap; +using ExtractedSamplerMap = angle::HashMap; + +TIntermTyped *RewriteModifiedStructFieldSelectionExpression( + TCompiler *compiler, + TIntermBinary *node, + const StructureMap &structureMap, + const StructureUniformMap &structureUniformMap, + const ExtractedSamplerMap &extractedSamplers); + +TIntermTyped *RewriteExpressionVisitBinaryHelper(TCompiler *compiler, + TIntermBinary *node, + const StructureMap &structureMap, + const StructureUniformMap &structureUniformMap, + const ExtractedSamplerMap &extractedSamplers) +{ + // Only interested in EOpIndexDirectStruct binary nodes. + if (node->getOp() != EOpIndexDirectStruct) + { + return nullptr; + } + + const TStructure *structure = node->getLeft()->getType().getStruct(); + ASSERT(structure); + + // If the result of the index is not a sampler and the struct is not replaced, there's nothing + // to do. + if (!node->getType().isSampler() && structureMap.find(structure) == structureMap.end()) + { + return nullptr; + } + + // Otherwise, replace the whole expression such that: + // + // - if sampler, it's indexed with whatever indices the parent structs were indexed with, + // - otherwise, the chain of field selections is rewritten by modifying the base uniform so all + // the intermediate nodes would have the correct type (and therefore fields). + ASSERT(structureMap.find(structure) != structureMap.end()); + + return RewriteModifiedStructFieldSelectionExpression(compiler, node, structureMap, + structureUniformMap, extractedSamplers); +} + +// Given an expression, this traverser calculates a new expression where sampler-in-structs are +// replaced with their extracted ones, and field indices are adjusted for the rest of the fields. +// In particular, this is run on the right node of EOpIndexIndirect binary nodes, so that the +// expression in the index gets a chance to go through this transformation. +class RewriteExpressionTraverser final : public TIntermTraverser +{ + public: + explicit RewriteExpressionTraverser(TCompiler *compiler, + const StructureMap &structureMap, + const StructureUniformMap &structureUniformMap, + const ExtractedSamplerMap &extractedSamplers) + : TIntermTraverser(true, false, false), + mCompiler(compiler), + mStructureMap(structureMap), + mStructureUniformMap(structureUniformMap), + mExtractedSamplers(extractedSamplers) + {} + + bool visitBinary(Visit visit, TIntermBinary *node) override + { + TIntermTyped *rewritten = RewriteExpressionVisitBinaryHelper( + mCompiler, node, mStructureMap, mStructureUniformMap, mExtractedSamplers); + + if (rewritten == nullptr) + { + return true; + } + + queueReplacement(rewritten, OriginalNode::IS_DROPPED); + + // Don't iterate as the expression is rewritten. + return false; + } + + void visitSymbol(TIntermSymbol *node) override + { + // It's impossible to reach here with a symbol that needs replacement. + // MonomorphizeUnsupportedFunctions makes sure that whole structs containing + // samplers are not passed to functions, so any instance of the struct uniform is + // necessarily indexed right away. visitBinary should have already taken care of it. + ASSERT(mStructureUniformMap.find(&node->variable()) == mStructureUniformMap.end()); + } + + private: + TCompiler *mCompiler; + + // See RewriteStructSamplersTraverser. + const StructureMap &mStructureMap; + const StructureUniformMap &mStructureUniformMap; + const ExtractedSamplerMap &mExtractedSamplers; +}; + +// Rewrite the index of an EOpIndexIndirect expression. The root can never need replacing, because +// it cannot be a sampler itself or of a struct type. +void RewriteIndexExpression(TCompiler *compiler, + TIntermTyped *expression, + const StructureMap &structureMap, + const StructureUniformMap &structureUniformMap, + const ExtractedSamplerMap &extractedSamplers) +{ + RewriteExpressionTraverser traverser(compiler, structureMap, structureUniformMap, + extractedSamplers); + expression->traverse(&traverser); + bool valid = traverser.updateTree(compiler, expression); + ASSERT(valid); +} + +// Given an expression such as the following: +// +// EOpIndexDirectStruct (sampler) +// / \ +// EOpIndex* field index +// / \ +// EOpIndexDirectStruct index 2 +// / \ +// EOpIndex* field index +// / \ +// EOpIndexDirectStruct index 1 +// / \ +// Uniform Struct field index +// +// produces: +// +// EOpIndex* +// / \ +// EOpIndex* index 2 +// / \ +// sampler index 1 +// +// Alternatively, if the expression is as such: +// +// EOpIndexDirectStruct +// / \ +// (modified struct type) EOpIndex* field index +// / \ +// EOpIndexDirectStruct index 2 +// / \ +// EOpIndex* field index +// / \ +// EOpIndexDirectStruct index 1 +// / \ +// Uniform Struct field index +// +// produces: +// +// EOpIndexDirectStruct +// / \ +// EOpIndex* mapped field index +// / \ +// EOpIndexDirectStruct index 2 +// / \ +// EOpIndex* mapped field index +// / \ +// EOpIndexDirectStruct index 1 +// / \ +// Uniform Struct mapped field index +// +TIntermTyped *RewriteModifiedStructFieldSelectionExpression( + TCompiler *compiler, + TIntermBinary *node, + const StructureMap &structureMap, + const StructureUniformMap &structureUniformMap, + const ExtractedSamplerMap &extractedSamplers) +{ + ASSERT(node->getOp() == EOpIndexDirectStruct); + + const bool isSampler = node->getType().isSampler(); + + TIntermSymbol *baseUniform = nullptr; + std::string samplerName; + + TVector indexNodeStack; + + // Iterate once and build the name of the sampler. + TIntermBinary *iter = node; + while (baseUniform == nullptr) + { + indexNodeStack.push_back(iter); + baseUniform = iter->getLeft()->getAsSymbolNode(); + + if (isSampler) + { + if (iter->getOp() == EOpIndexDirectStruct) + { + // When indexed into a struct, get the field name instead and construct the sampler + // name. + samplerName.insert(0, iter->getIndexStructFieldName().data()); + samplerName.insert(0, "_"); + } + + if (baseUniform) + { + // If left is a symbol, we have reached the end of the chain. Use the struct name + // to finish building the name of the sampler. + samplerName.insert(0, baseUniform->variable().name().data()); + } + } + + iter = iter->getLeft()->getAsBinaryNode(); + } + + TIntermTyped *rewritten = nullptr; + + if (isSampler) + { + ASSERT(extractedSamplers.find(samplerName) != extractedSamplers.end()); + rewritten = new TIntermSymbol(extractedSamplers.at(samplerName)); + } + else + { + const TVariable *baseUniformVar = &baseUniform->variable(); + ASSERT(structureUniformMap.find(baseUniformVar) != structureUniformMap.end()); + rewritten = new TIntermSymbol(structureUniformMap.at(baseUniformVar)); + } + + // Iterate again and build the expression from bottom up. + for (auto it = indexNodeStack.rbegin(); it != indexNodeStack.rend(); ++it) + { + TIntermBinary *indexNode = *it; + + switch (indexNode->getOp()) + { + case EOpIndexDirectStruct: + if (!isSampler) + { + // Remap the field. + const TStructure *structure = indexNode->getLeft()->getType().getStruct(); + ASSERT(structureMap.find(structure) != structureMap.end()); + + TIntermConstantUnion *asConstantUnion = + indexNode->getRight()->getAsConstantUnion(); + ASSERT(asConstantUnion); + + const int fieldIndex = asConstantUnion->getIConst(0); + ASSERT(fieldIndex < + static_cast(structureMap.at(structure).fieldMap.size())); + + const int mappedFieldIndex = structureMap.at(structure).fieldMap[fieldIndex]; + + rewritten = new TIntermBinary(EOpIndexDirectStruct, rewritten, + CreateIndexNode(mappedFieldIndex)); + } + break; + + case EOpIndexDirect: + rewritten = new TIntermBinary(EOpIndexDirect, rewritten, indexNode->getRight()); + break; + + case EOpIndexIndirect: + { + // Run RewriteExpressionTraverser on the right node. It may itself be an expression + // with a sampler inside that needs to be rewritten, or simply use a field of a + // struct that's remapped. + TIntermTyped *indexExpression = indexNode->getRight(); + RewriteIndexExpression(compiler, indexExpression, structureMap, structureUniformMap, + extractedSamplers); + rewritten = new TIntermBinary(EOpIndexIndirect, rewritten, indexExpression); + break; + } + + default: + UNREACHABLE(); + break; + } + } + + return rewritten; +} + +class RewriteStructSamplersTraverser final : public TIntermTraverser +{ + public: + explicit RewriteStructSamplersTraverser(TCompiler *compiler, TSymbolTable *symbolTable) + : TIntermTraverser(true, false, false, symbolTable), + mCompiler(compiler), + mRemovedUniformsCount(0) + {} + + int removedUniformsCount() const { return mRemovedUniformsCount; } + + // Each struct sampler declaration is stripped of its samplers. New uniforms are added for each + // stripped struct sampler. + bool visitDeclaration(Visit visit, TIntermDeclaration *decl) override + { + if (!mInGlobalScope) + { + return true; + } + + const TIntermSequence &sequence = *(decl->getSequence()); + TIntermTyped *declarator = sequence.front()->getAsTyped(); + const TType &type = declarator->getType(); + + if (!type.isStructureContainingSamplers()) + { + return false; + } + + TIntermSequence newSequence; + + if (type.isStructSpecifier()) + { + // If this is just a struct definition (not a uniform variable declaration of a + // struct type), just remove the samplers. They are not instantiated yet. + const TStructure *structure = type.getStruct(); + ASSERT(structure && mStructureMap.find(structure) == mStructureMap.end()); + + stripStructSpecifierSamplers(structure, &newSequence); + } + else + { + const TStructure *structure = type.getStruct(); + + // If the structure is defined at the same time, create the mapping to the stripped + // version first. + if (mStructureMap.find(structure) == mStructureMap.end()) + { + stripStructSpecifierSamplers(structure, &newSequence); + } + + // Then, extract the samplers from the struct and create global-scope variables instead. + TIntermSymbol *asSymbol = declarator->getAsSymbolNode(); + ASSERT(asSymbol); + const TVariable &variable = asSymbol->variable(); + ASSERT(variable.symbolType() != SymbolType::Empty); + + extractStructSamplerUniforms(variable, structure, &newSequence); + } + + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), decl, + std::move(newSequence)); + + return false; + } + + // Same implementation as in RewriteExpressionTraverser. That traverser cannot replace root. + bool visitBinary(Visit visit, TIntermBinary *node) override + { + TIntermTyped *rewritten = RewriteExpressionVisitBinaryHelper( + mCompiler, node, mStructureMap, mStructureUniformMap, mExtractedSamplers); + + if (rewritten == nullptr) + { + return true; + } + + queueReplacement(rewritten, OriginalNode::IS_DROPPED); + + // Don't iterate as the expression is rewritten. + return false; + } + + // Same implementation as in RewriteExpressionTraverser. That traverser cannot replace root. + void visitSymbol(TIntermSymbol *node) override + { + ASSERT(mStructureUniformMap.find(&node->variable()) == mStructureUniformMap.end()); + } + + private: + // Removes all samplers from a struct specifier. + void stripStructSpecifierSamplers(const TStructure *structure, TIntermSequence *newSequence) + { + TFieldList *newFieldList = new TFieldList; + ASSERT(structure->containsSamplers()); + + // Add this struct to the struct map + ASSERT(mStructureMap.find(structure) == mStructureMap.end()); + StructureData *modifiedData = &mStructureMap[structure]; + + modifiedData->modified = nullptr; + modifiedData->fieldMap.resize(structure->fields().size(), std::numeric_limits::max()); + + for (size_t fieldIndex = 0; fieldIndex < structure->fields().size(); ++fieldIndex) + { + const TField *field = structure->fields()[fieldIndex]; + const TType &fieldType = *field->type(); + + // If the field is a sampler, or a struct that's entirely removed, skip it. + if (!fieldType.isSampler() && !isRemovedStructType(fieldType)) + { + TType *newType = nullptr; + + // Otherwise, if it's a struct that's replaced, create a new field of the replaced + // type. + if (fieldType.isStructureContainingSamplers()) + { + const TStructure *fieldStruct = fieldType.getStruct(); + ASSERT(mStructureMap.find(fieldStruct) != mStructureMap.end()); + + const TStructure *modifiedStruct = mStructureMap[fieldStruct].modified; + ASSERT(modifiedStruct); + + newType = new TType(modifiedStruct, true); + if (fieldType.isArray()) + { + newType->makeArrays(fieldType.getArraySizes()); + } + } + else + { + // If not, duplicate the field as is. + newType = new TType(fieldType); + } + + // Record the mapping of the field indices, so future EOpIndexDirectStruct's into + // this struct can be fixed up. + modifiedData->fieldMap[fieldIndex] = static_cast(newFieldList->size()); + + TField *newField = + new TField(newType, field->name(), field->line(), field->symbolType()); + newFieldList->push_back(newField); + } + } + + // Prune empty structs. + if (newFieldList->empty()) + { + return; + } + + // Declare a new struct with the same name and the new fields. + modifiedData->modified = + new TStructure(mSymbolTable, structure->name(), newFieldList, structure->symbolType()); + TType *newStructType = new TType(modifiedData->modified, true); + TVariable *newStructVar = + new TVariable(mSymbolTable, kEmptyImmutableString, newStructType, SymbolType::Empty); + TIntermSymbol *newStructRef = new TIntermSymbol(newStructVar); + + TIntermDeclaration *structDecl = new TIntermDeclaration; + structDecl->appendDeclarator(newStructRef); + + newSequence->push_back(structDecl); + } + + // Returns true if the type is a struct that was removed because we extracted all the members. + bool isRemovedStructType(const TType &type) const + { + const TStructure *structure = type.getStruct(); + if (structure == nullptr) + { + // Not a struct + return false; + } + + // A struct is removed if it is in the map, but doesn't have a replacement struct. + auto iter = mStructureMap.find(structure); + return iter != mStructureMap.end() && iter->second.modified == nullptr; + } + + // Removes samplers from struct uniforms. For each sampler removed also adds a new globally + // defined sampler uniform. + void extractStructSamplerUniforms(const TVariable &variable, + const TStructure *structure, + TIntermSequence *newSequence) + { + ASSERT(structure->containsSamplers()); + ASSERT(mStructureMap.find(structure) != mStructureMap.end()); + + const TType &type = variable.getType(); + enterArray(type); + + for (const TField *field : structure->fields()) + { + extractFieldSamplers(variable.name().data(), field, newSequence); + } + + // If there's a replacement structure (because there are non-sampler fields in the struct), + // add a declaration with that type. + const TStructure *modified = mStructureMap[structure].modified; + if (modified != nullptr) + { + TType *newType = new TType(modified, false); + if (type.isArray()) + { + newType->makeArrays(type.getArraySizes()); + } + newType->setQualifier(EvqUniform); + const TVariable *newVariable = + new TVariable(mSymbolTable, variable.name(), newType, variable.symbolType()); + + TIntermDeclaration *newDecl = new TIntermDeclaration(); + newDecl->appendDeclarator(new TIntermSymbol(newVariable)); + + newSequence->push_back(newDecl); + + ASSERT(mStructureUniformMap.find(&variable) == mStructureUniformMap.end()); + mStructureUniformMap[&variable] = newVariable; + } + else + { + mRemovedUniformsCount++; + } + + exitArray(type); + } + + // Extracts samplers from a field of a struct. Works with nested structs and arrays. + void extractFieldSamplers(const std::string &prefix, + const TField *field, + TIntermSequence *newSequence) + { + const TType &fieldType = *field->type(); + if (fieldType.isSampler() || fieldType.isStructureContainingSamplers()) + { + std::string newPrefix = prefix + "_" + field->name().data(); + + if (fieldType.isSampler()) + { + extractSampler(newPrefix, fieldType, newSequence); + } + else + { + enterArray(fieldType); + const TStructure *structure = fieldType.getStruct(); + for (const TField *nestedField : structure->fields()) + { + extractFieldSamplers(newPrefix, nestedField, newSequence); + } + exitArray(fieldType); + } + } + } + + void GenerateArraySizesFromStack(TVector *sizesOut) + { + sizesOut->reserve(mArraySizeStack.size()); + + for (auto it = mArraySizeStack.rbegin(); it != mArraySizeStack.rend(); ++it) + { + sizesOut->push_back(*it); + } + } + + // Extracts a sampler from a struct. Declares the new extracted sampler. + void extractSampler(const std::string &newName, + const TType &fieldType, + TIntermSequence *newSequence) + { + ASSERT(fieldType.isSampler()); + + TType *newType = new TType(fieldType); + + // Add array dimensions accumulated so far due to struct arrays. Note that to support + // nested arrays, mArraySizeStack has the outermost size in the front. |makeArrays| thus + // expects this in reverse order. + TVector parentArraySizes; + GenerateArraySizesFromStack(&parentArraySizes); + newType->makeArrays(parentArraySizes); + + ImmutableStringBuilder nameBuilder(newName.size() + 1); + nameBuilder << newName; + + newType->setQualifier(EvqUniform); + TVariable *newVariable = + new TVariable(mSymbolTable, nameBuilder, newType, SymbolType::AngleInternal); + TIntermSymbol *newSymbol = new TIntermSymbol(newVariable); + + TIntermDeclaration *samplerDecl = new TIntermDeclaration; + samplerDecl->appendDeclarator(newSymbol); + + newSequence->push_back(samplerDecl); + + // TODO: Use a temp name instead of generating a name as currently done. There is no + // guarantee that these generated names cannot clash. Create a mapping from the previous + // name to the name assigned to the temp variable so ShaderVariable::mappedName can be + // updated post-transformation. http://anglebug.com/4301 + ASSERT(mExtractedSamplers.find(newName) == mExtractedSamplers.end()); + mExtractedSamplers[newName] = newVariable; + } + + void enterArray(const TType &arrayType) + { + const TSpan &arraySizes = arrayType.getArraySizes(); + for (auto it = arraySizes.rbegin(); it != arraySizes.rend(); ++it) + { + unsigned int arraySize = *it; + mArraySizeStack.push_back(arraySize); + } + } + + void exitArray(const TType &arrayType) + { + mArraySizeStack.resize(mArraySizeStack.size() - arrayType.getNumArraySizes()); + } + + TCompiler *mCompiler; + int mRemovedUniformsCount; + + // Map structures with samplers to ones that have their samplers removed. + StructureMap mStructureMap; + + // Map uniform variables of structure type that are replaced with another variable. + StructureUniformMap mStructureUniformMap; + + // Map a constructed sampler name to its variable. Used to replace an expression that uses this + // sampler with the extracted one. + ExtractedSamplerMap mExtractedSamplers; + + // A stack of array sizes. Used to figure out the array dimensions of the extracted sampler, + // for example when it's nested in an array of structs in an array of structs. + TVector mArraySizeStack; +}; +} // anonymous namespace + +bool RewriteStructSamplers(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + int *removedUniformsCountOut) +{ + RewriteStructSamplersTraverser traverser(compiler, symbolTable); + root->traverse(&traverser); + *removedUniformsCountOut = traverser.removedUniformsCount(); + return traverser.updateTree(compiler, root); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteStructSamplers.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteStructSamplers.h new file mode 100644 index 0000000000..f4c73a27fc --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteStructSamplers.h @@ -0,0 +1,38 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteStructSamplers: Extract structs from samplers. +// +// This traverser is designed to strip out samplers from structs. It moves them into separate +// uniform sampler declarations. This allows the struct to be stored in the default uniform block. +// This transformation requires MonomorphizeUnsupportedFunctions to have been run so it +// wouldn't need to deal with functions that are passed such structs. +// +// For example: +// struct S { sampler2D samp; int i; }; +// uniform S uni; +// Is rewritten as: +// struct S { int i; }; +// uniform S uni; +// uniform sampler2D uni_i; + +#ifndef COMPILER_TRANSLATOR_TREEOPS_REWRITESTRUCTSAMPLERS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_REWRITESTRUCTSAMPLERS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool RewriteStructSamplers(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + int *removedUniformsCountOut); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_VULKAN_REWRITESTRUCTSAMPLERS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteTexelFetchOffset.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteTexelFetchOffset.cpp new file mode 100644 index 0000000000..71284ecc1b --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteTexelFetchOffset.cpp @@ -0,0 +1,168 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Implementation of texelFetchOffset translation issue workaround. +// See header for more info. + +#include "compiler/translator/tree_ops/RewriteTexelFetchOffset.h" + +#include "common/angleutils.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class Traverser : public TIntermTraverser +{ + public: + [[nodiscard]] static bool Apply(TCompiler *compiler, + TIntermNode *root, + const TSymbolTable &symbolTable, + int shaderVersion); + + private: + Traverser(const TSymbolTable &symbolTable, int shaderVersion); + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + void nextIteration(); + + const TSymbolTable *symbolTable; + const int shaderVersion; + bool mFound = false; +}; + +Traverser::Traverser(const TSymbolTable &symbolTable, int shaderVersion) + : TIntermTraverser(true, false, false), symbolTable(&symbolTable), shaderVersion(shaderVersion) +{} + +// static +bool Traverser::Apply(TCompiler *compiler, + TIntermNode *root, + const TSymbolTable &symbolTable, + int shaderVersion) +{ + Traverser traverser(symbolTable, shaderVersion); + do + { + traverser.nextIteration(); + root->traverse(&traverser); + if (traverser.mFound) + { + if (!traverser.updateTree(compiler, root)) + { + return false; + } + } + } while (traverser.mFound); + + return true; +} + +void Traverser::nextIteration() +{ + mFound = false; +} + +bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + if (mFound) + { + return false; + } + + // Decide if the node represents the call of texelFetchOffset. + if (!BuiltInGroup::IsBuiltIn(node->getOp())) + { + return true; + } + + ASSERT(node->getFunction()->symbolType() == SymbolType::BuiltIn); + if (node->getFunction()->name() != "texelFetchOffset") + { + return true; + } + + // Potential problem case detected, apply workaround. + const TIntermSequence *sequence = node->getSequence(); + ASSERT(sequence->size() == 4u); + + // Decide if the sampler is a 2DArray sampler. In that case position is ivec3 and offset is + // ivec2. + bool is2DArray = sequence->at(1)->getAsTyped()->getNominalSize() == 3 && + sequence->at(3)->getAsTyped()->getNominalSize() == 2; + + // Create new node that represents the call of function texelFetch. + // Its argument list will be: texelFetch(sampler, Position+offset, lod). + + TIntermSequence texelFetchArguments; + + // sampler + texelFetchArguments.push_back(sequence->at(0)); + + // Position + TIntermTyped *texCoordNode = sequence->at(1)->getAsTyped(); + ASSERT(texCoordNode); + + // offset + TIntermTyped *offsetNode = nullptr; + ASSERT(sequence->at(3)->getAsTyped()); + if (is2DArray) + { + // For 2DArray samplers, Position is ivec3 and offset is ivec2; + // So offset must be converted into an ivec3 before being added to Position. + TIntermSequence constructOffsetIvecArguments; + constructOffsetIvecArguments.push_back(sequence->at(3)->getAsTyped()); + + TIntermTyped *zeroNode = CreateZeroNode(TType(EbtInt)); + constructOffsetIvecArguments.push_back(zeroNode); + + offsetNode = TIntermAggregate::CreateConstructor(texCoordNode->getType(), + &constructOffsetIvecArguments); + offsetNode->setLine(texCoordNode->getLine()); + } + else + { + offsetNode = sequence->at(3)->getAsTyped(); + } + + // Position+offset + TIntermBinary *add = new TIntermBinary(EOpAdd, texCoordNode, offsetNode); + add->setLine(texCoordNode->getLine()); + texelFetchArguments.push_back(add); + + // lod + texelFetchArguments.push_back(sequence->at(2)); + + ASSERT(texelFetchArguments.size() == 3u); + + TIntermTyped *texelFetchNode = CreateBuiltInFunctionCallNode("texelFetch", &texelFetchArguments, + *symbolTable, shaderVersion); + texelFetchNode->setLine(node->getLine()); + + // Replace the old node by this new node. + queueReplacement(texelFetchNode, OriginalNode::IS_DROPPED); + mFound = true; + return false; +} + +} // anonymous namespace + +bool RewriteTexelFetchOffset(TCompiler *compiler, + TIntermNode *root, + const TSymbolTable &symbolTable, + int shaderVersion) +{ + // texelFetchOffset is only valid in GLSL 3.0 and later. + if (shaderVersion < 300) + return true; + + return Traverser::Apply(compiler, root, symbolTable, shaderVersion); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteTexelFetchOffset.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteTexelFetchOffset.h new file mode 100644 index 0000000000..c2c3c07aad --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/RewriteTexelFetchOffset.h @@ -0,0 +1,34 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// This mutating tree traversal works around an issue on the translation +// from texelFetchOffset into HLSL function Load on INTEL drivers. It +// works by translating texelFetchOffset into texelFetch: +// +// - From: texelFetchOffset(sampler, Position, lod, offset) +// - To: texelFetch(sampler, Position+offset, lod) +// +// See http://anglebug.com/1469 + +#ifndef COMPILER_TRANSLATOR_TREEOPS_REWRITE_TEXELFETCHOFFSET_H_ +#define COMPILER_TRANSLATOR_TREEOPS_REWRITE_TEXELFETCHOFFSET_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermNode; +class TSymbolTable; + +[[nodiscard]] bool RewriteTexelFetchOffset(TCompiler *compiler, + TIntermNode *root, + const TSymbolTable &symbolTable, + int shaderVersion); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_REWRITE_TEXELFETCHOFFSET_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.cpp new file mode 100644 index 0000000000..4eab90e4fa --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.cpp @@ -0,0 +1,223 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Scalarize vector and matrix constructor args, so that vectors built from components don't have +// matrix arguments, and matrices built from components don't have vector arguments. This avoids +// driver bugs around vector and matrix constructors. +// + +#include "compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h" +#include "common/debug.h" + +#include + +#include "angle_gl.h" +#include "common/angleutils.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/tree_util/IntermNodePatternMatcher.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +TIntermBinary *ConstructVectorIndexBinaryNode(TIntermTyped *symbolNode, int index) +{ + return new TIntermBinary(EOpIndexDirect, symbolNode, CreateIndexNode(index)); +} + +TIntermBinary *ConstructMatrixIndexBinaryNode(TIntermTyped *symbolNode, int colIndex, int rowIndex) +{ + TIntermBinary *colVectorNode = ConstructVectorIndexBinaryNode(symbolNode, colIndex); + + return new TIntermBinary(EOpIndexDirect, colVectorNode, CreateIndexNode(rowIndex)); +} + +class ScalarizeArgsTraverser : public TIntermTraverser +{ + public: + ScalarizeArgsTraverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, false, false, symbolTable), + mNodesToScalarize(IntermNodePatternMatcher::kScalarizedVecOrMatConstructor) + {} + + protected: + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + bool visitBlock(Visit visit, TIntermBlock *node) override; + + private: + void scalarizeArgs(TIntermAggregate *aggregate, bool scalarizeVector, bool scalarizeMatrix); + + // If we have the following code: + // mat4 m(0); + // vec4 v(1, m); + // We will rewrite to: + // mat4 m(0); + // mat4 s0 = m; + // vec4 v(1, s0[0][0], s0[0][1], s0[0][2]); + // This function is to create nodes for "mat4 s0 = m;" and insert it to the code sequence. This + // way the possible side effects of the constructor argument will only be evaluated once. + TIntermTyped *createTempVariable(TIntermTyped *original); + + std::vector mBlockStack; + + IntermNodePatternMatcher mNodesToScalarize; +}; + +bool ScalarizeArgsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + ASSERT(visit == PreVisit); + if (mNodesToScalarize.match(node, getParentNode())) + { + if (node->getType().isVector()) + { + scalarizeArgs(node, false, true); + } + else + { + ASSERT(node->getType().isMatrix()); + scalarizeArgs(node, true, false); + } + } + return true; +} + +bool ScalarizeArgsTraverser::visitBlock(Visit visit, TIntermBlock *node) +{ + mBlockStack.push_back(TIntermSequence()); + { + for (TIntermNode *child : *node->getSequence()) + { + ASSERT(child != nullptr); + child->traverse(this); + mBlockStack.back().push_back(child); + } + } + if (mBlockStack.back().size() > node->getSequence()->size()) + { + node->getSequence()->clear(); + *(node->getSequence()) = mBlockStack.back(); + } + mBlockStack.pop_back(); + return false; +} + +void ScalarizeArgsTraverser::scalarizeArgs(TIntermAggregate *aggregate, + bool scalarizeVector, + bool scalarizeMatrix) +{ + ASSERT(aggregate); + ASSERT(!aggregate->isArray()); + int size = static_cast(aggregate->getType().getObjectSize()); + TIntermSequence *sequence = aggregate->getSequence(); + TIntermSequence originalArgs(*sequence); + sequence->clear(); + for (TIntermNode *originalArgNode : originalArgs) + { + ASSERT(size > 0); + TIntermTyped *originalArg = originalArgNode->getAsTyped(); + ASSERT(originalArg); + TIntermTyped *argVariable = createTempVariable(originalArg); + if (originalArg->isScalar()) + { + sequence->push_back(argVariable); + size--; + } + else if (originalArg->isVector()) + { + if (scalarizeVector) + { + int repeat = std::min(size, originalArg->getNominalSize()); + size -= repeat; + for (int index = 0; index < repeat; ++index) + { + TIntermBinary *newNode = + ConstructVectorIndexBinaryNode(argVariable->deepCopy(), index); + sequence->push_back(newNode); + } + } + else + { + sequence->push_back(argVariable); + size -= originalArg->getNominalSize(); + } + } + else + { + ASSERT(originalArg->isMatrix()); + if (scalarizeMatrix) + { + int colIndex = 0, rowIndex = 0; + int repeat = std::min(size, originalArg->getCols() * originalArg->getRows()); + size -= repeat; + while (repeat > 0) + { + TIntermBinary *newNode = + ConstructMatrixIndexBinaryNode(argVariable->deepCopy(), colIndex, rowIndex); + sequence->push_back(newNode); + rowIndex++; + if (rowIndex >= originalArg->getRows()) + { + rowIndex = 0; + colIndex++; + } + repeat--; + } + } + else + { + sequence->push_back(argVariable); + size -= originalArg->getCols() * originalArg->getRows(); + } + } + } +} + +TIntermTyped *ScalarizeArgsTraverser::createTempVariable(TIntermTyped *original) +{ + ASSERT(original); + + TType *type = new TType(original->getType()); + type->setQualifier(EvqTemporary); + + // The precision of the constant must have been retained (or derived), which will now apply to + // the temp variable. In some cases, the precision cannot be derived, so use the constant as + // is. For example, in the following standalone statement, the precision of the constant 0 + // cannot be determined: + // + // mat2(0, bvec3(m)); + // + if (IsPrecisionApplicableToType(type->getBasicType()) && type->getPrecision() == EbpUndefined) + { + return original; + } + + TVariable *variable = CreateTempVariable(mSymbolTable, type); + + ASSERT(mBlockStack.size() > 0); + TIntermSequence &sequence = mBlockStack.back(); + TIntermDeclaration *declaration = CreateTempInitDeclarationNode(variable, original); + sequence.push_back(declaration); + + return CreateTempSymbolNode(variable); +} + +} // namespace + +bool ScalarizeVecAndMatConstructorArgs(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable) +{ + ScalarizeArgsTraverser scalarizer(symbolTable); + root->traverse(&scalarizer); + + return compiler->validateAST(root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h new file mode 100644 index 0000000000..617cbd7682 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h @@ -0,0 +1,28 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Scalarize vector and matrix constructor args, so that vectors built from components don't have +// matrix arguments, and matrices built from components don't have vector arguments. This avoids +// driver bugs around vector and matrix constructors. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ + +#include "GLSLANG/ShaderLang.h" +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool ScalarizeVecAndMatConstructorArgs(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateDeclarations.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateDeclarations.cpp new file mode 100644 index 0000000000..6d48449154 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateDeclarations.cpp @@ -0,0 +1,199 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// The SeparateDeclarations function processes declarations, so that in the end each declaration +// contains only one declarator. +// This is useful as an intermediate step when initialization needs to be separated from +// declaration, or when things need to be unfolded out of the initializer. +// Example: +// int a[1] = int[1](1), b[1] = int[1](2); +// gets transformed when run through this class into the AST equivalent of: +// int a[1] = int[1](1); +// int b[1] = int[1](2); + +#include "compiler/translator/tree_ops/SeparateDeclarations.h" + +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" + +namespace sh +{ + +namespace +{ + +class SeparateDeclarationsTraverser : private TIntermTraverser +{ + public: + [[nodiscard]] static bool apply(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable); + + private: + SeparateDeclarationsTraverser(TSymbolTable *symbolTable); + bool visitDeclaration(Visit, TIntermDeclaration *node) override; + void visitSymbol(TIntermSymbol *symbol) override; + + void separateDeclarator(TIntermSequence *sequence, + size_t index, + TIntermSequence *replacementDeclarations, + const TStructure **replacementStructure); + + VariableReplacementMap mVariableMap; +}; + +bool SeparateDeclarationsTraverser::apply(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable) +{ + SeparateDeclarationsTraverser separateDecl(symbolTable); + root->traverse(&separateDecl); + return separateDecl.updateTree(compiler, root); +} + +SeparateDeclarationsTraverser::SeparateDeclarationsTraverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, false, false, symbolTable) +{} + +bool SeparateDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node) +{ + TIntermSequence *sequence = node->getSequence(); + if (sequence->size() <= 1) + { + return true; + } + + TIntermBlock *parentBlock = getParentNode()->getAsBlock(); + ASSERT(parentBlock != nullptr); + + TIntermSequence replacementDeclarations; + const TStructure *replacementStructure = nullptr; + for (size_t ii = 0; ii < sequence->size(); ++ii) + { + separateDeclarator(sequence, ii, &replacementDeclarations, &replacementStructure); + } + + mMultiReplacements.emplace_back(parentBlock, node, std::move(replacementDeclarations)); + return false; +} + +void SeparateDeclarationsTraverser::visitSymbol(TIntermSymbol *symbol) +{ + const TVariable *variable = &symbol->variable(); + if (mVariableMap.count(variable) > 0) + { + queueAccessChainReplacement(mVariableMap[variable]->deepCopy()); + } +} + +void SeparateDeclarationsTraverser::separateDeclarator(TIntermSequence *sequence, + size_t index, + TIntermSequence *replacementDeclarations, + const TStructure **replacementStructure) +{ + TIntermTyped *declarator = sequence->at(index)->getAsTyped(); + const TType &declaratorType = declarator->getType(); + + // If the declaration is not simultaneously declaring a struct, can use the same declarator. + // Otherwise, the first declarator is taken as-is if the struct has a name. + const TStructure *structure = declaratorType.getStruct(); + const bool isStructSpecifier = declaratorType.isStructSpecifier(); + if (!isStructSpecifier || (index == 0 && structure->symbolType() != SymbolType::Empty)) + { + TIntermDeclaration *replacementDeclaration = new TIntermDeclaration; + + // Make sure to update the declarator's initializers if any. + declarator->traverse(this); + + replacementDeclaration->appendDeclarator(declarator); + replacementDeclaration->setLine(declarator->getLine()); + replacementDeclarations->push_back(replacementDeclaration); + return; + } + + // If the struct is nameless, split it out first. + if (structure->symbolType() == SymbolType::Empty) + { + if (*replacementStructure == nullptr) + { + TStructure *newStructure = + new TStructure(mSymbolTable, kEmptyImmutableString, &structure->fields(), + SymbolType::AngleInternal); + newStructure->setAtGlobalScope(structure->atGlobalScope()); + *replacementStructure = structure = newStructure; + + TType *namedType = new TType(structure, true); + namedType->setQualifier(EvqGlobal); + + TVariable *structVariable = + new TVariable(mSymbolTable, kEmptyImmutableString, namedType, SymbolType::Empty); + + TIntermDeclaration *structDeclaration = new TIntermDeclaration; + structDeclaration->appendDeclarator(new TIntermSymbol(structVariable)); + structDeclaration->setLine(declarator->getLine()); + replacementDeclarations->push_back(structDeclaration); + } + else + { + structure = *replacementStructure; + } + } + + // Redeclare the declarator but not as a struct specifier. + TIntermSymbol *asSymbol = declarator->getAsSymbolNode(); + TIntermTyped *initializer = nullptr; + if (asSymbol == nullptr) + { + TIntermBinary *asBinary = declarator->getAsBinaryNode(); + ASSERT(asBinary->getOp() == EOpInitialize); + asSymbol = asBinary->getLeft()->getAsSymbolNode(); + initializer = asBinary->getRight(); + + // Make sure the initializer itself has its variables replaced if necessary. + if (initializer->getAsSymbolNode()) + { + const TVariable *initializerVariable = &initializer->getAsSymbolNode()->variable(); + if (mVariableMap.count(initializerVariable) > 0) + { + initializer = mVariableMap[initializerVariable]->deepCopy(); + } + } + else + { + initializer->traverse(this); + } + } + + ASSERT(asSymbol && asSymbol->variable().symbolType() != SymbolType::Empty); + + TType *newType = new TType(structure, false); + newType->setQualifier(asSymbol->getType().getQualifier()); + newType->makeArrays(asSymbol->getType().getArraySizes()); + + TVariable *replacementVar = new TVariable(mSymbolTable, asSymbol->getName(), newType, + asSymbol->variable().symbolType()); + TIntermSymbol *replacementSymbol = new TIntermSymbol(replacementVar); + TIntermTyped *replacement = replacementSymbol; + if (initializer) + { + replacement = new TIntermBinary(EOpInitialize, replacement, initializer); + } + + TIntermDeclaration *replacementDeclaration = new TIntermDeclaration; + replacementDeclaration->appendDeclarator(replacement); + replacementDeclaration->setLine(declarator->getLine()); + replacementDeclarations->push_back(replacementDeclaration); + + mVariableMap[&asSymbol->variable()] = replacementSymbol; +} +} // namespace + +bool SeparateDeclarations(TCompiler *compiler, TIntermNode *root, TSymbolTable *symbolTable) +{ + return SeparateDeclarationsTraverser::apply(compiler, root, symbolTable); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateDeclarations.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateDeclarations.h new file mode 100644 index 0000000000..5f55162ef4 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateDeclarations.h @@ -0,0 +1,32 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// The SeparateDeclarations function processes declarations, so that in the end each declaration +// contains only one declarator. +// This is useful as an intermediate step when initialization needs to be separated from +// declaration, or when things need to be unfolded out of the initializer. +// Example: +// int a[1] = int[1](1), b[1] = int[1](2); +// gets transformed when run through this class into the AST equivalent of: +// int a[1] = int[1](1); +// int b[1] = int[1](2); + +#ifndef COMPILER_TRANSLATOR_TREEOPS_SEPARATEDECLARATIONS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_SEPARATEDECLARATIONS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermNode; +class TSymbolTable; + +[[nodiscard]] bool SeparateDeclarations(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_SEPARATEDECLARATIONS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.cpp new file mode 100644 index 0000000000..fb3f4ba1c1 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.cpp @@ -0,0 +1,115 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SeparateStructFromUniformDeclarations: Separate struct declarations from uniform declarations. +// + +#include "compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" + +namespace sh +{ +namespace +{ +// This traverser translates embedded uniform structs into a specifier and declaration. +// This makes the declarations easier to move into uniform blocks. +class Traverser : public TIntermTraverser +{ + public: + explicit Traverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, false, false, symbolTable) + {} + + bool visitDeclaration(Visit visit, TIntermDeclaration *decl) override + { + ASSERT(visit == PreVisit); + + if (!mInGlobalScope) + { + return true; + } + + const TIntermSequence &sequence = *(decl->getSequence()); + ASSERT(sequence.size() == 1); + TIntermTyped *declarator = sequence.front()->getAsTyped(); + const TType &type = declarator->getType(); + + if (type.isStructSpecifier() && type.getQualifier() == EvqUniform) + { + doReplacement(decl, declarator, type); + return false; + } + + return true; + } + + void visitSymbol(TIntermSymbol *symbol) override + { + const TVariable *variable = &symbol->variable(); + if (mVariableMap.count(variable) > 0) + { + queueAccessChainReplacement(mVariableMap[variable]->deepCopy()); + } + } + + private: + void doReplacement(TIntermDeclaration *decl, TIntermTyped *declarator, const TType &oldType) + { + const TStructure *structure = oldType.getStruct(); + if (structure->symbolType() == SymbolType::Empty) + { + // Handle nameless structs: uniform struct { ... } variable; + structure = new TStructure(mSymbolTable, kEmptyImmutableString, &structure->fields(), + SymbolType::AngleInternal); + } + TType *namedType = new TType(structure, true); + namedType->setQualifier(EvqGlobal); + + TVariable *structVariable = + new TVariable(mSymbolTable, kEmptyImmutableString, namedType, SymbolType::Empty); + TIntermSymbol *structDeclarator = new TIntermSymbol(structVariable); + TIntermDeclaration *structDeclaration = new TIntermDeclaration; + structDeclaration->appendDeclarator(structDeclarator); + + TIntermSequence newSequence; + newSequence.push_back(structDeclaration); + + // Redeclare the uniform with the (potentially) new struct type + TIntermSymbol *asSymbol = declarator->getAsSymbolNode(); + ASSERT(asSymbol && asSymbol->variable().symbolType() != SymbolType::Empty); + + TIntermDeclaration *namedDecl = new TIntermDeclaration; + TType *uniformType = new TType(structure, false); + uniformType->setQualifier(EvqUniform); + uniformType->makeArrays(oldType.getArraySizes()); + + TVariable *newVar = new TVariable(mSymbolTable, asSymbol->getName(), uniformType, + asSymbol->variable().symbolType()); + TIntermSymbol *newSymbol = new TIntermSymbol(newVar); + namedDecl->appendDeclarator(newSymbol); + + newSequence.push_back(namedDecl); + + mVariableMap[&asSymbol->variable()] = newSymbol; + + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), decl, + std::move(newSequence)); + } + + VariableReplacementMap mVariableMap; +}; +} // anonymous namespace + +bool SeparateStructFromUniformDeclarations(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable) +{ + Traverser separateStructDecls(symbolTable); + root->traverse(&separateStructDecls); + return separateStructDecls.updateTree(compiler, root); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.h new file mode 100644 index 0000000000..424a742e54 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/SeparateStructFromUniformDeclarations.h @@ -0,0 +1,39 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SeparateStructFromUniformDeclarations: Separate struct declarations from uniform declarations. +// It necessarily gives nameless uniform structs internal names. +// +// For example: +// uniform struct { int a; } uni; +// becomes: +// struct s1 { int a; }; +// uniform s1 uni; +// +// And: +// uniform struct S { int a; } uni; +// becomes: +// struct S { int a; }; +// uniform S uni; +// +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_SEPARATESTRUCTFROMUNIFORMDECLARATIONS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_SEPARATESTRUCTFROMUNIFORMDECLARATIONS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool SeparateStructFromUniformDeclarations(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_SEPARATESTRUCTFROMUNIFORMDECLARATIONS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/SimplifyLoopConditions.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/SimplifyLoopConditions.cpp new file mode 100644 index 0000000000..c6a3e0b9ee --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/SimplifyLoopConditions.cpp @@ -0,0 +1,499 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SimplifyLoopConditions is an AST traverser that converts loop conditions and loop expressions +// to regular statements inside the loop. This way further transformations that generate statements +// from loop conditions and loop expressions work correctly. +// + +#include "compiler/translator/tree_ops/SimplifyLoopConditions.h" + +#include "compiler/translator/StaticType.h" +#include "compiler/translator/tree_util/IntermNodePatternMatcher.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +struct LoopInfo +{ + const TVariable *conditionVariable = nullptr; + TIntermTyped *condition = nullptr; + TIntermTyped *expression = nullptr; +}; + +class SimplifyLoopConditionsTraverser : public TLValueTrackingTraverser +{ + public: + SimplifyLoopConditionsTraverser(const IntermNodePatternMatcher *conditionsToSimplify, + TSymbolTable *symbolTable); + + void traverseLoop(TIntermLoop *node) override; + + bool visitUnary(Visit visit, TIntermUnary *node) override; + bool visitBinary(Visit visit, TIntermBinary *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + bool visitTernary(Visit visit, TIntermTernary *node) override; + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; + bool visitBranch(Visit visit, TIntermBranch *node) override; + + bool foundLoopToChange() const { return mFoundLoopToChange; } + + protected: + // Marked to true once an operation that needs to be hoisted out of a loop expression has been + // found. + bool mFoundLoopToChange; + bool mInsideLoopInitConditionOrExpression; + const IntermNodePatternMatcher *mConditionsToSimplify; + + private: + LoopInfo mLoop; +}; + +SimplifyLoopConditionsTraverser::SimplifyLoopConditionsTraverser( + const IntermNodePatternMatcher *conditionsToSimplify, + TSymbolTable *symbolTable) + : TLValueTrackingTraverser(true, false, false, symbolTable), + mFoundLoopToChange(false), + mInsideLoopInitConditionOrExpression(false), + mConditionsToSimplify(conditionsToSimplify) +{} + +// If we're inside a loop initialization, condition, or expression, we check for expressions that +// should be moved out of the loop condition or expression. If one is found, the loop is +// transformed. +// If we're not inside loop initialization, condition, or expression, we only need to traverse nodes +// that may contain loops. + +bool SimplifyLoopConditionsTraverser::visitUnary(Visit visit, TIntermUnary *node) +{ + if (!mInsideLoopInitConditionOrExpression) + return false; + + if (mFoundLoopToChange) + return false; // Already decided to change this loop. + + ASSERT(mConditionsToSimplify); + mFoundLoopToChange = mConditionsToSimplify->match(node); + return !mFoundLoopToChange; +} + +bool SimplifyLoopConditionsTraverser::visitBinary(Visit visit, TIntermBinary *node) +{ + if (!mInsideLoopInitConditionOrExpression) + return false; + + if (mFoundLoopToChange) + return false; // Already decided to change this loop. + + ASSERT(mConditionsToSimplify); + mFoundLoopToChange = + mConditionsToSimplify->match(node, getParentNode(), isLValueRequiredHere()); + return !mFoundLoopToChange; +} + +bool SimplifyLoopConditionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + if (!mInsideLoopInitConditionOrExpression) + return false; + + if (mFoundLoopToChange) + return false; // Already decided to change this loop. + + ASSERT(mConditionsToSimplify); + mFoundLoopToChange = mConditionsToSimplify->match(node, getParentNode()); + return !mFoundLoopToChange; +} + +bool SimplifyLoopConditionsTraverser::visitTernary(Visit visit, TIntermTernary *node) +{ + if (!mInsideLoopInitConditionOrExpression) + return false; + + if (mFoundLoopToChange) + return false; // Already decided to change this loop. + + ASSERT(mConditionsToSimplify); + mFoundLoopToChange = mConditionsToSimplify->match(node); + return !mFoundLoopToChange; +} + +bool SimplifyLoopConditionsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) +{ + if (!mInsideLoopInitConditionOrExpression) + return false; + + if (mFoundLoopToChange) + return false; // Already decided to change this loop. + + ASSERT(mConditionsToSimplify); + mFoundLoopToChange = mConditionsToSimplify->match(node); + return !mFoundLoopToChange; +} + +bool SimplifyLoopConditionsTraverser::visitBranch(Visit visit, TIntermBranch *node) +{ + if (node->getFlowOp() == EOpContinue && (mLoop.condition || mLoop.expression)) + { + TIntermBlock *parent = getParentNode()->getAsBlock(); + ASSERT(parent); + TIntermSequence seq; + if (mLoop.expression) + { + seq.push_back(mLoop.expression->deepCopy()); + } + if (mLoop.condition) + { + ASSERT(mLoop.conditionVariable); + seq.push_back( + CreateTempAssignmentNode(mLoop.conditionVariable, mLoop.condition->deepCopy())); + } + seq.push_back(node); + mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parent, node, std::move(seq))); + } + + return true; +} + +TIntermBlock *CreateFromBody(TIntermLoop *node, bool *bodyEndsInBranchOut) +{ + TIntermBlock *newBody = new TIntermBlock(); + *bodyEndsInBranchOut = false; + + TIntermBlock *nodeBody = node->getBody(); + if (nodeBody != nullptr) + { + newBody->getSequence()->push_back(nodeBody); + *bodyEndsInBranchOut = EndsInBranch(nodeBody); + } + return newBody; +} + +void SimplifyLoopConditionsTraverser::traverseLoop(TIntermLoop *node) +{ + // Mark that we're inside a loop condition or expression, and determine if the loop needs to be + // transformed. + + ScopedNodeInTraversalPath addToPath(this, node); + + mInsideLoopInitConditionOrExpression = true; + mFoundLoopToChange = !mConditionsToSimplify; + + if (!mFoundLoopToChange && node->getInit()) + { + node->getInit()->traverse(this); + } + + if (!mFoundLoopToChange && node->getCondition()) + { + node->getCondition()->traverse(this); + } + + if (!mFoundLoopToChange && node->getExpression()) + { + node->getExpression()->traverse(this); + } + + mInsideLoopInitConditionOrExpression = false; + + const LoopInfo prevLoop = mLoop; + + if (mFoundLoopToChange) + { + const TType *boolType = StaticType::Get(); + mLoop.conditionVariable = CreateTempVariable(mSymbolTable, boolType); + mLoop.condition = node->getCondition(); + mLoop.expression = node->getExpression(); + + // Replace the loop condition with a boolean variable that's updated on each iteration. + TLoopType loopType = node->getType(); + if (loopType == ELoopWhile) + { + ASSERT(!mLoop.expression); + + if (mLoop.condition->getAsSymbolNode()) + { + // Mask continue statement condition variable update. + mLoop.condition = nullptr; + } + else if (mLoop.condition->getAsConstantUnion()) + { + // Transform: + // while (expr) { body; } + // into + // bool s0 = expr; + // while (s0) { body; } + TIntermDeclaration *tempInitDeclaration = + CreateTempInitDeclarationNode(mLoop.conditionVariable, mLoop.condition); + insertStatementInParentBlock(tempInitDeclaration); + + node->setCondition(CreateTempSymbolNode(mLoop.conditionVariable)); + + // Mask continue statement condition variable update. + mLoop.condition = nullptr; + } + else + { + // Transform: + // while (expr) { body; } + // into + // bool s0 = expr; + // while (s0) { { body; } s0 = expr; } + // + // Local case statements are transformed into: + // s0 = expr; continue; + TIntermDeclaration *tempInitDeclaration = + CreateTempInitDeclarationNode(mLoop.conditionVariable, mLoop.condition); + insertStatementInParentBlock(tempInitDeclaration); + + bool bodyEndsInBranch; + TIntermBlock *newBody = CreateFromBody(node, &bodyEndsInBranch); + if (!bodyEndsInBranch) + { + newBody->getSequence()->push_back(CreateTempAssignmentNode( + mLoop.conditionVariable, mLoop.condition->deepCopy())); + } + + // Can't use queueReplacement to replace old body, since it may have been nullptr. + // It's safe to do the replacements in place here - the new body will still be + // traversed, but that won't create any problems. + node->setBody(newBody); + node->setCondition(CreateTempSymbolNode(mLoop.conditionVariable)); + } + } + else if (loopType == ELoopDoWhile) + { + ASSERT(!mLoop.expression); + + if (mLoop.condition->getAsSymbolNode()) + { + // Mask continue statement condition variable update. + mLoop.condition = nullptr; + } + else if (mLoop.condition->getAsConstantUnion()) + { + // Transform: + // do { + // body; + // } while (expr); + // into + // bool s0 = expr; + // do { + // body; + // } while (s0); + TIntermDeclaration *tempInitDeclaration = + CreateTempInitDeclarationNode(mLoop.conditionVariable, mLoop.condition); + insertStatementInParentBlock(tempInitDeclaration); + + node->setCondition(CreateTempSymbolNode(mLoop.conditionVariable)); + + // Mask continue statement condition variable update. + mLoop.condition = nullptr; + } + else + { + // Transform: + // do { + // body; + // } while (expr); + // into + // bool s0; + // do { + // { body; } + // s0 = expr; + // } while (s0); + // Local case statements are transformed into: + // s0 = expr; continue; + TIntermDeclaration *tempInitDeclaration = + CreateTempDeclarationNode(mLoop.conditionVariable); + insertStatementInParentBlock(tempInitDeclaration); + + bool bodyEndsInBranch; + TIntermBlock *newBody = CreateFromBody(node, &bodyEndsInBranch); + if (!bodyEndsInBranch) + { + newBody->getSequence()->push_back( + CreateTempAssignmentNode(mLoop.conditionVariable, mLoop.condition)); + } + + // Can't use queueReplacement to replace old body, since it may have been nullptr. + // It's safe to do the replacements in place here - the new body will still be + // traversed, but that won't create any problems. + node->setBody(newBody); + node->setCondition(CreateTempSymbolNode(mLoop.conditionVariable)); + } + } + else if (loopType == ELoopFor) + { + if (!mLoop.condition) + { + mLoop.condition = CreateBoolNode(true); + } + + TIntermLoop *whileLoop; + TIntermBlock *loopScope = new TIntermBlock(); + TIntermSequence *loopScopeSequence = loopScope->getSequence(); + + // Insert "init;" + if (node->getInit()) + { + loopScopeSequence->push_back(node->getInit()); + } + + if (mLoop.condition->getAsSymbolNode()) + { + // Move the loop condition inside the loop. + // Transform: + // for (init; expr; exprB) { body; } + // into + // { + // init; + // while (expr) { + // { body; } + // exprB; + // } + // } + // + // Local case statements are transformed into: + // exprB; continue; + + // Insert "{ body; }" in the while loop + bool bodyEndsInBranch; + TIntermBlock *whileLoopBody = CreateFromBody(node, &bodyEndsInBranch); + // Insert "exprB;" in the while loop + if (!bodyEndsInBranch && node->getExpression()) + { + whileLoopBody->getSequence()->push_back(node->getExpression()); + } + // Create "while(expr) { whileLoopBody }" + whileLoop = + new TIntermLoop(ELoopWhile, nullptr, mLoop.condition, nullptr, whileLoopBody); + + // Mask continue statement condition variable update. + mLoop.condition = nullptr; + } + else if (mLoop.condition->getAsConstantUnion()) + { + // Move the loop condition inside the loop. + // Transform: + // for (init; expr; exprB) { body; } + // into + // { + // init; + // bool s0 = expr; + // while (s0) { + // { body; } + // exprB; + // } + // } + // + // Local case statements are transformed into: + // exprB; continue; + + // Insert "bool s0 = expr;" + loopScopeSequence->push_back( + CreateTempInitDeclarationNode(mLoop.conditionVariable, mLoop.condition)); + // Insert "{ body; }" in the while loop + bool bodyEndsInBranch; + TIntermBlock *whileLoopBody = CreateFromBody(node, &bodyEndsInBranch); + // Insert "exprB;" in the while loop + if (!bodyEndsInBranch && node->getExpression()) + { + whileLoopBody->getSequence()->push_back(node->getExpression()); + } + // Create "while(s0) { whileLoopBody }" + whileLoop = new TIntermLoop(ELoopWhile, nullptr, + CreateTempSymbolNode(mLoop.conditionVariable), nullptr, + whileLoopBody); + + // Mask continue statement condition variable update. + mLoop.condition = nullptr; + } + else + { + // Move the loop condition inside the loop. + // Transform: + // for (init; expr; exprB) { body; } + // into + // { + // init; + // bool s0 = expr; + // while (s0) { + // { body; } + // exprB; + // s0 = expr; + // } + // } + // + // Local case statements are transformed into: + // exprB; s0 = expr; continue; + + // Insert "bool s0 = expr;" + loopScopeSequence->push_back( + CreateTempInitDeclarationNode(mLoop.conditionVariable, mLoop.condition)); + // Insert "{ body; }" in the while loop + bool bodyEndsInBranch; + TIntermBlock *whileLoopBody = CreateFromBody(node, &bodyEndsInBranch); + // Insert "exprB;" in the while loop + if (!bodyEndsInBranch && node->getExpression()) + { + whileLoopBody->getSequence()->push_back(node->getExpression()); + } + // Insert "s0 = expr;" in the while loop + if (!bodyEndsInBranch) + { + whileLoopBody->getSequence()->push_back(CreateTempAssignmentNode( + mLoop.conditionVariable, mLoop.condition->deepCopy())); + } + // Create "while(s0) { whileLoopBody }" + whileLoop = new TIntermLoop(ELoopWhile, nullptr, + CreateTempSymbolNode(mLoop.conditionVariable), nullptr, + whileLoopBody); + } + + loopScope->getSequence()->push_back(whileLoop); + queueReplacement(loopScope, OriginalNode::IS_DROPPED); + + // After this the old body node will be traversed and loops inside it may be + // transformed. This is fine, since the old body node will still be in the AST after + // the transformation that's queued here, and transforming loops inside it doesn't + // need to know the exact post-transform path to it. + } + } + + mFoundLoopToChange = false; + + // We traverse the body of the loop even if the loop is transformed. + if (node->getBody()) + node->getBody()->traverse(this); + + mLoop = prevLoop; +} + +} // namespace + +bool SimplifyLoopConditions(TCompiler *compiler, TIntermNode *root, TSymbolTable *symbolTable) +{ + SimplifyLoopConditionsTraverser traverser(nullptr, symbolTable); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +bool SimplifyLoopConditions(TCompiler *compiler, + TIntermNode *root, + unsigned int conditionsToSimplifyMask, + TSymbolTable *symbolTable) +{ + IntermNodePatternMatcher conditionsToSimplify(conditionsToSimplifyMask); + SimplifyLoopConditionsTraverser traverser(&conditionsToSimplify, symbolTable); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/SimplifyLoopConditions.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/SimplifyLoopConditions.h new file mode 100644 index 0000000000..2a554c019d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/SimplifyLoopConditions.h @@ -0,0 +1,32 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SimplifyLoopConditions is an AST traverser that converts loop conditions and loop expressions +// to regular statements inside the loop. This way further transformations that generate statements +// from loop conditions and loop expressions work correctly. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_SIMPLIFYLOOPCONDITIONS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_SIMPLIFYLOOPCONDITIONS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermNode; +class TSymbolTable; + +[[nodiscard]] bool SimplifyLoopConditions(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable); + +[[nodiscard]] bool SimplifyLoopConditions(TCompiler *compiler, + TIntermNode *root, + unsigned int conditionsToSimplify, + TSymbolTable *symbolTable); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_SIMPLIFYLOOPCONDITIONS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/SplitSequenceOperator.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/SplitSequenceOperator.cpp new file mode 100644 index 0000000000..45985954b0 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/SplitSequenceOperator.cpp @@ -0,0 +1,173 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SplitSequenceOperator is an AST traverser that detects sequence operator expressions that +// go through further AST transformations that generate statements, and splits them so that +// possible side effects of earlier parts of the sequence operator expression are guaranteed to be +// evaluated before the latter parts of the sequence operator expression are evaluated. +// + +#include "compiler/translator/tree_ops/SplitSequenceOperator.h" + +#include "compiler/translator/tree_util/IntermNodePatternMatcher.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser +{ + public: + SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask, TSymbolTable *symbolTable); + + bool visitUnary(Visit visit, TIntermUnary *node) override; + bool visitBinary(Visit visit, TIntermBinary *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + bool visitTernary(Visit visit, TIntermTernary *node) override; + + void nextIteration(); + bool foundExpressionToSplit() const { return mFoundExpressionToSplit; } + + protected: + // Marked to true once an operation that needs to be hoisted out of the expression has been + // found. After that, no more AST updates are performed on that traversal. + bool mFoundExpressionToSplit; + int mInsideSequenceOperator; + + IntermNodePatternMatcher mPatternToSplitMatcher; +}; + +SplitSequenceOperatorTraverser::SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask, + TSymbolTable *symbolTable) + : TLValueTrackingTraverser(true, false, true, symbolTable), + mFoundExpressionToSplit(false), + mInsideSequenceOperator(0), + mPatternToSplitMatcher(patternsToSplitMask) +{} + +void SplitSequenceOperatorTraverser::nextIteration() +{ + mFoundExpressionToSplit = false; + mInsideSequenceOperator = 0; +} + +bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + if (mFoundExpressionToSplit) + return false; + + if (mInsideSequenceOperator > 0 && visit == PreVisit) + { + // Detect expressions that need to be simplified + mFoundExpressionToSplit = mPatternToSplitMatcher.match(node, getParentNode()); + return !mFoundExpressionToSplit; + } + + return true; +} + +bool SplitSequenceOperatorTraverser::visitUnary(Visit visit, TIntermUnary *node) +{ + if (mFoundExpressionToSplit) + return false; + + if (mInsideSequenceOperator > 0 && visit == PreVisit) + { + // Detect expressions that need to be simplified + mFoundExpressionToSplit = mPatternToSplitMatcher.match(node); + return !mFoundExpressionToSplit; + } + + return true; +} + +bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *node) +{ + if (node->getOp() == EOpComma) + { + if (visit == PreVisit) + { + if (mFoundExpressionToSplit) + { + return false; + } + mInsideSequenceOperator++; + } + else if (visit == PostVisit) + { + // Split sequence operators starting from the outermost one to preserve correct + // execution order. + if (mFoundExpressionToSplit && mInsideSequenceOperator == 1) + { + // Move the left side operand into a separate statement in the parent block. + TIntermSequence insertions; + insertions.push_back(node->getLeft()); + insertStatementsInParentBlock(insertions); + // Replace the comma node with its right side operand. + queueReplacement(node->getRight(), OriginalNode::IS_DROPPED); + } + mInsideSequenceOperator--; + } + return true; + } + + if (mFoundExpressionToSplit) + return false; + + if (mInsideSequenceOperator > 0 && visit == PreVisit) + { + // Detect expressions that need to be simplified + mFoundExpressionToSplit = + mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere()); + return !mFoundExpressionToSplit; + } + + return true; +} + +bool SplitSequenceOperatorTraverser::visitTernary(Visit visit, TIntermTernary *node) +{ + if (mFoundExpressionToSplit) + return false; + + if (mInsideSequenceOperator > 0 && visit == PreVisit) + { + // Detect expressions that need to be simplified + mFoundExpressionToSplit = mPatternToSplitMatcher.match(node); + return !mFoundExpressionToSplit; + } + + return true; +} + +} // namespace + +bool SplitSequenceOperator(TCompiler *compiler, + TIntermNode *root, + int patternsToSplitMask, + TSymbolTable *symbolTable) +{ + SplitSequenceOperatorTraverser traverser(patternsToSplitMask, symbolTable); + // Separate one expression at a time, and reset the traverser between iterations. + do + { + traverser.nextIteration(); + root->traverse(&traverser); + if (traverser.foundExpressionToSplit()) + { + if (!traverser.updateTree(compiler, root)) + { + return false; + } + } + } while (traverser.foundExpressionToSplit()); + + return true; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/SplitSequenceOperator.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/SplitSequenceOperator.h new file mode 100644 index 0000000000..2a9f09a1f2 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/SplitSequenceOperator.h @@ -0,0 +1,30 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SplitSequenceOperator is an AST traverser that detects sequence operator expressions that +// go through further AST transformations that generate statements, and splits them so that +// possible side effects of earlier parts of the sequence operator expression are guaranteed to be +// evaluated before the latter parts of the sequence operator expression are evaluated. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_SPLITSEQUENCEOPERATOR_H_ +#define COMPILER_TRANSLATOR_TREEOPS_SPLITSEQUENCEOPERATOR_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermNode; +class TSymbolTable; + +[[nodiscard]] bool SplitSequenceOperator(TCompiler *compiler, + TIntermNode *root, + int patternsToSplitMask, + TSymbolTable *symbolTable); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_SPLITSEQUENCEOPERATOR_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/AddAndTrueToLoopCondition.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/AddAndTrueToLoopCondition.cpp new file mode 100644 index 0000000000..36e426f8e1 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/AddAndTrueToLoopCondition.cpp @@ -0,0 +1,60 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/tree_ops/apple/AddAndTrueToLoopCondition.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +// An AST traverser that rewrites for and while loops by replacing "condition" with +// "condition && true" to work around condition bug on Intel Mac. +class AddAndTrueToLoopConditionTraverser : public TIntermTraverser +{ + public: + AddAndTrueToLoopConditionTraverser() : TIntermTraverser(true, false, false) {} + + bool visitLoop(Visit, TIntermLoop *loop) override + { + // do-while loop doesn't have this bug. + if (loop->getType() != ELoopFor && loop->getType() != ELoopWhile) + { + return true; + } + + // For loop may not have a condition. + if (loop->getCondition() == nullptr) + { + return true; + } + + // Constant true. + TIntermTyped *trueValue = CreateBoolNode(true); + + // CONDITION && true. + TIntermBinary *andOp = new TIntermBinary(EOpLogicalAnd, loop->getCondition(), trueValue); + loop->setCondition(andOp); + + return true; + } +}; + +} // anonymous namespace + +bool AddAndTrueToLoopCondition(TCompiler *compiler, TIntermNode *root) +{ + AddAndTrueToLoopConditionTraverser traverser; + root->traverse(&traverser); + return compiler->validateAST(root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/AddAndTrueToLoopCondition.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/AddAndTrueToLoopCondition.h new file mode 100644 index 0000000000..d23158e81a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/AddAndTrueToLoopCondition.h @@ -0,0 +1,31 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Rewrite condition in for and while loops to work around driver bug on Intel Mac. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_APPLE_ADDANDTRUETOLOOPCONDITION_H_ +#define COMPILER_TRANSLATOR_TREEOPS_APPLE_ADDANDTRUETOLOOPCONDITION_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermNode; + +#if defined(ANGLE_ENABLE_GLSL) && defined(ANGLE_ENABLE_APPLE_WORKAROUNDS) +[[nodiscard]] bool AddAndTrueToLoopCondition(TCompiler *compiler, TIntermNode *root); +#else +[[nodiscard]] ANGLE_INLINE bool AddAndTrueToLoopCondition(TCompiler *compiler, TIntermNode *root) +{ + UNREACHABLE(); + return false; +} +#endif + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_APPLE_ADDANDTRUETOLOOPCONDITION_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteDoWhile.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteDoWhile.cpp new file mode 100644 index 0000000000..de322aadab --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteDoWhile.cpp @@ -0,0 +1,147 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RewriteDoWhile.cpp: rewrites do-while loops using another equivalent +// construct. + +#include "compiler/translator/tree_ops/apple/RewriteDoWhile.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +// An AST traverser that rewrites loops of the form +// do { +// CODE; +// } while (CONDITION) +// +// to loops of the form +// bool temp = false; +// while (true) { +// if (temp) { +// if (!CONDITION) { +// break; +// } +// } +// temp = true; +// CODE; +// } +// +// The reason we don't use a simpler form, with for example just (temp && !CONDITION) in the +// while condition, is that short-circuit is often badly supported by driver shader compiler. +// The double if has the same effect, but forces shader compilers to behave. +// +// TODO(cwallez) when UnfoldShortCircuitIntoIf handles loops correctly, revisit this as we might +// be able to use while (temp || CONDITION) with temp initially set to true then run +// UnfoldShortCircuitIntoIf +class DoWhileRewriter : public TIntermTraverser +{ + public: + DoWhileRewriter(TSymbolTable *symbolTable) : TIntermTraverser(true, false, false, symbolTable) + {} + + bool visitBlock(Visit, TIntermBlock *node) override + { + // A well-formed AST can only have do-while inside TIntermBlock. By doing a prefix traversal + // we are able to replace the do-while in the sequence directly as the content of the + // do-while will be traversed later. + + TIntermSequence *statements = node->getSequence(); + + // The statements vector will have new statements inserted when we encounter a do-while, + // which prevents us from using a range-based for loop. Using the usual i++ works, as + // the (two) new statements inserted replace the statement at the current position. + for (size_t i = 0; i < statements->size(); i++) + { + TIntermNode *statement = (*statements)[i]; + TIntermLoop *loop = statement->getAsLoopNode(); + + if (loop == nullptr || loop->getType() != ELoopDoWhile) + { + continue; + } + + // Found a loop to change. + const TType *boolType = StaticType::Get(); + TVariable *conditionVariable = CreateTempVariable(mSymbolTable, boolType); + + // bool temp = false; + TIntermDeclaration *tempDeclaration = + CreateTempInitDeclarationNode(conditionVariable, CreateBoolNode(false)); + + // temp = true; + TIntermBinary *assignTrue = + CreateTempAssignmentNode(conditionVariable, CreateBoolNode(true)); + + // if (temp) { + // if (!CONDITION) { + // break; + // } + // } + TIntermIfElse *breakIf = nullptr; + { + TIntermBranch *breakStatement = new TIntermBranch(EOpBreak, nullptr); + + TIntermBlock *breakBlock = new TIntermBlock(); + breakBlock->getSequence()->push_back(breakStatement); + + TIntermUnary *negatedCondition = + new TIntermUnary(EOpLogicalNot, loop->getCondition(), nullptr); + + TIntermIfElse *innerIf = new TIntermIfElse(negatedCondition, breakBlock, nullptr); + + TIntermBlock *innerIfBlock = new TIntermBlock(); + innerIfBlock->getSequence()->push_back(innerIf); + + breakIf = new TIntermIfElse(CreateTempSymbolNode(conditionVariable), innerIfBlock, + nullptr); + } + + // Assemble the replacement loops, reusing the do-while loop's body and inserting our + // statements at the front. + TIntermLoop *newLoop = nullptr; + { + TIntermBlock *body = loop->getBody(); + if (body == nullptr) + { + body = new TIntermBlock(); + } + auto sequence = body->getSequence(); + sequence->insert(sequence->begin(), assignTrue); + sequence->insert(sequence->begin(), breakIf); + + newLoop = new TIntermLoop(ELoopWhile, nullptr, CreateBoolNode(true), nullptr, body); + } + + TIntermSequence replacement; + replacement.push_back(tempDeclaration); + replacement.push_back(newLoop); + + node->replaceChildNodeWithMultiple(loop, replacement); + } + return true; + } +}; + +} // anonymous namespace + +bool RewriteDoWhile(TCompiler *compiler, TIntermNode *root, TSymbolTable *symbolTable) +{ + DoWhileRewriter rewriter(symbolTable); + + root->traverse(&rewriter); + + return compiler->validateAST(root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteDoWhile.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteDoWhile.h new file mode 100644 index 0000000000..71bdc8857b --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteDoWhile.h @@ -0,0 +1,38 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RewriteDoWhile.h: rewrite do-while loops as while loops to work around +// driver bugs + +#ifndef COMPILER_TRANSLATOR_TREEOPS_APPLE_REWRITEDOWHILE_H_ +#define COMPILER_TRANSLATOR_TREEOPS_APPLE_REWRITEDOWHILE_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermNode; +class TSymbolTable; + +#if defined(ANGLE_ENABLE_GLSL) && defined(ANGLE_ENABLE_APPLE_WORKAROUNDS) +[[nodiscard]] bool RewriteDoWhile(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable); +#else +[[nodiscard]] ANGLE_INLINE bool RewriteDoWhile(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable) +{ + UNREACHABLE(); + return false; +} +#endif + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_APPLE_REWRITEDOWHILE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.cpp new file mode 100644 index 0000000000..49dc11efe2 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.cpp @@ -0,0 +1,1595 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteRowMajorMatrices: Rewrite row-major matrices as column-major. +// + +#include "compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" + +namespace sh +{ +namespace +{ +// Only structs with matrices are tracked. If layout(row_major) is applied to a struct that doesn't +// have matrices, it's silently dropped. This is also used to avoid creating duplicates for inner +// structs that don't have matrices. +struct StructConversionData +{ + // The converted struct with every matrix transposed. + TStructure *convertedStruct = nullptr; + + // The copy-from and copy-to functions copying from a struct to its converted version and back. + TFunction *copyFromOriginal = nullptr; + TFunction *copyToOriginal = nullptr; +}; + +bool DoesFieldContainRowMajorMatrix(const TField *field, bool isBlockRowMajor) +{ + TLayoutMatrixPacking matrixPacking = field->type()->getLayoutQualifier().matrixPacking; + + // The field is row major if either explicitly specified as such, or if it inherits it from the + // block layout qualifier. + if (matrixPacking == EmpColumnMajor || (matrixPacking == EmpUnspecified && !isBlockRowMajor)) + { + return false; + } + + // The field is qualified with row_major, but if it's not a matrix or a struct containing + // matrices, that's a useless qualifier. + const TType *type = field->type(); + return type->isMatrix() || type->isStructureContainingMatrices(); +} + +TField *DuplicateField(const TField *field) +{ + return new TField(new TType(*field->type()), field->name(), field->line(), field->symbolType()); +} + +void SetColumnMajor(TType *type) +{ + TLayoutQualifier layoutQualifier = type->getLayoutQualifier(); + layoutQualifier.matrixPacking = EmpColumnMajor; + type->setLayoutQualifier(layoutQualifier); +} + +TType *TransposeMatrixType(const TType *type) +{ + TType *newType = new TType(*type); + + SetColumnMajor(newType); + + newType->setPrimarySize(type->getRows()); + newType->setSecondarySize(type->getCols()); + + return newType; +} + +void CopyArraySizes(const TType *from, TType *to) +{ + if (from->isArray()) + { + to->makeArrays(from->getArraySizes()); + } +} + +// Determine if the node is an index node (array index or struct field selection). For the purposes +// of this transformation, swizzle nodes are considered index nodes too. +bool IsIndexNode(TIntermNode *node, TIntermNode *child) +{ + if (node->getAsSwizzleNode()) + { + return true; + } + + TIntermBinary *binaryNode = node->getAsBinaryNode(); + if (binaryNode == nullptr || child != binaryNode->getLeft()) + { + return false; + } + + TOperator op = binaryNode->getOp(); + + return op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock || + op == EOpIndexDirectStruct || op == EOpIndexIndirect; +} + +TIntermSymbol *CopyToTempVariable(TSymbolTable *symbolTable, + TIntermTyped *node, + TIntermSequence *prependStatements) +{ + TVariable *temp = CreateTempVariable(symbolTable, &node->getType()); + TIntermDeclaration *tempDecl = CreateTempInitDeclarationNode(temp, node); + prependStatements->push_back(tempDecl); + + return new TIntermSymbol(temp); +} + +TIntermAggregate *CreateStructCopyCall(const TFunction *copyFunc, TIntermTyped *expression) +{ + TIntermSequence args = {expression}; + return TIntermAggregate::CreateFunctionCall(*copyFunc, &args); +} + +TIntermTyped *CreateTransposeCall(TSymbolTable *symbolTable, TIntermTyped *expression) +{ + TIntermSequence args = {expression}; + return CreateBuiltInFunctionCallNode("transpose", &args, *symbolTable, 300); +} + +TOperator GetIndex(TSymbolTable *symbolTable, + TIntermNode *node, + TIntermSequence *indices, + TIntermSequence *prependStatements) +{ + // Swizzle nodes are converted EOpIndexDirect for simplicity, with one index per swizzle + // channel. + TIntermSwizzle *asSwizzle = node->getAsSwizzleNode(); + if (asSwizzle) + { + for (int channel : asSwizzle->getSwizzleOffsets()) + { + indices->push_back(CreateIndexNode(channel)); + } + return EOpIndexDirect; + } + + TIntermBinary *binaryNode = node->getAsBinaryNode(); + ASSERT(binaryNode); + + TOperator op = binaryNode->getOp(); + ASSERT(op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock || + op == EOpIndexDirectStruct || op == EOpIndexIndirect); + + TIntermTyped *rhs = binaryNode->getRight()->deepCopy(); + if (rhs->getAsConstantUnion() == nullptr) + { + rhs = CopyToTempVariable(symbolTable, rhs, prependStatements); + } + + indices->push_back(rhs); + return op; +} + +TIntermTyped *ReplicateIndexNode(TSymbolTable *symbolTable, + TIntermNode *node, + TIntermTyped *lhs, + TIntermSequence *indices) +{ + TIntermSwizzle *asSwizzle = node->getAsSwizzleNode(); + if (asSwizzle) + { + return new TIntermSwizzle(lhs, asSwizzle->getSwizzleOffsets()); + } + + TIntermBinary *binaryNode = node->getAsBinaryNode(); + ASSERT(binaryNode); + + ASSERT(indices->size() == 1); + TIntermTyped *rhs = indices->front()->getAsTyped(); + + return new TIntermBinary(binaryNode->getOp(), lhs, rhs); +} + +TOperator GetIndexOp(TIntermNode *node) +{ + return node->getAsConstantUnion() ? EOpIndexDirect : EOpIndexIndirect; +} + +bool IsConvertedField(TIntermTyped *indexNode, + const angle::HashMap &convertedFields) +{ + TIntermBinary *asBinary = indexNode->getAsBinaryNode(); + if (asBinary == nullptr) + { + return false; + } + + if (asBinary->getOp() != EOpIndexDirectInterfaceBlock) + { + return false; + } + + const TInterfaceBlock *interfaceBlock = asBinary->getLeft()->getType().getInterfaceBlock(); + ASSERT(interfaceBlock); + + TIntermConstantUnion *fieldIndexNode = asBinary->getRight()->getAsConstantUnion(); + ASSERT(fieldIndexNode); + ASSERT(fieldIndexNode->getConstantValue() != nullptr); + + int fieldIndex = fieldIndexNode->getConstantValue()->getIConst(); + const TField *field = interfaceBlock->fields()[fieldIndex]; + + return convertedFields.count(field) > 0 && convertedFields.at(field); +} + +// A helper class to transform expressions of array type. Iterates over every element of the +// array. +class TransformArrayHelper +{ + public: + TransformArrayHelper(TIntermTyped *baseExpression) + : mBaseExpression(baseExpression), + mBaseExpressionType(baseExpression->getType()), + mArrayIndices(mBaseExpressionType.getArraySizes().size(), 0) + {} + + TIntermTyped *getNextElement(TIntermTyped *valueExpression, TIntermTyped **valueElementOut) + { + const TSpan &arraySizes = mBaseExpressionType.getArraySizes(); + + // If the last index overflows, element enumeration is done. + if (mArrayIndices.back() >= arraySizes.back()) + { + return nullptr; + } + + TIntermTyped *element = getCurrentElement(mBaseExpression); + if (valueExpression) + { + *valueElementOut = getCurrentElement(valueExpression); + } + + incrementIndices(arraySizes); + return element; + } + + void accumulateForRead(TSymbolTable *symbolTable, + TIntermTyped *transformedElement, + TIntermSequence *prependStatements) + { + TIntermTyped *temp = CopyToTempVariable(symbolTable, transformedElement, prependStatements); + mReadTransformConstructorArgs.push_back(temp); + } + + TIntermTyped *constructReadTransformExpression() + { + const TSpan &baseTypeArraySizes = mBaseExpressionType.getArraySizes(); + TVector arraySizes(baseTypeArraySizes.begin(), baseTypeArraySizes.end()); + TIntermTyped *firstElement = mReadTransformConstructorArgs.front()->getAsTyped(); + const TType &baseType = firstElement->getType(); + + // If N dimensions, acc[0] == size[0] and acc[i] == size[i] * acc[i-1]. + // The last value is unused, and is not present. + TVector accumulatedArraySizes(arraySizes.size() - 1); + + if (accumulatedArraySizes.size() > 0) + { + accumulatedArraySizes[0] = arraySizes[0]; + } + for (size_t index = 1; index + 1 < arraySizes.size(); ++index) + { + accumulatedArraySizes[index] = accumulatedArraySizes[index - 1] * arraySizes[index]; + } + + return constructReadTransformExpressionHelper(arraySizes, accumulatedArraySizes, baseType, + 0); + } + + private: + TIntermTyped *getCurrentElement(TIntermTyped *expression) + { + TIntermTyped *element = expression->deepCopy(); + for (auto it = mArrayIndices.rbegin(); it != mArrayIndices.rend(); ++it) + { + unsigned int index = *it; + element = new TIntermBinary(EOpIndexDirect, element, CreateIndexNode(index)); + } + return element; + } + + void incrementIndices(const TSpan &arraySizes) + { + // Assume mArrayIndices is an N digit number, where digit i is in the range + // [0, arraySizes[i]). This function increments this number. Last digit is the most + // significant digit. + for (size_t digitIndex = 0; digitIndex < arraySizes.size(); ++digitIndex) + { + ++mArrayIndices[digitIndex]; + if (mArrayIndices[digitIndex] < arraySizes[digitIndex]) + { + break; + } + if (digitIndex + 1 != arraySizes.size()) + { + // This digit has now overflown and is reset to 0, carry will be added to the next + // digit. The most significant digit will keep the overflow though, to make it + // clear we have exhausted the range. + mArrayIndices[digitIndex] = 0; + } + } + } + + TIntermTyped *constructReadTransformExpressionHelper( + const TVector &arraySizes, + const TVector &accumulatedArraySizes, + const TType &baseType, + size_t elementsOffset) + { + ASSERT(!arraySizes.empty()); + + TType *transformedType = new TType(baseType); + transformedType->makeArrays(arraySizes); + + // If one dimensional, create the constructor with the given elements. + if (arraySizes.size() == 1) + { + ASSERT(accumulatedArraySizes.size() == 0); + + auto sliceStart = mReadTransformConstructorArgs.begin() + elementsOffset; + TIntermSequence slice(sliceStart, sliceStart + arraySizes[0]); + + return TIntermAggregate::CreateConstructor(*transformedType, &slice); + } + + // If not, create constructors for every column recursively. + TVector subArraySizes(arraySizes.begin(), arraySizes.end() - 1); + TVector subArrayAccumulatedSizes(accumulatedArraySizes.begin(), + accumulatedArraySizes.end() - 1); + + TIntermSequence constructorArgs; + unsigned int colStride = accumulatedArraySizes.back(); + for (size_t col = 0; col < arraySizes.back(); ++col) + { + size_t colElementsOffset = elementsOffset + col * colStride; + + constructorArgs.push_back(constructReadTransformExpressionHelper( + subArraySizes, subArrayAccumulatedSizes, baseType, colElementsOffset)); + } + + return TIntermAggregate::CreateConstructor(*transformedType, &constructorArgs); + } + + TIntermTyped *mBaseExpression; + const TType &mBaseExpressionType; + TVector mArrayIndices; + + TIntermSequence mReadTransformConstructorArgs; +}; + +// Traverser that: +// +// 1. Converts |layout(row_major) matCxR M| to |layout(column_major) matRxC Mt|. +// 2. Converts |layout(row_major) S s| to |layout(column_major) St st|, where S is a struct that +// contains matrices, and St is a new struct with the transformation in 1 applied to matrix +// members (recursively). +// 3. When read from, the following transformations are applied: +// +// M -> transpose(Mt) +// M[c] -> gvecN(Mt[0][c], Mt[1][c], ..., Mt[N-1][c]) +// M[c][r] -> Mt[r][c] +// M[c].yz -> gvec2(Mt[1][c], Mt[2][c]) +// MArr -> MType[D1]..[DN](transpose(MtArr[0]...[0]), ...) +// s -> copy_St_to_S(st) +// sArr -> SType[D1]...[DN](copy_St_to_S(stArr[0]..[0]), ...) +// (matrix reads through struct are transformed similarly to M) +// +// 4. When written to, the following transformations are applied: +// +// M = exp -> Mt = transpose(exp) +// M[c] = exp -> temp = exp +// Mt[0][c] = temp[0] +// Mt[1][c] = temp[1] +// ... +// Mt[N-1][c] = temp[N-1] +// M[c][r] = exp -> Mt[r][c] = exp +// M[c].yz = exp -> temp = exp +// Mt[1][c] = temp[0] +// Mt[2][c] = temp[1] +// MArr = exp -> temp = exp +// Mt = MtType[D1]..[DN](temp([0]...[0]), ...) +// s = exp -> st = copy_S_to_St(exp) +// sArr = exp -> temp = exp +// St = StType[D1]...[DN](copy_S_to_St(temp[0]..[0]), ...) +// (matrix writes through struct are transformed similarly to M) +// +// 5. If any of the above is passed to an `inout` parameter, both transformations are applied: +// +// f(M[c]) -> temp = gvecN(Mt[0][c], Mt[1][c], ..., Mt[N-1][c]) +// f(temp) +// Mt[0][c] = temp[0] +// Mt[1][c] = temp[1] +// ... +// Mt[N-1][c] = temp[N-1] +// +// f(s) -> temp = copy_St_to_S(st) +// f(temp) +// st = copy_S_to_St(temp) +// +// If passed to an `out` parameter, the `temp` parameter is simply not initialized. +// +// 6. If the expression leading to the matrix or struct has array subscripts, temp values are +// created for them to avoid duplicating side effects. +// +class RewriteRowMajorMatricesTraverser : public TIntermTraverser +{ + public: + RewriteRowMajorMatricesTraverser(TCompiler *compiler, TSymbolTable *symbolTable) + : TIntermTraverser(true, true, true, symbolTable), + mCompiler(compiler), + mStructMapOut(&mOuterPass.structMap), + mInterfaceBlockMap(&mOuterPass.interfaceBlockMap), + mInterfaceBlockFieldConvertedIn(mOuterPass.interfaceBlockFieldConverted), + mCopyFunctionDefinitionsOut(&mOuterPass.copyFunctionDefinitions), + mOuterTraverser(nullptr), + mInnerPassRoot(nullptr), + mIsProcessingInnerPassSubtree(false) + {} + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + // No need to process declarations in inner passes. + if (mInnerPassRoot != nullptr) + { + return true; + } + + if (visit != PreVisit) + { + return true; + } + + const TIntermSequence &sequence = *(node->getSequence()); + + TIntermTyped *variable = sequence.front()->getAsTyped(); + const TType &type = variable->getType(); + + // If it's a struct declaration that has matrices, remember it. If a row-major instance + // of it is created, it will have to be converted. + if (type.isStructSpecifier() && type.isStructureContainingMatrices()) + { + const TStructure *structure = type.getStruct(); + ASSERT(structure); + + ASSERT(mOuterPass.structMap.count(structure) == 0); + + StructConversionData structData; + mOuterPass.structMap[structure] = structData; + + return false; + } + + // If it's an interface block, it may have to be converted if it contains any row-major + // fields. + if (type.isInterfaceBlock() && type.getInterfaceBlock()->containsMatrices()) + { + const TInterfaceBlock *block = type.getInterfaceBlock(); + ASSERT(block); + bool isBlockRowMajor = type.getLayoutQualifier().matrixPacking == EmpRowMajor; + + const TFieldList &fields = block->fields(); + bool anyRowMajor = isBlockRowMajor; + + for (const TField *field : fields) + { + if (DoesFieldContainRowMajorMatrix(field, isBlockRowMajor)) + { + anyRowMajor = true; + break; + } + } + + if (anyRowMajor) + { + convertInterfaceBlock(node); + } + + return false; + } + + return true; + } + + void visitSymbol(TIntermSymbol *symbol) override + { + // If in inner pass, only process if the symbol is under that root. + if (mInnerPassRoot != nullptr && !mIsProcessingInnerPassSubtree) + { + return; + } + + const TVariable *variable = &symbol->variable(); + bool needsRewrite = mInterfaceBlockMap->count(variable) != 0; + + // If it's a field of a nameless interface block, it may still need conversion. + if (!needsRewrite) + { + // Nameless interface block field symbols have the interface block pointer set, but are + // not interface blocks. + if (symbol->getType().getInterfaceBlock() && !variable->getType().isInterfaceBlock()) + { + needsRewrite = convertNamelessInterfaceBlockField(symbol); + } + } + + if (needsRewrite) + { + transformExpression(symbol); + } + } + + bool visitBinary(Visit visit, TIntermBinary *node) override + { + if (node == mInnerPassRoot) + { + // We only want to process the right-hand side of an assignment in inner passes. When + // visit is InVisit, the left-hand side is already processed, and the right-hand side is + // next. Set a flag to mark this duration. + mIsProcessingInnerPassSubtree = visit == InVisit; + } + + return true; + } + + TIntermSequence *getStructCopyFunctions() { return &mOuterPass.copyFunctionDefinitions; } + + private: + typedef angle::HashMap StructMap; + typedef angle::HashMap InterfaceBlockMap; + typedef angle::HashMap InterfaceBlockFieldConverted; + + RewriteRowMajorMatricesTraverser( + TSymbolTable *symbolTable, + RewriteRowMajorMatricesTraverser *outerTraverser, + InterfaceBlockMap *interfaceBlockMap, + const InterfaceBlockFieldConverted &interfaceBlockFieldConverted, + StructMap *structMap, + TIntermSequence *copyFunctionDefinitions, + TIntermBinary *innerPassRoot) + : TIntermTraverser(true, true, true, symbolTable), + mStructMapOut(structMap), + mInterfaceBlockMap(interfaceBlockMap), + mInterfaceBlockFieldConvertedIn(interfaceBlockFieldConverted), + mCopyFunctionDefinitionsOut(copyFunctionDefinitions), + mOuterTraverser(outerTraverser), + mInnerPassRoot(innerPassRoot), + mIsProcessingInnerPassSubtree(false) + {} + + void convertInterfaceBlock(TIntermDeclaration *node) + { + ASSERT(mInnerPassRoot == nullptr); + + const TIntermSequence &sequence = *(node->getSequence()); + + TIntermTyped *variableNode = sequence.front()->getAsTyped(); + const TType &type = variableNode->getType(); + const TInterfaceBlock *block = type.getInterfaceBlock(); + ASSERT(block); + + bool isBlockRowMajor = type.getLayoutQualifier().matrixPacking == EmpRowMajor; + + // Recreate the struct with its row-major fields converted to column-major equivalents. + TIntermSequence newDeclarations; + + TFieldList *newFields = new TFieldList; + for (const TField *field : block->fields()) + { + TField *newField = nullptr; + + if (DoesFieldContainRowMajorMatrix(field, isBlockRowMajor)) + { + newField = convertField(field, &newDeclarations); + + // Remember that this field was converted. + mOuterPass.interfaceBlockFieldConverted[field] = true; + } + else + { + newField = DuplicateField(field); + } + + newFields->push_back(newField); + } + + // Create a new interface block with these fields. + TLayoutQualifier blockLayoutQualifier = type.getLayoutQualifier(); + blockLayoutQualifier.matrixPacking = EmpColumnMajor; + + TInterfaceBlock *newInterfaceBlock = + new TInterfaceBlock(mSymbolTable, block->name(), newFields, blockLayoutQualifier, + block->symbolType(), block->extensions()); + + // Create a new declaration with the new type. Declarations are separated at this point, + // so there should be only one variable here. + ASSERT(sequence.size() == 1); + + TType *newInterfaceBlockType = + new TType(newInterfaceBlock, type.getQualifier(), blockLayoutQualifier); + + TIntermDeclaration *newDeclaration = new TIntermDeclaration; + const TVariable *variable = &variableNode->getAsSymbolNode()->variable(); + + const TType *newType = newInterfaceBlockType; + if (type.isArray()) + { + TType *newArrayType = new TType(*newType); + CopyArraySizes(&type, newArrayType); + newType = newArrayType; + } + + // If the interface block variable itself is temp, use an empty name. + bool variableIsTemp = variable->symbolType() == SymbolType::Empty; + const ImmutableString &variableName = + variableIsTemp ? kEmptyImmutableString : variable->name(); + + TVariable *newVariable = new TVariable(mSymbolTable, variableName, newType, + variable->symbolType(), variable->extensions()); + + newDeclaration->appendDeclarator(new TIntermSymbol(newVariable)); + + mOuterPass.interfaceBlockMap[variable] = newVariable; + + newDeclarations.push_back(newDeclaration); + + // Replace the interface block definition with the new one, prepending any new struct + // definitions. + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, + std::move(newDeclarations)); + } + + bool convertNamelessInterfaceBlockField(TIntermSymbol *symbol) + { + const TVariable *variable = &symbol->variable(); + const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock(); + + // Find the variable corresponding to this interface block. If the interface block + // is not rewritten, or this refers to a field that is not rewritten, there's + // nothing to do. + for (auto iter : *mInterfaceBlockMap) + { + // Skip other rewritten nameless interface block fields. + if (!iter.first->getType().isInterfaceBlock()) + { + continue; + } + + // Skip if this is not a field of this rewritten interface block. + if (iter.first->getType().getInterfaceBlock() != interfaceBlock) + { + continue; + } + + const ImmutableString symbolName = symbol->getName(); + + // Find which field it is + const TVector fields = interfaceBlock->fields(); + const size_t fieldIndex = variable->getType().getInterfaceBlockFieldIndex(); + ASSERT(fieldIndex < fields.size()); + + const TField *field = fields[fieldIndex]; + ASSERT(field->name() == symbolName); + + // If this field doesn't need a rewrite, there's nothing to do. + if (mInterfaceBlockFieldConvertedIn.count(field) == 0 || + !mInterfaceBlockFieldConvertedIn.at(field)) + { + break; + } + + // Create a new variable that references the replaced interface block. + TType *newType = new TType(variable->getType()); + newType->setInterfaceBlockField(iter.second->getType().getInterfaceBlock(), fieldIndex); + + TVariable *newVariable = new TVariable(mSymbolTable, variable->name(), newType, + variable->symbolType(), variable->extensions()); + + (*mInterfaceBlockMap)[variable] = newVariable; + + return true; + } + + return false; + } + + void convertStruct(const TStructure *structure, TIntermSequence *newDeclarations) + { + ASSERT(mInnerPassRoot == nullptr); + + ASSERT(mOuterPass.structMap.count(structure) != 0); + StructConversionData *structData = &mOuterPass.structMap[structure]; + + if (structData->convertedStruct) + { + return; + } + + TFieldList *newFields = new TFieldList; + for (const TField *field : structure->fields()) + { + newFields->push_back(convertField(field, newDeclarations)); + } + + // Create unique names for the converted structs. We can't leave them nameless and have + // a name autogenerated similar to temp variables, as nameless structs exist. A fake + // variable is created for the sole purpose of generating a temp name. + TVariable *newStructTypeName = + new TVariable(mSymbolTable, kEmptyImmutableString, + StaticType::GetBasic(), SymbolType::Empty); + + TStructure *newStruct = new TStructure(mSymbolTable, newStructTypeName->name(), newFields, + SymbolType::AngleInternal); + TType *newType = new TType(newStruct, true); + TVariable *newStructVar = + new TVariable(mSymbolTable, kEmptyImmutableString, newType, SymbolType::Empty); + + TIntermDeclaration *structDecl = new TIntermDeclaration; + structDecl->appendDeclarator(new TIntermSymbol(newStructVar)); + + newDeclarations->push_back(structDecl); + + structData->convertedStruct = newStruct; + } + + TField *convertField(const TField *field, TIntermSequence *newDeclarations) + { + ASSERT(mInnerPassRoot == nullptr); + + TField *newField = nullptr; + + const TType *fieldType = field->type(); + TType *newType = nullptr; + + if (fieldType->isStructureContainingMatrices()) + { + // If the field is a struct instance, convert the struct and replace the field + // with an instance of the new struct. + const TStructure *fieldTypeStruct = fieldType->getStruct(); + convertStruct(fieldTypeStruct, newDeclarations); + + StructConversionData &structData = mOuterPass.structMap[fieldTypeStruct]; + newType = new TType(structData.convertedStruct, false); + SetColumnMajor(newType); + CopyArraySizes(fieldType, newType); + } + else if (fieldType->isMatrix()) + { + // If the field is a matrix, transpose the matrix and replace the field with + // that, removing the matrix packing qualifier. + newType = TransposeMatrixType(fieldType); + } + + if (newType) + { + newField = new TField(newType, field->name(), field->line(), field->symbolType()); + } + else + { + newField = DuplicateField(field); + } + + return newField; + } + + void determineAccess(TIntermNode *expression, + TIntermNode *accessor, + bool *isReadOut, + bool *isWriteOut) + { + // If passing to a function, look at whether the parameter is in, out or inout. + TIntermAggregate *functionCall = accessor->getAsAggregate(); + + if (functionCall) + { + TIntermSequence *arguments = functionCall->getSequence(); + for (size_t argIndex = 0; argIndex < arguments->size(); ++argIndex) + { + if ((*arguments)[argIndex] == expression) + { + TQualifier qualifier = EvqParamIn; + + // If the aggregate is not a function call, it's a constructor, and so every + // argument is an input. + const TFunction *function = functionCall->getFunction(); + if (function) + { + const TVariable *param = function->getParam(argIndex); + qualifier = param->getType().getQualifier(); + } + + *isReadOut = qualifier != EvqParamOut; + *isWriteOut = qualifier == EvqParamOut || qualifier == EvqParamInOut; + break; + } + } + return; + } + + TIntermBinary *assignment = accessor->getAsBinaryNode(); + if (assignment && IsAssignment(assignment->getOp())) + { + // If expression is on the right of assignment, it's being read from. + *isReadOut = assignment->getRight() == expression; + // If it's on the left of assignment, it's being written to. + *isWriteOut = assignment->getLeft() == expression; + return; + } + + // Any other usage is a read. + *isReadOut = true; + *isWriteOut = false; + } + + void transformExpression(TIntermSymbol *symbol) + { + // Walk up the parent chain while the nodes are EOpIndex* (whether array indexing or struct + // field selection) or swizzle and construct the replacement expression. This traversal can + // lead to one of the following possibilities: + // + // - a.b[N].etc.s (struct, or struct array): copy function should be declared and used, + // - a.b[N].etc.M (matrix or matrix array): transpose() should be used, + // - a.b[N].etc.M[c] (a column): each element in column needs to be handled separately, + // - a.b[N].etc.M[c].yz (multiple elements): similar to whole column, but a subset of + // elements, + // - a.b[N].etc.M[c][r] (an element): single element to handle. + // - a.b[N].etc.x (not struct or matrix): not modified + // + // primaryIndex will contain c, if any. secondaryIndices will contain {0, ..., R-1} + // (if no [r] or swizzle), {r} (if [r]), or {1, 2} (corresponding to .yz) if any. + // + // In all cases, the base symbol is replaced. |baseExpression| will contain everything up + // to (and not including) the last index/swizzle operations, i.e. a.b[N].etc.s/M/x. Any + // non constant array subscript is assigned to a temp variable to avoid duplicating side + // effects. + // + // --- + // + // NOTE that due to the use of insertStatementsInParentBlock, cases like this will be + // mistranslated, and this bug is likely present in most transformations that use this + // feature: + // + // if (x == 1 && a.b[x = 2].etc.M = value) + // + // which will translate to: + // + // temp = (x = 2) + // if (x == 1 && a.b[temp].etc.M = transpose(value)) + // + // See http://anglebug.com/3829. + // + TIntermTyped *baseExpression = + new TIntermSymbol(mInterfaceBlockMap->at(&symbol->variable())); + const TStructure *structure = nullptr; + + TIntermNode *primaryIndex = nullptr; + TIntermSequence secondaryIndices; + + // In some cases, it is necessary to prepend or append statements. Those are captured in + // |prependStatements| and |appendStatements|. + TIntermSequence prependStatements; + TIntermSequence appendStatements; + + // If the expression is neither a struct or matrix, no modification is necessary. + // If it's a struct that doesn't have matrices, again there's no transformation necessary. + // If it's an interface block matrix field that didn't need to be transposed, no + // transpformation is necessary. + // + // In all these cases, |baseExpression| contains all of the original expression. + // + // If the starting symbol itself is a field of a nameless interface block, it needs + // conversion if we reach here. + bool requiresTransformation = !symbol->getType().isInterfaceBlock(); + + uint32_t accessorIndex = 0; + TIntermTyped *previousAncestor = symbol; + while (IsIndexNode(getAncestorNode(accessorIndex), previousAncestor)) + { + TIntermTyped *ancestor = getAncestorNode(accessorIndex)->getAsTyped(); + ASSERT(ancestor); + + const TType &previousAncestorType = previousAncestor->getType(); + + TIntermSequence indices; + TOperator op = GetIndex(mSymbolTable, ancestor, &indices, &prependStatements); + + bool opIsIndex = op == EOpIndexDirect || op == EOpIndexIndirect; + bool isArrayIndex = opIsIndex && previousAncestorType.isArray(); + bool isMatrixIndex = opIsIndex && previousAncestorType.isMatrix(); + + // If it's a direct index in a matrix, it's the primary index. + bool isMatrixPrimarySubscript = isMatrixIndex && !isArrayIndex; + ASSERT(!isMatrixPrimarySubscript || + (primaryIndex == nullptr && secondaryIndices.empty())); + // If primary index is seen and the ancestor is still an index, it must be a direct + // index as the secondary one. Note that if primaryIndex is set, there can only ever be + // one more parent of interest, and that's subscripting the second dimension. + bool isMatrixSecondarySubscript = primaryIndex != nullptr; + ASSERT(!isMatrixSecondarySubscript || (opIsIndex && !isArrayIndex)); + + if (requiresTransformation && isMatrixPrimarySubscript) + { + ASSERT(indices.size() == 1); + primaryIndex = indices.front(); + + // Default the secondary indices to include every row. If there's a secondary + // subscript provided, it will override this. + const uint8_t rows = previousAncestorType.getRows(); + for (uint8_t r = 0; r < rows; ++r) + { + secondaryIndices.push_back(CreateIndexNode(r)); + } + } + else if (isMatrixSecondarySubscript) + { + ASSERT(requiresTransformation); + + secondaryIndices = indices; + + // Indices after this point are not interesting. There can't actually be any other + // index nodes other than desktop GLSL's swizzles on scalars, like M[1][2].yyy. + ++accessorIndex; + break; + } + else + { + // Replicate the expression otherwise. + baseExpression = + ReplicateIndexNode(mSymbolTable, ancestor, baseExpression, &indices); + + const TType &ancestorType = ancestor->getType(); + structure = ancestorType.getStruct(); + + requiresTransformation = + requiresTransformation || + IsConvertedField(ancestor, mInterfaceBlockFieldConvertedIn); + + // If we reach a point where the expression is neither a matrix-containing struct + // nor a matrix, there's no transformation required. This can happen if we decend + // through a struct marked with row-major but arrive at a member that doesn't + // include a matrix. + if (!ancestorType.isMatrix() && !ancestorType.isStructureContainingMatrices()) + { + requiresTransformation = false; + } + } + + previousAncestor = ancestor; + ++accessorIndex; + } + + TIntermNode *originalExpression = + accessorIndex == 0 ? symbol : getAncestorNode(accessorIndex - 1); + TIntermNode *accessor = getAncestorNode(accessorIndex); + + // if accessor is EOpArrayLength, we don't need to perform any transformations either. + // Note that this only applies to unsized arrays, as the RemoveArrayLengthMethod() + // transformation would have removed this operation otherwise. + TIntermUnary *accessorAsUnary = accessor->getAsUnaryNode(); + if (requiresTransformation && accessorAsUnary && accessorAsUnary->getOp() == EOpArrayLength) + { + ASSERT(accessorAsUnary->getOperand() == originalExpression); + ASSERT(accessorAsUnary->getOperand()->getType().isUnsizedArray()); + + requiresTransformation = false; + + // We need to replace the whole expression including the EOpArrayLength, to avoid + // confusing the replacement code as the original and new expressions don't have the + // same type (one is the transpose of the other). This doesn't affect the .length() + // operation, so this replacement is ok, though it's not worth special-casing this in + // the node replacement algorithm. + // + // Note: the |if (!requiresTransformation)| immediately below will be entered after + // this. + originalExpression = accessor; + accessor = getAncestorNode(accessorIndex + 1); + baseExpression = new TIntermUnary(EOpArrayLength, baseExpression, nullptr); + } + + if (!requiresTransformation) + { + ASSERT(primaryIndex == nullptr); + queueReplacementWithParent(accessor, originalExpression, baseExpression, + OriginalNode::IS_DROPPED); + + RewriteRowMajorMatricesTraverser *traverser = mOuterTraverser ? mOuterTraverser : this; + traverser->insertStatementsInParentBlock(prependStatements, appendStatements); + return; + } + + ASSERT(structure == nullptr || primaryIndex == nullptr); + ASSERT(structure != nullptr || baseExpression->getType().isMatrix()); + + // At the end, we can determine if the expression is being read from or written to (or both, + // if sent as an inout parameter to a function). For the sake of the transformation, the + // left-hand side of operations like += can be treated as "written to", without necessarily + // "read from". + bool isRead = false; + bool isWrite = false; + + determineAccess(originalExpression, accessor, &isRead, &isWrite); + + ASSERT(isRead || isWrite); + + TIntermTyped *readExpression = nullptr; + if (isRead) + { + readExpression = transformReadExpression( + baseExpression, primaryIndex, &secondaryIndices, structure, &prependStatements); + + // If both read from and written to (i.e. passed to inout parameter), store the + // expression in a temp variable and pass that to the function. + if (isWrite) + { + readExpression = + CopyToTempVariable(mSymbolTable, readExpression, &prependStatements); + } + + // Replace the original expression with the transformed one. Read transformations + // always generate a single expression that can be used in place of the original (as + // oppposed to write transformations that can generate multiple statements). + queueReplacementWithParent(accessor, originalExpression, readExpression, + OriginalNode::IS_DROPPED); + } + + TIntermSequence postTransformPrependStatements; + TIntermSequence *writeStatements = &appendStatements; + TOperator assignmentOperator = EOpAssign; + + if (isWrite) + { + TIntermTyped *valueExpression = readExpression; + + if (!valueExpression) + { + // If there's already a read expression, this was an inout parameter and + // |valueExpression| will contain the temp variable that was passed to the function + // instead. + // + // If not, then the modification is either through being passed as an out parameter + // to a function, or an assignment. In the former case, create a temp variable to + // be passed to the function. In the latter case, create a temp variable that holds + // the right hand side expression. + // + // In either case, use that temp value as the value to assign to |baseExpression|. + + TVariable *temp = + CreateTempVariable(mSymbolTable, &originalExpression->getAsTyped()->getType()); + TIntermDeclaration *tempDecl = nullptr; + + valueExpression = new TIntermSymbol(temp); + + TIntermBinary *assignment = accessor->getAsBinaryNode(); + if (assignment) + { + assignmentOperator = assignment->getOp(); + ASSERT(IsAssignment(assignmentOperator)); + + // We are converting the assignment to the left-hand side of an expression in + // the form M=exp. A subexpression of exp itself could require a + // transformation. This complicates things as there would be two replacements: + // + // - Replace M=exp with temp (because the return value of the assignment could + // be used) + // - Replace exp with exp2, where parent is M=exp + // + // The second replacement however is ineffective as the whole of M=exp is + // already transformed. What's worse, M=exp is transformed without taking exp's + // transformations into account. To address this issue, this same traverser is + // called on the right-hand side expression, with a special flag such that it + // only processes that expression. + // + RewriteRowMajorMatricesTraverser *outerTraverser = + mOuterTraverser ? mOuterTraverser : this; + RewriteRowMajorMatricesTraverser rhsTraverser( + mSymbolTable, outerTraverser, mInterfaceBlockMap, + mInterfaceBlockFieldConvertedIn, mStructMapOut, mCopyFunctionDefinitionsOut, + assignment); + getRootNode()->traverse(&rhsTraverser); + bool valid = rhsTraverser.updateTree(mCompiler, getRootNode()); + ASSERT(valid); + + tempDecl = CreateTempInitDeclarationNode(temp, assignment->getRight()); + + // Replace the whole assignment expression with the right-hand side as a read + // expression, in case the result of the assignment is used. For example, this + // transforms: + // + // if ((M += exp) == X) + // { + // // use M + // } + // + // to: + // + // temp = exp; + // M += transform(temp); + // if (transform(M) == X) + // { + // // use M + // } + // + // Note that in this case the assignment to M must be prepended in the parent + // block. In contrast, when sent to a function, the assignment to M should be + // done after the current function call is done. + // + // If the read from M itself (to replace assigmnet) needs to generate extra + // statements, they should be appended after the statements that write to M. + // These statements are stored in postTransformPrependStatements and appended to + // prependStatements in the end. + // + writeStatements = &prependStatements; + + TIntermTyped *assignmentResultExpression = transformReadExpression( + baseExpression->deepCopy(), primaryIndex, &secondaryIndices, structure, + &postTransformPrependStatements); + + // Replace the whole assignment, instead of just the right hand side. + TIntermNode *accessorParent = getAncestorNode(accessorIndex + 1); + queueReplacementWithParent(accessorParent, accessor, assignmentResultExpression, + OriginalNode::IS_DROPPED); + } + else + { + tempDecl = CreateTempDeclarationNode(temp); + + // Replace the write expression (a function call argument) with the temp + // variable. + queueReplacementWithParent(accessor, originalExpression, valueExpression, + OriginalNode::IS_DROPPED); + } + prependStatements.push_back(tempDecl); + } + + if (isRead) + { + baseExpression = baseExpression->deepCopy(); + } + transformWriteExpression(baseExpression, primaryIndex, &secondaryIndices, structure, + valueExpression, assignmentOperator, writeStatements); + } + + prependStatements.insert(prependStatements.end(), postTransformPrependStatements.begin(), + postTransformPrependStatements.end()); + + RewriteRowMajorMatricesTraverser *traverser = mOuterTraverser ? mOuterTraverser : this; + traverser->insertStatementsInParentBlock(prependStatements, appendStatements); + } + + TIntermTyped *transformReadExpression(TIntermTyped *baseExpression, + TIntermNode *primaryIndex, + TIntermSequence *secondaryIndices, + const TStructure *structure, + TIntermSequence *prependStatements) + { + const TType &baseExpressionType = baseExpression->getType(); + + if (structure) + { + ASSERT(primaryIndex == nullptr && secondaryIndices->empty()); + ASSERT(mStructMapOut->count(structure) != 0); + ASSERT((*mStructMapOut)[structure].convertedStruct != nullptr); + + // Declare copy-from-converted-to-original-struct function (if not already). + declareStructCopyToOriginal(structure); + + const TFunction *copyToOriginal = (*mStructMapOut)[structure].copyToOriginal; + + if (baseExpressionType.isArray()) + { + // If base expression is an array, transform every element. + TransformArrayHelper transformHelper(baseExpression); + + TIntermTyped *element = nullptr; + while ((element = transformHelper.getNextElement(nullptr, nullptr)) != nullptr) + { + TIntermTyped *transformedElement = + CreateStructCopyCall(copyToOriginal, element); + transformHelper.accumulateForRead(mSymbolTable, transformedElement, + prependStatements); + } + return transformHelper.constructReadTransformExpression(); + } + else + { + // If not reading an array, the result is simply a call to this function with the + // base expression. + return CreateStructCopyCall(copyToOriginal, baseExpression); + } + } + + // If not indexed, the result is transpose(exp) + if (primaryIndex == nullptr) + { + ASSERT(secondaryIndices->empty()); + + if (baseExpressionType.isArray()) + { + // If array, transpose every element. + TransformArrayHelper transformHelper(baseExpression); + + TIntermTyped *element = nullptr; + while ((element = transformHelper.getNextElement(nullptr, nullptr)) != nullptr) + { + TIntermTyped *transformedElement = CreateTransposeCall(mSymbolTable, element); + transformHelper.accumulateForRead(mSymbolTable, transformedElement, + prependStatements); + } + return transformHelper.constructReadTransformExpression(); + } + else + { + return CreateTransposeCall(mSymbolTable, baseExpression); + } + } + + // If indexed the result is a vector (or just one element) where the primary and secondary + // indices are swapped. + ASSERT(!secondaryIndices->empty()); + + TOperator primaryIndexOp = GetIndexOp(primaryIndex); + TIntermTyped *primaryIndexAsTyped = primaryIndex->getAsTyped(); + + TIntermSequence transposedColumn; + for (TIntermNode *secondaryIndex : *secondaryIndices) + { + TOperator secondaryIndexOp = GetIndexOp(secondaryIndex); + TIntermTyped *secondaryIndexAsTyped = secondaryIndex->getAsTyped(); + + TIntermBinary *colIndexed = new TIntermBinary( + secondaryIndexOp, baseExpression->deepCopy(), secondaryIndexAsTyped->deepCopy()); + TIntermBinary *colRowIndexed = + new TIntermBinary(primaryIndexOp, colIndexed, primaryIndexAsTyped->deepCopy()); + + transposedColumn.push_back(colRowIndexed); + } + + if (secondaryIndices->size() == 1) + { + // If only one element, return that directly. + return transposedColumn.front()->getAsTyped(); + } + + // Otherwise create a constructor with the appropriate dimension. + TType *vecType = new TType(baseExpressionType.getBasicType(), secondaryIndices->size()); + return TIntermAggregate::CreateConstructor(*vecType, &transposedColumn); + } + + void transformWriteExpression(TIntermTyped *baseExpression, + TIntermNode *primaryIndex, + TIntermSequence *secondaryIndices, + const TStructure *structure, + TIntermTyped *valueExpression, + TOperator assignmentOperator, + TIntermSequence *writeStatements) + { + const TType &baseExpressionType = baseExpression->getType(); + + if (structure) + { + ASSERT(primaryIndex == nullptr && secondaryIndices->empty()); + ASSERT(mStructMapOut->count(structure) != 0); + ASSERT((*mStructMapOut)[structure].convertedStruct != nullptr); + + // Declare copy-to-converted-from-original-struct function (if not already). + declareStructCopyFromOriginal(structure); + + // The result is call to this function with the value expression assigned to base + // expression. + const TFunction *copyFromOriginal = (*mStructMapOut)[structure].copyFromOriginal; + + if (baseExpressionType.isArray()) + { + // If array, assign every element. + TransformArrayHelper transformHelper(baseExpression); + + TIntermTyped *element = nullptr; + TIntermTyped *valueElement = nullptr; + while ((element = transformHelper.getNextElement(valueExpression, &valueElement)) != + nullptr) + { + TIntermTyped *functionCall = + CreateStructCopyCall(copyFromOriginal, valueElement); + writeStatements->push_back(new TIntermBinary(EOpAssign, element, functionCall)); + } + } + else + { + TIntermTyped *functionCall = + CreateStructCopyCall(copyFromOriginal, valueExpression->deepCopy()); + writeStatements->push_back( + new TIntermBinary(EOpAssign, baseExpression, functionCall)); + } + + return; + } + + // If not indexed, the result is transpose(exp) + if (primaryIndex == nullptr) + { + ASSERT(secondaryIndices->empty()); + + if (baseExpressionType.isArray()) + { + // If array, assign every element. + TransformArrayHelper transformHelper(baseExpression); + + TIntermTyped *element = nullptr; + TIntermTyped *valueElement = nullptr; + while ((element = transformHelper.getNextElement(valueExpression, &valueElement)) != + nullptr) + { + TIntermTyped *valueTransposed = CreateTransposeCall(mSymbolTable, valueElement); + writeStatements->push_back( + new TIntermBinary(EOpAssign, element, valueTransposed)); + } + } + else + { + TIntermTyped *valueTransposed = + CreateTransposeCall(mSymbolTable, valueExpression->deepCopy()); + writeStatements->push_back( + new TIntermBinary(assignmentOperator, baseExpression, valueTransposed)); + } + + return; + } + + // If indexed, create one assignment per secondary index. If the right-hand side is a + // scalar, it's used with every assignment. If it's a vector, the assignment is + // per-component. The right-hand side cannot be a matrix as that would imply left-hand + // side being a matrix too, which is covered above where |primaryIndex == nullptr|. + ASSERT(!secondaryIndices->empty()); + + bool isValueExpressionScalar = valueExpression->getType().getNominalSize() == 1; + ASSERT(isValueExpressionScalar || valueExpression->getType().getNominalSize() == + static_cast(secondaryIndices->size())); + + TOperator primaryIndexOp = GetIndexOp(primaryIndex); + TIntermTyped *primaryIndexAsTyped = primaryIndex->getAsTyped(); + + for (TIntermNode *secondaryIndex : *secondaryIndices) + { + TOperator secondaryIndexOp = GetIndexOp(secondaryIndex); + TIntermTyped *secondaryIndexAsTyped = secondaryIndex->getAsTyped(); + + TIntermBinary *colIndexed = new TIntermBinary( + secondaryIndexOp, baseExpression->deepCopy(), secondaryIndexAsTyped->deepCopy()); + TIntermBinary *colRowIndexed = + new TIntermBinary(primaryIndexOp, colIndexed, primaryIndexAsTyped->deepCopy()); + + TIntermTyped *valueExpressionIndexed = valueExpression->deepCopy(); + if (!isValueExpressionScalar) + { + valueExpressionIndexed = new TIntermBinary(secondaryIndexOp, valueExpressionIndexed, + secondaryIndexAsTyped->deepCopy()); + } + + writeStatements->push_back( + new TIntermBinary(assignmentOperator, colRowIndexed, valueExpressionIndexed)); + } + } + + const TFunction *getCopyStructFieldFunction(const TType *fromFieldType, + const TType *toFieldType, + bool isCopyToOriginal) + { + ASSERT(fromFieldType->getStruct()); + ASSERT(toFieldType->getStruct()); + + // If copying from or to the original struct, the "to" field struct could require + // conversion to or from the "from" field struct. |isCopyToOriginal| tells us if we + // should expect to find toField or fromField in mStructMapOut, if true or false + // respectively. + const TFunction *fieldCopyFunction = nullptr; + if (isCopyToOriginal) + { + const TStructure *toFieldStruct = toFieldType->getStruct(); + + auto iter = mStructMapOut->find(toFieldStruct); + if (iter != mStructMapOut->end()) + { + declareStructCopyToOriginal(toFieldStruct); + fieldCopyFunction = iter->second.copyToOriginal; + } + } + else + { + const TStructure *fromFieldStruct = fromFieldType->getStruct(); + + auto iter = mStructMapOut->find(fromFieldStruct); + if (iter != mStructMapOut->end()) + { + declareStructCopyFromOriginal(fromFieldStruct); + fieldCopyFunction = iter->second.copyFromOriginal; + } + } + + return fieldCopyFunction; + } + + void addFieldCopy(TIntermBlock *body, + TIntermTyped *to, + TIntermTyped *from, + bool isCopyToOriginal) + { + const TType &fromType = from->getType(); + const TType &toType = to->getType(); + + TIntermTyped *rhs = from; + + if (fromType.getStruct()) + { + const TFunction *fieldCopyFunction = + getCopyStructFieldFunction(&fromType, &toType, isCopyToOriginal); + + if (fieldCopyFunction) + { + rhs = CreateStructCopyCall(fieldCopyFunction, from); + } + } + else if (fromType.isMatrix()) + { + rhs = CreateTransposeCall(mSymbolTable, from); + } + + body->appendStatement(new TIntermBinary(EOpAssign, to, rhs)); + } + + TFunction *declareStructCopy(const TStructure *from, + const TStructure *to, + bool isCopyToOriginal) + { + TType *fromType = new TType(from, true); + TType *toType = new TType(to, true); + + // Create the parameter and return value variables. + TVariable *fromVar = new TVariable(mSymbolTable, ImmutableString("from"), fromType, + SymbolType::AngleInternal); + TVariable *toVar = + new TVariable(mSymbolTable, ImmutableString("to"), toType, SymbolType::AngleInternal); + + TIntermSymbol *fromSymbol = new TIntermSymbol(fromVar); + TIntermSymbol *toSymbol = new TIntermSymbol(toVar); + + // Create the function body as statements are generated. + TIntermBlock *body = new TIntermBlock; + + // Declare the result variable. + TIntermDeclaration *toDecl = new TIntermDeclaration(); + toDecl->appendDeclarator(toSymbol); + body->appendStatement(toDecl); + + // Iterate over fields of the struct and copy one by one, transposing the matrices. If a + // struct is encountered that requires a transformation, this function is recursively + // called. As a result, it is important that the copy functions are placed in the code in + // order. + const TFieldList &fromFields = from->fields(); + const TFieldList &toFields = to->fields(); + ASSERT(fromFields.size() == toFields.size()); + + for (size_t fieldIndex = 0; fieldIndex < fromFields.size(); ++fieldIndex) + { + TIntermTyped *fieldIndexNode = CreateIndexNode(static_cast(fieldIndex)); + + TIntermTyped *fromField = + new TIntermBinary(EOpIndexDirectStruct, fromSymbol->deepCopy(), fieldIndexNode); + TIntermTyped *toField = new TIntermBinary(EOpIndexDirectStruct, toSymbol->deepCopy(), + fieldIndexNode->deepCopy()); + + const TType *fromFieldType = fromFields[fieldIndex]->type(); + bool isStructOrMatrix = fromFieldType->getStruct() || fromFieldType->isMatrix(); + + if (fromFieldType->isArray() && isStructOrMatrix) + { + // If struct or matrix array, we need to copy element by element. + TransformArrayHelper transformHelper(toField); + + TIntermTyped *toElement = nullptr; + TIntermTyped *fromElement = nullptr; + while ((toElement = transformHelper.getNextElement(fromField, &fromElement)) != + nullptr) + { + addFieldCopy(body, toElement, fromElement, isCopyToOriginal); + } + } + else + { + addFieldCopy(body, toField, fromField, isCopyToOriginal); + } + } + + // Add return statement. + body->appendStatement(new TIntermBranch(EOpReturn, toSymbol->deepCopy())); + + // Declare the function + TFunction *copyFunction = new TFunction(mSymbolTable, kEmptyImmutableString, + SymbolType::AngleInternal, toType, true); + copyFunction->addParameter(fromVar); + + TIntermFunctionDefinition *functionDef = + CreateInternalFunctionDefinitionNode(*copyFunction, body); + mCopyFunctionDefinitionsOut->push_back(functionDef); + + return copyFunction; + } + + void declareStructCopyFromOriginal(const TStructure *structure) + { + StructConversionData *structData = &(*mStructMapOut)[structure]; + if (structData->copyFromOriginal) + { + return; + } + + structData->copyFromOriginal = + declareStructCopy(structure, structData->convertedStruct, false); + } + + void declareStructCopyToOriginal(const TStructure *structure) + { + StructConversionData *structData = &(*mStructMapOut)[structure]; + if (structData->copyToOriginal) + { + return; + } + + structData->copyToOriginal = + declareStructCopy(structData->convertedStruct, structure, true); + } + + TCompiler *mCompiler; + + // This traverser can call itself to transform a subexpression before moving on. However, it + // needs to accumulate conversion functions in inner passes. The fields below marked with Out + // or In are inherited from the outer pass (for inner passes), or point to storage fields in + // mOuterPass (for the outer pass). The latter should not be used by the inner passes as they + // would be empty, so they are placed inside a struct to make them explicit. + struct + { + StructMap structMap; + InterfaceBlockMap interfaceBlockMap; + InterfaceBlockFieldConverted interfaceBlockFieldConverted; + TIntermSequence copyFunctionDefinitions; + } mOuterPass; + + // A map from structures with matrices to their converted version. + StructMap *mStructMapOut; + // A map from interface block instances with row-major matrices to their converted variable. If + // an interface block is nameless, its fields are placed in this map instead. When a variable + // in this map is encountered, it signals the start of an expression that my need conversion, + // which is either "interfaceBlock.field..." or "field..." if nameless. + InterfaceBlockMap *mInterfaceBlockMap; + // A map from interface block fields to whether they need to be converted. If a field was + // already column-major, it shouldn't be transposed. + const InterfaceBlockFieldConverted &mInterfaceBlockFieldConvertedIn; + + TIntermSequence *mCopyFunctionDefinitionsOut; + + // If set, it's an inner pass and this will point to the outer pass traverser. All statement + // insertions are stored in the outer traverser and applied at once in the end. This prevents + // the inner passes from adding statements which invalidates the outer traverser's statement + // position tracking. + RewriteRowMajorMatricesTraverser *mOuterTraverser; + + // If set, it's an inner pass that should only process the right-hand side of this particular + // node. + TIntermBinary *mInnerPassRoot; + bool mIsProcessingInnerPassSubtree; +}; + +} // anonymous namespace + +bool RewriteRowMajorMatrices(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable) +{ + RewriteRowMajorMatricesTraverser traverser(compiler, symbolTable); + root->traverse(&traverser); + if (!traverser.updateTree(compiler, root)) + { + return false; + } + + size_t firstFunctionIndex = FindFirstFunctionDefinitionIndex(root); + root->insertChildNodes(firstFunctionIndex, *traverser.getStructCopyFunctions()); + + return compiler->validateAST(root); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.h new file mode 100644 index 0000000000..2f3577248e --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.h @@ -0,0 +1,37 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteRowMajorMatrices: Change row-major matrices to column-major in uniform and storage +// buffers. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_APPLE_REWRITEROWMAJORMATRICES_H_ +#define COMPILER_TRANSLATOR_TREEOPS_APPLE_REWRITEROWMAJORMATRICES_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +#if (defined(ANGLE_ENABLE_GLSL) || defined(ANGLE_ENABLE_METAL)) && \ + defined(ANGLE_ENABLE_APPLE_WORKAROUNDS) +[[nodiscard]] bool RewriteRowMajorMatrices(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); +#else +[[nodiscard]] ANGLE_INLINE bool RewriteRowMajorMatrices(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable) +{ + UNREACHABLE(); + return false; +} +#endif + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_APPLE_REWRITEROWMAJORMATRICES_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteUnaryMinusOperatorFloat.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteUnaryMinusOperatorFloat.cpp new file mode 100644 index 0000000000..4aa8a28203 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteUnaryMinusOperatorFloat.cpp @@ -0,0 +1,97 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/tree_ops/apple/RewriteUnaryMinusOperatorFloat.h" + +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class Traverser : public TIntermTraverser +{ + public: + [[nodiscard]] static bool Apply(TCompiler *compiler, TIntermNode *root); + + private: + Traverser(); + bool visitUnary(Visit visit, TIntermUnary *node) override; + void nextIteration(); + + bool mFound = false; +}; + +// static +bool Traverser::Apply(TCompiler *compiler, TIntermNode *root) +{ + Traverser traverser; + do + { + traverser.nextIteration(); + root->traverse(&traverser); + if (traverser.mFound) + { + if (!traverser.updateTree(compiler, root)) + { + return false; + } + } + } while (traverser.mFound); + + return true; +} + +Traverser::Traverser() : TIntermTraverser(true, false, false) {} + +void Traverser::nextIteration() +{ + mFound = false; +} + +bool Traverser::visitUnary(Visit visit, TIntermUnary *node) +{ + if (mFound) + { + return false; + } + + // Detect if the current operator is unary minus operator. + if (node->getOp() != EOpNegative) + { + return true; + } + + // Detect if the current operand is a float variable. + TIntermTyped *fValue = node->getOperand(); + if (!fValue->getType().isScalarFloat()) + { + return true; + } + + // 0.0 - float + TIntermTyped *zero = CreateZeroNode(fValue->getType()); + zero->setLine(fValue->getLine()); + TIntermBinary *sub = new TIntermBinary(EOpSub, zero, fValue); + sub->setLine(fValue->getLine()); + + queueReplacement(sub, OriginalNode::IS_DROPPED); + + mFound = true; + return false; +} + +} // anonymous namespace + +bool RewriteUnaryMinusOperatorFloat(TCompiler *compiler, TIntermNode *root) +{ + return Traverser::Apply(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteUnaryMinusOperatorFloat.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteUnaryMinusOperatorFloat.h new file mode 100644 index 0000000000..30c4d25d01 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/RewriteUnaryMinusOperatorFloat.h @@ -0,0 +1,31 @@ +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Rewrite "-float" to "0.0 - float" to work around unary minus operator on float issue on Intel Mac +// OSX 10.11. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_APPLE_REWRITEUNARYMINUSOPERATORFLOAT_H_ +#define COMPILER_TRANSLATOR_TREEOPS_APPLE_REWRITEUNARYMINUSOPERATORFLOAT_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermNode; + +#if defined(ANGLE_ENABLE_GLSL) && defined(ANGLE_ENABLE_APPLE_WORKAROUNDS) +[[nodiscard]] bool RewriteUnaryMinusOperatorFloat(TCompiler *compiler, TIntermNode *root); +#else +[[nodiscard]] ANGLE_INLINE bool RewriteUnaryMinusOperatorFloat(TCompiler *compiler, + TIntermNode *root) +{ + UNREACHABLE(); + return false; +} +#endif + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_APPLE_REWRITEUNARYMINUSOPERATORFLOAT_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.cpp new file mode 100644 index 0000000000..55e2f8b971 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.cpp @@ -0,0 +1,74 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.h" + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +// "x || y" is equivalent to "x ? true : y". +TIntermTernary *UnfoldOR(TIntermTyped *x, TIntermTyped *y) +{ + return new TIntermTernary(x, CreateBoolNode(true), y); +} + +// "x && y" is equivalent to "x ? y : false". +TIntermTernary *UnfoldAND(TIntermTyped *x, TIntermTyped *y) +{ + return new TIntermTernary(x, y, CreateBoolNode(false)); +} + +// This traverser identifies all the short circuit binary nodes that need to +// be replaced, and creates the corresponding replacement nodes. However, +// the actual replacements happen after the traverse through updateTree(). + +class UnfoldShortCircuitASTTraverser : public TIntermTraverser +{ + public: + UnfoldShortCircuitASTTraverser() : TIntermTraverser(true, false, false) {} + + bool visitBinary(Visit visit, TIntermBinary *) override; +}; + +bool UnfoldShortCircuitASTTraverser::visitBinary(Visit visit, TIntermBinary *node) +{ + TIntermTernary *replacement = nullptr; + + switch (node->getOp()) + { + case EOpLogicalOr: + replacement = UnfoldOR(node->getLeft(), node->getRight()); + break; + case EOpLogicalAnd: + replacement = UnfoldAND(node->getLeft(), node->getRight()); + break; + default: + break; + } + if (replacement) + { + queueReplacement(replacement, OriginalNode::IS_DROPPED); + } + return true; +} + +} // anonymous namespace + +bool UnfoldShortCircuitAST(TCompiler *compiler, TIntermBlock *root) +{ + UnfoldShortCircuitASTTraverser traverser; + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.h new file mode 100644 index 0000000000..648c7190a9 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.h @@ -0,0 +1,33 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// UnfoldShortCircuitAST is an AST traverser to replace short-circuiting +// operations with ternary operations. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_APPLE_UNFOLDSHORTCIRCUITAST_H_ +#define COMPILER_TRANSLATOR_TREEOPS_APPLE_UNFOLDSHORTCIRCUITAST_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; + +#if defined(ANGLE_ENABLE_GLSL) && defined(ANGLE_ENABLE_APPLE_WORKAROUNDS) +[[nodiscard]] bool UnfoldShortCircuitAST(TCompiler *compiler, TIntermBlock *root); +#else +[[nodiscard]] ANGLE_INLINE bool UnfoldShortCircuitAST(TCompiler *compiler, TIntermBlock *root) +{ + UNREACHABLE(); + return false; +} +#endif + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_APPLE_UNFOLDSHORTCIRCUITAST_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AddDefaultReturnStatements.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AddDefaultReturnStatements.cpp new file mode 100644 index 0000000000..8790c4f5f2 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AddDefaultReturnStatements.cpp @@ -0,0 +1,61 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// AddDefaultReturnStatements.cpp: Add default return statements to functions that do not end in a +// return. +// + +#include "compiler/translator/tree_ops/d3d/AddDefaultReturnStatements.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +bool NeedsReturnStatement(TIntermFunctionDefinition *node, TType *returnType) +{ + *returnType = node->getFunctionPrototype()->getType(); + if (returnType->getBasicType() == EbtVoid) + { + return false; + } + + TIntermBlock *bodyNode = node->getBody(); + TIntermBranch *returnNode = bodyNode->getSequence()->back()->getAsBranchNode(); + if (returnNode != nullptr && returnNode->getFlowOp() == EOpReturn) + { + return false; + } + + return true; +} + +} // anonymous namespace + +bool AddDefaultReturnStatements(TCompiler *compiler, TIntermBlock *root) +{ + TType returnType; + for (TIntermNode *node : *root->getSequence()) + { + TIntermFunctionDefinition *definition = node->getAsFunctionDefinition(); + if (definition != nullptr && NeedsReturnStatement(definition, &returnType)) + { + TIntermBranch *branch = new TIntermBranch(EOpReturn, CreateZeroNode(returnType)); + + TIntermBlock *bodyNode = definition->getBody(); + bodyNode->getSequence()->push_back(branch); + } + } + + return compiler->validateAST(root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AddDefaultReturnStatements.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AddDefaultReturnStatements.h new file mode 100644 index 0000000000..52b601514c --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AddDefaultReturnStatements.h @@ -0,0 +1,24 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// AddDefaultReturnStatements.h: Add default return statements to functions that do not end in a +// return. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_ADDDEFAULTRETURNSTATEMENTS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_ADDDEFAULTRETURNSTATEMENTS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; + +[[nodiscard]] bool AddDefaultReturnStatements(TCompiler *compiler, TIntermBlock *root); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_ADDDEFAULTRETURNSTATEMENTS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignArraysInSSBOs.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignArraysInSSBOs.cpp new file mode 100644 index 0000000000..d9a0c9bebc --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignArraysInSSBOs.cpp @@ -0,0 +1,82 @@ +// +// Copyright 2022 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/tree_ops/d3d/AggregateAssignArraysInSSBOs.h" + +#include "compiler/translator/StaticType.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +class AggregateAssignArraysInSSBOsTraverser : public TIntermTraverser +{ + public: + AggregateAssignArraysInSSBOsTraverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, false, false, symbolTable) + {} + + protected: + bool visitBinary(Visit visit, TIntermBinary *node) override + { + // Replace all aggregate assignments to arrays in SSBOs with element-by-element assignments. + // TODO(anglebug.com/7363): this implementation only works for the simple case (assignment + // statement), not more complex cases such as assignment-as-expression or functions with + // side effects in the RHS. + + if (node->getOp() != EOpAssign) + { + return true; + } + else if (!node->getLeft()->getType().isArray()) + { + return true; + } + else if (!IsInShaderStorageBlock(node->getLeft())) + { + return true; + } + const TType *mediumpIndexType = StaticType::Get(); + auto *indexVariable = CreateTempVariable(mSymbolTable, mediumpIndexType); + auto *indexInit = + CreateTempInitDeclarationNode(indexVariable, CreateZeroNode(indexVariable->getType())); + auto *arraySizeNode = CreateIndexNode(node->getOutermostArraySize()); + auto *indexSymbolNode = CreateTempSymbolNode(indexVariable); + auto *cond = new TIntermBinary(EOpLessThan, indexSymbolNode->deepCopy(), arraySizeNode); + auto *indexIncrement = + new TIntermUnary(EOpPreIncrement, indexSymbolNode->deepCopy(), nullptr); + auto *forLoopBody = new TIntermBlock(); + auto *indexedLeft = + new TIntermBinary(EOpIndexDirect, node->getLeft(), indexSymbolNode->deepCopy()); + auto *indexedRight = + new TIntermBinary(EOpIndexDirect, node->getRight(), indexSymbolNode->deepCopy()); + auto *assign = new TIntermBinary(TOperator::EOpAssign, indexedLeft, indexedRight); + forLoopBody->appendStatement(assign); + auto *forLoop = + new TIntermLoop(ELoopFor, indexInit, cond, indexIncrement, EnsureBlock(forLoopBody)); + queueReplacement(forLoop, OriginalNode::IS_DROPPED); + return false; + } +}; + +} // namespace + +bool AggregateAssignArraysInSSBOs(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable) +{ + AggregateAssignArraysInSSBOsTraverser traverser(symbolTable); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignArraysInSSBOs.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignArraysInSSBOs.h new file mode 100644 index 0000000000..ce965bb002 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignArraysInSSBOs.h @@ -0,0 +1,23 @@ +// +// Copyright 2022 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_AGGREGATEASSIGNARRAYSINSSBOS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_AGGREGATEASSIGNARRAYSINSSBOS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool AggregateAssignArraysInSSBOs(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_AGGREGATEASSIGNARRAYSINSSBOS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.cpp new file mode 100644 index 0000000000..4293f4c4da --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.cpp @@ -0,0 +1,76 @@ +// +// Copyright 2022 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.h" + +#include "compiler/translator/StaticType.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +class AggregateAssignStructsInSSBOsTraverser : public TIntermTraverser +{ + public: + AggregateAssignStructsInSSBOsTraverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, false, false, symbolTable) + {} + + protected: + bool visitBinary(Visit visit, TIntermBinary *node) override + { + // Replace all assignments to structs in SSBOs with field-by-field asignments. + // TODO(anglebug.com/7362): this implementation only works for the simple case (assignment + // statement), not more complex cases such as assignment-as-expression or functions with + // side effects in the RHS. + const TStructure *s; + if (node->getOp() != EOpAssign) + { + return true; + } + else if (!IsInShaderStorageBlock(node->getLeft())) + { + return true; + } + else if (!(s = node->getLeft()->getType().getStruct())) + { + return true; + } + ASSERT(node->getRight()->getType().getStruct() == s); + auto *block = new TIntermBlock(); + for (int i = 0; i < static_cast(s->fields().size()); ++i) + { + auto *left = new TIntermBinary(EOpIndexDirectStruct, node->getLeft()->deepCopy(), + CreateIndexNode(i)); + auto *right = new TIntermBinary(EOpIndexDirectStruct, node->getRight()->deepCopy(), + CreateIndexNode(i)); + auto *assign = new TIntermBinary(TOperator::EOpAssign, left, right); + block->appendStatement(assign); + } + + queueReplacement(block, OriginalNode::IS_DROPPED); + return false; + } +}; + +} // namespace + +bool AggregateAssignStructsInSSBOs(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable) +{ + AggregateAssignStructsInSSBOsTraverser traverser(symbolTable); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.h new file mode 100644 index 0000000000..910345902b --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.h @@ -0,0 +1,23 @@ +// +// Copyright 2022 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_AGGREGATEASSIGNSTRUCTSINSSBOS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_AGGREGATEASSIGNSTRUCTSINSSBOS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool AggregateAssignStructsInSSBOs(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_AGGREGATEASSIGNSTRUCTSINSSBOS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ArrayReturnValueToOutParameter.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ArrayReturnValueToOutParameter.cpp new file mode 100644 index 0000000000..54d8fc0808 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ArrayReturnValueToOutParameter.cpp @@ -0,0 +1,233 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// The ArrayReturnValueToOutParameter function changes return values of an array type to out +// parameters in function definitions, prototypes, and call sites. + +#include "compiler/translator/tree_ops/d3d/ArrayReturnValueToOutParameter.h" + +#include + +#include "compiler/translator/StaticType.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +constexpr const ImmutableString kReturnValueVariableName("angle_return"); + +class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser +{ + public: + [[nodiscard]] static bool apply(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable); + + private: + ArrayReturnValueToOutParameterTraverser(TSymbolTable *symbolTable); + + void visitFunctionPrototype(TIntermFunctionPrototype *node) override; + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + bool visitBranch(Visit visit, TIntermBranch *node) override; + bool visitBinary(Visit visit, TIntermBinary *node) override; + + TIntermAggregate *createReplacementCall(TIntermAggregate *originalCall, + TIntermTyped *returnValueTarget); + + // Set when traversal is inside a function with array return value. + TIntermFunctionDefinition *mFunctionWithArrayReturnValue; + + struct ChangedFunction + { + const TVariable *returnValueVariable; + const TFunction *func; + }; + + // Map from function symbol ids to the changed function. + std::map mChangedFunctions; +}; + +TIntermAggregate *ArrayReturnValueToOutParameterTraverser::createReplacementCall( + TIntermAggregate *originalCall, + TIntermTyped *returnValueTarget) +{ + TIntermSequence replacementArguments; + TIntermSequence *originalArguments = originalCall->getSequence(); + for (auto &arg : *originalArguments) + { + replacementArguments.push_back(arg); + } + replacementArguments.push_back(returnValueTarget); + ASSERT(originalCall->getFunction()); + const TSymbolUniqueId &originalId = originalCall->getFunction()->uniqueId(); + TIntermAggregate *replacementCall = TIntermAggregate::CreateFunctionCall( + *mChangedFunctions[originalId.get()].func, &replacementArguments); + replacementCall->setLine(originalCall->getLine()); + return replacementCall; +} + +bool ArrayReturnValueToOutParameterTraverser::apply(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable) +{ + ArrayReturnValueToOutParameterTraverser arrayReturnValueToOutParam(symbolTable); + root->traverse(&arrayReturnValueToOutParam); + return arrayReturnValueToOutParam.updateTree(compiler, root); +} + +ArrayReturnValueToOutParameterTraverser::ArrayReturnValueToOutParameterTraverser( + TSymbolTable *symbolTable) + : TIntermTraverser(true, false, true, symbolTable), mFunctionWithArrayReturnValue(nullptr) +{} + +bool ArrayReturnValueToOutParameterTraverser::visitFunctionDefinition( + Visit visit, + TIntermFunctionDefinition *node) +{ + if (node->getFunctionPrototype()->isArray() && visit == PreVisit) + { + // Replacing the function header is done on visitFunctionPrototype(). + mFunctionWithArrayReturnValue = node; + } + if (visit == PostVisit) + { + mFunctionWithArrayReturnValue = nullptr; + } + return true; +} + +void ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(TIntermFunctionPrototype *node) +{ + if (node->isArray()) + { + // Replace the whole prototype node with another node that has the out parameter + // added. Also set the function to return void. + const TSymbolUniqueId &functionId = node->getFunction()->uniqueId(); + if (mChangedFunctions.find(functionId.get()) == mChangedFunctions.end()) + { + TType *returnValueVariableType = new TType(node->getType()); + returnValueVariableType->setQualifier(EvqParamOut); + ChangedFunction changedFunction; + changedFunction.returnValueVariable = + new TVariable(mSymbolTable, kReturnValueVariableName, returnValueVariableType, + SymbolType::AngleInternal); + TFunction *func = new TFunction(mSymbolTable, node->getFunction()->name(), + node->getFunction()->symbolType(), + StaticType::GetBasic(), false); + for (size_t i = 0; i < node->getFunction()->getParamCount(); ++i) + { + func->addParameter(node->getFunction()->getParam(i)); + } + func->addParameter(changedFunction.returnValueVariable); + changedFunction.func = func; + mChangedFunctions[functionId.get()] = changedFunction; + } + TIntermFunctionPrototype *replacement = + new TIntermFunctionPrototype(mChangedFunctions[functionId.get()].func); + replacement->setLine(node->getLine()); + + queueReplacement(replacement, OriginalNode::IS_DROPPED); + } +} + +bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + ASSERT(!node->isArray() || node->getOp() != EOpCallInternalRawFunction); + if (visit == PreVisit && node->isArray() && node->getOp() == EOpCallFunctionInAST) + { + // Handle call sites where the returned array is not assigned. + // Examples where f() is a function returning an array: + // 1. f(); + // 2. another_array == f(); + // 3. another_function(f()); + // 4. return f(); + // Cases 2 to 4 are already converted to simpler cases by + // SeparateExpressionsReturningArrays, so we only need to worry about the case where a + // function call returning an array forms an expression by itself. + TIntermBlock *parentBlock = getParentNode()->getAsBlock(); + if (parentBlock) + { + // replace + // f(); + // with + // type s0[size]; f(s0); + TIntermSequence replacements; + + // type s0[size]; + TIntermDeclaration *returnValueDeclaration = nullptr; + TVariable *returnValue = DeclareTempVariable(mSymbolTable, new TType(node->getType()), + EvqTemporary, &returnValueDeclaration); + replacements.push_back(returnValueDeclaration); + + // f(s0); + TIntermSymbol *returnValueSymbol = CreateTempSymbolNode(returnValue); + replacements.push_back(createReplacementCall(node, returnValueSymbol)); + mMultiReplacements.emplace_back(parentBlock, node, std::move(replacements)); + } + return false; + } + return true; +} + +bool ArrayReturnValueToOutParameterTraverser::visitBranch(Visit visit, TIntermBranch *node) +{ + if (mFunctionWithArrayReturnValue && node->getFlowOp() == EOpReturn) + { + // Instead of returning a value, assign to the out parameter and then return. + TIntermSequence replacements; + + TIntermTyped *expression = node->getExpression(); + ASSERT(expression != nullptr); + const TSymbolUniqueId &functionId = + mFunctionWithArrayReturnValue->getFunction()->uniqueId(); + ASSERT(mChangedFunctions.find(functionId.get()) != mChangedFunctions.end()); + TIntermSymbol *returnValueSymbol = + new TIntermSymbol(mChangedFunctions[functionId.get()].returnValueVariable); + TIntermBinary *replacementAssignment = + new TIntermBinary(EOpAssign, returnValueSymbol, expression); + replacementAssignment->setLine(expression->getLine()); + replacements.push_back(replacementAssignment); + + TIntermBranch *replacementBranch = new TIntermBranch(EOpReturn, nullptr); + replacementBranch->setLine(node->getLine()); + replacements.push_back(replacementBranch); + + mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, + std::move(replacements)); + } + return false; +} + +bool ArrayReturnValueToOutParameterTraverser::visitBinary(Visit visit, TIntermBinary *node) +{ + if (node->getOp() == EOpAssign && node->getLeft()->isArray()) + { + TIntermAggregate *rightAgg = node->getRight()->getAsAggregate(); + ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpCallInternalRawFunction); + if (rightAgg != nullptr && rightAgg->getOp() == EOpCallFunctionInAST) + { + TIntermAggregate *replacementCall = createReplacementCall(rightAgg, node->getLeft()); + queueReplacement(replacementCall, OriginalNode::IS_DROPPED); + } + } + return false; +} + +} // namespace + +bool ArrayReturnValueToOutParameter(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable) +{ + return ArrayReturnValueToOutParameterTraverser::apply(compiler, root, symbolTable); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ArrayReturnValueToOutParameter.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ArrayReturnValueToOutParameter.h new file mode 100644 index 0000000000..ae8d04ae9a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ArrayReturnValueToOutParameter.h @@ -0,0 +1,27 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// The ArrayReturnValueToOutParameter function changes return values of an array type to out +// parameters in function definitions, prototypes and call sites. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_ARRAYRETURNVALUETOOUTPARAMETER_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_ARRAYRETURNVALUETOOUTPARAMETER_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermNode; +class TSymbolTable; + +[[nodiscard]] bool ArrayReturnValueToOutParameter(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_ARRAYRETURNVALUETOOUTPARAMETER_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/BreakVariableAliasingInInnerLoops.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/BreakVariableAliasingInInnerLoops.cpp new file mode 100644 index 0000000000..908da7a8c2 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/BreakVariableAliasingInInnerLoops.cpp @@ -0,0 +1,110 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend +// may record a variable as aliasing another. Sometimes the alias information gets garbled +// so we work around this issue by breaking the aliasing chain in inner loops. + +#include "compiler/translator/tree_ops/d3d/BreakVariableAliasingInInnerLoops.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +// A HLSL compiler developer gave us more details on the root cause and the workaround needed: +// The root problem is that if the HLSL compiler is applying aliasing information even on +// incomplete simulations (in this case, a single pass). The bug is triggered by an assignment +// that comes from a series of assignments, possibly with swizzled or ternary operators with +// known conditionals, where the source is before the loop. +// So, a workaround is to add a +0 term to variables the first time they are assigned to in +// an inner loop (if they are declared in an outside scope, otherwise there is no need). +// This will break the aliasing chain. + +// For simplicity here we add a +0 to any assignment that is in at least two nested loops. Because +// the bug only shows up with swizzles, and ternary assignment, whole array or whole structure +// assignment don't need a workaround. + +namespace sh +{ + +namespace +{ + +class AliasingBreaker : public TIntermTraverser +{ + public: + AliasingBreaker() : TIntermTraverser(true, false, true) {} + + protected: + bool visitBinary(Visit visit, TIntermBinary *binary) override + { + if (visit != PreVisit) + { + return false; + } + + if (mLoopLevel < 2 || !binary->isAssignment()) + { + return true; + } + + TIntermTyped *B = binary->getRight(); + TType type = B->getType(); + + if (!type.isScalar() && !type.isVector() && !type.isMatrix()) + { + return true; + } + + if (type.isArray() || IsSampler(type.getBasicType())) + { + return true; + } + + // We have a scalar / vector / matrix assignment with loop depth 2. + // Transform it from + // A = B + // to + // A = (B + typeof(0)); + + TIntermBinary *bPlusZero = new TIntermBinary(EOpAdd, B, CreateZeroNode(type)); + bPlusZero->setLine(B->getLine()); + + binary->replaceChildNode(B, bPlusZero); + + return true; + } + + bool visitLoop(Visit visit, TIntermLoop *loop) override + { + if (visit == PreVisit) + { + mLoopLevel++; + } + else + { + ASSERT(mLoopLevel > 0); + mLoopLevel--; + } + + return true; + } + + private: + int mLoopLevel = 0; +}; + +} // anonymous namespace + +bool BreakVariableAliasingInInnerLoops(TCompiler *compiler, TIntermNode *root) +{ + AliasingBreaker breaker; + root->traverse(&breaker); + + return compiler->validateAST(root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/BreakVariableAliasingInInnerLoops.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/BreakVariableAliasingInInnerLoops.h new file mode 100644 index 0000000000..455c7c322d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/BreakVariableAliasingInInnerLoops.h @@ -0,0 +1,25 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend +// may record a variable as aliasing another. Sometimes the alias information gets garbled +// so we work around this issue by breaking the aliasing chain in inner loops. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_BREAKVARIABLEALIASINGININNERLOOPS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_BREAKVARIABLEALIASINGININNERLOOPS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermNode; + +[[nodiscard]] bool BreakVariableAliasingInInnerLoops(TCompiler *compiler, TIntermNode *root); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_BREAKVARIABLEALIASINGININNERLOOPS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ExpandIntegerPowExpressions.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ExpandIntegerPowExpressions.cpp new file mode 100644 index 0000000000..e873db56cd --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ExpandIntegerPowExpressions.cpp @@ -0,0 +1,152 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Implementation of the integer pow expressions HLSL bug workaround. +// See header for more info. + +#include "compiler/translator/tree_ops/d3d/ExpandIntegerPowExpressions.h" + +#include +#include + +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class Traverser : public TIntermTraverser +{ + public: + [[nodiscard]] static bool Apply(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable); + + private: + Traverser(TSymbolTable *symbolTable); + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + void nextIteration(); + + bool mFound = false; +}; + +// static +bool Traverser::Apply(TCompiler *compiler, TIntermNode *root, TSymbolTable *symbolTable) +{ + Traverser traverser(symbolTable); + do + { + traverser.nextIteration(); + root->traverse(&traverser); + if (traverser.mFound) + { + if (!traverser.updateTree(compiler, root)) + { + return false; + } + } + } while (traverser.mFound); + + return true; +} + +Traverser::Traverser(TSymbolTable *symbolTable) : TIntermTraverser(true, false, false, symbolTable) +{} + +void Traverser::nextIteration() +{ + mFound = false; +} + +bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + if (mFound) + { + return false; + } + + // Test 0: skip non-pow operators. + if (node->getOp() != EOpPow) + { + return true; + } + + const TIntermSequence *sequence = node->getSequence(); + ASSERT(sequence->size() == 2u); + const TIntermConstantUnion *constantExponent = sequence->at(1)->getAsConstantUnion(); + + // Test 1: check for a single constant. + if (!constantExponent || constantExponent->getNominalSize() != 1) + { + return true; + } + + float exponentValue = constantExponent->getConstantValue()->getFConst(); + + // Test 2: exponentValue is in the problematic range. + if (exponentValue < -5.0f || exponentValue > 9.0f) + { + return true; + } + + // Test 3: exponentValue is integer or pretty close to an integer. + if (std::abs(exponentValue - std::round(exponentValue)) > 0.0001f) + { + return true; + } + + // Test 4: skip -1, 0, and 1 + int exponent = static_cast(std::round(exponentValue)); + int n = std::abs(exponent); + if (n < 2) + { + return true; + } + + // Potential problem case detected, apply workaround. + + TIntermTyped *lhs = sequence->at(0)->getAsTyped(); + ASSERT(lhs); + + TIntermDeclaration *lhsVariableDeclaration = nullptr; + TVariable *lhsVariable = + DeclareTempVariable(mSymbolTable, lhs, EvqTemporary, &lhsVariableDeclaration); + insertStatementInParentBlock(lhsVariableDeclaration); + + // Create a chain of n-1 multiples. + TIntermTyped *current = CreateTempSymbolNode(lhsVariable); + for (int i = 1; i < n; ++i) + { + TIntermBinary *mul = new TIntermBinary(EOpMul, current, CreateTempSymbolNode(lhsVariable)); + mul->setLine(node->getLine()); + current = mul; + } + + // For negative pow, compute the reciprocal of the positive pow. + if (exponent < 0) + { + TConstantUnion *oneVal = new TConstantUnion(); + oneVal->setFConst(1.0f); + TIntermConstantUnion *oneNode = new TIntermConstantUnion(oneVal, node->getType()); + TIntermBinary *div = new TIntermBinary(EOpDiv, oneNode, current); + current = div; + } + + queueReplacement(current, OriginalNode::IS_DROPPED); + mFound = true; + return false; +} + +} // anonymous namespace + +bool ExpandIntegerPowExpressions(TCompiler *compiler, TIntermNode *root, TSymbolTable *symbolTable) +{ + return Traverser::Apply(compiler, root, symbolTable); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ExpandIntegerPowExpressions.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ExpandIntegerPowExpressions.h new file mode 100644 index 0000000000..2404fb08ac --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/ExpandIntegerPowExpressions.h @@ -0,0 +1,34 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// This mutating tree traversal works around a bug in the HLSL compiler optimizer with "pow" that +// manifests under the following conditions: +// +// - If pow() has a literal exponent value +// - ... and this value is integer or within 10e-6 of an integer +// - ... and it is in {-4, -3, -2, 2, 3, 4, 5, 6, 7, 8} +// +// The workaround is to replace the pow with a series of multiplies. +// See http://anglebug.com/851 + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_EXPANDINTEGERPOWEXPRESSIONS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_EXPANDINTEGERPOWEXPRESSIONS_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermNode; +class TSymbolTable; + +[[nodiscard]] bool ExpandIntegerPowExpressions(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_EXPANDINTEGERPOWEXPRESSIONS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RecordUniformBlocksWithLargeArrayMember.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RecordUniformBlocksWithLargeArrayMember.cpp new file mode 100644 index 0000000000..18d49814ac --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RecordUniformBlocksWithLargeArrayMember.cpp @@ -0,0 +1,385 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RecordUniformBlocksWithLargeArrayMember.h: +// Collect all uniform blocks which have one or more large array members, +// and the array sizes are greater than or equal to 50. If some of them +// satify some conditions, we will translate them to StructuredBuffers +// on Direct3D backend. +// + +#include "compiler/translator/tree_ops/d3d/RecordUniformBlocksWithLargeArrayMember.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ +// Only when a uniform block member's array size is greater than or equal to +// kMinArraySizeUseStructuredBuffer, then we may translate the uniform block +// to a StructuredBuffer on Direct3D backend. +const unsigned int kMinArraySizeUseStructuredBuffer = 50u; + +// There is a maximum of D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT(128) slots that are +// available for shader resources on Direct3D 11. When shader version is 300, we only use +// D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT(16) slots for texture units. We allow StructuredBuffer +// to use the maximum of 60 slots, that is enough here. +const unsigned int kMaxAllowToUseRegisterCount = 60u; + +// Traverser that all uniform blocks which have one or more large array members, and the array +// sizes are greater than or equal to 50. +class UniformBlocksWithLargeArrayMemberTraverser : public TIntermTraverser +{ + public: + UniformBlocksWithLargeArrayMemberTraverser(); + + void visitSymbol(TIntermSymbol *node) override; + bool visitBinary(Visit visit, TIntermBinary *node) override; + std::map &getUniformBlockMayTranslation() + { + return mUniformBlockMayTranslation; + } + std::map &getUniformBlockNotAllowTranslation() + { + return mUniformBlockNotAllowTranslation; + } + std::map &getUniformBlockUsedRegisterCount() + { + return mUniformBlockUsedRegisterCount; + } + std::map &getUniformBlockWithLargeArrayMember() + { + return mUniformBlockWithLargeArrayMember; + } + + private: + std::map mUniformBlockMayTranslation; + std::map mUniformBlockNotAllowTranslation; + std::map mUniformBlockUsedRegisterCount; + std::map mUniformBlockWithLargeArrayMember; +}; + +UniformBlocksWithLargeArrayMemberTraverser::UniformBlocksWithLargeArrayMemberTraverser() + : TIntermTraverser(true, true, false) +{} + +static bool IsSupportedTypeForStructuredBuffer(const TType &type) +{ + const TStructure *structure = type.getStruct(); + const TLayoutMatrixPacking matrixPacking = type.getLayoutQualifier().matrixPacking; + if (structure) + { + const TFieldList &fields = structure->fields(); + for (size_t i = 0; i < fields.size(); i++) + { + const TType &fieldType = *fields[i]->type(); + // Do not allow the structure's member is array or structure. + if (!fieldType.isArray() && !fieldType.getStruct() && + (fieldType.isScalar() || fieldType.isVector() || + (fieldType.isMatrix() && + ((matrixPacking != EmpRowMajor && fieldType.getRows() == 4) || + (matrixPacking == EmpRowMajor && fieldType.getCols() == 4))))) + { + return true; + } + } + return false; + } + else if (type.isMatrix()) + { + // Only supports the matrix types that we do not need to pad in a structure or an array + // explicitly. + return (matrixPacking != EmpRowMajor && type.getRows() == 4) || + (matrixPacking == EmpRowMajor && type.getCols() == 4); + } + else + { + // Supports vector and scalar types in a structure or an array. + return true; + } +} + +static bool CanTranslateUniformBlockToStructuredBuffer(const TInterfaceBlock &interfaceBlock) +{ + const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage(); + + if (blockStorage == EbsStd140 && interfaceBlock.fields().size() == 1u) + { + const TType &fieldType = *interfaceBlock.fields()[0]->type(); + if (fieldType.getNumArraySizes() == 1u && + fieldType.getOutermostArraySize() >= kMinArraySizeUseStructuredBuffer) + { + return IsSupportedTypeForStructuredBuffer(fieldType); + } + } + + return false; +} + +static bool FieldIsOrHasLargeArrayField(const TField &field) +{ + const TType *type = field.type(); + if (type->getArraySizeProduct() >= kMinArraySizeUseStructuredBuffer) + { + return true; + } + + const TStructure *structure = type->getStruct(); + if (structure) + { + const TFieldList &fields = structure->fields(); + bool hasLargeArrayField = false; + for (size_t i = 0; i < fields.size(); i++) + { + hasLargeArrayField = FieldIsOrHasLargeArrayField(*fields[i]); + if (hasLargeArrayField) + { + break; + } + } + return hasLargeArrayField; + } + + return false; +} + +static bool IsInterfaceBlockWithLargeArrayField(const TInterfaceBlock &interfaceBlock) +{ + const TFieldList &fields = interfaceBlock.fields(); + bool isLargeArrayField = false; + for (size_t i = 0; i < fields.size(); i++) + { + isLargeArrayField = FieldIsOrHasLargeArrayField(*fields[i]); + if (isLargeArrayField) + { + break; + } + } + + return isLargeArrayField; +} + +void UniformBlocksWithLargeArrayMemberTraverser::visitSymbol(TIntermSymbol *node) +{ + const TVariable &variable = node->variable(); + const TType &variableType = variable.getType(); + TQualifier qualifier = variable.getType().getQualifier(); + + if (qualifier == EvqUniform) + { + const TInterfaceBlock *interfaceBlock = variableType.getInterfaceBlock(); + if (interfaceBlock) + { + if (CanTranslateUniformBlockToStructuredBuffer(*interfaceBlock)) + { + if (mUniformBlockMayTranslation.count(interfaceBlock->uniqueId().get()) == 0) + { + mUniformBlockMayTranslation[interfaceBlock->uniqueId().get()] = interfaceBlock; + } + + if (!variableType.isInterfaceBlock()) + { + TIntermNode *accessor = getAncestorNode(0); + TIntermBinary *accessorAsBinary = accessor->getAsBinaryNode(); + // The uniform block variable is array type, only indexing operator is allowed + // to operate on the variable, otherwise do not translate the uniform block to + // HLSL StructuredBuffer. + if (!accessorAsBinary || + !(accessorAsBinary && (accessorAsBinary->getOp() == EOpIndexDirect || + accessorAsBinary->getOp() == EOpIndexIndirect))) + { + if (mUniformBlockNotAllowTranslation.count( + interfaceBlock->uniqueId().get()) == 0) + { + mUniformBlockNotAllowTranslation[interfaceBlock->uniqueId().get()] = + interfaceBlock; + } + } + else + { + if (mUniformBlockUsedRegisterCount.count( + interfaceBlock->uniqueId().get()) == 0) + { + // The uniform block is not an instanced one, so it only uses one + // register. + mUniformBlockUsedRegisterCount[interfaceBlock->uniqueId().get()] = 1; + } + } + } + else + { + if (mUniformBlockUsedRegisterCount.count(interfaceBlock->uniqueId().get()) == 0) + { + // The uniform block is an instanced one, the count of used registers + // depends on the array size of variable. + mUniformBlockUsedRegisterCount[interfaceBlock->uniqueId().get()] = + variableType.isArray() ? variableType.getOutermostArraySize() : 1; + } + } + } + + if (interfaceBlock->blockStorage() == EbsStd140 && + IsInterfaceBlockWithLargeArrayField(*interfaceBlock)) + { + if (!variableType.isInterfaceBlock()) + { + TIntermNode *accessor = getAncestorNode(0); + TIntermBinary *accessorAsBinary = accessor->getAsBinaryNode(); + if (accessorAsBinary && (accessorAsBinary->getOp() == EOpIndexDirect || + accessorAsBinary->getOp() == EOpIndexIndirect)) + { + if (mUniformBlockWithLargeArrayMember.count( + interfaceBlock->uniqueId().get()) == 0) + { + mUniformBlockWithLargeArrayMember[interfaceBlock->uniqueId().get()] = + interfaceBlock; + } + } + } + } + } + } +} + +bool UniformBlocksWithLargeArrayMemberTraverser::visitBinary(Visit visit, TIntermBinary *node) +{ + switch (node->getOp()) + { + case EOpIndexDirect: + { + if (visit == PreVisit) + { + const TType &leftType = node->getLeft()->getType(); + if (leftType.isInterfaceBlock()) + { + const TInterfaceBlock *interfaceBlock = leftType.getInterfaceBlock(); + if (CanTranslateUniformBlockToStructuredBuffer(*interfaceBlock) && + mUniformBlockMayTranslation.count(interfaceBlock->uniqueId().get()) == 0) + { + mUniformBlockMayTranslation[interfaceBlock->uniqueId().get()] = + interfaceBlock; + if (mUniformBlockUsedRegisterCount.count( + interfaceBlock->uniqueId().get()) == 0) + { + // The uniform block is an instanced one, the count of used registers + // depends on the array size of variable. + mUniformBlockUsedRegisterCount[interfaceBlock->uniqueId().get()] = + leftType.isArray() ? leftType.getOutermostArraySize() : 1; + } + return false; + } + + if (interfaceBlock->blockStorage() == EbsStd140 && + IsInterfaceBlockWithLargeArrayField(*interfaceBlock)) + { + if (mUniformBlockWithLargeArrayMember.count( + interfaceBlock->uniqueId().get()) == 0) + { + mUniformBlockWithLargeArrayMember[interfaceBlock->uniqueId().get()] = + interfaceBlock; + } + } + } + } + break; + } + case EOpIndexDirectInterfaceBlock: + { + if (visit == InVisit) + { + const TInterfaceBlock *interfaceBlock = + node->getLeft()->getType().getInterfaceBlock(); + if (CanTranslateUniformBlockToStructuredBuffer(*interfaceBlock)) + { + TIntermNode *accessor = getAncestorNode(0); + TIntermBinary *accessorAsBinary = accessor->getAsBinaryNode(); + // The uniform block variable is array type, only indexing operator is allowed + // to operate on the variable, otherwise do not translate the uniform block to + // HLSL StructuredBuffer. + if ((!accessorAsBinary || + !(accessorAsBinary && (accessorAsBinary->getOp() == EOpIndexDirect || + accessorAsBinary->getOp() == EOpIndexIndirect))) && + mUniformBlockNotAllowTranslation.count(interfaceBlock->uniqueId().get()) == + 0) + { + mUniformBlockNotAllowTranslation[interfaceBlock->uniqueId().get()] = + interfaceBlock; + return false; + } + } + + if (interfaceBlock->blockStorage() == EbsStd140 && + IsInterfaceBlockWithLargeArrayField(*interfaceBlock)) + { + TIntermNode *accessor = getAncestorNode(0); + TIntermBinary *accessorAsBinary = accessor->getAsBinaryNode(); + if (accessorAsBinary && (accessorAsBinary->getOp() == EOpIndexDirect || + accessorAsBinary->getOp() == EOpIndexIndirect)) + { + if (mUniformBlockWithLargeArrayMember.count( + interfaceBlock->uniqueId().get()) == 0) + { + mUniformBlockWithLargeArrayMember[interfaceBlock->uniqueId().get()] = + interfaceBlock; + } + } + } + } + break; + } + default: + break; + } + + return true; +} +} // namespace + +bool RecordUniformBlocksWithLargeArrayMember( + TIntermNode *root, + std::map &uniformBlockOptimizedMap, + std::set &slowCompilingUniformBlockSet) +{ + UniformBlocksWithLargeArrayMemberTraverser traverser; + root->traverse(&traverser); + std::map &uniformBlockMayTranslation = + traverser.getUniformBlockMayTranslation(); + std::map &uniformBlockNotAllowTranslation = + traverser.getUniformBlockNotAllowTranslation(); + std::map &uniformBlockUsedRegisterCount = + traverser.getUniformBlockUsedRegisterCount(); + std::map &uniformBlockWithLargeArrayMember = + traverser.getUniformBlockWithLargeArrayMember(); + + unsigned int usedRegisterCount = 0; + for (auto &uniformBlock : uniformBlockMayTranslation) + { + if (uniformBlockNotAllowTranslation.count(uniformBlock.first) == 0) + { + usedRegisterCount += uniformBlockUsedRegisterCount[uniformBlock.first]; + if (usedRegisterCount > kMaxAllowToUseRegisterCount) + { + break; + } + uniformBlockOptimizedMap[uniformBlock.first] = uniformBlock.second; + } + } + + for (auto &uniformBlock : uniformBlockWithLargeArrayMember) + { + if (uniformBlockOptimizedMap.count(uniformBlock.first) == 0) + { + slowCompilingUniformBlockSet.insert(uniformBlock.second->name().data()); + } + } + + return true; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RecordUniformBlocksWithLargeArrayMember.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RecordUniformBlocksWithLargeArrayMember.h new file mode 100644 index 0000000000..d7825c28cb --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RecordUniformBlocksWithLargeArrayMember.h @@ -0,0 +1,28 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RecordUniformBlocksWithLargeArrayMember.h: +// Collect all uniform blocks which have one or more large array members, +// and the array sizes are greater than or equal to 50. If some of them +// satify some conditions, we will translate them to StructuredBuffers +// on Direct3D backend. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_RECORDUNIFORMBLOCKSWITHLARGEARRAYMEMBER_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_RECORDUNIFORMBLOCKSWITHLARGEARRAYMEMBER_H_ + +#include "compiler/translator/IntermNode.h" + +namespace sh +{ +class TIntermNode; + +[[nodiscard]] bool RecordUniformBlocksWithLargeArrayMember( + TIntermNode *root, + std::map &uniformBlockOptimizedMap, + std::set &slowCompilingUniformBlockSet); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_RECORDUNIFORMBLOCKSWITHLARGEARRAYMEMBER_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RemoveSwitchFallThrough.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RemoveSwitchFallThrough.cpp new file mode 100644 index 0000000000..6360f1083c --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RemoveSwitchFallThrough.cpp @@ -0,0 +1,270 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RemoveSwitchFallThrough.cpp: Remove fall-through from switch statements. +// Note that it is unsafe to do further AST transformations on the AST generated +// by this function. It leaves duplicate nodes in the AST making replacements +// unreliable. + +#include "compiler/translator/tree_ops/d3d/RemoveSwitchFallThrough.h" + +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class RemoveSwitchFallThroughTraverser : public TIntermTraverser +{ + public: + static TIntermBlock *removeFallThrough(TIntermBlock *statementList, + PerformanceDiagnostics *perfDiagnostics); + + private: + RemoveSwitchFallThroughTraverser(TIntermBlock *statementList, + PerformanceDiagnostics *perfDiagnostics); + + void visitSymbol(TIntermSymbol *node) override; + void visitConstantUnion(TIntermConstantUnion *node) override; + bool visitDeclaration(Visit, TIntermDeclaration *node) override; + bool visitBinary(Visit, TIntermBinary *node) override; + bool visitUnary(Visit, TIntermUnary *node) override; + bool visitTernary(Visit visit, TIntermTernary *node) override; + bool visitSwizzle(Visit, TIntermSwizzle *node) override; + bool visitIfElse(Visit visit, TIntermIfElse *node) override; + bool visitSwitch(Visit, TIntermSwitch *node) override; + bool visitCase(Visit, TIntermCase *node) override; + bool visitAggregate(Visit, TIntermAggregate *node) override; + bool visitBlock(Visit, TIntermBlock *node) override; + bool visitLoop(Visit, TIntermLoop *node) override; + bool visitBranch(Visit, TIntermBranch *node) override; + + void outputSequence(TIntermSequence *sequence, size_t startIndex); + void handlePreviousCase(); + + TIntermBlock *mStatementList; + TIntermBlock *mStatementListOut; + bool mLastStatementWasBreak; + TIntermBlock *mPreviousCase; + std::vector mCasesSharingBreak; + PerformanceDiagnostics *mPerfDiagnostics; +}; + +TIntermBlock *RemoveSwitchFallThroughTraverser::removeFallThrough( + TIntermBlock *statementList, + PerformanceDiagnostics *perfDiagnostics) +{ + RemoveSwitchFallThroughTraverser rm(statementList, perfDiagnostics); + ASSERT(statementList); + statementList->traverse(&rm); + ASSERT(rm.mPreviousCase || statementList->getSequence()->empty()); + if (!rm.mLastStatementWasBreak && rm.mPreviousCase) + { + // Make sure that there's a branch at the end of the final case inside the switch statement. + // This also ensures that any cases that fall through to the final case will get the break. + TIntermBranch *finalBreak = new TIntermBranch(EOpBreak, nullptr); + rm.mPreviousCase->getSequence()->push_back(finalBreak); + rm.mLastStatementWasBreak = true; + } + rm.handlePreviousCase(); + return rm.mStatementListOut; +} + +RemoveSwitchFallThroughTraverser::RemoveSwitchFallThroughTraverser( + TIntermBlock *statementList, + PerformanceDiagnostics *perfDiagnostics) + : TIntermTraverser(true, false, false), + mStatementList(statementList), + mLastStatementWasBreak(false), + mPreviousCase(nullptr), + mPerfDiagnostics(perfDiagnostics) +{ + mStatementListOut = new TIntermBlock(); +} + +void RemoveSwitchFallThroughTraverser::visitSymbol(TIntermSymbol *node) +{ + // Note that this assumes that switch statements which don't begin by a case statement + // have already been weeded out in validation. + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; +} + +void RemoveSwitchFallThroughTraverser::visitConstantUnion(TIntermConstantUnion *node) +{ + // Conditions of case labels are not traversed, so this is a constant statement like "0;". + // These are no-ops so there's no need to add them back to the statement list. Should have + // already been pruned out of the AST, in fact. + UNREACHABLE(); +} + +bool RemoveSwitchFallThroughTraverser::visitDeclaration(Visit, TIntermDeclaration *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThroughTraverser::visitBinary(Visit, TIntermBinary *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThroughTraverser::visitUnary(Visit, TIntermUnary *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThroughTraverser::visitTernary(Visit, TIntermTernary *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThroughTraverser::visitSwizzle(Visit, TIntermSwizzle *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThroughTraverser::visitIfElse(Visit, TIntermIfElse *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThroughTraverser::visitSwitch(Visit, TIntermSwitch *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + // Don't go into nested switch statements + return false; +} + +void RemoveSwitchFallThroughTraverser::outputSequence(TIntermSequence *sequence, size_t startIndex) +{ + for (size_t i = startIndex; i < sequence->size(); ++i) + { + mStatementListOut->getSequence()->push_back(sequence->at(i)); + } +} + +void RemoveSwitchFallThroughTraverser::handlePreviousCase() +{ + if (mPreviousCase) + mCasesSharingBreak.push_back(mPreviousCase); + if (mLastStatementWasBreak) + { + for (size_t i = 0; i < mCasesSharingBreak.size(); ++i) + { + ASSERT(!mCasesSharingBreak.at(i)->getSequence()->empty()); + if (mCasesSharingBreak.at(i)->getSequence()->size() == 1) + { + // Fall-through is allowed in case the label has no statements. + outputSequence(mCasesSharingBreak.at(i)->getSequence(), 0); + } + else + { + // Include all the statements that this case can fall through under the same label. + if (mCasesSharingBreak.size() > i + 1u) + { + mPerfDiagnostics->warning(mCasesSharingBreak.at(i)->getLine(), + "Performance: non-empty fall-through cases in " + "switch statements generate extra code.", + "switch"); + } + for (size_t j = i; j < mCasesSharingBreak.size(); ++j) + { + size_t startIndex = + j > i ? 1 : 0; // Add the label only from the first sequence. + outputSequence(mCasesSharingBreak.at(j)->getSequence(), startIndex); + } + } + } + mCasesSharingBreak.clear(); + } + mLastStatementWasBreak = false; + mPreviousCase = nullptr; +} + +bool RemoveSwitchFallThroughTraverser::visitCase(Visit, TIntermCase *node) +{ + handlePreviousCase(); + mPreviousCase = new TIntermBlock(); + mPreviousCase->getSequence()->push_back(node); + mPreviousCase->setLine(node->getLine()); + // Don't traverse the condition of the case statement + return false; +} + +bool RemoveSwitchFallThroughTraverser::visitAggregate(Visit, TIntermAggregate *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool DoesBlockAlwaysBreak(TIntermBlock *node) +{ + if (node->getSequence()->empty()) + { + return false; + } + + TIntermBlock *lastStatementAsBlock = node->getSequence()->back()->getAsBlock(); + if (lastStatementAsBlock) + { + return DoesBlockAlwaysBreak(lastStatementAsBlock); + } + + TIntermBranch *lastStatementAsBranch = node->getSequence()->back()->getAsBranchNode(); + return lastStatementAsBranch != nullptr; +} + +bool RemoveSwitchFallThroughTraverser::visitBlock(Visit, TIntermBlock *node) +{ + if (node != mStatementList) + { + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = DoesBlockAlwaysBreak(node); + return false; + } + return true; +} + +bool RemoveSwitchFallThroughTraverser::visitLoop(Visit, TIntermLoop *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThroughTraverser::visitBranch(Visit, TIntermBranch *node) +{ + mPreviousCase->getSequence()->push_back(node); + // TODO: Verify that accepting return or continue statements here doesn't cause problems. + mLastStatementWasBreak = true; + return false; +} + +} // anonymous namespace + +TIntermBlock *RemoveSwitchFallThrough(TIntermBlock *statementList, + PerformanceDiagnostics *perfDiagnostics) +{ + return RemoveSwitchFallThroughTraverser::removeFallThrough(statementList, perfDiagnostics); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RemoveSwitchFallThrough.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RemoveSwitchFallThrough.h new file mode 100644 index 0000000000..b92e7e5f6d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RemoveSwitchFallThrough.h @@ -0,0 +1,27 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RemoveSwitchFallThrough.h: Remove fall-through from switch statements. +// Note that it is unsafe to do further AST transformations on the AST generated +// by this function. It leaves duplicate nodes in the AST making replacements +// unreliable. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_REMOVESWITCHFALLTHROUGH_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_REMOVESWITCHFALLTHROUGH_H_ + +namespace sh +{ + +class TIntermBlock; +class PerformanceDiagnostics; + +// When given a statementList from a switch AST node, return an updated +// statementList that has fall-through removed. +TIntermBlock *RemoveSwitchFallThrough(TIntermBlock *statementList, + PerformanceDiagnostics *perfDiagnostics); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_REMOVESWITCHFALLTHROUGH_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteAtomicFunctionExpressions.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteAtomicFunctionExpressions.cpp new file mode 100644 index 0000000000..b2de6079b7 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteAtomicFunctionExpressions.cpp @@ -0,0 +1,183 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Implementation of the function RewriteAtomicFunctionExpressions. +// See the header for more details. + +#include "compiler/translator/tree_ops/d3d/RewriteAtomicFunctionExpressions.h" + +#include "compiler/translator/tree_util/IntermNodePatternMatcher.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ +namespace +{ +// Traverser that simplifies all the atomic function expressions into the ones that can be directly +// translated into HLSL. +// +// case 1 (only for atomicExchange and atomicCompSwap): +// original: +// atomicExchange(counter, newValue); +// new: +// tempValue = atomicExchange(counter, newValue); +// +// case 2 (atomic function, temporary variable required): +// original: +// value = atomicAdd(counter, 1) * otherValue; +// someArray[atomicAdd(counter, 1)] = someOtherValue; +// new: +// value = ((tempValue = atomicAdd(counter, 1)), tempValue) * otherValue; +// someArray[((tempValue = atomicAdd(counter, 1)), tempValue)] = someOtherValue; +// +// case 3 (atomic function used directly initialize a variable): +// original: +// int value = atomicAdd(counter, 1); +// new: +// tempValue = atomicAdd(counter, 1); +// int value = tempValue; +// +class RewriteAtomicFunctionExpressionsTraverser : public TIntermTraverser +{ + public: + RewriteAtomicFunctionExpressionsTraverser(TSymbolTable *symbolTable, int shaderVersion); + + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + bool visitBlock(Visit visit, TIntermBlock *node) override; + + private: + static bool IsAtomicExchangeOrCompSwapNoReturnValue(TIntermAggregate *node, + TIntermNode *parentNode); + static bool IsAtomicFunctionInsideExpression(TIntermAggregate *node, TIntermNode *parentNode); + + void rewriteAtomicFunctionCallNode(TIntermAggregate *oldAtomicFunctionNode); + + const TVariable *getTempVariable(const TType *type); + + int mShaderVersion; + TIntermSequence mTempVariables; +}; + +RewriteAtomicFunctionExpressionsTraverser::RewriteAtomicFunctionExpressionsTraverser( + TSymbolTable *symbolTable, + int shaderVersion) + : TIntermTraverser(false, false, true, symbolTable), mShaderVersion(shaderVersion) +{} + +void RewriteAtomicFunctionExpressionsTraverser::rewriteAtomicFunctionCallNode( + TIntermAggregate *oldAtomicFunctionNode) +{ + ASSERT(oldAtomicFunctionNode); + + const TVariable *returnVariable = getTempVariable(&oldAtomicFunctionNode->getType()); + + TIntermBinary *rewrittenNode = new TIntermBinary( + TOperator::EOpAssign, CreateTempSymbolNode(returnVariable), oldAtomicFunctionNode); + + auto *parentNode = getParentNode(); + + auto *parentBinary = parentNode->getAsBinaryNode(); + if (parentBinary && parentBinary->getOp() == EOpInitialize) + { + insertStatementInParentBlock(rewrittenNode); + queueReplacement(CreateTempSymbolNode(returnVariable), OriginalNode::IS_DROPPED); + } + else + { + // As all atomic function assignment will be converted to the last argument of an + // interlocked function, if we need the return value, assignment needs to be wrapped with + // the comma operator and the temporary variables. + if (!parentNode->getAsBlock()) + { + rewrittenNode = TIntermBinary::CreateComma( + rewrittenNode, new TIntermSymbol(returnVariable), mShaderVersion); + } + + queueReplacement(rewrittenNode, OriginalNode::IS_DROPPED); + } +} + +const TVariable *RewriteAtomicFunctionExpressionsTraverser::getTempVariable(const TType *type) +{ + TIntermDeclaration *variableDeclaration; + TVariable *returnVariable = + DeclareTempVariable(mSymbolTable, type, EvqTemporary, &variableDeclaration); + mTempVariables.push_back(variableDeclaration); + return returnVariable; +} + +bool RewriteAtomicFunctionExpressionsTraverser::IsAtomicExchangeOrCompSwapNoReturnValue( + TIntermAggregate *node, + TIntermNode *parentNode) +{ + ASSERT(node); + return (node->getOp() == EOpAtomicExchange || node->getOp() == EOpAtomicCompSwap) && + parentNode && parentNode->getAsBlock(); +} + +bool RewriteAtomicFunctionExpressionsTraverser::IsAtomicFunctionInsideExpression( + TIntermAggregate *node, + TIntermNode *parentNode) +{ + ASSERT(node); + // We only need to handle atomic functions with a parent that it is not block nodes. If the + // parent node is block, it means that the atomic function is not inside an expression. + if (!BuiltInGroup::IsAtomicMemory(node->getOp()) || parentNode->getAsBlock()) + { + return false; + } + + auto *parentAsBinary = parentNode->getAsBinaryNode(); + // Assignments are handled in OutputHLSL + return !parentAsBinary || parentAsBinary->getOp() != EOpAssign; +} + +bool RewriteAtomicFunctionExpressionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + ASSERT(visit == PostVisit); + // Skip atomic memory functions for SSBO. They will be processed in the OutputHLSL traverser. + if (BuiltInGroup::IsAtomicMemory(node->getOp()) && + IsInShaderStorageBlock((*node->getSequence())[0]->getAsTyped())) + { + return false; + } + + TIntermNode *parentNode = getParentNode(); + if (IsAtomicExchangeOrCompSwapNoReturnValue(node, parentNode) || + IsAtomicFunctionInsideExpression(node, parentNode)) + { + rewriteAtomicFunctionCallNode(node); + } + + return true; +} + +bool RewriteAtomicFunctionExpressionsTraverser::visitBlock(Visit visit, TIntermBlock *node) +{ + ASSERT(visit == PostVisit); + + if (!mTempVariables.empty() && getParentNode()->getAsFunctionDefinition()) + { + insertStatementsInBlockAtPosition(node, 0, mTempVariables, TIntermSequence()); + mTempVariables.clear(); + } + + return true; +} + +} // anonymous namespace + +bool RewriteAtomicFunctionExpressions(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable, + int shaderVersion) +{ + RewriteAtomicFunctionExpressionsTraverser traverser(symbolTable, shaderVersion); + traverser.traverse(root); + return traverser.updateTree(compiler, root); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteAtomicFunctionExpressions.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteAtomicFunctionExpressions.h new file mode 100644 index 0000000000..60e6ffa2d1 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteAtomicFunctionExpressions.h @@ -0,0 +1,42 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteAtomicFunctionExpressions rewrites the expressions that contain +// atomic function calls and cannot be directly translated into HLSL into +// several simple ones that can be easily handled in the HLSL translator. +// +// We need to rewite these expressions because: +// 1. All GLSL atomic functions have return values, which all represent the +// original value of the shared or ssbo variable; while all HLSL atomic +// functions don't, and the original value can be stored in the last +// parameter of the function call. +// 2. For HLSL atomic functions, the last parameter that stores the original +// value is optional except for InterlockedExchange and +// InterlockedCompareExchange. Missing original_value in the call of +// InterlockedExchange or InterlockedCompareExchange results in a compile +// error from HLSL compiler. +// +// RewriteAtomicFunctionExpressions is a function that can modify the AST +// to ensure all the expressions that contain atomic function calls can be +// directly translated into HLSL expressions. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_REWRITE_ATOMIC_FUNCTION_EXPRESSIONS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_REWRITE_ATOMIC_FUNCTION_EXPRESSIONS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermNode; +class TSymbolTable; + +[[nodiscard]] bool RewriteAtomicFunctionExpressions(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable, + int shaderVersion); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_REWRITE_ATOMIC_FUNCTION_EXPRESSIONS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteElseBlocks.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteElseBlocks.cpp new file mode 100644 index 0000000000..10647d1bf1 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteElseBlocks.cpp @@ -0,0 +1,123 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteElseBlocks.cpp: Implementation for tree transform to change +// all if-else blocks to if-if blocks. +// + +#include "compiler/translator/tree_ops/d3d/RewriteElseBlocks.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/NodeSearch.h" + +namespace sh +{ + +namespace +{ + +class ElseBlockRewriter : public TIntermTraverser +{ + public: + ElseBlockRewriter(TSymbolTable *symbolTable); + + protected: + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *aggregate) override; + bool visitBlock(Visit visit, TIntermBlock *block) override; + + private: + TIntermNode *rewriteIfElse(TIntermIfElse *ifElse); + + const TType *mFunctionType; +}; + +ElseBlockRewriter::ElseBlockRewriter(TSymbolTable *symbolTable) + : TIntermTraverser(true, false, true, symbolTable), mFunctionType(nullptr) +{} + +bool ElseBlockRewriter::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) +{ + // Store the current function context (see comment below) + mFunctionType = ((visit == PreVisit) ? &node->getFunctionPrototype()->getType() : nullptr); + return true; +} + +bool ElseBlockRewriter::visitBlock(Visit visit, TIntermBlock *node) +{ + if (visit == PostVisit) + { + for (size_t statementIndex = 0; statementIndex != node->getSequence()->size(); + statementIndex++) + { + TIntermNode *statement = (*node->getSequence())[statementIndex]; + TIntermIfElse *ifElse = statement->getAsIfElseNode(); + if (ifElse && ifElse->getFalseBlock() != nullptr) + { + (*node->getSequence())[statementIndex] = rewriteIfElse(ifElse); + } + } + } + return true; +} + +TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse) +{ + ASSERT(ifElse != nullptr); + + TIntermDeclaration *storeCondition = nullptr; + TVariable *conditionVariable = + DeclareTempVariable(mSymbolTable, ifElse->getCondition(), EvqTemporary, &storeCondition); + + TIntermBlock *falseBlock = nullptr; + + TType boolType(EbtBool, EbpUndefined, EvqTemporary); + + if (ifElse->getFalseBlock()) + { + TIntermBlock *negatedElse = nullptr; + // crbug.com/346463 + // D3D generates error messages claiming a function has no return value, when rewriting + // an if-else clause that returns something non-void in a function. By appending mock + // returns (that are unreachable) we can silence this compile error. + if (mFunctionType && mFunctionType->getBasicType() != EbtVoid) + { + TIntermNode *returnNode = new TIntermBranch(EOpReturn, CreateZeroNode(*mFunctionType)); + negatedElse = new TIntermBlock(); + negatedElse->appendStatement(returnNode); + } + + TIntermSymbol *conditionSymbolElse = CreateTempSymbolNode(conditionVariable); + TIntermUnary *negatedCondition = + new TIntermUnary(EOpLogicalNot, conditionSymbolElse, nullptr); + TIntermIfElse *falseIfElse = + new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse); + falseBlock = EnsureBlock(falseIfElse); + } + + TIntermSymbol *conditionSymbolSel = CreateTempSymbolNode(conditionVariable); + TIntermIfElse *newIfElse = + new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock); + + TIntermBlock *block = new TIntermBlock(); + block->getSequence()->push_back(storeCondition); + block->getSequence()->push_back(newIfElse); + + return block; +} + +} // anonymous namespace + +bool RewriteElseBlocks(TCompiler *compiler, TIntermNode *node, TSymbolTable *symbolTable) +{ + ElseBlockRewriter rewriter(symbolTable); + node->traverse(&rewriter); + + return compiler->validateAST(node); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteElseBlocks.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteElseBlocks.h new file mode 100644 index 0000000000..cab0f7090c --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteElseBlocks.h @@ -0,0 +1,27 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteElseBlocks.h: Prototype for tree transform to change +// all if-else blocks to if-if blocks. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_REWRITEELSEBLOCKS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_REWRITEELSEBLOCKS_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermNode; +class TSymbolTable; + +[[nodiscard]] bool RewriteElseBlocks(TCompiler *compiler, + TIntermNode *node, + TSymbolTable *symbolTable); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_REWRITEELSEBLOCKS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteExpressionsWithShaderStorageBlock.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteExpressionsWithShaderStorageBlock.cpp new file mode 100644 index 0000000000..709f394878 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteExpressionsWithShaderStorageBlock.cpp @@ -0,0 +1,420 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteExpressionsWithShaderStorageBlock rewrites the expressions that contain shader storage +// block calls into several simple ones that can be easily handled in the HLSL translator. After the +// AST pass, all ssbo related blocks will be like below: +// ssbo_access_chain = ssbo_access_chain; +// ssbo_access_chain = expr_no_ssbo; +// lvalue_no_ssbo = ssbo_access_chain; +// + +#include "compiler/translator/tree_ops/d3d/RewriteExpressionsWithShaderStorageBlock.h" + +#include "compiler/translator/Symbol.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ +namespace +{ + +bool IsIncrementOrDecrementOperator(TOperator op) +{ + switch (op) + { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + return true; + default: + return false; + } +} + +bool IsCompoundAssignment(TOperator op) +{ + switch (op) + { + case EOpAddAssign: + case EOpSubAssign: + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + case EOpDivAssign: + case EOpIModAssign: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: + return true; + default: + return false; + } +} + +// EOpIndexDirect, EOpIndexIndirect, EOpIndexDirectStruct, EOpIndexDirectInterfaceBlock belong to +// operators in SSBO access chain. +bool IsReadonlyBinaryOperatorNotInSSBOAccessChain(TOperator op) +{ + switch (op) + { + case EOpComma: + case EOpAdd: + case EOpSub: + case EOpMul: + case EOpDiv: + case EOpIMod: + case EOpBitShiftLeft: + case EOpBitShiftRight: + case EOpBitwiseAnd: + case EOpBitwiseXor: + case EOpBitwiseOr: + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + case EOpVectorTimesScalar: + case EOpMatrixTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesMatrix: + case EOpLogicalOr: + case EOpLogicalXor: + case EOpLogicalAnd: + return true; + default: + return false; + } +} + +bool HasSSBOAsFunctionArgument(TIntermSequence *arguments) +{ + for (TIntermNode *arg : *arguments) + { + TIntermTyped *typedArg = arg->getAsTyped(); + if (IsInShaderStorageBlock(typedArg)) + { + return true; + } + } + return false; +} + +class RewriteExpressionsWithShaderStorageBlockTraverser : public TIntermTraverser +{ + public: + RewriteExpressionsWithShaderStorageBlockTraverser(TSymbolTable *symbolTable); + void nextIteration(); + bool foundSSBO() const { return mFoundSSBO; } + + private: + bool visitBinary(Visit, TIntermBinary *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + bool visitUnary(Visit visit, TIntermUnary *node) override; + + TIntermSymbol *insertInitStatementAndReturnTempSymbol(TIntermTyped *node, + TIntermSequence *insertions); + + bool mFoundSSBO; +}; + +RewriteExpressionsWithShaderStorageBlockTraverser:: + RewriteExpressionsWithShaderStorageBlockTraverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, true, false, symbolTable), mFoundSSBO(false) +{} + +TIntermSymbol * +RewriteExpressionsWithShaderStorageBlockTraverser::insertInitStatementAndReturnTempSymbol( + TIntermTyped *node, + TIntermSequence *insertions) +{ + TIntermDeclaration *variableDeclaration; + TVariable *tempVariable = + DeclareTempVariable(mSymbolTable, node, EvqTemporary, &variableDeclaration); + + insertions->push_back(variableDeclaration); + return CreateTempSymbolNode(tempVariable); +} + +bool RewriteExpressionsWithShaderStorageBlockTraverser::visitBinary(Visit visit, + TIntermBinary *node) +{ + // Make sure that the expression is caculated from left to right. + if (visit != InVisit) + { + return true; + } + + if (mFoundSSBO) + { + return false; + } + + bool rightSSBO = IsInShaderStorageBlock(node->getRight()); + bool leftSSBO = IsInShaderStorageBlock(node->getLeft()); + if (!leftSSBO && !rightSSBO) + { + return true; + } + + // case 1: Compound assigment operator + // original: + // lssbo += expr; + // new: + // var rvalue = expr; + // var temp = lssbo; + // temp += rvalue; + // lssbo = temp; + // + // original: + // lvalue_no_ssbo += rssbo; + // new: + // var rvalue = rssbo; + // lvalue_no_ssbo += rvalue; + if (IsCompoundAssignment(node->getOp())) + { + mFoundSSBO = true; + TIntermSequence insertions; + TIntermTyped *rightNode = + insertInitStatementAndReturnTempSymbol(node->getRight(), &insertions); + if (leftSSBO) + { + TIntermSymbol *tempSymbol = + insertInitStatementAndReturnTempSymbol(node->getLeft()->deepCopy(), &insertions); + TIntermBinary *tempCompoundOperate = + new TIntermBinary(node->getOp(), tempSymbol->deepCopy(), rightNode->deepCopy()); + insertions.push_back(tempCompoundOperate); + insertStatementsInParentBlock(insertions); + + TIntermBinary *assignTempValueToSSBO = + new TIntermBinary(EOpAssign, node->getLeft(), tempSymbol->deepCopy()); + queueReplacement(assignTempValueToSSBO, OriginalNode::IS_DROPPED); + } + else + { + insertStatementsInParentBlock(insertions); + TIntermBinary *compoundAssignRValueToLValue = + new TIntermBinary(node->getOp(), node->getLeft(), rightNode->deepCopy()); + queueReplacement(compoundAssignRValueToLValue, OriginalNode::IS_DROPPED); + } + } + // case 2: Readonly binary operator + // original: + // ssbo0 + ssbo1 + ssbo2; + // new: + // var temp0 = ssbo0; + // var temp1 = ssbo1; + // var temp2 = ssbo2; + // temp0 + temp1 + temp2; + else if (IsReadonlyBinaryOperatorNotInSSBOAccessChain(node->getOp()) && (leftSSBO || rightSSBO)) + { + mFoundSSBO = true; + TIntermTyped *rightNode = node->getRight(); + TIntermTyped *leftNode = node->getLeft(); + TIntermSequence insertions; + if (rightSSBO) + { + rightNode = insertInitStatementAndReturnTempSymbol(node->getRight(), &insertions); + } + if (leftSSBO) + { + leftNode = insertInitStatementAndReturnTempSymbol(node->getLeft(), &insertions); + } + + insertStatementsInParentBlock(insertions); + TIntermBinary *newExpr = + new TIntermBinary(node->getOp(), leftNode->deepCopy(), rightNode->deepCopy()); + queueReplacement(newExpr, OriginalNode::IS_DROPPED); + } + return !mFoundSSBO; +} + +// case 3: ssbo as the argument of aggregate type +// original: +// foo(ssbo); +// new: +// var tempArg = ssbo; +// foo(tempArg); +// ssbo = tempArg; (Optional based on whether ssbo is an out|input argument) +// +// original: +// foo(ssbo) * expr; +// new: +// var tempArg = ssbo; +// var tempReturn = foo(tempArg); +// ssbo = tempArg; (Optional based on whether ssbo is an out|input argument) +// tempReturn * expr; +bool RewriteExpressionsWithShaderStorageBlockTraverser::visitAggregate(Visit visit, + TIntermAggregate *node) +{ + // Make sure that visitAggregate is only executed once for same node. + if (visit != PreVisit) + { + return true; + } + + if (mFoundSSBO) + { + return false; + } + + // We still need to process the ssbo as the non-first argument of atomic memory functions. + if (BuiltInGroup::IsAtomicMemory(node->getOp()) && + IsInShaderStorageBlock((*node->getSequence())[0]->getAsTyped())) + { + return true; + } + + if (!HasSSBOAsFunctionArgument(node->getSequence())) + { + return true; + } + + mFoundSSBO = true; + TIntermSequence insertions; + TIntermSequence readBackToSSBOs; + TIntermSequence *originalArguments = node->getSequence(); + for (size_t i = 0; i < node->getChildCount(); ++i) + { + TIntermTyped *ssboArgument = (*originalArguments)[i]->getAsTyped(); + if (IsInShaderStorageBlock(ssboArgument)) + { + TIntermSymbol *argumentCopy = + insertInitStatementAndReturnTempSymbol(ssboArgument, &insertions); + if (node->getFunction() != nullptr) + { + TQualifier qual = node->getFunction()->getParam(i)->getType().getQualifier(); + if (qual == EvqParamInOut || qual == EvqParamOut) + { + TIntermBinary *readBackToSSBO = new TIntermBinary( + EOpAssign, ssboArgument->deepCopy(), argumentCopy->deepCopy()); + readBackToSSBOs.push_back(readBackToSSBO); + } + } + node->replaceChildNode(ssboArgument, argumentCopy); + } + } + + TIntermBlock *parentBlock = getParentNode()->getAsBlock(); + if (parentBlock) + { + // Aggregate node is as a single sentence. + insertions.push_back(node); + if (!readBackToSSBOs.empty()) + { + insertions.insert(insertions.end(), readBackToSSBOs.begin(), readBackToSSBOs.end()); + } + mMultiReplacements.emplace_back(parentBlock, node, std::move(insertions)); + } + else + { + // Aggregate node is inside an expression. + TIntermSymbol *tempSymbol = insertInitStatementAndReturnTempSymbol(node, &insertions); + if (!readBackToSSBOs.empty()) + { + insertions.insert(insertions.end(), readBackToSSBOs.begin(), readBackToSSBOs.end()); + } + insertStatementsInParentBlock(insertions); + queueReplacement(tempSymbol->deepCopy(), OriginalNode::IS_DROPPED); + } + + return false; +} + +bool RewriteExpressionsWithShaderStorageBlockTraverser::visitUnary(Visit visit, TIntermUnary *node) +{ + if (mFoundSSBO) + { + return false; + } + + if (!IsInShaderStorageBlock(node->getOperand())) + { + return true; + } + + // .length() is processed in OutputHLSL. + if (node->getOp() == EOpArrayLength) + { + return true; + } + + mFoundSSBO = true; + + // case 4: ssbo as the operand of ++/-- + // original: + // ++ssbo * expr; + // new: + // var temp1 = ssbo; + // var temp2 = ++temp1; + // ssbo = temp1; + // temp2 * expr; + if (IsIncrementOrDecrementOperator(node->getOp())) + { + TIntermSequence insertions; + TIntermSymbol *temp1 = + insertInitStatementAndReturnTempSymbol(node->getOperand(), &insertions); + TIntermUnary *newUnary = new TIntermUnary(node->getOp(), temp1->deepCopy(), nullptr); + TIntermSymbol *temp2 = insertInitStatementAndReturnTempSymbol(newUnary, &insertions); + TIntermBinary *readBackToSSBO = + new TIntermBinary(EOpAssign, node->getOperand()->deepCopy(), temp1->deepCopy()); + insertions.push_back(readBackToSSBO); + insertStatementsInParentBlock(insertions); + queueReplacement(temp2->deepCopy(), OriginalNode::IS_DROPPED); + } + // case 5: ssbo as the operand of readonly unary operator + // original: + // ~ssbo * expr; + // new: + // var temp = ssbo; + // ~temp * expr; + else + { + TIntermSequence insertions; + TIntermSymbol *temp = + insertInitStatementAndReturnTempSymbol(node->getOperand(), &insertions); + insertStatementsInParentBlock(insertions); + node->replaceChildNode(node->getOperand(), temp->deepCopy()); + } + return false; +} + +void RewriteExpressionsWithShaderStorageBlockTraverser::nextIteration() +{ + mFoundSSBO = false; +} + +} // anonymous namespace + +bool RewriteExpressionsWithShaderStorageBlock(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable) +{ + RewriteExpressionsWithShaderStorageBlockTraverser traverser(symbolTable); + do + { + traverser.nextIteration(); + root->traverse(&traverser); + if (traverser.foundSSBO()) + { + if (!traverser.updateTree(compiler, root)) + { + return false; + } + } + } while (traverser.foundSSBO()); + + return true; +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteExpressionsWithShaderStorageBlock.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteExpressionsWithShaderStorageBlock.h new file mode 100644 index 0000000000..bf824c4a23 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteExpressionsWithShaderStorageBlock.h @@ -0,0 +1,37 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteExpressionsWithShaderStorageBlock rewrites the expressions that contain shader storage +// block calls into several simple ones that can be easily handled in the HLSL translator. After the +// AST pass, all ssbo related blocks will be like below: +// ssbo_access_chain = ssbo_access_chain; +// ssbo_access_chain = expr_no_ssbo; +// lvalue_no_ssbo = ssbo_access_chain; +// +// Below situations are needed to be rewritten (Details can be found in .cpp file). +// SSBO as the operand of compound assignment operators. +// SSBO as the operand of ++/--. +// SSBO as the operand of repeated assignment. +// SSBO as the operand of readonly unary/binary/ternary operators. +// SSBO as the argument of aggregate type. +// SSBO as the condition of if/switch/while/do-while/for + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_REWRITE_EXPRESSIONS_WITH_SHADER_STORAGE_BLOCK_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_REWRITE_EXPRESSIONS_WITH_SHADER_STORAGE_BLOCK_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermNode; +class TSymbolTable; + +[[nodiscard]] bool RewriteExpressionsWithShaderStorageBlock(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_REWRITE_EXPRESSIONS_WITH_SHADER_STORAGE_BLOCK_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteUnaryMinusOperatorInt.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteUnaryMinusOperatorInt.cpp new file mode 100644 index 0000000000..5d8cdb657d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteUnaryMinusOperatorInt.cpp @@ -0,0 +1,117 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Implementation of evaluating unary integer variable bug workaround. +// See header for more info. + +#include "compiler/translator/tree_ops/d3d/RewriteUnaryMinusOperatorInt.h" + +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class Traverser : public TIntermTraverser +{ + public: + [[nodiscard]] static bool Apply(TCompiler *compiler, TIntermNode *root); + + private: + Traverser(); + bool visitUnary(Visit visit, TIntermUnary *node) override; + void nextIteration(); + + bool mFound = false; +}; + +// static +bool Traverser::Apply(TCompiler *compiler, TIntermNode *root) +{ + Traverser traverser; + do + { + traverser.nextIteration(); + root->traverse(&traverser); + if (traverser.mFound) + { + if (!traverser.updateTree(compiler, root)) + { + return false; + } + } + } while (traverser.mFound); + + return true; +} + +Traverser::Traverser() : TIntermTraverser(true, false, false) {} + +void Traverser::nextIteration() +{ + mFound = false; +} + +bool Traverser::visitUnary(Visit visit, TIntermUnary *node) +{ + if (mFound) + { + return false; + } + + // Decide if the current unary operator is unary minus. + if (node->getOp() != EOpNegative) + { + return true; + } + + // Decide if the current operand is an integer variable. + TIntermTyped *opr = node->getOperand(); + if (!opr->getType().isScalarInt()) + { + return true; + } + + // Potential problem case detected, apply workaround: -(int) -> ~(int) + 1. + // ~(int) + TIntermUnary *bitwiseNot = new TIntermUnary(EOpBitwiseNot, opr, nullptr); + bitwiseNot->setLine(opr->getLine()); + + // Constant 1 (or 1u) + TConstantUnion *one = new TConstantUnion(); + if (opr->getType().getBasicType() == EbtInt) + { + one->setIConst(1); + } + else + { + one->setUConst(1u); + } + TType *oneType = new TType(opr->getType()); + oneType->setQualifier(EvqConst); + + TIntermConstantUnion *oneNode = new TIntermConstantUnion(one, *oneType); + oneNode->setLine(opr->getLine()); + + // ~(int) + 1 + TIntermBinary *add = new TIntermBinary(EOpAdd, bitwiseNot, oneNode); + add->setLine(opr->getLine()); + + queueReplacement(add, OriginalNode::IS_DROPPED); + + mFound = true; + return false; +} + +} // anonymous namespace + +bool RewriteUnaryMinusOperatorInt(TCompiler *compiler, TIntermNode *root) +{ + return Traverser::Apply(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteUnaryMinusOperatorInt.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteUnaryMinusOperatorInt.h new file mode 100644 index 0000000000..cc5ac86456 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/RewriteUnaryMinusOperatorInt.h @@ -0,0 +1,23 @@ +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// This mutating tree traversal works around a bug on evaluating unary +// integer variable on Intel D3D driver. It works by rewriting -(int) to +// ~(int) + 1 when evaluating unary integer variables. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_REWRITEUNARYMINUSOPERATORINT_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_REWRITEUNARYMINUSOPERATORINT_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermNode; + +[[nodiscard]] bool RewriteUnaryMinusOperatorInt(TCompiler *compiler, TIntermNode *root); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_REWRITEUNARYMINUSOPERATORINT_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayConstructorStatements.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayConstructorStatements.cpp new file mode 100644 index 0000000000..170b29acd7 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayConstructorStatements.cpp @@ -0,0 +1,83 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SeparateArrayConstructorStatements splits statements that are array constructors and drops all of +// their constant arguments. For example, a statement like: +// int[2](0, i++); +// Will be changed to: +// i++; + +#include "compiler/translator/tree_ops/d3d/SeparateArrayConstructorStatements.h" + +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +void SplitConstructorArgs(const TIntermSequence &originalArgs, TIntermSequence *argsOut) +{ + for (TIntermNode *arg : originalArgs) + { + TIntermTyped *argTyped = arg->getAsTyped(); + if (argTyped->hasSideEffects()) + { + TIntermAggregate *argAggregate = argTyped->getAsAggregate(); + if (argTyped->isArray() && argAggregate && argAggregate->isConstructor()) + { + SplitConstructorArgs(*argAggregate->getSequence(), argsOut); + } + else + { + argsOut->push_back(argTyped); + } + } + } +} + +class SeparateArrayConstructorStatementsTraverser : public TIntermTraverser +{ + public: + SeparateArrayConstructorStatementsTraverser(); + + bool visitAggregate(Visit visit, TIntermAggregate *node) override; +}; + +SeparateArrayConstructorStatementsTraverser::SeparateArrayConstructorStatementsTraverser() + : TIntermTraverser(true, false, false) +{} + +bool SeparateArrayConstructorStatementsTraverser::visitAggregate(Visit visit, + TIntermAggregate *node) +{ + TIntermBlock *parentAsBlock = getParentNode()->getAsBlock(); + if (!parentAsBlock) + { + return false; + } + if (!node->isArray() || !node->isConstructor()) + { + return false; + } + + TIntermSequence constructorArgs; + SplitConstructorArgs(*node->getSequence(), &constructorArgs); + mMultiReplacements.emplace_back(parentAsBlock, node, std::move(constructorArgs)); + + return false; +} + +} // namespace + +bool SeparateArrayConstructorStatements(TCompiler *compiler, TIntermBlock *root) +{ + SeparateArrayConstructorStatementsTraverser traverser; + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayConstructorStatements.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayConstructorStatements.h new file mode 100644 index 0000000000..225a4651da --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayConstructorStatements.h @@ -0,0 +1,25 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SeparateArrayConstructorStatements splits statements that are array constructors and drops all of +// their constant arguments. For example, a statement like: +// int[2](0, i++); +// Will be changed to: +// i++; + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_SEPARATEARRAYCONSTRUCTORSTATEMENTS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_SEPARATEARRAYCONSTRUCTORSTATEMENTS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; + +[[nodiscard]] bool SeparateArrayConstructorStatements(TCompiler *compiler, TIntermBlock *root); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_SEPARATEARRAYCONSTRUCTORSTATEMENTS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayInitialization.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayInitialization.cpp new file mode 100644 index 0000000000..de5c393cf6 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayInitialization.cpp @@ -0,0 +1,89 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// The SeparateArrayInitialization function splits each array initialization into a declaration and +// an assignment. +// Example: +// type[n] a = initializer; +// will effectively become +// type[n] a; +// a = initializer; +// +// Note that if the array is declared as const, the initialization may still be split, making the +// AST technically invalid. Because of that this transformation should only be used when subsequent +// stages don't care about const qualifiers. However, the initialization will not be split if the +// initializer can be written as a HLSL literal. + +#include "compiler/translator/tree_ops/d3d/SeparateArrayInitialization.h" + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/OutputHLSL.h" + +namespace sh +{ + +namespace +{ + +class SeparateArrayInitTraverser : private TIntermTraverser +{ + public: + [[nodiscard]] static bool apply(TCompiler *compiler, TIntermNode *root); + + private: + SeparateArrayInitTraverser(); + bool visitDeclaration(Visit, TIntermDeclaration *node) override; +}; + +bool SeparateArrayInitTraverser::apply(TCompiler *compiler, TIntermNode *root) +{ + SeparateArrayInitTraverser separateInit; + root->traverse(&separateInit); + return separateInit.updateTree(compiler, root); +} + +SeparateArrayInitTraverser::SeparateArrayInitTraverser() : TIntermTraverser(true, false, false) {} + +bool SeparateArrayInitTraverser::visitDeclaration(Visit, TIntermDeclaration *node) +{ + TIntermSequence *sequence = node->getSequence(); + TIntermBinary *initNode = sequence->back()->getAsBinaryNode(); + if (initNode != nullptr && initNode->getOp() == EOpInitialize) + { + TIntermTyped *initializer = initNode->getRight(); + if (initializer->isArray() && !initializer->hasConstantValue()) + { + // We rely on that array declarations have been isolated to single declarations. + ASSERT(sequence->size() == 1); + TIntermTyped *symbol = initNode->getLeft(); + TIntermBlock *parentBlock = getParentNode()->getAsBlock(); + ASSERT(parentBlock != nullptr); + + TIntermSequence replacements; + + TIntermDeclaration *replacementDeclaration = new TIntermDeclaration(); + replacementDeclaration->appendDeclarator(symbol); + replacementDeclaration->setLine(symbol->getLine()); + replacements.push_back(replacementDeclaration); + + TIntermBinary *replacementAssignment = + new TIntermBinary(EOpAssign, symbol, initializer); + replacementAssignment->setLine(symbol->getLine()); + replacements.push_back(replacementAssignment); + + mMultiReplacements.emplace_back(parentBlock, node, std::move(replacements)); + } + } + return false; +} + +} // namespace + +bool SeparateArrayInitialization(TCompiler *compiler, TIntermNode *root) +{ + return SeparateArrayInitTraverser::apply(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayInitialization.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayInitialization.h new file mode 100644 index 0000000000..e83554186a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayInitialization.h @@ -0,0 +1,32 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// The SeparateArrayInitialization function splits each array initialization into a declaration and +// an assignment. +// Example: +// type[n] a = initializer; +// will effectively become +// type[n] a; +// a = initializer; +// +// Note that if the array is declared as const, the initialization may still be split, making the +// AST technically invalid. Because of that this transformation should only be used when subsequent +// stages don't care about const qualifiers. However, the initialization will not be split if the +// initializer can be written as a HLSL literal. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_SEPARATEARRAYINITIALIZATION_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_SEPARATEARRAYINITIALIZATION_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermNode; + +[[nodiscard]] bool SeparateArrayInitialization(TCompiler *compiler, TIntermNode *root); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_SEPARATEARRAYINITIALIZATION_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateExpressionsReturningArrays.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateExpressionsReturningArrays.cpp new file mode 100644 index 0000000000..58d8a0a9be --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateExpressionsReturningArrays.cpp @@ -0,0 +1,138 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SeparateExpressionsReturningArrays splits array-returning expressions that are not array names +// from more complex expressions, assigning them to a temporary variable a#. +// Examples where a, b and c are all arrays: +// (a = b) == (a = c) is split into a = b; type[n] a1 = a; a = c; type[n] a2 = a; a1 == a2; +// type d = type[n](...)[i]; is split into type[n] a1 = type[n](...); type d = a1[i]; + +#include "compiler/translator/tree_ops/d3d/SeparateExpressionsReturningArrays.h" + +#include "compiler/translator/tree_util/IntermNodePatternMatcher.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +// Traverser that separates one array expression into a statement at a time. +class SeparateExpressionsTraverser : public TIntermTraverser +{ + public: + SeparateExpressionsTraverser(TSymbolTable *symbolTable); + + bool visitBinary(Visit visit, TIntermBinary *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + + void nextIteration(); + bool foundArrayExpression() const { return mFoundArrayExpression; } + + protected: + // Marked to true once an operation that needs to be hoisted out of the expression has been + // found. After that, no more AST updates are performed on that traversal. + bool mFoundArrayExpression; + + IntermNodePatternMatcher mPatternToSeparateMatcher; +}; + +SeparateExpressionsTraverser::SeparateExpressionsTraverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, false, false, symbolTable), + mFoundArrayExpression(false), + mPatternToSeparateMatcher(IntermNodePatternMatcher::kExpressionReturningArray) +{} + +// Performs a shallow copy of an assignment node. +// These shallow copies are useful when a node gets inserted into an aggregate node +// and also needs to be replaced in its original location by a different node. +TIntermBinary *CopyAssignmentNode(TIntermBinary *node) +{ + return new TIntermBinary(node->getOp(), node->getLeft(), node->getRight()); +} + +bool SeparateExpressionsTraverser::visitBinary(Visit visit, TIntermBinary *node) +{ + if (mFoundArrayExpression) + return false; + + // Return if the expression is not an array or if we're not inside a complex expression. + if (!mPatternToSeparateMatcher.match(node, getParentNode())) + return true; + + ASSERT(node->getOp() == EOpAssign); + + mFoundArrayExpression = true; + + TIntermSequence insertions; + insertions.push_back(CopyAssignmentNode(node)); + // TODO(oetuaho): In some cases it would be more optimal to not add the temporary node, but just + // use the original target of the assignment. Care must be taken so that this doesn't happen + // when the same array symbol is a target of assignment more than once in one expression. + TIntermDeclaration *arrayVariableDeclaration; + TVariable *arrayVariable = + DeclareTempVariable(mSymbolTable, node->getLeft(), EvqTemporary, &arrayVariableDeclaration); + insertions.push_back(arrayVariableDeclaration); + insertStatementsInParentBlock(insertions); + + queueReplacement(CreateTempSymbolNode(arrayVariable), OriginalNode::IS_DROPPED); + + return false; +} + +bool SeparateExpressionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + if (mFoundArrayExpression) + return false; // No need to traverse further + + if (!mPatternToSeparateMatcher.match(node, getParentNode())) + return true; + + ASSERT(node->isConstructor() || node->getOp() == EOpCallFunctionInAST); + + mFoundArrayExpression = true; + + TIntermDeclaration *arrayVariableDeclaration; + TVariable *arrayVariable = DeclareTempVariable(mSymbolTable, node->shallowCopy(), EvqTemporary, + &arrayVariableDeclaration); + insertStatementInParentBlock(arrayVariableDeclaration); + + queueReplacement(CreateTempSymbolNode(arrayVariable), OriginalNode::IS_DROPPED); + + return false; +} + +void SeparateExpressionsTraverser::nextIteration() +{ + mFoundArrayExpression = false; +} + +} // namespace + +bool SeparateExpressionsReturningArrays(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable) +{ + SeparateExpressionsTraverser traverser(symbolTable); + // Separate one expression at a time, and reset the traverser between iterations. + do + { + traverser.nextIteration(); + root->traverse(&traverser); + if (traverser.foundArrayExpression()) + { + if (!traverser.updateTree(compiler, root)) + { + return false; + } + } + } while (traverser.foundArrayExpression()); + + return true; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateExpressionsReturningArrays.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateExpressionsReturningArrays.h new file mode 100644 index 0000000000..6a9350d89a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateExpressionsReturningArrays.h @@ -0,0 +1,28 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SeparateExpressionsReturningArrays splits array-returning expressions that are not array names +// from more complex expressions, assigning them to a temporary variable a#. +// Examples where a, b and c are all arrays: +// (a = b) == (a = c) is split into a = b; type[n] a1 = a; a = c; type[n] a2 = a; a1 == a2; +// type d = type[n](...)[i]; is split into type[n] a1 = type[n](...); type d = a1[i]; + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermNode; +class TSymbolTable; + +[[nodiscard]] bool SeparateExpressionsReturningArrays(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/UnfoldShortCircuitToIf.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/UnfoldShortCircuitToIf.cpp new file mode 100644 index 0000000000..5b104c4889 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/UnfoldShortCircuitToIf.cpp @@ -0,0 +1,200 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// UnfoldShortCircuitToIf is an AST traverser to convert short-circuiting operators to if-else +// statements. +// The results are assigned to s# temporaries, which are used by the main translator instead of +// the original expression. +// + +#include "compiler/translator/tree_ops/d3d/UnfoldShortCircuitToIf.h" + +#include "compiler/translator/StaticType.h" +#include "compiler/translator/tree_util/IntermNodePatternMatcher.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +// Traverser that unfolds one short-circuiting operation at a time. +class UnfoldShortCircuitTraverser : public TIntermTraverser +{ + public: + UnfoldShortCircuitTraverser(TSymbolTable *symbolTable); + + bool visitBinary(Visit visit, TIntermBinary *node) override; + bool visitTernary(Visit visit, TIntermTernary *node) override; + + void nextIteration(); + bool foundShortCircuit() const { return mFoundShortCircuit; } + + protected: + // Marked to true once an operation that needs to be unfolded has been found. + // After that, no more unfolding is performed on that traversal. + bool mFoundShortCircuit; + + IntermNodePatternMatcher mPatternToUnfoldMatcher; +}; + +UnfoldShortCircuitTraverser::UnfoldShortCircuitTraverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, false, true, symbolTable), + mFoundShortCircuit(false), + mPatternToUnfoldMatcher(IntermNodePatternMatcher::kUnfoldedShortCircuitExpression) +{} + +bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node) +{ + if (mFoundShortCircuit) + return false; + + if (visit != PreVisit) + return true; + + if (!mPatternToUnfoldMatcher.match(node, getParentNode())) + return true; + + // If our right node doesn't have side effects, we know we don't need to unfold this + // expression: there will be no short-circuiting side effects to avoid + // (note: unfolding doesn't depend on the left node -- it will always be evaluated) + ASSERT(node->getRight()->hasSideEffects()); + + mFoundShortCircuit = true; + + switch (node->getOp()) + { + case EOpLogicalOr: + { + // "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true; + // else s = y;", + // and then further simplifies down to "bool s = x; if(!s) s = y;". + + TIntermSequence insertions; + const TType *boolType = StaticType::Get(); + TVariable *resultVariable = CreateTempVariable(mSymbolTable, boolType); + + ASSERT(node->getLeft()->getType() == *boolType); + insertions.push_back(CreateTempInitDeclarationNode(resultVariable, node->getLeft())); + + TIntermBlock *assignRightBlock = new TIntermBlock(); + ASSERT(node->getRight()->getType() == *boolType); + assignRightBlock->getSequence()->push_back( + CreateTempAssignmentNode(resultVariable, node->getRight())); + + TIntermUnary *notTempSymbol = + new TIntermUnary(EOpLogicalNot, CreateTempSymbolNode(resultVariable), nullptr); + TIntermIfElse *ifNode = new TIntermIfElse(notTempSymbol, assignRightBlock, nullptr); + insertions.push_back(ifNode); + + insertStatementsInParentBlock(insertions); + + queueReplacement(CreateTempSymbolNode(resultVariable), OriginalNode::IS_DROPPED); + return false; + } + case EOpLogicalAnd: + { + // "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y; + // else s = false;", + // and then further simplifies down to "bool s = x; if(s) s = y;". + TIntermSequence insertions; + const TType *boolType = StaticType::Get(); + TVariable *resultVariable = CreateTempVariable(mSymbolTable, boolType); + + ASSERT(node->getLeft()->getType() == *boolType); + insertions.push_back(CreateTempInitDeclarationNode(resultVariable, node->getLeft())); + + TIntermBlock *assignRightBlock = new TIntermBlock(); + ASSERT(node->getRight()->getType() == *boolType); + assignRightBlock->getSequence()->push_back( + CreateTempAssignmentNode(resultVariable, node->getRight())); + + TIntermIfElse *ifNode = + new TIntermIfElse(CreateTempSymbolNode(resultVariable), assignRightBlock, nullptr); + insertions.push_back(ifNode); + + insertStatementsInParentBlock(insertions); + + queueReplacement(CreateTempSymbolNode(resultVariable), OriginalNode::IS_DROPPED); + return false; + } + default: + UNREACHABLE(); + return true; + } +} + +bool UnfoldShortCircuitTraverser::visitTernary(Visit visit, TIntermTernary *node) +{ + if (mFoundShortCircuit) + return false; + + if (visit != PreVisit) + return true; + + if (!mPatternToUnfoldMatcher.match(node)) + return true; + + mFoundShortCircuit = true; + + // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;" + TIntermSequence insertions; + TIntermDeclaration *tempDeclaration = nullptr; + TVariable *resultVariable = DeclareTempVariable(mSymbolTable, new TType(node->getType()), + EvqTemporary, &tempDeclaration); + insertions.push_back(tempDeclaration); + + TIntermBlock *trueBlock = new TIntermBlock(); + TIntermBinary *trueAssignment = + CreateTempAssignmentNode(resultVariable, node->getTrueExpression()); + trueBlock->getSequence()->push_back(trueAssignment); + + TIntermBlock *falseBlock = new TIntermBlock(); + TIntermBinary *falseAssignment = + CreateTempAssignmentNode(resultVariable, node->getFalseExpression()); + falseBlock->getSequence()->push_back(falseAssignment); + + TIntermIfElse *ifNode = + new TIntermIfElse(node->getCondition()->getAsTyped(), trueBlock, falseBlock); + insertions.push_back(ifNode); + + insertStatementsInParentBlock(insertions); + + TIntermSymbol *ternaryResult = CreateTempSymbolNode(resultVariable); + queueReplacement(ternaryResult, OriginalNode::IS_DROPPED); + + return false; +} + +void UnfoldShortCircuitTraverser::nextIteration() +{ + mFoundShortCircuit = false; +} + +} // namespace + +bool UnfoldShortCircuitToIf(TCompiler *compiler, TIntermNode *root, TSymbolTable *symbolTable) +{ + UnfoldShortCircuitTraverser traverser(symbolTable); + // Unfold one operator at a time, and reset the traverser between iterations. + do + { + traverser.nextIteration(); + root->traverse(&traverser); + if (traverser.foundShortCircuit()) + { + if (!traverser.updateTree(compiler, root)) + { + return false; + } + } + } while (traverser.foundShortCircuit()); + + return true; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/UnfoldShortCircuitToIf.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/UnfoldShortCircuitToIf.h new file mode 100644 index 0000000000..97587e4d38 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/UnfoldShortCircuitToIf.h @@ -0,0 +1,30 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// UnfoldShortCircuitToIf is an AST traverser to convert short-circuiting operators to if-else +// statements. +// The results are assigned to s# temporaries, which are used by the main translator instead of +// the original expression. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_UNFOLDSHORTCIRCUIT_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_UNFOLDSHORTCIRCUIT_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermNode; +class TSymbolTable; + +[[nodiscard]] bool UnfoldShortCircuitToIf(TCompiler *compiler, + TIntermNode *root, + TSymbolTable *symbolTable); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_UNFOLDSHORTCIRCUIT_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/WrapSwitchStatementsInBlocks.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/WrapSwitchStatementsInBlocks.cpp new file mode 100644 index 0000000000..58a941da0e --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/WrapSwitchStatementsInBlocks.cpp @@ -0,0 +1,126 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// WrapSwitchStatementsInBlocks.cpp: Wrap switch statements in blocks and declare all switch-scoped +// variables there to make the AST compatible with HLSL output. +// +// switch (init) +// { +// case 0: +// float f; +// default: +// f = 1.0; +// } +// +// becomes +// +// { +// float f; +// switch (init) +// { +// case 0: +// default: +// f = 1.0; +// } +// } + +#include "compiler/translator/tree_ops/d3d/WrapSwitchStatementsInBlocks.h" + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class WrapSwitchStatementsInBlocksTraverser : public TIntermTraverser +{ + public: + WrapSwitchStatementsInBlocksTraverser() : TIntermTraverser(true, false, false) {} + + bool visitSwitch(Visit visit, TIntermSwitch *node) override; +}; + +bool WrapSwitchStatementsInBlocksTraverser::visitSwitch(Visit, TIntermSwitch *node) +{ + std::vector declarations; + TIntermSequence *statementList = node->getStatementList()->getSequence(); + for (TIntermNode *statement : *statementList) + { + TIntermDeclaration *asDeclaration = statement->getAsDeclarationNode(); + if (asDeclaration) + { + declarations.push_back(asDeclaration); + } + } + if (declarations.empty()) + { + // We don't need to wrap the switch if it doesn't contain declarations as its direct + // descendants. + return true; + } + + TIntermBlock *wrapperBlock = new TIntermBlock(); + for (TIntermDeclaration *declaration : declarations) + { + // SeparateDeclarations should have already been run. + ASSERT(declaration->getSequence()->size() == 1); + + TIntermDeclaration *declarationInBlock = new TIntermDeclaration(); + TIntermSymbol *declaratorAsSymbol = declaration->getSequence()->at(0)->getAsSymbolNode(); + if (declaratorAsSymbol) + { + // This is a simple declaration like: "float f;" + // Remove the declaration from inside the switch and put it in the wrapping block. + TIntermSequence emptyReplacement; + mMultiReplacements.emplace_back(node->getStatementList(), declaration, + std::move(emptyReplacement)); + + declarationInBlock->appendDeclarator(declaratorAsSymbol->deepCopy()); + // The declaration can't be the last statement inside the switch since unused variables + // should already have been pruned. + ASSERT(declaration != statementList->back()); + } + else + { + // This is an init declaration like: "float f = 0.0;" + // Change the init declaration inside the switch into an assignment and put a plain + // declaration in the wrapping block. + TIntermBinary *declaratorAsBinary = + declaration->getSequence()->at(0)->getAsBinaryNode(); + ASSERT(declaratorAsBinary); + + TIntermBinary *initAssignment = new TIntermBinary( + EOpAssign, declaratorAsBinary->getLeft(), declaratorAsBinary->getRight()); + + queueReplacementWithParent(node->getStatementList(), declaration, initAssignment, + OriginalNode::IS_DROPPED); + + declarationInBlock->appendDeclarator(declaratorAsBinary->getLeft()->deepCopy()); + } + wrapperBlock->appendStatement(declarationInBlock); + } + + wrapperBlock->appendStatement(node); + queueReplacement(wrapperBlock, OriginalNode::BECOMES_CHILD); + + // Should be fine to process multiple switch statements, even nesting ones in the same + // traversal. + return true; +} + +} // anonymous namespace + +// Wrap switch statements in the AST into blocks when needed. +bool WrapSwitchStatementsInBlocks(TCompiler *compiler, TIntermBlock *root) +{ + WrapSwitchStatementsInBlocksTraverser traverser; + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/WrapSwitchStatementsInBlocks.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/WrapSwitchStatementsInBlocks.h new file mode 100644 index 0000000000..0c765c306a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/WrapSwitchStatementsInBlocks.h @@ -0,0 +1,25 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// WrapSwitchStatementsInBlocks.h: Wrap switch statements in blocks and declare all switch-scoped +// variables there to make the AST compatible with HLSL output. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_D3D_WRAPSWITCHSTATEMENTSINBLOCKS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_D3D_WRAPSWITCHSTATEMENTSINBLOCKS_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; + +// Wrap switch statements in the AST into blocks when needed. Returns true if the AST was changed. +[[nodiscard]] bool WrapSwitchStatementsInBlocks(TCompiler *compiler, TIntermBlock *root); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_D3D_WRAPSWITCHSTATEMENTSINBLOCKS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/ClampFragDepth.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/ClampFragDepth.cpp new file mode 100644 index 0000000000..309cb14752 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/ClampFragDepth.cpp @@ -0,0 +1,54 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ClampFragDepth.cpp: Limit the value that is written to gl_FragDepth to the range [0.0, 1.0]. +// The clamping is run at the very end of shader execution, and is only performed if the shader +// statically accesses gl_FragDepth. +// + +#include "compiler/translator/tree_ops/gl/ClampFragDepth.h" + +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/BuiltIn.h" +#include "compiler/translator/tree_util/FindSymbolNode.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/RunAtTheEndOfShader.h" + +namespace sh +{ + +bool ClampFragDepth(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable) +{ + // Only clamp gl_FragDepth if it's used in the shader. + if (!FindSymbolNode(root, ImmutableString("gl_FragDepth"))) + { + return true; + } + + TIntermSymbol *fragDepthNode = new TIntermSymbol(BuiltInVariable::gl_FragDepth()); + + TIntermTyped *minFragDepthNode = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); + + TConstantUnion *maxFragDepthConstant = new TConstantUnion(); + maxFragDepthConstant->setFConst(1.0); + TIntermConstantUnion *maxFragDepthNode = + new TIntermConstantUnion(maxFragDepthConstant, TType(EbtFloat, EbpHigh, EvqConst)); + + // clamp(gl_FragDepth, 0.0, 1.0) + TIntermSequence clampArguments; + clampArguments.push_back(fragDepthNode->deepCopy()); + clampArguments.push_back(minFragDepthNode); + clampArguments.push_back(maxFragDepthNode); + TIntermTyped *clampedFragDepth = + CreateBuiltInFunctionCallNode("clamp", &clampArguments, *symbolTable, 100); + + // gl_FragDepth = clamp(gl_FragDepth, 0.0, 1.0) + TIntermBinary *assignFragDepth = new TIntermBinary(EOpAssign, fragDepthNode, clampedFragDepth); + + return RunAtTheEndOfShader(compiler, root, assignFragDepth, symbolTable); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/ClampFragDepth.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/ClampFragDepth.h new file mode 100644 index 0000000000..70326c9a34 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/ClampFragDepth.h @@ -0,0 +1,39 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ClampFragDepth.h: Limit the value that is written to gl_FragDepth to the range [0.0, 1.0]. +// The clamping is run at the very end of shader execution, and is only performed if the shader +// statically accesses gl_FragDepth. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_GL_CLAMPFRAGDEPTH_H_ +#define COMPILER_TRANSLATOR_TREEOPS_GL_CLAMPFRAGDEPTH_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +#ifdef ANGLE_ENABLE_GLSL +[[nodiscard]] bool ClampFragDepth(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); +#else +[[nodiscard]] ANGLE_INLINE bool ClampFragDepth(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable) +{ + UNREACHABLE(); + return false; +} +#endif + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_GL_CLAMPFRAGDEPTH_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RegenerateStructNames.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RegenerateStructNames.cpp new file mode 100644 index 0000000000..e15ef32166 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RegenerateStructNames.cpp @@ -0,0 +1,119 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/tree_ops/gl/RegenerateStructNames.h" + +#include "common/debug.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +#include + +namespace sh +{ + +namespace +{ +constexpr const ImmutableString kPrefix("_webgl_struct_"); +} // anonymous namespace + +class RegenerateStructNamesTraverser : public TIntermTraverser +{ + public: + RegenerateStructNamesTraverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, false, false, symbolTable), mScopeDepth(0) + {} + + protected: + void visitSymbol(TIntermSymbol *) override; + bool visitBlock(Visit, TIntermBlock *block) override; + + private: + // Indicating the depth of the current scope. + // The global scope is 1. + int mScopeDepth; + + // If a struct is declared globally, push its ID in this set. + std::set mDeclaredGlobalStructs; +}; + +void RegenerateStructNamesTraverser::visitSymbol(TIntermSymbol *symbol) +{ + ASSERT(symbol); + const TType &type = symbol->getType(); + const TStructure *userType = type.getStruct(); + if (!userType) + return; + + if (userType->symbolType() == SymbolType::BuiltIn || + userType->symbolType() == SymbolType::Empty) + { + // Built-in struct or nameless struct, do not touch it. + return; + } + + int uniqueId = userType->uniqueId().get(); + + ASSERT(mScopeDepth > 0); + if (mScopeDepth == 1) + { + // If a struct is defined at global scope, we don't map its name. + // This is because at global level, the struct might be used to + // declare a uniform, so the same name needs to stay the same for + // vertex/fragment shaders. However, our mapping uses internal ID, + // which will be different for the same struct in vertex/fragment + // shaders. + // This is OK because names for any structs defined in other scopes + // will begin with "_webgl", which is reserved. So there will be + // no conflicts among unmapped struct names from global scope and + // mapped struct names from other scopes. + // However, we need to keep track of these global structs, so if a + // variable is used in a local scope, we don't try to modify the + // struct name through that variable. + mDeclaredGlobalStructs.insert(uniqueId); + return; + } + if (mDeclaredGlobalStructs.count(uniqueId) > 0) + return; + // Map {name} to _webgl_struct_{uniqueId}_{name}. + if (userType->name().beginsWith(kPrefix)) + { + // The name has already been regenerated. + return; + } + ImmutableStringBuilder tmp(kPrefix.length() + sizeof(uniqueId) * 2u + 1u + + userType->name().length()); + tmp << kPrefix; + tmp.appendHex(uniqueId); + tmp << '_' << userType->name(); + + // TODO(oetuaho): Add another mechanism to change symbol names so that the const_cast is not + // needed. + const_cast(userType)->setName(tmp); +} + +bool RegenerateStructNamesTraverser::visitBlock(Visit, TIntermBlock *block) +{ + ++mScopeDepth; + TIntermSequence &sequence = *(block->getSequence()); + for (TIntermNode *node : sequence) + { + node->traverse(this); + } + --mScopeDepth; + return false; +} + +bool RegenerateStructNames(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable) +{ + RegenerateStructNamesTraverser traverser(symbolTable); + root->traverse(&traverser); + return compiler->validateAST(root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RegenerateStructNames.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RegenerateStructNames.h new file mode 100644 index 0000000000..04cfe6a476 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RegenerateStructNames.h @@ -0,0 +1,34 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TREEOPS_GL_REGENERATESTRUCTNAMES_H_ +#define COMPILER_TRANSLATOR_TREEOPS_GL_REGENERATESTRUCTNAMES_H_ + +#include "common/angleutils.h" + +namespace sh +{ +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +#if defined(ANGLE_ENABLE_GLSL) +[[nodiscard]] bool RegenerateStructNames(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); +#else +[[nodiscard]] ANGLE_INLINE bool RegenerateStructNames(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable) +{ + UNREACHABLE(); + return false; +} +#endif + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_GL_REGENERATESTRUCTNAMES_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RewriteRepeatedAssignToSwizzled.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RewriteRepeatedAssignToSwizzled.cpp new file mode 100644 index 0000000000..83a0f029b8 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RewriteRepeatedAssignToSwizzled.cpp @@ -0,0 +1,97 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteRepeatedAssignToSwizzled.cpp: Rewrite expressions that assign an assignment to a swizzled +// vector, like: +// v.x = z = expression; +// to: +// z = expression; +// v.x = z; +// +// Note that this doesn't handle some corner cases: expressions nested inside other expressions, +// inside loop headers, or inside if conditions. + +#include "compiler/translator/tree_ops/gl/RewriteRepeatedAssignToSwizzled.h" + +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class RewriteAssignToSwizzledTraverser : public TIntermTraverser +{ + public: + [[nodiscard]] static bool rewrite(TCompiler *compiler, TIntermBlock *root); + + private: + RewriteAssignToSwizzledTraverser(); + + bool visitBinary(Visit, TIntermBinary *node) override; + + void nextIteration(); + + bool didRewrite() { return mDidRewrite; } + + bool mDidRewrite; +}; + +// static +bool RewriteAssignToSwizzledTraverser::rewrite(TCompiler *compiler, TIntermBlock *root) +{ + RewriteAssignToSwizzledTraverser rewrite; + do + { + rewrite.nextIteration(); + root->traverse(&rewrite); + if (!rewrite.updateTree(compiler, root)) + { + return false; + } + } while (rewrite.didRewrite()); + + return true; +} + +RewriteAssignToSwizzledTraverser::RewriteAssignToSwizzledTraverser() + : TIntermTraverser(true, false, false), mDidRewrite(false) +{} + +void RewriteAssignToSwizzledTraverser::nextIteration() +{ + mDidRewrite = false; +} + +bool RewriteAssignToSwizzledTraverser::visitBinary(Visit, TIntermBinary *node) +{ + TIntermBinary *rightBinary = node->getRight()->getAsBinaryNode(); + TIntermBlock *parentBlock = getParentNode()->getAsBlock(); + if (parentBlock && node->isAssignment() && node->getLeft()->getAsSwizzleNode() && rightBinary && + rightBinary->isAssignment()) + { + TIntermSequence replacements; + replacements.push_back(rightBinary); + TIntermTyped *rightAssignmentTargetCopy = rightBinary->getLeft()->deepCopy(); + TIntermBinary *lastAssign = + new TIntermBinary(EOpAssign, node->getLeft(), rightAssignmentTargetCopy); + replacements.push_back(lastAssign); + mMultiReplacements.emplace_back(parentBlock, node, std::move(replacements)); + mDidRewrite = true; + return false; + } + return true; +} + +} // anonymous namespace + +bool RewriteRepeatedAssignToSwizzled(TCompiler *compiler, TIntermBlock *root) +{ + return RewriteAssignToSwizzledTraverser::rewrite(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RewriteRepeatedAssignToSwizzled.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RewriteRepeatedAssignToSwizzled.h new file mode 100644 index 0000000000..1ab9b7ebb8 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/RewriteRepeatedAssignToSwizzled.h @@ -0,0 +1,40 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteRepeatedAssignToSwizzled.h: Rewrite expressions that assign an assignment to a swizzled +// vector, like: +// v.x = z = expression; +// to: +// z = expression; +// v.x = z; +// +// Note that this doesn't handle some corner cases: expressions nested inside other expressions, +// inside loop headers, or inside if conditions. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_GL_REWRITEREPEATEDASSIGNTOSWIZZLED_H_ +#define COMPILER_TRANSLATOR_TREEOPS_GL_REWRITEREPEATEDASSIGNTOSWIZZLED_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; + +#ifdef ANGLE_ENABLE_GLSL +[[nodiscard]] bool RewriteRepeatedAssignToSwizzled(TCompiler *compiler, TIntermBlock *root); +#else +[[nodiscard]] ANGLE_INLINE bool RewriteRepeatedAssignToSwizzled(TCompiler *compiler, + TIntermBlock *root) +{ + UNREACHABLE(); + return false; +} +#endif + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_GL_REWRITEREPEATEDASSIGNTOSWIZZLED_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/UseInterfaceBlockFields.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/UseInterfaceBlockFields.cpp new file mode 100644 index 0000000000..e94ca2fd17 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/UseInterfaceBlockFields.cpp @@ -0,0 +1,108 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// UseInterfaceBlockFields.cpp: insert statements to reference all members in InterfaceBlock list at +// the beginning of main. This is to work around a Mac driver that treats unused standard/shared +// uniform blocks as inactive. + +#include "compiler/translator/tree_ops/gl/UseInterfaceBlockFields.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/FindMain.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +void AddNodeUseStatements(TIntermTyped *node, TIntermSequence *sequence) +{ + if (node->isArray()) + { + for (unsigned int i = 0u; i < node->getOutermostArraySize(); ++i) + { + TIntermBinary *element = + new TIntermBinary(EOpIndexDirect, node->deepCopy(), CreateIndexNode(i)); + AddNodeUseStatements(element, sequence); + } + } + else + { + sequence->insert(sequence->begin(), node); + } +} + +void AddFieldUseStatements(const ShaderVariable &var, + TIntermSequence *sequence, + const TSymbolTable &symbolTable) +{ + ASSERT(var.name.find_last_of('[') == std::string::npos); + TIntermSymbol *symbol = ReferenceGlobalVariable(ImmutableString(var.name), symbolTable); + AddNodeUseStatements(symbol, sequence); +} + +void InsertUseCode(const InterfaceBlock &block, TIntermTyped *blockNode, TIntermSequence *sequence) +{ + for (unsigned int i = 0; i < block.fields.size(); ++i) + { + TIntermBinary *element = new TIntermBinary(EOpIndexDirectInterfaceBlock, + blockNode->deepCopy(), CreateIndexNode(i)); + sequence->insert(sequence->begin(), element); + } +} + +void InsertUseCode(TIntermSequence *sequence, + const InterfaceBlockList &blocks, + const TSymbolTable &symbolTable) +{ + for (const auto &block : blocks) + { + if (block.instanceName.empty()) + { + for (const auto &var : block.fields) + { + AddFieldUseStatements(var, sequence, symbolTable); + } + } + else if (block.arraySize > 0u) + { + TIntermSymbol *arraySymbol = + ReferenceGlobalVariable(ImmutableString(block.instanceName), symbolTable); + for (unsigned int i = 0u; i < block.arraySize; ++i) + { + TIntermBinary *elementSymbol = + new TIntermBinary(EOpIndexDirect, arraySymbol->deepCopy(), CreateIndexNode(i)); + InsertUseCode(block, elementSymbol, sequence); + } + } + else + { + TIntermSymbol *blockSymbol = + ReferenceGlobalVariable(ImmutableString(block.instanceName), symbolTable); + InsertUseCode(block, blockSymbol, sequence); + } + } +} + +} // namespace + +bool UseInterfaceBlockFields(TCompiler *compiler, + TIntermBlock *root, + const InterfaceBlockList &blocks, + const TSymbolTable &symbolTable) +{ + TIntermBlock *mainBody = FindMainBody(root); + InsertUseCode(mainBody->getSequence(), blocks, symbolTable); + + return compiler->validateAST(root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/UseInterfaceBlockFields.h b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/UseInterfaceBlockFields.h new file mode 100644 index 0000000000..a4f5f3e5e6 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/gl/UseInterfaceBlockFields.h @@ -0,0 +1,44 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// UseInterfaceBlockFields.h: insert statements to reference all members in InterfaceBlock list at +// the beginning of main. This is to work around a Mac driver that treats unused standard/shared +// uniform blocks as inactive. + +#ifndef COMPILER_TRANSLATOR_TREEOPS_GL_USEINTERFACEBLOCKFIELDS_H_ +#define COMPILER_TRANSLATOR_TREEOPS_GL_USEINTERFACEBLOCKFIELDS_H_ + +#include +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +using InterfaceBlockList = std::vector; + +#ifdef ANGLE_ENABLE_GLSL +[[nodiscard]] bool UseInterfaceBlockFields(TCompiler *compiler, + TIntermBlock *root, + const InterfaceBlockList &blocks, + const TSymbolTable &symbolTable); +#else +[[nodiscard]] ANGLE_INLINE bool UseInterfaceBlockFields(TCompiler *compiler, + TIntermBlock *root, + const InterfaceBlockList &blocks, + const TSymbolTable &symbolTable) +{ + UNREACHABLE(); + return false; +} +#endif + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEOPS_GL_USEINTERFACEBLOCKFIELDS_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/AsNode.h b/gfx/angle/checkout/src/compiler/translator/tree_util/AsNode.h new file mode 100644 index 0000000000..1c6de182d9 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/AsNode.h @@ -0,0 +1,212 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_INTERMASNODE_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_INTERMASNODE_H_ + +#include "common/angleutils.h" +#include "compiler/translator/IntermNode.h" + +#include + +namespace sh +{ + +namespace priv +{ + +template +struct AsNode +{}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermNode *exec(TIntermNode *node) { return node; } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermTyped *exec(TIntermNode *node) + { + return node ? node->getAsTyped() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermSymbol *exec(TIntermNode *node) + { + return node ? node->getAsSymbolNode() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermConstantUnion *exec(TIntermNode *node) + { + return node ? node->getAsConstantUnion() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermFunctionPrototype *exec(TIntermNode *node) + { + return node ? node->getAsFunctionPrototypeNode() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermPreprocessorDirective *exec(TIntermNode *node) + { + return node ? node->getAsPreprocessorDirective() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermSwizzle *exec(TIntermNode *node) + { + return node ? node->getAsSwizzleNode() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermBinary *exec(TIntermNode *node) + { + return node ? node->getAsBinaryNode() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermUnary *exec(TIntermNode *node) + { + return node ? node->getAsUnaryNode() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermTernary *exec(TIntermNode *node) + { + return node ? node->getAsTernaryNode() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermIfElse *exec(TIntermNode *node) + { + return node ? node->getAsIfElseNode() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermSwitch *exec(TIntermNode *node) + { + return node ? node->getAsSwitchNode() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermCase *exec(TIntermNode *node) + { + return node ? node->getAsCaseNode() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermFunctionDefinition *exec(TIntermNode *node) + { + return node ? node->getAsFunctionDefinition() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermAggregate *exec(TIntermNode *node) + { + return node ? node->getAsAggregate() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermBlock *exec(TIntermNode *node) + { + return node ? node->getAsBlock() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermGlobalQualifierDeclaration *exec(TIntermNode *node) + { + return node ? node->getAsGlobalQualifierDeclarationNode() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermDeclaration *exec(TIntermNode *node) + { + return node ? node->getAsDeclarationNode() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermLoop *exec(TIntermNode *node) + { + return node ? node->getAsLoopNode() : nullptr; + } +}; + +template <> +struct AsNode +{ + static ANGLE_INLINE TIntermBranch *exec(TIntermNode *node) + { + return node ? node->getAsBranchNode() : nullptr; + } +}; + +} // namespace priv + +template +ANGLE_INLINE T *asNode(TIntermNode *node) +{ + return priv::AsNode::exec(node); +} + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_INTERMASNODE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/BuiltIn.h b/gfx/angle/checkout/src/compiler/translator/tree_util/BuiltIn.h new file mode 100644 index 0000000000..22c33f9fc0 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/BuiltIn.h @@ -0,0 +1,18 @@ +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// BuiltIn.h: +// Chooses BuiltIn_complete_autogen.h or BuiltIn_ESSL_autogen.h +// depending on whether platform is android + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_H_ + +#if defined(ANDROID) +# include "BuiltIn_ESSL_autogen.h" +#else +# include "BuiltIn_complete_autogen.h" +#endif + +#endif // COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/BuiltIn_ESSL_autogen.h b/gfx/angle/checkout/src/compiler/translator/tree_util/BuiltIn_ESSL_autogen.h new file mode 100644 index 0000000000..5380d82c68 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/BuiltIn_ESSL_autogen.h @@ -0,0 +1,4177 @@ +// GENERATED FILE - DO NOT EDIT. +// Generated by gen_builtin_symbols.py using data from builtin_variables.json and +// builtin_function_declarations.txt. +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// BuiltIn_ESSL_autogen.h: +// Compile-time initialized built-ins. + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_ + +#include "compiler/translator/SymbolUniqueId.h" + +namespace sh +{ + +class TVariable; + +class BuiltInId +{ + public: + static constexpr const TSymbolUniqueId radians_Float1 = TSymbolUniqueId(3086); + static constexpr const TSymbolUniqueId pt00B = TSymbolUniqueId(3087); + static constexpr const TSymbolUniqueId radians_Float2 = TSymbolUniqueId(3088); + static constexpr const TSymbolUniqueId pt10B = TSymbolUniqueId(3089); + static constexpr const TSymbolUniqueId radians_Float3 = TSymbolUniqueId(3090); + static constexpr const TSymbolUniqueId pt20B = TSymbolUniqueId(3091); + static constexpr const TSymbolUniqueId radians_Float4 = TSymbolUniqueId(3092); + static constexpr const TSymbolUniqueId pt30B = TSymbolUniqueId(3093); + static constexpr const TSymbolUniqueId degrees_Float1 = TSymbolUniqueId(3094); + static constexpr const TSymbolUniqueId degrees_Float2 = TSymbolUniqueId(3095); + static constexpr const TSymbolUniqueId degrees_Float3 = TSymbolUniqueId(3096); + static constexpr const TSymbolUniqueId degrees_Float4 = TSymbolUniqueId(3097); + static constexpr const TSymbolUniqueId sin_Float1 = TSymbolUniqueId(3098); + static constexpr const TSymbolUniqueId sin_Float2 = TSymbolUniqueId(3099); + static constexpr const TSymbolUniqueId sin_Float3 = TSymbolUniqueId(3100); + static constexpr const TSymbolUniqueId sin_Float4 = TSymbolUniqueId(3101); + static constexpr const TSymbolUniqueId cos_Float1 = TSymbolUniqueId(3102); + static constexpr const TSymbolUniqueId cos_Float2 = TSymbolUniqueId(3103); + static constexpr const TSymbolUniqueId cos_Float3 = TSymbolUniqueId(3104); + static constexpr const TSymbolUniqueId cos_Float4 = TSymbolUniqueId(3105); + static constexpr const TSymbolUniqueId tan_Float1 = TSymbolUniqueId(3106); + static constexpr const TSymbolUniqueId tan_Float2 = TSymbolUniqueId(3107); + static constexpr const TSymbolUniqueId tan_Float3 = TSymbolUniqueId(3108); + static constexpr const TSymbolUniqueId tan_Float4 = TSymbolUniqueId(3109); + static constexpr const TSymbolUniqueId asin_Float1 = TSymbolUniqueId(3110); + static constexpr const TSymbolUniqueId asin_Float2 = TSymbolUniqueId(3111); + static constexpr const TSymbolUniqueId asin_Float3 = TSymbolUniqueId(3112); + static constexpr const TSymbolUniqueId asin_Float4 = TSymbolUniqueId(3113); + static constexpr const TSymbolUniqueId acos_Float1 = TSymbolUniqueId(3114); + static constexpr const TSymbolUniqueId acos_Float2 = TSymbolUniqueId(3115); + static constexpr const TSymbolUniqueId acos_Float3 = TSymbolUniqueId(3116); + static constexpr const TSymbolUniqueId acos_Float4 = TSymbolUniqueId(3117); + static constexpr const TSymbolUniqueId atan_Float1_Float1 = TSymbolUniqueId(3118); + static constexpr const TSymbolUniqueId atan_Float2_Float2 = TSymbolUniqueId(3119); + static constexpr const TSymbolUniqueId atan_Float3_Float3 = TSymbolUniqueId(3120); + static constexpr const TSymbolUniqueId atan_Float4_Float4 = TSymbolUniqueId(3121); + static constexpr const TSymbolUniqueId atan_Float1 = TSymbolUniqueId(3122); + static constexpr const TSymbolUniqueId atan_Float2 = TSymbolUniqueId(3123); + static constexpr const TSymbolUniqueId atan_Float3 = TSymbolUniqueId(3124); + static constexpr const TSymbolUniqueId atan_Float4 = TSymbolUniqueId(3125); + static constexpr const TSymbolUniqueId sinh_Float1 = TSymbolUniqueId(3126); + static constexpr const TSymbolUniqueId sinh_Float2 = TSymbolUniqueId(3127); + static constexpr const TSymbolUniqueId sinh_Float3 = TSymbolUniqueId(3128); + static constexpr const TSymbolUniqueId sinh_Float4 = TSymbolUniqueId(3129); + static constexpr const TSymbolUniqueId cosh_Float1 = TSymbolUniqueId(3130); + static constexpr const TSymbolUniqueId cosh_Float2 = TSymbolUniqueId(3131); + static constexpr const TSymbolUniqueId cosh_Float3 = TSymbolUniqueId(3132); + static constexpr const TSymbolUniqueId cosh_Float4 = TSymbolUniqueId(3133); + static constexpr const TSymbolUniqueId tanh_Float1 = TSymbolUniqueId(3134); + static constexpr const TSymbolUniqueId tanh_Float2 = TSymbolUniqueId(3135); + static constexpr const TSymbolUniqueId tanh_Float3 = TSymbolUniqueId(3136); + static constexpr const TSymbolUniqueId tanh_Float4 = TSymbolUniqueId(3137); + static constexpr const TSymbolUniqueId asinh_Float1 = TSymbolUniqueId(3138); + static constexpr const TSymbolUniqueId asinh_Float2 = TSymbolUniqueId(3139); + static constexpr const TSymbolUniqueId asinh_Float3 = TSymbolUniqueId(3140); + static constexpr const TSymbolUniqueId asinh_Float4 = TSymbolUniqueId(3141); + static constexpr const TSymbolUniqueId acosh_Float1 = TSymbolUniqueId(3142); + static constexpr const TSymbolUniqueId acosh_Float2 = TSymbolUniqueId(3143); + static constexpr const TSymbolUniqueId acosh_Float3 = TSymbolUniqueId(3144); + static constexpr const TSymbolUniqueId acosh_Float4 = TSymbolUniqueId(3145); + static constexpr const TSymbolUniqueId atanh_Float1 = TSymbolUniqueId(3146); + static constexpr const TSymbolUniqueId atanh_Float2 = TSymbolUniqueId(3147); + static constexpr const TSymbolUniqueId atanh_Float3 = TSymbolUniqueId(3148); + static constexpr const TSymbolUniqueId atanh_Float4 = TSymbolUniqueId(3149); + static constexpr const TSymbolUniqueId pow_Float1_Float1 = TSymbolUniqueId(3150); + static constexpr const TSymbolUniqueId pow_Float2_Float2 = TSymbolUniqueId(3151); + static constexpr const TSymbolUniqueId pow_Float3_Float3 = TSymbolUniqueId(3152); + static constexpr const TSymbolUniqueId pow_Float4_Float4 = TSymbolUniqueId(3153); + static constexpr const TSymbolUniqueId exp_Float1 = TSymbolUniqueId(3154); + static constexpr const TSymbolUniqueId exp_Float2 = TSymbolUniqueId(3155); + static constexpr const TSymbolUniqueId exp_Float3 = TSymbolUniqueId(3156); + static constexpr const TSymbolUniqueId exp_Float4 = TSymbolUniqueId(3157); + static constexpr const TSymbolUniqueId log_Float1 = TSymbolUniqueId(3158); + static constexpr const TSymbolUniqueId log_Float2 = TSymbolUniqueId(3159); + static constexpr const TSymbolUniqueId log_Float3 = TSymbolUniqueId(3160); + static constexpr const TSymbolUniqueId log_Float4 = TSymbolUniqueId(3161); + static constexpr const TSymbolUniqueId exp2_Float1 = TSymbolUniqueId(3162); + static constexpr const TSymbolUniqueId exp2_Float2 = TSymbolUniqueId(3163); + static constexpr const TSymbolUniqueId exp2_Float3 = TSymbolUniqueId(3164); + static constexpr const TSymbolUniqueId exp2_Float4 = TSymbolUniqueId(3165); + static constexpr const TSymbolUniqueId log2_Float1 = TSymbolUniqueId(3166); + static constexpr const TSymbolUniqueId log2_Float2 = TSymbolUniqueId(3167); + static constexpr const TSymbolUniqueId log2_Float3 = TSymbolUniqueId(3168); + static constexpr const TSymbolUniqueId log2_Float4 = TSymbolUniqueId(3169); + static constexpr const TSymbolUniqueId sqrt_Float1 = TSymbolUniqueId(3170); + static constexpr const TSymbolUniqueId sqrt_Float2 = TSymbolUniqueId(3171); + static constexpr const TSymbolUniqueId sqrt_Float3 = TSymbolUniqueId(3172); + static constexpr const TSymbolUniqueId sqrt_Float4 = TSymbolUniqueId(3173); + static constexpr const TSymbolUniqueId inversesqrt_Float1 = TSymbolUniqueId(3174); + static constexpr const TSymbolUniqueId inversesqrt_Float2 = TSymbolUniqueId(3175); + static constexpr const TSymbolUniqueId inversesqrt_Float3 = TSymbolUniqueId(3176); + static constexpr const TSymbolUniqueId inversesqrt_Float4 = TSymbolUniqueId(3177); + static constexpr const TSymbolUniqueId abs_Float1 = TSymbolUniqueId(3178); + static constexpr const TSymbolUniqueId abs_Float2 = TSymbolUniqueId(3179); + static constexpr const TSymbolUniqueId abs_Float3 = TSymbolUniqueId(3180); + static constexpr const TSymbolUniqueId abs_Float4 = TSymbolUniqueId(3181); + static constexpr const TSymbolUniqueId abs_Int1 = TSymbolUniqueId(3182); + static constexpr const TSymbolUniqueId pt00D = TSymbolUniqueId(3183); + static constexpr const TSymbolUniqueId abs_Int2 = TSymbolUniqueId(3184); + static constexpr const TSymbolUniqueId pt10D = TSymbolUniqueId(3185); + static constexpr const TSymbolUniqueId abs_Int3 = TSymbolUniqueId(3186); + static constexpr const TSymbolUniqueId pt20D = TSymbolUniqueId(3187); + static constexpr const TSymbolUniqueId abs_Int4 = TSymbolUniqueId(3188); + static constexpr const TSymbolUniqueId pt30D = TSymbolUniqueId(3189); + static constexpr const TSymbolUniqueId sign_Float1 = TSymbolUniqueId(3190); + static constexpr const TSymbolUniqueId sign_Float2 = TSymbolUniqueId(3191); + static constexpr const TSymbolUniqueId sign_Float3 = TSymbolUniqueId(3192); + static constexpr const TSymbolUniqueId sign_Float4 = TSymbolUniqueId(3193); + static constexpr const TSymbolUniqueId sign_Int1 = TSymbolUniqueId(3194); + static constexpr const TSymbolUniqueId sign_Int2 = TSymbolUniqueId(3195); + static constexpr const TSymbolUniqueId sign_Int3 = TSymbolUniqueId(3196); + static constexpr const TSymbolUniqueId sign_Int4 = TSymbolUniqueId(3197); + static constexpr const TSymbolUniqueId floor_Float1 = TSymbolUniqueId(3198); + static constexpr const TSymbolUniqueId floor_Float2 = TSymbolUniqueId(3199); + static constexpr const TSymbolUniqueId floor_Float3 = TSymbolUniqueId(3200); + static constexpr const TSymbolUniqueId floor_Float4 = TSymbolUniqueId(3201); + static constexpr const TSymbolUniqueId trunc_Float1 = TSymbolUniqueId(3202); + static constexpr const TSymbolUniqueId trunc_Float2 = TSymbolUniqueId(3203); + static constexpr const TSymbolUniqueId trunc_Float3 = TSymbolUniqueId(3204); + static constexpr const TSymbolUniqueId trunc_Float4 = TSymbolUniqueId(3205); + static constexpr const TSymbolUniqueId round_Float1 = TSymbolUniqueId(3206); + static constexpr const TSymbolUniqueId round_Float2 = TSymbolUniqueId(3207); + static constexpr const TSymbolUniqueId round_Float3 = TSymbolUniqueId(3208); + static constexpr const TSymbolUniqueId round_Float4 = TSymbolUniqueId(3209); + static constexpr const TSymbolUniqueId roundEven_Float1 = TSymbolUniqueId(3210); + static constexpr const TSymbolUniqueId roundEven_Float2 = TSymbolUniqueId(3211); + static constexpr const TSymbolUniqueId roundEven_Float3 = TSymbolUniqueId(3212); + static constexpr const TSymbolUniqueId roundEven_Float4 = TSymbolUniqueId(3213); + static constexpr const TSymbolUniqueId ceil_Float1 = TSymbolUniqueId(3214); + static constexpr const TSymbolUniqueId ceil_Float2 = TSymbolUniqueId(3215); + static constexpr const TSymbolUniqueId ceil_Float3 = TSymbolUniqueId(3216); + static constexpr const TSymbolUniqueId ceil_Float4 = TSymbolUniqueId(3217); + static constexpr const TSymbolUniqueId fract_Float1 = TSymbolUniqueId(3218); + static constexpr const TSymbolUniqueId fract_Float2 = TSymbolUniqueId(3219); + static constexpr const TSymbolUniqueId fract_Float3 = TSymbolUniqueId(3220); + static constexpr const TSymbolUniqueId fract_Float4 = TSymbolUniqueId(3221); + static constexpr const TSymbolUniqueId mod_Float1_Float1 = TSymbolUniqueId(3222); + static constexpr const TSymbolUniqueId mod_Float2_Float1 = TSymbolUniqueId(3223); + static constexpr const TSymbolUniqueId mod_Float3_Float1 = TSymbolUniqueId(3224); + static constexpr const TSymbolUniqueId mod_Float4_Float1 = TSymbolUniqueId(3225); + static constexpr const TSymbolUniqueId mod_Float2_Float2 = TSymbolUniqueId(3226); + static constexpr const TSymbolUniqueId mod_Float3_Float3 = TSymbolUniqueId(3227); + static constexpr const TSymbolUniqueId mod_Float4_Float4 = TSymbolUniqueId(3228); + static constexpr const TSymbolUniqueId min_Float1_Float1 = TSymbolUniqueId(3229); + static constexpr const TSymbolUniqueId min_Float2_Float1 = TSymbolUniqueId(3230); + static constexpr const TSymbolUniqueId min_Float3_Float1 = TSymbolUniqueId(3231); + static constexpr const TSymbolUniqueId min_Float4_Float1 = TSymbolUniqueId(3232); + static constexpr const TSymbolUniqueId min_Float2_Float2 = TSymbolUniqueId(3233); + static constexpr const TSymbolUniqueId min_Float3_Float3 = TSymbolUniqueId(3234); + static constexpr const TSymbolUniqueId min_Float4_Float4 = TSymbolUniqueId(3235); + static constexpr const TSymbolUniqueId min_Int1_Int1 = TSymbolUniqueId(3236); + static constexpr const TSymbolUniqueId min_Int2_Int2 = TSymbolUniqueId(3237); + static constexpr const TSymbolUniqueId min_Int3_Int3 = TSymbolUniqueId(3238); + static constexpr const TSymbolUniqueId min_Int4_Int4 = TSymbolUniqueId(3239); + static constexpr const TSymbolUniqueId min_Int2_Int1 = TSymbolUniqueId(3240); + static constexpr const TSymbolUniqueId min_Int3_Int1 = TSymbolUniqueId(3241); + static constexpr const TSymbolUniqueId min_Int4_Int1 = TSymbolUniqueId(3242); + static constexpr const TSymbolUniqueId min_UInt1_UInt1 = TSymbolUniqueId(3243); + static constexpr const TSymbolUniqueId pt00E = TSymbolUniqueId(3244); + static constexpr const TSymbolUniqueId min_UInt2_UInt2 = TSymbolUniqueId(3245); + static constexpr const TSymbolUniqueId pt10E = TSymbolUniqueId(3246); + static constexpr const TSymbolUniqueId min_UInt3_UInt3 = TSymbolUniqueId(3247); + static constexpr const TSymbolUniqueId pt20E = TSymbolUniqueId(3248); + static constexpr const TSymbolUniqueId min_UInt4_UInt4 = TSymbolUniqueId(3249); + static constexpr const TSymbolUniqueId pt30E = TSymbolUniqueId(3250); + static constexpr const TSymbolUniqueId min_UInt2_UInt1 = TSymbolUniqueId(3251); + static constexpr const TSymbolUniqueId min_UInt3_UInt1 = TSymbolUniqueId(3252); + static constexpr const TSymbolUniqueId min_UInt4_UInt1 = TSymbolUniqueId(3253); + static constexpr const TSymbolUniqueId max_Float1_Float1 = TSymbolUniqueId(3254); + static constexpr const TSymbolUniqueId max_Float2_Float1 = TSymbolUniqueId(3255); + static constexpr const TSymbolUniqueId max_Float3_Float1 = TSymbolUniqueId(3256); + static constexpr const TSymbolUniqueId max_Float4_Float1 = TSymbolUniqueId(3257); + static constexpr const TSymbolUniqueId max_Float2_Float2 = TSymbolUniqueId(3258); + static constexpr const TSymbolUniqueId max_Float3_Float3 = TSymbolUniqueId(3259); + static constexpr const TSymbolUniqueId max_Float4_Float4 = TSymbolUniqueId(3260); + static constexpr const TSymbolUniqueId max_Int1_Int1 = TSymbolUniqueId(3261); + static constexpr const TSymbolUniqueId max_Int2_Int2 = TSymbolUniqueId(3262); + static constexpr const TSymbolUniqueId max_Int3_Int3 = TSymbolUniqueId(3263); + static constexpr const TSymbolUniqueId max_Int4_Int4 = TSymbolUniqueId(3264); + static constexpr const TSymbolUniqueId max_Int2_Int1 = TSymbolUniqueId(3265); + static constexpr const TSymbolUniqueId max_Int3_Int1 = TSymbolUniqueId(3266); + static constexpr const TSymbolUniqueId max_Int4_Int1 = TSymbolUniqueId(3267); + static constexpr const TSymbolUniqueId max_UInt1_UInt1 = TSymbolUniqueId(3268); + static constexpr const TSymbolUniqueId max_UInt2_UInt2 = TSymbolUniqueId(3269); + static constexpr const TSymbolUniqueId max_UInt3_UInt3 = TSymbolUniqueId(3270); + static constexpr const TSymbolUniqueId max_UInt4_UInt4 = TSymbolUniqueId(3271); + static constexpr const TSymbolUniqueId max_UInt2_UInt1 = TSymbolUniqueId(3272); + static constexpr const TSymbolUniqueId max_UInt3_UInt1 = TSymbolUniqueId(3273); + static constexpr const TSymbolUniqueId max_UInt4_UInt1 = TSymbolUniqueId(3274); + static constexpr const TSymbolUniqueId clamp_Float1_Float1_Float1 = TSymbolUniqueId(3275); + static constexpr const TSymbolUniqueId clamp_Float2_Float1_Float1 = TSymbolUniqueId(3276); + static constexpr const TSymbolUniqueId clamp_Float3_Float1_Float1 = TSymbolUniqueId(3277); + static constexpr const TSymbolUniqueId clamp_Float4_Float1_Float1 = TSymbolUniqueId(3278); + static constexpr const TSymbolUniqueId clamp_Float2_Float2_Float2 = TSymbolUniqueId(3279); + static constexpr const TSymbolUniqueId clamp_Float3_Float3_Float3 = TSymbolUniqueId(3280); + static constexpr const TSymbolUniqueId clamp_Float4_Float4_Float4 = TSymbolUniqueId(3281); + static constexpr const TSymbolUniqueId clamp_Int1_Int1_Int1 = TSymbolUniqueId(3282); + static constexpr const TSymbolUniqueId clamp_Int2_Int1_Int1 = TSymbolUniqueId(3283); + static constexpr const TSymbolUniqueId clamp_Int3_Int1_Int1 = TSymbolUniqueId(3284); + static constexpr const TSymbolUniqueId clamp_Int4_Int1_Int1 = TSymbolUniqueId(3285); + static constexpr const TSymbolUniqueId clamp_Int2_Int2_Int2 = TSymbolUniqueId(3286); + static constexpr const TSymbolUniqueId clamp_Int3_Int3_Int3 = TSymbolUniqueId(3287); + static constexpr const TSymbolUniqueId clamp_Int4_Int4_Int4 = TSymbolUniqueId(3288); + static constexpr const TSymbolUniqueId clamp_UInt1_UInt1_UInt1 = TSymbolUniqueId(3289); + static constexpr const TSymbolUniqueId clamp_UInt2_UInt1_UInt1 = TSymbolUniqueId(3290); + static constexpr const TSymbolUniqueId clamp_UInt3_UInt1_UInt1 = TSymbolUniqueId(3291); + static constexpr const TSymbolUniqueId clamp_UInt4_UInt1_UInt1 = TSymbolUniqueId(3292); + static constexpr const TSymbolUniqueId clamp_UInt2_UInt2_UInt2 = TSymbolUniqueId(3293); + static constexpr const TSymbolUniqueId clamp_UInt3_UInt3_UInt3 = TSymbolUniqueId(3294); + static constexpr const TSymbolUniqueId clamp_UInt4_UInt4_UInt4 = TSymbolUniqueId(3295); + static constexpr const TSymbolUniqueId mix_Float1_Float1_Float1 = TSymbolUniqueId(3296); + static constexpr const TSymbolUniqueId mix_Float2_Float2_Float1 = TSymbolUniqueId(3297); + static constexpr const TSymbolUniqueId mix_Float3_Float3_Float1 = TSymbolUniqueId(3298); + static constexpr const TSymbolUniqueId mix_Float4_Float4_Float1 = TSymbolUniqueId(3299); + static constexpr const TSymbolUniqueId mix_Float2_Float2_Float2 = TSymbolUniqueId(3300); + static constexpr const TSymbolUniqueId mix_Float3_Float3_Float3 = TSymbolUniqueId(3301); + static constexpr const TSymbolUniqueId mix_Float4_Float4_Float4 = TSymbolUniqueId(3302); + static constexpr const TSymbolUniqueId mix_Float1_Float1_Bool1 = TSymbolUniqueId(3303); + static constexpr const TSymbolUniqueId pt00F = TSymbolUniqueId(3304); + static constexpr const TSymbolUniqueId mix_Float2_Float2_Bool2 = TSymbolUniqueId(3305); + static constexpr const TSymbolUniqueId pt10F = TSymbolUniqueId(3306); + static constexpr const TSymbolUniqueId mix_Float3_Float3_Bool3 = TSymbolUniqueId(3307); + static constexpr const TSymbolUniqueId pt20F = TSymbolUniqueId(3308); + static constexpr const TSymbolUniqueId mix_Float4_Float4_Bool4 = TSymbolUniqueId(3309); + static constexpr const TSymbolUniqueId pt30F = TSymbolUniqueId(3310); + static constexpr const TSymbolUniqueId mix_Int1_Int1_Bool1 = TSymbolUniqueId(3311); + static constexpr const TSymbolUniqueId mix_Int2_Int2_Bool2 = TSymbolUniqueId(3312); + static constexpr const TSymbolUniqueId mix_Int3_Int3_Bool3 = TSymbolUniqueId(3313); + static constexpr const TSymbolUniqueId mix_Int4_Int4_Bool4 = TSymbolUniqueId(3314); + static constexpr const TSymbolUniqueId mix_UInt1_UInt1_Bool1 = TSymbolUniqueId(3315); + static constexpr const TSymbolUniqueId mix_UInt2_UInt2_Bool2 = TSymbolUniqueId(3316); + static constexpr const TSymbolUniqueId mix_UInt3_UInt3_Bool3 = TSymbolUniqueId(3317); + static constexpr const TSymbolUniqueId mix_UInt4_UInt4_Bool4 = TSymbolUniqueId(3318); + static constexpr const TSymbolUniqueId mix_Bool1_Bool1_Bool1 = TSymbolUniqueId(3319); + static constexpr const TSymbolUniqueId mix_Bool2_Bool2_Bool2 = TSymbolUniqueId(3320); + static constexpr const TSymbolUniqueId mix_Bool3_Bool3_Bool3 = TSymbolUniqueId(3321); + static constexpr const TSymbolUniqueId mix_Bool4_Bool4_Bool4 = TSymbolUniqueId(3322); + static constexpr const TSymbolUniqueId step_Float1_Float1 = TSymbolUniqueId(3323); + static constexpr const TSymbolUniqueId step_Float2_Float2 = TSymbolUniqueId(3324); + static constexpr const TSymbolUniqueId step_Float3_Float3 = TSymbolUniqueId(3325); + static constexpr const TSymbolUniqueId step_Float4_Float4 = TSymbolUniqueId(3326); + static constexpr const TSymbolUniqueId step_Float1_Float2 = TSymbolUniqueId(3327); + static constexpr const TSymbolUniqueId step_Float1_Float3 = TSymbolUniqueId(3328); + static constexpr const TSymbolUniqueId step_Float1_Float4 = TSymbolUniqueId(3329); + static constexpr const TSymbolUniqueId smoothstep_Float1_Float1_Float1 = TSymbolUniqueId(3330); + static constexpr const TSymbolUniqueId smoothstep_Float2_Float2_Float2 = TSymbolUniqueId(3331); + static constexpr const TSymbolUniqueId smoothstep_Float3_Float3_Float3 = TSymbolUniqueId(3332); + static constexpr const TSymbolUniqueId smoothstep_Float4_Float4_Float4 = TSymbolUniqueId(3333); + static constexpr const TSymbolUniqueId smoothstep_Float1_Float1_Float2 = TSymbolUniqueId(3334); + static constexpr const TSymbolUniqueId smoothstep_Float1_Float1_Float3 = TSymbolUniqueId(3335); + static constexpr const TSymbolUniqueId smoothstep_Float1_Float1_Float4 = TSymbolUniqueId(3336); + static constexpr const TSymbolUniqueId modf_Float1_Float1 = TSymbolUniqueId(3337); + static constexpr const TSymbolUniqueId pt_o_00B = TSymbolUniqueId(3338); + static constexpr const TSymbolUniqueId modf_Float2_Float2 = TSymbolUniqueId(3339); + static constexpr const TSymbolUniqueId pt_o_10B = TSymbolUniqueId(3340); + static constexpr const TSymbolUniqueId modf_Float3_Float3 = TSymbolUniqueId(3341); + static constexpr const TSymbolUniqueId pt_o_20B = TSymbolUniqueId(3342); + static constexpr const TSymbolUniqueId modf_Float4_Float4 = TSymbolUniqueId(3343); + static constexpr const TSymbolUniqueId pt_o_30B = TSymbolUniqueId(3344); + static constexpr const TSymbolUniqueId isnan_Float1 = TSymbolUniqueId(3345); + static constexpr const TSymbolUniqueId isnan_Float2 = TSymbolUniqueId(3346); + static constexpr const TSymbolUniqueId isnan_Float3 = TSymbolUniqueId(3347); + static constexpr const TSymbolUniqueId isnan_Float4 = TSymbolUniqueId(3348); + static constexpr const TSymbolUniqueId isinf_Float1 = TSymbolUniqueId(3349); + static constexpr const TSymbolUniqueId isinf_Float2 = TSymbolUniqueId(3350); + static constexpr const TSymbolUniqueId isinf_Float3 = TSymbolUniqueId(3351); + static constexpr const TSymbolUniqueId isinf_Float4 = TSymbolUniqueId(3352); + static constexpr const TSymbolUniqueId floatBitsToInt_Float1 = TSymbolUniqueId(3353); + static constexpr const TSymbolUniqueId floatBitsToInt_Float2 = TSymbolUniqueId(3354); + static constexpr const TSymbolUniqueId floatBitsToInt_Float3 = TSymbolUniqueId(3355); + static constexpr const TSymbolUniqueId floatBitsToInt_Float4 = TSymbolUniqueId(3356); + static constexpr const TSymbolUniqueId floatBitsToUint_Float1 = TSymbolUniqueId(3357); + static constexpr const TSymbolUniqueId floatBitsToUint_Float2 = TSymbolUniqueId(3358); + static constexpr const TSymbolUniqueId floatBitsToUint_Float3 = TSymbolUniqueId(3359); + static constexpr const TSymbolUniqueId floatBitsToUint_Float4 = TSymbolUniqueId(3360); + static constexpr const TSymbolUniqueId intBitsToFloat_Int1 = TSymbolUniqueId(3361); + static constexpr const TSymbolUniqueId intBitsToFloat_Int2 = TSymbolUniqueId(3362); + static constexpr const TSymbolUniqueId intBitsToFloat_Int3 = TSymbolUniqueId(3363); + static constexpr const TSymbolUniqueId intBitsToFloat_Int4 = TSymbolUniqueId(3364); + static constexpr const TSymbolUniqueId uintBitsToFloat_UInt1 = TSymbolUniqueId(3365); + static constexpr const TSymbolUniqueId uintBitsToFloat_UInt2 = TSymbolUniqueId(3366); + static constexpr const TSymbolUniqueId uintBitsToFloat_UInt3 = TSymbolUniqueId(3367); + static constexpr const TSymbolUniqueId uintBitsToFloat_UInt4 = TSymbolUniqueId(3368); + static constexpr const TSymbolUniqueId fma_Float1_Float1_Float1 = TSymbolUniqueId(3369); + static constexpr const TSymbolUniqueId fma_Float2_Float2_Float2 = TSymbolUniqueId(3370); + static constexpr const TSymbolUniqueId fma_Float3_Float3_Float3 = TSymbolUniqueId(3371); + static constexpr const TSymbolUniqueId fma_Float4_Float4_Float4 = TSymbolUniqueId(3372); + static constexpr const TSymbolUniqueId fmaExt_Float1_Float1_Float1 = TSymbolUniqueId(3373); + static constexpr const TSymbolUniqueId fmaExt_Float2_Float2_Float2 = TSymbolUniqueId(3374); + static constexpr const TSymbolUniqueId fmaExt_Float3_Float3_Float3 = TSymbolUniqueId(3375); + static constexpr const TSymbolUniqueId fmaExt_Float4_Float4_Float4 = TSymbolUniqueId(3376); + static constexpr const TSymbolUniqueId frexp_Float1_Int1 = TSymbolUniqueId(3377); + static constexpr const TSymbolUniqueId pt_o_00D = TSymbolUniqueId(3378); + static constexpr const TSymbolUniqueId frexp_Float2_Int2 = TSymbolUniqueId(3379); + static constexpr const TSymbolUniqueId pt_o_10D = TSymbolUniqueId(3380); + static constexpr const TSymbolUniqueId frexp_Float3_Int3 = TSymbolUniqueId(3381); + static constexpr const TSymbolUniqueId pt_o_20D = TSymbolUniqueId(3382); + static constexpr const TSymbolUniqueId frexp_Float4_Int4 = TSymbolUniqueId(3383); + static constexpr const TSymbolUniqueId pt_o_30D = TSymbolUniqueId(3384); + static constexpr const TSymbolUniqueId ldexp_Float1_Int1 = TSymbolUniqueId(3385); + static constexpr const TSymbolUniqueId ldexp_Float2_Int2 = TSymbolUniqueId(3386); + static constexpr const TSymbolUniqueId ldexp_Float3_Int3 = TSymbolUniqueId(3387); + static constexpr const TSymbolUniqueId ldexp_Float4_Int4 = TSymbolUniqueId(3388); + static constexpr const TSymbolUniqueId packSnorm2x16_Float2 = TSymbolUniqueId(3389); + static constexpr const TSymbolUniqueId packHalf2x16_Float2 = TSymbolUniqueId(3390); + static constexpr const TSymbolUniqueId unpackSnorm2x16_UInt1 = TSymbolUniqueId(3391); + static constexpr const TSymbolUniqueId unpackHalf2x16_UInt1 = TSymbolUniqueId(3392); + static constexpr const TSymbolUniqueId packUnorm2x16_Float2 = TSymbolUniqueId(3393); + static constexpr const TSymbolUniqueId unpackUnorm2x16_UInt1 = TSymbolUniqueId(3394); + static constexpr const TSymbolUniqueId packUnorm4x8_Float4 = TSymbolUniqueId(3395); + static constexpr const TSymbolUniqueId packSnorm4x8_Float4 = TSymbolUniqueId(3396); + static constexpr const TSymbolUniqueId unpackUnorm4x8_UInt1 = TSymbolUniqueId(3397); + static constexpr const TSymbolUniqueId unpackSnorm4x8_UInt1 = TSymbolUniqueId(3398); + static constexpr const TSymbolUniqueId length_Float1 = TSymbolUniqueId(3399); + static constexpr const TSymbolUniqueId length_Float2 = TSymbolUniqueId(3400); + static constexpr const TSymbolUniqueId length_Float3 = TSymbolUniqueId(3401); + static constexpr const TSymbolUniqueId length_Float4 = TSymbolUniqueId(3402); + static constexpr const TSymbolUniqueId distance_Float1_Float1 = TSymbolUniqueId(3403); + static constexpr const TSymbolUniqueId distance_Float2_Float2 = TSymbolUniqueId(3404); + static constexpr const TSymbolUniqueId distance_Float3_Float3 = TSymbolUniqueId(3405); + static constexpr const TSymbolUniqueId distance_Float4_Float4 = TSymbolUniqueId(3406); + static constexpr const TSymbolUniqueId dot_Float1_Float1 = TSymbolUniqueId(3407); + static constexpr const TSymbolUniqueId dot_Float2_Float2 = TSymbolUniqueId(3408); + static constexpr const TSymbolUniqueId dot_Float3_Float3 = TSymbolUniqueId(3409); + static constexpr const TSymbolUniqueId dot_Float4_Float4 = TSymbolUniqueId(3410); + static constexpr const TSymbolUniqueId cross_Float3_Float3 = TSymbolUniqueId(3411); + static constexpr const TSymbolUniqueId normalize_Float1 = TSymbolUniqueId(3412); + static constexpr const TSymbolUniqueId normalize_Float2 = TSymbolUniqueId(3413); + static constexpr const TSymbolUniqueId normalize_Float3 = TSymbolUniqueId(3414); + static constexpr const TSymbolUniqueId normalize_Float4 = TSymbolUniqueId(3415); + static constexpr const TSymbolUniqueId faceforward_Float1_Float1_Float1 = TSymbolUniqueId(3416); + static constexpr const TSymbolUniqueId faceforward_Float2_Float2_Float2 = TSymbolUniqueId(3417); + static constexpr const TSymbolUniqueId faceforward_Float3_Float3_Float3 = TSymbolUniqueId(3418); + static constexpr const TSymbolUniqueId faceforward_Float4_Float4_Float4 = TSymbolUniqueId(3419); + static constexpr const TSymbolUniqueId reflect_Float1_Float1 = TSymbolUniqueId(3420); + static constexpr const TSymbolUniqueId reflect_Float2_Float2 = TSymbolUniqueId(3421); + static constexpr const TSymbolUniqueId reflect_Float3_Float3 = TSymbolUniqueId(3422); + static constexpr const TSymbolUniqueId reflect_Float4_Float4 = TSymbolUniqueId(3423); + static constexpr const TSymbolUniqueId refract_Float1_Float1_Float1 = TSymbolUniqueId(3424); + static constexpr const TSymbolUniqueId refract_Float2_Float2_Float1 = TSymbolUniqueId(3425); + static constexpr const TSymbolUniqueId refract_Float3_Float3_Float1 = TSymbolUniqueId(3426); + static constexpr const TSymbolUniqueId refract_Float4_Float4_Float1 = TSymbolUniqueId(3427); + static constexpr const TSymbolUniqueId matrixCompMult_Float2x2_Float2x2 = TSymbolUniqueId(3428); + static constexpr const TSymbolUniqueId pt50B = TSymbolUniqueId(3429); + static constexpr const TSymbolUniqueId matrixCompMult_Float3x3_Float3x3 = TSymbolUniqueId(3430); + static constexpr const TSymbolUniqueId ptA0B = TSymbolUniqueId(3431); + static constexpr const TSymbolUniqueId matrixCompMult_Float4x4_Float4x4 = TSymbolUniqueId(3432); + static constexpr const TSymbolUniqueId ptF0B = TSymbolUniqueId(3433); + static constexpr const TSymbolUniqueId matrixCompMult_Float2x3_Float2x3 = TSymbolUniqueId(3434); + static constexpr const TSymbolUniqueId pt90B = TSymbolUniqueId(3435); + static constexpr const TSymbolUniqueId matrixCompMult_Float3x2_Float3x2 = TSymbolUniqueId(3436); + static constexpr const TSymbolUniqueId pt60B = TSymbolUniqueId(3437); + static constexpr const TSymbolUniqueId matrixCompMult_Float2x4_Float2x4 = TSymbolUniqueId(3438); + static constexpr const TSymbolUniqueId ptD0B = TSymbolUniqueId(3439); + static constexpr const TSymbolUniqueId matrixCompMult_Float4x2_Float4x2 = TSymbolUniqueId(3440); + static constexpr const TSymbolUniqueId pt70B = TSymbolUniqueId(3441); + static constexpr const TSymbolUniqueId matrixCompMult_Float3x4_Float3x4 = TSymbolUniqueId(3442); + static constexpr const TSymbolUniqueId ptE0B = TSymbolUniqueId(3443); + static constexpr const TSymbolUniqueId matrixCompMult_Float4x3_Float4x3 = TSymbolUniqueId(3444); + static constexpr const TSymbolUniqueId ptB0B = TSymbolUniqueId(3445); + static constexpr const TSymbolUniqueId outerProduct_Float2_Float2 = TSymbolUniqueId(3446); + static constexpr const TSymbolUniqueId outerProduct_Float3_Float3 = TSymbolUniqueId(3447); + static constexpr const TSymbolUniqueId outerProduct_Float4_Float4 = TSymbolUniqueId(3448); + static constexpr const TSymbolUniqueId outerProduct_Float3_Float2 = TSymbolUniqueId(3449); + static constexpr const TSymbolUniqueId outerProduct_Float2_Float3 = TSymbolUniqueId(3450); + static constexpr const TSymbolUniqueId outerProduct_Float4_Float2 = TSymbolUniqueId(3451); + static constexpr const TSymbolUniqueId outerProduct_Float2_Float4 = TSymbolUniqueId(3452); + static constexpr const TSymbolUniqueId outerProduct_Float4_Float3 = TSymbolUniqueId(3453); + static constexpr const TSymbolUniqueId outerProduct_Float3_Float4 = TSymbolUniqueId(3454); + static constexpr const TSymbolUniqueId transpose_Float2x2 = TSymbolUniqueId(3455); + static constexpr const TSymbolUniqueId transpose_Float3x3 = TSymbolUniqueId(3456); + static constexpr const TSymbolUniqueId transpose_Float4x4 = TSymbolUniqueId(3457); + static constexpr const TSymbolUniqueId transpose_Float3x2 = TSymbolUniqueId(3458); + static constexpr const TSymbolUniqueId transpose_Float2x3 = TSymbolUniqueId(3459); + static constexpr const TSymbolUniqueId transpose_Float4x2 = TSymbolUniqueId(3460); + static constexpr const TSymbolUniqueId transpose_Float2x4 = TSymbolUniqueId(3461); + static constexpr const TSymbolUniqueId transpose_Float4x3 = TSymbolUniqueId(3462); + static constexpr const TSymbolUniqueId transpose_Float3x4 = TSymbolUniqueId(3463); + static constexpr const TSymbolUniqueId determinant_Float2x2 = TSymbolUniqueId(3464); + static constexpr const TSymbolUniqueId determinant_Float3x3 = TSymbolUniqueId(3465); + static constexpr const TSymbolUniqueId determinant_Float4x4 = TSymbolUniqueId(3466); + static constexpr const TSymbolUniqueId inverse_Float2x2 = TSymbolUniqueId(3467); + static constexpr const TSymbolUniqueId inverse_Float3x3 = TSymbolUniqueId(3468); + static constexpr const TSymbolUniqueId inverse_Float4x4 = TSymbolUniqueId(3469); + static constexpr const TSymbolUniqueId lessThan_Float2_Float2 = TSymbolUniqueId(3470); + static constexpr const TSymbolUniqueId lessThan_Float3_Float3 = TSymbolUniqueId(3471); + static constexpr const TSymbolUniqueId lessThan_Float4_Float4 = TSymbolUniqueId(3472); + static constexpr const TSymbolUniqueId lessThan_Int2_Int2 = TSymbolUniqueId(3473); + static constexpr const TSymbolUniqueId lessThan_Int3_Int3 = TSymbolUniqueId(3474); + static constexpr const TSymbolUniqueId lessThan_Int4_Int4 = TSymbolUniqueId(3475); + static constexpr const TSymbolUniqueId lessThan_UInt2_UInt2 = TSymbolUniqueId(3476); + static constexpr const TSymbolUniqueId lessThan_UInt3_UInt3 = TSymbolUniqueId(3477); + static constexpr const TSymbolUniqueId lessThan_UInt4_UInt4 = TSymbolUniqueId(3478); + static constexpr const TSymbolUniqueId lessThanEqual_Float2_Float2 = TSymbolUniqueId(3479); + static constexpr const TSymbolUniqueId lessThanEqual_Float3_Float3 = TSymbolUniqueId(3480); + static constexpr const TSymbolUniqueId lessThanEqual_Float4_Float4 = TSymbolUniqueId(3481); + static constexpr const TSymbolUniqueId lessThanEqual_Int2_Int2 = TSymbolUniqueId(3482); + static constexpr const TSymbolUniqueId lessThanEqual_Int3_Int3 = TSymbolUniqueId(3483); + static constexpr const TSymbolUniqueId lessThanEqual_Int4_Int4 = TSymbolUniqueId(3484); + static constexpr const TSymbolUniqueId lessThanEqual_UInt2_UInt2 = TSymbolUniqueId(3485); + static constexpr const TSymbolUniqueId lessThanEqual_UInt3_UInt3 = TSymbolUniqueId(3486); + static constexpr const TSymbolUniqueId lessThanEqual_UInt4_UInt4 = TSymbolUniqueId(3487); + static constexpr const TSymbolUniqueId greaterThan_Float2_Float2 = TSymbolUniqueId(3488); + static constexpr const TSymbolUniqueId greaterThan_Float3_Float3 = TSymbolUniqueId(3489); + static constexpr const TSymbolUniqueId greaterThan_Float4_Float4 = TSymbolUniqueId(3490); + static constexpr const TSymbolUniqueId greaterThan_Int2_Int2 = TSymbolUniqueId(3491); + static constexpr const TSymbolUniqueId greaterThan_Int3_Int3 = TSymbolUniqueId(3492); + static constexpr const TSymbolUniqueId greaterThan_Int4_Int4 = TSymbolUniqueId(3493); + static constexpr const TSymbolUniqueId greaterThan_UInt2_UInt2 = TSymbolUniqueId(3494); + static constexpr const TSymbolUniqueId greaterThan_UInt3_UInt3 = TSymbolUniqueId(3495); + static constexpr const TSymbolUniqueId greaterThan_UInt4_UInt4 = TSymbolUniqueId(3496); + static constexpr const TSymbolUniqueId greaterThanEqual_Float2_Float2 = TSymbolUniqueId(3497); + static constexpr const TSymbolUniqueId greaterThanEqual_Float3_Float3 = TSymbolUniqueId(3498); + static constexpr const TSymbolUniqueId greaterThanEqual_Float4_Float4 = TSymbolUniqueId(3499); + static constexpr const TSymbolUniqueId greaterThanEqual_Int2_Int2 = TSymbolUniqueId(3500); + static constexpr const TSymbolUniqueId greaterThanEqual_Int3_Int3 = TSymbolUniqueId(3501); + static constexpr const TSymbolUniqueId greaterThanEqual_Int4_Int4 = TSymbolUniqueId(3502); + static constexpr const TSymbolUniqueId greaterThanEqual_UInt2_UInt2 = TSymbolUniqueId(3503); + static constexpr const TSymbolUniqueId greaterThanEqual_UInt3_UInt3 = TSymbolUniqueId(3504); + static constexpr const TSymbolUniqueId greaterThanEqual_UInt4_UInt4 = TSymbolUniqueId(3505); + static constexpr const TSymbolUniqueId equal_Float2_Float2 = TSymbolUniqueId(3506); + static constexpr const TSymbolUniqueId equal_Float3_Float3 = TSymbolUniqueId(3507); + static constexpr const TSymbolUniqueId equal_Float4_Float4 = TSymbolUniqueId(3508); + static constexpr const TSymbolUniqueId equal_Int2_Int2 = TSymbolUniqueId(3509); + static constexpr const TSymbolUniqueId equal_Int3_Int3 = TSymbolUniqueId(3510); + static constexpr const TSymbolUniqueId equal_Int4_Int4 = TSymbolUniqueId(3511); + static constexpr const TSymbolUniqueId equal_UInt2_UInt2 = TSymbolUniqueId(3512); + static constexpr const TSymbolUniqueId equal_UInt3_UInt3 = TSymbolUniqueId(3513); + static constexpr const TSymbolUniqueId equal_UInt4_UInt4 = TSymbolUniqueId(3514); + static constexpr const TSymbolUniqueId equal_Bool2_Bool2 = TSymbolUniqueId(3515); + static constexpr const TSymbolUniqueId equal_Bool3_Bool3 = TSymbolUniqueId(3516); + static constexpr const TSymbolUniqueId equal_Bool4_Bool4 = TSymbolUniqueId(3517); + static constexpr const TSymbolUniqueId notEqual_Float2_Float2 = TSymbolUniqueId(3518); + static constexpr const TSymbolUniqueId notEqual_Float3_Float3 = TSymbolUniqueId(3519); + static constexpr const TSymbolUniqueId notEqual_Float4_Float4 = TSymbolUniqueId(3520); + static constexpr const TSymbolUniqueId notEqual_Int2_Int2 = TSymbolUniqueId(3521); + static constexpr const TSymbolUniqueId notEqual_Int3_Int3 = TSymbolUniqueId(3522); + static constexpr const TSymbolUniqueId notEqual_Int4_Int4 = TSymbolUniqueId(3523); + static constexpr const TSymbolUniqueId notEqual_UInt2_UInt2 = TSymbolUniqueId(3524); + static constexpr const TSymbolUniqueId notEqual_UInt3_UInt3 = TSymbolUniqueId(3525); + static constexpr const TSymbolUniqueId notEqual_UInt4_UInt4 = TSymbolUniqueId(3526); + static constexpr const TSymbolUniqueId notEqual_Bool2_Bool2 = TSymbolUniqueId(3527); + static constexpr const TSymbolUniqueId notEqual_Bool3_Bool3 = TSymbolUniqueId(3528); + static constexpr const TSymbolUniqueId notEqual_Bool4_Bool4 = TSymbolUniqueId(3529); + static constexpr const TSymbolUniqueId any_Bool2 = TSymbolUniqueId(3530); + static constexpr const TSymbolUniqueId any_Bool3 = TSymbolUniqueId(3531); + static constexpr const TSymbolUniqueId any_Bool4 = TSymbolUniqueId(3532); + static constexpr const TSymbolUniqueId all_Bool2 = TSymbolUniqueId(3533); + static constexpr const TSymbolUniqueId all_Bool3 = TSymbolUniqueId(3534); + static constexpr const TSymbolUniqueId all_Bool4 = TSymbolUniqueId(3535); + static constexpr const TSymbolUniqueId notFunc_Bool2 = TSymbolUniqueId(3536); + static constexpr const TSymbolUniqueId notFunc_Bool3 = TSymbolUniqueId(3537); + static constexpr const TSymbolUniqueId notFunc_Bool4 = TSymbolUniqueId(3538); + static constexpr const TSymbolUniqueId bitfieldExtract_Int1_Int1_Int1 = TSymbolUniqueId(3539); + static constexpr const TSymbolUniqueId bitfieldExtract_Int2_Int1_Int1 = TSymbolUniqueId(3540); + static constexpr const TSymbolUniqueId bitfieldExtract_Int3_Int1_Int1 = TSymbolUniqueId(3541); + static constexpr const TSymbolUniqueId bitfieldExtract_Int4_Int1_Int1 = TSymbolUniqueId(3542); + static constexpr const TSymbolUniqueId bitfieldExtract_UInt1_Int1_Int1 = TSymbolUniqueId(3543); + static constexpr const TSymbolUniqueId bitfieldExtract_UInt2_Int1_Int1 = TSymbolUniqueId(3544); + static constexpr const TSymbolUniqueId bitfieldExtract_UInt3_Int1_Int1 = TSymbolUniqueId(3545); + static constexpr const TSymbolUniqueId bitfieldExtract_UInt4_Int1_Int1 = TSymbolUniqueId(3546); + static constexpr const TSymbolUniqueId bitfieldInsert_Int1_Int1_Int1_Int1 = + TSymbolUniqueId(3547); + static constexpr const TSymbolUniqueId bitfieldInsert_Int2_Int2_Int1_Int1 = + TSymbolUniqueId(3548); + static constexpr const TSymbolUniqueId bitfieldInsert_Int3_Int3_Int1_Int1 = + TSymbolUniqueId(3549); + static constexpr const TSymbolUniqueId bitfieldInsert_Int4_Int4_Int1_Int1 = + TSymbolUniqueId(3550); + static constexpr const TSymbolUniqueId bitfieldInsert_UInt1_UInt1_Int1_Int1 = + TSymbolUniqueId(3551); + static constexpr const TSymbolUniqueId bitfieldInsert_UInt2_UInt2_Int1_Int1 = + TSymbolUniqueId(3552); + static constexpr const TSymbolUniqueId bitfieldInsert_UInt3_UInt3_Int1_Int1 = + TSymbolUniqueId(3553); + static constexpr const TSymbolUniqueId bitfieldInsert_UInt4_UInt4_Int1_Int1 = + TSymbolUniqueId(3554); + static constexpr const TSymbolUniqueId bitfieldReverse_Int1 = TSymbolUniqueId(3555); + static constexpr const TSymbolUniqueId bitfieldReverse_Int2 = TSymbolUniqueId(3556); + static constexpr const TSymbolUniqueId bitfieldReverse_Int3 = TSymbolUniqueId(3557); + static constexpr const TSymbolUniqueId bitfieldReverse_Int4 = TSymbolUniqueId(3558); + static constexpr const TSymbolUniqueId bitfieldReverse_UInt1 = TSymbolUniqueId(3559); + static constexpr const TSymbolUniqueId bitfieldReverse_UInt2 = TSymbolUniqueId(3560); + static constexpr const TSymbolUniqueId bitfieldReverse_UInt3 = TSymbolUniqueId(3561); + static constexpr const TSymbolUniqueId bitfieldReverse_UInt4 = TSymbolUniqueId(3562); + static constexpr const TSymbolUniqueId bitCount_Int1 = TSymbolUniqueId(3563); + static constexpr const TSymbolUniqueId bitCount_Int2 = TSymbolUniqueId(3564); + static constexpr const TSymbolUniqueId bitCount_Int3 = TSymbolUniqueId(3565); + static constexpr const TSymbolUniqueId bitCount_Int4 = TSymbolUniqueId(3566); + static constexpr const TSymbolUniqueId bitCount_UInt1 = TSymbolUniqueId(3567); + static constexpr const TSymbolUniqueId bitCount_UInt2 = TSymbolUniqueId(3568); + static constexpr const TSymbolUniqueId bitCount_UInt3 = TSymbolUniqueId(3569); + static constexpr const TSymbolUniqueId bitCount_UInt4 = TSymbolUniqueId(3570); + static constexpr const TSymbolUniqueId findLSB_Int1 = TSymbolUniqueId(3571); + static constexpr const TSymbolUniqueId findLSB_Int2 = TSymbolUniqueId(3572); + static constexpr const TSymbolUniqueId findLSB_Int3 = TSymbolUniqueId(3573); + static constexpr const TSymbolUniqueId findLSB_Int4 = TSymbolUniqueId(3574); + static constexpr const TSymbolUniqueId findLSB_UInt1 = TSymbolUniqueId(3575); + static constexpr const TSymbolUniqueId findLSB_UInt2 = TSymbolUniqueId(3576); + static constexpr const TSymbolUniqueId findLSB_UInt3 = TSymbolUniqueId(3577); + static constexpr const TSymbolUniqueId findLSB_UInt4 = TSymbolUniqueId(3578); + static constexpr const TSymbolUniqueId findMSB_Int1 = TSymbolUniqueId(3579); + static constexpr const TSymbolUniqueId findMSB_Int2 = TSymbolUniqueId(3580); + static constexpr const TSymbolUniqueId findMSB_Int3 = TSymbolUniqueId(3581); + static constexpr const TSymbolUniqueId findMSB_Int4 = TSymbolUniqueId(3582); + static constexpr const TSymbolUniqueId findMSB_UInt1 = TSymbolUniqueId(3583); + static constexpr const TSymbolUniqueId findMSB_UInt2 = TSymbolUniqueId(3584); + static constexpr const TSymbolUniqueId findMSB_UInt3 = TSymbolUniqueId(3585); + static constexpr const TSymbolUniqueId findMSB_UInt4 = TSymbolUniqueId(3586); + static constexpr const TSymbolUniqueId uaddCarry_UInt1_UInt1_UInt1 = TSymbolUniqueId(3587); + static constexpr const TSymbolUniqueId pt_o_00E = TSymbolUniqueId(3588); + static constexpr const TSymbolUniqueId uaddCarry_UInt2_UInt2_UInt2 = TSymbolUniqueId(3589); + static constexpr const TSymbolUniqueId pt_o_10E = TSymbolUniqueId(3590); + static constexpr const TSymbolUniqueId uaddCarry_UInt3_UInt3_UInt3 = TSymbolUniqueId(3591); + static constexpr const TSymbolUniqueId pt_o_20E = TSymbolUniqueId(3592); + static constexpr const TSymbolUniqueId uaddCarry_UInt4_UInt4_UInt4 = TSymbolUniqueId(3593); + static constexpr const TSymbolUniqueId pt_o_30E = TSymbolUniqueId(3594); + static constexpr const TSymbolUniqueId usubBorrow_UInt1_UInt1_UInt1 = TSymbolUniqueId(3595); + static constexpr const TSymbolUniqueId usubBorrow_UInt2_UInt2_UInt2 = TSymbolUniqueId(3596); + static constexpr const TSymbolUniqueId usubBorrow_UInt3_UInt3_UInt3 = TSymbolUniqueId(3597); + static constexpr const TSymbolUniqueId usubBorrow_UInt4_UInt4_UInt4 = TSymbolUniqueId(3598); + static constexpr const TSymbolUniqueId umulExtended_UInt1_UInt1_UInt1_UInt1 = + TSymbolUniqueId(3599); + static constexpr const TSymbolUniqueId umulExtended_UInt2_UInt2_UInt2_UInt2 = + TSymbolUniqueId(3600); + static constexpr const TSymbolUniqueId umulExtended_UInt3_UInt3_UInt3_UInt3 = + TSymbolUniqueId(3601); + static constexpr const TSymbolUniqueId umulExtended_UInt4_UInt4_UInt4_UInt4 = + TSymbolUniqueId(3602); + static constexpr const TSymbolUniqueId imulExtended_Int1_Int1_Int1_Int1 = TSymbolUniqueId(3603); + static constexpr const TSymbolUniqueId imulExtended_Int2_Int2_Int2_Int2 = TSymbolUniqueId(3604); + static constexpr const TSymbolUniqueId imulExtended_Int3_Int3_Int3_Int3 = TSymbolUniqueId(3605); + static constexpr const TSymbolUniqueId imulExtended_Int4_Int4_Int4_Int4 = TSymbolUniqueId(3606); + static constexpr const TSymbolUniqueId texture2D_Sampler2D1_Float2 = TSymbolUniqueId(3607); + static constexpr const TSymbolUniqueId pt00I = TSymbolUniqueId(3608); + static constexpr const TSymbolUniqueId texture2DProj_Sampler2D1_Float3 = TSymbolUniqueId(3609); + static constexpr const TSymbolUniqueId texture2DProj_Sampler2D1_Float4 = TSymbolUniqueId(3610); + static constexpr const TSymbolUniqueId textureCube_SamplerCube1_Float3 = TSymbolUniqueId(3611); + static constexpr const TSymbolUniqueId pt00K = TSymbolUniqueId(3612); + static constexpr const TSymbolUniqueId texture3D_Sampler3D1_Float3 = TSymbolUniqueId(3613); + static constexpr const TSymbolUniqueId pt00J = TSymbolUniqueId(3614); + static constexpr const TSymbolUniqueId texture3DProj_Sampler3D1_Float4 = TSymbolUniqueId(3615); + static constexpr const TSymbolUniqueId shadow2DEXT_Sampler2DShadow1_Float3 = + TSymbolUniqueId(3616); + static constexpr const TSymbolUniqueId pt00d = TSymbolUniqueId(3617); + static constexpr const TSymbolUniqueId shadow2DProjEXT_Sampler2DShadow1_Float4 = + TSymbolUniqueId(3618); + static constexpr const TSymbolUniqueId texture2D_SamplerExternalOES1_Float2 = + TSymbolUniqueId(3619); + static constexpr const TSymbolUniqueId pt00M = TSymbolUniqueId(3620); + static constexpr const TSymbolUniqueId texture2DProj_SamplerExternalOES1_Float3 = + TSymbolUniqueId(3621); + static constexpr const TSymbolUniqueId texture2DProj_SamplerExternalOES1_Float4 = + TSymbolUniqueId(3622); + static constexpr const TSymbolUniqueId texture2DRect_Sampler2DRect1_Float2 = + TSymbolUniqueId(3623); + static constexpr const TSymbolUniqueId pt00O = TSymbolUniqueId(3624); + static constexpr const TSymbolUniqueId texture2DRectProj_Sampler2DRect1_Float3 = + TSymbolUniqueId(3625); + static constexpr const TSymbolUniqueId texture2DRectProj_Sampler2DRect1_Float4 = + TSymbolUniqueId(3626); + static constexpr const TSymbolUniqueId texture2DGradEXT_Sampler2D1_Float2_Float2_Float2 = + TSymbolUniqueId(3627); + static constexpr const TSymbolUniqueId texture2DProjGradEXT_Sampler2D1_Float3_Float2_Float2 = + TSymbolUniqueId(3628); + static constexpr const TSymbolUniqueId texture2DProjGradEXT_Sampler2D1_Float4_Float2_Float2 = + TSymbolUniqueId(3629); + static constexpr const TSymbolUniqueId textureCubeGradEXT_SamplerCube1_Float3_Float3_Float3 = + TSymbolUniqueId(3630); + static constexpr const TSymbolUniqueId textureVideoWEBGL_SamplerVideoWEBGL1_Float2 = + TSymbolUniqueId(3631); + static constexpr const TSymbolUniqueId pt00y = TSymbolUniqueId(3632); + static constexpr const TSymbolUniqueId texture2D_Sampler2D1_Float2_Float1 = + TSymbolUniqueId(3633); + static constexpr const TSymbolUniqueId texture2DProj_Sampler2D1_Float3_Float1 = + TSymbolUniqueId(3634); + static constexpr const TSymbolUniqueId texture2DProj_Sampler2D1_Float4_Float1 = + TSymbolUniqueId(3635); + static constexpr const TSymbolUniqueId textureCube_SamplerCube1_Float3_Float1 = + TSymbolUniqueId(3636); + static constexpr const TSymbolUniqueId texture3D_Sampler3D1_Float3_Float1 = + TSymbolUniqueId(3637); + static constexpr const TSymbolUniqueId texture3DProj_Sampler3D1_Float4_Float1 = + TSymbolUniqueId(3638); + static constexpr const TSymbolUniqueId texture3DLod_Sampler3D1_Float3_Float1 = + TSymbolUniqueId(3639); + static constexpr const TSymbolUniqueId texture3DProjLod_Sampler3D1_Float4_Float1 = + TSymbolUniqueId(3640); + static constexpr const TSymbolUniqueId texture2DLod_Sampler2D1_Float2_Float1 = + TSymbolUniqueId(3641); + static constexpr const TSymbolUniqueId texture2DProjLod_Sampler2D1_Float3_Float1 = + TSymbolUniqueId(3642); + static constexpr const TSymbolUniqueId texture2DProjLod_Sampler2D1_Float4_Float1 = + TSymbolUniqueId(3643); + static constexpr const TSymbolUniqueId textureCubeLod_SamplerCube1_Float3_Float1 = + TSymbolUniqueId(3644); + static constexpr const TSymbolUniqueId texture2DLodEXT_Sampler2D1_Float2_Float1 = + TSymbolUniqueId(3645); + static constexpr const TSymbolUniqueId texture2DProjLodEXT_Sampler2D1_Float3_Float1 = + TSymbolUniqueId(3646); + static constexpr const TSymbolUniqueId texture2DProjLodEXT_Sampler2D1_Float4_Float1 = + TSymbolUniqueId(3647); + static constexpr const TSymbolUniqueId textureCubeLodEXT_SamplerCube1_Float3_Float1 = + TSymbolUniqueId(3648); + static constexpr const TSymbolUniqueId texture_Sampler2D1_Float2 = TSymbolUniqueId(3649); + static constexpr const TSymbolUniqueId texture_ISampler2D1_Float2 = TSymbolUniqueId(3650); + static constexpr const TSymbolUniqueId pt00R = TSymbolUniqueId(3651); + static constexpr const TSymbolUniqueId texture_USampler2D1_Float2 = TSymbolUniqueId(3652); + static constexpr const TSymbolUniqueId pt00X = TSymbolUniqueId(3653); + static constexpr const TSymbolUniqueId texture_Sampler3D1_Float3 = TSymbolUniqueId(3654); + static constexpr const TSymbolUniqueId texture_ISampler3D1_Float3 = TSymbolUniqueId(3655); + static constexpr const TSymbolUniqueId pt00S = TSymbolUniqueId(3656); + static constexpr const TSymbolUniqueId texture_USampler3D1_Float3 = TSymbolUniqueId(3657); + static constexpr const TSymbolUniqueId pt00Y = TSymbolUniqueId(3658); + static constexpr const TSymbolUniqueId texture_SamplerCube1_Float3 = TSymbolUniqueId(3659); + static constexpr const TSymbolUniqueId texture_ISamplerCube1_Float3 = TSymbolUniqueId(3660); + static constexpr const TSymbolUniqueId pt00T = TSymbolUniqueId(3661); + static constexpr const TSymbolUniqueId texture_USamplerCube1_Float3 = TSymbolUniqueId(3662); + static constexpr const TSymbolUniqueId pt00Z = TSymbolUniqueId(3663); + static constexpr const TSymbolUniqueId texture_Sampler2DArray1_Float3 = TSymbolUniqueId(3664); + static constexpr const TSymbolUniqueId pt00L = TSymbolUniqueId(3665); + static constexpr const TSymbolUniqueId texture_ISampler2DArray1_Float3 = TSymbolUniqueId(3666); + static constexpr const TSymbolUniqueId pt00U = TSymbolUniqueId(3667); + static constexpr const TSymbolUniqueId texture_USampler2DArray1_Float3 = TSymbolUniqueId(3668); + static constexpr const TSymbolUniqueId pt00a = TSymbolUniqueId(3669); + static constexpr const TSymbolUniqueId texture_Sampler2DShadow1_Float3 = TSymbolUniqueId(3670); + static constexpr const TSymbolUniqueId texture_SamplerCubeShadow1_Float4 = + TSymbolUniqueId(3671); + static constexpr const TSymbolUniqueId pt00e = TSymbolUniqueId(3672); + static constexpr const TSymbolUniqueId texture_Sampler2DArrayShadow1_Float4 = + TSymbolUniqueId(3673); + static constexpr const TSymbolUniqueId pt00f = TSymbolUniqueId(3674); + static constexpr const TSymbolUniqueId texture_SamplerCubeArray1_Float4 = TSymbolUniqueId(3675); + static constexpr const TSymbolUniqueId pt00k = TSymbolUniqueId(3676); + static constexpr const TSymbolUniqueId texture_ISamplerCubeArray1_Float4 = + TSymbolUniqueId(3677); + static constexpr const TSymbolUniqueId pt00s = TSymbolUniqueId(3678); + static constexpr const TSymbolUniqueId texture_USamplerCubeArray1_Float4 = + TSymbolUniqueId(3679); + static constexpr const TSymbolUniqueId pt00x = TSymbolUniqueId(3680); + static constexpr const TSymbolUniqueId texture_SamplerCubeArrayShadow1_Float4_Float1 = + TSymbolUniqueId(3681); + static constexpr const TSymbolUniqueId pt00l = TSymbolUniqueId(3682); + static constexpr const TSymbolUniqueId textureExt_SamplerCubeArray1_Float4 = + TSymbolUniqueId(3683); + static constexpr const TSymbolUniqueId textureExt_ISamplerCubeArray1_Float4 = + TSymbolUniqueId(3684); + static constexpr const TSymbolUniqueId textureExt_USamplerCubeArray1_Float4 = + TSymbolUniqueId(3685); + static constexpr const TSymbolUniqueId textureExt_SamplerCubeArrayShadow1_Float4_Float1 = + TSymbolUniqueId(3686); + static constexpr const TSymbolUniqueId texture_SamplerExternalOES1_Float2 = + TSymbolUniqueId(3687); + static constexpr const TSymbolUniqueId texture_SamplerExternal2DY2YEXT1_Float2 = + TSymbolUniqueId(3688); + static constexpr const TSymbolUniqueId pt00N = TSymbolUniqueId(3689); + static constexpr const TSymbolUniqueId texture_Sampler2DRect1_Float2 = TSymbolUniqueId(3690); + static constexpr const TSymbolUniqueId texture_SamplerVideoWEBGL1_Float2 = + TSymbolUniqueId(3691); + static constexpr const TSymbolUniqueId textureProj_Sampler2D1_Float3 = TSymbolUniqueId(3692); + static constexpr const TSymbolUniqueId textureProj_ISampler2D1_Float3 = TSymbolUniqueId(3693); + static constexpr const TSymbolUniqueId textureProj_USampler2D1_Float3 = TSymbolUniqueId(3694); + static constexpr const TSymbolUniqueId textureProj_Sampler2D1_Float4 = TSymbolUniqueId(3695); + static constexpr const TSymbolUniqueId textureProj_ISampler2D1_Float4 = TSymbolUniqueId(3696); + static constexpr const TSymbolUniqueId textureProj_USampler2D1_Float4 = TSymbolUniqueId(3697); + static constexpr const TSymbolUniqueId textureProj_Sampler3D1_Float4 = TSymbolUniqueId(3698); + static constexpr const TSymbolUniqueId textureProj_ISampler3D1_Float4 = TSymbolUniqueId(3699); + static constexpr const TSymbolUniqueId textureProj_USampler3D1_Float4 = TSymbolUniqueId(3700); + static constexpr const TSymbolUniqueId textureProj_Sampler2DShadow1_Float4 = + TSymbolUniqueId(3701); + static constexpr const TSymbolUniqueId textureProj_SamplerExternalOES1_Float3 = + TSymbolUniqueId(3702); + static constexpr const TSymbolUniqueId textureProj_SamplerExternalOES1_Float4 = + TSymbolUniqueId(3703); + static constexpr const TSymbolUniqueId textureProj_SamplerExternal2DY2YEXT1_Float3 = + TSymbolUniqueId(3704); + static constexpr const TSymbolUniqueId textureProj_SamplerExternal2DY2YEXT1_Float4 = + TSymbolUniqueId(3705); + static constexpr const TSymbolUniqueId textureProj_Sampler2DRect1_Float3 = + TSymbolUniqueId(3706); + static constexpr const TSymbolUniqueId textureProj_Sampler2DRect1_Float4 = + TSymbolUniqueId(3707); + static constexpr const TSymbolUniqueId textureLod_Sampler2D1_Float2_Float1 = + TSymbolUniqueId(3708); + static constexpr const TSymbolUniqueId textureLod_ISampler2D1_Float2_Float1 = + TSymbolUniqueId(3709); + static constexpr const TSymbolUniqueId textureLod_USampler2D1_Float2_Float1 = + TSymbolUniqueId(3710); + static constexpr const TSymbolUniqueId textureLod_Sampler3D1_Float3_Float1 = + TSymbolUniqueId(3711); + static constexpr const TSymbolUniqueId textureLod_ISampler3D1_Float3_Float1 = + TSymbolUniqueId(3712); + static constexpr const TSymbolUniqueId textureLod_USampler3D1_Float3_Float1 = + TSymbolUniqueId(3713); + static constexpr const TSymbolUniqueId textureLod_SamplerCube1_Float3_Float1 = + TSymbolUniqueId(3714); + static constexpr const TSymbolUniqueId textureLod_ISamplerCube1_Float3_Float1 = + TSymbolUniqueId(3715); + static constexpr const TSymbolUniqueId textureLod_USamplerCube1_Float3_Float1 = + TSymbolUniqueId(3716); + static constexpr const TSymbolUniqueId textureLod_Sampler2DArray1_Float3_Float1 = + TSymbolUniqueId(3717); + static constexpr const TSymbolUniqueId textureLod_ISampler2DArray1_Float3_Float1 = + TSymbolUniqueId(3718); + static constexpr const TSymbolUniqueId textureLod_USampler2DArray1_Float3_Float1 = + TSymbolUniqueId(3719); + static constexpr const TSymbolUniqueId textureLod_Sampler2DShadow1_Float3_Float1 = + TSymbolUniqueId(3720); + static constexpr const TSymbolUniqueId textureLod_SamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(3721); + static constexpr const TSymbolUniqueId textureLod_ISamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(3722); + static constexpr const TSymbolUniqueId textureLod_USamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(3723); + static constexpr const TSymbolUniqueId textureLodExt_SamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(3724); + static constexpr const TSymbolUniqueId textureLodExt_ISamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(3725); + static constexpr const TSymbolUniqueId textureLodExt_USamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(3726); + static constexpr const TSymbolUniqueId textureSize_Sampler2D1_Int1 = TSymbolUniqueId(3727); + static constexpr const TSymbolUniqueId textureSize_ISampler2D1_Int1 = TSymbolUniqueId(3728); + static constexpr const TSymbolUniqueId textureSize_USampler2D1_Int1 = TSymbolUniqueId(3729); + static constexpr const TSymbolUniqueId textureSize_Sampler3D1_Int1 = TSymbolUniqueId(3730); + static constexpr const TSymbolUniqueId textureSize_ISampler3D1_Int1 = TSymbolUniqueId(3731); + static constexpr const TSymbolUniqueId textureSize_USampler3D1_Int1 = TSymbolUniqueId(3732); + static constexpr const TSymbolUniqueId textureSize_SamplerCube1_Int1 = TSymbolUniqueId(3733); + static constexpr const TSymbolUniqueId textureSize_ISamplerCube1_Int1 = TSymbolUniqueId(3734); + static constexpr const TSymbolUniqueId textureSize_USamplerCube1_Int1 = TSymbolUniqueId(3735); + static constexpr const TSymbolUniqueId textureSize_Sampler2DArray1_Int1 = TSymbolUniqueId(3736); + static constexpr const TSymbolUniqueId textureSize_ISampler2DArray1_Int1 = + TSymbolUniqueId(3737); + static constexpr const TSymbolUniqueId textureSize_USampler2DArray1_Int1 = + TSymbolUniqueId(3738); + static constexpr const TSymbolUniqueId textureSize_Sampler2DShadow1_Int1 = + TSymbolUniqueId(3739); + static constexpr const TSymbolUniqueId textureSize_SamplerCubeShadow1_Int1 = + TSymbolUniqueId(3740); + static constexpr const TSymbolUniqueId textureSize_Sampler2DArrayShadow1_Int1 = + TSymbolUniqueId(3741); + static constexpr const TSymbolUniqueId textureSize_SamplerCubeArray1_Int1 = + TSymbolUniqueId(3742); + static constexpr const TSymbolUniqueId textureSize_ISamplerCubeArray1_Int1 = + TSymbolUniqueId(3743); + static constexpr const TSymbolUniqueId textureSize_USamplerCubeArray1_Int1 = + TSymbolUniqueId(3744); + static constexpr const TSymbolUniqueId textureSize_SamplerCubeArrayShadow1_Int1 = + TSymbolUniqueId(3745); + static constexpr const TSymbolUniqueId textureSizeExt_SamplerCubeArray1_Int1 = + TSymbolUniqueId(3746); + static constexpr const TSymbolUniqueId textureSizeExt_ISamplerCubeArray1_Int1 = + TSymbolUniqueId(3747); + static constexpr const TSymbolUniqueId textureSizeExt_USamplerCubeArray1_Int1 = + TSymbolUniqueId(3748); + static constexpr const TSymbolUniqueId textureSizeExt_SamplerCubeArrayShadow1_Int1 = + TSymbolUniqueId(3749); + static constexpr const TSymbolUniqueId textureSize_SamplerBuffer1 = TSymbolUniqueId(3750); + static constexpr const TSymbolUniqueId pt00j = TSymbolUniqueId(3751); + static constexpr const TSymbolUniqueId textureSize_ISamplerBuffer1 = TSymbolUniqueId(3752); + static constexpr const TSymbolUniqueId pt00r = TSymbolUniqueId(3753); + static constexpr const TSymbolUniqueId textureSize_USamplerBuffer1 = TSymbolUniqueId(3754); + static constexpr const TSymbolUniqueId pt00w = TSymbolUniqueId(3755); + static constexpr const TSymbolUniqueId textureSizeExt_SamplerBuffer1 = TSymbolUniqueId(3756); + static constexpr const TSymbolUniqueId textureSizeExt_ISamplerBuffer1 = TSymbolUniqueId(3757); + static constexpr const TSymbolUniqueId textureSizeExt_USamplerBuffer1 = TSymbolUniqueId(3758); + static constexpr const TSymbolUniqueId textureSize_Sampler2DMS1 = TSymbolUniqueId(3759); + static constexpr const TSymbolUniqueId pt00P = TSymbolUniqueId(3760); + static constexpr const TSymbolUniqueId textureSize_ISampler2DMS1 = TSymbolUniqueId(3761); + static constexpr const TSymbolUniqueId pt00V = TSymbolUniqueId(3762); + static constexpr const TSymbolUniqueId textureSize_USampler2DMS1 = TSymbolUniqueId(3763); + static constexpr const TSymbolUniqueId pt00b = TSymbolUniqueId(3764); + static constexpr const TSymbolUniqueId textureSizeExt_Sampler2DMS1 = TSymbolUniqueId(3765); + static constexpr const TSymbolUniqueId textureSizeExt_ISampler2DMS1 = TSymbolUniqueId(3766); + static constexpr const TSymbolUniqueId textureSizeExt_USampler2DMS1 = TSymbolUniqueId(3767); + static constexpr const TSymbolUniqueId textureSize_Sampler2DMSArray1 = TSymbolUniqueId(3768); + static constexpr const TSymbolUniqueId pt00Q = TSymbolUniqueId(3769); + static constexpr const TSymbolUniqueId textureSize_ISampler2DMSArray1 = TSymbolUniqueId(3770); + static constexpr const TSymbolUniqueId pt00W = TSymbolUniqueId(3771); + static constexpr const TSymbolUniqueId textureSize_USampler2DMSArray1 = TSymbolUniqueId(3772); + static constexpr const TSymbolUniqueId pt00c = TSymbolUniqueId(3773); + static constexpr const TSymbolUniqueId textureSizeExt_Sampler2DMSArray1 = TSymbolUniqueId(3774); + static constexpr const TSymbolUniqueId textureSizeExt_ISampler2DMSArray1 = + TSymbolUniqueId(3775); + static constexpr const TSymbolUniqueId textureSizeExt_USampler2DMSArray1 = + TSymbolUniqueId(3776); + static constexpr const TSymbolUniqueId textureSize_SamplerExternalOES1_Int1 = + TSymbolUniqueId(3777); + static constexpr const TSymbolUniqueId textureSize_SamplerExternal2DY2YEXT1_Int1 = + TSymbolUniqueId(3778); + static constexpr const TSymbolUniqueId textureProjLod_Sampler2D1_Float3_Float1 = + TSymbolUniqueId(3779); + static constexpr const TSymbolUniqueId textureProjLod_ISampler2D1_Float3_Float1 = + TSymbolUniqueId(3780); + static constexpr const TSymbolUniqueId textureProjLod_USampler2D1_Float3_Float1 = + TSymbolUniqueId(3781); + static constexpr const TSymbolUniqueId textureProjLod_Sampler2D1_Float4_Float1 = + TSymbolUniqueId(3782); + static constexpr const TSymbolUniqueId textureProjLod_ISampler2D1_Float4_Float1 = + TSymbolUniqueId(3783); + static constexpr const TSymbolUniqueId textureProjLod_USampler2D1_Float4_Float1 = + TSymbolUniqueId(3784); + static constexpr const TSymbolUniqueId textureProjLod_Sampler3D1_Float4_Float1 = + TSymbolUniqueId(3785); + static constexpr const TSymbolUniqueId textureProjLod_ISampler3D1_Float4_Float1 = + TSymbolUniqueId(3786); + static constexpr const TSymbolUniqueId textureProjLod_USampler3D1_Float4_Float1 = + TSymbolUniqueId(3787); + static constexpr const TSymbolUniqueId textureProjLod_Sampler2DShadow1_Float4_Float1 = + TSymbolUniqueId(3788); + static constexpr const TSymbolUniqueId texelFetch_Sampler2D1_Int2_Int1 = TSymbolUniqueId(3789); + static constexpr const TSymbolUniqueId texelFetch_ISampler2D1_Int2_Int1 = TSymbolUniqueId(3790); + static constexpr const TSymbolUniqueId texelFetch_USampler2D1_Int2_Int1 = TSymbolUniqueId(3791); + static constexpr const TSymbolUniqueId texelFetch_Sampler3D1_Int3_Int1 = TSymbolUniqueId(3792); + static constexpr const TSymbolUniqueId texelFetch_ISampler3D1_Int3_Int1 = TSymbolUniqueId(3793); + static constexpr const TSymbolUniqueId texelFetch_USampler3D1_Int3_Int1 = TSymbolUniqueId(3794); + static constexpr const TSymbolUniqueId texelFetch_Sampler2DArray1_Int3_Int1 = + TSymbolUniqueId(3795); + static constexpr const TSymbolUniqueId texelFetch_ISampler2DArray1_Int3_Int1 = + TSymbolUniqueId(3796); + static constexpr const TSymbolUniqueId texelFetch_USampler2DArray1_Int3_Int1 = + TSymbolUniqueId(3797); + static constexpr const TSymbolUniqueId texelFetch_SamplerBuffer1_Int1 = TSymbolUniqueId(3798); + static constexpr const TSymbolUniqueId texelFetch_ISamplerBuffer1_Int1 = TSymbolUniqueId(3799); + static constexpr const TSymbolUniqueId texelFetch_USamplerBuffer1_Int1 = TSymbolUniqueId(3800); + static constexpr const TSymbolUniqueId texelFetchExt_SamplerBuffer1_Int1 = + TSymbolUniqueId(3801); + static constexpr const TSymbolUniqueId texelFetchExt_ISamplerBuffer1_Int1 = + TSymbolUniqueId(3802); + static constexpr const TSymbolUniqueId texelFetchExt_USamplerBuffer1_Int1 = + TSymbolUniqueId(3803); + static constexpr const TSymbolUniqueId texelFetch_Sampler2DMS1_Int2_Int1 = + TSymbolUniqueId(3804); + static constexpr const TSymbolUniqueId texelFetch_ISampler2DMS1_Int2_Int1 = + TSymbolUniqueId(3805); + static constexpr const TSymbolUniqueId texelFetch_USampler2DMS1_Int2_Int1 = + TSymbolUniqueId(3806); + static constexpr const TSymbolUniqueId texelFetchExt_Sampler2DMS1_Int2_Int1 = + TSymbolUniqueId(3807); + static constexpr const TSymbolUniqueId texelFetchExt_ISampler2DMS1_Int2_Int1 = + TSymbolUniqueId(3808); + static constexpr const TSymbolUniqueId texelFetchExt_USampler2DMS1_Int2_Int1 = + TSymbolUniqueId(3809); + static constexpr const TSymbolUniqueId texelFetch_Sampler2DMSArray1_Int3_Int1 = + TSymbolUniqueId(3810); + static constexpr const TSymbolUniqueId texelFetch_ISampler2DMSArray1_Int3_Int1 = + TSymbolUniqueId(3811); + static constexpr const TSymbolUniqueId texelFetch_USampler2DMSArray1_Int3_Int1 = + TSymbolUniqueId(3812); + static constexpr const TSymbolUniqueId texelFetchExt_Sampler2DMSArray1_Int3_Int1 = + TSymbolUniqueId(3813); + static constexpr const TSymbolUniqueId texelFetchExt_ISampler2DMSArray1_Int3_Int1 = + TSymbolUniqueId(3814); + static constexpr const TSymbolUniqueId texelFetchExt_USampler2DMSArray1_Int3_Int1 = + TSymbolUniqueId(3815); + static constexpr const TSymbolUniqueId texelFetch_SamplerExternalOES1_Int2_Int1 = + TSymbolUniqueId(3816); + static constexpr const TSymbolUniqueId texelFetch_SamplerExternal2DY2YEXT1_Int2_Int1 = + TSymbolUniqueId(3817); + static constexpr const TSymbolUniqueId textureGrad_Sampler2D1_Float2_Float2_Float2 = + TSymbolUniqueId(3818); + static constexpr const TSymbolUniqueId textureGrad_ISampler2D1_Float2_Float2_Float2 = + TSymbolUniqueId(3819); + static constexpr const TSymbolUniqueId textureGrad_USampler2D1_Float2_Float2_Float2 = + TSymbolUniqueId(3820); + static constexpr const TSymbolUniqueId textureGrad_Sampler3D1_Float3_Float3_Float3 = + TSymbolUniqueId(3821); + static constexpr const TSymbolUniqueId textureGrad_ISampler3D1_Float3_Float3_Float3 = + TSymbolUniqueId(3822); + static constexpr const TSymbolUniqueId textureGrad_USampler3D1_Float3_Float3_Float3 = + TSymbolUniqueId(3823); + static constexpr const TSymbolUniqueId textureGrad_SamplerCube1_Float3_Float3_Float3 = + TSymbolUniqueId(3824); + static constexpr const TSymbolUniqueId textureGrad_ISamplerCube1_Float3_Float3_Float3 = + TSymbolUniqueId(3825); + static constexpr const TSymbolUniqueId textureGrad_USamplerCube1_Float3_Float3_Float3 = + TSymbolUniqueId(3826); + static constexpr const TSymbolUniqueId textureGrad_Sampler2DShadow1_Float3_Float2_Float2 = + TSymbolUniqueId(3827); + static constexpr const TSymbolUniqueId textureGrad_SamplerCubeShadow1_Float4_Float3_Float3 = + TSymbolUniqueId(3828); + static constexpr const TSymbolUniqueId textureGrad_Sampler2DArray1_Float3_Float2_Float2 = + TSymbolUniqueId(3829); + static constexpr const TSymbolUniqueId textureGrad_ISampler2DArray1_Float3_Float2_Float2 = + TSymbolUniqueId(3830); + static constexpr const TSymbolUniqueId textureGrad_USampler2DArray1_Float3_Float2_Float2 = + TSymbolUniqueId(3831); + static constexpr const TSymbolUniqueId textureGrad_Sampler2DArrayShadow1_Float4_Float2_Float2 = + TSymbolUniqueId(3832); + static constexpr const TSymbolUniqueId textureGrad_SamplerCubeArray1_Float4_Float3_Float3 = + TSymbolUniqueId(3833); + static constexpr const TSymbolUniqueId textureGrad_ISamplerCubeArray1_Float4_Float3_Float3 = + TSymbolUniqueId(3834); + static constexpr const TSymbolUniqueId textureGrad_USamplerCubeArray1_Float4_Float3_Float3 = + TSymbolUniqueId(3835); + static constexpr const TSymbolUniqueId textureGradExt_SamplerCubeArray1_Float4_Float3_Float3 = + TSymbolUniqueId(3836); + static constexpr const TSymbolUniqueId textureGradExt_ISamplerCubeArray1_Float4_Float3_Float3 = + TSymbolUniqueId(3837); + static constexpr const TSymbolUniqueId textureGradExt_USamplerCubeArray1_Float4_Float3_Float3 = + TSymbolUniqueId(3838); + static constexpr const TSymbolUniqueId textureProjGrad_Sampler2D1_Float3_Float2_Float2 = + TSymbolUniqueId(3839); + static constexpr const TSymbolUniqueId textureProjGrad_ISampler2D1_Float3_Float2_Float2 = + TSymbolUniqueId(3840); + static constexpr const TSymbolUniqueId textureProjGrad_USampler2D1_Float3_Float2_Float2 = + TSymbolUniqueId(3841); + static constexpr const TSymbolUniqueId textureProjGrad_Sampler2D1_Float4_Float2_Float2 = + TSymbolUniqueId(3842); + static constexpr const TSymbolUniqueId textureProjGrad_ISampler2D1_Float4_Float2_Float2 = + TSymbolUniqueId(3843); + static constexpr const TSymbolUniqueId textureProjGrad_USampler2D1_Float4_Float2_Float2 = + TSymbolUniqueId(3844); + static constexpr const TSymbolUniqueId textureProjGrad_Sampler3D1_Float4_Float3_Float3 = + TSymbolUniqueId(3845); + static constexpr const TSymbolUniqueId textureProjGrad_ISampler3D1_Float4_Float3_Float3 = + TSymbolUniqueId(3846); + static constexpr const TSymbolUniqueId textureProjGrad_USampler3D1_Float4_Float3_Float3 = + TSymbolUniqueId(3847); + static constexpr const TSymbolUniqueId textureProjGrad_Sampler2DShadow1_Float4_Float2_Float2 = + TSymbolUniqueId(3848); + static constexpr const TSymbolUniqueId texture_Sampler2D1_Float2_Float1 = TSymbolUniqueId(3849); + static constexpr const TSymbolUniqueId texture_ISampler2D1_Float2_Float1 = + TSymbolUniqueId(3850); + static constexpr const TSymbolUniqueId texture_USampler2D1_Float2_Float1 = + TSymbolUniqueId(3851); + static constexpr const TSymbolUniqueId texture_Sampler3D1_Float3_Float1 = TSymbolUniqueId(3852); + static constexpr const TSymbolUniqueId texture_ISampler3D1_Float3_Float1 = + TSymbolUniqueId(3853); + static constexpr const TSymbolUniqueId texture_USampler3D1_Float3_Float1 = + TSymbolUniqueId(3854); + static constexpr const TSymbolUniqueId texture_SamplerCube1_Float3_Float1 = + TSymbolUniqueId(3855); + static constexpr const TSymbolUniqueId texture_ISamplerCube1_Float3_Float1 = + TSymbolUniqueId(3856); + static constexpr const TSymbolUniqueId texture_USamplerCube1_Float3_Float1 = + TSymbolUniqueId(3857); + static constexpr const TSymbolUniqueId texture_Sampler2DArray1_Float3_Float1 = + TSymbolUniqueId(3858); + static constexpr const TSymbolUniqueId texture_ISampler2DArray1_Float3_Float1 = + TSymbolUniqueId(3859); + static constexpr const TSymbolUniqueId texture_USampler2DArray1_Float3_Float1 = + TSymbolUniqueId(3860); + static constexpr const TSymbolUniqueId textureProj_Sampler2D1_Float3_Float1 = + TSymbolUniqueId(3861); + static constexpr const TSymbolUniqueId textureProj_ISampler2D1_Float3_Float1 = + TSymbolUniqueId(3862); + static constexpr const TSymbolUniqueId textureProj_USampler2D1_Float3_Float1 = + TSymbolUniqueId(3863); + static constexpr const TSymbolUniqueId textureProj_Sampler2D1_Float4_Float1 = + TSymbolUniqueId(3864); + static constexpr const TSymbolUniqueId textureProj_ISampler2D1_Float4_Float1 = + TSymbolUniqueId(3865); + static constexpr const TSymbolUniqueId textureProj_USampler2D1_Float4_Float1 = + TSymbolUniqueId(3866); + static constexpr const TSymbolUniqueId textureProj_Sampler3D1_Float4_Float1 = + TSymbolUniqueId(3867); + static constexpr const TSymbolUniqueId textureProj_ISampler3D1_Float4_Float1 = + TSymbolUniqueId(3868); + static constexpr const TSymbolUniqueId textureProj_USampler3D1_Float4_Float1 = + TSymbolUniqueId(3869); + static constexpr const TSymbolUniqueId texture_Sampler2DShadow1_Float3_Float1 = + TSymbolUniqueId(3870); + static constexpr const TSymbolUniqueId texture_SamplerCubeShadow1_Float4_Float1 = + TSymbolUniqueId(3871); + static constexpr const TSymbolUniqueId textureProj_Sampler2DShadow1_Float4_Float1 = + TSymbolUniqueId(3872); + static constexpr const TSymbolUniqueId texture_SamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(3873); + static constexpr const TSymbolUniqueId texture_ISamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(3874); + static constexpr const TSymbolUniqueId texture_USamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(3875); + static constexpr const TSymbolUniqueId textureExt_SamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(3876); + static constexpr const TSymbolUniqueId textureExt_ISamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(3877); + static constexpr const TSymbolUniqueId textureExt_USamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(3878); + static constexpr const TSymbolUniqueId texture_SamplerExternalOES1_Float2_Float1 = + TSymbolUniqueId(3879); + static constexpr const TSymbolUniqueId textureProj_SamplerExternalOES1_Float3_Float1 = + TSymbolUniqueId(3880); + static constexpr const TSymbolUniqueId textureProj_SamplerExternalOES1_Float4_Float1 = + TSymbolUniqueId(3881); + static constexpr const TSymbolUniqueId texture_SamplerExternal2DY2YEXT1_Float2_Float1 = + TSymbolUniqueId(3882); + static constexpr const TSymbolUniqueId textureProj_SamplerExternal2DY2YEXT1_Float3_Float1 = + TSymbolUniqueId(3883); + static constexpr const TSymbolUniqueId textureProj_SamplerExternal2DY2YEXT1_Float4_Float1 = + TSymbolUniqueId(3884); + static constexpr const TSymbolUniqueId textureOffset_Sampler2D1_Float2_Int2 = + TSymbolUniqueId(3885); + static constexpr const TSymbolUniqueId textureOffset_ISampler2D1_Float2_Int2 = + TSymbolUniqueId(3886); + static constexpr const TSymbolUniqueId textureOffset_USampler2D1_Float2_Int2 = + TSymbolUniqueId(3887); + static constexpr const TSymbolUniqueId textureOffset_Sampler3D1_Float3_Int3 = + TSymbolUniqueId(3888); + static constexpr const TSymbolUniqueId textureOffset_ISampler3D1_Float3_Int3 = + TSymbolUniqueId(3889); + static constexpr const TSymbolUniqueId textureOffset_USampler3D1_Float3_Int3 = + TSymbolUniqueId(3890); + static constexpr const TSymbolUniqueId textureOffset_Sampler2DShadow1_Float3_Int2 = + TSymbolUniqueId(3891); + static constexpr const TSymbolUniqueId textureOffset_Sampler2DArray1_Float3_Int2 = + TSymbolUniqueId(3892); + static constexpr const TSymbolUniqueId textureOffset_ISampler2DArray1_Float3_Int2 = + TSymbolUniqueId(3893); + static constexpr const TSymbolUniqueId textureOffset_USampler2DArray1_Float3_Int2 = + TSymbolUniqueId(3894); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2D1_Float3_Int2 = + TSymbolUniqueId(3895); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler2D1_Float3_Int2 = + TSymbolUniqueId(3896); + static constexpr const TSymbolUniqueId textureProjOffset_USampler2D1_Float3_Int2 = + TSymbolUniqueId(3897); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2D1_Float4_Int2 = + TSymbolUniqueId(3898); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler2D1_Float4_Int2 = + TSymbolUniqueId(3899); + static constexpr const TSymbolUniqueId textureProjOffset_USampler2D1_Float4_Int2 = + TSymbolUniqueId(3900); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler3D1_Float4_Int3 = + TSymbolUniqueId(3901); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler3D1_Float4_Int3 = + TSymbolUniqueId(3902); + static constexpr const TSymbolUniqueId textureProjOffset_USampler3D1_Float4_Int3 = + TSymbolUniqueId(3903); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2DShadow1_Float4_Int2 = + TSymbolUniqueId(3904); + static constexpr const TSymbolUniqueId textureLodOffset_Sampler2D1_Float2_Float1_Int2 = + TSymbolUniqueId(3905); + static constexpr const TSymbolUniqueId textureLodOffset_ISampler2D1_Float2_Float1_Int2 = + TSymbolUniqueId(3906); + static constexpr const TSymbolUniqueId textureLodOffset_USampler2D1_Float2_Float1_Int2 = + TSymbolUniqueId(3907); + static constexpr const TSymbolUniqueId textureLodOffset_Sampler3D1_Float3_Float1_Int3 = + TSymbolUniqueId(3908); + static constexpr const TSymbolUniqueId textureLodOffset_ISampler3D1_Float3_Float1_Int3 = + TSymbolUniqueId(3909); + static constexpr const TSymbolUniqueId textureLodOffset_USampler3D1_Float3_Float1_Int3 = + TSymbolUniqueId(3910); + static constexpr const TSymbolUniqueId textureLodOffset_Sampler2DShadow1_Float3_Float1_Int2 = + TSymbolUniqueId(3911); + static constexpr const TSymbolUniqueId textureLodOffset_Sampler2DArray1_Float3_Float1_Int2 = + TSymbolUniqueId(3912); + static constexpr const TSymbolUniqueId textureLodOffset_ISampler2DArray1_Float3_Float1_Int2 = + TSymbolUniqueId(3913); + static constexpr const TSymbolUniqueId textureLodOffset_USampler2DArray1_Float3_Float1_Int2 = + TSymbolUniqueId(3914); + static constexpr const TSymbolUniqueId textureProjLodOffset_Sampler2D1_Float3_Float1_Int2 = + TSymbolUniqueId(3915); + static constexpr const TSymbolUniqueId textureProjLodOffset_ISampler2D1_Float3_Float1_Int2 = + TSymbolUniqueId(3916); + static constexpr const TSymbolUniqueId textureProjLodOffset_USampler2D1_Float3_Float1_Int2 = + TSymbolUniqueId(3917); + static constexpr const TSymbolUniqueId textureProjLodOffset_Sampler2D1_Float4_Float1_Int2 = + TSymbolUniqueId(3918); + static constexpr const TSymbolUniqueId textureProjLodOffset_ISampler2D1_Float4_Float1_Int2 = + TSymbolUniqueId(3919); + static constexpr const TSymbolUniqueId textureProjLodOffset_USampler2D1_Float4_Float1_Int2 = + TSymbolUniqueId(3920); + static constexpr const TSymbolUniqueId textureProjLodOffset_Sampler3D1_Float4_Float1_Int3 = + TSymbolUniqueId(3921); + static constexpr const TSymbolUniqueId textureProjLodOffset_ISampler3D1_Float4_Float1_Int3 = + TSymbolUniqueId(3922); + static constexpr const TSymbolUniqueId textureProjLodOffset_USampler3D1_Float4_Float1_Int3 = + TSymbolUniqueId(3923); + static constexpr const TSymbolUniqueId + textureProjLodOffset_Sampler2DShadow1_Float4_Float1_Int2 = TSymbolUniqueId(3924); + static constexpr const TSymbolUniqueId texelFetchOffset_Sampler2D1_Int2_Int1_Int2 = + TSymbolUniqueId(3925); + static constexpr const TSymbolUniqueId texelFetchOffset_ISampler2D1_Int2_Int1_Int2 = + TSymbolUniqueId(3926); + static constexpr const TSymbolUniqueId texelFetchOffset_USampler2D1_Int2_Int1_Int2 = + TSymbolUniqueId(3927); + static constexpr const TSymbolUniqueId texelFetchOffset_Sampler3D1_Int3_Int1_Int3 = + TSymbolUniqueId(3928); + static constexpr const TSymbolUniqueId texelFetchOffset_ISampler3D1_Int3_Int1_Int3 = + TSymbolUniqueId(3929); + static constexpr const TSymbolUniqueId texelFetchOffset_USampler3D1_Int3_Int1_Int3 = + TSymbolUniqueId(3930); + static constexpr const TSymbolUniqueId texelFetchOffset_Sampler2DArray1_Int3_Int1_Int2 = + TSymbolUniqueId(3931); + static constexpr const TSymbolUniqueId texelFetchOffset_ISampler2DArray1_Int3_Int1_Int2 = + TSymbolUniqueId(3932); + static constexpr const TSymbolUniqueId texelFetchOffset_USampler2DArray1_Int3_Int1_Int2 = + TSymbolUniqueId(3933); + static constexpr const TSymbolUniqueId textureGradOffset_Sampler2D1_Float2_Float2_Float2_Int2 = + TSymbolUniqueId(3934); + static constexpr const TSymbolUniqueId textureGradOffset_ISampler2D1_Float2_Float2_Float2_Int2 = + TSymbolUniqueId(3935); + static constexpr const TSymbolUniqueId textureGradOffset_USampler2D1_Float2_Float2_Float2_Int2 = + TSymbolUniqueId(3936); + static constexpr const TSymbolUniqueId textureGradOffset_Sampler3D1_Float3_Float3_Float3_Int3 = + TSymbolUniqueId(3937); + static constexpr const TSymbolUniqueId textureGradOffset_ISampler3D1_Float3_Float3_Float3_Int3 = + TSymbolUniqueId(3938); + static constexpr const TSymbolUniqueId textureGradOffset_USampler3D1_Float3_Float3_Float3_Int3 = + TSymbolUniqueId(3939); + static constexpr const TSymbolUniqueId + textureGradOffset_Sampler2DShadow1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(3940); + static constexpr const TSymbolUniqueId + textureGradOffset_Sampler2DArray1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(3941); + static constexpr const TSymbolUniqueId + textureGradOffset_ISampler2DArray1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(3942); + static constexpr const TSymbolUniqueId + textureGradOffset_USampler2DArray1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(3943); + static constexpr const TSymbolUniqueId + textureGradOffset_Sampler2DArrayShadow1_Float4_Float2_Float2_Int2 = TSymbolUniqueId(3944); + static constexpr const TSymbolUniqueId + textureProjGradOffset_Sampler2D1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(3945); + static constexpr const TSymbolUniqueId + textureProjGradOffset_ISampler2D1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(3946); + static constexpr const TSymbolUniqueId + textureProjGradOffset_USampler2D1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(3947); + static constexpr const TSymbolUniqueId + textureProjGradOffset_Sampler2D1_Float4_Float2_Float2_Int2 = TSymbolUniqueId(3948); + static constexpr const TSymbolUniqueId + textureProjGradOffset_ISampler2D1_Float4_Float2_Float2_Int2 = TSymbolUniqueId(3949); + static constexpr const TSymbolUniqueId + textureProjGradOffset_USampler2D1_Float4_Float2_Float2_Int2 = TSymbolUniqueId(3950); + static constexpr const TSymbolUniqueId + textureProjGradOffset_Sampler3D1_Float4_Float3_Float3_Int3 = TSymbolUniqueId(3951); + static constexpr const TSymbolUniqueId + textureProjGradOffset_ISampler3D1_Float4_Float3_Float3_Int3 = TSymbolUniqueId(3952); + static constexpr const TSymbolUniqueId + textureProjGradOffset_USampler3D1_Float4_Float3_Float3_Int3 = TSymbolUniqueId(3953); + static constexpr const TSymbolUniqueId + textureProjGradOffset_Sampler2DShadow1_Float4_Float2_Float2_Int2 = TSymbolUniqueId(3954); + static constexpr const TSymbolUniqueId textureOffset_Sampler2D1_Float2_Int2_Float1 = + TSymbolUniqueId(3955); + static constexpr const TSymbolUniqueId textureOffset_ISampler2D1_Float2_Int2_Float1 = + TSymbolUniqueId(3956); + static constexpr const TSymbolUniqueId textureOffset_USampler2D1_Float2_Int2_Float1 = + TSymbolUniqueId(3957); + static constexpr const TSymbolUniqueId textureOffset_Sampler3D1_Float3_Int3_Float1 = + TSymbolUniqueId(3958); + static constexpr const TSymbolUniqueId textureOffset_ISampler3D1_Float3_Int3_Float1 = + TSymbolUniqueId(3959); + static constexpr const TSymbolUniqueId textureOffset_USampler3D1_Float3_Int3_Float1 = + TSymbolUniqueId(3960); + static constexpr const TSymbolUniqueId textureOffset_Sampler2DShadow1_Float3_Int2_Float1 = + TSymbolUniqueId(3961); + static constexpr const TSymbolUniqueId textureOffset_Sampler2DArray1_Float3_Int2_Float1 = + TSymbolUniqueId(3962); + static constexpr const TSymbolUniqueId textureOffset_ISampler2DArray1_Float3_Int2_Float1 = + TSymbolUniqueId(3963); + static constexpr const TSymbolUniqueId textureOffset_USampler2DArray1_Float3_Int2_Float1 = + TSymbolUniqueId(3964); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2D1_Float3_Int2_Float1 = + TSymbolUniqueId(3965); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler2D1_Float3_Int2_Float1 = + TSymbolUniqueId(3966); + static constexpr const TSymbolUniqueId textureProjOffset_USampler2D1_Float3_Int2_Float1 = + TSymbolUniqueId(3967); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2D1_Float4_Int2_Float1 = + TSymbolUniqueId(3968); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler2D1_Float4_Int2_Float1 = + TSymbolUniqueId(3969); + static constexpr const TSymbolUniqueId textureProjOffset_USampler2D1_Float4_Int2_Float1 = + TSymbolUniqueId(3970); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler3D1_Float4_Int3_Float1 = + TSymbolUniqueId(3971); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler3D1_Float4_Int3_Float1 = + TSymbolUniqueId(3972); + static constexpr const TSymbolUniqueId textureProjOffset_USampler3D1_Float4_Int3_Float1 = + TSymbolUniqueId(3973); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2DShadow1_Float4_Int2_Float1 = + TSymbolUniqueId(3974); + static constexpr const TSymbolUniqueId textureGather_Sampler2D1_Float2 = TSymbolUniqueId(3975); + static constexpr const TSymbolUniqueId textureGather_ISampler2D1_Float2 = TSymbolUniqueId(3976); + static constexpr const TSymbolUniqueId textureGather_USampler2D1_Float2 = TSymbolUniqueId(3977); + static constexpr const TSymbolUniqueId textureGather_Sampler2D1_Float2_Int1 = + TSymbolUniqueId(3978); + static constexpr const TSymbolUniqueId textureGather_ISampler2D1_Float2_Int1 = + TSymbolUniqueId(3979); + static constexpr const TSymbolUniqueId textureGather_USampler2D1_Float2_Int1 = + TSymbolUniqueId(3980); + static constexpr const TSymbolUniqueId textureGather_Sampler2DArray1_Float3 = + TSymbolUniqueId(3981); + static constexpr const TSymbolUniqueId textureGather_ISampler2DArray1_Float3 = + TSymbolUniqueId(3982); + static constexpr const TSymbolUniqueId textureGather_USampler2DArray1_Float3 = + TSymbolUniqueId(3983); + static constexpr const TSymbolUniqueId textureGather_Sampler2DArray1_Float3_Int1 = + TSymbolUniqueId(3984); + static constexpr const TSymbolUniqueId textureGather_ISampler2DArray1_Float3_Int1 = + TSymbolUniqueId(3985); + static constexpr const TSymbolUniqueId textureGather_USampler2DArray1_Float3_Int1 = + TSymbolUniqueId(3986); + static constexpr const TSymbolUniqueId textureGather_SamplerCube1_Float3 = + TSymbolUniqueId(3987); + static constexpr const TSymbolUniqueId textureGather_ISamplerCube1_Float3 = + TSymbolUniqueId(3988); + static constexpr const TSymbolUniqueId textureGather_USamplerCube1_Float3 = + TSymbolUniqueId(3989); + static constexpr const TSymbolUniqueId textureGather_SamplerCube1_Float3_Int1 = + TSymbolUniqueId(3990); + static constexpr const TSymbolUniqueId textureGather_ISamplerCube1_Float3_Int1 = + TSymbolUniqueId(3991); + static constexpr const TSymbolUniqueId textureGather_USamplerCube1_Float3_Int1 = + TSymbolUniqueId(3992); + static constexpr const TSymbolUniqueId textureGather_SamplerCubeArray1_Float4 = + TSymbolUniqueId(3993); + static constexpr const TSymbolUniqueId textureGather_ISamplerCubeArray1_Float4 = + TSymbolUniqueId(3994); + static constexpr const TSymbolUniqueId textureGather_USamplerCubeArray1_Float4 = + TSymbolUniqueId(3995); + static constexpr const TSymbolUniqueId textureGather_SamplerCubeArray1_Float4_Int1 = + TSymbolUniqueId(3996); + static constexpr const TSymbolUniqueId textureGather_ISamplerCubeArray1_Float4_Int1 = + TSymbolUniqueId(3997); + static constexpr const TSymbolUniqueId textureGather_USamplerCubeArray1_Float4_Int1 = + TSymbolUniqueId(3998); + static constexpr const TSymbolUniqueId textureGather_SamplerCubeArrayShadow1_Float4_Float1 = + TSymbolUniqueId(3999); + static constexpr const TSymbolUniqueId textureGatherExt_SamplerCubeArray1_Float4 = + TSymbolUniqueId(4000); + static constexpr const TSymbolUniqueId textureGatherExt_ISamplerCubeArray1_Float4 = + TSymbolUniqueId(4001); + static constexpr const TSymbolUniqueId textureGatherExt_USamplerCubeArray1_Float4 = + TSymbolUniqueId(4002); + static constexpr const TSymbolUniqueId textureGatherExt_SamplerCubeArray1_Float4_Int1 = + TSymbolUniqueId(4003); + static constexpr const TSymbolUniqueId textureGatherExt_ISamplerCubeArray1_Float4_Int1 = + TSymbolUniqueId(4004); + static constexpr const TSymbolUniqueId textureGatherExt_USamplerCubeArray1_Float4_Int1 = + TSymbolUniqueId(4005); + static constexpr const TSymbolUniqueId textureGatherExt_SamplerCubeArrayShadow1_Float4_Float1 = + TSymbolUniqueId(4006); + static constexpr const TSymbolUniqueId textureGather_Sampler2DShadow1_Float2 = + TSymbolUniqueId(4007); + static constexpr const TSymbolUniqueId textureGather_Sampler2DShadow1_Float2_Float1 = + TSymbolUniqueId(4008); + static constexpr const TSymbolUniqueId textureGather_Sampler2DArrayShadow1_Float3 = + TSymbolUniqueId(4009); + static constexpr const TSymbolUniqueId textureGather_Sampler2DArrayShadow1_Float3_Float1 = + TSymbolUniqueId(4010); + static constexpr const TSymbolUniqueId textureGather_SamplerCubeShadow1_Float3 = + TSymbolUniqueId(4011); + static constexpr const TSymbolUniqueId textureGather_SamplerCubeShadow1_Float3_Float1 = + TSymbolUniqueId(4012); + static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2D1_Float2_Int2 = + TSymbolUniqueId(4013); + static constexpr const TSymbolUniqueId textureGatherOffset_ISampler2D1_Float2_Int2 = + TSymbolUniqueId(4014); + static constexpr const TSymbolUniqueId textureGatherOffset_USampler2D1_Float2_Int2 = + TSymbolUniqueId(4015); + static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2DArray1_Float3_Int2 = + TSymbolUniqueId(4016); + static constexpr const TSymbolUniqueId textureGatherOffset_ISampler2DArray1_Float3_Int2 = + TSymbolUniqueId(4017); + static constexpr const TSymbolUniqueId textureGatherOffset_USampler2DArray1_Float3_Int2 = + TSymbolUniqueId(4018); + static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2DShadow1_Float2_Float1_Int2 = + TSymbolUniqueId(4019); + static constexpr const TSymbolUniqueId + textureGatherOffset_Sampler2DArrayShadow1_Float3_Float1_Int2 = TSymbolUniqueId(4020); + static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2D1_Float2_Int2_Int1 = + TSymbolUniqueId(4021); + static constexpr const TSymbolUniqueId textureGatherOffset_ISampler2D1_Float2_Int2_Int1 = + TSymbolUniqueId(4022); + static constexpr const TSymbolUniqueId textureGatherOffset_USampler2D1_Float2_Int2_Int1 = + TSymbolUniqueId(4023); + static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2DArray1_Float3_Int2_Int1 = + TSymbolUniqueId(4024); + static constexpr const TSymbolUniqueId textureGatherOffset_ISampler2DArray1_Float3_Int2_Int1 = + TSymbolUniqueId(4025); + static constexpr const TSymbolUniqueId textureGatherOffset_USampler2DArray1_Float3_Int2_Int1 = + TSymbolUniqueId(4026); + static constexpr const TSymbolUniqueId textureGatherOffsets_Sampler2D1_Float2_4xInt2 = + TSymbolUniqueId(4027); + static constexpr const TSymbolUniqueId pt10Dx4 = TSymbolUniqueId(4028); + static constexpr const TSymbolUniqueId textureGatherOffsets_ISampler2D1_Float2_4xInt2 = + TSymbolUniqueId(4029); + static constexpr const TSymbolUniqueId textureGatherOffsets_USampler2D1_Float2_4xInt2 = + TSymbolUniqueId(4030); + static constexpr const TSymbolUniqueId textureGatherOffsets_Sampler2DArray1_Float3_4xInt2 = + TSymbolUniqueId(4031); + static constexpr const TSymbolUniqueId textureGatherOffsets_ISampler2DArray1_Float3_4xInt2 = + TSymbolUniqueId(4032); + static constexpr const TSymbolUniqueId textureGatherOffsets_USampler2DArray1_Float3_4xInt2 = + TSymbolUniqueId(4033); + static constexpr const TSymbolUniqueId + textureGatherOffsets_Sampler2DShadow1_Float2_Float1_4xInt2 = TSymbolUniqueId(4034); + static constexpr const TSymbolUniqueId + textureGatherOffsets_Sampler2DArrayShadow1_Float3_Float1_4xInt2 = TSymbolUniqueId(4035); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_Sampler2D1_Float2_4xInt2 = + TSymbolUniqueId(4036); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_ISampler2D1_Float2_4xInt2 = + TSymbolUniqueId(4037); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_USampler2D1_Float2_4xInt2 = + TSymbolUniqueId(4038); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_Sampler2DArray1_Float3_4xInt2 = + TSymbolUniqueId(4039); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_ISampler2DArray1_Float3_4xInt2 = + TSymbolUniqueId(4040); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_USampler2DArray1_Float3_4xInt2 = + TSymbolUniqueId(4041); + static constexpr const TSymbolUniqueId + textureGatherOffsetsExt_Sampler2DShadow1_Float2_Float1_4xInt2 = TSymbolUniqueId(4042); + static constexpr const TSymbolUniqueId + textureGatherOffsetsExt_Sampler2DArrayShadow1_Float3_Float1_4xInt2 = TSymbolUniqueId(4043); + static constexpr const TSymbolUniqueId textureGatherOffsets_Sampler2D1_Float2_4xInt2_Int1 = + TSymbolUniqueId(4044); + static constexpr const TSymbolUniqueId textureGatherOffsets_ISampler2D1_Float2_4xInt2_Int1 = + TSymbolUniqueId(4045); + static constexpr const TSymbolUniqueId textureGatherOffsets_USampler2D1_Float2_4xInt2_Int1 = + TSymbolUniqueId(4046); + static constexpr const TSymbolUniqueId textureGatherOffsets_Sampler2DArray1_Float3_4xInt2_Int1 = + TSymbolUniqueId(4047); + static constexpr const TSymbolUniqueId + textureGatherOffsets_ISampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(4048); + static constexpr const TSymbolUniqueId + textureGatherOffsets_USampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(4049); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_Sampler2D1_Float2_4xInt2_Int1 = + TSymbolUniqueId(4050); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_ISampler2D1_Float2_4xInt2_Int1 = + TSymbolUniqueId(4051); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_USampler2D1_Float2_4xInt2_Int1 = + TSymbolUniqueId(4052); + static constexpr const TSymbolUniqueId + textureGatherOffsetsExt_Sampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(4053); + static constexpr const TSymbolUniqueId + textureGatherOffsetsExt_ISampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(4054); + static constexpr const TSymbolUniqueId + textureGatherOffsetsExt_USampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(4055); + static constexpr const TSymbolUniqueId rgb_2_yuv_Float3_YuvCscStandardEXT1 = + TSymbolUniqueId(4056); + static constexpr const TSymbolUniqueId pt00H = TSymbolUniqueId(4057); + static constexpr const TSymbolUniqueId yuv_2_rgb_Float3_YuvCscStandardEXT1 = + TSymbolUniqueId(4058); + static constexpr const TSymbolUniqueId dFdxExt_Float1 = TSymbolUniqueId(4059); + static constexpr const TSymbolUniqueId dFdxExt_Float2 = TSymbolUniqueId(4060); + static constexpr const TSymbolUniqueId dFdxExt_Float3 = TSymbolUniqueId(4061); + static constexpr const TSymbolUniqueId dFdxExt_Float4 = TSymbolUniqueId(4062); + static constexpr const TSymbolUniqueId dFdyExt_Float1 = TSymbolUniqueId(4063); + static constexpr const TSymbolUniqueId dFdyExt_Float2 = TSymbolUniqueId(4064); + static constexpr const TSymbolUniqueId dFdyExt_Float3 = TSymbolUniqueId(4065); + static constexpr const TSymbolUniqueId dFdyExt_Float4 = TSymbolUniqueId(4066); + static constexpr const TSymbolUniqueId fwidthExt_Float1 = TSymbolUniqueId(4067); + static constexpr const TSymbolUniqueId fwidthExt_Float2 = TSymbolUniqueId(4068); + static constexpr const TSymbolUniqueId fwidthExt_Float3 = TSymbolUniqueId(4069); + static constexpr const TSymbolUniqueId fwidthExt_Float4 = TSymbolUniqueId(4070); + static constexpr const TSymbolUniqueId dFdx_Float1 = TSymbolUniqueId(4071); + static constexpr const TSymbolUniqueId dFdx_Float2 = TSymbolUniqueId(4072); + static constexpr const TSymbolUniqueId dFdx_Float3 = TSymbolUniqueId(4073); + static constexpr const TSymbolUniqueId dFdx_Float4 = TSymbolUniqueId(4074); + static constexpr const TSymbolUniqueId dFdy_Float1 = TSymbolUniqueId(4075); + static constexpr const TSymbolUniqueId dFdy_Float2 = TSymbolUniqueId(4076); + static constexpr const TSymbolUniqueId dFdy_Float3 = TSymbolUniqueId(4077); + static constexpr const TSymbolUniqueId dFdy_Float4 = TSymbolUniqueId(4078); + static constexpr const TSymbolUniqueId fwidth_Float1 = TSymbolUniqueId(4079); + static constexpr const TSymbolUniqueId fwidth_Float2 = TSymbolUniqueId(4080); + static constexpr const TSymbolUniqueId fwidth_Float3 = TSymbolUniqueId(4081); + static constexpr const TSymbolUniqueId fwidth_Float4 = TSymbolUniqueId(4082); + static constexpr const TSymbolUniqueId interpolateAtCentroid_Float1 = TSymbolUniqueId(4083); + static constexpr const TSymbolUniqueId interpolateAtCentroid_Float2 = TSymbolUniqueId(4084); + static constexpr const TSymbolUniqueId interpolateAtCentroid_Float3 = TSymbolUniqueId(4085); + static constexpr const TSymbolUniqueId interpolateAtCentroid_Float4 = TSymbolUniqueId(4086); + static constexpr const TSymbolUniqueId interpolateAtSample_Float1_Int1 = TSymbolUniqueId(4087); + static constexpr const TSymbolUniqueId interpolateAtSample_Float2_Int1 = TSymbolUniqueId(4088); + static constexpr const TSymbolUniqueId interpolateAtSample_Float3_Int1 = TSymbolUniqueId(4089); + static constexpr const TSymbolUniqueId interpolateAtSample_Float4_Int1 = TSymbolUniqueId(4090); + static constexpr const TSymbolUniqueId interpolateAtOffset_Float1_Float2 = + TSymbolUniqueId(4091); + static constexpr const TSymbolUniqueId interpolateAtOffset_Float2_Float2 = + TSymbolUniqueId(4092); + static constexpr const TSymbolUniqueId interpolateAtOffset_Float3_Float2 = + TSymbolUniqueId(4093); + static constexpr const TSymbolUniqueId interpolateAtOffset_Float4_Float2 = + TSymbolUniqueId(4094); + static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float1 = TSymbolUniqueId(4095); + static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float2 = TSymbolUniqueId(4096); + static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float3 = TSymbolUniqueId(4097); + static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float4 = TSymbolUniqueId(4098); + static constexpr const TSymbolUniqueId interpolateAtSampleExt_Float1_Int1 = + TSymbolUniqueId(4099); + static constexpr const TSymbolUniqueId interpolateAtSampleExt_Float2_Int1 = + TSymbolUniqueId(4100); + static constexpr const TSymbolUniqueId interpolateAtSampleExt_Float3_Int1 = + TSymbolUniqueId(4101); + static constexpr const TSymbolUniqueId interpolateAtSampleExt_Float4_Int1 = + TSymbolUniqueId(4102); + static constexpr const TSymbolUniqueId interpolateAtOffsetExt_Float1_Float2 = + TSymbolUniqueId(4103); + static constexpr const TSymbolUniqueId interpolateAtOffsetExt_Float2_Float2 = + TSymbolUniqueId(4104); + static constexpr const TSymbolUniqueId interpolateAtOffsetExt_Float3_Float2 = + TSymbolUniqueId(4105); + static constexpr const TSymbolUniqueId interpolateAtOffsetExt_Float4_Float2 = + TSymbolUniqueId(4106); + static constexpr const TSymbolUniqueId atomicCounter_AtomicCounter1 = TSymbolUniqueId(4107); + static constexpr const TSymbolUniqueId pt00G = TSymbolUniqueId(4108); + static constexpr const TSymbolUniqueId atomicCounterIncrement_AtomicCounter1 = + TSymbolUniqueId(4109); + static constexpr const TSymbolUniqueId atomicCounterDecrement_AtomicCounter1 = + TSymbolUniqueId(4110); + static constexpr const TSymbolUniqueId atomicAdd_UInt1_UInt1 = TSymbolUniqueId(4111); + static constexpr const TSymbolUniqueId pt_io_00E = TSymbolUniqueId(4112); + static constexpr const TSymbolUniqueId atomicAdd_Int1_Int1 = TSymbolUniqueId(4113); + static constexpr const TSymbolUniqueId pt_io_00D = TSymbolUniqueId(4114); + static constexpr const TSymbolUniqueId atomicMin_UInt1_UInt1 = TSymbolUniqueId(4115); + static constexpr const TSymbolUniqueId atomicMin_Int1_Int1 = TSymbolUniqueId(4116); + static constexpr const TSymbolUniqueId atomicMax_UInt1_UInt1 = TSymbolUniqueId(4117); + static constexpr const TSymbolUniqueId atomicMax_Int1_Int1 = TSymbolUniqueId(4118); + static constexpr const TSymbolUniqueId atomicAnd_UInt1_UInt1 = TSymbolUniqueId(4119); + static constexpr const TSymbolUniqueId atomicAnd_Int1_Int1 = TSymbolUniqueId(4120); + static constexpr const TSymbolUniqueId atomicOr_UInt1_UInt1 = TSymbolUniqueId(4121); + static constexpr const TSymbolUniqueId atomicOr_Int1_Int1 = TSymbolUniqueId(4122); + static constexpr const TSymbolUniqueId atomicXor_UInt1_UInt1 = TSymbolUniqueId(4123); + static constexpr const TSymbolUniqueId atomicXor_Int1_Int1 = TSymbolUniqueId(4124); + static constexpr const TSymbolUniqueId atomicExchange_UInt1_UInt1 = TSymbolUniqueId(4125); + static constexpr const TSymbolUniqueId atomicExchange_Int1_Int1 = TSymbolUniqueId(4126); + static constexpr const TSymbolUniqueId atomicCompSwap_UInt1_UInt1_UInt1 = TSymbolUniqueId(4127); + static constexpr const TSymbolUniqueId atomicCompSwap_Int1_Int1_Int1 = TSymbolUniqueId(4128); + static constexpr const TSymbolUniqueId imageSize_Image2D1 = TSymbolUniqueId(4129); + static constexpr const TSymbolUniqueId pt00z = TSymbolUniqueId(4130); + static constexpr const TSymbolUniqueId imageSize_IImage2D1 = TSymbolUniqueId(4131); + static constexpr const TSymbolUniqueId pt01K = TSymbolUniqueId(4132); + static constexpr const TSymbolUniqueId imageSize_UImage2D1 = TSymbolUniqueId(4133); + static constexpr const TSymbolUniqueId pt01V = TSymbolUniqueId(4134); + static constexpr const TSymbolUniqueId imageSize_Image3D1 = TSymbolUniqueId(4135); + static constexpr const TSymbolUniqueId pt01A = TSymbolUniqueId(4136); + static constexpr const TSymbolUniqueId imageSize_IImage3D1 = TSymbolUniqueId(4137); + static constexpr const TSymbolUniqueId pt01L = TSymbolUniqueId(4138); + static constexpr const TSymbolUniqueId imageSize_UImage3D1 = TSymbolUniqueId(4139); + static constexpr const TSymbolUniqueId pt01W = TSymbolUniqueId(4140); + static constexpr const TSymbolUniqueId imageSize_Image2DArray1 = TSymbolUniqueId(4141); + static constexpr const TSymbolUniqueId pt01B = TSymbolUniqueId(4142); + static constexpr const TSymbolUniqueId imageSize_IImage2DArray1 = TSymbolUniqueId(4143); + static constexpr const TSymbolUniqueId pt01M = TSymbolUniqueId(4144); + static constexpr const TSymbolUniqueId imageSize_UImage2DArray1 = TSymbolUniqueId(4145); + static constexpr const TSymbolUniqueId pt01X = TSymbolUniqueId(4146); + static constexpr const TSymbolUniqueId imageSize_ImageCube1 = TSymbolUniqueId(4147); + static constexpr const TSymbolUniqueId pt01C = TSymbolUniqueId(4148); + static constexpr const TSymbolUniqueId imageSize_IImageCube1 = TSymbolUniqueId(4149); + static constexpr const TSymbolUniqueId pt01N = TSymbolUniqueId(4150); + static constexpr const TSymbolUniqueId imageSize_UImageCube1 = TSymbolUniqueId(4151); + static constexpr const TSymbolUniqueId pt01Y = TSymbolUniqueId(4152); + static constexpr const TSymbolUniqueId imageSize_ImageCubeArray1 = TSymbolUniqueId(4153); + static constexpr const TSymbolUniqueId pt01H = TSymbolUniqueId(4154); + static constexpr const TSymbolUniqueId imageSize_IImageCubeArray1 = TSymbolUniqueId(4155); + static constexpr const TSymbolUniqueId pt01S = TSymbolUniqueId(4156); + static constexpr const TSymbolUniqueId imageSize_UImageCubeArray1 = TSymbolUniqueId(4157); + static constexpr const TSymbolUniqueId pt01d = TSymbolUniqueId(4158); + static constexpr const TSymbolUniqueId imageSizeExt_ImageCubeArray1 = TSymbolUniqueId(4159); + static constexpr const TSymbolUniqueId imageSizeExt_IImageCubeArray1 = TSymbolUniqueId(4160); + static constexpr const TSymbolUniqueId imageSizeExt_UImageCubeArray1 = TSymbolUniqueId(4161); + static constexpr const TSymbolUniqueId imageSize_ImageBuffer1 = TSymbolUniqueId(4162); + static constexpr const TSymbolUniqueId pt01J = TSymbolUniqueId(4163); + static constexpr const TSymbolUniqueId imageSize_IImageBuffer1 = TSymbolUniqueId(4164); + static constexpr const TSymbolUniqueId pt01U = TSymbolUniqueId(4165); + static constexpr const TSymbolUniqueId imageSize_UImageBuffer1 = TSymbolUniqueId(4166); + static constexpr const TSymbolUniqueId pt01f = TSymbolUniqueId(4167); + static constexpr const TSymbolUniqueId imageSizeExt_ImageBuffer1 = TSymbolUniqueId(4168); + static constexpr const TSymbolUniqueId imageSizeExt_IImageBuffer1 = TSymbolUniqueId(4169); + static constexpr const TSymbolUniqueId imageSizeExt_UImageBuffer1 = TSymbolUniqueId(4170); + static constexpr const TSymbolUniqueId imageStore_Image2D1_Int2_Float4 = TSymbolUniqueId(4171); + static constexpr const TSymbolUniqueId imageStore_IImage2D1_Int2_Int4 = TSymbolUniqueId(4172); + static constexpr const TSymbolUniqueId imageStore_UImage2D1_Int2_UInt4 = TSymbolUniqueId(4173); + static constexpr const TSymbolUniqueId imageStore_Image3D1_Int3_Float4 = TSymbolUniqueId(4174); + static constexpr const TSymbolUniqueId imageStore_IImage3D1_Int3_Int4 = TSymbolUniqueId(4175); + static constexpr const TSymbolUniqueId imageStore_UImage3D1_Int3_UInt4 = TSymbolUniqueId(4176); + static constexpr const TSymbolUniqueId imageStore_Image2DArray1_Int3_Float4 = + TSymbolUniqueId(4177); + static constexpr const TSymbolUniqueId imageStore_IImage2DArray1_Int3_Int4 = + TSymbolUniqueId(4178); + static constexpr const TSymbolUniqueId imageStore_UImage2DArray1_Int3_UInt4 = + TSymbolUniqueId(4179); + static constexpr const TSymbolUniqueId imageStore_ImageCube1_Int3_Float4 = + TSymbolUniqueId(4180); + static constexpr const TSymbolUniqueId imageStore_IImageCube1_Int3_Int4 = TSymbolUniqueId(4181); + static constexpr const TSymbolUniqueId imageStore_UImageCube1_Int3_UInt4 = + TSymbolUniqueId(4182); + static constexpr const TSymbolUniqueId imageStore_ImageCubeArray1_Int3_Float4 = + TSymbolUniqueId(4183); + static constexpr const TSymbolUniqueId imageStore_IImageCubeArray1_Int3_Int4 = + TSymbolUniqueId(4184); + static constexpr const TSymbolUniqueId imageStore_UImageCubeArray1_Int3_UInt4 = + TSymbolUniqueId(4185); + static constexpr const TSymbolUniqueId imageStoreExt_ImageCubeArray1_Int3_Float4 = + TSymbolUniqueId(4186); + static constexpr const TSymbolUniqueId imageStoreExt_IImageCubeArray1_Int3_Int4 = + TSymbolUniqueId(4187); + static constexpr const TSymbolUniqueId imageStoreExt_UImageCubeArray1_Int3_UInt4 = + TSymbolUniqueId(4188); + static constexpr const TSymbolUniqueId imageStore_ImageBuffer1_Int1_Float4 = + TSymbolUniqueId(4189); + static constexpr const TSymbolUniqueId imageStore_IImageBuffer1_Int1_Int4 = + TSymbolUniqueId(4190); + static constexpr const TSymbolUniqueId imageStore_UImageBuffer1_Int1_UInt4 = + TSymbolUniqueId(4191); + static constexpr const TSymbolUniqueId imageStoreExt_ImageBuffer1_Int1_Float4 = + TSymbolUniqueId(4192); + static constexpr const TSymbolUniqueId imageStoreExt_IImageBuffer1_Int1_Int4 = + TSymbolUniqueId(4193); + static constexpr const TSymbolUniqueId imageStoreExt_UImageBuffer1_Int1_UInt4 = + TSymbolUniqueId(4194); + static constexpr const TSymbolUniqueId imageLoad_Image2D1_Int2 = TSymbolUniqueId(4195); + static constexpr const TSymbolUniqueId imageLoad_IImage2D1_Int2 = TSymbolUniqueId(4196); + static constexpr const TSymbolUniqueId imageLoad_UImage2D1_Int2 = TSymbolUniqueId(4197); + static constexpr const TSymbolUniqueId imageLoad_Image3D1_Int3 = TSymbolUniqueId(4198); + static constexpr const TSymbolUniqueId imageLoad_IImage3D1_Int3 = TSymbolUniqueId(4199); + static constexpr const TSymbolUniqueId imageLoad_UImage3D1_Int3 = TSymbolUniqueId(4200); + static constexpr const TSymbolUniqueId imageLoad_Image2DArray1_Int3 = TSymbolUniqueId(4201); + static constexpr const TSymbolUniqueId imageLoad_IImage2DArray1_Int3 = TSymbolUniqueId(4202); + static constexpr const TSymbolUniqueId imageLoad_UImage2DArray1_Int3 = TSymbolUniqueId(4203); + static constexpr const TSymbolUniqueId imageLoad_ImageCube1_Int3 = TSymbolUniqueId(4204); + static constexpr const TSymbolUniqueId imageLoad_IImageCube1_Int3 = TSymbolUniqueId(4205); + static constexpr const TSymbolUniqueId imageLoad_UImageCube1_Int3 = TSymbolUniqueId(4206); + static constexpr const TSymbolUniqueId imageLoad_ImageCubeArray1_Int3 = TSymbolUniqueId(4207); + static constexpr const TSymbolUniqueId imageLoad_IImageCubeArray1_Int3 = TSymbolUniqueId(4208); + static constexpr const TSymbolUniqueId imageLoad_UImageCubeArray1_Int3 = TSymbolUniqueId(4209); + static constexpr const TSymbolUniqueId imageLoadExt_ImageCubeArray1_Int3 = + TSymbolUniqueId(4210); + static constexpr const TSymbolUniqueId imageLoadExt_IImageCubeArray1_Int3 = + TSymbolUniqueId(4211); + static constexpr const TSymbolUniqueId imageLoadExt_UImageCubeArray1_Int3 = + TSymbolUniqueId(4212); + static constexpr const TSymbolUniqueId imageLoad_ImageBuffer1_Int1 = TSymbolUniqueId(4213); + static constexpr const TSymbolUniqueId imageLoad_IImageBuffer1_Int1 = TSymbolUniqueId(4214); + static constexpr const TSymbolUniqueId imageLoad_UImageBuffer1_Int1 = TSymbolUniqueId(4215); + static constexpr const TSymbolUniqueId imageLoadExt_ImageBuffer1_Int1 = TSymbolUniqueId(4216); + static constexpr const TSymbolUniqueId imageLoadExt_IImageBuffer1_Int1 = TSymbolUniqueId(4217); + static constexpr const TSymbolUniqueId imageLoadExt_UImageBuffer1_Int1 = TSymbolUniqueId(4218); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2D1_Int2_UInt1 = + TSymbolUniqueId(4219); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(4220); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(4221); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image3D1_Int3_UInt1 = + TSymbolUniqueId(4222); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(4223); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(4224); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(4225); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(4226); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(4227); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4228); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4229); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4230); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(4231); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4232); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4233); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4234); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4235); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4236); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image1D1_Int1_UInt1 = + TSymbolUniqueId(4237); + static constexpr const TSymbolUniqueId pt01D = TSymbolUniqueId(4238); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(4239); + static constexpr const TSymbolUniqueId pt01O = TSymbolUniqueId(4240); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(4241); + static constexpr const TSymbolUniqueId pt01Z = TSymbolUniqueId(4242); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(4243); + static constexpr const TSymbolUniqueId pt01E = TSymbolUniqueId(4244); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4245); + static constexpr const TSymbolUniqueId pt01P = TSymbolUniqueId(4246); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4247); + static constexpr const TSymbolUniqueId pt01a = TSymbolUniqueId(4248); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(4249); + static constexpr const TSymbolUniqueId pt01I = TSymbolUniqueId(4250); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(4251); + static constexpr const TSymbolUniqueId pt01T = TSymbolUniqueId(4252); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(4253); + static constexpr const TSymbolUniqueId pt01e = TSymbolUniqueId(4254); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4255); + static constexpr const TSymbolUniqueId pt01F = TSymbolUniqueId(4256); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4257); + static constexpr const TSymbolUniqueId pt01Q = TSymbolUniqueId(4258); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4259); + static constexpr const TSymbolUniqueId pt01b = TSymbolUniqueId(4260); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4261); + static constexpr const TSymbolUniqueId pt01G = TSymbolUniqueId(4262); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4263); + static constexpr const TSymbolUniqueId pt01R = TSymbolUniqueId(4264); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4265); + static constexpr const TSymbolUniqueId pt01c = TSymbolUniqueId(4266); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2D1_Int2_Int1 = + TSymbolUniqueId(4267); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2D1_Int2_Int1 = + TSymbolUniqueId(4268); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2D1_Int2_Int1 = + TSymbolUniqueId(4269); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image3D1_Int3_Int1 = + TSymbolUniqueId(4270); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage3D1_Int3_Int1 = + TSymbolUniqueId(4271); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage3D1_Int3_Int1 = + TSymbolUniqueId(4272); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageCube1_Int3_Int1 = + TSymbolUniqueId(4273); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageCube1_Int3_Int1 = + TSymbolUniqueId(4274); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageCube1_Int3_Int1 = + TSymbolUniqueId(4275); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4276); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4277); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4278); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(4279); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4280); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4281); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4282); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4283); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4284); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image1D1_Int1_Int1 = + TSymbolUniqueId(4285); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage1D1_Int1_Int1 = + TSymbolUniqueId(4286); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage1D1_Int1_Int1 = + TSymbolUniqueId(4287); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(4288); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4289); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4290); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageRect1_Int2_Int1 = + TSymbolUniqueId(4291); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageRect1_Int2_Int1 = + TSymbolUniqueId(4292); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageRect1_Int2_Int1 = + TSymbolUniqueId(4293); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4294); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4295); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4296); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4297); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4298); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4299); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2D1_Int2_UInt1 = + TSymbolUniqueId(4300); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(4301); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(4302); + static constexpr const TSymbolUniqueId imageAtomicMin_Image3D1_Int3_UInt1 = + TSymbolUniqueId(4303); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(4304); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(4305); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(4306); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(4307); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(4308); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4309); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4310); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4311); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(4312); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4313); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4314); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4315); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4316); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4317); + static constexpr const TSymbolUniqueId imageAtomicMin_Image1D1_Int1_UInt1 = + TSymbolUniqueId(4318); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(4319); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(4320); + static constexpr const TSymbolUniqueId imageAtomicMin_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(4321); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4322); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4323); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(4324); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(4325); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(4326); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4327); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4328); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4329); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4330); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4331); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4332); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2D1_Int2_Int1 = + TSymbolUniqueId(4333); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2D1_Int2_Int1 = + TSymbolUniqueId(4334); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2D1_Int2_Int1 = + TSymbolUniqueId(4335); + static constexpr const TSymbolUniqueId imageAtomicMin_Image3D1_Int3_Int1 = + TSymbolUniqueId(4336); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage3D1_Int3_Int1 = + TSymbolUniqueId(4337); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage3D1_Int3_Int1 = + TSymbolUniqueId(4338); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageCube1_Int3_Int1 = + TSymbolUniqueId(4339); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageCube1_Int3_Int1 = + TSymbolUniqueId(4340); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageCube1_Int3_Int1 = + TSymbolUniqueId(4341); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4342); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4343); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4344); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(4345); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4346); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4347); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4348); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4349); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4350); + static constexpr const TSymbolUniqueId imageAtomicMin_Image1D1_Int1_Int1 = + TSymbolUniqueId(4351); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage1D1_Int1_Int1 = + TSymbolUniqueId(4352); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage1D1_Int1_Int1 = + TSymbolUniqueId(4353); + static constexpr const TSymbolUniqueId imageAtomicMin_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(4354); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4355); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4356); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageRect1_Int2_Int1 = + TSymbolUniqueId(4357); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageRect1_Int2_Int1 = + TSymbolUniqueId(4358); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageRect1_Int2_Int1 = + TSymbolUniqueId(4359); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4360); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4361); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4362); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4363); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4364); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4365); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2D1_Int2_UInt1 = + TSymbolUniqueId(4366); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(4367); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(4368); + static constexpr const TSymbolUniqueId imageAtomicMax_Image3D1_Int3_UInt1 = + TSymbolUniqueId(4369); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(4370); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(4371); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(4372); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(4373); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(4374); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4375); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4376); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4377); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(4378); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4379); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4380); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4381); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4382); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4383); + static constexpr const TSymbolUniqueId imageAtomicMax_Image1D1_Int1_UInt1 = + TSymbolUniqueId(4384); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(4385); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(4386); + static constexpr const TSymbolUniqueId imageAtomicMax_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(4387); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4388); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4389); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(4390); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(4391); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(4392); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4393); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4394); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4395); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4396); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4397); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4398); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2D1_Int2_Int1 = + TSymbolUniqueId(4399); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2D1_Int2_Int1 = + TSymbolUniqueId(4400); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2D1_Int2_Int1 = + TSymbolUniqueId(4401); + static constexpr const TSymbolUniqueId imageAtomicMax_Image3D1_Int3_Int1 = + TSymbolUniqueId(4402); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage3D1_Int3_Int1 = + TSymbolUniqueId(4403); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage3D1_Int3_Int1 = + TSymbolUniqueId(4404); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageCube1_Int3_Int1 = + TSymbolUniqueId(4405); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageCube1_Int3_Int1 = + TSymbolUniqueId(4406); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageCube1_Int3_Int1 = + TSymbolUniqueId(4407); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4408); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4409); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4410); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(4411); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4412); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4413); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4414); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4415); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4416); + static constexpr const TSymbolUniqueId imageAtomicMax_Image1D1_Int1_Int1 = + TSymbolUniqueId(4417); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage1D1_Int1_Int1 = + TSymbolUniqueId(4418); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage1D1_Int1_Int1 = + TSymbolUniqueId(4419); + static constexpr const TSymbolUniqueId imageAtomicMax_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(4420); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4421); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4422); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageRect1_Int2_Int1 = + TSymbolUniqueId(4423); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageRect1_Int2_Int1 = + TSymbolUniqueId(4424); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageRect1_Int2_Int1 = + TSymbolUniqueId(4425); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4426); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4427); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4428); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4429); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4430); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4431); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2D1_Int2_UInt1 = + TSymbolUniqueId(4432); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(4433); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(4434); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image3D1_Int3_UInt1 = + TSymbolUniqueId(4435); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(4436); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(4437); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(4438); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(4439); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(4440); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4441); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4442); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4443); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(4444); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4445); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4446); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4447); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4448); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4449); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image1D1_Int1_UInt1 = + TSymbolUniqueId(4450); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(4451); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(4452); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(4453); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4454); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4455); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(4456); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(4457); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(4458); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4459); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4460); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4461); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4462); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4463); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4464); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2D1_Int2_Int1 = + TSymbolUniqueId(4465); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2D1_Int2_Int1 = + TSymbolUniqueId(4466); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2D1_Int2_Int1 = + TSymbolUniqueId(4467); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image3D1_Int3_Int1 = + TSymbolUniqueId(4468); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage3D1_Int3_Int1 = + TSymbolUniqueId(4469); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage3D1_Int3_Int1 = + TSymbolUniqueId(4470); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCube1_Int3_Int1 = + TSymbolUniqueId(4471); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCube1_Int3_Int1 = + TSymbolUniqueId(4472); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCube1_Int3_Int1 = + TSymbolUniqueId(4473); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4474); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4475); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4476); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(4477); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4478); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4479); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4480); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4481); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4482); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image1D1_Int1_Int1 = + TSymbolUniqueId(4483); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage1D1_Int1_Int1 = + TSymbolUniqueId(4484); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage1D1_Int1_Int1 = + TSymbolUniqueId(4485); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(4486); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4487); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4488); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageRect1_Int2_Int1 = + TSymbolUniqueId(4489); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageRect1_Int2_Int1 = + TSymbolUniqueId(4490); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageRect1_Int2_Int1 = + TSymbolUniqueId(4491); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4492); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4493); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4494); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4495); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4496); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4497); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2D1_Int2_UInt1 = + TSymbolUniqueId(4498); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(4499); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(4500); + static constexpr const TSymbolUniqueId imageAtomicOr_Image3D1_Int3_UInt1 = + TSymbolUniqueId(4501); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(4502); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(4503); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(4504); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(4505); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(4506); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4507); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4508); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4509); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(4510); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4511); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4512); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4513); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4514); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4515); + static constexpr const TSymbolUniqueId imageAtomicOr_Image1D1_Int1_UInt1 = + TSymbolUniqueId(4516); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(4517); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(4518); + static constexpr const TSymbolUniqueId imageAtomicOr_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(4519); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4520); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4521); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(4522); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(4523); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(4524); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4525); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4526); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4527); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4528); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4529); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4530); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2D1_Int2_Int1 = TSymbolUniqueId(4531); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2D1_Int2_Int1 = + TSymbolUniqueId(4532); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2D1_Int2_Int1 = + TSymbolUniqueId(4533); + static constexpr const TSymbolUniqueId imageAtomicOr_Image3D1_Int3_Int1 = TSymbolUniqueId(4534); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage3D1_Int3_Int1 = + TSymbolUniqueId(4535); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage3D1_Int3_Int1 = + TSymbolUniqueId(4536); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageCube1_Int3_Int1 = + TSymbolUniqueId(4537); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageCube1_Int3_Int1 = + TSymbolUniqueId(4538); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageCube1_Int3_Int1 = + TSymbolUniqueId(4539); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4540); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4541); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4542); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(4543); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4544); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4545); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4546); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4547); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4548); + static constexpr const TSymbolUniqueId imageAtomicOr_Image1D1_Int1_Int1 = TSymbolUniqueId(4549); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage1D1_Int1_Int1 = + TSymbolUniqueId(4550); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage1D1_Int1_Int1 = + TSymbolUniqueId(4551); + static constexpr const TSymbolUniqueId imageAtomicOr_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(4552); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4553); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4554); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageRect1_Int2_Int1 = + TSymbolUniqueId(4555); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageRect1_Int2_Int1 = + TSymbolUniqueId(4556); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageRect1_Int2_Int1 = + TSymbolUniqueId(4557); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4558); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4559); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4560); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4561); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4562); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4563); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2D1_Int2_UInt1 = + TSymbolUniqueId(4564); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(4565); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(4566); + static constexpr const TSymbolUniqueId imageAtomicXor_Image3D1_Int3_UInt1 = + TSymbolUniqueId(4567); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(4568); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(4569); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(4570); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(4571); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(4572); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4573); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4574); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4575); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(4576); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4577); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4578); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4579); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4580); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4581); + static constexpr const TSymbolUniqueId imageAtomicXor_Image1D1_Int1_UInt1 = + TSymbolUniqueId(4582); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(4583); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(4584); + static constexpr const TSymbolUniqueId imageAtomicXor_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(4585); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4586); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4587); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(4588); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(4589); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(4590); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4591); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4592); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4593); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4594); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4595); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4596); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2D1_Int2_Int1 = + TSymbolUniqueId(4597); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2D1_Int2_Int1 = + TSymbolUniqueId(4598); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2D1_Int2_Int1 = + TSymbolUniqueId(4599); + static constexpr const TSymbolUniqueId imageAtomicXor_Image3D1_Int3_Int1 = + TSymbolUniqueId(4600); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage3D1_Int3_Int1 = + TSymbolUniqueId(4601); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage3D1_Int3_Int1 = + TSymbolUniqueId(4602); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageCube1_Int3_Int1 = + TSymbolUniqueId(4603); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageCube1_Int3_Int1 = + TSymbolUniqueId(4604); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageCube1_Int3_Int1 = + TSymbolUniqueId(4605); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4606); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4607); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4608); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(4609); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4610); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4611); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4612); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4613); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4614); + static constexpr const TSymbolUniqueId imageAtomicXor_Image1D1_Int1_Int1 = + TSymbolUniqueId(4615); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage1D1_Int1_Int1 = + TSymbolUniqueId(4616); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage1D1_Int1_Int1 = + TSymbolUniqueId(4617); + static constexpr const TSymbolUniqueId imageAtomicXor_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(4618); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4619); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4620); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageRect1_Int2_Int1 = + TSymbolUniqueId(4621); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageRect1_Int2_Int1 = + TSymbolUniqueId(4622); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageRect1_Int2_Int1 = + TSymbolUniqueId(4623); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4624); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4625); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4626); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4627); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4628); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4629); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2D1_Int2_UInt1 = + TSymbolUniqueId(4630); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(4631); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(4632); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image3D1_Int3_UInt1 = + TSymbolUniqueId(4633); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(4634); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(4635); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(4636); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(4637); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(4638); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4639); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4640); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4641); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(4642); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4643); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4644); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4645); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4646); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4647); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image1D1_Int1_UInt1 = + TSymbolUniqueId(4648); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(4649); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(4650); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(4651); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4652); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4653); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(4654); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(4655); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(4656); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4657); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4658); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4659); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4660); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4661); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4662); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2D1_Int2_Int1 = + TSymbolUniqueId(4663); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2D1_Int2_Int1 = + TSymbolUniqueId(4664); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2D1_Int2_Int1 = + TSymbolUniqueId(4665); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image3D1_Int3_Int1 = + TSymbolUniqueId(4666); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage3D1_Int3_Int1 = + TSymbolUniqueId(4667); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage3D1_Int3_Int1 = + TSymbolUniqueId(4668); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCube1_Int3_Int1 = + TSymbolUniqueId(4669); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCube1_Int3_Int1 = + TSymbolUniqueId(4670); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCube1_Int3_Int1 = + TSymbolUniqueId(4671); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4672); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4673); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4674); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(4675); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4676); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4677); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4678); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4679); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4680); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image1D1_Int1_Int1 = + TSymbolUniqueId(4681); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage1D1_Int1_Int1 = + TSymbolUniqueId(4682); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage1D1_Int1_Int1 = + TSymbolUniqueId(4683); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(4684); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4685); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4686); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageRect1_Int2_Int1 = + TSymbolUniqueId(4687); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageRect1_Int2_Int1 = + TSymbolUniqueId(4688); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageRect1_Int2_Int1 = + TSymbolUniqueId(4689); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4690); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4691); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4692); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4693); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4694); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4695); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2D1_Int2_Float1 = + TSymbolUniqueId(4696); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2D1_Int2_Float1 = + TSymbolUniqueId(4697); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2D1_Int2_Float1 = + TSymbolUniqueId(4698); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image3D1_Int3_Float1 = + TSymbolUniqueId(4699); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage3D1_Int3_Float1 = + TSymbolUniqueId(4700); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage3D1_Int3_Float1 = + TSymbolUniqueId(4701); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCube1_Int3_Float1 = + TSymbolUniqueId(4702); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCube1_Int3_Float1 = + TSymbolUniqueId(4703); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCube1_Int3_Float1 = + TSymbolUniqueId(4704); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageBuffer1_Int1_Float1 = + TSymbolUniqueId(4705); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageBuffer1_Int1_Float1 = + TSymbolUniqueId(4706); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageBuffer1_Int1_Float1 = + TSymbolUniqueId(4707); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DArray1_Int3_Float1 = + TSymbolUniqueId(4708); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DArray1_Int3_Float1 = + TSymbolUniqueId(4709); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DArray1_Int3_Float1 = + TSymbolUniqueId(4710); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCubeArray1_Int3_Float1 = + TSymbolUniqueId(4711); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCubeArray1_Int3_Float1 = + TSymbolUniqueId(4712); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCubeArray1_Int3_Float1 = + TSymbolUniqueId(4713); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image1D1_Int1_Float1 = + TSymbolUniqueId(4714); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage1D1_Int1_Float1 = + TSymbolUniqueId(4715); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage1D1_Int1_Float1 = + TSymbolUniqueId(4716); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image1DArray1_Int2_Float1 = + TSymbolUniqueId(4717); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage1DArray1_Int2_Float1 = + TSymbolUniqueId(4718); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage1DArray1_Int2_Float1 = + TSymbolUniqueId(4719); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageRect1_Int2_Float1 = + TSymbolUniqueId(4720); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageRect1_Int2_Float1 = + TSymbolUniqueId(4721); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageRect1_Int2_Float1 = + TSymbolUniqueId(4722); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMS1_Int2_Int1_Float1 = + TSymbolUniqueId(4723); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMS1_Int2_Int1_Float1 = + TSymbolUniqueId(4724); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMS1_Int2_Int1_Float1 = + TSymbolUniqueId(4725); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMSArray1_Int3_Int1_Float1 = + TSymbolUniqueId(4726); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMSArray1_Int3_Int1_Float1 = + TSymbolUniqueId(4727); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMSArray1_Int3_Int1_Float1 = + TSymbolUniqueId(4728); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2D1_Int2_UInt1_UInt1 = + TSymbolUniqueId(4729); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2D1_Int2_UInt1_UInt1 = + TSymbolUniqueId(4730); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2D1_Int2_UInt1_UInt1 = + TSymbolUniqueId(4731); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image3D1_Int3_UInt1_UInt1 = + TSymbolUniqueId(4732); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage3D1_Int3_UInt1_UInt1 = + TSymbolUniqueId(4733); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage3D1_Int3_UInt1_UInt1 = + TSymbolUniqueId(4734); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCube1_Int3_UInt1_UInt1 = + TSymbolUniqueId(4735); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCube1_Int3_UInt1_UInt1 = + TSymbolUniqueId(4736); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCube1_Int3_UInt1_UInt1 = + TSymbolUniqueId(4737); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageBuffer1_Int1_UInt1_UInt1 = + TSymbolUniqueId(4738); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageBuffer1_Int1_UInt1_UInt1 = + TSymbolUniqueId(4739); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageBuffer1_Int1_UInt1_UInt1 = + TSymbolUniqueId(4740); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(4741); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2DArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(4742); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2DArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(4743); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCubeArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(4744); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCubeArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(4745); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCubeArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(4746); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image1D1_Int1_UInt1_UInt1 = + TSymbolUniqueId(4747); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage1D1_Int1_UInt1_UInt1 = + TSymbolUniqueId(4748); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage1D1_Int1_UInt1_UInt1 = + TSymbolUniqueId(4749); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image1DArray1_Int2_UInt1_UInt1 = + TSymbolUniqueId(4750); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage1DArray1_Int2_UInt1_UInt1 = + TSymbolUniqueId(4751); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage1DArray1_Int2_UInt1_UInt1 = + TSymbolUniqueId(4752); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageRect1_Int2_UInt1_UInt1 = + TSymbolUniqueId(4753); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageRect1_Int2_UInt1_UInt1 = + TSymbolUniqueId(4754); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageRect1_Int2_UInt1_UInt1 = + TSymbolUniqueId(4755); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DMS1_Int2_Int1_UInt1_UInt1 = + TSymbolUniqueId(4756); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2DMS1_Int2_Int1_UInt1_UInt1 = + TSymbolUniqueId(4757); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2DMS1_Int2_Int1_UInt1_UInt1 = + TSymbolUniqueId(4758); + static constexpr const TSymbolUniqueId + imageAtomicCompSwap_Image2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(4759); + static constexpr const TSymbolUniqueId + imageAtomicCompSwap_IImage2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(4760); + static constexpr const TSymbolUniqueId + imageAtomicCompSwap_UImage2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(4761); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2D1_Int2_Int1_Int1 = + TSymbolUniqueId(4762); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2D1_Int2_Int1_Int1 = + TSymbolUniqueId(4763); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2D1_Int2_Int1_Int1 = + TSymbolUniqueId(4764); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image3D1_Int3_Int1_Int1 = + TSymbolUniqueId(4765); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage3D1_Int3_Int1_Int1 = + TSymbolUniqueId(4766); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage3D1_Int3_Int1_Int1 = + TSymbolUniqueId(4767); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCube1_Int3_Int1_Int1 = + TSymbolUniqueId(4768); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCube1_Int3_Int1_Int1 = + TSymbolUniqueId(4769); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCube1_Int3_Int1_Int1 = + TSymbolUniqueId(4770); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageBuffer1_Int1_Int1_Int1 = + TSymbolUniqueId(4771); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageBuffer1_Int1_Int1_Int1 = + TSymbolUniqueId(4772); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageBuffer1_Int1_Int1_Int1 = + TSymbolUniqueId(4773); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4774); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2DArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4775); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2DArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4776); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCubeArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4777); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCubeArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4778); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCubeArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4779); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image1D1_Int1_Int1_Int1 = + TSymbolUniqueId(4780); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage1D1_Int1_Int1_Int1 = + TSymbolUniqueId(4781); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage1D1_Int1_Int1_Int1 = + TSymbolUniqueId(4782); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(4783); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(4784); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(4785); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageRect1_Int2_Int1_Int1 = + TSymbolUniqueId(4786); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageRect1_Int2_Int1_Int1 = + TSymbolUniqueId(4787); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageRect1_Int2_Int1_Int1 = + TSymbolUniqueId(4788); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DMS1_Int2_Int1_Int1_Int1 = + TSymbolUniqueId(4789); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2DMS1_Int2_Int1_Int1_Int1 = + TSymbolUniqueId(4790); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2DMS1_Int2_Int1_Int1_Int1 = + TSymbolUniqueId(4791); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DMSArray1_Int3_Int1_Int1_Int1 = + TSymbolUniqueId(4792); + static constexpr const TSymbolUniqueId + imageAtomicCompSwap_IImage2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(4793); + static constexpr const TSymbolUniqueId + imageAtomicCompSwap_UImage2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(4794); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2D1_Int2_UInt1 = + TSymbolUniqueId(4795); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(4796); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(4797); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image3D1_Int3_UInt1 = + TSymbolUniqueId(4798); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(4799); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(4800); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(4801); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(4802); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(4803); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4804); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4805); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4806); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(4807); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4808); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4809); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4810); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4811); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4812); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image1D1_Int1_UInt1 = + TSymbolUniqueId(4813); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(4814); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(4815); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(4816); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4817); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4818); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(4819); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(4820); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(4821); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4822); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4823); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4824); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4825); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4826); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4827); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2D1_Int2_Int1 = + TSymbolUniqueId(4828); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2D1_Int2_Int1 = + TSymbolUniqueId(4829); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2D1_Int2_Int1 = + TSymbolUniqueId(4830); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image3D1_Int3_Int1 = + TSymbolUniqueId(4831); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage3D1_Int3_Int1 = + TSymbolUniqueId(4832); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage3D1_Int3_Int1 = + TSymbolUniqueId(4833); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCube1_Int3_Int1 = + TSymbolUniqueId(4834); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCube1_Int3_Int1 = + TSymbolUniqueId(4835); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCube1_Int3_Int1 = + TSymbolUniqueId(4836); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4837); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4838); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4839); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(4840); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4841); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4842); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4843); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4844); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4845); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image1D1_Int1_Int1 = + TSymbolUniqueId(4846); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage1D1_Int1_Int1 = + TSymbolUniqueId(4847); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage1D1_Int1_Int1 = + TSymbolUniqueId(4848); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(4849); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4850); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4851); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageRect1_Int2_Int1 = + TSymbolUniqueId(4852); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageRect1_Int2_Int1 = + TSymbolUniqueId(4853); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageRect1_Int2_Int1 = + TSymbolUniqueId(4854); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4855); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4856); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4857); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4858); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4859); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4860); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2D1_Int2_UInt1 = + TSymbolUniqueId(4861); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(4862); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(4863); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image3D1_Int3_UInt1 = + TSymbolUniqueId(4864); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(4865); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(4866); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(4867); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(4868); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(4869); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4870); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4871); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4872); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(4873); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4874); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4875); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4876); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4877); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4878); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image1D1_Int1_UInt1 = + TSymbolUniqueId(4879); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(4880); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(4881); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(4882); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4883); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4884); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(4885); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(4886); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(4887); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4888); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4889); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4890); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4891); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4892); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4893); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2D1_Int2_Int1 = + TSymbolUniqueId(4894); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2D1_Int2_Int1 = + TSymbolUniqueId(4895); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2D1_Int2_Int1 = + TSymbolUniqueId(4896); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image3D1_Int3_Int1 = + TSymbolUniqueId(4897); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage3D1_Int3_Int1 = + TSymbolUniqueId(4898); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage3D1_Int3_Int1 = + TSymbolUniqueId(4899); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageCube1_Int3_Int1 = + TSymbolUniqueId(4900); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageCube1_Int3_Int1 = + TSymbolUniqueId(4901); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageCube1_Int3_Int1 = + TSymbolUniqueId(4902); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4903); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4904); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4905); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(4906); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4907); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4908); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4909); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4910); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4911); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image1D1_Int1_Int1 = + TSymbolUniqueId(4912); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage1D1_Int1_Int1 = + TSymbolUniqueId(4913); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage1D1_Int1_Int1 = + TSymbolUniqueId(4914); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(4915); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4916); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4917); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageRect1_Int2_Int1 = + TSymbolUniqueId(4918); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageRect1_Int2_Int1 = + TSymbolUniqueId(4919); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageRect1_Int2_Int1 = + TSymbolUniqueId(4920); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4921); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4922); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4923); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4924); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4925); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4926); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2D1_Int2_UInt1 = + TSymbolUniqueId(4927); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(4928); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(4929); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image3D1_Int3_UInt1 = + TSymbolUniqueId(4930); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(4931); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(4932); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(4933); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(4934); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(4935); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4936); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4937); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(4938); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(4939); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4940); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(4941); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4942); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4943); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(4944); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image1D1_Int1_UInt1 = + TSymbolUniqueId(4945); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(4946); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(4947); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(4948); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4949); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(4950); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(4951); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(4952); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(4953); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4954); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4955); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(4956); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4957); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4958); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(4959); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2D1_Int2_Int1 = + TSymbolUniqueId(4960); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2D1_Int2_Int1 = + TSymbolUniqueId(4961); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2D1_Int2_Int1 = + TSymbolUniqueId(4962); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image3D1_Int3_Int1 = + TSymbolUniqueId(4963); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage3D1_Int3_Int1 = + TSymbolUniqueId(4964); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage3D1_Int3_Int1 = + TSymbolUniqueId(4965); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageCube1_Int3_Int1 = + TSymbolUniqueId(4966); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageCube1_Int3_Int1 = + TSymbolUniqueId(4967); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageCube1_Int3_Int1 = + TSymbolUniqueId(4968); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4969); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4970); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(4971); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(4972); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4973); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(4974); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4975); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4976); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(4977); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image1D1_Int1_Int1 = + TSymbolUniqueId(4978); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage1D1_Int1_Int1 = + TSymbolUniqueId(4979); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage1D1_Int1_Int1 = + TSymbolUniqueId(4980); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(4981); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4982); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(4983); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageRect1_Int2_Int1 = + TSymbolUniqueId(4984); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageRect1_Int2_Int1 = + TSymbolUniqueId(4985); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageRect1_Int2_Int1 = + TSymbolUniqueId(4986); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4987); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4988); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(4989); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4990); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4991); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(4992); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2D1_Int2_UInt1 = + TSymbolUniqueId(4993); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(4994); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(4995); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image3D1_Int3_UInt1 = + TSymbolUniqueId(4996); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(4997); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(4998); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(4999); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(5000); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(5001); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(5002); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(5003); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(5004); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(5005); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(5006); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(5007); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(5008); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(5009); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(5010); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image1D1_Int1_UInt1 = + TSymbolUniqueId(5011); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(5012); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(5013); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(5014); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(5015); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(5016); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(5017); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(5018); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(5019); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(5020); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(5021); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(5022); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(5023); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(5024); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(5025); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2D1_Int2_Int1 = + TSymbolUniqueId(5026); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2D1_Int2_Int1 = + TSymbolUniqueId(5027); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2D1_Int2_Int1 = + TSymbolUniqueId(5028); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image3D1_Int3_Int1 = + TSymbolUniqueId(5029); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage3D1_Int3_Int1 = + TSymbolUniqueId(5030); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage3D1_Int3_Int1 = + TSymbolUniqueId(5031); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageCube1_Int3_Int1 = + TSymbolUniqueId(5032); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageCube1_Int3_Int1 = + TSymbolUniqueId(5033); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageCube1_Int3_Int1 = + TSymbolUniqueId(5034); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(5035); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(5036); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(5037); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(5038); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(5039); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(5040); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(5041); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(5042); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(5043); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image1D1_Int1_Int1 = + TSymbolUniqueId(5044); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage1D1_Int1_Int1 = + TSymbolUniqueId(5045); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage1D1_Int1_Int1 = + TSymbolUniqueId(5046); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(5047); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(5048); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(5049); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageRect1_Int2_Int1 = + TSymbolUniqueId(5050); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageRect1_Int2_Int1 = + TSymbolUniqueId(5051); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageRect1_Int2_Int1 = + TSymbolUniqueId(5052); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(5053); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(5054); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(5055); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5056); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5057); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5058); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2D1_Int2_UInt1 = + TSymbolUniqueId(5059); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(5060); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(5061); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image3D1_Int3_UInt1 = + TSymbolUniqueId(5062); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(5063); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(5064); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(5065); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(5066); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(5067); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(5068); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(5069); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(5070); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(5071); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(5072); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(5073); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(5074); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(5075); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(5076); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image1D1_Int1_UInt1 = + TSymbolUniqueId(5077); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(5078); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(5079); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(5080); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(5081); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(5082); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(5083); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(5084); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(5085); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(5086); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(5087); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(5088); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(5089); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(5090); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(5091); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2D1_Int2_Int1 = + TSymbolUniqueId(5092); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2D1_Int2_Int1 = + TSymbolUniqueId(5093); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2D1_Int2_Int1 = + TSymbolUniqueId(5094); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image3D1_Int3_Int1 = + TSymbolUniqueId(5095); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage3D1_Int3_Int1 = + TSymbolUniqueId(5096); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage3D1_Int3_Int1 = + TSymbolUniqueId(5097); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageCube1_Int3_Int1 = + TSymbolUniqueId(5098); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageCube1_Int3_Int1 = + TSymbolUniqueId(5099); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageCube1_Int3_Int1 = + TSymbolUniqueId(5100); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(5101); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(5102); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(5103); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(5104); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(5105); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(5106); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(5107); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(5108); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(5109); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image1D1_Int1_Int1 = + TSymbolUniqueId(5110); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage1D1_Int1_Int1 = + TSymbolUniqueId(5111); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage1D1_Int1_Int1 = + TSymbolUniqueId(5112); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(5113); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(5114); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(5115); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageRect1_Int2_Int1 = + TSymbolUniqueId(5116); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageRect1_Int2_Int1 = + TSymbolUniqueId(5117); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageRect1_Int2_Int1 = + TSymbolUniqueId(5118); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(5119); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(5120); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(5121); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5122); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5123); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5124); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2D1_Int2_UInt1 = + TSymbolUniqueId(5125); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(5126); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(5127); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image3D1_Int3_UInt1 = + TSymbolUniqueId(5128); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(5129); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(5130); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(5131); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(5132); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(5133); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(5134); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(5135); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(5136); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(5137); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(5138); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(5139); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(5140); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(5141); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(5142); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image1D1_Int1_UInt1 = + TSymbolUniqueId(5143); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(5144); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(5145); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(5146); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(5147); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(5148); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(5149); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(5150); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(5151); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(5152); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(5153); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(5154); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(5155); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(5156); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(5157); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2D1_Int2_Int1 = + TSymbolUniqueId(5158); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2D1_Int2_Int1 = + TSymbolUniqueId(5159); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2D1_Int2_Int1 = + TSymbolUniqueId(5160); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image3D1_Int3_Int1 = + TSymbolUniqueId(5161); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage3D1_Int3_Int1 = + TSymbolUniqueId(5162); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage3D1_Int3_Int1 = + TSymbolUniqueId(5163); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageCube1_Int3_Int1 = + TSymbolUniqueId(5164); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageCube1_Int3_Int1 = + TSymbolUniqueId(5165); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageCube1_Int3_Int1 = + TSymbolUniqueId(5166); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(5167); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(5168); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(5169); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(5170); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(5171); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(5172); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(5173); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(5174); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(5175); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image1D1_Int1_Int1 = + TSymbolUniqueId(5176); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage1D1_Int1_Int1 = + TSymbolUniqueId(5177); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage1D1_Int1_Int1 = + TSymbolUniqueId(5178); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(5179); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(5180); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(5181); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageRect1_Int2_Int1 = + TSymbolUniqueId(5182); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageRect1_Int2_Int1 = + TSymbolUniqueId(5183); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageRect1_Int2_Int1 = + TSymbolUniqueId(5184); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(5185); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(5186); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(5187); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5188); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5189); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5190); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2D1_Int2_UInt1 = + TSymbolUniqueId(5191); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(5192); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(5193); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image3D1_Int3_UInt1 = + TSymbolUniqueId(5194); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(5195); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(5196); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(5197); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(5198); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(5199); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(5200); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(5201); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(5202); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(5203); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(5204); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(5205); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(5206); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(5207); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(5208); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image1D1_Int1_UInt1 = + TSymbolUniqueId(5209); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(5210); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(5211); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(5212); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(5213); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(5214); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(5215); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(5216); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(5217); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(5218); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(5219); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(5220); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(5221); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(5222); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(5223); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2D1_Int2_Int1 = + TSymbolUniqueId(5224); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2D1_Int2_Int1 = + TSymbolUniqueId(5225); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2D1_Int2_Int1 = + TSymbolUniqueId(5226); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image3D1_Int3_Int1 = + TSymbolUniqueId(5227); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage3D1_Int3_Int1 = + TSymbolUniqueId(5228); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage3D1_Int3_Int1 = + TSymbolUniqueId(5229); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCube1_Int3_Int1 = + TSymbolUniqueId(5230); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCube1_Int3_Int1 = + TSymbolUniqueId(5231); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCube1_Int3_Int1 = + TSymbolUniqueId(5232); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(5233); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(5234); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(5235); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(5236); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(5237); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(5238); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(5239); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(5240); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(5241); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image1D1_Int1_Int1 = + TSymbolUniqueId(5242); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage1D1_Int1_Int1 = + TSymbolUniqueId(5243); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage1D1_Int1_Int1 = + TSymbolUniqueId(5244); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(5245); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(5246); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(5247); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageRect1_Int2_Int1 = + TSymbolUniqueId(5248); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageRect1_Int2_Int1 = + TSymbolUniqueId(5249); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageRect1_Int2_Int1 = + TSymbolUniqueId(5250); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(5251); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(5252); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(5253); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5254); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5255); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5256); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2D1_Int2_Float1 = + TSymbolUniqueId(5257); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2D1_Int2_Float1 = + TSymbolUniqueId(5258); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2D1_Int2_Float1 = + TSymbolUniqueId(5259); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image3D1_Int3_Float1 = + TSymbolUniqueId(5260); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage3D1_Int3_Float1 = + TSymbolUniqueId(5261); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage3D1_Int3_Float1 = + TSymbolUniqueId(5262); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCube1_Int3_Float1 = + TSymbolUniqueId(5263); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCube1_Int3_Float1 = + TSymbolUniqueId(5264); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCube1_Int3_Float1 = + TSymbolUniqueId(5265); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageBuffer1_Int1_Float1 = + TSymbolUniqueId(5266); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageBuffer1_Int1_Float1 = + TSymbolUniqueId(5267); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageBuffer1_Int1_Float1 = + TSymbolUniqueId(5268); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DArray1_Int3_Float1 = + TSymbolUniqueId(5269); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DArray1_Int3_Float1 = + TSymbolUniqueId(5270); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DArray1_Int3_Float1 = + TSymbolUniqueId(5271); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCubeArray1_Int3_Float1 = + TSymbolUniqueId(5272); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCubeArray1_Int3_Float1 = + TSymbolUniqueId(5273); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCubeArray1_Int3_Float1 = + TSymbolUniqueId(5274); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image1D1_Int1_Float1 = + TSymbolUniqueId(5275); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage1D1_Int1_Float1 = + TSymbolUniqueId(5276); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage1D1_Int1_Float1 = + TSymbolUniqueId(5277); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image1DArray1_Int2_Float1 = + TSymbolUniqueId(5278); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage1DArray1_Int2_Float1 = + TSymbolUniqueId(5279); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage1DArray1_Int2_Float1 = + TSymbolUniqueId(5280); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageRect1_Int2_Float1 = + TSymbolUniqueId(5281); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageRect1_Int2_Float1 = + TSymbolUniqueId(5282); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageRect1_Int2_Float1 = + TSymbolUniqueId(5283); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMS1_Int2_Int1_Float1 = + TSymbolUniqueId(5284); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_Float1 = + TSymbolUniqueId(5285); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_Float1 = + TSymbolUniqueId(5286); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_Float1 = + TSymbolUniqueId(5287); + static constexpr const TSymbolUniqueId + imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_Float1 = TSymbolUniqueId(5288); + static constexpr const TSymbolUniqueId + imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_Float1 = TSymbolUniqueId(5289); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2D1_Int2_UInt1_UInt1 = + TSymbolUniqueId(5290); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2D1_Int2_UInt1_UInt1 = + TSymbolUniqueId(5291); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2D1_Int2_UInt1_UInt1 = + TSymbolUniqueId(5292); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image3D1_Int3_UInt1_UInt1 = + TSymbolUniqueId(5293); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage3D1_Int3_UInt1_UInt1 = + TSymbolUniqueId(5294); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage3D1_Int3_UInt1_UInt1 = + TSymbolUniqueId(5295); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageCube1_Int3_UInt1_UInt1 = + TSymbolUniqueId(5296); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageCube1_Int3_UInt1_UInt1 = + TSymbolUniqueId(5297); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageCube1_Int3_UInt1_UInt1 = + TSymbolUniqueId(5298); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageBuffer1_Int1_UInt1_UInt1 = + TSymbolUniqueId(5299); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageBuffer1_Int1_UInt1_UInt1 = + TSymbolUniqueId(5300); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageBuffer1_Int1_UInt1_UInt1 = + TSymbolUniqueId(5301); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2DArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(5302); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2DArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(5303); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2DArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(5304); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageCubeArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(5305); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_IImageCubeArray1_Int3_UInt1_UInt1 = TSymbolUniqueId(5306); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_UImageCubeArray1_Int3_UInt1_UInt1 = TSymbolUniqueId(5307); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image1D1_Int1_UInt1_UInt1 = + TSymbolUniqueId(5308); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage1D1_Int1_UInt1_UInt1 = + TSymbolUniqueId(5309); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage1D1_Int1_UInt1_UInt1 = + TSymbolUniqueId(5310); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image1DArray1_Int2_UInt1_UInt1 = + TSymbolUniqueId(5311); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage1DArray1_Int2_UInt1_UInt1 = + TSymbolUniqueId(5312); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage1DArray1_Int2_UInt1_UInt1 = + TSymbolUniqueId(5313); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageRect1_Int2_UInt1_UInt1 = + TSymbolUniqueId(5314); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageRect1_Int2_UInt1_UInt1 = + TSymbolUniqueId(5315); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageRect1_Int2_UInt1_UInt1 = + TSymbolUniqueId(5316); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2DMS1_Int2_Int1_UInt1_UInt1 = + TSymbolUniqueId(5317); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_IImage2DMS1_Int2_Int1_UInt1_UInt1 = TSymbolUniqueId(5318); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_UImage2DMS1_Int2_Int1_UInt1_UInt1 = TSymbolUniqueId(5319); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_Image2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(5320); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_IImage2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(5321); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_UImage2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(5322); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2D1_Int2_Int1_Int1 = + TSymbolUniqueId(5323); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2D1_Int2_Int1_Int1 = + TSymbolUniqueId(5324); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2D1_Int2_Int1_Int1 = + TSymbolUniqueId(5325); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image3D1_Int3_Int1_Int1 = + TSymbolUniqueId(5326); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage3D1_Int3_Int1_Int1 = + TSymbolUniqueId(5327); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage3D1_Int3_Int1_Int1 = + TSymbolUniqueId(5328); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageCube1_Int3_Int1_Int1 = + TSymbolUniqueId(5329); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageCube1_Int3_Int1_Int1 = + TSymbolUniqueId(5330); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageCube1_Int3_Int1_Int1 = + TSymbolUniqueId(5331); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageBuffer1_Int1_Int1_Int1 = + TSymbolUniqueId(5332); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageBuffer1_Int1_Int1_Int1 = + TSymbolUniqueId(5333); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageBuffer1_Int1_Int1_Int1 = + TSymbolUniqueId(5334); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2DArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5335); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2DArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5336); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2DArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5337); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageCubeArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5338); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageCubeArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5339); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageCubeArray1_Int3_Int1_Int1 = + TSymbolUniqueId(5340); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image1D1_Int1_Int1_Int1 = + TSymbolUniqueId(5341); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage1D1_Int1_Int1_Int1 = + TSymbolUniqueId(5342); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage1D1_Int1_Int1_Int1 = + TSymbolUniqueId(5343); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(5344); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(5345); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(5346); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageRect1_Int2_Int1_Int1 = + TSymbolUniqueId(5347); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageRect1_Int2_Int1_Int1 = + TSymbolUniqueId(5348); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageRect1_Int2_Int1_Int1 = + TSymbolUniqueId(5349); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2DMS1_Int2_Int1_Int1_Int1 = + TSymbolUniqueId(5350); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2DMS1_Int2_Int1_Int1_Int1 = + TSymbolUniqueId(5351); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2DMS1_Int2_Int1_Int1_Int1 = + TSymbolUniqueId(5352); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_Image2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(5353); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_IImage2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(5354); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_UImage2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(5355); + static constexpr const TSymbolUniqueId pixelLocalLoadANGLE_PixelLocalANGLE1 = + TSymbolUniqueId(5356); + static constexpr const TSymbolUniqueId pt01g = TSymbolUniqueId(5357); + static constexpr const TSymbolUniqueId pixelLocalLoadANGLE_IPixelLocalANGLE1 = + TSymbolUniqueId(5358); + static constexpr const TSymbolUniqueId pt01h = TSymbolUniqueId(5359); + static constexpr const TSymbolUniqueId pixelLocalLoadANGLE_UPixelLocalANGLE1 = + TSymbolUniqueId(5360); + static constexpr const TSymbolUniqueId pt01i = TSymbolUniqueId(5361); + static constexpr const TSymbolUniqueId pixelLocalStoreANGLE_PixelLocalANGLE1_Float4 = + TSymbolUniqueId(5362); + static constexpr const TSymbolUniqueId pixelLocalStoreANGLE_IPixelLocalANGLE1_Int4 = + TSymbolUniqueId(5363); + static constexpr const TSymbolUniqueId pixelLocalStoreANGLE_UPixelLocalANGLE1_UInt4 = + TSymbolUniqueId(5364); + static constexpr const TSymbolUniqueId beginInvocationInterlockNV = TSymbolUniqueId(5365); + static constexpr const TSymbolUniqueId endInvocationInterlockNV = TSymbolUniqueId(5366); + static constexpr const TSymbolUniqueId beginFragmentShaderOrderingINTEL = TSymbolUniqueId(5367); + static constexpr const TSymbolUniqueId beginInvocationInterlockARB = TSymbolUniqueId(5368); + static constexpr const TSymbolUniqueId endInvocationInterlockARB = TSymbolUniqueId(5369); + static constexpr const TSymbolUniqueId memoryBarrier = TSymbolUniqueId(5370); + static constexpr const TSymbolUniqueId memoryBarrierAtomicCounter = TSymbolUniqueId(5371); + static constexpr const TSymbolUniqueId memoryBarrierBuffer = TSymbolUniqueId(5372); + static constexpr const TSymbolUniqueId memoryBarrierImage = TSymbolUniqueId(5373); + static constexpr const TSymbolUniqueId barrier = TSymbolUniqueId(5374); + static constexpr const TSymbolUniqueId memoryBarrierShared = TSymbolUniqueId(5375); + static constexpr const TSymbolUniqueId groupMemoryBarrier = TSymbolUniqueId(5376); + static constexpr const TSymbolUniqueId barrierTCS = TSymbolUniqueId(5377); + static constexpr const TSymbolUniqueId barrierTCSES3_2 = TSymbolUniqueId(5378); + static constexpr const TSymbolUniqueId EmitVertex = TSymbolUniqueId(5379); + static constexpr const TSymbolUniqueId EmitVertexES3_2 = TSymbolUniqueId(5380); + static constexpr const TSymbolUniqueId EndPrimitive = TSymbolUniqueId(5381); + static constexpr const TSymbolUniqueId EndPrimitiveES3_2 = TSymbolUniqueId(5382); + static constexpr const TSymbolUniqueId subpassLoad_SubpassInput1 = TSymbolUniqueId(5383); + static constexpr const TSymbolUniqueId pt01j = TSymbolUniqueId(5384); + static constexpr const TSymbolUniqueId subpassLoad_ISubpassInput1 = TSymbolUniqueId(5385); + static constexpr const TSymbolUniqueId pt01k = TSymbolUniqueId(5386); + static constexpr const TSymbolUniqueId subpassLoad_USubpassInput1 = TSymbolUniqueId(5387); + static constexpr const TSymbolUniqueId pt01l = TSymbolUniqueId(5388); + static constexpr const TSymbolUniqueId subpassLoad_SubpassInputMS1_Int1 = TSymbolUniqueId(5389); + static constexpr const TSymbolUniqueId pt01m = TSymbolUniqueId(5390); + static constexpr const TSymbolUniqueId subpassLoad_ISubpassInputMS1_Int1 = + TSymbolUniqueId(5391); + static constexpr const TSymbolUniqueId pt01n = TSymbolUniqueId(5392); + static constexpr const TSymbolUniqueId subpassLoad_USubpassInputMS1_Int1 = + TSymbolUniqueId(5393); + static constexpr const TSymbolUniqueId pt01o = TSymbolUniqueId(5394); + static constexpr const TSymbolUniqueId gl_DepthRangeParameters = TSymbolUniqueId(5395); + static constexpr const TSymbolUniqueId gl_DepthRange = TSymbolUniqueId(5396); + static constexpr const TSymbolUniqueId gl_NumSamples = TSymbolUniqueId(5397); + static constexpr const TSymbolUniqueId gl_NumSamplesES3_2 = TSymbolUniqueId(5398); + static constexpr const TSymbolUniqueId gl_MaxVertexAttribs = TSymbolUniqueId(5399); + static constexpr const TSymbolUniqueId gl_MaxVertexUniformVectors = TSymbolUniqueId(5400); + static constexpr const TSymbolUniqueId gl_MaxVertexTextureImageUnits = TSymbolUniqueId(5401); + static constexpr const TSymbolUniqueId gl_MaxCombinedTextureImageUnits = TSymbolUniqueId(5402); + static constexpr const TSymbolUniqueId gl_MaxTextureImageUnits = TSymbolUniqueId(5403); + static constexpr const TSymbolUniqueId gl_MaxFragmentUniformVectors = TSymbolUniqueId(5404); + static constexpr const TSymbolUniqueId gl_MaxVaryingVectors = TSymbolUniqueId(5405); + static constexpr const TSymbolUniqueId gl_MaxDrawBuffers = TSymbolUniqueId(5406); + static constexpr const TSymbolUniqueId gl_MaxDualSourceDrawBuffersEXT = TSymbolUniqueId(5407); + static constexpr const TSymbolUniqueId gl_MaxVertexOutputVectors = TSymbolUniqueId(5408); + static constexpr const TSymbolUniqueId gl_MaxFragmentInputVectors = TSymbolUniqueId(5409); + static constexpr const TSymbolUniqueId gl_MinProgramTexelOffset = TSymbolUniqueId(5410); + static constexpr const TSymbolUniqueId gl_MaxProgramTexelOffset = TSymbolUniqueId(5411); + static constexpr const TSymbolUniqueId gl_MaxImageUnits = TSymbolUniqueId(5412); + static constexpr const TSymbolUniqueId gl_MaxVertexImageUniforms = TSymbolUniqueId(5413); + static constexpr const TSymbolUniqueId gl_MaxFragmentImageUniforms = TSymbolUniqueId(5414); + static constexpr const TSymbolUniqueId gl_MaxComputeImageUniforms = TSymbolUniqueId(5415); + static constexpr const TSymbolUniqueId gl_MaxCombinedImageUniforms = TSymbolUniqueId(5416); + static constexpr const TSymbolUniqueId gl_MaxCombinedShaderOutputResources = + TSymbolUniqueId(5417); + static constexpr const TSymbolUniqueId gl_MaxComputeWorkGroupCount = TSymbolUniqueId(5418); + static constexpr const TSymbolUniqueId gl_MaxComputeWorkGroupSize = TSymbolUniqueId(5419); + static constexpr const TSymbolUniqueId gl_MaxComputeUniformComponents = TSymbolUniqueId(5420); + static constexpr const TSymbolUniqueId gl_MaxComputeTextureImageUnits = TSymbolUniqueId(5421); + static constexpr const TSymbolUniqueId gl_MaxComputeAtomicCounters = TSymbolUniqueId(5422); + static constexpr const TSymbolUniqueId gl_MaxComputeAtomicCounterBuffers = + TSymbolUniqueId(5423); + static constexpr const TSymbolUniqueId gl_MaxVertexAtomicCounters = TSymbolUniqueId(5424); + static constexpr const TSymbolUniqueId gl_MaxFragmentAtomicCounters = TSymbolUniqueId(5425); + static constexpr const TSymbolUniqueId gl_MaxCombinedAtomicCounters = TSymbolUniqueId(5426); + static constexpr const TSymbolUniqueId gl_MaxAtomicCounterBindings = TSymbolUniqueId(5427); + static constexpr const TSymbolUniqueId gl_MaxVertexAtomicCounterBuffers = TSymbolUniqueId(5428); + static constexpr const TSymbolUniqueId gl_MaxFragmentAtomicCounterBuffers = + TSymbolUniqueId(5429); + static constexpr const TSymbolUniqueId gl_MaxCombinedAtomicCounterBuffers = + TSymbolUniqueId(5430); + static constexpr const TSymbolUniqueId gl_MaxAtomicCounterBufferSize = TSymbolUniqueId(5431); + static constexpr const TSymbolUniqueId gl_MaxGeometryInputComponents = TSymbolUniqueId(5432); + static constexpr const TSymbolUniqueId gl_MaxGeometryInputComponentsES3_2 = + TSymbolUniqueId(5433); + static constexpr const TSymbolUniqueId gl_MaxGeometryOutputComponents = TSymbolUniqueId(5434); + static constexpr const TSymbolUniqueId gl_MaxGeometryOutputComponentsES3_2 = + TSymbolUniqueId(5435); + static constexpr const TSymbolUniqueId gl_MaxGeometryImageUniforms = TSymbolUniqueId(5436); + static constexpr const TSymbolUniqueId gl_MaxGeometryImageUniformsES3_2 = TSymbolUniqueId(5437); + static constexpr const TSymbolUniqueId gl_MaxGeometryTextureImageUnits = TSymbolUniqueId(5438); + static constexpr const TSymbolUniqueId gl_MaxGeometryTextureImageUnitsES3_2 = + TSymbolUniqueId(5439); + static constexpr const TSymbolUniqueId gl_MaxGeometryOutputVertices = TSymbolUniqueId(5440); + static constexpr const TSymbolUniqueId gl_MaxGeometryOutputVerticesES3_2 = + TSymbolUniqueId(5441); + static constexpr const TSymbolUniqueId gl_MaxGeometryTotalOutputComponents = + TSymbolUniqueId(5442); + static constexpr const TSymbolUniqueId gl_MaxGeometryTotalOutputComponentsES3_2 = + TSymbolUniqueId(5443); + static constexpr const TSymbolUniqueId gl_MaxGeometryUniformComponents = TSymbolUniqueId(5444); + static constexpr const TSymbolUniqueId gl_MaxGeometryUniformComponentsES3_2 = + TSymbolUniqueId(5445); + static constexpr const TSymbolUniqueId gl_MaxGeometryAtomicCounters = TSymbolUniqueId(5446); + static constexpr const TSymbolUniqueId gl_MaxGeometryAtomicCountersES3_2 = + TSymbolUniqueId(5447); + static constexpr const TSymbolUniqueId gl_MaxGeometryAtomicCounterBuffers = + TSymbolUniqueId(5448); + static constexpr const TSymbolUniqueId gl_MaxGeometryAtomicCounterBuffersES3_2 = + TSymbolUniqueId(5449); + static constexpr const TSymbolUniqueId gl_MaxTessControlInputComponents = TSymbolUniqueId(5450); + static constexpr const TSymbolUniqueId gl_MaxTessControlInputComponentsES3_2 = + TSymbolUniqueId(5451); + static constexpr const TSymbolUniqueId gl_MaxTessControlOutputComponents = + TSymbolUniqueId(5452); + static constexpr const TSymbolUniqueId gl_MaxTessControlOutputComponentsES3_2 = + TSymbolUniqueId(5453); + static constexpr const TSymbolUniqueId gl_MaxTessControlTextureImageUnits = + TSymbolUniqueId(5454); + static constexpr const TSymbolUniqueId gl_MaxTessControlTextureImageUnitsES3_2 = + TSymbolUniqueId(5455); + static constexpr const TSymbolUniqueId gl_MaxTessControlUniformComponents = + TSymbolUniqueId(5456); + static constexpr const TSymbolUniqueId gl_MaxTessControlUniformComponentsES3_2 = + TSymbolUniqueId(5457); + static constexpr const TSymbolUniqueId gl_MaxTessControlTotalOutputComponents = + TSymbolUniqueId(5458); + static constexpr const TSymbolUniqueId gl_MaxTessControlTotalOutputComponentsES3_2 = + TSymbolUniqueId(5459); + static constexpr const TSymbolUniqueId gl_MaxTessControlImageUniforms = TSymbolUniqueId(5460); + static constexpr const TSymbolUniqueId gl_MaxTessControlImageUniformsES3_2 = + TSymbolUniqueId(5461); + static constexpr const TSymbolUniqueId gl_MaxTessControlAtomicCounters = TSymbolUniqueId(5462); + static constexpr const TSymbolUniqueId gl_MaxTessControlAtomicCountersES3_2 = + TSymbolUniqueId(5463); + static constexpr const TSymbolUniqueId gl_MaxTessControlAtomicCounterBuffers = + TSymbolUniqueId(5464); + static constexpr const TSymbolUniqueId gl_MaxTessControlAtomicCounterBuffersES3_2 = + TSymbolUniqueId(5465); + static constexpr const TSymbolUniqueId gl_MaxTessPatchComponents = TSymbolUniqueId(5466); + static constexpr const TSymbolUniqueId gl_MaxTessPatchComponentsES3_2 = TSymbolUniqueId(5467); + static constexpr const TSymbolUniqueId gl_MaxPatchVertices = TSymbolUniqueId(5468); + static constexpr const TSymbolUniqueId gl_MaxPatchVerticesES3_2 = TSymbolUniqueId(5469); + static constexpr const TSymbolUniqueId gl_MaxTessGenLevel = TSymbolUniqueId(5470); + static constexpr const TSymbolUniqueId gl_MaxTessGenLevelES3_2 = TSymbolUniqueId(5471); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationInputComponents = + TSymbolUniqueId(5472); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationInputComponentsES3_2 = + TSymbolUniqueId(5473); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationOutputComponents = + TSymbolUniqueId(5474); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationOutputComponentsES3_2 = + TSymbolUniqueId(5475); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationTextureImageUnits = + TSymbolUniqueId(5476); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationTextureImageUnitsES3_2 = + TSymbolUniqueId(5477); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationUniformComponents = + TSymbolUniqueId(5478); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationUniformComponentsES3_2 = + TSymbolUniqueId(5479); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationImageUniforms = + TSymbolUniqueId(5480); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationImageUniformsES3_2 = + TSymbolUniqueId(5481); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationAtomicCounters = + TSymbolUniqueId(5482); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationAtomicCountersES3_2 = + TSymbolUniqueId(5483); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationAtomicCounterBuffers = + TSymbolUniqueId(5484); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationAtomicCounterBuffersES3_2 = + TSymbolUniqueId(5485); + static constexpr const TSymbolUniqueId gl_MaxSamples = TSymbolUniqueId(5486); + static constexpr const TSymbolUniqueId gl_MaxSamplesES3_2 = TSymbolUniqueId(5487); + static constexpr const TSymbolUniqueId gl_MaxClipDistancesAPPLE = TSymbolUniqueId(5488); + static constexpr const TSymbolUniqueId gl_MaxCullDistancesEXT = TSymbolUniqueId(5489); + static constexpr const TSymbolUniqueId gl_MaxCombinedClipAndCullDistancesEXT = + TSymbolUniqueId(5490); + static constexpr const TSymbolUniqueId gl_FragCoord = TSymbolUniqueId(5491); + static constexpr const TSymbolUniqueId gl_FrontFacing = TSymbolUniqueId(5492); + static constexpr const TSymbolUniqueId gl_PointCoord = TSymbolUniqueId(5493); + static constexpr const TSymbolUniqueId gl_FragColor = TSymbolUniqueId(5494); + static constexpr const TSymbolUniqueId gl_FragData = TSymbolUniqueId(5495); + static constexpr const TSymbolUniqueId gl_FragDepth = TSymbolUniqueId(5496); + static constexpr const TSymbolUniqueId gl_HelperInvocation = TSymbolUniqueId(5497); + static constexpr const TSymbolUniqueId gl_FragCoord300 = TSymbolUniqueId(5498); + static constexpr const TSymbolUniqueId gl_SecondaryFragColorEXT = TSymbolUniqueId(5499); + static constexpr const TSymbolUniqueId gl_SecondaryFragDataEXT = TSymbolUniqueId(5500); + static constexpr const TSymbolUniqueId gl_FragDepthEXT = TSymbolUniqueId(5501); + static constexpr const TSymbolUniqueId gl_LastFragData = TSymbolUniqueId(5502); + static constexpr const TSymbolUniqueId gl_LastFragColor = TSymbolUniqueId(5503); + static constexpr const TSymbolUniqueId gl_LastFragDataNV = TSymbolUniqueId(5504); + static constexpr const TSymbolUniqueId gl_LastFragColorARM = TSymbolUniqueId(5505); + static constexpr const TSymbolUniqueId gl_PrimitiveID = TSymbolUniqueId(5506); + static constexpr const TSymbolUniqueId gl_PrimitiveIDES3_2 = TSymbolUniqueId(5507); + static constexpr const TSymbolUniqueId gl_Layer = TSymbolUniqueId(5508); + static constexpr const TSymbolUniqueId gl_LayerES3_2 = TSymbolUniqueId(5509); + static constexpr const TSymbolUniqueId gl_SampleID = TSymbolUniqueId(5510); + static constexpr const TSymbolUniqueId gl_SampleIDES3_2 = TSymbolUniqueId(5511); + static constexpr const TSymbolUniqueId gl_SamplePosition = TSymbolUniqueId(5512); + static constexpr const TSymbolUniqueId gl_SamplePositionES3_2 = TSymbolUniqueId(5513); + static constexpr const TSymbolUniqueId gl_SampleMaskIn = TSymbolUniqueId(5514); + static constexpr const TSymbolUniqueId gl_SampleMaskInES3_2 = TSymbolUniqueId(5515); + static constexpr const TSymbolUniqueId gl_SampleMask = TSymbolUniqueId(5516); + static constexpr const TSymbolUniqueId gl_SampleMaskES3_2 = TSymbolUniqueId(5517); + static constexpr const TSymbolUniqueId gl_CullDistance = TSymbolUniqueId(5518); + static constexpr const TSymbolUniqueId gl_ClipDistance = TSymbolUniqueId(5519); + static constexpr const TSymbolUniqueId gl_Position = TSymbolUniqueId(5520); + static constexpr const TSymbolUniqueId gl_PointSize = TSymbolUniqueId(5521); + static constexpr const TSymbolUniqueId gl_InstanceID = TSymbolUniqueId(5522); + static constexpr const TSymbolUniqueId gl_InstanceIndex = TSymbolUniqueId(5523); + static constexpr const TSymbolUniqueId gl_VertexID = TSymbolUniqueId(5524); + static constexpr const TSymbolUniqueId gl_VertexIndex = TSymbolUniqueId(5525); + static constexpr const TSymbolUniqueId gl_ViewportIndex = TSymbolUniqueId(5526); + static constexpr const TSymbolUniqueId gl_LayerVS = TSymbolUniqueId(5527); + static constexpr const TSymbolUniqueId gl_PointSize300 = TSymbolUniqueId(5528); + static constexpr const TSymbolUniqueId gl_DrawID = TSymbolUniqueId(5529); + static constexpr const TSymbolUniqueId gl_BaseVertex = TSymbolUniqueId(5530); + static constexpr const TSymbolUniqueId gl_BaseInstance = TSymbolUniqueId(5531); + static constexpr const TSymbolUniqueId angle_BaseVertex = TSymbolUniqueId(5532); + static constexpr const TSymbolUniqueId angle_BaseInstance = TSymbolUniqueId(5533); + static constexpr const TSymbolUniqueId gl_ClipDistanceAPPLE = TSymbolUniqueId(5534); + static constexpr const TSymbolUniqueId gl_CullDistanceEXT = TSymbolUniqueId(5535); + static constexpr const TSymbolUniqueId gl_NumWorkGroups = TSymbolUniqueId(5536); + static constexpr const TSymbolUniqueId gl_WorkGroupSize = TSymbolUniqueId(5537); + static constexpr const TSymbolUniqueId gl_WorkGroupID = TSymbolUniqueId(5538); + static constexpr const TSymbolUniqueId gl_LocalInvocationID = TSymbolUniqueId(5539); + static constexpr const TSymbolUniqueId gl_GlobalInvocationID = TSymbolUniqueId(5540); + static constexpr const TSymbolUniqueId gl_LocalInvocationIndex = TSymbolUniqueId(5541); + static constexpr const TSymbolUniqueId gl_PrimitiveIDIn = TSymbolUniqueId(5542); + static constexpr const TSymbolUniqueId gl_PrimitiveIDInES3_2 = TSymbolUniqueId(5543); + static constexpr const TSymbolUniqueId gl_InvocationID = TSymbolUniqueId(5544); + static constexpr const TSymbolUniqueId gl_InvocationIDES3_2 = TSymbolUniqueId(5545); + static constexpr const TSymbolUniqueId gl_PrimitiveIDGS = TSymbolUniqueId(5546); + static constexpr const TSymbolUniqueId gl_PrimitiveIDGSES3_2 = TSymbolUniqueId(5547); + static constexpr const TSymbolUniqueId gl_LayerGS = TSymbolUniqueId(5548); + static constexpr const TSymbolUniqueId gl_LayerGSES3_2 = TSymbolUniqueId(5549); + static constexpr const TSymbolUniqueId gl_PerVertex = TSymbolUniqueId(5550); + static constexpr const TSymbolUniqueId gl_PerVertexES3_2 = TSymbolUniqueId(5551); + static constexpr const TSymbolUniqueId gl_in = TSymbolUniqueId(5552); + static constexpr const TSymbolUniqueId gl_inES3_2 = TSymbolUniqueId(5553); + static constexpr const TSymbolUniqueId gl_PerVertexOutBlock = TSymbolUniqueId(5554); + static constexpr const TSymbolUniqueId gl_PerVertexOutBlockES3_2 = TSymbolUniqueId(5555); + static constexpr const TSymbolUniqueId gl_PositionGS = TSymbolUniqueId(5556); + static constexpr const TSymbolUniqueId gl_PositionGSES3_2 = TSymbolUniqueId(5557); + static constexpr const TSymbolUniqueId gl_PatchVerticesInTCS = TSymbolUniqueId(5558); + static constexpr const TSymbolUniqueId gl_PatchVerticesInTCSES3_2 = TSymbolUniqueId(5559); + static constexpr const TSymbolUniqueId gl_InvocationIDTCS = TSymbolUniqueId(5560); + static constexpr const TSymbolUniqueId gl_InvocationIDTCSES3_2 = TSymbolUniqueId(5561); + static constexpr const TSymbolUniqueId gl_PrimitiveIDTCS = TSymbolUniqueId(5562); + static constexpr const TSymbolUniqueId gl_PrimitiveIDTCSES3_2 = TSymbolUniqueId(5563); + static constexpr const TSymbolUniqueId gl_TessLevelOuterTCS = TSymbolUniqueId(5564); + static constexpr const TSymbolUniqueId gl_TessLevelOuterTCSES3_2 = TSymbolUniqueId(5565); + static constexpr const TSymbolUniqueId gl_TessLevelInnerTCS = TSymbolUniqueId(5566); + static constexpr const TSymbolUniqueId gl_TessLevelInnerTCSES3_2 = TSymbolUniqueId(5567); + static constexpr const TSymbolUniqueId gl_PerVertexTCS = TSymbolUniqueId(5568); + static constexpr const TSymbolUniqueId gl_PerVertexTCSES3_2 = TSymbolUniqueId(5569); + static constexpr const TSymbolUniqueId gl_inTCS = TSymbolUniqueId(5570); + static constexpr const TSymbolUniqueId gl_inTCSES3_2 = TSymbolUniqueId(5571); + static constexpr const TSymbolUniqueId gl_outTCS = TSymbolUniqueId(5572); + static constexpr const TSymbolUniqueId gl_outTCSES3_2 = TSymbolUniqueId(5573); + static constexpr const TSymbolUniqueId gl_BoundingBoxTCS = TSymbolUniqueId(5574); + static constexpr const TSymbolUniqueId gl_BoundingBoxTCSES3_2 = TSymbolUniqueId(5575); + static constexpr const TSymbolUniqueId gl_PerVertexOutTcsBlock = TSymbolUniqueId(5576); + static constexpr const TSymbolUniqueId gl_PerVertexOutTcsBlockES3_2 = TSymbolUniqueId(5577); + static constexpr const TSymbolUniqueId gl_PositionTCS = TSymbolUniqueId(5578); + static constexpr const TSymbolUniqueId gl_PositionTCSES3_2 = TSymbolUniqueId(5579); + static constexpr const TSymbolUniqueId gl_BoundingBoxEXTTCS = TSymbolUniqueId(5580); + static constexpr const TSymbolUniqueId gl_BoundingBoxEXTTCSES3_2 = TSymbolUniqueId(5581); + static constexpr const TSymbolUniqueId gl_BoundingBoxOESTCS = TSymbolUniqueId(5582); + static constexpr const TSymbolUniqueId gl_BoundingBoxOESTCSES3_2 = TSymbolUniqueId(5583); + static constexpr const TSymbolUniqueId gl_PatchVerticesInTES = TSymbolUniqueId(5584); + static constexpr const TSymbolUniqueId gl_PatchVerticesInTESES3_2 = TSymbolUniqueId(5585); + static constexpr const TSymbolUniqueId gl_PrimitiveIDTES = TSymbolUniqueId(5586); + static constexpr const TSymbolUniqueId gl_PrimitiveIDTESES3_2 = TSymbolUniqueId(5587); + static constexpr const TSymbolUniqueId gl_TessCoord = TSymbolUniqueId(5588); + static constexpr const TSymbolUniqueId gl_TessLevelOuterTES = TSymbolUniqueId(5589); + static constexpr const TSymbolUniqueId gl_TessLevelOuterTESES3_2 = TSymbolUniqueId(5590); + static constexpr const TSymbolUniqueId gl_TessLevelInnerTES = TSymbolUniqueId(5591); + static constexpr const TSymbolUniqueId gl_TessLevelInnerTESES3_2 = TSymbolUniqueId(5592); + static constexpr const TSymbolUniqueId gl_PerVertexTES = TSymbolUniqueId(5593); + static constexpr const TSymbolUniqueId gl_PerVertexTESES3_2 = TSymbolUniqueId(5594); + static constexpr const TSymbolUniqueId gl_inTES = TSymbolUniqueId(5595); + static constexpr const TSymbolUniqueId gl_inTESES3_2 = TSymbolUniqueId(5596); + static constexpr const TSymbolUniqueId gl_outTES = TSymbolUniqueId(5597); + static constexpr const TSymbolUniqueId gl_outTESES3_2 = TSymbolUniqueId(5598); + static constexpr const TSymbolUniqueId gl_PerVertexOutTesBlock = TSymbolUniqueId(5599); + static constexpr const TSymbolUniqueId gl_PerVertexOutTesBlockES3_2 = TSymbolUniqueId(5600); + static constexpr const TSymbolUniqueId gl_PositionTES = TSymbolUniqueId(5601); + static constexpr const TSymbolUniqueId gl_PositionTESES3_2 = TSymbolUniqueId(5602); + static constexpr const TSymbolUniqueId gl_ViewID_OVR = TSymbolUniqueId(5603); + +}; // class BuiltInId + +namespace BuiltInVariable +{ + +const TVariable *angle_BaseInstance(); +const TVariable *angle_BaseVertex(); +const TVariable *gl_BaseInstance(); +const TVariable *gl_BaseVertex(); +const TVariable *gl_DrawID(); +const TVariable *gl_FragColor(); +const TVariable *gl_FragCoord(); +const TVariable *gl_FragCoord300(); +const TVariable *gl_FragDepth(); +const TVariable *gl_FrontFacing(); +const TVariable *gl_GlobalInvocationID(); +const TVariable *gl_HelperInvocation(); +const TVariable *gl_InstanceID(); +const TVariable *gl_InstanceIndex(); +const TVariable *gl_InvocationID(); +const TVariable *gl_InvocationIDES3_2(); +const TVariable *gl_InvocationIDTCS(); +const TVariable *gl_InvocationIDTCSES3_2(); +const TVariable *gl_LastFragColor(); +const TVariable *gl_LastFragColorARM(); +const TVariable *gl_Layer(); +const TVariable *gl_LayerES3_2(); +const TVariable *gl_LayerGS(); +const TVariable *gl_LayerGSES3_2(); +const TVariable *gl_LayerVS(); +const TVariable *gl_LocalInvocationID(); +const TVariable *gl_LocalInvocationIndex(); +const TVariable *gl_NumSamples(); +const TVariable *gl_NumSamplesES3_2(); +const TVariable *gl_NumWorkGroups(); +const TVariable *gl_PatchVerticesInTCS(); +const TVariable *gl_PatchVerticesInTCSES3_2(); +const TVariable *gl_PatchVerticesInTES(); +const TVariable *gl_PatchVerticesInTESES3_2(); +const TVariable *gl_PointCoord(); +const TVariable *gl_PointSize(); +const TVariable *gl_PointSize300(); +const TVariable *gl_Position(); +const TVariable *gl_PrimitiveID(); +const TVariable *gl_PrimitiveIDES3_2(); +const TVariable *gl_PrimitiveIDGS(); +const TVariable *gl_PrimitiveIDGSES3_2(); +const TVariable *gl_PrimitiveIDIn(); +const TVariable *gl_PrimitiveIDInES3_2(); +const TVariable *gl_PrimitiveIDTCS(); +const TVariable *gl_PrimitiveIDTCSES3_2(); +const TVariable *gl_PrimitiveIDTES(); +const TVariable *gl_PrimitiveIDTESES3_2(); +const TVariable *gl_SampleID(); +const TVariable *gl_SampleIDES3_2(); +const TVariable *gl_SamplePosition(); +const TVariable *gl_SamplePositionES3_2(); +const TVariable *gl_SecondaryFragColorEXT(); +const TVariable *gl_TessCoord(); +const TVariable *gl_VertexID(); +const TVariable *gl_VertexIndex(); +const TVariable *gl_ViewID_OVR(); +const TVariable *gl_ViewportIndex(); +const TVariable *gl_WorkGroupID(); +const TVariable *gl_WorkGroupSize(); + +} // namespace BuiltInVariable + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/BuiltIn_complete_autogen.h b/gfx/angle/checkout/src/compiler/translator/tree_util/BuiltIn_complete_autogen.h new file mode 100644 index 0000000000..406d930d56 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/BuiltIn_complete_autogen.h @@ -0,0 +1,5008 @@ +// GENERATED FILE - DO NOT EDIT. +// Generated by gen_builtin_symbols.py using data from builtin_variables.json and +// builtin_function_declarations.txt. +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// BuiltIn_complete_autogen.h: +// Compile-time initialized built-ins. + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_ + +#include "compiler/translator/SymbolUniqueId.h" + +namespace sh +{ + +class TVariable; + +class BuiltInId +{ + public: + static constexpr const TSymbolUniqueId radians_Float1 = TSymbolUniqueId(0); + static constexpr const TSymbolUniqueId pt00B = TSymbolUniqueId(1); + static constexpr const TSymbolUniqueId radians_Float2 = TSymbolUniqueId(2); + static constexpr const TSymbolUniqueId pt10B = TSymbolUniqueId(3); + static constexpr const TSymbolUniqueId radians_Float3 = TSymbolUniqueId(4); + static constexpr const TSymbolUniqueId pt20B = TSymbolUniqueId(5); + static constexpr const TSymbolUniqueId radians_Float4 = TSymbolUniqueId(6); + static constexpr const TSymbolUniqueId pt30B = TSymbolUniqueId(7); + static constexpr const TSymbolUniqueId degrees_Float1 = TSymbolUniqueId(8); + static constexpr const TSymbolUniqueId degrees_Float2 = TSymbolUniqueId(9); + static constexpr const TSymbolUniqueId degrees_Float3 = TSymbolUniqueId(10); + static constexpr const TSymbolUniqueId degrees_Float4 = TSymbolUniqueId(11); + static constexpr const TSymbolUniqueId sin_Float1 = TSymbolUniqueId(12); + static constexpr const TSymbolUniqueId sin_Float2 = TSymbolUniqueId(13); + static constexpr const TSymbolUniqueId sin_Float3 = TSymbolUniqueId(14); + static constexpr const TSymbolUniqueId sin_Float4 = TSymbolUniqueId(15); + static constexpr const TSymbolUniqueId cos_Float1 = TSymbolUniqueId(16); + static constexpr const TSymbolUniqueId cos_Float2 = TSymbolUniqueId(17); + static constexpr const TSymbolUniqueId cos_Float3 = TSymbolUniqueId(18); + static constexpr const TSymbolUniqueId cos_Float4 = TSymbolUniqueId(19); + static constexpr const TSymbolUniqueId tan_Float1 = TSymbolUniqueId(20); + static constexpr const TSymbolUniqueId tan_Float2 = TSymbolUniqueId(21); + static constexpr const TSymbolUniqueId tan_Float3 = TSymbolUniqueId(22); + static constexpr const TSymbolUniqueId tan_Float4 = TSymbolUniqueId(23); + static constexpr const TSymbolUniqueId asin_Float1 = TSymbolUniqueId(24); + static constexpr const TSymbolUniqueId asin_Float2 = TSymbolUniqueId(25); + static constexpr const TSymbolUniqueId asin_Float3 = TSymbolUniqueId(26); + static constexpr const TSymbolUniqueId asin_Float4 = TSymbolUniqueId(27); + static constexpr const TSymbolUniqueId acos_Float1 = TSymbolUniqueId(28); + static constexpr const TSymbolUniqueId acos_Float2 = TSymbolUniqueId(29); + static constexpr const TSymbolUniqueId acos_Float3 = TSymbolUniqueId(30); + static constexpr const TSymbolUniqueId acos_Float4 = TSymbolUniqueId(31); + static constexpr const TSymbolUniqueId atan_Float1_Float1 = TSymbolUniqueId(32); + static constexpr const TSymbolUniqueId atan_Float2_Float2 = TSymbolUniqueId(33); + static constexpr const TSymbolUniqueId atan_Float3_Float3 = TSymbolUniqueId(34); + static constexpr const TSymbolUniqueId atan_Float4_Float4 = TSymbolUniqueId(35); + static constexpr const TSymbolUniqueId atan_Float1 = TSymbolUniqueId(36); + static constexpr const TSymbolUniqueId atan_Float2 = TSymbolUniqueId(37); + static constexpr const TSymbolUniqueId atan_Float3 = TSymbolUniqueId(38); + static constexpr const TSymbolUniqueId atan_Float4 = TSymbolUniqueId(39); + static constexpr const TSymbolUniqueId sinh_Float1 = TSymbolUniqueId(40); + static constexpr const TSymbolUniqueId sinh_Float2 = TSymbolUniqueId(41); + static constexpr const TSymbolUniqueId sinh_Float3 = TSymbolUniqueId(42); + static constexpr const TSymbolUniqueId sinh_Float4 = TSymbolUniqueId(43); + static constexpr const TSymbolUniqueId cosh_Float1 = TSymbolUniqueId(44); + static constexpr const TSymbolUniqueId cosh_Float2 = TSymbolUniqueId(45); + static constexpr const TSymbolUniqueId cosh_Float3 = TSymbolUniqueId(46); + static constexpr const TSymbolUniqueId cosh_Float4 = TSymbolUniqueId(47); + static constexpr const TSymbolUniqueId tanh_Float1 = TSymbolUniqueId(48); + static constexpr const TSymbolUniqueId tanh_Float2 = TSymbolUniqueId(49); + static constexpr const TSymbolUniqueId tanh_Float3 = TSymbolUniqueId(50); + static constexpr const TSymbolUniqueId tanh_Float4 = TSymbolUniqueId(51); + static constexpr const TSymbolUniqueId asinh_Float1 = TSymbolUniqueId(52); + static constexpr const TSymbolUniqueId asinh_Float2 = TSymbolUniqueId(53); + static constexpr const TSymbolUniqueId asinh_Float3 = TSymbolUniqueId(54); + static constexpr const TSymbolUniqueId asinh_Float4 = TSymbolUniqueId(55); + static constexpr const TSymbolUniqueId acosh_Float1 = TSymbolUniqueId(56); + static constexpr const TSymbolUniqueId acosh_Float2 = TSymbolUniqueId(57); + static constexpr const TSymbolUniqueId acosh_Float3 = TSymbolUniqueId(58); + static constexpr const TSymbolUniqueId acosh_Float4 = TSymbolUniqueId(59); + static constexpr const TSymbolUniqueId atanh_Float1 = TSymbolUniqueId(60); + static constexpr const TSymbolUniqueId atanh_Float2 = TSymbolUniqueId(61); + static constexpr const TSymbolUniqueId atanh_Float3 = TSymbolUniqueId(62); + static constexpr const TSymbolUniqueId atanh_Float4 = TSymbolUniqueId(63); + static constexpr const TSymbolUniqueId pow_Float1_Float1 = TSymbolUniqueId(64); + static constexpr const TSymbolUniqueId pow_Float2_Float2 = TSymbolUniqueId(65); + static constexpr const TSymbolUniqueId pow_Float3_Float3 = TSymbolUniqueId(66); + static constexpr const TSymbolUniqueId pow_Float4_Float4 = TSymbolUniqueId(67); + static constexpr const TSymbolUniqueId exp_Float1 = TSymbolUniqueId(68); + static constexpr const TSymbolUniqueId exp_Float2 = TSymbolUniqueId(69); + static constexpr const TSymbolUniqueId exp_Float3 = TSymbolUniqueId(70); + static constexpr const TSymbolUniqueId exp_Float4 = TSymbolUniqueId(71); + static constexpr const TSymbolUniqueId log_Float1 = TSymbolUniqueId(72); + static constexpr const TSymbolUniqueId log_Float2 = TSymbolUniqueId(73); + static constexpr const TSymbolUniqueId log_Float3 = TSymbolUniqueId(74); + static constexpr const TSymbolUniqueId log_Float4 = TSymbolUniqueId(75); + static constexpr const TSymbolUniqueId exp2_Float1 = TSymbolUniqueId(76); + static constexpr const TSymbolUniqueId exp2_Float2 = TSymbolUniqueId(77); + static constexpr const TSymbolUniqueId exp2_Float3 = TSymbolUniqueId(78); + static constexpr const TSymbolUniqueId exp2_Float4 = TSymbolUniqueId(79); + static constexpr const TSymbolUniqueId log2_Float1 = TSymbolUniqueId(80); + static constexpr const TSymbolUniqueId log2_Float2 = TSymbolUniqueId(81); + static constexpr const TSymbolUniqueId log2_Float3 = TSymbolUniqueId(82); + static constexpr const TSymbolUniqueId log2_Float4 = TSymbolUniqueId(83); + static constexpr const TSymbolUniqueId sqrt_Float1 = TSymbolUniqueId(84); + static constexpr const TSymbolUniqueId sqrt_Float2 = TSymbolUniqueId(85); + static constexpr const TSymbolUniqueId sqrt_Float3 = TSymbolUniqueId(86); + static constexpr const TSymbolUniqueId sqrt_Float4 = TSymbolUniqueId(87); + static constexpr const TSymbolUniqueId sqrt_Double1 = TSymbolUniqueId(88); + static constexpr const TSymbolUniqueId pt00C = TSymbolUniqueId(89); + static constexpr const TSymbolUniqueId sqrt_Double2 = TSymbolUniqueId(90); + static constexpr const TSymbolUniqueId pt10C = TSymbolUniqueId(91); + static constexpr const TSymbolUniqueId sqrt_Double3 = TSymbolUniqueId(92); + static constexpr const TSymbolUniqueId pt20C = TSymbolUniqueId(93); + static constexpr const TSymbolUniqueId sqrt_Double4 = TSymbolUniqueId(94); + static constexpr const TSymbolUniqueId pt30C = TSymbolUniqueId(95); + static constexpr const TSymbolUniqueId inversesqrt_Float1 = TSymbolUniqueId(96); + static constexpr const TSymbolUniqueId inversesqrt_Float2 = TSymbolUniqueId(97); + static constexpr const TSymbolUniqueId inversesqrt_Float3 = TSymbolUniqueId(98); + static constexpr const TSymbolUniqueId inversesqrt_Float4 = TSymbolUniqueId(99); + static constexpr const TSymbolUniqueId inversesqrt_Double1 = TSymbolUniqueId(100); + static constexpr const TSymbolUniqueId inversesqrt_Double2 = TSymbolUniqueId(101); + static constexpr const TSymbolUniqueId inversesqrt_Double3 = TSymbolUniqueId(102); + static constexpr const TSymbolUniqueId inversesqrt_Double4 = TSymbolUniqueId(103); + static constexpr const TSymbolUniqueId abs_Float1 = TSymbolUniqueId(104); + static constexpr const TSymbolUniqueId abs_Float2 = TSymbolUniqueId(105); + static constexpr const TSymbolUniqueId abs_Float3 = TSymbolUniqueId(106); + static constexpr const TSymbolUniqueId abs_Float4 = TSymbolUniqueId(107); + static constexpr const TSymbolUniqueId abs_Int1 = TSymbolUniqueId(108); + static constexpr const TSymbolUniqueId pt00D = TSymbolUniqueId(109); + static constexpr const TSymbolUniqueId abs_Int2 = TSymbolUniqueId(110); + static constexpr const TSymbolUniqueId pt10D = TSymbolUniqueId(111); + static constexpr const TSymbolUniqueId abs_Int3 = TSymbolUniqueId(112); + static constexpr const TSymbolUniqueId pt20D = TSymbolUniqueId(113); + static constexpr const TSymbolUniqueId abs_Int4 = TSymbolUniqueId(114); + static constexpr const TSymbolUniqueId pt30D = TSymbolUniqueId(115); + static constexpr const TSymbolUniqueId abs_Double1 = TSymbolUniqueId(116); + static constexpr const TSymbolUniqueId abs_Double2 = TSymbolUniqueId(117); + static constexpr const TSymbolUniqueId abs_Double3 = TSymbolUniqueId(118); + static constexpr const TSymbolUniqueId abs_Double4 = TSymbolUniqueId(119); + static constexpr const TSymbolUniqueId sign_Float1 = TSymbolUniqueId(120); + static constexpr const TSymbolUniqueId sign_Float2 = TSymbolUniqueId(121); + static constexpr const TSymbolUniqueId sign_Float3 = TSymbolUniqueId(122); + static constexpr const TSymbolUniqueId sign_Float4 = TSymbolUniqueId(123); + static constexpr const TSymbolUniqueId sign_Int1 = TSymbolUniqueId(124); + static constexpr const TSymbolUniqueId sign_Int2 = TSymbolUniqueId(125); + static constexpr const TSymbolUniqueId sign_Int3 = TSymbolUniqueId(126); + static constexpr const TSymbolUniqueId sign_Int4 = TSymbolUniqueId(127); + static constexpr const TSymbolUniqueId sign_Double1 = TSymbolUniqueId(128); + static constexpr const TSymbolUniqueId sign_Double2 = TSymbolUniqueId(129); + static constexpr const TSymbolUniqueId sign_Double3 = TSymbolUniqueId(130); + static constexpr const TSymbolUniqueId sign_Double4 = TSymbolUniqueId(131); + static constexpr const TSymbolUniqueId floor_Float1 = TSymbolUniqueId(132); + static constexpr const TSymbolUniqueId floor_Float2 = TSymbolUniqueId(133); + static constexpr const TSymbolUniqueId floor_Float3 = TSymbolUniqueId(134); + static constexpr const TSymbolUniqueId floor_Float4 = TSymbolUniqueId(135); + static constexpr const TSymbolUniqueId floor_Double1 = TSymbolUniqueId(136); + static constexpr const TSymbolUniqueId floor_Double2 = TSymbolUniqueId(137); + static constexpr const TSymbolUniqueId floor_Double3 = TSymbolUniqueId(138); + static constexpr const TSymbolUniqueId floor_Double4 = TSymbolUniqueId(139); + static constexpr const TSymbolUniqueId trunc_Float1 = TSymbolUniqueId(140); + static constexpr const TSymbolUniqueId trunc_Float2 = TSymbolUniqueId(141); + static constexpr const TSymbolUniqueId trunc_Float3 = TSymbolUniqueId(142); + static constexpr const TSymbolUniqueId trunc_Float4 = TSymbolUniqueId(143); + static constexpr const TSymbolUniqueId trunc_Double1 = TSymbolUniqueId(144); + static constexpr const TSymbolUniqueId trunc_Double2 = TSymbolUniqueId(145); + static constexpr const TSymbolUniqueId trunc_Double3 = TSymbolUniqueId(146); + static constexpr const TSymbolUniqueId trunc_Double4 = TSymbolUniqueId(147); + static constexpr const TSymbolUniqueId round_Float1 = TSymbolUniqueId(148); + static constexpr const TSymbolUniqueId round_Float2 = TSymbolUniqueId(149); + static constexpr const TSymbolUniqueId round_Float3 = TSymbolUniqueId(150); + static constexpr const TSymbolUniqueId round_Float4 = TSymbolUniqueId(151); + static constexpr const TSymbolUniqueId round_Double1 = TSymbolUniqueId(152); + static constexpr const TSymbolUniqueId round_Double2 = TSymbolUniqueId(153); + static constexpr const TSymbolUniqueId round_Double3 = TSymbolUniqueId(154); + static constexpr const TSymbolUniqueId round_Double4 = TSymbolUniqueId(155); + static constexpr const TSymbolUniqueId roundEven_Float1 = TSymbolUniqueId(156); + static constexpr const TSymbolUniqueId roundEven_Float2 = TSymbolUniqueId(157); + static constexpr const TSymbolUniqueId roundEven_Float3 = TSymbolUniqueId(158); + static constexpr const TSymbolUniqueId roundEven_Float4 = TSymbolUniqueId(159); + static constexpr const TSymbolUniqueId roundEven_Double1 = TSymbolUniqueId(160); + static constexpr const TSymbolUniqueId roundEven_Double2 = TSymbolUniqueId(161); + static constexpr const TSymbolUniqueId roundEven_Double3 = TSymbolUniqueId(162); + static constexpr const TSymbolUniqueId roundEven_Double4 = TSymbolUniqueId(163); + static constexpr const TSymbolUniqueId ceil_Float1 = TSymbolUniqueId(164); + static constexpr const TSymbolUniqueId ceil_Float2 = TSymbolUniqueId(165); + static constexpr const TSymbolUniqueId ceil_Float3 = TSymbolUniqueId(166); + static constexpr const TSymbolUniqueId ceil_Float4 = TSymbolUniqueId(167); + static constexpr const TSymbolUniqueId ceil_Double1 = TSymbolUniqueId(168); + static constexpr const TSymbolUniqueId ceil_Double2 = TSymbolUniqueId(169); + static constexpr const TSymbolUniqueId ceil_Double3 = TSymbolUniqueId(170); + static constexpr const TSymbolUniqueId ceil_Double4 = TSymbolUniqueId(171); + static constexpr const TSymbolUniqueId fract_Float1 = TSymbolUniqueId(172); + static constexpr const TSymbolUniqueId fract_Float2 = TSymbolUniqueId(173); + static constexpr const TSymbolUniqueId fract_Float3 = TSymbolUniqueId(174); + static constexpr const TSymbolUniqueId fract_Float4 = TSymbolUniqueId(175); + static constexpr const TSymbolUniqueId fract_Double1 = TSymbolUniqueId(176); + static constexpr const TSymbolUniqueId fract_Double2 = TSymbolUniqueId(177); + static constexpr const TSymbolUniqueId fract_Double3 = TSymbolUniqueId(178); + static constexpr const TSymbolUniqueId fract_Double4 = TSymbolUniqueId(179); + static constexpr const TSymbolUniqueId mod_Float1_Float1 = TSymbolUniqueId(180); + static constexpr const TSymbolUniqueId mod_Float2_Float1 = TSymbolUniqueId(181); + static constexpr const TSymbolUniqueId mod_Float3_Float1 = TSymbolUniqueId(182); + static constexpr const TSymbolUniqueId mod_Float4_Float1 = TSymbolUniqueId(183); + static constexpr const TSymbolUniqueId mod_Float2_Float2 = TSymbolUniqueId(184); + static constexpr const TSymbolUniqueId mod_Float3_Float3 = TSymbolUniqueId(185); + static constexpr const TSymbolUniqueId mod_Float4_Float4 = TSymbolUniqueId(186); + static constexpr const TSymbolUniqueId mod_Double1_Double1 = TSymbolUniqueId(187); + static constexpr const TSymbolUniqueId mod_Double2_Double1 = TSymbolUniqueId(188); + static constexpr const TSymbolUniqueId mod_Double3_Double1 = TSymbolUniqueId(189); + static constexpr const TSymbolUniqueId mod_Double4_Double1 = TSymbolUniqueId(190); + static constexpr const TSymbolUniqueId mod_Double2_Double2 = TSymbolUniqueId(191); + static constexpr const TSymbolUniqueId mod_Double3_Double3 = TSymbolUniqueId(192); + static constexpr const TSymbolUniqueId mod_Double4_Double4 = TSymbolUniqueId(193); + static constexpr const TSymbolUniqueId min_Float1_Float1 = TSymbolUniqueId(194); + static constexpr const TSymbolUniqueId min_Float2_Float1 = TSymbolUniqueId(195); + static constexpr const TSymbolUniqueId min_Float3_Float1 = TSymbolUniqueId(196); + static constexpr const TSymbolUniqueId min_Float4_Float1 = TSymbolUniqueId(197); + static constexpr const TSymbolUniqueId min_Float2_Float2 = TSymbolUniqueId(198); + static constexpr const TSymbolUniqueId min_Float3_Float3 = TSymbolUniqueId(199); + static constexpr const TSymbolUniqueId min_Float4_Float4 = TSymbolUniqueId(200); + static constexpr const TSymbolUniqueId min_Double1_Double1 = TSymbolUniqueId(201); + static constexpr const TSymbolUniqueId min_Double2_Double2 = TSymbolUniqueId(202); + static constexpr const TSymbolUniqueId min_Double3_Double3 = TSymbolUniqueId(203); + static constexpr const TSymbolUniqueId min_Double4_Double4 = TSymbolUniqueId(204); + static constexpr const TSymbolUniqueId min_Double2_Double1 = TSymbolUniqueId(205); + static constexpr const TSymbolUniqueId min_Double3_Double1 = TSymbolUniqueId(206); + static constexpr const TSymbolUniqueId min_Double4_Double1 = TSymbolUniqueId(207); + static constexpr const TSymbolUniqueId min_Int1_Int1 = TSymbolUniqueId(208); + static constexpr const TSymbolUniqueId min_Int2_Int2 = TSymbolUniqueId(209); + static constexpr const TSymbolUniqueId min_Int3_Int3 = TSymbolUniqueId(210); + static constexpr const TSymbolUniqueId min_Int4_Int4 = TSymbolUniqueId(211); + static constexpr const TSymbolUniqueId min_Int2_Int1 = TSymbolUniqueId(212); + static constexpr const TSymbolUniqueId min_Int3_Int1 = TSymbolUniqueId(213); + static constexpr const TSymbolUniqueId min_Int4_Int1 = TSymbolUniqueId(214); + static constexpr const TSymbolUniqueId min_UInt1_UInt1 = TSymbolUniqueId(215); + static constexpr const TSymbolUniqueId pt00E = TSymbolUniqueId(216); + static constexpr const TSymbolUniqueId min_UInt2_UInt2 = TSymbolUniqueId(217); + static constexpr const TSymbolUniqueId pt10E = TSymbolUniqueId(218); + static constexpr const TSymbolUniqueId min_UInt3_UInt3 = TSymbolUniqueId(219); + static constexpr const TSymbolUniqueId pt20E = TSymbolUniqueId(220); + static constexpr const TSymbolUniqueId min_UInt4_UInt4 = TSymbolUniqueId(221); + static constexpr const TSymbolUniqueId pt30E = TSymbolUniqueId(222); + static constexpr const TSymbolUniqueId min_UInt2_UInt1 = TSymbolUniqueId(223); + static constexpr const TSymbolUniqueId min_UInt3_UInt1 = TSymbolUniqueId(224); + static constexpr const TSymbolUniqueId min_UInt4_UInt1 = TSymbolUniqueId(225); + static constexpr const TSymbolUniqueId max_Float1_Float1 = TSymbolUniqueId(226); + static constexpr const TSymbolUniqueId max_Float2_Float1 = TSymbolUniqueId(227); + static constexpr const TSymbolUniqueId max_Float3_Float1 = TSymbolUniqueId(228); + static constexpr const TSymbolUniqueId max_Float4_Float1 = TSymbolUniqueId(229); + static constexpr const TSymbolUniqueId max_Float2_Float2 = TSymbolUniqueId(230); + static constexpr const TSymbolUniqueId max_Float3_Float3 = TSymbolUniqueId(231); + static constexpr const TSymbolUniqueId max_Float4_Float4 = TSymbolUniqueId(232); + static constexpr const TSymbolUniqueId max_Double1_Double1 = TSymbolUniqueId(233); + static constexpr const TSymbolUniqueId max_Double2_Double2 = TSymbolUniqueId(234); + static constexpr const TSymbolUniqueId max_Double3_Double3 = TSymbolUniqueId(235); + static constexpr const TSymbolUniqueId max_Double4_Double4 = TSymbolUniqueId(236); + static constexpr const TSymbolUniqueId max_Double2_Double1 = TSymbolUniqueId(237); + static constexpr const TSymbolUniqueId max_Double3_Double1 = TSymbolUniqueId(238); + static constexpr const TSymbolUniqueId max_Double4_Double1 = TSymbolUniqueId(239); + static constexpr const TSymbolUniqueId max_Int1_Int1 = TSymbolUniqueId(240); + static constexpr const TSymbolUniqueId max_Int2_Int2 = TSymbolUniqueId(241); + static constexpr const TSymbolUniqueId max_Int3_Int3 = TSymbolUniqueId(242); + static constexpr const TSymbolUniqueId max_Int4_Int4 = TSymbolUniqueId(243); + static constexpr const TSymbolUniqueId max_Int2_Int1 = TSymbolUniqueId(244); + static constexpr const TSymbolUniqueId max_Int3_Int1 = TSymbolUniqueId(245); + static constexpr const TSymbolUniqueId max_Int4_Int1 = TSymbolUniqueId(246); + static constexpr const TSymbolUniqueId max_UInt1_UInt1 = TSymbolUniqueId(247); + static constexpr const TSymbolUniqueId max_UInt2_UInt2 = TSymbolUniqueId(248); + static constexpr const TSymbolUniqueId max_UInt3_UInt3 = TSymbolUniqueId(249); + static constexpr const TSymbolUniqueId max_UInt4_UInt4 = TSymbolUniqueId(250); + static constexpr const TSymbolUniqueId max_UInt2_UInt1 = TSymbolUniqueId(251); + static constexpr const TSymbolUniqueId max_UInt3_UInt1 = TSymbolUniqueId(252); + static constexpr const TSymbolUniqueId max_UInt4_UInt1 = TSymbolUniqueId(253); + static constexpr const TSymbolUniqueId clamp_Float1_Float1_Float1 = TSymbolUniqueId(254); + static constexpr const TSymbolUniqueId clamp_Float2_Float1_Float1 = TSymbolUniqueId(255); + static constexpr const TSymbolUniqueId clamp_Float3_Float1_Float1 = TSymbolUniqueId(256); + static constexpr const TSymbolUniqueId clamp_Float4_Float1_Float1 = TSymbolUniqueId(257); + static constexpr const TSymbolUniqueId clamp_Float2_Float2_Float2 = TSymbolUniqueId(258); + static constexpr const TSymbolUniqueId clamp_Float3_Float3_Float3 = TSymbolUniqueId(259); + static constexpr const TSymbolUniqueId clamp_Float4_Float4_Float4 = TSymbolUniqueId(260); + static constexpr const TSymbolUniqueId clamp_Double1_Double1_Double1 = TSymbolUniqueId(261); + static constexpr const TSymbolUniqueId clamp_Double2_Double1_Double1 = TSymbolUniqueId(262); + static constexpr const TSymbolUniqueId clamp_Double3_Double1_Double1 = TSymbolUniqueId(263); + static constexpr const TSymbolUniqueId clamp_Double4_Double1_Double1 = TSymbolUniqueId(264); + static constexpr const TSymbolUniqueId clamp_Double2_Double2_Double2 = TSymbolUniqueId(265); + static constexpr const TSymbolUniqueId clamp_Double3_Double3_Double3 = TSymbolUniqueId(266); + static constexpr const TSymbolUniqueId clamp_Double4_Double4_Double4 = TSymbolUniqueId(267); + static constexpr const TSymbolUniqueId clamp_Int1_Int1_Int1 = TSymbolUniqueId(268); + static constexpr const TSymbolUniqueId clamp_Int2_Int1_Int1 = TSymbolUniqueId(269); + static constexpr const TSymbolUniqueId clamp_Int3_Int1_Int1 = TSymbolUniqueId(270); + static constexpr const TSymbolUniqueId clamp_Int4_Int1_Int1 = TSymbolUniqueId(271); + static constexpr const TSymbolUniqueId clamp_Int2_Int2_Int2 = TSymbolUniqueId(272); + static constexpr const TSymbolUniqueId clamp_Int3_Int3_Int3 = TSymbolUniqueId(273); + static constexpr const TSymbolUniqueId clamp_Int4_Int4_Int4 = TSymbolUniqueId(274); + static constexpr const TSymbolUniqueId clamp_UInt1_UInt1_UInt1 = TSymbolUniqueId(275); + static constexpr const TSymbolUniqueId clamp_UInt2_UInt1_UInt1 = TSymbolUniqueId(276); + static constexpr const TSymbolUniqueId clamp_UInt3_UInt1_UInt1 = TSymbolUniqueId(277); + static constexpr const TSymbolUniqueId clamp_UInt4_UInt1_UInt1 = TSymbolUniqueId(278); + static constexpr const TSymbolUniqueId clamp_UInt2_UInt2_UInt2 = TSymbolUniqueId(279); + static constexpr const TSymbolUniqueId clamp_UInt3_UInt3_UInt3 = TSymbolUniqueId(280); + static constexpr const TSymbolUniqueId clamp_UInt4_UInt4_UInt4 = TSymbolUniqueId(281); + static constexpr const TSymbolUniqueId mix_Float1_Float1_Float1 = TSymbolUniqueId(282); + static constexpr const TSymbolUniqueId mix_Float2_Float2_Float1 = TSymbolUniqueId(283); + static constexpr const TSymbolUniqueId mix_Float3_Float3_Float1 = TSymbolUniqueId(284); + static constexpr const TSymbolUniqueId mix_Float4_Float4_Float1 = TSymbolUniqueId(285); + static constexpr const TSymbolUniqueId mix_Float2_Float2_Float2 = TSymbolUniqueId(286); + static constexpr const TSymbolUniqueId mix_Float3_Float3_Float3 = TSymbolUniqueId(287); + static constexpr const TSymbolUniqueId mix_Float4_Float4_Float4 = TSymbolUniqueId(288); + static constexpr const TSymbolUniqueId mix_Double1_Double1_Double1 = TSymbolUniqueId(289); + static constexpr const TSymbolUniqueId mix_Double2_Double2_Double1 = TSymbolUniqueId(290); + static constexpr const TSymbolUniqueId mix_Double3_Double3_Double1 = TSymbolUniqueId(291); + static constexpr const TSymbolUniqueId mix_Double4_Double4_Double1 = TSymbolUniqueId(292); + static constexpr const TSymbolUniqueId mix_Double2_Double2_Double2 = TSymbolUniqueId(293); + static constexpr const TSymbolUniqueId mix_Double3_Double3_Double3 = TSymbolUniqueId(294); + static constexpr const TSymbolUniqueId mix_Double4_Double4_Double4 = TSymbolUniqueId(295); + static constexpr const TSymbolUniqueId mix_Float1_Float1_Bool1 = TSymbolUniqueId(296); + static constexpr const TSymbolUniqueId pt00F = TSymbolUniqueId(297); + static constexpr const TSymbolUniqueId mix_Float2_Float2_Bool2 = TSymbolUniqueId(298); + static constexpr const TSymbolUniqueId pt10F = TSymbolUniqueId(299); + static constexpr const TSymbolUniqueId mix_Float3_Float3_Bool3 = TSymbolUniqueId(300); + static constexpr const TSymbolUniqueId pt20F = TSymbolUniqueId(301); + static constexpr const TSymbolUniqueId mix_Float4_Float4_Bool4 = TSymbolUniqueId(302); + static constexpr const TSymbolUniqueId pt30F = TSymbolUniqueId(303); + static constexpr const TSymbolUniqueId mix_Double1_Double1_Bool1 = TSymbolUniqueId(304); + static constexpr const TSymbolUniqueId mix_Double2_Double2_Bool2 = TSymbolUniqueId(305); + static constexpr const TSymbolUniqueId mix_Double3_Double3_Bool3 = TSymbolUniqueId(306); + static constexpr const TSymbolUniqueId mix_Double4_Double4_Bool4 = TSymbolUniqueId(307); + static constexpr const TSymbolUniqueId mix_Int1_Int1_Bool1 = TSymbolUniqueId(308); + static constexpr const TSymbolUniqueId mix_Int2_Int2_Bool2 = TSymbolUniqueId(309); + static constexpr const TSymbolUniqueId mix_Int3_Int3_Bool3 = TSymbolUniqueId(310); + static constexpr const TSymbolUniqueId mix_Int4_Int4_Bool4 = TSymbolUniqueId(311); + static constexpr const TSymbolUniqueId mix_UInt1_UInt1_Bool1 = TSymbolUniqueId(312); + static constexpr const TSymbolUniqueId mix_UInt2_UInt2_Bool2 = TSymbolUniqueId(313); + static constexpr const TSymbolUniqueId mix_UInt3_UInt3_Bool3 = TSymbolUniqueId(314); + static constexpr const TSymbolUniqueId mix_UInt4_UInt4_Bool4 = TSymbolUniqueId(315); + static constexpr const TSymbolUniqueId mix_Bool1_Bool1_Bool1 = TSymbolUniqueId(316); + static constexpr const TSymbolUniqueId mix_Bool2_Bool2_Bool2 = TSymbolUniqueId(317); + static constexpr const TSymbolUniqueId mix_Bool3_Bool3_Bool3 = TSymbolUniqueId(318); + static constexpr const TSymbolUniqueId mix_Bool4_Bool4_Bool4 = TSymbolUniqueId(319); + static constexpr const TSymbolUniqueId step_Float1_Float1 = TSymbolUniqueId(320); + static constexpr const TSymbolUniqueId step_Float2_Float2 = TSymbolUniqueId(321); + static constexpr const TSymbolUniqueId step_Float3_Float3 = TSymbolUniqueId(322); + static constexpr const TSymbolUniqueId step_Float4_Float4 = TSymbolUniqueId(323); + static constexpr const TSymbolUniqueId step_Float1_Float2 = TSymbolUniqueId(324); + static constexpr const TSymbolUniqueId step_Float1_Float3 = TSymbolUniqueId(325); + static constexpr const TSymbolUniqueId step_Float1_Float4 = TSymbolUniqueId(326); + static constexpr const TSymbolUniqueId step_Double1_Double1 = TSymbolUniqueId(327); + static constexpr const TSymbolUniqueId step_Double2_Double2 = TSymbolUniqueId(328); + static constexpr const TSymbolUniqueId step_Double3_Double3 = TSymbolUniqueId(329); + static constexpr const TSymbolUniqueId step_Double4_Double4 = TSymbolUniqueId(330); + static constexpr const TSymbolUniqueId step_Double1_Double2 = TSymbolUniqueId(331); + static constexpr const TSymbolUniqueId step_Double1_Double3 = TSymbolUniqueId(332); + static constexpr const TSymbolUniqueId step_Double1_Double4 = TSymbolUniqueId(333); + static constexpr const TSymbolUniqueId smoothstep_Double1_Double1_Double1 = + TSymbolUniqueId(334); + static constexpr const TSymbolUniqueId smoothstep_Double2_Double2_Double2 = + TSymbolUniqueId(335); + static constexpr const TSymbolUniqueId smoothstep_Double3_Double3_Double3 = + TSymbolUniqueId(336); + static constexpr const TSymbolUniqueId smoothstep_Double4_Double4_Double4 = + TSymbolUniqueId(337); + static constexpr const TSymbolUniqueId smoothstep_Double1_Double1_Double2 = + TSymbolUniqueId(338); + static constexpr const TSymbolUniqueId smoothstep_Double1_Double1_Double3 = + TSymbolUniqueId(339); + static constexpr const TSymbolUniqueId smoothstep_Double1_Double1_Double4 = + TSymbolUniqueId(340); + static constexpr const TSymbolUniqueId smoothstep_Float1_Float1_Float1 = TSymbolUniqueId(341); + static constexpr const TSymbolUniqueId smoothstep_Float2_Float2_Float2 = TSymbolUniqueId(342); + static constexpr const TSymbolUniqueId smoothstep_Float3_Float3_Float3 = TSymbolUniqueId(343); + static constexpr const TSymbolUniqueId smoothstep_Float4_Float4_Float4 = TSymbolUniqueId(344); + static constexpr const TSymbolUniqueId smoothstep_Float1_Float1_Float2 = TSymbolUniqueId(345); + static constexpr const TSymbolUniqueId smoothstep_Float1_Float1_Float3 = TSymbolUniqueId(346); + static constexpr const TSymbolUniqueId smoothstep_Float1_Float1_Float4 = TSymbolUniqueId(347); + static constexpr const TSymbolUniqueId modf_Float1_Float1 = TSymbolUniqueId(348); + static constexpr const TSymbolUniqueId pt_o_00B = TSymbolUniqueId(349); + static constexpr const TSymbolUniqueId modf_Float2_Float2 = TSymbolUniqueId(350); + static constexpr const TSymbolUniqueId pt_o_10B = TSymbolUniqueId(351); + static constexpr const TSymbolUniqueId modf_Float3_Float3 = TSymbolUniqueId(352); + static constexpr const TSymbolUniqueId pt_o_20B = TSymbolUniqueId(353); + static constexpr const TSymbolUniqueId modf_Float4_Float4 = TSymbolUniqueId(354); + static constexpr const TSymbolUniqueId pt_o_30B = TSymbolUniqueId(355); + static constexpr const TSymbolUniqueId modf_Double1_Double1 = TSymbolUniqueId(356); + static constexpr const TSymbolUniqueId pt_o_00C = TSymbolUniqueId(357); + static constexpr const TSymbolUniqueId modf_Double2_Double2 = TSymbolUniqueId(358); + static constexpr const TSymbolUniqueId pt_o_10C = TSymbolUniqueId(359); + static constexpr const TSymbolUniqueId modf_Double3_Double3 = TSymbolUniqueId(360); + static constexpr const TSymbolUniqueId pt_o_20C = TSymbolUniqueId(361); + static constexpr const TSymbolUniqueId modf_Double4_Double4 = TSymbolUniqueId(362); + static constexpr const TSymbolUniqueId pt_o_30C = TSymbolUniqueId(363); + static constexpr const TSymbolUniqueId isnan_Float1 = TSymbolUniqueId(364); + static constexpr const TSymbolUniqueId isnan_Float2 = TSymbolUniqueId(365); + static constexpr const TSymbolUniqueId isnan_Float3 = TSymbolUniqueId(366); + static constexpr const TSymbolUniqueId isnan_Float4 = TSymbolUniqueId(367); + static constexpr const TSymbolUniqueId isnan_Double1 = TSymbolUniqueId(368); + static constexpr const TSymbolUniqueId isnan_Double2 = TSymbolUniqueId(369); + static constexpr const TSymbolUniqueId isnan_Double3 = TSymbolUniqueId(370); + static constexpr const TSymbolUniqueId isnan_Double4 = TSymbolUniqueId(371); + static constexpr const TSymbolUniqueId isinf_Float1 = TSymbolUniqueId(372); + static constexpr const TSymbolUniqueId isinf_Float2 = TSymbolUniqueId(373); + static constexpr const TSymbolUniqueId isinf_Float3 = TSymbolUniqueId(374); + static constexpr const TSymbolUniqueId isinf_Float4 = TSymbolUniqueId(375); + static constexpr const TSymbolUniqueId isinf_Double1 = TSymbolUniqueId(376); + static constexpr const TSymbolUniqueId isinf_Double2 = TSymbolUniqueId(377); + static constexpr const TSymbolUniqueId isinf_Double3 = TSymbolUniqueId(378); + static constexpr const TSymbolUniqueId isinf_Double4 = TSymbolUniqueId(379); + static constexpr const TSymbolUniqueId floatBitsToInt_Float1 = TSymbolUniqueId(380); + static constexpr const TSymbolUniqueId floatBitsToInt_Float2 = TSymbolUniqueId(381); + static constexpr const TSymbolUniqueId floatBitsToInt_Float3 = TSymbolUniqueId(382); + static constexpr const TSymbolUniqueId floatBitsToInt_Float4 = TSymbolUniqueId(383); + static constexpr const TSymbolUniqueId floatBitsToUint_Float1 = TSymbolUniqueId(384); + static constexpr const TSymbolUniqueId floatBitsToUint_Float2 = TSymbolUniqueId(385); + static constexpr const TSymbolUniqueId floatBitsToUint_Float3 = TSymbolUniqueId(386); + static constexpr const TSymbolUniqueId floatBitsToUint_Float4 = TSymbolUniqueId(387); + static constexpr const TSymbolUniqueId intBitsToFloat_Int1 = TSymbolUniqueId(388); + static constexpr const TSymbolUniqueId intBitsToFloat_Int2 = TSymbolUniqueId(389); + static constexpr const TSymbolUniqueId intBitsToFloat_Int3 = TSymbolUniqueId(390); + static constexpr const TSymbolUniqueId intBitsToFloat_Int4 = TSymbolUniqueId(391); + static constexpr const TSymbolUniqueId uintBitsToFloat_UInt1 = TSymbolUniqueId(392); + static constexpr const TSymbolUniqueId uintBitsToFloat_UInt2 = TSymbolUniqueId(393); + static constexpr const TSymbolUniqueId uintBitsToFloat_UInt3 = TSymbolUniqueId(394); + static constexpr const TSymbolUniqueId uintBitsToFloat_UInt4 = TSymbolUniqueId(395); + static constexpr const TSymbolUniqueId fma_Float1_Float1_Float1 = TSymbolUniqueId(396); + static constexpr const TSymbolUniqueId fma_Float2_Float2_Float2 = TSymbolUniqueId(397); + static constexpr const TSymbolUniqueId fma_Float3_Float3_Float3 = TSymbolUniqueId(398); + static constexpr const TSymbolUniqueId fma_Float4_Float4_Float4 = TSymbolUniqueId(399); + static constexpr const TSymbolUniqueId fmaExt_Float1_Float1_Float1 = TSymbolUniqueId(400); + static constexpr const TSymbolUniqueId fmaExt_Float2_Float2_Float2 = TSymbolUniqueId(401); + static constexpr const TSymbolUniqueId fmaExt_Float3_Float3_Float3 = TSymbolUniqueId(402); + static constexpr const TSymbolUniqueId fmaExt_Float4_Float4_Float4 = TSymbolUniqueId(403); + static constexpr const TSymbolUniqueId fma_Double1_Double1_Double1 = TSymbolUniqueId(404); + static constexpr const TSymbolUniqueId fma_Double2_Double2_Double2 = TSymbolUniqueId(405); + static constexpr const TSymbolUniqueId fma_Double3_Double3_Double3 = TSymbolUniqueId(406); + static constexpr const TSymbolUniqueId fma_Double4_Double4_Double4 = TSymbolUniqueId(407); + static constexpr const TSymbolUniqueId frexp_Float1_Int1 = TSymbolUniqueId(408); + static constexpr const TSymbolUniqueId pt_o_00D = TSymbolUniqueId(409); + static constexpr const TSymbolUniqueId frexp_Float2_Int2 = TSymbolUniqueId(410); + static constexpr const TSymbolUniqueId pt_o_10D = TSymbolUniqueId(411); + static constexpr const TSymbolUniqueId frexp_Float3_Int3 = TSymbolUniqueId(412); + static constexpr const TSymbolUniqueId pt_o_20D = TSymbolUniqueId(413); + static constexpr const TSymbolUniqueId frexp_Float4_Int4 = TSymbolUniqueId(414); + static constexpr const TSymbolUniqueId pt_o_30D = TSymbolUniqueId(415); + static constexpr const TSymbolUniqueId frexp_Double1_Int1 = TSymbolUniqueId(416); + static constexpr const TSymbolUniqueId frexp_Double2_Int2 = TSymbolUniqueId(417); + static constexpr const TSymbolUniqueId frexp_Double3_Int3 = TSymbolUniqueId(418); + static constexpr const TSymbolUniqueId frexp_Double4_Int4 = TSymbolUniqueId(419); + static constexpr const TSymbolUniqueId ldexp_Float1_Int1 = TSymbolUniqueId(420); + static constexpr const TSymbolUniqueId ldexp_Float2_Int2 = TSymbolUniqueId(421); + static constexpr const TSymbolUniqueId ldexp_Float3_Int3 = TSymbolUniqueId(422); + static constexpr const TSymbolUniqueId ldexp_Float4_Int4 = TSymbolUniqueId(423); + static constexpr const TSymbolUniqueId ldexp_Double1_Int1 = TSymbolUniqueId(424); + static constexpr const TSymbolUniqueId ldexp_Double2_Int2 = TSymbolUniqueId(425); + static constexpr const TSymbolUniqueId ldexp_Double3_Int3 = TSymbolUniqueId(426); + static constexpr const TSymbolUniqueId ldexp_Double4_Int4 = TSymbolUniqueId(427); + static constexpr const TSymbolUniqueId packSnorm2x16_Float2 = TSymbolUniqueId(428); + static constexpr const TSymbolUniqueId packHalf2x16_Float2 = TSymbolUniqueId(429); + static constexpr const TSymbolUniqueId unpackSnorm2x16_UInt1 = TSymbolUniqueId(430); + static constexpr const TSymbolUniqueId unpackHalf2x16_UInt1 = TSymbolUniqueId(431); + static constexpr const TSymbolUniqueId packUnorm2x16_Float2 = TSymbolUniqueId(432); + static constexpr const TSymbolUniqueId unpackUnorm2x16_UInt1 = TSymbolUniqueId(433); + static constexpr const TSymbolUniqueId packUnorm4x8_Float4 = TSymbolUniqueId(434); + static constexpr const TSymbolUniqueId packSnorm4x8_Float4 = TSymbolUniqueId(435); + static constexpr const TSymbolUniqueId unpackUnorm4x8_UInt1 = TSymbolUniqueId(436); + static constexpr const TSymbolUniqueId unpackSnorm4x8_UInt1 = TSymbolUniqueId(437); + static constexpr const TSymbolUniqueId packDouble2x32_UInt2 = TSymbolUniqueId(438); + static constexpr const TSymbolUniqueId unpackDouble2x32_Double1 = TSymbolUniqueId(439); + static constexpr const TSymbolUniqueId length_Float1 = TSymbolUniqueId(440); + static constexpr const TSymbolUniqueId length_Float2 = TSymbolUniqueId(441); + static constexpr const TSymbolUniqueId length_Float3 = TSymbolUniqueId(442); + static constexpr const TSymbolUniqueId length_Float4 = TSymbolUniqueId(443); + static constexpr const TSymbolUniqueId length_Double1 = TSymbolUniqueId(444); + static constexpr const TSymbolUniqueId length_Double2 = TSymbolUniqueId(445); + static constexpr const TSymbolUniqueId length_Double3 = TSymbolUniqueId(446); + static constexpr const TSymbolUniqueId length_Double4 = TSymbolUniqueId(447); + static constexpr const TSymbolUniqueId distance_Float1_Float1 = TSymbolUniqueId(448); + static constexpr const TSymbolUniqueId distance_Float2_Float2 = TSymbolUniqueId(449); + static constexpr const TSymbolUniqueId distance_Float3_Float3 = TSymbolUniqueId(450); + static constexpr const TSymbolUniqueId distance_Float4_Float4 = TSymbolUniqueId(451); + static constexpr const TSymbolUniqueId distance_Double1_Double1 = TSymbolUniqueId(452); + static constexpr const TSymbolUniqueId distance_Double2_Double2 = TSymbolUniqueId(453); + static constexpr const TSymbolUniqueId distance_Double3_Double3 = TSymbolUniqueId(454); + static constexpr const TSymbolUniqueId distance_Double4_Double4 = TSymbolUniqueId(455); + static constexpr const TSymbolUniqueId dot_Float1_Float1 = TSymbolUniqueId(456); + static constexpr const TSymbolUniqueId dot_Float2_Float2 = TSymbolUniqueId(457); + static constexpr const TSymbolUniqueId dot_Float3_Float3 = TSymbolUniqueId(458); + static constexpr const TSymbolUniqueId dot_Float4_Float4 = TSymbolUniqueId(459); + static constexpr const TSymbolUniqueId dot_Double1_Double1 = TSymbolUniqueId(460); + static constexpr const TSymbolUniqueId dot_Double2_Double2 = TSymbolUniqueId(461); + static constexpr const TSymbolUniqueId dot_Double3_Double3 = TSymbolUniqueId(462); + static constexpr const TSymbolUniqueId dot_Double4_Double4 = TSymbolUniqueId(463); + static constexpr const TSymbolUniqueId cross_Float3_Float3 = TSymbolUniqueId(464); + static constexpr const TSymbolUniqueId cross_Double3_Double3 = TSymbolUniqueId(465); + static constexpr const TSymbolUniqueId normalize_Float1 = TSymbolUniqueId(466); + static constexpr const TSymbolUniqueId normalize_Float2 = TSymbolUniqueId(467); + static constexpr const TSymbolUniqueId normalize_Float3 = TSymbolUniqueId(468); + static constexpr const TSymbolUniqueId normalize_Float4 = TSymbolUniqueId(469); + static constexpr const TSymbolUniqueId normalize_Double1 = TSymbolUniqueId(470); + static constexpr const TSymbolUniqueId normalize_Double2 = TSymbolUniqueId(471); + static constexpr const TSymbolUniqueId normalize_Double3 = TSymbolUniqueId(472); + static constexpr const TSymbolUniqueId normalize_Double4 = TSymbolUniqueId(473); + static constexpr const TSymbolUniqueId faceforward_Float1_Float1_Float1 = TSymbolUniqueId(474); + static constexpr const TSymbolUniqueId faceforward_Float2_Float2_Float2 = TSymbolUniqueId(475); + static constexpr const TSymbolUniqueId faceforward_Float3_Float3_Float3 = TSymbolUniqueId(476); + static constexpr const TSymbolUniqueId faceforward_Float4_Float4_Float4 = TSymbolUniqueId(477); + static constexpr const TSymbolUniqueId faceforward_Double1_Double1_Double1 = + TSymbolUniqueId(478); + static constexpr const TSymbolUniqueId faceforward_Double2_Double2_Double2 = + TSymbolUniqueId(479); + static constexpr const TSymbolUniqueId faceforward_Double3_Double3_Double3 = + TSymbolUniqueId(480); + static constexpr const TSymbolUniqueId faceforward_Double4_Double4_Double4 = + TSymbolUniqueId(481); + static constexpr const TSymbolUniqueId reflect_Float1_Float1 = TSymbolUniqueId(482); + static constexpr const TSymbolUniqueId reflect_Float2_Float2 = TSymbolUniqueId(483); + static constexpr const TSymbolUniqueId reflect_Float3_Float3 = TSymbolUniqueId(484); + static constexpr const TSymbolUniqueId reflect_Float4_Float4 = TSymbolUniqueId(485); + static constexpr const TSymbolUniqueId reflect_Double1_Double1 = TSymbolUniqueId(486); + static constexpr const TSymbolUniqueId reflect_Double2_Double2 = TSymbolUniqueId(487); + static constexpr const TSymbolUniqueId reflect_Double3_Double3 = TSymbolUniqueId(488); + static constexpr const TSymbolUniqueId reflect_Double4_Double4 = TSymbolUniqueId(489); + static constexpr const TSymbolUniqueId refract_Float1_Float1_Float1 = TSymbolUniqueId(490); + static constexpr const TSymbolUniqueId refract_Float2_Float2_Float1 = TSymbolUniqueId(491); + static constexpr const TSymbolUniqueId refract_Float3_Float3_Float1 = TSymbolUniqueId(492); + static constexpr const TSymbolUniqueId refract_Float4_Float4_Float1 = TSymbolUniqueId(493); + static constexpr const TSymbolUniqueId refract_Double1_Double1_Float1 = TSymbolUniqueId(494); + static constexpr const TSymbolUniqueId refract_Double2_Double2_Float1 = TSymbolUniqueId(495); + static constexpr const TSymbolUniqueId refract_Double3_Double3_Float1 = TSymbolUniqueId(496); + static constexpr const TSymbolUniqueId refract_Double4_Double4_Float1 = TSymbolUniqueId(497); + static constexpr const TSymbolUniqueId ftransform = TSymbolUniqueId(498); + static constexpr const TSymbolUniqueId matrixCompMult_Float2x2_Float2x2 = TSymbolUniqueId(499); + static constexpr const TSymbolUniqueId pt50B = TSymbolUniqueId(500); + static constexpr const TSymbolUniqueId matrixCompMult_Float3x3_Float3x3 = TSymbolUniqueId(501); + static constexpr const TSymbolUniqueId ptA0B = TSymbolUniqueId(502); + static constexpr const TSymbolUniqueId matrixCompMult_Float4x4_Float4x4 = TSymbolUniqueId(503); + static constexpr const TSymbolUniqueId ptF0B = TSymbolUniqueId(504); + static constexpr const TSymbolUniqueId matrixCompMult_Float2x3_Float2x3 = TSymbolUniqueId(505); + static constexpr const TSymbolUniqueId pt90B = TSymbolUniqueId(506); + static constexpr const TSymbolUniqueId matrixCompMult_Float3x2_Float3x2 = TSymbolUniqueId(507); + static constexpr const TSymbolUniqueId pt60B = TSymbolUniqueId(508); + static constexpr const TSymbolUniqueId matrixCompMult_Float2x4_Float2x4 = TSymbolUniqueId(509); + static constexpr const TSymbolUniqueId ptD0B = TSymbolUniqueId(510); + static constexpr const TSymbolUniqueId matrixCompMult_Float4x2_Float4x2 = TSymbolUniqueId(511); + static constexpr const TSymbolUniqueId pt70B = TSymbolUniqueId(512); + static constexpr const TSymbolUniqueId matrixCompMult_Float3x4_Float3x4 = TSymbolUniqueId(513); + static constexpr const TSymbolUniqueId ptE0B = TSymbolUniqueId(514); + static constexpr const TSymbolUniqueId matrixCompMult_Float4x3_Float4x3 = TSymbolUniqueId(515); + static constexpr const TSymbolUniqueId ptB0B = TSymbolUniqueId(516); + static constexpr const TSymbolUniqueId outerProduct_Float2_Float2 = TSymbolUniqueId(517); + static constexpr const TSymbolUniqueId outerProduct_Float3_Float3 = TSymbolUniqueId(518); + static constexpr const TSymbolUniqueId outerProduct_Float4_Float4 = TSymbolUniqueId(519); + static constexpr const TSymbolUniqueId outerProduct_Float3_Float2 = TSymbolUniqueId(520); + static constexpr const TSymbolUniqueId outerProduct_Float2_Float3 = TSymbolUniqueId(521); + static constexpr const TSymbolUniqueId outerProduct_Float4_Float2 = TSymbolUniqueId(522); + static constexpr const TSymbolUniqueId outerProduct_Float2_Float4 = TSymbolUniqueId(523); + static constexpr const TSymbolUniqueId outerProduct_Float4_Float3 = TSymbolUniqueId(524); + static constexpr const TSymbolUniqueId outerProduct_Float3_Float4 = TSymbolUniqueId(525); + static constexpr const TSymbolUniqueId transpose_Float2x2 = TSymbolUniqueId(526); + static constexpr const TSymbolUniqueId transpose_Float3x3 = TSymbolUniqueId(527); + static constexpr const TSymbolUniqueId transpose_Float4x4 = TSymbolUniqueId(528); + static constexpr const TSymbolUniqueId transpose_Float3x2 = TSymbolUniqueId(529); + static constexpr const TSymbolUniqueId transpose_Float2x3 = TSymbolUniqueId(530); + static constexpr const TSymbolUniqueId transpose_Float4x2 = TSymbolUniqueId(531); + static constexpr const TSymbolUniqueId transpose_Float2x4 = TSymbolUniqueId(532); + static constexpr const TSymbolUniqueId transpose_Float4x3 = TSymbolUniqueId(533); + static constexpr const TSymbolUniqueId transpose_Float3x4 = TSymbolUniqueId(534); + static constexpr const TSymbolUniqueId determinant_Float2x2 = TSymbolUniqueId(535); + static constexpr const TSymbolUniqueId determinant_Float3x3 = TSymbolUniqueId(536); + static constexpr const TSymbolUniqueId determinant_Float4x4 = TSymbolUniqueId(537); + static constexpr const TSymbolUniqueId inverse_Float2x2 = TSymbolUniqueId(538); + static constexpr const TSymbolUniqueId inverse_Float3x3 = TSymbolUniqueId(539); + static constexpr const TSymbolUniqueId inverse_Float4x4 = TSymbolUniqueId(540); + static constexpr const TSymbolUniqueId lessThan_Float2_Float2 = TSymbolUniqueId(541); + static constexpr const TSymbolUniqueId lessThan_Float3_Float3 = TSymbolUniqueId(542); + static constexpr const TSymbolUniqueId lessThan_Float4_Float4 = TSymbolUniqueId(543); + static constexpr const TSymbolUniqueId lessThan_Int2_Int2 = TSymbolUniqueId(544); + static constexpr const TSymbolUniqueId lessThan_Int3_Int3 = TSymbolUniqueId(545); + static constexpr const TSymbolUniqueId lessThan_Int4_Int4 = TSymbolUniqueId(546); + static constexpr const TSymbolUniqueId lessThan_UInt2_UInt2 = TSymbolUniqueId(547); + static constexpr const TSymbolUniqueId lessThan_UInt3_UInt3 = TSymbolUniqueId(548); + static constexpr const TSymbolUniqueId lessThan_UInt4_UInt4 = TSymbolUniqueId(549); + static constexpr const TSymbolUniqueId lessThanEqual_Float2_Float2 = TSymbolUniqueId(550); + static constexpr const TSymbolUniqueId lessThanEqual_Float3_Float3 = TSymbolUniqueId(551); + static constexpr const TSymbolUniqueId lessThanEqual_Float4_Float4 = TSymbolUniqueId(552); + static constexpr const TSymbolUniqueId lessThanEqual_Int2_Int2 = TSymbolUniqueId(553); + static constexpr const TSymbolUniqueId lessThanEqual_Int3_Int3 = TSymbolUniqueId(554); + static constexpr const TSymbolUniqueId lessThanEqual_Int4_Int4 = TSymbolUniqueId(555); + static constexpr const TSymbolUniqueId lessThanEqual_UInt2_UInt2 = TSymbolUniqueId(556); + static constexpr const TSymbolUniqueId lessThanEqual_UInt3_UInt3 = TSymbolUniqueId(557); + static constexpr const TSymbolUniqueId lessThanEqual_UInt4_UInt4 = TSymbolUniqueId(558); + static constexpr const TSymbolUniqueId greaterThan_Float2_Float2 = TSymbolUniqueId(559); + static constexpr const TSymbolUniqueId greaterThan_Float3_Float3 = TSymbolUniqueId(560); + static constexpr const TSymbolUniqueId greaterThan_Float4_Float4 = TSymbolUniqueId(561); + static constexpr const TSymbolUniqueId greaterThan_Int2_Int2 = TSymbolUniqueId(562); + static constexpr const TSymbolUniqueId greaterThan_Int3_Int3 = TSymbolUniqueId(563); + static constexpr const TSymbolUniqueId greaterThan_Int4_Int4 = TSymbolUniqueId(564); + static constexpr const TSymbolUniqueId greaterThan_UInt2_UInt2 = TSymbolUniqueId(565); + static constexpr const TSymbolUniqueId greaterThan_UInt3_UInt3 = TSymbolUniqueId(566); + static constexpr const TSymbolUniqueId greaterThan_UInt4_UInt4 = TSymbolUniqueId(567); + static constexpr const TSymbolUniqueId greaterThanEqual_Float2_Float2 = TSymbolUniqueId(568); + static constexpr const TSymbolUniqueId greaterThanEqual_Float3_Float3 = TSymbolUniqueId(569); + static constexpr const TSymbolUniqueId greaterThanEqual_Float4_Float4 = TSymbolUniqueId(570); + static constexpr const TSymbolUniqueId greaterThanEqual_Int2_Int2 = TSymbolUniqueId(571); + static constexpr const TSymbolUniqueId greaterThanEqual_Int3_Int3 = TSymbolUniqueId(572); + static constexpr const TSymbolUniqueId greaterThanEqual_Int4_Int4 = TSymbolUniqueId(573); + static constexpr const TSymbolUniqueId greaterThanEqual_UInt2_UInt2 = TSymbolUniqueId(574); + static constexpr const TSymbolUniqueId greaterThanEqual_UInt3_UInt3 = TSymbolUniqueId(575); + static constexpr const TSymbolUniqueId greaterThanEqual_UInt4_UInt4 = TSymbolUniqueId(576); + static constexpr const TSymbolUniqueId equal_Float2_Float2 = TSymbolUniqueId(577); + static constexpr const TSymbolUniqueId equal_Float3_Float3 = TSymbolUniqueId(578); + static constexpr const TSymbolUniqueId equal_Float4_Float4 = TSymbolUniqueId(579); + static constexpr const TSymbolUniqueId equal_Int2_Int2 = TSymbolUniqueId(580); + static constexpr const TSymbolUniqueId equal_Int3_Int3 = TSymbolUniqueId(581); + static constexpr const TSymbolUniqueId equal_Int4_Int4 = TSymbolUniqueId(582); + static constexpr const TSymbolUniqueId equal_UInt2_UInt2 = TSymbolUniqueId(583); + static constexpr const TSymbolUniqueId equal_UInt3_UInt3 = TSymbolUniqueId(584); + static constexpr const TSymbolUniqueId equal_UInt4_UInt4 = TSymbolUniqueId(585); + static constexpr const TSymbolUniqueId equal_Bool2_Bool2 = TSymbolUniqueId(586); + static constexpr const TSymbolUniqueId equal_Bool3_Bool3 = TSymbolUniqueId(587); + static constexpr const TSymbolUniqueId equal_Bool4_Bool4 = TSymbolUniqueId(588); + static constexpr const TSymbolUniqueId notEqual_Float2_Float2 = TSymbolUniqueId(589); + static constexpr const TSymbolUniqueId notEqual_Float3_Float3 = TSymbolUniqueId(590); + static constexpr const TSymbolUniqueId notEqual_Float4_Float4 = TSymbolUniqueId(591); + static constexpr const TSymbolUniqueId notEqual_Int2_Int2 = TSymbolUniqueId(592); + static constexpr const TSymbolUniqueId notEqual_Int3_Int3 = TSymbolUniqueId(593); + static constexpr const TSymbolUniqueId notEqual_Int4_Int4 = TSymbolUniqueId(594); + static constexpr const TSymbolUniqueId notEqual_UInt2_UInt2 = TSymbolUniqueId(595); + static constexpr const TSymbolUniqueId notEqual_UInt3_UInt3 = TSymbolUniqueId(596); + static constexpr const TSymbolUniqueId notEqual_UInt4_UInt4 = TSymbolUniqueId(597); + static constexpr const TSymbolUniqueId notEqual_Bool2_Bool2 = TSymbolUniqueId(598); + static constexpr const TSymbolUniqueId notEqual_Bool3_Bool3 = TSymbolUniqueId(599); + static constexpr const TSymbolUniqueId notEqual_Bool4_Bool4 = TSymbolUniqueId(600); + static constexpr const TSymbolUniqueId any_Bool2 = TSymbolUniqueId(601); + static constexpr const TSymbolUniqueId any_Bool3 = TSymbolUniqueId(602); + static constexpr const TSymbolUniqueId any_Bool4 = TSymbolUniqueId(603); + static constexpr const TSymbolUniqueId all_Bool2 = TSymbolUniqueId(604); + static constexpr const TSymbolUniqueId all_Bool3 = TSymbolUniqueId(605); + static constexpr const TSymbolUniqueId all_Bool4 = TSymbolUniqueId(606); + static constexpr const TSymbolUniqueId notFunc_Bool2 = TSymbolUniqueId(607); + static constexpr const TSymbolUniqueId notFunc_Bool3 = TSymbolUniqueId(608); + static constexpr const TSymbolUniqueId notFunc_Bool4 = TSymbolUniqueId(609); + static constexpr const TSymbolUniqueId bitfieldExtract_Int1_Int1_Int1 = TSymbolUniqueId(610); + static constexpr const TSymbolUniqueId bitfieldExtract_Int2_Int1_Int1 = TSymbolUniqueId(611); + static constexpr const TSymbolUniqueId bitfieldExtract_Int3_Int1_Int1 = TSymbolUniqueId(612); + static constexpr const TSymbolUniqueId bitfieldExtract_Int4_Int1_Int1 = TSymbolUniqueId(613); + static constexpr const TSymbolUniqueId bitfieldExtract_UInt1_Int1_Int1 = TSymbolUniqueId(614); + static constexpr const TSymbolUniqueId bitfieldExtract_UInt2_Int1_Int1 = TSymbolUniqueId(615); + static constexpr const TSymbolUniqueId bitfieldExtract_UInt3_Int1_Int1 = TSymbolUniqueId(616); + static constexpr const TSymbolUniqueId bitfieldExtract_UInt4_Int1_Int1 = TSymbolUniqueId(617); + static constexpr const TSymbolUniqueId bitfieldInsert_Int1_Int1_Int1_Int1 = + TSymbolUniqueId(618); + static constexpr const TSymbolUniqueId bitfieldInsert_Int2_Int2_Int1_Int1 = + TSymbolUniqueId(619); + static constexpr const TSymbolUniqueId bitfieldInsert_Int3_Int3_Int1_Int1 = + TSymbolUniqueId(620); + static constexpr const TSymbolUniqueId bitfieldInsert_Int4_Int4_Int1_Int1 = + TSymbolUniqueId(621); + static constexpr const TSymbolUniqueId bitfieldInsert_UInt1_UInt1_Int1_Int1 = + TSymbolUniqueId(622); + static constexpr const TSymbolUniqueId bitfieldInsert_UInt2_UInt2_Int1_Int1 = + TSymbolUniqueId(623); + static constexpr const TSymbolUniqueId bitfieldInsert_UInt3_UInt3_Int1_Int1 = + TSymbolUniqueId(624); + static constexpr const TSymbolUniqueId bitfieldInsert_UInt4_UInt4_Int1_Int1 = + TSymbolUniqueId(625); + static constexpr const TSymbolUniqueId bitfieldReverse_Int1 = TSymbolUniqueId(626); + static constexpr const TSymbolUniqueId bitfieldReverse_Int2 = TSymbolUniqueId(627); + static constexpr const TSymbolUniqueId bitfieldReverse_Int3 = TSymbolUniqueId(628); + static constexpr const TSymbolUniqueId bitfieldReverse_Int4 = TSymbolUniqueId(629); + static constexpr const TSymbolUniqueId bitfieldReverse_UInt1 = TSymbolUniqueId(630); + static constexpr const TSymbolUniqueId bitfieldReverse_UInt2 = TSymbolUniqueId(631); + static constexpr const TSymbolUniqueId bitfieldReverse_UInt3 = TSymbolUniqueId(632); + static constexpr const TSymbolUniqueId bitfieldReverse_UInt4 = TSymbolUniqueId(633); + static constexpr const TSymbolUniqueId bitCount_Int1 = TSymbolUniqueId(634); + static constexpr const TSymbolUniqueId bitCount_Int2 = TSymbolUniqueId(635); + static constexpr const TSymbolUniqueId bitCount_Int3 = TSymbolUniqueId(636); + static constexpr const TSymbolUniqueId bitCount_Int4 = TSymbolUniqueId(637); + static constexpr const TSymbolUniqueId bitCount_UInt1 = TSymbolUniqueId(638); + static constexpr const TSymbolUniqueId bitCount_UInt2 = TSymbolUniqueId(639); + static constexpr const TSymbolUniqueId bitCount_UInt3 = TSymbolUniqueId(640); + static constexpr const TSymbolUniqueId bitCount_UInt4 = TSymbolUniqueId(641); + static constexpr const TSymbolUniqueId findLSB_Int1 = TSymbolUniqueId(642); + static constexpr const TSymbolUniqueId findLSB_Int2 = TSymbolUniqueId(643); + static constexpr const TSymbolUniqueId findLSB_Int3 = TSymbolUniqueId(644); + static constexpr const TSymbolUniqueId findLSB_Int4 = TSymbolUniqueId(645); + static constexpr const TSymbolUniqueId findLSB_UInt1 = TSymbolUniqueId(646); + static constexpr const TSymbolUniqueId findLSB_UInt2 = TSymbolUniqueId(647); + static constexpr const TSymbolUniqueId findLSB_UInt3 = TSymbolUniqueId(648); + static constexpr const TSymbolUniqueId findLSB_UInt4 = TSymbolUniqueId(649); + static constexpr const TSymbolUniqueId findMSB_Int1 = TSymbolUniqueId(650); + static constexpr const TSymbolUniqueId findMSB_Int2 = TSymbolUniqueId(651); + static constexpr const TSymbolUniqueId findMSB_Int3 = TSymbolUniqueId(652); + static constexpr const TSymbolUniqueId findMSB_Int4 = TSymbolUniqueId(653); + static constexpr const TSymbolUniqueId findMSB_UInt1 = TSymbolUniqueId(654); + static constexpr const TSymbolUniqueId findMSB_UInt2 = TSymbolUniqueId(655); + static constexpr const TSymbolUniqueId findMSB_UInt3 = TSymbolUniqueId(656); + static constexpr const TSymbolUniqueId findMSB_UInt4 = TSymbolUniqueId(657); + static constexpr const TSymbolUniqueId uaddCarry_UInt1_UInt1_UInt1 = TSymbolUniqueId(658); + static constexpr const TSymbolUniqueId pt_o_00E = TSymbolUniqueId(659); + static constexpr const TSymbolUniqueId uaddCarry_UInt2_UInt2_UInt2 = TSymbolUniqueId(660); + static constexpr const TSymbolUniqueId pt_o_10E = TSymbolUniqueId(661); + static constexpr const TSymbolUniqueId uaddCarry_UInt3_UInt3_UInt3 = TSymbolUniqueId(662); + static constexpr const TSymbolUniqueId pt_o_20E = TSymbolUniqueId(663); + static constexpr const TSymbolUniqueId uaddCarry_UInt4_UInt4_UInt4 = TSymbolUniqueId(664); + static constexpr const TSymbolUniqueId pt_o_30E = TSymbolUniqueId(665); + static constexpr const TSymbolUniqueId usubBorrow_UInt1_UInt1_UInt1 = TSymbolUniqueId(666); + static constexpr const TSymbolUniqueId usubBorrow_UInt2_UInt2_UInt2 = TSymbolUniqueId(667); + static constexpr const TSymbolUniqueId usubBorrow_UInt3_UInt3_UInt3 = TSymbolUniqueId(668); + static constexpr const TSymbolUniqueId usubBorrow_UInt4_UInt4_UInt4 = TSymbolUniqueId(669); + static constexpr const TSymbolUniqueId umulExtended_UInt1_UInt1_UInt1_UInt1 = + TSymbolUniqueId(670); + static constexpr const TSymbolUniqueId umulExtended_UInt2_UInt2_UInt2_UInt2 = + TSymbolUniqueId(671); + static constexpr const TSymbolUniqueId umulExtended_UInt3_UInt3_UInt3_UInt3 = + TSymbolUniqueId(672); + static constexpr const TSymbolUniqueId umulExtended_UInt4_UInt4_UInt4_UInt4 = + TSymbolUniqueId(673); + static constexpr const TSymbolUniqueId imulExtended_Int1_Int1_Int1_Int1 = TSymbolUniqueId(674); + static constexpr const TSymbolUniqueId imulExtended_Int2_Int2_Int2_Int2 = TSymbolUniqueId(675); + static constexpr const TSymbolUniqueId imulExtended_Int3_Int3_Int3_Int3 = TSymbolUniqueId(676); + static constexpr const TSymbolUniqueId imulExtended_Int4_Int4_Int4_Int4 = TSymbolUniqueId(677); + static constexpr const TSymbolUniqueId texture2D_Sampler2D1_Float2 = TSymbolUniqueId(678); + static constexpr const TSymbolUniqueId pt00I = TSymbolUniqueId(679); + static constexpr const TSymbolUniqueId texture2DProj_Sampler2D1_Float3 = TSymbolUniqueId(680); + static constexpr const TSymbolUniqueId texture2DProj_Sampler2D1_Float4 = TSymbolUniqueId(681); + static constexpr const TSymbolUniqueId textureCube_SamplerCube1_Float3 = TSymbolUniqueId(682); + static constexpr const TSymbolUniqueId pt00K = TSymbolUniqueId(683); + static constexpr const TSymbolUniqueId texture1D_Sampler1D1_Float1 = TSymbolUniqueId(684); + static constexpr const TSymbolUniqueId pt00g = TSymbolUniqueId(685); + static constexpr const TSymbolUniqueId texture1DProj_Sampler1D1_Float2 = TSymbolUniqueId(686); + static constexpr const TSymbolUniqueId texture1DProj_Sampler1D1_Float4 = TSymbolUniqueId(687); + static constexpr const TSymbolUniqueId texture3D_Sampler3D1_Float3 = TSymbolUniqueId(688); + static constexpr const TSymbolUniqueId pt00J = TSymbolUniqueId(689); + static constexpr const TSymbolUniqueId texture3DProj_Sampler3D1_Float4 = TSymbolUniqueId(690); + static constexpr const TSymbolUniqueId shadow1D_Sampler1DShadow1_Float3 = TSymbolUniqueId(691); + static constexpr const TSymbolUniqueId pt00m = TSymbolUniqueId(692); + static constexpr const TSymbolUniqueId shadow1DProj_Sampler1DShadow1_Float4 = + TSymbolUniqueId(693); + static constexpr const TSymbolUniqueId shadow2D_Sampler2DShadow1_Float3 = TSymbolUniqueId(694); + static constexpr const TSymbolUniqueId pt00d = TSymbolUniqueId(695); + static constexpr const TSymbolUniqueId shadow2DProj_Sampler2DShadow1_Float4 = + TSymbolUniqueId(696); + static constexpr const TSymbolUniqueId shadow2DEXT_Sampler2DShadow1_Float3 = + TSymbolUniqueId(697); + static constexpr const TSymbolUniqueId shadow2DProjEXT_Sampler2DShadow1_Float4 = + TSymbolUniqueId(698); + static constexpr const TSymbolUniqueId texture2D_SamplerExternalOES1_Float2 = + TSymbolUniqueId(699); + static constexpr const TSymbolUniqueId pt00M = TSymbolUniqueId(700); + static constexpr const TSymbolUniqueId texture2DProj_SamplerExternalOES1_Float3 = + TSymbolUniqueId(701); + static constexpr const TSymbolUniqueId texture2DProj_SamplerExternalOES1_Float4 = + TSymbolUniqueId(702); + static constexpr const TSymbolUniqueId texture2DRect_Sampler2DRect1_Float2 = + TSymbolUniqueId(703); + static constexpr const TSymbolUniqueId pt00O = TSymbolUniqueId(704); + static constexpr const TSymbolUniqueId texture2DRectProj_Sampler2DRect1_Float3 = + TSymbolUniqueId(705); + static constexpr const TSymbolUniqueId texture2DRectProj_Sampler2DRect1_Float4 = + TSymbolUniqueId(706); + static constexpr const TSymbolUniqueId texture2DGradEXT_Sampler2D1_Float2_Float2_Float2 = + TSymbolUniqueId(707); + static constexpr const TSymbolUniqueId texture2DProjGradEXT_Sampler2D1_Float3_Float2_Float2 = + TSymbolUniqueId(708); + static constexpr const TSymbolUniqueId texture2DProjGradEXT_Sampler2D1_Float4_Float2_Float2 = + TSymbolUniqueId(709); + static constexpr const TSymbolUniqueId textureCubeGradEXT_SamplerCube1_Float3_Float3_Float3 = + TSymbolUniqueId(710); + static constexpr const TSymbolUniqueId textureVideoWEBGL_SamplerVideoWEBGL1_Float2 = + TSymbolUniqueId(711); + static constexpr const TSymbolUniqueId pt00y = TSymbolUniqueId(712); + static constexpr const TSymbolUniqueId texture2D_Sampler2D1_Float2_Float1 = + TSymbolUniqueId(713); + static constexpr const TSymbolUniqueId texture2DProj_Sampler2D1_Float3_Float1 = + TSymbolUniqueId(714); + static constexpr const TSymbolUniqueId texture2DProj_Sampler2D1_Float4_Float1 = + TSymbolUniqueId(715); + static constexpr const TSymbolUniqueId textureCube_SamplerCube1_Float3_Float1 = + TSymbolUniqueId(716); + static constexpr const TSymbolUniqueId texture3D_Sampler3D1_Float3_Float1 = + TSymbolUniqueId(717); + static constexpr const TSymbolUniqueId texture3DProj_Sampler3D1_Float4_Float1 = + TSymbolUniqueId(718); + static constexpr const TSymbolUniqueId texture1D_Sampler1D1_Float1_Float1 = + TSymbolUniqueId(719); + static constexpr const TSymbolUniqueId texture1DProj_Sampler1D1_Float2_Float1 = + TSymbolUniqueId(720); + static constexpr const TSymbolUniqueId texture1DProj_Sampler1D1_Float4_Float1 = + TSymbolUniqueId(721); + static constexpr const TSymbolUniqueId shadow1D_Sampler1DShadow1_Float3_Float1 = + TSymbolUniqueId(722); + static constexpr const TSymbolUniqueId shadow1DProj_Sampler1DShadow1_Float4_Float1 = + TSymbolUniqueId(723); + static constexpr const TSymbolUniqueId shadow2D_Sampler2DShadow1_Float3_Float1 = + TSymbolUniqueId(724); + static constexpr const TSymbolUniqueId shadow2DProj_Sampler2DShadow1_Float4_Float1 = + TSymbolUniqueId(725); + static constexpr const TSymbolUniqueId texture2DLod_Sampler2D1_Float2_Float1 = + TSymbolUniqueId(726); + static constexpr const TSymbolUniqueId texture2DProjLod_Sampler2D1_Float3_Float1 = + TSymbolUniqueId(727); + static constexpr const TSymbolUniqueId texture2DProjLod_Sampler2D1_Float4_Float1 = + TSymbolUniqueId(728); + static constexpr const TSymbolUniqueId textureCubeLod_SamplerCube1_Float3_Float1 = + TSymbolUniqueId(729); + static constexpr const TSymbolUniqueId texture1DLod_Sampler1D1_Float1_Float1 = + TSymbolUniqueId(730); + static constexpr const TSymbolUniqueId texture1DProjLod_Sampler1D1_Float2_Float1 = + TSymbolUniqueId(731); + static constexpr const TSymbolUniqueId texture1DProjLod_Sampler1D1_Float4_Float1 = + TSymbolUniqueId(732); + static constexpr const TSymbolUniqueId shadow1DLod_Sampler1DShadow1_Float3_Float1 = + TSymbolUniqueId(733); + static constexpr const TSymbolUniqueId shadow1DProjLod_Sampler1DShadow1_Float4_Float1 = + TSymbolUniqueId(734); + static constexpr const TSymbolUniqueId shadow2DLod_Sampler2DShadow1_Float3_Float1 = + TSymbolUniqueId(735); + static constexpr const TSymbolUniqueId shadow2DProjLod_Sampler2DShadow1_Float4_Float1 = + TSymbolUniqueId(736); + static constexpr const TSymbolUniqueId texture3DLod_Sampler3D1_Float3_Float1 = + TSymbolUniqueId(737); + static constexpr const TSymbolUniqueId texture3DProjLod_Sampler3D1_Float4_Float1 = + TSymbolUniqueId(738); + static constexpr const TSymbolUniqueId texture2DLodEXT_Sampler2D1_Float2_Float1 = + TSymbolUniqueId(739); + static constexpr const TSymbolUniqueId texture2DProjLodEXT_Sampler2D1_Float3_Float1 = + TSymbolUniqueId(740); + static constexpr const TSymbolUniqueId texture2DProjLodEXT_Sampler2D1_Float4_Float1 = + TSymbolUniqueId(741); + static constexpr const TSymbolUniqueId textureCubeLodEXT_SamplerCube1_Float3_Float1 = + TSymbolUniqueId(742); + static constexpr const TSymbolUniqueId texture_Sampler2D1_Float2 = TSymbolUniqueId(743); + static constexpr const TSymbolUniqueId texture_ISampler2D1_Float2 = TSymbolUniqueId(744); + static constexpr const TSymbolUniqueId pt00R = TSymbolUniqueId(745); + static constexpr const TSymbolUniqueId texture_USampler2D1_Float2 = TSymbolUniqueId(746); + static constexpr const TSymbolUniqueId pt00X = TSymbolUniqueId(747); + static constexpr const TSymbolUniqueId texture_Sampler3D1_Float3 = TSymbolUniqueId(748); + static constexpr const TSymbolUniqueId texture_ISampler3D1_Float3 = TSymbolUniqueId(749); + static constexpr const TSymbolUniqueId pt00S = TSymbolUniqueId(750); + static constexpr const TSymbolUniqueId texture_USampler3D1_Float3 = TSymbolUniqueId(751); + static constexpr const TSymbolUniqueId pt00Y = TSymbolUniqueId(752); + static constexpr const TSymbolUniqueId texture_SamplerCube1_Float3 = TSymbolUniqueId(753); + static constexpr const TSymbolUniqueId texture_ISamplerCube1_Float3 = TSymbolUniqueId(754); + static constexpr const TSymbolUniqueId pt00T = TSymbolUniqueId(755); + static constexpr const TSymbolUniqueId texture_USamplerCube1_Float3 = TSymbolUniqueId(756); + static constexpr const TSymbolUniqueId pt00Z = TSymbolUniqueId(757); + static constexpr const TSymbolUniqueId texture_Sampler2DArray1_Float3 = TSymbolUniqueId(758); + static constexpr const TSymbolUniqueId pt00L = TSymbolUniqueId(759); + static constexpr const TSymbolUniqueId texture_ISampler2DArray1_Float3 = TSymbolUniqueId(760); + static constexpr const TSymbolUniqueId pt00U = TSymbolUniqueId(761); + static constexpr const TSymbolUniqueId texture_USampler2DArray1_Float3 = TSymbolUniqueId(762); + static constexpr const TSymbolUniqueId pt00a = TSymbolUniqueId(763); + static constexpr const TSymbolUniqueId texture_Sampler2DShadow1_Float3 = TSymbolUniqueId(764); + static constexpr const TSymbolUniqueId texture_SamplerCubeShadow1_Float4 = TSymbolUniqueId(765); + static constexpr const TSymbolUniqueId pt00e = TSymbolUniqueId(766); + static constexpr const TSymbolUniqueId texture_Sampler2DArrayShadow1_Float4 = + TSymbolUniqueId(767); + static constexpr const TSymbolUniqueId pt00f = TSymbolUniqueId(768); + static constexpr const TSymbolUniqueId texture_Sampler1D1_Float1 = TSymbolUniqueId(769); + static constexpr const TSymbolUniqueId texture_ISampler1D1_Float1 = TSymbolUniqueId(770); + static constexpr const TSymbolUniqueId pt00o = TSymbolUniqueId(771); + static constexpr const TSymbolUniqueId texture_USampler1D1_Float1 = TSymbolUniqueId(772); + static constexpr const TSymbolUniqueId pt00t = TSymbolUniqueId(773); + static constexpr const TSymbolUniqueId texture_Sampler1DShadow1_Float3 = TSymbolUniqueId(774); + static constexpr const TSymbolUniqueId texture_Sampler1DArray1_Float3 = TSymbolUniqueId(775); + static constexpr const TSymbolUniqueId pt00h = TSymbolUniqueId(776); + static constexpr const TSymbolUniqueId texture_ISampler1DArray1_Float3 = TSymbolUniqueId(777); + static constexpr const TSymbolUniqueId pt00p = TSymbolUniqueId(778); + static constexpr const TSymbolUniqueId texture_USampler1DArray1_Float3 = TSymbolUniqueId(779); + static constexpr const TSymbolUniqueId pt00u = TSymbolUniqueId(780); + static constexpr const TSymbolUniqueId texture_Sampler1DArrayShadow1_Float3 = + TSymbolUniqueId(781); + static constexpr const TSymbolUniqueId pt00i = TSymbolUniqueId(782); + static constexpr const TSymbolUniqueId texture_Sampler2DRect1_Float2 = TSymbolUniqueId(783); + static constexpr const TSymbolUniqueId texture_ISampler2DRect1_Float2 = TSymbolUniqueId(784); + static constexpr const TSymbolUniqueId pt00q = TSymbolUniqueId(785); + static constexpr const TSymbolUniqueId texture_USampler2DRect1_Float2 = TSymbolUniqueId(786); + static constexpr const TSymbolUniqueId pt00v = TSymbolUniqueId(787); + static constexpr const TSymbolUniqueId texture_Sampler2DRectShadow1_Float3 = + TSymbolUniqueId(788); + static constexpr const TSymbolUniqueId pt00n = TSymbolUniqueId(789); + static constexpr const TSymbolUniqueId texture_SamplerCubeArray1_Float4 = TSymbolUniqueId(790); + static constexpr const TSymbolUniqueId pt00k = TSymbolUniqueId(791); + static constexpr const TSymbolUniqueId texture_ISamplerCubeArray1_Float4 = TSymbolUniqueId(792); + static constexpr const TSymbolUniqueId pt00s = TSymbolUniqueId(793); + static constexpr const TSymbolUniqueId texture_USamplerCubeArray1_Float4 = TSymbolUniqueId(794); + static constexpr const TSymbolUniqueId pt00x = TSymbolUniqueId(795); + static constexpr const TSymbolUniqueId texture_SamplerCubeArrayShadow1_Float4_Float1 = + TSymbolUniqueId(796); + static constexpr const TSymbolUniqueId pt00l = TSymbolUniqueId(797); + static constexpr const TSymbolUniqueId textureExt_SamplerCubeArray1_Float4 = + TSymbolUniqueId(798); + static constexpr const TSymbolUniqueId textureExt_ISamplerCubeArray1_Float4 = + TSymbolUniqueId(799); + static constexpr const TSymbolUniqueId textureExt_USamplerCubeArray1_Float4 = + TSymbolUniqueId(800); + static constexpr const TSymbolUniqueId textureExt_SamplerCubeArrayShadow1_Float4_Float1 = + TSymbolUniqueId(801); + static constexpr const TSymbolUniqueId texture_SamplerExternalOES1_Float2 = + TSymbolUniqueId(802); + static constexpr const TSymbolUniqueId texture_SamplerExternal2DY2YEXT1_Float2 = + TSymbolUniqueId(803); + static constexpr const TSymbolUniqueId pt00N = TSymbolUniqueId(804); + static constexpr const TSymbolUniqueId texture_SamplerVideoWEBGL1_Float2 = TSymbolUniqueId(805); + static constexpr const TSymbolUniqueId textureProj_Sampler2D1_Float3 = TSymbolUniqueId(806); + static constexpr const TSymbolUniqueId textureProj_ISampler2D1_Float3 = TSymbolUniqueId(807); + static constexpr const TSymbolUniqueId textureProj_USampler2D1_Float3 = TSymbolUniqueId(808); + static constexpr const TSymbolUniqueId textureProj_Sampler2D1_Float4 = TSymbolUniqueId(809); + static constexpr const TSymbolUniqueId textureProj_ISampler2D1_Float4 = TSymbolUniqueId(810); + static constexpr const TSymbolUniqueId textureProj_USampler2D1_Float4 = TSymbolUniqueId(811); + static constexpr const TSymbolUniqueId textureProj_Sampler3D1_Float4 = TSymbolUniqueId(812); + static constexpr const TSymbolUniqueId textureProj_ISampler3D1_Float4 = TSymbolUniqueId(813); + static constexpr const TSymbolUniqueId textureProj_USampler3D1_Float4 = TSymbolUniqueId(814); + static constexpr const TSymbolUniqueId textureProj_Sampler2DShadow1_Float4 = + TSymbolUniqueId(815); + static constexpr const TSymbolUniqueId textureProj_Sampler1D1_Float2 = TSymbolUniqueId(816); + static constexpr const TSymbolUniqueId textureProj_ISampler1D1_Float2 = TSymbolUniqueId(817); + static constexpr const TSymbolUniqueId textureProj_USampler1D1_Float2 = TSymbolUniqueId(818); + static constexpr const TSymbolUniqueId textureProj_Sampler1D1_Float4 = TSymbolUniqueId(819); + static constexpr const TSymbolUniqueId textureProj_ISampler1D1_Float4 = TSymbolUniqueId(820); + static constexpr const TSymbolUniqueId textureProj_USampler1D1_Float4 = TSymbolUniqueId(821); + static constexpr const TSymbolUniqueId textureProj_Sampler1DShadow1_Float4 = + TSymbolUniqueId(822); + static constexpr const TSymbolUniqueId textureProj_Sampler2DRect1_Float3 = TSymbolUniqueId(823); + static constexpr const TSymbolUniqueId textureProj_ISampler2DRect1_Float3 = + TSymbolUniqueId(824); + static constexpr const TSymbolUniqueId textureProj_USampler2DRect1_Float3 = + TSymbolUniqueId(825); + static constexpr const TSymbolUniqueId textureProj_Sampler2DRect1_Float4 = TSymbolUniqueId(826); + static constexpr const TSymbolUniqueId textureProj_ISampler2DRect1_Float4 = + TSymbolUniqueId(827); + static constexpr const TSymbolUniqueId textureProj_USampler2DRect1_Float4 = + TSymbolUniqueId(828); + static constexpr const TSymbolUniqueId textureProj_Sampler2DRectShadow1_Float4 = + TSymbolUniqueId(829); + static constexpr const TSymbolUniqueId textureProj_SamplerExternalOES1_Float3 = + TSymbolUniqueId(830); + static constexpr const TSymbolUniqueId textureProj_SamplerExternalOES1_Float4 = + TSymbolUniqueId(831); + static constexpr const TSymbolUniqueId textureProj_SamplerExternal2DY2YEXT1_Float3 = + TSymbolUniqueId(832); + static constexpr const TSymbolUniqueId textureProj_SamplerExternal2DY2YEXT1_Float4 = + TSymbolUniqueId(833); + static constexpr const TSymbolUniqueId textureLod_Sampler2D1_Float2_Float1 = + TSymbolUniqueId(834); + static constexpr const TSymbolUniqueId textureLod_ISampler2D1_Float2_Float1 = + TSymbolUniqueId(835); + static constexpr const TSymbolUniqueId textureLod_USampler2D1_Float2_Float1 = + TSymbolUniqueId(836); + static constexpr const TSymbolUniqueId textureLod_Sampler3D1_Float3_Float1 = + TSymbolUniqueId(837); + static constexpr const TSymbolUniqueId textureLod_ISampler3D1_Float3_Float1 = + TSymbolUniqueId(838); + static constexpr const TSymbolUniqueId textureLod_USampler3D1_Float3_Float1 = + TSymbolUniqueId(839); + static constexpr const TSymbolUniqueId textureLod_SamplerCube1_Float3_Float1 = + TSymbolUniqueId(840); + static constexpr const TSymbolUniqueId textureLod_ISamplerCube1_Float3_Float1 = + TSymbolUniqueId(841); + static constexpr const TSymbolUniqueId textureLod_USamplerCube1_Float3_Float1 = + TSymbolUniqueId(842); + static constexpr const TSymbolUniqueId textureLod_Sampler2DArray1_Float3_Float1 = + TSymbolUniqueId(843); + static constexpr const TSymbolUniqueId textureLod_ISampler2DArray1_Float3_Float1 = + TSymbolUniqueId(844); + static constexpr const TSymbolUniqueId textureLod_USampler2DArray1_Float3_Float1 = + TSymbolUniqueId(845); + static constexpr const TSymbolUniqueId textureLod_Sampler2DShadow1_Float3_Float1 = + TSymbolUniqueId(846); + static constexpr const TSymbolUniqueId textureLod_Sampler1D1_Float1_Float1 = + TSymbolUniqueId(847); + static constexpr const TSymbolUniqueId textureLod_ISampler1D1_Float1_Float1 = + TSymbolUniqueId(848); + static constexpr const TSymbolUniqueId textureLod_USampler1D1_Float1_Float1 = + TSymbolUniqueId(849); + static constexpr const TSymbolUniqueId textureLod_Sampler1DShadow1_Float3_Float1 = + TSymbolUniqueId(850); + static constexpr const TSymbolUniqueId textureLod_Sampler1DArray1_Float2_Float1 = + TSymbolUniqueId(851); + static constexpr const TSymbolUniqueId textureLod_ISampler1DArray1_Float2_Float1 = + TSymbolUniqueId(852); + static constexpr const TSymbolUniqueId textureLod_USampler1DArray1_Float2_Float1 = + TSymbolUniqueId(853); + static constexpr const TSymbolUniqueId textureLod_Sampler1DArrayShadow1_Float3_Float1 = + TSymbolUniqueId(854); + static constexpr const TSymbolUniqueId textureLod_SamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(855); + static constexpr const TSymbolUniqueId textureLod_ISamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(856); + static constexpr const TSymbolUniqueId textureLod_USamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(857); + static constexpr const TSymbolUniqueId textureLodExt_SamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(858); + static constexpr const TSymbolUniqueId textureLodExt_ISamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(859); + static constexpr const TSymbolUniqueId textureLodExt_USamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(860); + static constexpr const TSymbolUniqueId textureSize_Sampler2D1_Int1 = TSymbolUniqueId(861); + static constexpr const TSymbolUniqueId textureSize_ISampler2D1_Int1 = TSymbolUniqueId(862); + static constexpr const TSymbolUniqueId textureSize_USampler2D1_Int1 = TSymbolUniqueId(863); + static constexpr const TSymbolUniqueId textureSize_Sampler3D1_Int1 = TSymbolUniqueId(864); + static constexpr const TSymbolUniqueId textureSize_ISampler3D1_Int1 = TSymbolUniqueId(865); + static constexpr const TSymbolUniqueId textureSize_USampler3D1_Int1 = TSymbolUniqueId(866); + static constexpr const TSymbolUniqueId textureSize_SamplerCube1_Int1 = TSymbolUniqueId(867); + static constexpr const TSymbolUniqueId textureSize_ISamplerCube1_Int1 = TSymbolUniqueId(868); + static constexpr const TSymbolUniqueId textureSize_USamplerCube1_Int1 = TSymbolUniqueId(869); + static constexpr const TSymbolUniqueId textureSize_Sampler2DArray1_Int1 = TSymbolUniqueId(870); + static constexpr const TSymbolUniqueId textureSize_ISampler2DArray1_Int1 = TSymbolUniqueId(871); + static constexpr const TSymbolUniqueId textureSize_USampler2DArray1_Int1 = TSymbolUniqueId(872); + static constexpr const TSymbolUniqueId textureSize_Sampler2DShadow1_Int1 = TSymbolUniqueId(873); + static constexpr const TSymbolUniqueId textureSize_SamplerCubeShadow1_Int1 = + TSymbolUniqueId(874); + static constexpr const TSymbolUniqueId textureSize_Sampler2DArrayShadow1_Int1 = + TSymbolUniqueId(875); + static constexpr const TSymbolUniqueId textureSize_Sampler1D1_Int1 = TSymbolUniqueId(876); + static constexpr const TSymbolUniqueId textureSize_ISampler1D1_Int1 = TSymbolUniqueId(877); + static constexpr const TSymbolUniqueId textureSize_USampler1D1_Int1 = TSymbolUniqueId(878); + static constexpr const TSymbolUniqueId textureSize_Sampler1DShadow1_Int1 = TSymbolUniqueId(879); + static constexpr const TSymbolUniqueId textureSize_SamplerCubeArray1_Int1 = + TSymbolUniqueId(880); + static constexpr const TSymbolUniqueId textureSize_ISamplerCubeArray1_Int1 = + TSymbolUniqueId(881); + static constexpr const TSymbolUniqueId textureSize_USamplerCubeArray1_Int1 = + TSymbolUniqueId(882); + static constexpr const TSymbolUniqueId textureSize_SamplerCubeArrayShadow1_Int1 = + TSymbolUniqueId(883); + static constexpr const TSymbolUniqueId textureSizeExt_SamplerCubeArray1_Int1 = + TSymbolUniqueId(884); + static constexpr const TSymbolUniqueId textureSizeExt_ISamplerCubeArray1_Int1 = + TSymbolUniqueId(885); + static constexpr const TSymbolUniqueId textureSizeExt_USamplerCubeArray1_Int1 = + TSymbolUniqueId(886); + static constexpr const TSymbolUniqueId textureSizeExt_SamplerCubeArrayShadow1_Int1 = + TSymbolUniqueId(887); + static constexpr const TSymbolUniqueId textureSize_Sampler2DRect1 = TSymbolUniqueId(888); + static constexpr const TSymbolUniqueId textureSize_ISampler2DRect1 = TSymbolUniqueId(889); + static constexpr const TSymbolUniqueId textureSize_USampler2DRect1 = TSymbolUniqueId(890); + static constexpr const TSymbolUniqueId textureSize_Sampler2DRectShadow1 = TSymbolUniqueId(891); + static constexpr const TSymbolUniqueId textureSize_Sampler1DArray1_Int1 = TSymbolUniqueId(892); + static constexpr const TSymbolUniqueId textureSize_ISampler1DArray1_Int1 = TSymbolUniqueId(893); + static constexpr const TSymbolUniqueId textureSize_USampler1DArray1_Int1 = TSymbolUniqueId(894); + static constexpr const TSymbolUniqueId textureSize_Sampler1DArrayShadow1_Int1 = + TSymbolUniqueId(895); + static constexpr const TSymbolUniqueId textureSize_SamplerBuffer1 = TSymbolUniqueId(896); + static constexpr const TSymbolUniqueId pt00j = TSymbolUniqueId(897); + static constexpr const TSymbolUniqueId textureSize_ISamplerBuffer1 = TSymbolUniqueId(898); + static constexpr const TSymbolUniqueId pt00r = TSymbolUniqueId(899); + static constexpr const TSymbolUniqueId textureSize_USamplerBuffer1 = TSymbolUniqueId(900); + static constexpr const TSymbolUniqueId pt00w = TSymbolUniqueId(901); + static constexpr const TSymbolUniqueId textureSizeExt_SamplerBuffer1 = TSymbolUniqueId(902); + static constexpr const TSymbolUniqueId textureSizeExt_ISamplerBuffer1 = TSymbolUniqueId(903); + static constexpr const TSymbolUniqueId textureSizeExt_USamplerBuffer1 = TSymbolUniqueId(904); + static constexpr const TSymbolUniqueId textureSize_Sampler2DMS1 = TSymbolUniqueId(905); + static constexpr const TSymbolUniqueId pt00P = TSymbolUniqueId(906); + static constexpr const TSymbolUniqueId textureSize_ISampler2DMS1 = TSymbolUniqueId(907); + static constexpr const TSymbolUniqueId pt00V = TSymbolUniqueId(908); + static constexpr const TSymbolUniqueId textureSize_USampler2DMS1 = TSymbolUniqueId(909); + static constexpr const TSymbolUniqueId pt00b = TSymbolUniqueId(910); + static constexpr const TSymbolUniqueId textureSizeExt_Sampler2DMS1 = TSymbolUniqueId(911); + static constexpr const TSymbolUniqueId textureSizeExt_ISampler2DMS1 = TSymbolUniqueId(912); + static constexpr const TSymbolUniqueId textureSizeExt_USampler2DMS1 = TSymbolUniqueId(913); + static constexpr const TSymbolUniqueId textureSize_Sampler2DMSArray1 = TSymbolUniqueId(914); + static constexpr const TSymbolUniqueId pt00Q = TSymbolUniqueId(915); + static constexpr const TSymbolUniqueId textureSize_ISampler2DMSArray1 = TSymbolUniqueId(916); + static constexpr const TSymbolUniqueId pt00W = TSymbolUniqueId(917); + static constexpr const TSymbolUniqueId textureSize_USampler2DMSArray1 = TSymbolUniqueId(918); + static constexpr const TSymbolUniqueId pt00c = TSymbolUniqueId(919); + static constexpr const TSymbolUniqueId textureSizeExt_Sampler2DMSArray1 = TSymbolUniqueId(920); + static constexpr const TSymbolUniqueId textureSizeExt_ISampler2DMSArray1 = TSymbolUniqueId(921); + static constexpr const TSymbolUniqueId textureSizeExt_USampler2DMSArray1 = TSymbolUniqueId(922); + static constexpr const TSymbolUniqueId textureSize_SamplerExternalOES1_Int1 = + TSymbolUniqueId(923); + static constexpr const TSymbolUniqueId textureSize_SamplerExternal2DY2YEXT1_Int1 = + TSymbolUniqueId(924); + static constexpr const TSymbolUniqueId textureProjLod_Sampler2D1_Float3_Float1 = + TSymbolUniqueId(925); + static constexpr const TSymbolUniqueId textureProjLod_ISampler2D1_Float3_Float1 = + TSymbolUniqueId(926); + static constexpr const TSymbolUniqueId textureProjLod_USampler2D1_Float3_Float1 = + TSymbolUniqueId(927); + static constexpr const TSymbolUniqueId textureProjLod_Sampler2D1_Float4_Float1 = + TSymbolUniqueId(928); + static constexpr const TSymbolUniqueId textureProjLod_ISampler2D1_Float4_Float1 = + TSymbolUniqueId(929); + static constexpr const TSymbolUniqueId textureProjLod_USampler2D1_Float4_Float1 = + TSymbolUniqueId(930); + static constexpr const TSymbolUniqueId textureProjLod_Sampler3D1_Float4_Float1 = + TSymbolUniqueId(931); + static constexpr const TSymbolUniqueId textureProjLod_ISampler3D1_Float4_Float1 = + TSymbolUniqueId(932); + static constexpr const TSymbolUniqueId textureProjLod_USampler3D1_Float4_Float1 = + TSymbolUniqueId(933); + static constexpr const TSymbolUniqueId textureProjLod_Sampler2DShadow1_Float4_Float1 = + TSymbolUniqueId(934); + static constexpr const TSymbolUniqueId textureProjLod_Sampler1D1_Float2_Float1 = + TSymbolUniqueId(935); + static constexpr const TSymbolUniqueId textureProjLod_ISampler1D1_Float2_Float1 = + TSymbolUniqueId(936); + static constexpr const TSymbolUniqueId textureProjLod_USampler1D1_Float2_Float1 = + TSymbolUniqueId(937); + static constexpr const TSymbolUniqueId textureProjLod_Sampler1D1_Float4_Float1 = + TSymbolUniqueId(938); + static constexpr const TSymbolUniqueId textureProjLod_ISampler1D1_Float4_Float1 = + TSymbolUniqueId(939); + static constexpr const TSymbolUniqueId textureProjLod_USampler1D1_Float4_Float1 = + TSymbolUniqueId(940); + static constexpr const TSymbolUniqueId textureProjLod_Sampler1DShadow1_Float4_Float1 = + TSymbolUniqueId(941); + static constexpr const TSymbolUniqueId texelFetch_Sampler2D1_Int2_Int1 = TSymbolUniqueId(942); + static constexpr const TSymbolUniqueId texelFetch_ISampler2D1_Int2_Int1 = TSymbolUniqueId(943); + static constexpr const TSymbolUniqueId texelFetch_USampler2D1_Int2_Int1 = TSymbolUniqueId(944); + static constexpr const TSymbolUniqueId texelFetch_Sampler3D1_Int3_Int1 = TSymbolUniqueId(945); + static constexpr const TSymbolUniqueId texelFetch_ISampler3D1_Int3_Int1 = TSymbolUniqueId(946); + static constexpr const TSymbolUniqueId texelFetch_USampler3D1_Int3_Int1 = TSymbolUniqueId(947); + static constexpr const TSymbolUniqueId texelFetch_Sampler2DArray1_Int3_Int1 = + TSymbolUniqueId(948); + static constexpr const TSymbolUniqueId texelFetch_ISampler2DArray1_Int3_Int1 = + TSymbolUniqueId(949); + static constexpr const TSymbolUniqueId texelFetch_USampler2DArray1_Int3_Int1 = + TSymbolUniqueId(950); + static constexpr const TSymbolUniqueId texelFetch_Sampler1D1_Int1_Int1 = TSymbolUniqueId(951); + static constexpr const TSymbolUniqueId texelFetch_ISampler1D1_Int1_Int1 = TSymbolUniqueId(952); + static constexpr const TSymbolUniqueId texelFetch_USampler1D1_Int1_Int1 = TSymbolUniqueId(953); + static constexpr const TSymbolUniqueId texelFetch_Sampler2DRect1_Int2 = TSymbolUniqueId(954); + static constexpr const TSymbolUniqueId texelFetch_ISampler2DRect1_Int2 = TSymbolUniqueId(955); + static constexpr const TSymbolUniqueId texelFetch_USampler2DRect1_Int2 = TSymbolUniqueId(956); + static constexpr const TSymbolUniqueId texelFetch_Sampler1DArray1_Int2_Int1 = + TSymbolUniqueId(957); + static constexpr const TSymbolUniqueId texelFetch_ISampler1DArray1_Int2_Int1 = + TSymbolUniqueId(958); + static constexpr const TSymbolUniqueId texelFetch_USampler1DArray1_Int2_Int1 = + TSymbolUniqueId(959); + static constexpr const TSymbolUniqueId texelFetch_SamplerBuffer1_Int1 = TSymbolUniqueId(960); + static constexpr const TSymbolUniqueId texelFetch_ISamplerBuffer1_Int1 = TSymbolUniqueId(961); + static constexpr const TSymbolUniqueId texelFetch_USamplerBuffer1_Int1 = TSymbolUniqueId(962); + static constexpr const TSymbolUniqueId texelFetchExt_SamplerBuffer1_Int1 = TSymbolUniqueId(963); + static constexpr const TSymbolUniqueId texelFetchExt_ISamplerBuffer1_Int1 = + TSymbolUniqueId(964); + static constexpr const TSymbolUniqueId texelFetchExt_USamplerBuffer1_Int1 = + TSymbolUniqueId(965); + static constexpr const TSymbolUniqueId texelFetch_Sampler2DMS1_Int2_Int1 = TSymbolUniqueId(966); + static constexpr const TSymbolUniqueId texelFetch_ISampler2DMS1_Int2_Int1 = + TSymbolUniqueId(967); + static constexpr const TSymbolUniqueId texelFetch_USampler2DMS1_Int2_Int1 = + TSymbolUniqueId(968); + static constexpr const TSymbolUniqueId texelFetchExt_Sampler2DMS1_Int2_Int1 = + TSymbolUniqueId(969); + static constexpr const TSymbolUniqueId texelFetchExt_ISampler2DMS1_Int2_Int1 = + TSymbolUniqueId(970); + static constexpr const TSymbolUniqueId texelFetchExt_USampler2DMS1_Int2_Int1 = + TSymbolUniqueId(971); + static constexpr const TSymbolUniqueId texelFetch_Sampler2DMSArray1_Int3_Int1 = + TSymbolUniqueId(972); + static constexpr const TSymbolUniqueId texelFetch_ISampler2DMSArray1_Int3_Int1 = + TSymbolUniqueId(973); + static constexpr const TSymbolUniqueId texelFetch_USampler2DMSArray1_Int3_Int1 = + TSymbolUniqueId(974); + static constexpr const TSymbolUniqueId texelFetchExt_Sampler2DMSArray1_Int3_Int1 = + TSymbolUniqueId(975); + static constexpr const TSymbolUniqueId texelFetchExt_ISampler2DMSArray1_Int3_Int1 = + TSymbolUniqueId(976); + static constexpr const TSymbolUniqueId texelFetchExt_USampler2DMSArray1_Int3_Int1 = + TSymbolUniqueId(977); + static constexpr const TSymbolUniqueId texelFetch_SamplerExternalOES1_Int2_Int1 = + TSymbolUniqueId(978); + static constexpr const TSymbolUniqueId texelFetch_SamplerExternal2DY2YEXT1_Int2_Int1 = + TSymbolUniqueId(979); + static constexpr const TSymbolUniqueId textureGrad_Sampler2D1_Float2_Float2_Float2 = + TSymbolUniqueId(980); + static constexpr const TSymbolUniqueId textureGrad_ISampler2D1_Float2_Float2_Float2 = + TSymbolUniqueId(981); + static constexpr const TSymbolUniqueId textureGrad_USampler2D1_Float2_Float2_Float2 = + TSymbolUniqueId(982); + static constexpr const TSymbolUniqueId textureGrad_Sampler3D1_Float3_Float3_Float3 = + TSymbolUniqueId(983); + static constexpr const TSymbolUniqueId textureGrad_ISampler3D1_Float3_Float3_Float3 = + TSymbolUniqueId(984); + static constexpr const TSymbolUniqueId textureGrad_USampler3D1_Float3_Float3_Float3 = + TSymbolUniqueId(985); + static constexpr const TSymbolUniqueId textureGrad_SamplerCube1_Float3_Float3_Float3 = + TSymbolUniqueId(986); + static constexpr const TSymbolUniqueId textureGrad_ISamplerCube1_Float3_Float3_Float3 = + TSymbolUniqueId(987); + static constexpr const TSymbolUniqueId textureGrad_USamplerCube1_Float3_Float3_Float3 = + TSymbolUniqueId(988); + static constexpr const TSymbolUniqueId textureGrad_Sampler2D1_Float1_Float1_Float1 = + TSymbolUniqueId(989); + static constexpr const TSymbolUniqueId textureGrad_ISampler2D1_Float1_Float1_Float1 = + TSymbolUniqueId(990); + static constexpr const TSymbolUniqueId textureGrad_USampler2D1_Float1_Float1_Float1 = + TSymbolUniqueId(991); + static constexpr const TSymbolUniqueId textureGrad_Sampler2DRect1_Float2_Float2_Float2 = + TSymbolUniqueId(992); + static constexpr const TSymbolUniqueId textureGrad_ISampler2DRect1_Float2_Float2_Float2 = + TSymbolUniqueId(993); + static constexpr const TSymbolUniqueId textureGrad_USampler2DRect1_Float2_Float2_Float2 = + TSymbolUniqueId(994); + static constexpr const TSymbolUniqueId textureGrad_Sampler2DRectShadow1_Float3_Float2_Float2 = + TSymbolUniqueId(995); + static constexpr const TSymbolUniqueId textureGrad_Sampler2DShadow1_Float3_Float2_Float2 = + TSymbolUniqueId(996); + static constexpr const TSymbolUniqueId textureGrad_SamplerCubeShadow1_Float4_Float3_Float3 = + TSymbolUniqueId(997); + static constexpr const TSymbolUniqueId textureGrad_Sampler2DArray1_Float3_Float2_Float2 = + TSymbolUniqueId(998); + static constexpr const TSymbolUniqueId textureGrad_ISampler2DArray1_Float3_Float2_Float2 = + TSymbolUniqueId(999); + static constexpr const TSymbolUniqueId textureGrad_USampler2DArray1_Float3_Float2_Float2 = + TSymbolUniqueId(1000); + static constexpr const TSymbolUniqueId textureGrad_Sampler2DArrayShadow1_Float4_Float2_Float2 = + TSymbolUniqueId(1001); + static constexpr const TSymbolUniqueId textureGrad_Sampler1DShadow1_Float3_Float1_Float1 = + TSymbolUniqueId(1002); + static constexpr const TSymbolUniqueId textureGrad_Sampler1DArray1_Float2_Float1_Float1 = + TSymbolUniqueId(1003); + static constexpr const TSymbolUniqueId textureGrad_ISampler1DArray1_Float2_Float1_Float1 = + TSymbolUniqueId(1004); + static constexpr const TSymbolUniqueId textureGrad_USampler1DArray1_Float2_Float1_Float1 = + TSymbolUniqueId(1005); + static constexpr const TSymbolUniqueId textureGrad_Sampler1DArrayShadow1_Float3_Float1_Float1 = + TSymbolUniqueId(1006); + static constexpr const TSymbolUniqueId textureGrad_SamplerCubeArray1_Float4_Float3_Float3 = + TSymbolUniqueId(1007); + static constexpr const TSymbolUniqueId textureGrad_ISamplerCubeArray1_Float4_Float3_Float3 = + TSymbolUniqueId(1008); + static constexpr const TSymbolUniqueId textureGrad_USamplerCubeArray1_Float4_Float3_Float3 = + TSymbolUniqueId(1009); + static constexpr const TSymbolUniqueId textureGradExt_SamplerCubeArray1_Float4_Float3_Float3 = + TSymbolUniqueId(1010); + static constexpr const TSymbolUniqueId textureGradExt_ISamplerCubeArray1_Float4_Float3_Float3 = + TSymbolUniqueId(1011); + static constexpr const TSymbolUniqueId textureGradExt_USamplerCubeArray1_Float4_Float3_Float3 = + TSymbolUniqueId(1012); + static constexpr const TSymbolUniqueId textureProjGrad_Sampler2D1_Float3_Float2_Float2 = + TSymbolUniqueId(1013); + static constexpr const TSymbolUniqueId textureProjGrad_ISampler2D1_Float3_Float2_Float2 = + TSymbolUniqueId(1014); + static constexpr const TSymbolUniqueId textureProjGrad_USampler2D1_Float3_Float2_Float2 = + TSymbolUniqueId(1015); + static constexpr const TSymbolUniqueId textureProjGrad_Sampler2D1_Float4_Float2_Float2 = + TSymbolUniqueId(1016); + static constexpr const TSymbolUniqueId textureProjGrad_ISampler2D1_Float4_Float2_Float2 = + TSymbolUniqueId(1017); + static constexpr const TSymbolUniqueId textureProjGrad_USampler2D1_Float4_Float2_Float2 = + TSymbolUniqueId(1018); + static constexpr const TSymbolUniqueId textureProjGrad_Sampler3D1_Float4_Float3_Float3 = + TSymbolUniqueId(1019); + static constexpr const TSymbolUniqueId textureProjGrad_ISampler3D1_Float4_Float3_Float3 = + TSymbolUniqueId(1020); + static constexpr const TSymbolUniqueId textureProjGrad_USampler3D1_Float4_Float3_Float3 = + TSymbolUniqueId(1021); + static constexpr const TSymbolUniqueId textureProjGrad_Sampler2DShadow1_Float4_Float2_Float2 = + TSymbolUniqueId(1022); + static constexpr const TSymbolUniqueId textureProjGrad_Sampler1D1_Float2_Float1_Float1 = + TSymbolUniqueId(1023); + static constexpr const TSymbolUniqueId textureProjGrad_ISampler1D1_Float2_Float1_Float1 = + TSymbolUniqueId(1024); + static constexpr const TSymbolUniqueId textureProjGrad_USampler1D1_Float2_Float1_Float1 = + TSymbolUniqueId(1025); + static constexpr const TSymbolUniqueId textureProjGrad_Sampler1D1_Float4_Float1_Float1 = + TSymbolUniqueId(1026); + static constexpr const TSymbolUniqueId textureProjGrad_ISampler1D1_Float4_Float1_Float1 = + TSymbolUniqueId(1027); + static constexpr const TSymbolUniqueId textureProjGrad_USampler1D1_Float4_Float1_Float1 = + TSymbolUniqueId(1028); + static constexpr const TSymbolUniqueId textureProjGrad_Sampler1DShadow1_Float4_Float1_Float1 = + TSymbolUniqueId(1029); + static constexpr const TSymbolUniqueId textureProjGrad_Sampler2DRect1_Float3_Float2_Float2 = + TSymbolUniqueId(1030); + static constexpr const TSymbolUniqueId textureProjGrad_ISampler2DRect1_Float3_Float2_Float2 = + TSymbolUniqueId(1031); + static constexpr const TSymbolUniqueId textureProjGrad_USampler2DRect1_Float3_Float2_Float2 = + TSymbolUniqueId(1032); + static constexpr const TSymbolUniqueId textureProjGrad_Sampler2DRect1_Float4_Float2_Float2 = + TSymbolUniqueId(1033); + static constexpr const TSymbolUniqueId textureProjGrad_ISampler2DRect1_Float4_Float2_Float2 = + TSymbolUniqueId(1034); + static constexpr const TSymbolUniqueId textureProjGrad_USampler2DRect1_Float4_Float2_Float2 = + TSymbolUniqueId(1035); + static constexpr const TSymbolUniqueId + textureProjGrad_Sampler2DRectShadow1_Float4_Float2_Float2 = TSymbolUniqueId(1036); + static constexpr const TSymbolUniqueId textureQueryLevels_Sampler1D1 = TSymbolUniqueId(1037); + static constexpr const TSymbolUniqueId textureQueryLevels_ISampler1D1 = TSymbolUniqueId(1038); + static constexpr const TSymbolUniqueId textureQueryLevels_USampler1D1 = TSymbolUniqueId(1039); + static constexpr const TSymbolUniqueId textureQueryLevels_Sampler2D1 = TSymbolUniqueId(1040); + static constexpr const TSymbolUniqueId textureQueryLevels_ISampler2D1 = TSymbolUniqueId(1041); + static constexpr const TSymbolUniqueId textureQueryLevels_USampler2D1 = TSymbolUniqueId(1042); + static constexpr const TSymbolUniqueId textureQueryLevels_Sampler3D1 = TSymbolUniqueId(1043); + static constexpr const TSymbolUniqueId textureQueryLevels_ISampler3D1 = TSymbolUniqueId(1044); + static constexpr const TSymbolUniqueId textureQueryLevels_USampler3D1 = TSymbolUniqueId(1045); + static constexpr const TSymbolUniqueId textureQueryLevels_SamplerCube1 = TSymbolUniqueId(1046); + static constexpr const TSymbolUniqueId textureQueryLevels_ISamplerCube1 = TSymbolUniqueId(1047); + static constexpr const TSymbolUniqueId textureQueryLevels_USamplerCube1 = TSymbolUniqueId(1048); + static constexpr const TSymbolUniqueId textureQueryLevels_Sampler1DArray1 = + TSymbolUniqueId(1049); + static constexpr const TSymbolUniqueId textureQueryLevels_ISampler1DArray1 = + TSymbolUniqueId(1050); + static constexpr const TSymbolUniqueId textureQueryLevels_USampler1DArray1 = + TSymbolUniqueId(1051); + static constexpr const TSymbolUniqueId textureQueryLevels_Sampler2DArray1 = + TSymbolUniqueId(1052); + static constexpr const TSymbolUniqueId textureQueryLevels_ISampler2DArray1 = + TSymbolUniqueId(1053); + static constexpr const TSymbolUniqueId textureQueryLevels_USampler2DArray1 = + TSymbolUniqueId(1054); + static constexpr const TSymbolUniqueId textureQueryLevels_SamplerCubeArray1 = + TSymbolUniqueId(1055); + static constexpr const TSymbolUniqueId textureQueryLevels_ISamplerCubeArray1 = + TSymbolUniqueId(1056); + static constexpr const TSymbolUniqueId textureQueryLevels_USamplerCubeArray1 = + TSymbolUniqueId(1057); + static constexpr const TSymbolUniqueId textureQueryLevels_Sampler1DShadow1 = + TSymbolUniqueId(1058); + static constexpr const TSymbolUniqueId textureQueryLevels_Sampler2DShadow1 = + TSymbolUniqueId(1059); + static constexpr const TSymbolUniqueId textureQueryLevels_SamplerCubeShadow1 = + TSymbolUniqueId(1060); + static constexpr const TSymbolUniqueId textureQueryLevels_Sampler1DArrayShadow1 = + TSymbolUniqueId(1061); + static constexpr const TSymbolUniqueId textureQueryLevels_Sampler2DArrayShadow1 = + TSymbolUniqueId(1062); + static constexpr const TSymbolUniqueId textureQueryLevels_SamplerCubeArrayShadow1 = + TSymbolUniqueId(1063); + static constexpr const TSymbolUniqueId textureSamples_Sampler2DMS1 = TSymbolUniqueId(1064); + static constexpr const TSymbolUniqueId textureSamples_ISampler2DMS1 = TSymbolUniqueId(1065); + static constexpr const TSymbolUniqueId textureSamples_USampler2DMS1 = TSymbolUniqueId(1066); + static constexpr const TSymbolUniqueId textureSamples_Sampler2DMSArray1 = TSymbolUniqueId(1067); + static constexpr const TSymbolUniqueId textureSamples_ISampler2DMSArray1 = + TSymbolUniqueId(1068); + static constexpr const TSymbolUniqueId textureSamples_USampler2DMSArray1 = + TSymbolUniqueId(1069); + static constexpr const TSymbolUniqueId texture_Sampler2D1_Float2_Float1 = TSymbolUniqueId(1070); + static constexpr const TSymbolUniqueId texture_ISampler2D1_Float2_Float1 = + TSymbolUniqueId(1071); + static constexpr const TSymbolUniqueId texture_USampler2D1_Float2_Float1 = + TSymbolUniqueId(1072); + static constexpr const TSymbolUniqueId texture_Sampler3D1_Float3_Float1 = TSymbolUniqueId(1073); + static constexpr const TSymbolUniqueId texture_ISampler3D1_Float3_Float1 = + TSymbolUniqueId(1074); + static constexpr const TSymbolUniqueId texture_USampler3D1_Float3_Float1 = + TSymbolUniqueId(1075); + static constexpr const TSymbolUniqueId texture_SamplerCube1_Float3_Float1 = + TSymbolUniqueId(1076); + static constexpr const TSymbolUniqueId texture_ISamplerCube1_Float3_Float1 = + TSymbolUniqueId(1077); + static constexpr const TSymbolUniqueId texture_USamplerCube1_Float3_Float1 = + TSymbolUniqueId(1078); + static constexpr const TSymbolUniqueId texture_Sampler2DArray1_Float3_Float1 = + TSymbolUniqueId(1079); + static constexpr const TSymbolUniqueId texture_ISampler2DArray1_Float3_Float1 = + TSymbolUniqueId(1080); + static constexpr const TSymbolUniqueId texture_USampler2DArray1_Float3_Float1 = + TSymbolUniqueId(1081); + static constexpr const TSymbolUniqueId textureProj_Sampler2D1_Float3_Float1 = + TSymbolUniqueId(1082); + static constexpr const TSymbolUniqueId textureProj_ISampler2D1_Float3_Float1 = + TSymbolUniqueId(1083); + static constexpr const TSymbolUniqueId textureProj_USampler2D1_Float3_Float1 = + TSymbolUniqueId(1084); + static constexpr const TSymbolUniqueId textureProj_Sampler2D1_Float4_Float1 = + TSymbolUniqueId(1085); + static constexpr const TSymbolUniqueId textureProj_ISampler2D1_Float4_Float1 = + TSymbolUniqueId(1086); + static constexpr const TSymbolUniqueId textureProj_USampler2D1_Float4_Float1 = + TSymbolUniqueId(1087); + static constexpr const TSymbolUniqueId textureProj_Sampler3D1_Float4_Float1 = + TSymbolUniqueId(1088); + static constexpr const TSymbolUniqueId textureProj_ISampler3D1_Float4_Float1 = + TSymbolUniqueId(1089); + static constexpr const TSymbolUniqueId textureProj_USampler3D1_Float4_Float1 = + TSymbolUniqueId(1090); + static constexpr const TSymbolUniqueId texture_Sampler2DShadow1_Float3_Float1 = + TSymbolUniqueId(1091); + static constexpr const TSymbolUniqueId texture_SamplerCubeShadow1_Float4_Float1 = + TSymbolUniqueId(1092); + static constexpr const TSymbolUniqueId textureProj_Sampler2DShadow1_Float4_Float1 = + TSymbolUniqueId(1093); + static constexpr const TSymbolUniqueId texture_Sampler1D1_Float1_Float1 = TSymbolUniqueId(1094); + static constexpr const TSymbolUniqueId texture_ISampler1D1_Float1_Float1 = + TSymbolUniqueId(1095); + static constexpr const TSymbolUniqueId texture_USampler1D1_Float1_Float1 = + TSymbolUniqueId(1096); + static constexpr const TSymbolUniqueId texture_Sampler1DShadow1_Float3_Float1 = + TSymbolUniqueId(1097); + static constexpr const TSymbolUniqueId texture_Sampler1DArray1_Float3_Float1 = + TSymbolUniqueId(1098); + static constexpr const TSymbolUniqueId texture_ISampler1DArray1_Float3_Float1 = + TSymbolUniqueId(1099); + static constexpr const TSymbolUniqueId texture_USampler1DArray1_Float3_Float1 = + TSymbolUniqueId(1100); + static constexpr const TSymbolUniqueId texture_Sampler1DArrayShadow1_Float3_Float1 = + TSymbolUniqueId(1101); + static constexpr const TSymbolUniqueId texture_Sampler2DArrayShadow1_Float4_Float1 = + TSymbolUniqueId(1102); + static constexpr const TSymbolUniqueId textureProj_Sampler1D1_Float2_Float1 = + TSymbolUniqueId(1103); + static constexpr const TSymbolUniqueId textureProj_ISampler1D1_Float2_Float1 = + TSymbolUniqueId(1104); + static constexpr const TSymbolUniqueId textureProj_USampler1D1_Float2_Float1 = + TSymbolUniqueId(1105); + static constexpr const TSymbolUniqueId textureProj_Sampler1D1_Float4_Float1 = + TSymbolUniqueId(1106); + static constexpr const TSymbolUniqueId textureProj_ISampler1D1_Float4_Float1 = + TSymbolUniqueId(1107); + static constexpr const TSymbolUniqueId textureProj_USampler1D1_Float4_Float1 = + TSymbolUniqueId(1108); + static constexpr const TSymbolUniqueId textureProj_Sampler1DShadow1_Float4_Float1 = + TSymbolUniqueId(1109); + static constexpr const TSymbolUniqueId texture_SamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(1110); + static constexpr const TSymbolUniqueId texture_ISamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(1111); + static constexpr const TSymbolUniqueId texture_USamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(1112); + static constexpr const TSymbolUniqueId textureExt_SamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(1113); + static constexpr const TSymbolUniqueId textureExt_ISamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(1114); + static constexpr const TSymbolUniqueId textureExt_USamplerCubeArray1_Float4_Float1 = + TSymbolUniqueId(1115); + static constexpr const TSymbolUniqueId texture_SamplerExternalOES1_Float2_Float1 = + TSymbolUniqueId(1116); + static constexpr const TSymbolUniqueId textureProj_SamplerExternalOES1_Float3_Float1 = + TSymbolUniqueId(1117); + static constexpr const TSymbolUniqueId textureProj_SamplerExternalOES1_Float4_Float1 = + TSymbolUniqueId(1118); + static constexpr const TSymbolUniqueId texture_SamplerExternal2DY2YEXT1_Float2_Float1 = + TSymbolUniqueId(1119); + static constexpr const TSymbolUniqueId textureProj_SamplerExternal2DY2YEXT1_Float3_Float1 = + TSymbolUniqueId(1120); + static constexpr const TSymbolUniqueId textureProj_SamplerExternal2DY2YEXT1_Float4_Float1 = + TSymbolUniqueId(1121); + static constexpr const TSymbolUniqueId textureQueryLod_Sampler1D1_Float1 = + TSymbolUniqueId(1122); + static constexpr const TSymbolUniqueId textureQueryLod_ISampler1D1_Float1 = + TSymbolUniqueId(1123); + static constexpr const TSymbolUniqueId textureQueryLod_USampler1D1_Float1 = + TSymbolUniqueId(1124); + static constexpr const TSymbolUniqueId textureQueryLod_Sampler2D1_Float2 = + TSymbolUniqueId(1125); + static constexpr const TSymbolUniqueId textureQueryLod_ISampler2D1_Float2 = + TSymbolUniqueId(1126); + static constexpr const TSymbolUniqueId textureQueryLod_USampler2D1_Float2 = + TSymbolUniqueId(1127); + static constexpr const TSymbolUniqueId textureQueryLod_Sampler3D1_Float3 = + TSymbolUniqueId(1128); + static constexpr const TSymbolUniqueId textureQueryLod_ISampler3D1_Float3 = + TSymbolUniqueId(1129); + static constexpr const TSymbolUniqueId textureQueryLod_USampler3D1_Float3 = + TSymbolUniqueId(1130); + static constexpr const TSymbolUniqueId textureQueryLod_SamplerCube1_Float3 = + TSymbolUniqueId(1131); + static constexpr const TSymbolUniqueId textureQueryLod_ISamplerCube1_Float3 = + TSymbolUniqueId(1132); + static constexpr const TSymbolUniqueId textureQueryLod_USamplerCube1_Float3 = + TSymbolUniqueId(1133); + static constexpr const TSymbolUniqueId textureQueryLod_Sampler1DArray1_Float1 = + TSymbolUniqueId(1134); + static constexpr const TSymbolUniqueId textureQueryLod_ISampler1DArray1_Float1 = + TSymbolUniqueId(1135); + static constexpr const TSymbolUniqueId textureQueryLod_USampler1DArray1_Float1 = + TSymbolUniqueId(1136); + static constexpr const TSymbolUniqueId textureQueryLod_Sampler2DArray1_Float2 = + TSymbolUniqueId(1137); + static constexpr const TSymbolUniqueId textureQueryLod_ISampler2DArray1_Float2 = + TSymbolUniqueId(1138); + static constexpr const TSymbolUniqueId textureQueryLod_USampler2DArray1_Float2 = + TSymbolUniqueId(1139); + static constexpr const TSymbolUniqueId textureQueryLod_SamplerCubeArray1_Float3 = + TSymbolUniqueId(1140); + static constexpr const TSymbolUniqueId textureQueryLod_ISamplerCubeArray1_Float3 = + TSymbolUniqueId(1141); + static constexpr const TSymbolUniqueId textureQueryLod_USamplerCubeArray1_Float3 = + TSymbolUniqueId(1142); + static constexpr const TSymbolUniqueId textureQueryLod_Sampler1DShadow1_Float1 = + TSymbolUniqueId(1143); + static constexpr const TSymbolUniqueId textureQueryLod_Sampler2DShadow1_Float2 = + TSymbolUniqueId(1144); + static constexpr const TSymbolUniqueId textureQueryLod_SamplerCubeShadow1_Float3 = + TSymbolUniqueId(1145); + static constexpr const TSymbolUniqueId textureQueryLod_Sampler1DArrayShadow1_Float1 = + TSymbolUniqueId(1146); + static constexpr const TSymbolUniqueId textureQueryLod_Sampler2DArrayShadow1_Float2 = + TSymbolUniqueId(1147); + static constexpr const TSymbolUniqueId textureQueryLod_SamplerCubeArrayShadow1_Float3 = + TSymbolUniqueId(1148); + static constexpr const TSymbolUniqueId textureOffset_Sampler2D1_Float2_Int2 = + TSymbolUniqueId(1149); + static constexpr const TSymbolUniqueId textureOffset_ISampler2D1_Float2_Int2 = + TSymbolUniqueId(1150); + static constexpr const TSymbolUniqueId textureOffset_USampler2D1_Float2_Int2 = + TSymbolUniqueId(1151); + static constexpr const TSymbolUniqueId textureOffset_Sampler3D1_Float3_Int3 = + TSymbolUniqueId(1152); + static constexpr const TSymbolUniqueId textureOffset_ISampler3D1_Float3_Int3 = + TSymbolUniqueId(1153); + static constexpr const TSymbolUniqueId textureOffset_USampler3D1_Float3_Int3 = + TSymbolUniqueId(1154); + static constexpr const TSymbolUniqueId textureOffset_Sampler2DShadow1_Float3_Int2 = + TSymbolUniqueId(1155); + static constexpr const TSymbolUniqueId textureOffset_Sampler2DArray1_Float3_Int2 = + TSymbolUniqueId(1156); + static constexpr const TSymbolUniqueId textureOffset_ISampler2DArray1_Float3_Int2 = + TSymbolUniqueId(1157); + static constexpr const TSymbolUniqueId textureOffset_USampler2DArray1_Float3_Int2 = + TSymbolUniqueId(1158); + static constexpr const TSymbolUniqueId textureOffset_Sampler1D1_Float1_Int1 = + TSymbolUniqueId(1159); + static constexpr const TSymbolUniqueId textureOffset_ISampler1D1_Float1_Int1 = + TSymbolUniqueId(1160); + static constexpr const TSymbolUniqueId textureOffset_USampler1D1_Float1_Int1 = + TSymbolUniqueId(1161); + static constexpr const TSymbolUniqueId textureOffset_Sampler2DRect1_Float2_Int2 = + TSymbolUniqueId(1162); + static constexpr const TSymbolUniqueId textureOffset_ISampler2DRect1_Float2_Int2 = + TSymbolUniqueId(1163); + static constexpr const TSymbolUniqueId textureOffset_USampler2DRect1_Float2_Int2 = + TSymbolUniqueId(1164); + static constexpr const TSymbolUniqueId textureOffset_Sampler2DRectShadow1_Float3_Int2 = + TSymbolUniqueId(1165); + static constexpr const TSymbolUniqueId textureOffset_Sampler1DShadow1_Float3_Int1 = + TSymbolUniqueId(1166); + static constexpr const TSymbolUniqueId textureOffset_Sampler1DArray1_Float2_Int1 = + TSymbolUniqueId(1167); + static constexpr const TSymbolUniqueId textureOffset_ISampler1DArray1_Float2_Int1 = + TSymbolUniqueId(1168); + static constexpr const TSymbolUniqueId textureOffset_USampler1DArray1_Float2_Int1 = + TSymbolUniqueId(1169); + static constexpr const TSymbolUniqueId textureOffset_Sampler1DArrayShadow1_Float3_Int1 = + TSymbolUniqueId(1170); + static constexpr const TSymbolUniqueId textureOffset_Sampler2DArrayShadow1_Float4_Int2 = + TSymbolUniqueId(1171); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2D1_Float3_Int2 = + TSymbolUniqueId(1172); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler2D1_Float3_Int2 = + TSymbolUniqueId(1173); + static constexpr const TSymbolUniqueId textureProjOffset_USampler2D1_Float3_Int2 = + TSymbolUniqueId(1174); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2D1_Float4_Int2 = + TSymbolUniqueId(1175); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler2D1_Float4_Int2 = + TSymbolUniqueId(1176); + static constexpr const TSymbolUniqueId textureProjOffset_USampler2D1_Float4_Int2 = + TSymbolUniqueId(1177); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler3D1_Float4_Int3 = + TSymbolUniqueId(1178); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler3D1_Float4_Int3 = + TSymbolUniqueId(1179); + static constexpr const TSymbolUniqueId textureProjOffset_USampler3D1_Float4_Int3 = + TSymbolUniqueId(1180); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2DShadow1_Float4_Int2 = + TSymbolUniqueId(1181); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler1D1_Float2_Int1 = + TSymbolUniqueId(1182); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler1D1_Float2_Int1 = + TSymbolUniqueId(1183); + static constexpr const TSymbolUniqueId textureProjOffset_USampler1D1_Float2_Int1 = + TSymbolUniqueId(1184); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler1D1_Float4_Int1 = + TSymbolUniqueId(1185); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler1D1_Float4_Int1 = + TSymbolUniqueId(1186); + static constexpr const TSymbolUniqueId textureProjOffset_USampler1D1_Float4_Int1 = + TSymbolUniqueId(1187); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2DRect1_Float3_Int2 = + TSymbolUniqueId(1188); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler2DRect1_Float3_Int2 = + TSymbolUniqueId(1189); + static constexpr const TSymbolUniqueId textureProjOffset_USampler2DRect1_Float3_Int2 = + TSymbolUniqueId(1190); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2DRect1_Float4_Int2 = + TSymbolUniqueId(1191); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler2DRect1_Float4_Int2 = + TSymbolUniqueId(1192); + static constexpr const TSymbolUniqueId textureProjOffset_USampler2DRect1_Float4_Int2 = + TSymbolUniqueId(1193); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2DRectShadow1_Float4_Int2 = + TSymbolUniqueId(1194); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler1DShadow1_Float4_Int1 = + TSymbolUniqueId(1195); + static constexpr const TSymbolUniqueId textureLodOffset_Sampler2D1_Float2_Float1_Int2 = + TSymbolUniqueId(1196); + static constexpr const TSymbolUniqueId textureLodOffset_ISampler2D1_Float2_Float1_Int2 = + TSymbolUniqueId(1197); + static constexpr const TSymbolUniqueId textureLodOffset_USampler2D1_Float2_Float1_Int2 = + TSymbolUniqueId(1198); + static constexpr const TSymbolUniqueId textureLodOffset_Sampler3D1_Float3_Float1_Int3 = + TSymbolUniqueId(1199); + static constexpr const TSymbolUniqueId textureLodOffset_ISampler3D1_Float3_Float1_Int3 = + TSymbolUniqueId(1200); + static constexpr const TSymbolUniqueId textureLodOffset_USampler3D1_Float3_Float1_Int3 = + TSymbolUniqueId(1201); + static constexpr const TSymbolUniqueId textureLodOffset_Sampler2DShadow1_Float3_Float1_Int2 = + TSymbolUniqueId(1202); + static constexpr const TSymbolUniqueId textureLodOffset_Sampler2DArray1_Float3_Float1_Int2 = + TSymbolUniqueId(1203); + static constexpr const TSymbolUniqueId textureLodOffset_ISampler2DArray1_Float3_Float1_Int2 = + TSymbolUniqueId(1204); + static constexpr const TSymbolUniqueId textureLodOffset_USampler2DArray1_Float3_Float1_Int2 = + TSymbolUniqueId(1205); + static constexpr const TSymbolUniqueId textureLodOffset_Sampler1D1_Float1_Float1_Int1 = + TSymbolUniqueId(1206); + static constexpr const TSymbolUniqueId textureLodOffset_ISampler1D1_Float1_Float1_Int1 = + TSymbolUniqueId(1207); + static constexpr const TSymbolUniqueId textureLodOffset_USampler1D1_Float1_Float1_Int1 = + TSymbolUniqueId(1208); + static constexpr const TSymbolUniqueId textureLodOffset_Sampler1DShadow1_Float3_Float1_Int1 = + TSymbolUniqueId(1209); + static constexpr const TSymbolUniqueId textureLodOffset_Sampler1DArray1_Float2_Float1_Int1 = + TSymbolUniqueId(1210); + static constexpr const TSymbolUniqueId textureLodOffset_ISampler1DArray1_Float2_Float1_Int1 = + TSymbolUniqueId(1211); + static constexpr const TSymbolUniqueId textureLodOffset_USampler1DArray1_Float2_Float1_Int1 = + TSymbolUniqueId(1212); + static constexpr const TSymbolUniqueId + textureLodOffset_Sampler1DArrayShadow1_Float3_Float1_Int1 = TSymbolUniqueId(1213); + static constexpr const TSymbolUniqueId textureProjLodOffset_Sampler2D1_Float3_Float1_Int2 = + TSymbolUniqueId(1214); + static constexpr const TSymbolUniqueId textureProjLodOffset_ISampler2D1_Float3_Float1_Int2 = + TSymbolUniqueId(1215); + static constexpr const TSymbolUniqueId textureProjLodOffset_USampler2D1_Float3_Float1_Int2 = + TSymbolUniqueId(1216); + static constexpr const TSymbolUniqueId textureProjLodOffset_Sampler2D1_Float4_Float1_Int2 = + TSymbolUniqueId(1217); + static constexpr const TSymbolUniqueId textureProjLodOffset_ISampler2D1_Float4_Float1_Int2 = + TSymbolUniqueId(1218); + static constexpr const TSymbolUniqueId textureProjLodOffset_USampler2D1_Float4_Float1_Int2 = + TSymbolUniqueId(1219); + static constexpr const TSymbolUniqueId textureProjLodOffset_Sampler3D1_Float4_Float1_Int3 = + TSymbolUniqueId(1220); + static constexpr const TSymbolUniqueId textureProjLodOffset_ISampler3D1_Float4_Float1_Int3 = + TSymbolUniqueId(1221); + static constexpr const TSymbolUniqueId textureProjLodOffset_USampler3D1_Float4_Float1_Int3 = + TSymbolUniqueId(1222); + static constexpr const TSymbolUniqueId + textureProjLodOffset_Sampler2DShadow1_Float4_Float1_Int2 = TSymbolUniqueId(1223); + static constexpr const TSymbolUniqueId textureProjLodOffset_Sampler1D1_Float2_Float1_Int1 = + TSymbolUniqueId(1224); + static constexpr const TSymbolUniqueId textureProjLodOffset_ISampler1D1_Float2_Float1_Int1 = + TSymbolUniqueId(1225); + static constexpr const TSymbolUniqueId textureProjLodOffset_USampler1D1_Float2_Float1_Int1 = + TSymbolUniqueId(1226); + static constexpr const TSymbolUniqueId textureProjLodOffset_Sampler1D1_Float4_Float1_Int1 = + TSymbolUniqueId(1227); + static constexpr const TSymbolUniqueId textureProjLodOffset_ISampler1D1_Float4_Float1_Int1 = + TSymbolUniqueId(1228); + static constexpr const TSymbolUniqueId textureProjLodOffset_USampler1D1_Float4_Float1_Int1 = + TSymbolUniqueId(1229); + static constexpr const TSymbolUniqueId + textureProjLodOffset_Sampler1DShadow1_Float4_Float1_Int1 = TSymbolUniqueId(1230); + static constexpr const TSymbolUniqueId texelFetchOffset_Sampler2D1_Int2_Int1_Int2 = + TSymbolUniqueId(1231); + static constexpr const TSymbolUniqueId texelFetchOffset_ISampler2D1_Int2_Int1_Int2 = + TSymbolUniqueId(1232); + static constexpr const TSymbolUniqueId texelFetchOffset_USampler2D1_Int2_Int1_Int2 = + TSymbolUniqueId(1233); + static constexpr const TSymbolUniqueId texelFetchOffset_Sampler3D1_Int3_Int1_Int3 = + TSymbolUniqueId(1234); + static constexpr const TSymbolUniqueId texelFetchOffset_ISampler3D1_Int3_Int1_Int3 = + TSymbolUniqueId(1235); + static constexpr const TSymbolUniqueId texelFetchOffset_USampler3D1_Int3_Int1_Int3 = + TSymbolUniqueId(1236); + static constexpr const TSymbolUniqueId texelFetchOffset_Sampler2DArray1_Int3_Int1_Int2 = + TSymbolUniqueId(1237); + static constexpr const TSymbolUniqueId texelFetchOffset_ISampler2DArray1_Int3_Int1_Int2 = + TSymbolUniqueId(1238); + static constexpr const TSymbolUniqueId texelFetchOffset_USampler2DArray1_Int3_Int1_Int2 = + TSymbolUniqueId(1239); + static constexpr const TSymbolUniqueId texelFetchOffset_Sampler1D1_Int1_Int1_Int1 = + TSymbolUniqueId(1240); + static constexpr const TSymbolUniqueId texelFetchOffset_ISampler1D1_Int1_Int1_Int1 = + TSymbolUniqueId(1241); + static constexpr const TSymbolUniqueId texelFetchOffset_USampler1D1_Int1_Int1_Int1 = + TSymbolUniqueId(1242); + static constexpr const TSymbolUniqueId texelFetchOffset_Sampler2DRect1_Int2_Int2 = + TSymbolUniqueId(1243); + static constexpr const TSymbolUniqueId texelFetchOffset_ISampler2DRect1_Int2_Int2 = + TSymbolUniqueId(1244); + static constexpr const TSymbolUniqueId texelFetchOffset_USampler2DRect1_Int2_Int2 = + TSymbolUniqueId(1245); + static constexpr const TSymbolUniqueId texelFetchOffset_Sampler1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(1246); + static constexpr const TSymbolUniqueId texelFetchOffset_ISampler1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(1247); + static constexpr const TSymbolUniqueId texelFetchOffset_USampler1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(1248); + static constexpr const TSymbolUniqueId textureGradOffset_Sampler2D1_Float2_Float2_Float2_Int2 = + TSymbolUniqueId(1249); + static constexpr const TSymbolUniqueId textureGradOffset_ISampler2D1_Float2_Float2_Float2_Int2 = + TSymbolUniqueId(1250); + static constexpr const TSymbolUniqueId textureGradOffset_USampler2D1_Float2_Float2_Float2_Int2 = + TSymbolUniqueId(1251); + static constexpr const TSymbolUniqueId textureGradOffset_Sampler3D1_Float3_Float3_Float3_Int3 = + TSymbolUniqueId(1252); + static constexpr const TSymbolUniqueId textureGradOffset_ISampler3D1_Float3_Float3_Float3_Int3 = + TSymbolUniqueId(1253); + static constexpr const TSymbolUniqueId textureGradOffset_USampler3D1_Float3_Float3_Float3_Int3 = + TSymbolUniqueId(1254); + static constexpr const TSymbolUniqueId + textureGradOffset_Sampler2DShadow1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(1255); + static constexpr const TSymbolUniqueId + textureGradOffset_Sampler2DArray1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(1256); + static constexpr const TSymbolUniqueId + textureGradOffset_ISampler2DArray1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(1257); + static constexpr const TSymbolUniqueId + textureGradOffset_USampler2DArray1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(1258); + static constexpr const TSymbolUniqueId + textureGradOffset_Sampler2DArrayShadow1_Float4_Float2_Float2_Int2 = TSymbolUniqueId(1259); + static constexpr const TSymbolUniqueId textureGradOffset_Sampler1D1_Float1_Float1_Float1_Int1 = + TSymbolUniqueId(1260); + static constexpr const TSymbolUniqueId textureGradOffset_ISampler1D1_Float1_Float1_Float1_Int1 = + TSymbolUniqueId(1261); + static constexpr const TSymbolUniqueId textureGradOffset_USampler1D1_Float1_Float1_Float1_Int1 = + TSymbolUniqueId(1262); + static constexpr const TSymbolUniqueId + textureGradOffset_Sampler2DRect1_Float2_Float2_Float2_Int2 = TSymbolUniqueId(1263); + static constexpr const TSymbolUniqueId + textureGradOffset_ISampler2DRect1_Float2_Float2_Float2_Int2 = TSymbolUniqueId(1264); + static constexpr const TSymbolUniqueId + textureGradOffset_USampler2DRect1_Float2_Float2_Float2_Int2 = TSymbolUniqueId(1265); + static constexpr const TSymbolUniqueId + textureGradOffset_Sampler2DRectShadow1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(1266); + static constexpr const TSymbolUniqueId + textureGradOffset_Sampler1DShadow1_Float3_Float1_Float1_Int1 = TSymbolUniqueId(1267); + static constexpr const TSymbolUniqueId + textureGradOffset_Sampler1DArray1_Float2_Float1_Float1_Int1 = TSymbolUniqueId(1268); + static constexpr const TSymbolUniqueId + textureGradOffset_ISampler1DArray1_Float2_Float1_Float1_Int1 = TSymbolUniqueId(1269); + static constexpr const TSymbolUniqueId + textureGradOffset_USampler1DArray1_Float2_Float1_Float1_Int1 = TSymbolUniqueId(1270); + static constexpr const TSymbolUniqueId + textureGradOffset_Sampler1DArrayShadow1_Float3_Float1_Float1_Int1 = TSymbolUniqueId(1271); + static constexpr const TSymbolUniqueId + textureProjGradOffset_Sampler2D1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(1272); + static constexpr const TSymbolUniqueId + textureProjGradOffset_ISampler2D1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(1273); + static constexpr const TSymbolUniqueId + textureProjGradOffset_USampler2D1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(1274); + static constexpr const TSymbolUniqueId + textureProjGradOffset_Sampler2D1_Float4_Float2_Float2_Int2 = TSymbolUniqueId(1275); + static constexpr const TSymbolUniqueId + textureProjGradOffset_ISampler2D1_Float4_Float2_Float2_Int2 = TSymbolUniqueId(1276); + static constexpr const TSymbolUniqueId + textureProjGradOffset_USampler2D1_Float4_Float2_Float2_Int2 = TSymbolUniqueId(1277); + static constexpr const TSymbolUniqueId + textureProjGradOffset_Sampler3D1_Float4_Float3_Float3_Int3 = TSymbolUniqueId(1278); + static constexpr const TSymbolUniqueId + textureProjGradOffset_ISampler3D1_Float4_Float3_Float3_Int3 = TSymbolUniqueId(1279); + static constexpr const TSymbolUniqueId + textureProjGradOffset_USampler3D1_Float4_Float3_Float3_Int3 = TSymbolUniqueId(1280); + static constexpr const TSymbolUniqueId + textureProjGradOffset_Sampler2DShadow1_Float4_Float2_Float2_Int2 = TSymbolUniqueId(1281); + static constexpr const TSymbolUniqueId + textureProjGradOffset_Sampler1D1_Float2_Float1_Float1_Int1 = TSymbolUniqueId(1282); + static constexpr const TSymbolUniqueId + textureProjGradOffset_ISampler1D1_Float2_Float1_Float1_Int1 = TSymbolUniqueId(1283); + static constexpr const TSymbolUniqueId + textureProjGradOffset_USampler1D1_Float2_Float1_Float1_Int1 = TSymbolUniqueId(1284); + static constexpr const TSymbolUniqueId + textureProjGradOffset_Sampler1D1_Float4_Float1_Float1_Int1 = TSymbolUniqueId(1285); + static constexpr const TSymbolUniqueId + textureProjGradOffset_ISampler1D1_Float4_Float1_Float1_Int1 = TSymbolUniqueId(1286); + static constexpr const TSymbolUniqueId + textureProjGradOffset_USampler1D1_Float4_Float1_Float1_Int1 = TSymbolUniqueId(1287); + static constexpr const TSymbolUniqueId + textureProjGradOffset_Sampler2DRect1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(1288); + static constexpr const TSymbolUniqueId + textureProjGradOffset_ISampler2DRect1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(1289); + static constexpr const TSymbolUniqueId + textureProjGradOffset_USampler2DRect1_Float3_Float2_Float2_Int2 = TSymbolUniqueId(1290); + static constexpr const TSymbolUniqueId + textureProjGradOffset_Sampler2DRect1_Float4_Float2_Float2_Int2 = TSymbolUniqueId(1291); + static constexpr const TSymbolUniqueId + textureProjGradOffset_ISampler2DRect1_Float4_Float2_Float2_Int2 = TSymbolUniqueId(1292); + static constexpr const TSymbolUniqueId + textureProjGradOffset_USampler2DRect1_Float4_Float2_Float2_Int2 = TSymbolUniqueId(1293); + static constexpr const TSymbolUniqueId + textureProjGradOffset_Sampler2DRectShadow1_Float4_Float2_Float2_Int2 = + TSymbolUniqueId(1294); + static constexpr const TSymbolUniqueId + textureProjGradOffset_Sampler1DShadow1_Float4_Float1_Float1_Int1 = TSymbolUniqueId(1295); + static constexpr const TSymbolUniqueId textureOffset_Sampler2D1_Float2_Int2_Float1 = + TSymbolUniqueId(1296); + static constexpr const TSymbolUniqueId textureOffset_ISampler2D1_Float2_Int2_Float1 = + TSymbolUniqueId(1297); + static constexpr const TSymbolUniqueId textureOffset_USampler2D1_Float2_Int2_Float1 = + TSymbolUniqueId(1298); + static constexpr const TSymbolUniqueId textureOffset_Sampler3D1_Float3_Int3_Float1 = + TSymbolUniqueId(1299); + static constexpr const TSymbolUniqueId textureOffset_ISampler3D1_Float3_Int3_Float1 = + TSymbolUniqueId(1300); + static constexpr const TSymbolUniqueId textureOffset_USampler3D1_Float3_Int3_Float1 = + TSymbolUniqueId(1301); + static constexpr const TSymbolUniqueId textureOffset_Sampler2DShadow1_Float3_Int2_Float1 = + TSymbolUniqueId(1302); + static constexpr const TSymbolUniqueId textureOffset_Sampler2DArray1_Float3_Int2_Float1 = + TSymbolUniqueId(1303); + static constexpr const TSymbolUniqueId textureOffset_ISampler2DArray1_Float3_Int2_Float1 = + TSymbolUniqueId(1304); + static constexpr const TSymbolUniqueId textureOffset_USampler2DArray1_Float3_Int2_Float1 = + TSymbolUniqueId(1305); + static constexpr const TSymbolUniqueId textureOffset_Sampler1D1_Float1_Int1_Float1 = + TSymbolUniqueId(1306); + static constexpr const TSymbolUniqueId textureOffset_ISampler1D1_Float1_Int1_Float1 = + TSymbolUniqueId(1307); + static constexpr const TSymbolUniqueId textureOffset_USampler1D1_Float1_Int1_Float1 = + TSymbolUniqueId(1308); + static constexpr const TSymbolUniqueId textureOffset_Sampler1DShadow1_Float3_Int1_Float1 = + TSymbolUniqueId(1309); + static constexpr const TSymbolUniqueId textureOffset_Sampler1DArray1_Float2_Int1_Float1 = + TSymbolUniqueId(1310); + static constexpr const TSymbolUniqueId textureOffset_ISampler1DArray1_Float2_Int1_Float1 = + TSymbolUniqueId(1311); + static constexpr const TSymbolUniqueId textureOffset_USampler1DArray1_Float2_Int1_Float1 = + TSymbolUniqueId(1312); + static constexpr const TSymbolUniqueId textureOffset_Sampler1DArrayShadow1_Float3_Int1_Float1 = + TSymbolUniqueId(1313); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2D1_Float3_Int2_Float1 = + TSymbolUniqueId(1314); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler2D1_Float3_Int2_Float1 = + TSymbolUniqueId(1315); + static constexpr const TSymbolUniqueId textureProjOffset_USampler2D1_Float3_Int2_Float1 = + TSymbolUniqueId(1316); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2D1_Float4_Int2_Float1 = + TSymbolUniqueId(1317); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler2D1_Float4_Int2_Float1 = + TSymbolUniqueId(1318); + static constexpr const TSymbolUniqueId textureProjOffset_USampler2D1_Float4_Int2_Float1 = + TSymbolUniqueId(1319); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler3D1_Float4_Int3_Float1 = + TSymbolUniqueId(1320); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler3D1_Float4_Int3_Float1 = + TSymbolUniqueId(1321); + static constexpr const TSymbolUniqueId textureProjOffset_USampler3D1_Float4_Int3_Float1 = + TSymbolUniqueId(1322); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler2DShadow1_Float4_Int2_Float1 = + TSymbolUniqueId(1323); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler1D1_Float2_Int1_Float1 = + TSymbolUniqueId(1324); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler1D1_Float2_Int1_Float1 = + TSymbolUniqueId(1325); + static constexpr const TSymbolUniqueId textureProjOffset_USampler1D1_Float2_Int1_Float1 = + TSymbolUniqueId(1326); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler1D1_Float4_Int1_Float1 = + TSymbolUniqueId(1327); + static constexpr const TSymbolUniqueId textureProjOffset_ISampler1D1_Float4_Int1_Float1 = + TSymbolUniqueId(1328); + static constexpr const TSymbolUniqueId textureProjOffset_USampler1D1_Float4_Int1_Float1 = + TSymbolUniqueId(1329); + static constexpr const TSymbolUniqueId textureProjOffset_Sampler1DShadow1_Float4_Int1_Float1 = + TSymbolUniqueId(1330); + static constexpr const TSymbolUniqueId textureGather_Sampler2D1_Float2 = TSymbolUniqueId(1331); + static constexpr const TSymbolUniqueId textureGather_ISampler2D1_Float2 = TSymbolUniqueId(1332); + static constexpr const TSymbolUniqueId textureGather_USampler2D1_Float2 = TSymbolUniqueId(1333); + static constexpr const TSymbolUniqueId textureGather_Sampler2D1_Float2_Int1 = + TSymbolUniqueId(1334); + static constexpr const TSymbolUniqueId textureGather_ISampler2D1_Float2_Int1 = + TSymbolUniqueId(1335); + static constexpr const TSymbolUniqueId textureGather_USampler2D1_Float2_Int1 = + TSymbolUniqueId(1336); + static constexpr const TSymbolUniqueId textureGather_Sampler2DArray1_Float3 = + TSymbolUniqueId(1337); + static constexpr const TSymbolUniqueId textureGather_ISampler2DArray1_Float3 = + TSymbolUniqueId(1338); + static constexpr const TSymbolUniqueId textureGather_USampler2DArray1_Float3 = + TSymbolUniqueId(1339); + static constexpr const TSymbolUniqueId textureGather_Sampler2DArray1_Float3_Int1 = + TSymbolUniqueId(1340); + static constexpr const TSymbolUniqueId textureGather_ISampler2DArray1_Float3_Int1 = + TSymbolUniqueId(1341); + static constexpr const TSymbolUniqueId textureGather_USampler2DArray1_Float3_Int1 = + TSymbolUniqueId(1342); + static constexpr const TSymbolUniqueId textureGather_SamplerCube1_Float3 = + TSymbolUniqueId(1343); + static constexpr const TSymbolUniqueId textureGather_ISamplerCube1_Float3 = + TSymbolUniqueId(1344); + static constexpr const TSymbolUniqueId textureGather_USamplerCube1_Float3 = + TSymbolUniqueId(1345); + static constexpr const TSymbolUniqueId textureGather_SamplerCube1_Float3_Int1 = + TSymbolUniqueId(1346); + static constexpr const TSymbolUniqueId textureGather_ISamplerCube1_Float3_Int1 = + TSymbolUniqueId(1347); + static constexpr const TSymbolUniqueId textureGather_USamplerCube1_Float3_Int1 = + TSymbolUniqueId(1348); + static constexpr const TSymbolUniqueId textureGather_SamplerCubeArray1_Float4 = + TSymbolUniqueId(1349); + static constexpr const TSymbolUniqueId textureGather_ISamplerCubeArray1_Float4 = + TSymbolUniqueId(1350); + static constexpr const TSymbolUniqueId textureGather_USamplerCubeArray1_Float4 = + TSymbolUniqueId(1351); + static constexpr const TSymbolUniqueId textureGather_SamplerCubeArray1_Float4_Int1 = + TSymbolUniqueId(1352); + static constexpr const TSymbolUniqueId textureGather_ISamplerCubeArray1_Float4_Int1 = + TSymbolUniqueId(1353); + static constexpr const TSymbolUniqueId textureGather_USamplerCubeArray1_Float4_Int1 = + TSymbolUniqueId(1354); + static constexpr const TSymbolUniqueId textureGather_SamplerCubeArrayShadow1_Float4_Float1 = + TSymbolUniqueId(1355); + static constexpr const TSymbolUniqueId textureGatherExt_SamplerCubeArray1_Float4 = + TSymbolUniqueId(1356); + static constexpr const TSymbolUniqueId textureGatherExt_ISamplerCubeArray1_Float4 = + TSymbolUniqueId(1357); + static constexpr const TSymbolUniqueId textureGatherExt_USamplerCubeArray1_Float4 = + TSymbolUniqueId(1358); + static constexpr const TSymbolUniqueId textureGatherExt_SamplerCubeArray1_Float4_Int1 = + TSymbolUniqueId(1359); + static constexpr const TSymbolUniqueId textureGatherExt_ISamplerCubeArray1_Float4_Int1 = + TSymbolUniqueId(1360); + static constexpr const TSymbolUniqueId textureGatherExt_USamplerCubeArray1_Float4_Int1 = + TSymbolUniqueId(1361); + static constexpr const TSymbolUniqueId textureGatherExt_SamplerCubeArrayShadow1_Float4_Float1 = + TSymbolUniqueId(1362); + static constexpr const TSymbolUniqueId textureGather_Sampler2DRect1_Float3 = + TSymbolUniqueId(1363); + static constexpr const TSymbolUniqueId textureGather_ISampler2DRect1_Float3 = + TSymbolUniqueId(1364); + static constexpr const TSymbolUniqueId textureGather_USampler2DRect1_Float3 = + TSymbolUniqueId(1365); + static constexpr const TSymbolUniqueId textureGather_Sampler2DRect1_Float3_Int1 = + TSymbolUniqueId(1366); + static constexpr const TSymbolUniqueId textureGather_ISampler2DRect1_Float3_Int1 = + TSymbolUniqueId(1367); + static constexpr const TSymbolUniqueId textureGather_USampler2DRect1_Float3_Int1 = + TSymbolUniqueId(1368); + static constexpr const TSymbolUniqueId textureGather_Sampler2DRectShadow1_Float2_Float1 = + TSymbolUniqueId(1369); + static constexpr const TSymbolUniqueId textureGather_Sampler2DShadow1_Float2 = + TSymbolUniqueId(1370); + static constexpr const TSymbolUniqueId textureGather_Sampler2DShadow1_Float2_Float1 = + TSymbolUniqueId(1371); + static constexpr const TSymbolUniqueId textureGather_Sampler2DArrayShadow1_Float3 = + TSymbolUniqueId(1372); + static constexpr const TSymbolUniqueId textureGather_Sampler2DArrayShadow1_Float3_Float1 = + TSymbolUniqueId(1373); + static constexpr const TSymbolUniqueId textureGather_SamplerCubeShadow1_Float3 = + TSymbolUniqueId(1374); + static constexpr const TSymbolUniqueId textureGather_SamplerCubeShadow1_Float3_Float1 = + TSymbolUniqueId(1375); + static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2D1_Float2_Int2 = + TSymbolUniqueId(1376); + static constexpr const TSymbolUniqueId textureGatherOffset_ISampler2D1_Float2_Int2 = + TSymbolUniqueId(1377); + static constexpr const TSymbolUniqueId textureGatherOffset_USampler2D1_Float2_Int2 = + TSymbolUniqueId(1378); + static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2DArray1_Float3_Int2 = + TSymbolUniqueId(1379); + static constexpr const TSymbolUniqueId textureGatherOffset_ISampler2DArray1_Float3_Int2 = + TSymbolUniqueId(1380); + static constexpr const TSymbolUniqueId textureGatherOffset_USampler2DArray1_Float3_Int2 = + TSymbolUniqueId(1381); + static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2DShadow1_Float2_Float1_Int2 = + TSymbolUniqueId(1382); + static constexpr const TSymbolUniqueId + textureGatherOffset_Sampler2DArrayShadow1_Float3_Float1_Int2 = TSymbolUniqueId(1383); + static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2DRect1_Float2_Int2 = + TSymbolUniqueId(1384); + static constexpr const TSymbolUniqueId textureGatherOffset_ISampler2DRect1_Float2_Int2 = + TSymbolUniqueId(1385); + static constexpr const TSymbolUniqueId textureGatherOffset_USampler2DRect1_Float2_Int2 = + TSymbolUniqueId(1386); + static constexpr const TSymbolUniqueId + textureGatherOffset_Sampler2DRectShadow1_Float2_Float1_Int2 = TSymbolUniqueId(1387); + static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2D1_Float2_Int2_Int1 = + TSymbolUniqueId(1388); + static constexpr const TSymbolUniqueId textureGatherOffset_ISampler2D1_Float2_Int2_Int1 = + TSymbolUniqueId(1389); + static constexpr const TSymbolUniqueId textureGatherOffset_USampler2D1_Float2_Int2_Int1 = + TSymbolUniqueId(1390); + static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2DArray1_Float3_Int2_Int1 = + TSymbolUniqueId(1391); + static constexpr const TSymbolUniqueId textureGatherOffset_ISampler2DArray1_Float3_Int2_Int1 = + TSymbolUniqueId(1392); + static constexpr const TSymbolUniqueId textureGatherOffset_USampler2DArray1_Float3_Int2_Int1 = + TSymbolUniqueId(1393); + static constexpr const TSymbolUniqueId textureGatherOffset_Sampler2DRect1_Float2_Int2_Int1 = + TSymbolUniqueId(1394); + static constexpr const TSymbolUniqueId textureGatherOffset_ISampler2DRect1_Float2_Int2_Int1 = + TSymbolUniqueId(1395); + static constexpr const TSymbolUniqueId textureGatherOffset_USampler2DRect1_Float2_Int2_Int1 = + TSymbolUniqueId(1396); + static constexpr const TSymbolUniqueId textureGatherOffsets_Sampler2D1_Float2_4xInt2 = + TSymbolUniqueId(1397); + static constexpr const TSymbolUniqueId pt10Dx4 = TSymbolUniqueId(1398); + static constexpr const TSymbolUniqueId textureGatherOffsets_ISampler2D1_Float2_4xInt2 = + TSymbolUniqueId(1399); + static constexpr const TSymbolUniqueId textureGatherOffsets_USampler2D1_Float2_4xInt2 = + TSymbolUniqueId(1400); + static constexpr const TSymbolUniqueId textureGatherOffsets_Sampler2DArray1_Float3_4xInt2 = + TSymbolUniqueId(1401); + static constexpr const TSymbolUniqueId textureGatherOffsets_ISampler2DArray1_Float3_4xInt2 = + TSymbolUniqueId(1402); + static constexpr const TSymbolUniqueId textureGatherOffsets_USampler2DArray1_Float3_4xInt2 = + TSymbolUniqueId(1403); + static constexpr const TSymbolUniqueId + textureGatherOffsets_Sampler2DShadow1_Float2_Float1_4xInt2 = TSymbolUniqueId(1404); + static constexpr const TSymbolUniqueId + textureGatherOffsets_Sampler2DArrayShadow1_Float3_Float1_4xInt2 = TSymbolUniqueId(1405); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_Sampler2D1_Float2_4xInt2 = + TSymbolUniqueId(1406); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_ISampler2D1_Float2_4xInt2 = + TSymbolUniqueId(1407); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_USampler2D1_Float2_4xInt2 = + TSymbolUniqueId(1408); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_Sampler2DArray1_Float3_4xInt2 = + TSymbolUniqueId(1409); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_ISampler2DArray1_Float3_4xInt2 = + TSymbolUniqueId(1410); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_USampler2DArray1_Float3_4xInt2 = + TSymbolUniqueId(1411); + static constexpr const TSymbolUniqueId + textureGatherOffsetsExt_Sampler2DShadow1_Float2_Float1_4xInt2 = TSymbolUniqueId(1412); + static constexpr const TSymbolUniqueId + textureGatherOffsetsExt_Sampler2DArrayShadow1_Float3_Float1_4xInt2 = TSymbolUniqueId(1413); + static constexpr const TSymbolUniqueId textureGatherOffsets_Sampler2DRect1_Float2_4xInt2 = + TSymbolUniqueId(1414); + static constexpr const TSymbolUniqueId textureGatherOffsets_ISampler2DRect1_Float2_4xInt2 = + TSymbolUniqueId(1415); + static constexpr const TSymbolUniqueId textureGatherOffsets_USampler2DRect1_Float2_4xInt2 = + TSymbolUniqueId(1416); + static constexpr const TSymbolUniqueId + textureGatherOffsets_Sampler2DRectShadow1_Float2_Float1_4xInt2 = TSymbolUniqueId(1417); + static constexpr const TSymbolUniqueId textureGatherOffsets_Sampler2D1_Float2_4xInt2_Int1 = + TSymbolUniqueId(1418); + static constexpr const TSymbolUniqueId textureGatherOffsets_ISampler2D1_Float2_4xInt2_Int1 = + TSymbolUniqueId(1419); + static constexpr const TSymbolUniqueId textureGatherOffsets_USampler2D1_Float2_4xInt2_Int1 = + TSymbolUniqueId(1420); + static constexpr const TSymbolUniqueId textureGatherOffsets_Sampler2DArray1_Float3_4xInt2_Int1 = + TSymbolUniqueId(1421); + static constexpr const TSymbolUniqueId + textureGatherOffsets_ISampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(1422); + static constexpr const TSymbolUniqueId + textureGatherOffsets_USampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(1423); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_Sampler2D1_Float2_4xInt2_Int1 = + TSymbolUniqueId(1424); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_ISampler2D1_Float2_4xInt2_Int1 = + TSymbolUniqueId(1425); + static constexpr const TSymbolUniqueId textureGatherOffsetsExt_USampler2D1_Float2_4xInt2_Int1 = + TSymbolUniqueId(1426); + static constexpr const TSymbolUniqueId + textureGatherOffsetsExt_Sampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(1427); + static constexpr const TSymbolUniqueId + textureGatherOffsetsExt_ISampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(1428); + static constexpr const TSymbolUniqueId + textureGatherOffsetsExt_USampler2DArray1_Float3_4xInt2_Int1 = TSymbolUniqueId(1429); + static constexpr const TSymbolUniqueId textureGatherOffsets_Sampler2DRect1_Float2_4xInt2_Int1 = + TSymbolUniqueId(1430); + static constexpr const TSymbolUniqueId textureGatherOffsets_ISampler2DRect1_Float2_4xInt2_Int1 = + TSymbolUniqueId(1431); + static constexpr const TSymbolUniqueId textureGatherOffsets_USampler2DRect1_Float2_4xInt2_Int1 = + TSymbolUniqueId(1432); + static constexpr const TSymbolUniqueId rgb_2_yuv_Float3_YuvCscStandardEXT1 = + TSymbolUniqueId(1433); + static constexpr const TSymbolUniqueId pt00H = TSymbolUniqueId(1434); + static constexpr const TSymbolUniqueId yuv_2_rgb_Float3_YuvCscStandardEXT1 = + TSymbolUniqueId(1435); + static constexpr const TSymbolUniqueId dFdxExt_Float1 = TSymbolUniqueId(1436); + static constexpr const TSymbolUniqueId dFdxExt_Float2 = TSymbolUniqueId(1437); + static constexpr const TSymbolUniqueId dFdxExt_Float3 = TSymbolUniqueId(1438); + static constexpr const TSymbolUniqueId dFdxExt_Float4 = TSymbolUniqueId(1439); + static constexpr const TSymbolUniqueId dFdyExt_Float1 = TSymbolUniqueId(1440); + static constexpr const TSymbolUniqueId dFdyExt_Float2 = TSymbolUniqueId(1441); + static constexpr const TSymbolUniqueId dFdyExt_Float3 = TSymbolUniqueId(1442); + static constexpr const TSymbolUniqueId dFdyExt_Float4 = TSymbolUniqueId(1443); + static constexpr const TSymbolUniqueId fwidthExt_Float1 = TSymbolUniqueId(1444); + static constexpr const TSymbolUniqueId fwidthExt_Float2 = TSymbolUniqueId(1445); + static constexpr const TSymbolUniqueId fwidthExt_Float3 = TSymbolUniqueId(1446); + static constexpr const TSymbolUniqueId fwidthExt_Float4 = TSymbolUniqueId(1447); + static constexpr const TSymbolUniqueId dFdx_Float1 = TSymbolUniqueId(1448); + static constexpr const TSymbolUniqueId dFdx_Float2 = TSymbolUniqueId(1449); + static constexpr const TSymbolUniqueId dFdx_Float3 = TSymbolUniqueId(1450); + static constexpr const TSymbolUniqueId dFdx_Float4 = TSymbolUniqueId(1451); + static constexpr const TSymbolUniqueId dFdy_Float1 = TSymbolUniqueId(1452); + static constexpr const TSymbolUniqueId dFdy_Float2 = TSymbolUniqueId(1453); + static constexpr const TSymbolUniqueId dFdy_Float3 = TSymbolUniqueId(1454); + static constexpr const TSymbolUniqueId dFdy_Float4 = TSymbolUniqueId(1455); + static constexpr const TSymbolUniqueId fwidth_Float1 = TSymbolUniqueId(1456); + static constexpr const TSymbolUniqueId fwidth_Float2 = TSymbolUniqueId(1457); + static constexpr const TSymbolUniqueId fwidth_Float3 = TSymbolUniqueId(1458); + static constexpr const TSymbolUniqueId fwidth_Float4 = TSymbolUniqueId(1459); + static constexpr const TSymbolUniqueId dFdxFine_Float1 = TSymbolUniqueId(1460); + static constexpr const TSymbolUniqueId dFdxFine_Float2 = TSymbolUniqueId(1461); + static constexpr const TSymbolUniqueId dFdxFine_Float3 = TSymbolUniqueId(1462); + static constexpr const TSymbolUniqueId dFdxFine_Float4 = TSymbolUniqueId(1463); + static constexpr const TSymbolUniqueId dFdyFine_Float1 = TSymbolUniqueId(1464); + static constexpr const TSymbolUniqueId dFdyFine_Float2 = TSymbolUniqueId(1465); + static constexpr const TSymbolUniqueId dFdyFine_Float3 = TSymbolUniqueId(1466); + static constexpr const TSymbolUniqueId dFdyFine_Float4 = TSymbolUniqueId(1467); + static constexpr const TSymbolUniqueId dFdxCoarse_Float1 = TSymbolUniqueId(1468); + static constexpr const TSymbolUniqueId dFdxCoarse_Float2 = TSymbolUniqueId(1469); + static constexpr const TSymbolUniqueId dFdxCoarse_Float3 = TSymbolUniqueId(1470); + static constexpr const TSymbolUniqueId dFdxCoarse_Float4 = TSymbolUniqueId(1471); + static constexpr const TSymbolUniqueId dFdyCoarse_Float1 = TSymbolUniqueId(1472); + static constexpr const TSymbolUniqueId dFdyCoarse_Float2 = TSymbolUniqueId(1473); + static constexpr const TSymbolUniqueId dFdyCoarse_Float3 = TSymbolUniqueId(1474); + static constexpr const TSymbolUniqueId dFdyCoarse_Float4 = TSymbolUniqueId(1475); + static constexpr const TSymbolUniqueId fwidthFine_Float1 = TSymbolUniqueId(1476); + static constexpr const TSymbolUniqueId fwidthFine_Float2 = TSymbolUniqueId(1477); + static constexpr const TSymbolUniqueId fwidthFine_Float3 = TSymbolUniqueId(1478); + static constexpr const TSymbolUniqueId fwidthFine_Float4 = TSymbolUniqueId(1479); + static constexpr const TSymbolUniqueId fwidthCoarse_Float1 = TSymbolUniqueId(1480); + static constexpr const TSymbolUniqueId fwidthCoarse_Float2 = TSymbolUniqueId(1481); + static constexpr const TSymbolUniqueId fwidthCoarse_Float3 = TSymbolUniqueId(1482); + static constexpr const TSymbolUniqueId fwidthCoarse_Float4 = TSymbolUniqueId(1483); + static constexpr const TSymbolUniqueId interpolateAtCentroid_Float1 = TSymbolUniqueId(1484); + static constexpr const TSymbolUniqueId interpolateAtCentroid_Float2 = TSymbolUniqueId(1485); + static constexpr const TSymbolUniqueId interpolateAtCentroid_Float3 = TSymbolUniqueId(1486); + static constexpr const TSymbolUniqueId interpolateAtCentroid_Float4 = TSymbolUniqueId(1487); + static constexpr const TSymbolUniqueId interpolateAtSample_Float1_Int1 = TSymbolUniqueId(1488); + static constexpr const TSymbolUniqueId interpolateAtSample_Float2_Int1 = TSymbolUniqueId(1489); + static constexpr const TSymbolUniqueId interpolateAtSample_Float3_Int1 = TSymbolUniqueId(1490); + static constexpr const TSymbolUniqueId interpolateAtSample_Float4_Int1 = TSymbolUniqueId(1491); + static constexpr const TSymbolUniqueId interpolateAtOffset_Float1_Float2 = + TSymbolUniqueId(1492); + static constexpr const TSymbolUniqueId interpolateAtOffset_Float2_Float2 = + TSymbolUniqueId(1493); + static constexpr const TSymbolUniqueId interpolateAtOffset_Float3_Float2 = + TSymbolUniqueId(1494); + static constexpr const TSymbolUniqueId interpolateAtOffset_Float4_Float2 = + TSymbolUniqueId(1495); + static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float1 = TSymbolUniqueId(1496); + static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float2 = TSymbolUniqueId(1497); + static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float3 = TSymbolUniqueId(1498); + static constexpr const TSymbolUniqueId interpolateAtCentroidExt_Float4 = TSymbolUniqueId(1499); + static constexpr const TSymbolUniqueId interpolateAtSampleExt_Float1_Int1 = + TSymbolUniqueId(1500); + static constexpr const TSymbolUniqueId interpolateAtSampleExt_Float2_Int1 = + TSymbolUniqueId(1501); + static constexpr const TSymbolUniqueId interpolateAtSampleExt_Float3_Int1 = + TSymbolUniqueId(1502); + static constexpr const TSymbolUniqueId interpolateAtSampleExt_Float4_Int1 = + TSymbolUniqueId(1503); + static constexpr const TSymbolUniqueId interpolateAtOffsetExt_Float1_Float2 = + TSymbolUniqueId(1504); + static constexpr const TSymbolUniqueId interpolateAtOffsetExt_Float2_Float2 = + TSymbolUniqueId(1505); + static constexpr const TSymbolUniqueId interpolateAtOffsetExt_Float3_Float2 = + TSymbolUniqueId(1506); + static constexpr const TSymbolUniqueId interpolateAtOffsetExt_Float4_Float2 = + TSymbolUniqueId(1507); + static constexpr const TSymbolUniqueId atomicCounter_AtomicCounter1 = TSymbolUniqueId(1508); + static constexpr const TSymbolUniqueId pt00G = TSymbolUniqueId(1509); + static constexpr const TSymbolUniqueId atomicCounterIncrement_AtomicCounter1 = + TSymbolUniqueId(1510); + static constexpr const TSymbolUniqueId atomicCounterDecrement_AtomicCounter1 = + TSymbolUniqueId(1511); + static constexpr const TSymbolUniqueId atomicCounterAdd_AtomicCounter1_UInt1 = + TSymbolUniqueId(1512); + static constexpr const TSymbolUniqueId atomicCounterSubtract_AtomicCounter1_UInt1 = + TSymbolUniqueId(1513); + static constexpr const TSymbolUniqueId atomicCounterMin_AtomicCounter1_UInt1 = + TSymbolUniqueId(1514); + static constexpr const TSymbolUniqueId atomicCounterMax_AtomicCounter1_UInt1 = + TSymbolUniqueId(1515); + static constexpr const TSymbolUniqueId atomicCounterAnd_AtomicCounter1_UInt1 = + TSymbolUniqueId(1516); + static constexpr const TSymbolUniqueId atomicCounterOr_AtomicCounter1_UInt1 = + TSymbolUniqueId(1517); + static constexpr const TSymbolUniqueId atomicCounterXor_AtomicCounter1_UInt1 = + TSymbolUniqueId(1518); + static constexpr const TSymbolUniqueId atomicCounterExchange_AtomicCounter1_UInt1 = + TSymbolUniqueId(1519); + static constexpr const TSymbolUniqueId atomicCounterCompSwap_AtomicCounter1_UInt1_UInt1 = + TSymbolUniqueId(1520); + static constexpr const TSymbolUniqueId atomicAdd_UInt1_UInt1 = TSymbolUniqueId(1521); + static constexpr const TSymbolUniqueId pt_io_00E = TSymbolUniqueId(1522); + static constexpr const TSymbolUniqueId atomicAdd_Int1_Int1 = TSymbolUniqueId(1523); + static constexpr const TSymbolUniqueId pt_io_00D = TSymbolUniqueId(1524); + static constexpr const TSymbolUniqueId atomicMin_UInt1_UInt1 = TSymbolUniqueId(1525); + static constexpr const TSymbolUniqueId atomicMin_Int1_Int1 = TSymbolUniqueId(1526); + static constexpr const TSymbolUniqueId atomicMax_UInt1_UInt1 = TSymbolUniqueId(1527); + static constexpr const TSymbolUniqueId atomicMax_Int1_Int1 = TSymbolUniqueId(1528); + static constexpr const TSymbolUniqueId atomicAnd_UInt1_UInt1 = TSymbolUniqueId(1529); + static constexpr const TSymbolUniqueId atomicAnd_Int1_Int1 = TSymbolUniqueId(1530); + static constexpr const TSymbolUniqueId atomicOr_UInt1_UInt1 = TSymbolUniqueId(1531); + static constexpr const TSymbolUniqueId atomicOr_Int1_Int1 = TSymbolUniqueId(1532); + static constexpr const TSymbolUniqueId atomicXor_UInt1_UInt1 = TSymbolUniqueId(1533); + static constexpr const TSymbolUniqueId atomicXor_Int1_Int1 = TSymbolUniqueId(1534); + static constexpr const TSymbolUniqueId atomicExchange_UInt1_UInt1 = TSymbolUniqueId(1535); + static constexpr const TSymbolUniqueId atomicExchange_Int1_Int1 = TSymbolUniqueId(1536); + static constexpr const TSymbolUniqueId atomicCompSwap_UInt1_UInt1_UInt1 = TSymbolUniqueId(1537); + static constexpr const TSymbolUniqueId atomicCompSwap_Int1_Int1_Int1 = TSymbolUniqueId(1538); + static constexpr const TSymbolUniqueId imageSize_Image2D1 = TSymbolUniqueId(1539); + static constexpr const TSymbolUniqueId pt00z = TSymbolUniqueId(1540); + static constexpr const TSymbolUniqueId imageSize_IImage2D1 = TSymbolUniqueId(1541); + static constexpr const TSymbolUniqueId pt01K = TSymbolUniqueId(1542); + static constexpr const TSymbolUniqueId imageSize_UImage2D1 = TSymbolUniqueId(1543); + static constexpr const TSymbolUniqueId pt01V = TSymbolUniqueId(1544); + static constexpr const TSymbolUniqueId imageSize_Image3D1 = TSymbolUniqueId(1545); + static constexpr const TSymbolUniqueId pt01A = TSymbolUniqueId(1546); + static constexpr const TSymbolUniqueId imageSize_IImage3D1 = TSymbolUniqueId(1547); + static constexpr const TSymbolUniqueId pt01L = TSymbolUniqueId(1548); + static constexpr const TSymbolUniqueId imageSize_UImage3D1 = TSymbolUniqueId(1549); + static constexpr const TSymbolUniqueId pt01W = TSymbolUniqueId(1550); + static constexpr const TSymbolUniqueId imageSize_Image2DArray1 = TSymbolUniqueId(1551); + static constexpr const TSymbolUniqueId pt01B = TSymbolUniqueId(1552); + static constexpr const TSymbolUniqueId imageSize_IImage2DArray1 = TSymbolUniqueId(1553); + static constexpr const TSymbolUniqueId pt01M = TSymbolUniqueId(1554); + static constexpr const TSymbolUniqueId imageSize_UImage2DArray1 = TSymbolUniqueId(1555); + static constexpr const TSymbolUniqueId pt01X = TSymbolUniqueId(1556); + static constexpr const TSymbolUniqueId imageSize_ImageCube1 = TSymbolUniqueId(1557); + static constexpr const TSymbolUniqueId pt01C = TSymbolUniqueId(1558); + static constexpr const TSymbolUniqueId imageSize_IImageCube1 = TSymbolUniqueId(1559); + static constexpr const TSymbolUniqueId pt01N = TSymbolUniqueId(1560); + static constexpr const TSymbolUniqueId imageSize_UImageCube1 = TSymbolUniqueId(1561); + static constexpr const TSymbolUniqueId pt01Y = TSymbolUniqueId(1562); + static constexpr const TSymbolUniqueId imageSize_ImageCubeArray1 = TSymbolUniqueId(1563); + static constexpr const TSymbolUniqueId pt01H = TSymbolUniqueId(1564); + static constexpr const TSymbolUniqueId imageSize_IImageCubeArray1 = TSymbolUniqueId(1565); + static constexpr const TSymbolUniqueId pt01S = TSymbolUniqueId(1566); + static constexpr const TSymbolUniqueId imageSize_UImageCubeArray1 = TSymbolUniqueId(1567); + static constexpr const TSymbolUniqueId pt01d = TSymbolUniqueId(1568); + static constexpr const TSymbolUniqueId imageSizeExt_ImageCubeArray1 = TSymbolUniqueId(1569); + static constexpr const TSymbolUniqueId imageSizeExt_IImageCubeArray1 = TSymbolUniqueId(1570); + static constexpr const TSymbolUniqueId imageSizeExt_UImageCubeArray1 = TSymbolUniqueId(1571); + static constexpr const TSymbolUniqueId imageSize_ImageBuffer1 = TSymbolUniqueId(1572); + static constexpr const TSymbolUniqueId pt01J = TSymbolUniqueId(1573); + static constexpr const TSymbolUniqueId imageSize_IImageBuffer1 = TSymbolUniqueId(1574); + static constexpr const TSymbolUniqueId pt01U = TSymbolUniqueId(1575); + static constexpr const TSymbolUniqueId imageSize_UImageBuffer1 = TSymbolUniqueId(1576); + static constexpr const TSymbolUniqueId pt01f = TSymbolUniqueId(1577); + static constexpr const TSymbolUniqueId imageSizeExt_ImageBuffer1 = TSymbolUniqueId(1578); + static constexpr const TSymbolUniqueId imageSizeExt_IImageBuffer1 = TSymbolUniqueId(1579); + static constexpr const TSymbolUniqueId imageSizeExt_UImageBuffer1 = TSymbolUniqueId(1580); + static constexpr const TSymbolUniqueId imageSize_Image1D1 = TSymbolUniqueId(1581); + static constexpr const TSymbolUniqueId pt01D = TSymbolUniqueId(1582); + static constexpr const TSymbolUniqueId imageSize_IImage1D1 = TSymbolUniqueId(1583); + static constexpr const TSymbolUniqueId pt01O = TSymbolUniqueId(1584); + static constexpr const TSymbolUniqueId imageSize_UImage1D1 = TSymbolUniqueId(1585); + static constexpr const TSymbolUniqueId pt01Z = TSymbolUniqueId(1586); + static constexpr const TSymbolUniqueId imageSize_ImageRect1 = TSymbolUniqueId(1587); + static constexpr const TSymbolUniqueId pt01I = TSymbolUniqueId(1588); + static constexpr const TSymbolUniqueId imageSize_IImageRect1 = TSymbolUniqueId(1589); + static constexpr const TSymbolUniqueId pt01T = TSymbolUniqueId(1590); + static constexpr const TSymbolUniqueId imageSize_UImageRect1 = TSymbolUniqueId(1591); + static constexpr const TSymbolUniqueId pt01e = TSymbolUniqueId(1592); + static constexpr const TSymbolUniqueId imageSize_Image1DArray1 = TSymbolUniqueId(1593); + static constexpr const TSymbolUniqueId pt01E = TSymbolUniqueId(1594); + static constexpr const TSymbolUniqueId imageSize_IImage1DArray1 = TSymbolUniqueId(1595); + static constexpr const TSymbolUniqueId pt01P = TSymbolUniqueId(1596); + static constexpr const TSymbolUniqueId imageSize_UImage1DArray1 = TSymbolUniqueId(1597); + static constexpr const TSymbolUniqueId pt01a = TSymbolUniqueId(1598); + static constexpr const TSymbolUniqueId imageSize_Image2DMS1 = TSymbolUniqueId(1599); + static constexpr const TSymbolUniqueId pt01F = TSymbolUniqueId(1600); + static constexpr const TSymbolUniqueId imageSize_IImage2DMS1 = TSymbolUniqueId(1601); + static constexpr const TSymbolUniqueId pt01Q = TSymbolUniqueId(1602); + static constexpr const TSymbolUniqueId imageSize_UImage2DMS1 = TSymbolUniqueId(1603); + static constexpr const TSymbolUniqueId pt01b = TSymbolUniqueId(1604); + static constexpr const TSymbolUniqueId imageSize_Image2DMSArray1 = TSymbolUniqueId(1605); + static constexpr const TSymbolUniqueId pt01G = TSymbolUniqueId(1606); + static constexpr const TSymbolUniqueId imageSize_IImage2DMSArray1 = TSymbolUniqueId(1607); + static constexpr const TSymbolUniqueId pt01R = TSymbolUniqueId(1608); + static constexpr const TSymbolUniqueId imageSize_UImage2DMSArray1 = TSymbolUniqueId(1609); + static constexpr const TSymbolUniqueId pt01c = TSymbolUniqueId(1610); + static constexpr const TSymbolUniqueId imageSamples_Image2DMS1 = TSymbolUniqueId(1611); + static constexpr const TSymbolUniqueId imageSamples_IImage2DMS1 = TSymbolUniqueId(1612); + static constexpr const TSymbolUniqueId imageSamples_UImage2DMS1 = TSymbolUniqueId(1613); + static constexpr const TSymbolUniqueId imageSamples_Image2DMSArray1 = TSymbolUniqueId(1614); + static constexpr const TSymbolUniqueId imageSamples_IImage2DMSArray1 = TSymbolUniqueId(1615); + static constexpr const TSymbolUniqueId imageSamples_UImage2DMSArray1 = TSymbolUniqueId(1616); + static constexpr const TSymbolUniqueId imageStore_Image2D1_Int2_Float4 = TSymbolUniqueId(1617); + static constexpr const TSymbolUniqueId imageStore_IImage2D1_Int2_Int4 = TSymbolUniqueId(1618); + static constexpr const TSymbolUniqueId imageStore_UImage2D1_Int2_UInt4 = TSymbolUniqueId(1619); + static constexpr const TSymbolUniqueId imageStore_Image3D1_Int3_Float4 = TSymbolUniqueId(1620); + static constexpr const TSymbolUniqueId imageStore_IImage3D1_Int3_Int4 = TSymbolUniqueId(1621); + static constexpr const TSymbolUniqueId imageStore_UImage3D1_Int3_UInt4 = TSymbolUniqueId(1622); + static constexpr const TSymbolUniqueId imageStore_Image2DArray1_Int3_Float4 = + TSymbolUniqueId(1623); + static constexpr const TSymbolUniqueId imageStore_IImage2DArray1_Int3_Int4 = + TSymbolUniqueId(1624); + static constexpr const TSymbolUniqueId imageStore_UImage2DArray1_Int3_UInt4 = + TSymbolUniqueId(1625); + static constexpr const TSymbolUniqueId imageStore_ImageCube1_Int3_Float4 = + TSymbolUniqueId(1626); + static constexpr const TSymbolUniqueId imageStore_IImageCube1_Int3_Int4 = TSymbolUniqueId(1627); + static constexpr const TSymbolUniqueId imageStore_UImageCube1_Int3_UInt4 = + TSymbolUniqueId(1628); + static constexpr const TSymbolUniqueId imageStore_ImageCubeArray1_Int3_Float4 = + TSymbolUniqueId(1629); + static constexpr const TSymbolUniqueId imageStore_IImageCubeArray1_Int3_Int4 = + TSymbolUniqueId(1630); + static constexpr const TSymbolUniqueId imageStore_UImageCubeArray1_Int3_UInt4 = + TSymbolUniqueId(1631); + static constexpr const TSymbolUniqueId imageStoreExt_ImageCubeArray1_Int3_Float4 = + TSymbolUniqueId(1632); + static constexpr const TSymbolUniqueId imageStoreExt_IImageCubeArray1_Int3_Int4 = + TSymbolUniqueId(1633); + static constexpr const TSymbolUniqueId imageStoreExt_UImageCubeArray1_Int3_UInt4 = + TSymbolUniqueId(1634); + static constexpr const TSymbolUniqueId imageStore_ImageBuffer1_Int1_Float4 = + TSymbolUniqueId(1635); + static constexpr const TSymbolUniqueId imageStore_IImageBuffer1_Int1_Int4 = + TSymbolUniqueId(1636); + static constexpr const TSymbolUniqueId imageStore_UImageBuffer1_Int1_UInt4 = + TSymbolUniqueId(1637); + static constexpr const TSymbolUniqueId imageStoreExt_ImageBuffer1_Int1_Float4 = + TSymbolUniqueId(1638); + static constexpr const TSymbolUniqueId imageStoreExt_IImageBuffer1_Int1_Int4 = + TSymbolUniqueId(1639); + static constexpr const TSymbolUniqueId imageStoreExt_UImageBuffer1_Int1_UInt4 = + TSymbolUniqueId(1640); + static constexpr const TSymbolUniqueId imageStore_Image1D1_Int1_Float4 = TSymbolUniqueId(1641); + static constexpr const TSymbolUniqueId imageStore_IImage1D1_Int1_Int4 = TSymbolUniqueId(1642); + static constexpr const TSymbolUniqueId imageStore_UImage1D1_Int1_UInt4 = TSymbolUniqueId(1643); + static constexpr const TSymbolUniqueId imageStore_Image1DArray1_Int2_Float4 = + TSymbolUniqueId(1644); + static constexpr const TSymbolUniqueId imageStore_IImage1DArray1_Int2_Int4 = + TSymbolUniqueId(1645); + static constexpr const TSymbolUniqueId imageStore_UImage1DArray1_Int2_UInt4 = + TSymbolUniqueId(1646); + static constexpr const TSymbolUniqueId imageStore_ImageRect1_Int2_Float4 = + TSymbolUniqueId(1647); + static constexpr const TSymbolUniqueId imageStore_IImageRect1_Int2_Int4 = TSymbolUniqueId(1648); + static constexpr const TSymbolUniqueId imageStore_UImageRect1_Int2_UInt4 = + TSymbolUniqueId(1649); + static constexpr const TSymbolUniqueId imageStore_Image2DMS1_Int2_Int1_Float4 = + TSymbolUniqueId(1650); + static constexpr const TSymbolUniqueId imageStore_IImage2DMS1_Int2_Int1_Int4 = + TSymbolUniqueId(1651); + static constexpr const TSymbolUniqueId imageStore_UImage2DMS1_Int2_Int1_UInt4 = + TSymbolUniqueId(1652); + static constexpr const TSymbolUniqueId imageStore_Image2DMSArray1_Int3_Int1_Float4 = + TSymbolUniqueId(1653); + static constexpr const TSymbolUniqueId imageStore_IImage2DMSArray1_Int3_Int1_Int4 = + TSymbolUniqueId(1654); + static constexpr const TSymbolUniqueId imageStore_UImage2DMSArray1_Int3_Int1_UInt4 = + TSymbolUniqueId(1655); + static constexpr const TSymbolUniqueId imageLoad_Image2D1_Int2 = TSymbolUniqueId(1656); + static constexpr const TSymbolUniqueId imageLoad_IImage2D1_Int2 = TSymbolUniqueId(1657); + static constexpr const TSymbolUniqueId imageLoad_UImage2D1_Int2 = TSymbolUniqueId(1658); + static constexpr const TSymbolUniqueId imageLoad_Image3D1_Int3 = TSymbolUniqueId(1659); + static constexpr const TSymbolUniqueId imageLoad_IImage3D1_Int3 = TSymbolUniqueId(1660); + static constexpr const TSymbolUniqueId imageLoad_UImage3D1_Int3 = TSymbolUniqueId(1661); + static constexpr const TSymbolUniqueId imageLoad_Image2DArray1_Int3 = TSymbolUniqueId(1662); + static constexpr const TSymbolUniqueId imageLoad_IImage2DArray1_Int3 = TSymbolUniqueId(1663); + static constexpr const TSymbolUniqueId imageLoad_UImage2DArray1_Int3 = TSymbolUniqueId(1664); + static constexpr const TSymbolUniqueId imageLoad_ImageCube1_Int3 = TSymbolUniqueId(1665); + static constexpr const TSymbolUniqueId imageLoad_IImageCube1_Int3 = TSymbolUniqueId(1666); + static constexpr const TSymbolUniqueId imageLoad_UImageCube1_Int3 = TSymbolUniqueId(1667); + static constexpr const TSymbolUniqueId imageLoad_ImageCubeArray1_Int3 = TSymbolUniqueId(1668); + static constexpr const TSymbolUniqueId imageLoad_IImageCubeArray1_Int3 = TSymbolUniqueId(1669); + static constexpr const TSymbolUniqueId imageLoad_UImageCubeArray1_Int3 = TSymbolUniqueId(1670); + static constexpr const TSymbolUniqueId imageLoadExt_ImageCubeArray1_Int3 = + TSymbolUniqueId(1671); + static constexpr const TSymbolUniqueId imageLoadExt_IImageCubeArray1_Int3 = + TSymbolUniqueId(1672); + static constexpr const TSymbolUniqueId imageLoadExt_UImageCubeArray1_Int3 = + TSymbolUniqueId(1673); + static constexpr const TSymbolUniqueId imageLoad_ImageBuffer1_Int1 = TSymbolUniqueId(1674); + static constexpr const TSymbolUniqueId imageLoad_IImageBuffer1_Int1 = TSymbolUniqueId(1675); + static constexpr const TSymbolUniqueId imageLoad_UImageBuffer1_Int1 = TSymbolUniqueId(1676); + static constexpr const TSymbolUniqueId imageLoadExt_ImageBuffer1_Int1 = TSymbolUniqueId(1677); + static constexpr const TSymbolUniqueId imageLoadExt_IImageBuffer1_Int1 = TSymbolUniqueId(1678); + static constexpr const TSymbolUniqueId imageLoadExt_UImageBuffer1_Int1 = TSymbolUniqueId(1679); + static constexpr const TSymbolUniqueId imageLoad_Image1D1_Int1 = TSymbolUniqueId(1680); + static constexpr const TSymbolUniqueId imageLoad_IImage1D1_Int1 = TSymbolUniqueId(1681); + static constexpr const TSymbolUniqueId imageLoad_UImage1D1_Int1 = TSymbolUniqueId(1682); + static constexpr const TSymbolUniqueId imageLoad_Image1DArray1_Int2 = TSymbolUniqueId(1683); + static constexpr const TSymbolUniqueId imageLoad_IImage1DArray1_Int2 = TSymbolUniqueId(1684); + static constexpr const TSymbolUniqueId imageLoad_UImage1DArray1_Int2 = TSymbolUniqueId(1685); + static constexpr const TSymbolUniqueId imageLoad_ImageRect1_Int2 = TSymbolUniqueId(1686); + static constexpr const TSymbolUniqueId imageLoad_IImageRect1_Int2 = TSymbolUniqueId(1687); + static constexpr const TSymbolUniqueId imageLoad_UImageRect1_Int2 = TSymbolUniqueId(1688); + static constexpr const TSymbolUniqueId imageLoad_Image2DMS1_Int2_Int1 = TSymbolUniqueId(1689); + static constexpr const TSymbolUniqueId imageLoad_IImage2DMS1_Int2_Int1 = TSymbolUniqueId(1690); + static constexpr const TSymbolUniqueId imageLoad_UImage2DMS1_Int2_Int1 = TSymbolUniqueId(1691); + static constexpr const TSymbolUniqueId imageLoad_Image2DMSArray1_Int3_Int1 = + TSymbolUniqueId(1692); + static constexpr const TSymbolUniqueId imageLoad_IImage2DMSArray1_Int3_Int1 = + TSymbolUniqueId(1693); + static constexpr const TSymbolUniqueId imageLoad_UImage2DMSArray1_Int3_Int1 = + TSymbolUniqueId(1694); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2D1_Int2_UInt1 = + TSymbolUniqueId(1695); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(1696); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(1697); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image3D1_Int3_UInt1 = + TSymbolUniqueId(1698); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(1699); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(1700); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(1701); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(1702); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(1703); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1704); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1705); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1706); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(1707); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(1708); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(1709); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1710); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1711); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1712); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image1D1_Int1_UInt1 = + TSymbolUniqueId(1713); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(1714); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(1715); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(1716); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(1717); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(1718); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(1719); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(1720); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(1721); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1722); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1723); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1724); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1725); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1726); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1727); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2D1_Int2_Int1 = + TSymbolUniqueId(1728); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2D1_Int2_Int1 = + TSymbolUniqueId(1729); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2D1_Int2_Int1 = + TSymbolUniqueId(1730); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image3D1_Int3_Int1 = + TSymbolUniqueId(1731); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage3D1_Int3_Int1 = + TSymbolUniqueId(1732); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage3D1_Int3_Int1 = + TSymbolUniqueId(1733); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageCube1_Int3_Int1 = + TSymbolUniqueId(1734); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageCube1_Int3_Int1 = + TSymbolUniqueId(1735); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageCube1_Int3_Int1 = + TSymbolUniqueId(1736); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(1737); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(1738); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(1739); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(1740); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(1741); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(1742); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(1743); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(1744); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(1745); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image1D1_Int1_Int1 = + TSymbolUniqueId(1746); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage1D1_Int1_Int1 = + TSymbolUniqueId(1747); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage1D1_Int1_Int1 = + TSymbolUniqueId(1748); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(1749); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(1750); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(1751); + static constexpr const TSymbolUniqueId imageAtomicAdd_ImageRect1_Int2_Int1 = + TSymbolUniqueId(1752); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImageRect1_Int2_Int1 = + TSymbolUniqueId(1753); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImageRect1_Int2_Int1 = + TSymbolUniqueId(1754); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(1755); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(1756); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(1757); + static constexpr const TSymbolUniqueId imageAtomicAdd_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(1758); + static constexpr const TSymbolUniqueId imageAtomicAdd_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(1759); + static constexpr const TSymbolUniqueId imageAtomicAdd_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(1760); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2D1_Int2_UInt1 = + TSymbolUniqueId(1761); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(1762); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(1763); + static constexpr const TSymbolUniqueId imageAtomicMin_Image3D1_Int3_UInt1 = + TSymbolUniqueId(1764); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(1765); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(1766); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(1767); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(1768); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(1769); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1770); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1771); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1772); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(1773); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(1774); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(1775); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1776); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1777); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1778); + static constexpr const TSymbolUniqueId imageAtomicMin_Image1D1_Int1_UInt1 = + TSymbolUniqueId(1779); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(1780); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(1781); + static constexpr const TSymbolUniqueId imageAtomicMin_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(1782); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(1783); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(1784); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(1785); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(1786); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(1787); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1788); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1789); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1790); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1791); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1792); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1793); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2D1_Int2_Int1 = + TSymbolUniqueId(1794); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2D1_Int2_Int1 = + TSymbolUniqueId(1795); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2D1_Int2_Int1 = + TSymbolUniqueId(1796); + static constexpr const TSymbolUniqueId imageAtomicMin_Image3D1_Int3_Int1 = + TSymbolUniqueId(1797); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage3D1_Int3_Int1 = + TSymbolUniqueId(1798); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage3D1_Int3_Int1 = + TSymbolUniqueId(1799); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageCube1_Int3_Int1 = + TSymbolUniqueId(1800); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageCube1_Int3_Int1 = + TSymbolUniqueId(1801); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageCube1_Int3_Int1 = + TSymbolUniqueId(1802); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(1803); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(1804); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(1805); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(1806); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(1807); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(1808); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(1809); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(1810); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(1811); + static constexpr const TSymbolUniqueId imageAtomicMin_Image1D1_Int1_Int1 = + TSymbolUniqueId(1812); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage1D1_Int1_Int1 = + TSymbolUniqueId(1813); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage1D1_Int1_Int1 = + TSymbolUniqueId(1814); + static constexpr const TSymbolUniqueId imageAtomicMin_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(1815); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(1816); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(1817); + static constexpr const TSymbolUniqueId imageAtomicMin_ImageRect1_Int2_Int1 = + TSymbolUniqueId(1818); + static constexpr const TSymbolUniqueId imageAtomicMin_IImageRect1_Int2_Int1 = + TSymbolUniqueId(1819); + static constexpr const TSymbolUniqueId imageAtomicMin_UImageRect1_Int2_Int1 = + TSymbolUniqueId(1820); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(1821); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(1822); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(1823); + static constexpr const TSymbolUniqueId imageAtomicMin_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(1824); + static constexpr const TSymbolUniqueId imageAtomicMin_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(1825); + static constexpr const TSymbolUniqueId imageAtomicMin_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(1826); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2D1_Int2_UInt1 = + TSymbolUniqueId(1827); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(1828); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(1829); + static constexpr const TSymbolUniqueId imageAtomicMax_Image3D1_Int3_UInt1 = + TSymbolUniqueId(1830); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(1831); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(1832); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(1833); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(1834); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(1835); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1836); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1837); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1838); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(1839); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(1840); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(1841); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1842); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1843); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1844); + static constexpr const TSymbolUniqueId imageAtomicMax_Image1D1_Int1_UInt1 = + TSymbolUniqueId(1845); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(1846); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(1847); + static constexpr const TSymbolUniqueId imageAtomicMax_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(1848); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(1849); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(1850); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(1851); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(1852); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(1853); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1854); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1855); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1856); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1857); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1858); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1859); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2D1_Int2_Int1 = + TSymbolUniqueId(1860); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2D1_Int2_Int1 = + TSymbolUniqueId(1861); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2D1_Int2_Int1 = + TSymbolUniqueId(1862); + static constexpr const TSymbolUniqueId imageAtomicMax_Image3D1_Int3_Int1 = + TSymbolUniqueId(1863); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage3D1_Int3_Int1 = + TSymbolUniqueId(1864); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage3D1_Int3_Int1 = + TSymbolUniqueId(1865); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageCube1_Int3_Int1 = + TSymbolUniqueId(1866); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageCube1_Int3_Int1 = + TSymbolUniqueId(1867); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageCube1_Int3_Int1 = + TSymbolUniqueId(1868); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(1869); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(1870); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(1871); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(1872); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(1873); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(1874); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(1875); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(1876); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(1877); + static constexpr const TSymbolUniqueId imageAtomicMax_Image1D1_Int1_Int1 = + TSymbolUniqueId(1878); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage1D1_Int1_Int1 = + TSymbolUniqueId(1879); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage1D1_Int1_Int1 = + TSymbolUniqueId(1880); + static constexpr const TSymbolUniqueId imageAtomicMax_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(1881); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(1882); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(1883); + static constexpr const TSymbolUniqueId imageAtomicMax_ImageRect1_Int2_Int1 = + TSymbolUniqueId(1884); + static constexpr const TSymbolUniqueId imageAtomicMax_IImageRect1_Int2_Int1 = + TSymbolUniqueId(1885); + static constexpr const TSymbolUniqueId imageAtomicMax_UImageRect1_Int2_Int1 = + TSymbolUniqueId(1886); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(1887); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(1888); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(1889); + static constexpr const TSymbolUniqueId imageAtomicMax_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(1890); + static constexpr const TSymbolUniqueId imageAtomicMax_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(1891); + static constexpr const TSymbolUniqueId imageAtomicMax_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(1892); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2D1_Int2_UInt1 = + TSymbolUniqueId(1893); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(1894); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(1895); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image3D1_Int3_UInt1 = + TSymbolUniqueId(1896); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(1897); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(1898); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(1899); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(1900); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(1901); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1902); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1903); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1904); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(1905); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(1906); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(1907); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1908); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1909); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1910); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image1D1_Int1_UInt1 = + TSymbolUniqueId(1911); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(1912); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(1913); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(1914); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(1915); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(1916); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(1917); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(1918); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(1919); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1920); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1921); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1922); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1923); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1924); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1925); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2D1_Int2_Int1 = + TSymbolUniqueId(1926); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2D1_Int2_Int1 = + TSymbolUniqueId(1927); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2D1_Int2_Int1 = + TSymbolUniqueId(1928); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image3D1_Int3_Int1 = + TSymbolUniqueId(1929); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage3D1_Int3_Int1 = + TSymbolUniqueId(1930); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage3D1_Int3_Int1 = + TSymbolUniqueId(1931); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCube1_Int3_Int1 = + TSymbolUniqueId(1932); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCube1_Int3_Int1 = + TSymbolUniqueId(1933); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCube1_Int3_Int1 = + TSymbolUniqueId(1934); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(1935); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(1936); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(1937); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(1938); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(1939); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(1940); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(1941); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(1942); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(1943); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image1D1_Int1_Int1 = + TSymbolUniqueId(1944); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage1D1_Int1_Int1 = + TSymbolUniqueId(1945); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage1D1_Int1_Int1 = + TSymbolUniqueId(1946); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(1947); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(1948); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(1949); + static constexpr const TSymbolUniqueId imageAtomicAnd_ImageRect1_Int2_Int1 = + TSymbolUniqueId(1950); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImageRect1_Int2_Int1 = + TSymbolUniqueId(1951); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImageRect1_Int2_Int1 = + TSymbolUniqueId(1952); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(1953); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(1954); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(1955); + static constexpr const TSymbolUniqueId imageAtomicAnd_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(1956); + static constexpr const TSymbolUniqueId imageAtomicAnd_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(1957); + static constexpr const TSymbolUniqueId imageAtomicAnd_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(1958); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2D1_Int2_UInt1 = + TSymbolUniqueId(1959); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(1960); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(1961); + static constexpr const TSymbolUniqueId imageAtomicOr_Image3D1_Int3_UInt1 = + TSymbolUniqueId(1962); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(1963); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(1964); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(1965); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(1966); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(1967); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1968); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1969); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(1970); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(1971); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(1972); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(1973); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1974); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1975); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(1976); + static constexpr const TSymbolUniqueId imageAtomicOr_Image1D1_Int1_UInt1 = + TSymbolUniqueId(1977); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(1978); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(1979); + static constexpr const TSymbolUniqueId imageAtomicOr_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(1980); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(1981); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(1982); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(1983); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(1984); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(1985); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1986); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1987); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(1988); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1989); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1990); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(1991); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2D1_Int2_Int1 = TSymbolUniqueId(1992); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2D1_Int2_Int1 = + TSymbolUniqueId(1993); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2D1_Int2_Int1 = + TSymbolUniqueId(1994); + static constexpr const TSymbolUniqueId imageAtomicOr_Image3D1_Int3_Int1 = TSymbolUniqueId(1995); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage3D1_Int3_Int1 = + TSymbolUniqueId(1996); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage3D1_Int3_Int1 = + TSymbolUniqueId(1997); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageCube1_Int3_Int1 = + TSymbolUniqueId(1998); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageCube1_Int3_Int1 = + TSymbolUniqueId(1999); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageCube1_Int3_Int1 = + TSymbolUniqueId(2000); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2001); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2002); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2003); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(2004); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2005); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2006); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2007); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2008); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2009); + static constexpr const TSymbolUniqueId imageAtomicOr_Image1D1_Int1_Int1 = TSymbolUniqueId(2010); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage1D1_Int1_Int1 = + TSymbolUniqueId(2011); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage1D1_Int1_Int1 = + TSymbolUniqueId(2012); + static constexpr const TSymbolUniqueId imageAtomicOr_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(2013); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2014); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2015); + static constexpr const TSymbolUniqueId imageAtomicOr_ImageRect1_Int2_Int1 = + TSymbolUniqueId(2016); + static constexpr const TSymbolUniqueId imageAtomicOr_IImageRect1_Int2_Int1 = + TSymbolUniqueId(2017); + static constexpr const TSymbolUniqueId imageAtomicOr_UImageRect1_Int2_Int1 = + TSymbolUniqueId(2018); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2019); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2020); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2021); + static constexpr const TSymbolUniqueId imageAtomicOr_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2022); + static constexpr const TSymbolUniqueId imageAtomicOr_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2023); + static constexpr const TSymbolUniqueId imageAtomicOr_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2024); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2D1_Int2_UInt1 = + TSymbolUniqueId(2025); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(2026); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(2027); + static constexpr const TSymbolUniqueId imageAtomicXor_Image3D1_Int3_UInt1 = + TSymbolUniqueId(2028); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(2029); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(2030); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(2031); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(2032); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(2033); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2034); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2035); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2036); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(2037); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2038); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2039); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2040); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2041); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2042); + static constexpr const TSymbolUniqueId imageAtomicXor_Image1D1_Int1_UInt1 = + TSymbolUniqueId(2043); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(2044); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(2045); + static constexpr const TSymbolUniqueId imageAtomicXor_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(2046); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2047); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2048); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(2049); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(2050); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(2051); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2052); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2053); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2054); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2055); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2056); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2057); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2D1_Int2_Int1 = + TSymbolUniqueId(2058); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2D1_Int2_Int1 = + TSymbolUniqueId(2059); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2D1_Int2_Int1 = + TSymbolUniqueId(2060); + static constexpr const TSymbolUniqueId imageAtomicXor_Image3D1_Int3_Int1 = + TSymbolUniqueId(2061); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage3D1_Int3_Int1 = + TSymbolUniqueId(2062); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage3D1_Int3_Int1 = + TSymbolUniqueId(2063); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageCube1_Int3_Int1 = + TSymbolUniqueId(2064); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageCube1_Int3_Int1 = + TSymbolUniqueId(2065); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageCube1_Int3_Int1 = + TSymbolUniqueId(2066); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2067); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2068); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2069); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(2070); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2071); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2072); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2073); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2074); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2075); + static constexpr const TSymbolUniqueId imageAtomicXor_Image1D1_Int1_Int1 = + TSymbolUniqueId(2076); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage1D1_Int1_Int1 = + TSymbolUniqueId(2077); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage1D1_Int1_Int1 = + TSymbolUniqueId(2078); + static constexpr const TSymbolUniqueId imageAtomicXor_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(2079); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2080); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2081); + static constexpr const TSymbolUniqueId imageAtomicXor_ImageRect1_Int2_Int1 = + TSymbolUniqueId(2082); + static constexpr const TSymbolUniqueId imageAtomicXor_IImageRect1_Int2_Int1 = + TSymbolUniqueId(2083); + static constexpr const TSymbolUniqueId imageAtomicXor_UImageRect1_Int2_Int1 = + TSymbolUniqueId(2084); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2085); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2086); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2087); + static constexpr const TSymbolUniqueId imageAtomicXor_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2088); + static constexpr const TSymbolUniqueId imageAtomicXor_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2089); + static constexpr const TSymbolUniqueId imageAtomicXor_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2090); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2D1_Int2_UInt1 = + TSymbolUniqueId(2091); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(2092); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(2093); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image3D1_Int3_UInt1 = + TSymbolUniqueId(2094); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(2095); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(2096); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(2097); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(2098); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(2099); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2100); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2101); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2102); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(2103); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2104); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2105); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2106); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2107); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2108); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image1D1_Int1_UInt1 = + TSymbolUniqueId(2109); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(2110); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(2111); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(2112); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2113); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2114); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(2115); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(2116); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(2117); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2118); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2119); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2120); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2121); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2122); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2123); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2D1_Int2_Int1 = + TSymbolUniqueId(2124); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2D1_Int2_Int1 = + TSymbolUniqueId(2125); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2D1_Int2_Int1 = + TSymbolUniqueId(2126); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image3D1_Int3_Int1 = + TSymbolUniqueId(2127); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage3D1_Int3_Int1 = + TSymbolUniqueId(2128); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage3D1_Int3_Int1 = + TSymbolUniqueId(2129); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCube1_Int3_Int1 = + TSymbolUniqueId(2130); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCube1_Int3_Int1 = + TSymbolUniqueId(2131); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCube1_Int3_Int1 = + TSymbolUniqueId(2132); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2133); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2134); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2135); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(2136); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2137); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2138); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2139); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2140); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2141); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image1D1_Int1_Int1 = + TSymbolUniqueId(2142); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage1D1_Int1_Int1 = + TSymbolUniqueId(2143); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage1D1_Int1_Int1 = + TSymbolUniqueId(2144); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(2145); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2146); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2147); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageRect1_Int2_Int1 = + TSymbolUniqueId(2148); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageRect1_Int2_Int1 = + TSymbolUniqueId(2149); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageRect1_Int2_Int1 = + TSymbolUniqueId(2150); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2151); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2152); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2153); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2154); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2155); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2156); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2D1_Int2_Float1 = + TSymbolUniqueId(2157); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2D1_Int2_Float1 = + TSymbolUniqueId(2158); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2D1_Int2_Float1 = + TSymbolUniqueId(2159); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image3D1_Int3_Float1 = + TSymbolUniqueId(2160); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage3D1_Int3_Float1 = + TSymbolUniqueId(2161); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage3D1_Int3_Float1 = + TSymbolUniqueId(2162); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCube1_Int3_Float1 = + TSymbolUniqueId(2163); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCube1_Int3_Float1 = + TSymbolUniqueId(2164); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCube1_Int3_Float1 = + TSymbolUniqueId(2165); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageBuffer1_Int1_Float1 = + TSymbolUniqueId(2166); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageBuffer1_Int1_Float1 = + TSymbolUniqueId(2167); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageBuffer1_Int1_Float1 = + TSymbolUniqueId(2168); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DArray1_Int3_Float1 = + TSymbolUniqueId(2169); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DArray1_Int3_Float1 = + TSymbolUniqueId(2170); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DArray1_Int3_Float1 = + TSymbolUniqueId(2171); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageCubeArray1_Int3_Float1 = + TSymbolUniqueId(2172); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageCubeArray1_Int3_Float1 = + TSymbolUniqueId(2173); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageCubeArray1_Int3_Float1 = + TSymbolUniqueId(2174); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image1D1_Int1_Float1 = + TSymbolUniqueId(2175); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage1D1_Int1_Float1 = + TSymbolUniqueId(2176); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage1D1_Int1_Float1 = + TSymbolUniqueId(2177); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image1DArray1_Int2_Float1 = + TSymbolUniqueId(2178); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage1DArray1_Int2_Float1 = + TSymbolUniqueId(2179); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage1DArray1_Int2_Float1 = + TSymbolUniqueId(2180); + static constexpr const TSymbolUniqueId imageAtomicExchange_ImageRect1_Int2_Float1 = + TSymbolUniqueId(2181); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImageRect1_Int2_Float1 = + TSymbolUniqueId(2182); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImageRect1_Int2_Float1 = + TSymbolUniqueId(2183); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMS1_Int2_Int1_Float1 = + TSymbolUniqueId(2184); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMS1_Int2_Int1_Float1 = + TSymbolUniqueId(2185); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMS1_Int2_Int1_Float1 = + TSymbolUniqueId(2186); + static constexpr const TSymbolUniqueId imageAtomicExchange_Image2DMSArray1_Int3_Int1_Float1 = + TSymbolUniqueId(2187); + static constexpr const TSymbolUniqueId imageAtomicExchange_IImage2DMSArray1_Int3_Int1_Float1 = + TSymbolUniqueId(2188); + static constexpr const TSymbolUniqueId imageAtomicExchange_UImage2DMSArray1_Int3_Int1_Float1 = + TSymbolUniqueId(2189); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2D1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2190); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2D1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2191); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2D1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2192); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image3D1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2193); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage3D1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2194); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage3D1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2195); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCube1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2196); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCube1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2197); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCube1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2198); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageBuffer1_Int1_UInt1_UInt1 = + TSymbolUniqueId(2199); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageBuffer1_Int1_UInt1_UInt1 = + TSymbolUniqueId(2200); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageBuffer1_Int1_UInt1_UInt1 = + TSymbolUniqueId(2201); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2202); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2DArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2203); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2DArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2204); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCubeArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2205); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCubeArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2206); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCubeArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2207); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image1D1_Int1_UInt1_UInt1 = + TSymbolUniqueId(2208); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage1D1_Int1_UInt1_UInt1 = + TSymbolUniqueId(2209); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage1D1_Int1_UInt1_UInt1 = + TSymbolUniqueId(2210); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image1DArray1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2211); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage1DArray1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2212); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage1DArray1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2213); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageRect1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2214); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageRect1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2215); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageRect1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2216); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DMS1_Int2_Int1_UInt1_UInt1 = + TSymbolUniqueId(2217); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2DMS1_Int2_Int1_UInt1_UInt1 = + TSymbolUniqueId(2218); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2DMS1_Int2_Int1_UInt1_UInt1 = + TSymbolUniqueId(2219); + static constexpr const TSymbolUniqueId + imageAtomicCompSwap_Image2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(2220); + static constexpr const TSymbolUniqueId + imageAtomicCompSwap_IImage2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(2221); + static constexpr const TSymbolUniqueId + imageAtomicCompSwap_UImage2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(2222); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2D1_Int2_Int1_Int1 = + TSymbolUniqueId(2223); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2D1_Int2_Int1_Int1 = + TSymbolUniqueId(2224); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2D1_Int2_Int1_Int1 = + TSymbolUniqueId(2225); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image3D1_Int3_Int1_Int1 = + TSymbolUniqueId(2226); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage3D1_Int3_Int1_Int1 = + TSymbolUniqueId(2227); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage3D1_Int3_Int1_Int1 = + TSymbolUniqueId(2228); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCube1_Int3_Int1_Int1 = + TSymbolUniqueId(2229); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCube1_Int3_Int1_Int1 = + TSymbolUniqueId(2230); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCube1_Int3_Int1_Int1 = + TSymbolUniqueId(2231); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageBuffer1_Int1_Int1_Int1 = + TSymbolUniqueId(2232); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageBuffer1_Int1_Int1_Int1 = + TSymbolUniqueId(2233); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageBuffer1_Int1_Int1_Int1 = + TSymbolUniqueId(2234); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2235); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2DArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2236); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2DArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2237); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageCubeArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2238); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageCubeArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2239); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageCubeArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2240); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image1D1_Int1_Int1_Int1 = + TSymbolUniqueId(2241); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage1D1_Int1_Int1_Int1 = + TSymbolUniqueId(2242); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage1D1_Int1_Int1_Int1 = + TSymbolUniqueId(2243); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(2244); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(2245); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(2246); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_ImageRect1_Int2_Int1_Int1 = + TSymbolUniqueId(2247); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImageRect1_Int2_Int1_Int1 = + TSymbolUniqueId(2248); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImageRect1_Int2_Int1_Int1 = + TSymbolUniqueId(2249); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DMS1_Int2_Int1_Int1_Int1 = + TSymbolUniqueId(2250); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_IImage2DMS1_Int2_Int1_Int1_Int1 = + TSymbolUniqueId(2251); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_UImage2DMS1_Int2_Int1_Int1_Int1 = + TSymbolUniqueId(2252); + static constexpr const TSymbolUniqueId imageAtomicCompSwap_Image2DMSArray1_Int3_Int1_Int1_Int1 = + TSymbolUniqueId(2253); + static constexpr const TSymbolUniqueId + imageAtomicCompSwap_IImage2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(2254); + static constexpr const TSymbolUniqueId + imageAtomicCompSwap_UImage2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(2255); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2D1_Int2_UInt1 = + TSymbolUniqueId(2256); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(2257); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(2258); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image3D1_Int3_UInt1 = + TSymbolUniqueId(2259); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(2260); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(2261); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(2262); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(2263); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(2264); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2265); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2266); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2267); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(2268); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2269); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2270); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2271); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2272); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2273); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image1D1_Int1_UInt1 = + TSymbolUniqueId(2274); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(2275); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(2276); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(2277); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2278); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2279); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(2280); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(2281); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(2282); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2283); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2284); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2285); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2286); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2287); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2288); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2D1_Int2_Int1 = + TSymbolUniqueId(2289); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2D1_Int2_Int1 = + TSymbolUniqueId(2290); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2D1_Int2_Int1 = + TSymbolUniqueId(2291); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image3D1_Int3_Int1 = + TSymbolUniqueId(2292); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage3D1_Int3_Int1 = + TSymbolUniqueId(2293); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage3D1_Int3_Int1 = + TSymbolUniqueId(2294); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCube1_Int3_Int1 = + TSymbolUniqueId(2295); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCube1_Int3_Int1 = + TSymbolUniqueId(2296); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCube1_Int3_Int1 = + TSymbolUniqueId(2297); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2298); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2299); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2300); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(2301); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2302); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2303); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2304); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2305); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2306); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image1D1_Int1_Int1 = + TSymbolUniqueId(2307); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage1D1_Int1_Int1 = + TSymbolUniqueId(2308); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage1D1_Int1_Int1 = + TSymbolUniqueId(2309); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(2310); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2311); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2312); + static constexpr const TSymbolUniqueId imageAtomicAddExt_ImageRect1_Int2_Int1 = + TSymbolUniqueId(2313); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImageRect1_Int2_Int1 = + TSymbolUniqueId(2314); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImageRect1_Int2_Int1 = + TSymbolUniqueId(2315); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2316); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2317); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2318); + static constexpr const TSymbolUniqueId imageAtomicAddExt_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2319); + static constexpr const TSymbolUniqueId imageAtomicAddExt_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2320); + static constexpr const TSymbolUniqueId imageAtomicAddExt_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2321); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2D1_Int2_UInt1 = + TSymbolUniqueId(2322); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(2323); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(2324); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image3D1_Int3_UInt1 = + TSymbolUniqueId(2325); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(2326); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(2327); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(2328); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(2329); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(2330); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2331); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2332); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2333); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(2334); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2335); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2336); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2337); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2338); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2339); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image1D1_Int1_UInt1 = + TSymbolUniqueId(2340); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(2341); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(2342); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(2343); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2344); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2345); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(2346); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(2347); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(2348); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2349); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2350); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2351); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2352); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2353); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2354); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2D1_Int2_Int1 = + TSymbolUniqueId(2355); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2D1_Int2_Int1 = + TSymbolUniqueId(2356); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2D1_Int2_Int1 = + TSymbolUniqueId(2357); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image3D1_Int3_Int1 = + TSymbolUniqueId(2358); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage3D1_Int3_Int1 = + TSymbolUniqueId(2359); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage3D1_Int3_Int1 = + TSymbolUniqueId(2360); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageCube1_Int3_Int1 = + TSymbolUniqueId(2361); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageCube1_Int3_Int1 = + TSymbolUniqueId(2362); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageCube1_Int3_Int1 = + TSymbolUniqueId(2363); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2364); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2365); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2366); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(2367); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2368); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2369); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2370); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2371); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2372); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image1D1_Int1_Int1 = + TSymbolUniqueId(2373); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage1D1_Int1_Int1 = + TSymbolUniqueId(2374); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage1D1_Int1_Int1 = + TSymbolUniqueId(2375); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(2376); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2377); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2378); + static constexpr const TSymbolUniqueId imageAtomicMinExt_ImageRect1_Int2_Int1 = + TSymbolUniqueId(2379); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImageRect1_Int2_Int1 = + TSymbolUniqueId(2380); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImageRect1_Int2_Int1 = + TSymbolUniqueId(2381); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2382); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2383); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2384); + static constexpr const TSymbolUniqueId imageAtomicMinExt_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2385); + static constexpr const TSymbolUniqueId imageAtomicMinExt_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2386); + static constexpr const TSymbolUniqueId imageAtomicMinExt_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2387); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2D1_Int2_UInt1 = + TSymbolUniqueId(2388); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(2389); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(2390); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image3D1_Int3_UInt1 = + TSymbolUniqueId(2391); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(2392); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(2393); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(2394); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(2395); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(2396); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2397); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2398); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2399); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(2400); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2401); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2402); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2403); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2404); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2405); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image1D1_Int1_UInt1 = + TSymbolUniqueId(2406); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(2407); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(2408); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(2409); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2410); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2411); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(2412); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(2413); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(2414); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2415); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2416); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2417); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2418); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2419); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2420); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2D1_Int2_Int1 = + TSymbolUniqueId(2421); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2D1_Int2_Int1 = + TSymbolUniqueId(2422); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2D1_Int2_Int1 = + TSymbolUniqueId(2423); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image3D1_Int3_Int1 = + TSymbolUniqueId(2424); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage3D1_Int3_Int1 = + TSymbolUniqueId(2425); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage3D1_Int3_Int1 = + TSymbolUniqueId(2426); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageCube1_Int3_Int1 = + TSymbolUniqueId(2427); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageCube1_Int3_Int1 = + TSymbolUniqueId(2428); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageCube1_Int3_Int1 = + TSymbolUniqueId(2429); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2430); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2431); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2432); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(2433); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2434); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2435); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2436); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2437); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2438); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image1D1_Int1_Int1 = + TSymbolUniqueId(2439); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage1D1_Int1_Int1 = + TSymbolUniqueId(2440); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage1D1_Int1_Int1 = + TSymbolUniqueId(2441); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(2442); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2443); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2444); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_ImageRect1_Int2_Int1 = + TSymbolUniqueId(2445); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImageRect1_Int2_Int1 = + TSymbolUniqueId(2446); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImageRect1_Int2_Int1 = + TSymbolUniqueId(2447); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2448); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2449); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2450); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2451); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2452); + static constexpr const TSymbolUniqueId imageAtomicMaxExt_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2453); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2D1_Int2_UInt1 = + TSymbolUniqueId(2454); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(2455); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(2456); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image3D1_Int3_UInt1 = + TSymbolUniqueId(2457); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(2458); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(2459); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(2460); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(2461); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(2462); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2463); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2464); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2465); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(2466); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2467); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2468); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2469); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2470); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2471); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image1D1_Int1_UInt1 = + TSymbolUniqueId(2472); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(2473); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(2474); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(2475); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2476); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2477); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(2478); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(2479); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(2480); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2481); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2482); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2483); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2484); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2485); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2486); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2D1_Int2_Int1 = + TSymbolUniqueId(2487); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2D1_Int2_Int1 = + TSymbolUniqueId(2488); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2D1_Int2_Int1 = + TSymbolUniqueId(2489); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image3D1_Int3_Int1 = + TSymbolUniqueId(2490); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage3D1_Int3_Int1 = + TSymbolUniqueId(2491); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage3D1_Int3_Int1 = + TSymbolUniqueId(2492); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageCube1_Int3_Int1 = + TSymbolUniqueId(2493); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageCube1_Int3_Int1 = + TSymbolUniqueId(2494); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageCube1_Int3_Int1 = + TSymbolUniqueId(2495); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2496); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2497); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2498); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(2499); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2500); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2501); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2502); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2503); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2504); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image1D1_Int1_Int1 = + TSymbolUniqueId(2505); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage1D1_Int1_Int1 = + TSymbolUniqueId(2506); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage1D1_Int1_Int1 = + TSymbolUniqueId(2507); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(2508); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2509); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2510); + static constexpr const TSymbolUniqueId imageAtomicAndExt_ImageRect1_Int2_Int1 = + TSymbolUniqueId(2511); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImageRect1_Int2_Int1 = + TSymbolUniqueId(2512); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImageRect1_Int2_Int1 = + TSymbolUniqueId(2513); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2514); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2515); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2516); + static constexpr const TSymbolUniqueId imageAtomicAndExt_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2517); + static constexpr const TSymbolUniqueId imageAtomicAndExt_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2518); + static constexpr const TSymbolUniqueId imageAtomicAndExt_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2519); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2D1_Int2_UInt1 = + TSymbolUniqueId(2520); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(2521); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(2522); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image3D1_Int3_UInt1 = + TSymbolUniqueId(2523); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(2524); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(2525); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(2526); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(2527); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(2528); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2529); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2530); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2531); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(2532); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2533); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2534); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2535); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2536); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2537); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image1D1_Int1_UInt1 = + TSymbolUniqueId(2538); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(2539); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(2540); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(2541); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2542); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2543); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(2544); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(2545); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(2546); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2547); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2548); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2549); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2550); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2551); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2552); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2D1_Int2_Int1 = + TSymbolUniqueId(2553); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2D1_Int2_Int1 = + TSymbolUniqueId(2554); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2D1_Int2_Int1 = + TSymbolUniqueId(2555); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image3D1_Int3_Int1 = + TSymbolUniqueId(2556); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage3D1_Int3_Int1 = + TSymbolUniqueId(2557); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage3D1_Int3_Int1 = + TSymbolUniqueId(2558); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageCube1_Int3_Int1 = + TSymbolUniqueId(2559); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageCube1_Int3_Int1 = + TSymbolUniqueId(2560); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageCube1_Int3_Int1 = + TSymbolUniqueId(2561); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2562); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2563); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2564); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(2565); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2566); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2567); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2568); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2569); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2570); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image1D1_Int1_Int1 = + TSymbolUniqueId(2571); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage1D1_Int1_Int1 = + TSymbolUniqueId(2572); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage1D1_Int1_Int1 = + TSymbolUniqueId(2573); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(2574); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2575); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2576); + static constexpr const TSymbolUniqueId imageAtomicOrExt_ImageRect1_Int2_Int1 = + TSymbolUniqueId(2577); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImageRect1_Int2_Int1 = + TSymbolUniqueId(2578); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImageRect1_Int2_Int1 = + TSymbolUniqueId(2579); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2580); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2581); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2582); + static constexpr const TSymbolUniqueId imageAtomicOrExt_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2583); + static constexpr const TSymbolUniqueId imageAtomicOrExt_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2584); + static constexpr const TSymbolUniqueId imageAtomicOrExt_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2585); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2D1_Int2_UInt1 = + TSymbolUniqueId(2586); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(2587); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(2588); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image3D1_Int3_UInt1 = + TSymbolUniqueId(2589); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(2590); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(2591); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(2592); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(2593); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(2594); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2595); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2596); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2597); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(2598); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2599); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2600); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2601); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2602); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2603); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image1D1_Int1_UInt1 = + TSymbolUniqueId(2604); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(2605); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(2606); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(2607); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2608); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2609); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(2610); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(2611); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(2612); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2613); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2614); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2615); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2616); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2617); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2618); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2D1_Int2_Int1 = + TSymbolUniqueId(2619); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2D1_Int2_Int1 = + TSymbolUniqueId(2620); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2D1_Int2_Int1 = + TSymbolUniqueId(2621); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image3D1_Int3_Int1 = + TSymbolUniqueId(2622); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage3D1_Int3_Int1 = + TSymbolUniqueId(2623); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage3D1_Int3_Int1 = + TSymbolUniqueId(2624); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageCube1_Int3_Int1 = + TSymbolUniqueId(2625); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageCube1_Int3_Int1 = + TSymbolUniqueId(2626); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageCube1_Int3_Int1 = + TSymbolUniqueId(2627); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2628); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2629); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2630); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(2631); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2632); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2633); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2634); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2635); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2636); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image1D1_Int1_Int1 = + TSymbolUniqueId(2637); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage1D1_Int1_Int1 = + TSymbolUniqueId(2638); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage1D1_Int1_Int1 = + TSymbolUniqueId(2639); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(2640); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2641); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2642); + static constexpr const TSymbolUniqueId imageAtomicXorExt_ImageRect1_Int2_Int1 = + TSymbolUniqueId(2643); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImageRect1_Int2_Int1 = + TSymbolUniqueId(2644); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImageRect1_Int2_Int1 = + TSymbolUniqueId(2645); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2646); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2647); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2648); + static constexpr const TSymbolUniqueId imageAtomicXorExt_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2649); + static constexpr const TSymbolUniqueId imageAtomicXorExt_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2650); + static constexpr const TSymbolUniqueId imageAtomicXorExt_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2651); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2D1_Int2_UInt1 = + TSymbolUniqueId(2652); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2D1_Int2_UInt1 = + TSymbolUniqueId(2653); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2D1_Int2_UInt1 = + TSymbolUniqueId(2654); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image3D1_Int3_UInt1 = + TSymbolUniqueId(2655); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage3D1_Int3_UInt1 = + TSymbolUniqueId(2656); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage3D1_Int3_UInt1 = + TSymbolUniqueId(2657); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCube1_Int3_UInt1 = + TSymbolUniqueId(2658); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCube1_Int3_UInt1 = + TSymbolUniqueId(2659); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCube1_Int3_UInt1 = + TSymbolUniqueId(2660); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2661); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2662); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageBuffer1_Int1_UInt1 = + TSymbolUniqueId(2663); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DArray1_Int3_UInt1 = + TSymbolUniqueId(2664); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2665); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DArray1_Int3_UInt1 = + TSymbolUniqueId(2666); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2667); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2668); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCubeArray1_Int3_UInt1 = + TSymbolUniqueId(2669); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image1D1_Int1_UInt1 = + TSymbolUniqueId(2670); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage1D1_Int1_UInt1 = + TSymbolUniqueId(2671); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage1D1_Int1_UInt1 = + TSymbolUniqueId(2672); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image1DArray1_Int2_UInt1 = + TSymbolUniqueId(2673); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2674); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage1DArray1_Int2_UInt1 = + TSymbolUniqueId(2675); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageRect1_Int2_UInt1 = + TSymbolUniqueId(2676); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageRect1_Int2_UInt1 = + TSymbolUniqueId(2677); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageRect1_Int2_UInt1 = + TSymbolUniqueId(2678); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2679); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2680); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_UInt1 = + TSymbolUniqueId(2681); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2682); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2683); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_UInt1 = + TSymbolUniqueId(2684); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2D1_Int2_Int1 = + TSymbolUniqueId(2685); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2D1_Int2_Int1 = + TSymbolUniqueId(2686); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2D1_Int2_Int1 = + TSymbolUniqueId(2687); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image3D1_Int3_Int1 = + TSymbolUniqueId(2688); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage3D1_Int3_Int1 = + TSymbolUniqueId(2689); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage3D1_Int3_Int1 = + TSymbolUniqueId(2690); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCube1_Int3_Int1 = + TSymbolUniqueId(2691); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCube1_Int3_Int1 = + TSymbolUniqueId(2692); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCube1_Int3_Int1 = + TSymbolUniqueId(2693); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2694); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2695); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageBuffer1_Int1_Int1 = + TSymbolUniqueId(2696); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DArray1_Int3_Int1 = + TSymbolUniqueId(2697); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2698); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DArray1_Int3_Int1 = + TSymbolUniqueId(2699); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2700); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2701); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCubeArray1_Int3_Int1 = + TSymbolUniqueId(2702); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image1D1_Int1_Int1 = + TSymbolUniqueId(2703); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage1D1_Int1_Int1 = + TSymbolUniqueId(2704); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage1D1_Int1_Int1 = + TSymbolUniqueId(2705); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image1DArray1_Int2_Int1 = + TSymbolUniqueId(2706); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2707); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage1DArray1_Int2_Int1 = + TSymbolUniqueId(2708); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageRect1_Int2_Int1 = + TSymbolUniqueId(2709); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageRect1_Int2_Int1 = + TSymbolUniqueId(2710); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageRect1_Int2_Int1 = + TSymbolUniqueId(2711); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2712); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2713); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_Int1 = + TSymbolUniqueId(2714); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2715); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2716); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2717); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2D1_Int2_Float1 = + TSymbolUniqueId(2718); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2D1_Int2_Float1 = + TSymbolUniqueId(2719); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2D1_Int2_Float1 = + TSymbolUniqueId(2720); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image3D1_Int3_Float1 = + TSymbolUniqueId(2721); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage3D1_Int3_Float1 = + TSymbolUniqueId(2722); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage3D1_Int3_Float1 = + TSymbolUniqueId(2723); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCube1_Int3_Float1 = + TSymbolUniqueId(2724); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCube1_Int3_Float1 = + TSymbolUniqueId(2725); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCube1_Int3_Float1 = + TSymbolUniqueId(2726); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageBuffer1_Int1_Float1 = + TSymbolUniqueId(2727); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageBuffer1_Int1_Float1 = + TSymbolUniqueId(2728); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageBuffer1_Int1_Float1 = + TSymbolUniqueId(2729); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DArray1_Int3_Float1 = + TSymbolUniqueId(2730); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DArray1_Int3_Float1 = + TSymbolUniqueId(2731); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DArray1_Int3_Float1 = + TSymbolUniqueId(2732); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageCubeArray1_Int3_Float1 = + TSymbolUniqueId(2733); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageCubeArray1_Int3_Float1 = + TSymbolUniqueId(2734); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageCubeArray1_Int3_Float1 = + TSymbolUniqueId(2735); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image1D1_Int1_Float1 = + TSymbolUniqueId(2736); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage1D1_Int1_Float1 = + TSymbolUniqueId(2737); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage1D1_Int1_Float1 = + TSymbolUniqueId(2738); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image1DArray1_Int2_Float1 = + TSymbolUniqueId(2739); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage1DArray1_Int2_Float1 = + TSymbolUniqueId(2740); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage1DArray1_Int2_Float1 = + TSymbolUniqueId(2741); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_ImageRect1_Int2_Float1 = + TSymbolUniqueId(2742); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImageRect1_Int2_Float1 = + TSymbolUniqueId(2743); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImageRect1_Int2_Float1 = + TSymbolUniqueId(2744); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMS1_Int2_Int1_Float1 = + TSymbolUniqueId(2745); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_IImage2DMS1_Int2_Int1_Float1 = + TSymbolUniqueId(2746); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_UImage2DMS1_Int2_Int1_Float1 = + TSymbolUniqueId(2747); + static constexpr const TSymbolUniqueId imageAtomicExchangeExt_Image2DMSArray1_Int3_Int1_Float1 = + TSymbolUniqueId(2748); + static constexpr const TSymbolUniqueId + imageAtomicExchangeExt_IImage2DMSArray1_Int3_Int1_Float1 = TSymbolUniqueId(2749); + static constexpr const TSymbolUniqueId + imageAtomicExchangeExt_UImage2DMSArray1_Int3_Int1_Float1 = TSymbolUniqueId(2750); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2D1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2751); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2D1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2752); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2D1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2753); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image3D1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2754); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage3D1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2755); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage3D1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2756); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageCube1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2757); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageCube1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2758); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageCube1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2759); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageBuffer1_Int1_UInt1_UInt1 = + TSymbolUniqueId(2760); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageBuffer1_Int1_UInt1_UInt1 = + TSymbolUniqueId(2761); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageBuffer1_Int1_UInt1_UInt1 = + TSymbolUniqueId(2762); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2DArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2763); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2DArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2764); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2DArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2765); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageCubeArray1_Int3_UInt1_UInt1 = + TSymbolUniqueId(2766); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_IImageCubeArray1_Int3_UInt1_UInt1 = TSymbolUniqueId(2767); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_UImageCubeArray1_Int3_UInt1_UInt1 = TSymbolUniqueId(2768); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image1D1_Int1_UInt1_UInt1 = + TSymbolUniqueId(2769); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage1D1_Int1_UInt1_UInt1 = + TSymbolUniqueId(2770); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage1D1_Int1_UInt1_UInt1 = + TSymbolUniqueId(2771); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image1DArray1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2772); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage1DArray1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2773); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage1DArray1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2774); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageRect1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2775); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageRect1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2776); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageRect1_Int2_UInt1_UInt1 = + TSymbolUniqueId(2777); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2DMS1_Int2_Int1_UInt1_UInt1 = + TSymbolUniqueId(2778); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_IImage2DMS1_Int2_Int1_UInt1_UInt1 = TSymbolUniqueId(2779); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_UImage2DMS1_Int2_Int1_UInt1_UInt1 = TSymbolUniqueId(2780); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_Image2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(2781); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_IImage2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(2782); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_UImage2DMSArray1_Int3_Int1_UInt1_UInt1 = TSymbolUniqueId(2783); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2D1_Int2_Int1_Int1 = + TSymbolUniqueId(2784); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2D1_Int2_Int1_Int1 = + TSymbolUniqueId(2785); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2D1_Int2_Int1_Int1 = + TSymbolUniqueId(2786); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image3D1_Int3_Int1_Int1 = + TSymbolUniqueId(2787); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage3D1_Int3_Int1_Int1 = + TSymbolUniqueId(2788); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage3D1_Int3_Int1_Int1 = + TSymbolUniqueId(2789); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageCube1_Int3_Int1_Int1 = + TSymbolUniqueId(2790); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageCube1_Int3_Int1_Int1 = + TSymbolUniqueId(2791); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageCube1_Int3_Int1_Int1 = + TSymbolUniqueId(2792); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageBuffer1_Int1_Int1_Int1 = + TSymbolUniqueId(2793); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageBuffer1_Int1_Int1_Int1 = + TSymbolUniqueId(2794); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageBuffer1_Int1_Int1_Int1 = + TSymbolUniqueId(2795); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2DArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2796); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2DArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2797); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2DArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2798); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageCubeArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2799); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageCubeArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2800); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageCubeArray1_Int3_Int1_Int1 = + TSymbolUniqueId(2801); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image1D1_Int1_Int1_Int1 = + TSymbolUniqueId(2802); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage1D1_Int1_Int1_Int1 = + TSymbolUniqueId(2803); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage1D1_Int1_Int1_Int1 = + TSymbolUniqueId(2804); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(2805); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(2806); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage1DArray1_Int2_Int1_Int1 = + TSymbolUniqueId(2807); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_ImageRect1_Int2_Int1_Int1 = + TSymbolUniqueId(2808); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImageRect1_Int2_Int1_Int1 = + TSymbolUniqueId(2809); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImageRect1_Int2_Int1_Int1 = + TSymbolUniqueId(2810); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_Image2DMS1_Int2_Int1_Int1_Int1 = + TSymbolUniqueId(2811); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_IImage2DMS1_Int2_Int1_Int1_Int1 = + TSymbolUniqueId(2812); + static constexpr const TSymbolUniqueId imageAtomicCompSwapExt_UImage2DMS1_Int2_Int1_Int1_Int1 = + TSymbolUniqueId(2813); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_Image2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(2814); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_IImage2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(2815); + static constexpr const TSymbolUniqueId + imageAtomicCompSwapExt_UImage2DMSArray1_Int3_Int1_Int1_Int1 = TSymbolUniqueId(2816); + static constexpr const TSymbolUniqueId pixelLocalLoadANGLE_PixelLocalANGLE1 = + TSymbolUniqueId(2817); + static constexpr const TSymbolUniqueId pt01g = TSymbolUniqueId(2818); + static constexpr const TSymbolUniqueId pixelLocalLoadANGLE_IPixelLocalANGLE1 = + TSymbolUniqueId(2819); + static constexpr const TSymbolUniqueId pt01h = TSymbolUniqueId(2820); + static constexpr const TSymbolUniqueId pixelLocalLoadANGLE_UPixelLocalANGLE1 = + TSymbolUniqueId(2821); + static constexpr const TSymbolUniqueId pt01i = TSymbolUniqueId(2822); + static constexpr const TSymbolUniqueId pixelLocalStoreANGLE_PixelLocalANGLE1_Float4 = + TSymbolUniqueId(2823); + static constexpr const TSymbolUniqueId pixelLocalStoreANGLE_IPixelLocalANGLE1_Int4 = + TSymbolUniqueId(2824); + static constexpr const TSymbolUniqueId pixelLocalStoreANGLE_UPixelLocalANGLE1_UInt4 = + TSymbolUniqueId(2825); + static constexpr const TSymbolUniqueId beginInvocationInterlockNV = TSymbolUniqueId(2826); + static constexpr const TSymbolUniqueId endInvocationInterlockNV = TSymbolUniqueId(2827); + static constexpr const TSymbolUniqueId beginFragmentShaderOrderingINTEL = TSymbolUniqueId(2828); + static constexpr const TSymbolUniqueId beginInvocationInterlockARB = TSymbolUniqueId(2829); + static constexpr const TSymbolUniqueId endInvocationInterlockARB = TSymbolUniqueId(2830); + static constexpr const TSymbolUniqueId noise1_Float1 = TSymbolUniqueId(2831); + static constexpr const TSymbolUniqueId noise1_Float2 = TSymbolUniqueId(2832); + static constexpr const TSymbolUniqueId noise1_Float3 = TSymbolUniqueId(2833); + static constexpr const TSymbolUniqueId noise1_Float4 = TSymbolUniqueId(2834); + static constexpr const TSymbolUniqueId noise2_Float1 = TSymbolUniqueId(2835); + static constexpr const TSymbolUniqueId noise2_Float2 = TSymbolUniqueId(2836); + static constexpr const TSymbolUniqueId noise2_Float3 = TSymbolUniqueId(2837); + static constexpr const TSymbolUniqueId noise2_Float4 = TSymbolUniqueId(2838); + static constexpr const TSymbolUniqueId noise3_Float1 = TSymbolUniqueId(2839); + static constexpr const TSymbolUniqueId noise3_Float2 = TSymbolUniqueId(2840); + static constexpr const TSymbolUniqueId noise3_Float3 = TSymbolUniqueId(2841); + static constexpr const TSymbolUniqueId noise3_Float4 = TSymbolUniqueId(2842); + static constexpr const TSymbolUniqueId noise4_Float1 = TSymbolUniqueId(2843); + static constexpr const TSymbolUniqueId noise4_Float2 = TSymbolUniqueId(2844); + static constexpr const TSymbolUniqueId noise4_Float3 = TSymbolUniqueId(2845); + static constexpr const TSymbolUniqueId noise4_Float4 = TSymbolUniqueId(2846); + static constexpr const TSymbolUniqueId memoryBarrier = TSymbolUniqueId(2847); + static constexpr const TSymbolUniqueId memoryBarrierAtomicCounter = TSymbolUniqueId(2848); + static constexpr const TSymbolUniqueId memoryBarrierBuffer = TSymbolUniqueId(2849); + static constexpr const TSymbolUniqueId memoryBarrierImage = TSymbolUniqueId(2850); + static constexpr const TSymbolUniqueId barrier = TSymbolUniqueId(2851); + static constexpr const TSymbolUniqueId memoryBarrierShared = TSymbolUniqueId(2852); + static constexpr const TSymbolUniqueId groupMemoryBarrier = TSymbolUniqueId(2853); + static constexpr const TSymbolUniqueId barrierTCS = TSymbolUniqueId(2854); + static constexpr const TSymbolUniqueId barrierTCSES3_2 = TSymbolUniqueId(2855); + static constexpr const TSymbolUniqueId EmitVertex = TSymbolUniqueId(2856); + static constexpr const TSymbolUniqueId EmitVertexES3_2 = TSymbolUniqueId(2857); + static constexpr const TSymbolUniqueId EndPrimitive = TSymbolUniqueId(2858); + static constexpr const TSymbolUniqueId EndPrimitiveES3_2 = TSymbolUniqueId(2859); + static constexpr const TSymbolUniqueId EmitStreamVertex_Int1 = TSymbolUniqueId(2860); + static constexpr const TSymbolUniqueId EndStreamPrimitive_Int1 = TSymbolUniqueId(2861); + static constexpr const TSymbolUniqueId subpassLoad_SubpassInput1 = TSymbolUniqueId(2862); + static constexpr const TSymbolUniqueId pt01j = TSymbolUniqueId(2863); + static constexpr const TSymbolUniqueId subpassLoad_ISubpassInput1 = TSymbolUniqueId(2864); + static constexpr const TSymbolUniqueId pt01k = TSymbolUniqueId(2865); + static constexpr const TSymbolUniqueId subpassLoad_USubpassInput1 = TSymbolUniqueId(2866); + static constexpr const TSymbolUniqueId pt01l = TSymbolUniqueId(2867); + static constexpr const TSymbolUniqueId subpassLoad_SubpassInputMS1_Int1 = TSymbolUniqueId(2868); + static constexpr const TSymbolUniqueId pt01m = TSymbolUniqueId(2869); + static constexpr const TSymbolUniqueId subpassLoad_ISubpassInputMS1_Int1 = + TSymbolUniqueId(2870); + static constexpr const TSymbolUniqueId pt01n = TSymbolUniqueId(2871); + static constexpr const TSymbolUniqueId subpassLoad_USubpassInputMS1_Int1 = + TSymbolUniqueId(2872); + static constexpr const TSymbolUniqueId pt01o = TSymbolUniqueId(2873); + static constexpr const TSymbolUniqueId anyInvocation_Bool1 = TSymbolUniqueId(2874); + static constexpr const TSymbolUniqueId allInvocations_Bool1 = TSymbolUniqueId(2875); + static constexpr const TSymbolUniqueId allInvocationsEqual_Bool1 = TSymbolUniqueId(2876); + static constexpr const TSymbolUniqueId gl_DepthRangeParameters = TSymbolUniqueId(2877); + static constexpr const TSymbolUniqueId gl_DepthRange = TSymbolUniqueId(2878); + static constexpr const TSymbolUniqueId gl_NumSamples = TSymbolUniqueId(2879); + static constexpr const TSymbolUniqueId gl_NumSamplesES3_2 = TSymbolUniqueId(2880); + static constexpr const TSymbolUniqueId gl_MaxVertexAttribs = TSymbolUniqueId(2881); + static constexpr const TSymbolUniqueId gl_MaxVertexUniformVectors = TSymbolUniqueId(2882); + static constexpr const TSymbolUniqueId gl_MaxVertexTextureImageUnits = TSymbolUniqueId(2883); + static constexpr const TSymbolUniqueId gl_MaxCombinedTextureImageUnits = TSymbolUniqueId(2884); + static constexpr const TSymbolUniqueId gl_MaxTextureImageUnits = TSymbolUniqueId(2885); + static constexpr const TSymbolUniqueId gl_MaxFragmentUniformVectors = TSymbolUniqueId(2886); + static constexpr const TSymbolUniqueId gl_MaxVaryingVectors = TSymbolUniqueId(2887); + static constexpr const TSymbolUniqueId gl_MaxDrawBuffers = TSymbolUniqueId(2888); + static constexpr const TSymbolUniqueId gl_MaxDualSourceDrawBuffersEXT = TSymbolUniqueId(2889); + static constexpr const TSymbolUniqueId gl_MaxVertexOutputVectors = TSymbolUniqueId(2890); + static constexpr const TSymbolUniqueId gl_MaxFragmentInputVectors = TSymbolUniqueId(2891); + static constexpr const TSymbolUniqueId gl_MinProgramTexelOffset = TSymbolUniqueId(2892); + static constexpr const TSymbolUniqueId gl_MaxProgramTexelOffset = TSymbolUniqueId(2893); + static constexpr const TSymbolUniqueId gl_MaxImageUnits = TSymbolUniqueId(2894); + static constexpr const TSymbolUniqueId gl_MaxVertexImageUniforms = TSymbolUniqueId(2895); + static constexpr const TSymbolUniqueId gl_MaxFragmentImageUniforms = TSymbolUniqueId(2896); + static constexpr const TSymbolUniqueId gl_MaxComputeImageUniforms = TSymbolUniqueId(2897); + static constexpr const TSymbolUniqueId gl_MaxCombinedImageUniforms = TSymbolUniqueId(2898); + static constexpr const TSymbolUniqueId gl_MaxCombinedShaderOutputResources = + TSymbolUniqueId(2899); + static constexpr const TSymbolUniqueId gl_MaxComputeWorkGroupCount = TSymbolUniqueId(2900); + static constexpr const TSymbolUniqueId gl_MaxComputeWorkGroupSize = TSymbolUniqueId(2901); + static constexpr const TSymbolUniqueId gl_MaxComputeUniformComponents = TSymbolUniqueId(2902); + static constexpr const TSymbolUniqueId gl_MaxComputeTextureImageUnits = TSymbolUniqueId(2903); + static constexpr const TSymbolUniqueId gl_MaxComputeAtomicCounters = TSymbolUniqueId(2904); + static constexpr const TSymbolUniqueId gl_MaxComputeAtomicCounterBuffers = + TSymbolUniqueId(2905); + static constexpr const TSymbolUniqueId gl_MaxVertexAtomicCounters = TSymbolUniqueId(2906); + static constexpr const TSymbolUniqueId gl_MaxFragmentAtomicCounters = TSymbolUniqueId(2907); + static constexpr const TSymbolUniqueId gl_MaxCombinedAtomicCounters = TSymbolUniqueId(2908); + static constexpr const TSymbolUniqueId gl_MaxAtomicCounterBindings = TSymbolUniqueId(2909); + static constexpr const TSymbolUniqueId gl_MaxVertexAtomicCounterBuffers = TSymbolUniqueId(2910); + static constexpr const TSymbolUniqueId gl_MaxFragmentAtomicCounterBuffers = + TSymbolUniqueId(2911); + static constexpr const TSymbolUniqueId gl_MaxCombinedAtomicCounterBuffers = + TSymbolUniqueId(2912); + static constexpr const TSymbolUniqueId gl_MaxAtomicCounterBufferSize = TSymbolUniqueId(2913); + static constexpr const TSymbolUniqueId gl_MaxGeometryInputComponents = TSymbolUniqueId(2914); + static constexpr const TSymbolUniqueId gl_MaxGeometryInputComponentsES3_2 = + TSymbolUniqueId(2915); + static constexpr const TSymbolUniqueId gl_MaxGeometryOutputComponents = TSymbolUniqueId(2916); + static constexpr const TSymbolUniqueId gl_MaxGeometryOutputComponentsES3_2 = + TSymbolUniqueId(2917); + static constexpr const TSymbolUniqueId gl_MaxGeometryImageUniforms = TSymbolUniqueId(2918); + static constexpr const TSymbolUniqueId gl_MaxGeometryImageUniformsES3_2 = TSymbolUniqueId(2919); + static constexpr const TSymbolUniqueId gl_MaxGeometryTextureImageUnits = TSymbolUniqueId(2920); + static constexpr const TSymbolUniqueId gl_MaxGeometryTextureImageUnitsES3_2 = + TSymbolUniqueId(2921); + static constexpr const TSymbolUniqueId gl_MaxGeometryOutputVertices = TSymbolUniqueId(2922); + static constexpr const TSymbolUniqueId gl_MaxGeometryOutputVerticesES3_2 = + TSymbolUniqueId(2923); + static constexpr const TSymbolUniqueId gl_MaxGeometryTotalOutputComponents = + TSymbolUniqueId(2924); + static constexpr const TSymbolUniqueId gl_MaxGeometryTotalOutputComponentsES3_2 = + TSymbolUniqueId(2925); + static constexpr const TSymbolUniqueId gl_MaxGeometryUniformComponents = TSymbolUniqueId(2926); + static constexpr const TSymbolUniqueId gl_MaxGeometryUniformComponentsES3_2 = + TSymbolUniqueId(2927); + static constexpr const TSymbolUniqueId gl_MaxGeometryAtomicCounters = TSymbolUniqueId(2928); + static constexpr const TSymbolUniqueId gl_MaxGeometryAtomicCountersES3_2 = + TSymbolUniqueId(2929); + static constexpr const TSymbolUniqueId gl_MaxGeometryAtomicCounterBuffers = + TSymbolUniqueId(2930); + static constexpr const TSymbolUniqueId gl_MaxGeometryAtomicCounterBuffersES3_2 = + TSymbolUniqueId(2931); + static constexpr const TSymbolUniqueId gl_MaxTessControlInputComponents = TSymbolUniqueId(2932); + static constexpr const TSymbolUniqueId gl_MaxTessControlInputComponentsES3_2 = + TSymbolUniqueId(2933); + static constexpr const TSymbolUniqueId gl_MaxTessControlOutputComponents = + TSymbolUniqueId(2934); + static constexpr const TSymbolUniqueId gl_MaxTessControlOutputComponentsES3_2 = + TSymbolUniqueId(2935); + static constexpr const TSymbolUniqueId gl_MaxTessControlTextureImageUnits = + TSymbolUniqueId(2936); + static constexpr const TSymbolUniqueId gl_MaxTessControlTextureImageUnitsES3_2 = + TSymbolUniqueId(2937); + static constexpr const TSymbolUniqueId gl_MaxTessControlUniformComponents = + TSymbolUniqueId(2938); + static constexpr const TSymbolUniqueId gl_MaxTessControlUniformComponentsES3_2 = + TSymbolUniqueId(2939); + static constexpr const TSymbolUniqueId gl_MaxTessControlTotalOutputComponents = + TSymbolUniqueId(2940); + static constexpr const TSymbolUniqueId gl_MaxTessControlTotalOutputComponentsES3_2 = + TSymbolUniqueId(2941); + static constexpr const TSymbolUniqueId gl_MaxTessControlImageUniforms = TSymbolUniqueId(2942); + static constexpr const TSymbolUniqueId gl_MaxTessControlImageUniformsES3_2 = + TSymbolUniqueId(2943); + static constexpr const TSymbolUniqueId gl_MaxTessControlAtomicCounters = TSymbolUniqueId(2944); + static constexpr const TSymbolUniqueId gl_MaxTessControlAtomicCountersES3_2 = + TSymbolUniqueId(2945); + static constexpr const TSymbolUniqueId gl_MaxTessControlAtomicCounterBuffers = + TSymbolUniqueId(2946); + static constexpr const TSymbolUniqueId gl_MaxTessControlAtomicCounterBuffersES3_2 = + TSymbolUniqueId(2947); + static constexpr const TSymbolUniqueId gl_MaxTessPatchComponents = TSymbolUniqueId(2948); + static constexpr const TSymbolUniqueId gl_MaxTessPatchComponentsES3_2 = TSymbolUniqueId(2949); + static constexpr const TSymbolUniqueId gl_MaxPatchVertices = TSymbolUniqueId(2950); + static constexpr const TSymbolUniqueId gl_MaxPatchVerticesES3_2 = TSymbolUniqueId(2951); + static constexpr const TSymbolUniqueId gl_MaxTessGenLevel = TSymbolUniqueId(2952); + static constexpr const TSymbolUniqueId gl_MaxTessGenLevelES3_2 = TSymbolUniqueId(2953); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationInputComponents = + TSymbolUniqueId(2954); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationInputComponentsES3_2 = + TSymbolUniqueId(2955); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationOutputComponents = + TSymbolUniqueId(2956); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationOutputComponentsES3_2 = + TSymbolUniqueId(2957); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationTextureImageUnits = + TSymbolUniqueId(2958); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationTextureImageUnitsES3_2 = + TSymbolUniqueId(2959); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationUniformComponents = + TSymbolUniqueId(2960); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationUniformComponentsES3_2 = + TSymbolUniqueId(2961); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationImageUniforms = + TSymbolUniqueId(2962); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationImageUniformsES3_2 = + TSymbolUniqueId(2963); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationAtomicCounters = + TSymbolUniqueId(2964); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationAtomicCountersES3_2 = + TSymbolUniqueId(2965); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationAtomicCounterBuffers = + TSymbolUniqueId(2966); + static constexpr const TSymbolUniqueId gl_MaxTessEvaluationAtomicCounterBuffersES3_2 = + TSymbolUniqueId(2967); + static constexpr const TSymbolUniqueId gl_MaxSamples = TSymbolUniqueId(2968); + static constexpr const TSymbolUniqueId gl_MaxSamplesES3_2 = TSymbolUniqueId(2969); + static constexpr const TSymbolUniqueId gl_MaxClipDistancesAPPLE = TSymbolUniqueId(2970); + static constexpr const TSymbolUniqueId gl_MaxCullDistancesEXT = TSymbolUniqueId(2971); + static constexpr const TSymbolUniqueId gl_MaxCombinedClipAndCullDistancesEXT = + TSymbolUniqueId(2972); + static constexpr const TSymbolUniqueId gl_FragCoord = TSymbolUniqueId(2973); + static constexpr const TSymbolUniqueId gl_FrontFacing = TSymbolUniqueId(2974); + static constexpr const TSymbolUniqueId gl_PointCoord = TSymbolUniqueId(2975); + static constexpr const TSymbolUniqueId gl_FragColor = TSymbolUniqueId(2976); + static constexpr const TSymbolUniqueId gl_FragData = TSymbolUniqueId(2977); + static constexpr const TSymbolUniqueId gl_FragDepth = TSymbolUniqueId(2978); + static constexpr const TSymbolUniqueId gl_HelperInvocation = TSymbolUniqueId(2979); + static constexpr const TSymbolUniqueId gl_FragCoord300 = TSymbolUniqueId(2980); + static constexpr const TSymbolUniqueId gl_SecondaryFragColorEXT = TSymbolUniqueId(2981); + static constexpr const TSymbolUniqueId gl_SecondaryFragDataEXT = TSymbolUniqueId(2982); + static constexpr const TSymbolUniqueId gl_FragDepthEXT = TSymbolUniqueId(2983); + static constexpr const TSymbolUniqueId gl_LastFragData = TSymbolUniqueId(2984); + static constexpr const TSymbolUniqueId gl_LastFragColor = TSymbolUniqueId(2985); + static constexpr const TSymbolUniqueId gl_LastFragDataNV = TSymbolUniqueId(2986); + static constexpr const TSymbolUniqueId gl_LastFragColorARM = TSymbolUniqueId(2987); + static constexpr const TSymbolUniqueId gl_PrimitiveID = TSymbolUniqueId(2988); + static constexpr const TSymbolUniqueId gl_PrimitiveIDES3_2 = TSymbolUniqueId(2989); + static constexpr const TSymbolUniqueId gl_Layer = TSymbolUniqueId(2990); + static constexpr const TSymbolUniqueId gl_LayerES3_2 = TSymbolUniqueId(2991); + static constexpr const TSymbolUniqueId gl_SampleID = TSymbolUniqueId(2992); + static constexpr const TSymbolUniqueId gl_SampleIDES3_2 = TSymbolUniqueId(2993); + static constexpr const TSymbolUniqueId gl_SamplePosition = TSymbolUniqueId(2994); + static constexpr const TSymbolUniqueId gl_SamplePositionES3_2 = TSymbolUniqueId(2995); + static constexpr const TSymbolUniqueId gl_SampleMaskIn = TSymbolUniqueId(2996); + static constexpr const TSymbolUniqueId gl_SampleMaskInES3_2 = TSymbolUniqueId(2997); + static constexpr const TSymbolUniqueId gl_SampleMask = TSymbolUniqueId(2998); + static constexpr const TSymbolUniqueId gl_SampleMaskES3_2 = TSymbolUniqueId(2999); + static constexpr const TSymbolUniqueId gl_CullDistance = TSymbolUniqueId(3000); + static constexpr const TSymbolUniqueId gl_ClipDistance = TSymbolUniqueId(3001); + static constexpr const TSymbolUniqueId gl_Position = TSymbolUniqueId(3002); + static constexpr const TSymbolUniqueId gl_PointSize = TSymbolUniqueId(3003); + static constexpr const TSymbolUniqueId gl_InstanceID = TSymbolUniqueId(3004); + static constexpr const TSymbolUniqueId gl_InstanceIndex = TSymbolUniqueId(3005); + static constexpr const TSymbolUniqueId gl_VertexID = TSymbolUniqueId(3006); + static constexpr const TSymbolUniqueId gl_VertexIndex = TSymbolUniqueId(3007); + static constexpr const TSymbolUniqueId gl_ViewportIndex = TSymbolUniqueId(3008); + static constexpr const TSymbolUniqueId gl_LayerVS = TSymbolUniqueId(3009); + static constexpr const TSymbolUniqueId gl_PointSize300 = TSymbolUniqueId(3010); + static constexpr const TSymbolUniqueId gl_DrawID = TSymbolUniqueId(3011); + static constexpr const TSymbolUniqueId gl_BaseVertex = TSymbolUniqueId(3012); + static constexpr const TSymbolUniqueId gl_BaseInstance = TSymbolUniqueId(3013); + static constexpr const TSymbolUniqueId angle_BaseVertex = TSymbolUniqueId(3014); + static constexpr const TSymbolUniqueId angle_BaseInstance = TSymbolUniqueId(3015); + static constexpr const TSymbolUniqueId gl_ClipDistanceAPPLE = TSymbolUniqueId(3016); + static constexpr const TSymbolUniqueId gl_CullDistanceEXT = TSymbolUniqueId(3017); + static constexpr const TSymbolUniqueId gl_NumWorkGroups = TSymbolUniqueId(3018); + static constexpr const TSymbolUniqueId gl_WorkGroupSize = TSymbolUniqueId(3019); + static constexpr const TSymbolUniqueId gl_WorkGroupID = TSymbolUniqueId(3020); + static constexpr const TSymbolUniqueId gl_LocalInvocationID = TSymbolUniqueId(3021); + static constexpr const TSymbolUniqueId gl_GlobalInvocationID = TSymbolUniqueId(3022); + static constexpr const TSymbolUniqueId gl_LocalInvocationIndex = TSymbolUniqueId(3023); + static constexpr const TSymbolUniqueId gl_PrimitiveIDIn = TSymbolUniqueId(3024); + static constexpr const TSymbolUniqueId gl_PrimitiveIDInES3_2 = TSymbolUniqueId(3025); + static constexpr const TSymbolUniqueId gl_InvocationID = TSymbolUniqueId(3026); + static constexpr const TSymbolUniqueId gl_InvocationIDES3_2 = TSymbolUniqueId(3027); + static constexpr const TSymbolUniqueId gl_PrimitiveIDGS = TSymbolUniqueId(3028); + static constexpr const TSymbolUniqueId gl_PrimitiveIDGSES3_2 = TSymbolUniqueId(3029); + static constexpr const TSymbolUniqueId gl_LayerGS = TSymbolUniqueId(3030); + static constexpr const TSymbolUniqueId gl_LayerGSES3_2 = TSymbolUniqueId(3031); + static constexpr const TSymbolUniqueId gl_PerVertex = TSymbolUniqueId(3032); + static constexpr const TSymbolUniqueId gl_PerVertexES3_2 = TSymbolUniqueId(3033); + static constexpr const TSymbolUniqueId gl_in = TSymbolUniqueId(3034); + static constexpr const TSymbolUniqueId gl_inES3_2 = TSymbolUniqueId(3035); + static constexpr const TSymbolUniqueId gl_PerVertexOutBlock = TSymbolUniqueId(3036); + static constexpr const TSymbolUniqueId gl_PerVertexOutBlockES3_2 = TSymbolUniqueId(3037); + static constexpr const TSymbolUniqueId gl_PositionGS = TSymbolUniqueId(3038); + static constexpr const TSymbolUniqueId gl_PositionGSES3_2 = TSymbolUniqueId(3039); + static constexpr const TSymbolUniqueId gl_PatchVerticesInTCS = TSymbolUniqueId(3040); + static constexpr const TSymbolUniqueId gl_PatchVerticesInTCSES3_2 = TSymbolUniqueId(3041); + static constexpr const TSymbolUniqueId gl_InvocationIDTCS = TSymbolUniqueId(3042); + static constexpr const TSymbolUniqueId gl_InvocationIDTCSES3_2 = TSymbolUniqueId(3043); + static constexpr const TSymbolUniqueId gl_PrimitiveIDTCS = TSymbolUniqueId(3044); + static constexpr const TSymbolUniqueId gl_PrimitiveIDTCSES3_2 = TSymbolUniqueId(3045); + static constexpr const TSymbolUniqueId gl_TessLevelOuterTCS = TSymbolUniqueId(3046); + static constexpr const TSymbolUniqueId gl_TessLevelOuterTCSES3_2 = TSymbolUniqueId(3047); + static constexpr const TSymbolUniqueId gl_TessLevelInnerTCS = TSymbolUniqueId(3048); + static constexpr const TSymbolUniqueId gl_TessLevelInnerTCSES3_2 = TSymbolUniqueId(3049); + static constexpr const TSymbolUniqueId gl_PerVertexTCS = TSymbolUniqueId(3050); + static constexpr const TSymbolUniqueId gl_PerVertexTCSES3_2 = TSymbolUniqueId(3051); + static constexpr const TSymbolUniqueId gl_inTCS = TSymbolUniqueId(3052); + static constexpr const TSymbolUniqueId gl_inTCSES3_2 = TSymbolUniqueId(3053); + static constexpr const TSymbolUniqueId gl_outTCS = TSymbolUniqueId(3054); + static constexpr const TSymbolUniqueId gl_outTCSES3_2 = TSymbolUniqueId(3055); + static constexpr const TSymbolUniqueId gl_BoundingBoxTCS = TSymbolUniqueId(3056); + static constexpr const TSymbolUniqueId gl_BoundingBoxTCSES3_2 = TSymbolUniqueId(3057); + static constexpr const TSymbolUniqueId gl_PerVertexOutTcsBlock = TSymbolUniqueId(3058); + static constexpr const TSymbolUniqueId gl_PerVertexOutTcsBlockES3_2 = TSymbolUniqueId(3059); + static constexpr const TSymbolUniqueId gl_PositionTCS = TSymbolUniqueId(3060); + static constexpr const TSymbolUniqueId gl_PositionTCSES3_2 = TSymbolUniqueId(3061); + static constexpr const TSymbolUniqueId gl_BoundingBoxEXTTCS = TSymbolUniqueId(3062); + static constexpr const TSymbolUniqueId gl_BoundingBoxEXTTCSES3_2 = TSymbolUniqueId(3063); + static constexpr const TSymbolUniqueId gl_BoundingBoxOESTCS = TSymbolUniqueId(3064); + static constexpr const TSymbolUniqueId gl_BoundingBoxOESTCSES3_2 = TSymbolUniqueId(3065); + static constexpr const TSymbolUniqueId gl_PatchVerticesInTES = TSymbolUniqueId(3066); + static constexpr const TSymbolUniqueId gl_PatchVerticesInTESES3_2 = TSymbolUniqueId(3067); + static constexpr const TSymbolUniqueId gl_PrimitiveIDTES = TSymbolUniqueId(3068); + static constexpr const TSymbolUniqueId gl_PrimitiveIDTESES3_2 = TSymbolUniqueId(3069); + static constexpr const TSymbolUniqueId gl_TessCoord = TSymbolUniqueId(3070); + static constexpr const TSymbolUniqueId gl_TessLevelOuterTES = TSymbolUniqueId(3071); + static constexpr const TSymbolUniqueId gl_TessLevelOuterTESES3_2 = TSymbolUniqueId(3072); + static constexpr const TSymbolUniqueId gl_TessLevelInnerTES = TSymbolUniqueId(3073); + static constexpr const TSymbolUniqueId gl_TessLevelInnerTESES3_2 = TSymbolUniqueId(3074); + static constexpr const TSymbolUniqueId gl_PerVertexTES = TSymbolUniqueId(3075); + static constexpr const TSymbolUniqueId gl_PerVertexTESES3_2 = TSymbolUniqueId(3076); + static constexpr const TSymbolUniqueId gl_inTES = TSymbolUniqueId(3077); + static constexpr const TSymbolUniqueId gl_inTESES3_2 = TSymbolUniqueId(3078); + static constexpr const TSymbolUniqueId gl_outTES = TSymbolUniqueId(3079); + static constexpr const TSymbolUniqueId gl_outTESES3_2 = TSymbolUniqueId(3080); + static constexpr const TSymbolUniqueId gl_PerVertexOutTesBlock = TSymbolUniqueId(3081); + static constexpr const TSymbolUniqueId gl_PerVertexOutTesBlockES3_2 = TSymbolUniqueId(3082); + static constexpr const TSymbolUniqueId gl_PositionTES = TSymbolUniqueId(3083); + static constexpr const TSymbolUniqueId gl_PositionTESES3_2 = TSymbolUniqueId(3084); + static constexpr const TSymbolUniqueId gl_ViewID_OVR = TSymbolUniqueId(3085); + +}; // class BuiltInId + +namespace BuiltInVariable +{ + +const TVariable *angle_BaseInstance(); +const TVariable *angle_BaseVertex(); +const TVariable *gl_BaseInstance(); +const TVariable *gl_BaseVertex(); +const TVariable *gl_DrawID(); +const TVariable *gl_FragColor(); +const TVariable *gl_FragCoord(); +const TVariable *gl_FragCoord300(); +const TVariable *gl_FragDepth(); +const TVariable *gl_FrontFacing(); +const TVariable *gl_GlobalInvocationID(); +const TVariable *gl_HelperInvocation(); +const TVariable *gl_InstanceID(); +const TVariable *gl_InstanceIndex(); +const TVariable *gl_InvocationID(); +const TVariable *gl_InvocationIDES3_2(); +const TVariable *gl_InvocationIDTCS(); +const TVariable *gl_InvocationIDTCSES3_2(); +const TVariable *gl_LastFragColor(); +const TVariable *gl_LastFragColorARM(); +const TVariable *gl_Layer(); +const TVariable *gl_LayerES3_2(); +const TVariable *gl_LayerGS(); +const TVariable *gl_LayerGSES3_2(); +const TVariable *gl_LayerVS(); +const TVariable *gl_LocalInvocationID(); +const TVariable *gl_LocalInvocationIndex(); +const TVariable *gl_NumSamples(); +const TVariable *gl_NumSamplesES3_2(); +const TVariable *gl_NumWorkGroups(); +const TVariable *gl_PatchVerticesInTCS(); +const TVariable *gl_PatchVerticesInTCSES3_2(); +const TVariable *gl_PatchVerticesInTES(); +const TVariable *gl_PatchVerticesInTESES3_2(); +const TVariable *gl_PointCoord(); +const TVariable *gl_PointSize(); +const TVariable *gl_PointSize300(); +const TVariable *gl_Position(); +const TVariable *gl_PrimitiveID(); +const TVariable *gl_PrimitiveIDES3_2(); +const TVariable *gl_PrimitiveIDGS(); +const TVariable *gl_PrimitiveIDGSES3_2(); +const TVariable *gl_PrimitiveIDIn(); +const TVariable *gl_PrimitiveIDInES3_2(); +const TVariable *gl_PrimitiveIDTCS(); +const TVariable *gl_PrimitiveIDTCSES3_2(); +const TVariable *gl_PrimitiveIDTES(); +const TVariable *gl_PrimitiveIDTESES3_2(); +const TVariable *gl_SampleID(); +const TVariable *gl_SampleIDES3_2(); +const TVariable *gl_SamplePosition(); +const TVariable *gl_SamplePositionES3_2(); +const TVariable *gl_SecondaryFragColorEXT(); +const TVariable *gl_TessCoord(); +const TVariable *gl_VertexID(); +const TVariable *gl_VertexIndex(); +const TVariable *gl_ViewID_OVR(); +const TVariable *gl_ViewportIndex(); +const TVariable *gl_WorkGroupID(); +const TVariable *gl_WorkGroupSize(); + +} // namespace BuiltInVariable + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/DriverUniform.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/DriverUniform.cpp new file mode 100644 index 0000000000..9cf4dddcd0 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/DriverUniform.cpp @@ -0,0 +1,435 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// DriverUniform.cpp: Add code to support driver uniforms +// + +#include "compiler/translator/tree_util/DriverUniform.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/FindMain.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ +constexpr ImmutableString kEmulatedDepthRangeParams = ImmutableString("ANGLEDepthRangeParams"); + +constexpr const char kAcbBufferOffsets[] = "acbBufferOffsets"; +constexpr const char kDepthRange[] = "depthRange"; +constexpr const char kRenderArea[] = "renderArea"; +constexpr const char kFlipXY[] = "flipXY"; +constexpr const char kDither[] = "dither"; +constexpr const char kMisc[] = "misc"; + +// Extended uniforms +constexpr const char kXfbBufferOffsets[] = "xfbBufferOffsets"; +constexpr const char kXfbVerticesPerInstance[] = "xfbVerticesPerInstance"; +constexpr const char kUnused[] = "unused"; +constexpr const char kUnused2[] = "unused2"; +} // anonymous namespace + +// Class DriverUniform +bool DriverUniform::addComputeDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable) +{ + constexpr size_t kNumComputeDriverUniforms = 1; + constexpr std::array kComputeDriverUniformNames = { + {kAcbBufferOffsets}}; + + ASSERT(!mDriverUniforms); + // This field list mirrors the structure of ComputeDriverUniforms in ContextVk.cpp. + TFieldList *driverFieldList = new TFieldList; + + const std::array kDriverUniformTypes = {{ + new TType(EbtUInt, EbpHigh, EvqGlobal, 4), + }}; + + for (size_t uniformIndex = 0; uniformIndex < kNumComputeDriverUniforms; ++uniformIndex) + { + TField *driverUniformField = + new TField(kDriverUniformTypes[uniformIndex], + ImmutableString(kComputeDriverUniformNames[uniformIndex]), TSourceLoc(), + SymbolType::AngleInternal); + driverFieldList->push_back(driverUniformField); + } + + // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms". + TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); + layoutQualifier.blockStorage = EbsStd140; + layoutQualifier.pushConstant = true; + + mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform, + layoutQualifier, TMemoryQualifier::Create(), 0, + ImmutableString(vk::kDriverUniformsBlockName), + ImmutableString(vk::kDriverUniformsVarName)); + return mDriverUniforms != nullptr; +} + +TFieldList *DriverUniform::createUniformFields(TSymbolTable *symbolTable) +{ + constexpr size_t kNumGraphicsDriverUniforms = 6; + constexpr std::array kGraphicsDriverUniformNames = {{ + kAcbBufferOffsets, + kDepthRange, + kRenderArea, + kFlipXY, + kDither, + kMisc, + }}; + + // This field list mirrors the structure of GraphicsDriverUniforms in ContextVk.cpp. + TFieldList *driverFieldList = new TFieldList; + + const std::array kDriverUniformTypes = {{ + // acbBufferOffsets: Packed ubyte8 + new TType(EbtUInt, EbpHigh, EvqGlobal, 2), + // depthRange: Near and far depth + new TType(EbtFloat, EbpHigh, EvqGlobal, 2), + // renderArea: Packed ushort2 + new TType(EbtUInt, EbpHigh, EvqGlobal), + // flipXY: Packed snorm4 + new TType(EbtUInt, EbpHigh, EvqGlobal), + // dither: ushort + new TType(EbtUInt, EbpHigh, EvqGlobal), + // misc: Various bits of state + new TType(EbtUInt, EbpHigh, EvqGlobal), + }}; + + for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniforms; ++uniformIndex) + { + TField *driverUniformField = + new TField(kDriverUniformTypes[uniformIndex], + ImmutableString(kGraphicsDriverUniformNames[uniformIndex]), TSourceLoc(), + SymbolType::AngleInternal); + driverFieldList->push_back(driverUniformField); + } + + return driverFieldList; +} + +const TType *DriverUniform::createEmulatedDepthRangeType(TSymbolTable *symbolTable) +{ + // If already defined, return it immediately. + if (mEmulatedDepthRangeType != nullptr) + { + return mEmulatedDepthRangeType; + } + + // Create the depth range type. + TFieldList *depthRangeParamsFields = new TFieldList(); + TType *floatType = new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1); + depthRangeParamsFields->push_back( + new TField(floatType, ImmutableString("near"), TSourceLoc(), SymbolType::AngleInternal)); + depthRangeParamsFields->push_back( + new TField(floatType, ImmutableString("far"), TSourceLoc(), SymbolType::AngleInternal)); + depthRangeParamsFields->push_back( + new TField(floatType, ImmutableString("diff"), TSourceLoc(), SymbolType::AngleInternal)); + + TStructure *emulatedDepthRangeParams = new TStructure( + symbolTable, kEmulatedDepthRangeParams, depthRangeParamsFields, SymbolType::AngleInternal); + + mEmulatedDepthRangeType = new TType(emulatedDepthRangeParams, false); + + return mEmulatedDepthRangeType; +} + +// The Add*DriverUniformsToShader operation adds an internal uniform block to a shader. The driver +// block is used to implement Vulkan-specific features and workarounds. Returns the driver uniforms +// variable. +// +// There are Graphics and Compute variations as they require different uniforms. +bool DriverUniform::addGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable) +{ + ASSERT(!mDriverUniforms); + + // Declare the depth range struct type. + const TType *emulatedDepthRangeType = createEmulatedDepthRangeType(symbolTable); + const TType *emulatedDepthRangeDeclType = new TType(emulatedDepthRangeType->getStruct(), true); + + const TVariable *depthRangeVar = + new TVariable(symbolTable->nextUniqueId(), kEmptyImmutableString, SymbolType::Empty, + TExtension::UNDEFINED, emulatedDepthRangeDeclType); + + DeclareGlobalVariable(root, depthRangeVar); + + TFieldList *driverFieldList = createUniformFields(symbolTable); + if (mMode == DriverUniformMode::InterfaceBlock) + { + // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms". + TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); + layoutQualifier.blockStorage = EbsStd140; + layoutQualifier.pushConstant = true; + + mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform, + layoutQualifier, TMemoryQualifier::Create(), 0, + ImmutableString(vk::kDriverUniformsBlockName), + ImmutableString(vk::kDriverUniformsVarName)); + } + else + { + // Declare a structure "ANGLEUniformBlock" with instance name "ANGLE_angleUniforms". + // This code path is taken only by the direct-to-Metal backend, and the assumptions + // about the naming conventions of ANGLE-internal variables run too deeply to rename + // this one. + auto varName = ImmutableString("ANGLE_angleUniforms"); + auto result = DeclareStructure(root, symbolTable, driverFieldList, EvqUniform, + TMemoryQualifier::Create(), 0, + ImmutableString(vk::kDriverUniformsBlockName), &varName); + mDriverUniforms = result.second; + } + + return mDriverUniforms != nullptr; +} + +TIntermTyped *DriverUniform::createDriverUniformRef(const char *fieldName) const +{ + size_t fieldIndex = 0; + if (mMode == DriverUniformMode::InterfaceBlock) + { + fieldIndex = + FindFieldIndex(mDriverUniforms->getType().getInterfaceBlock()->fields(), fieldName); + } + else + { + fieldIndex = FindFieldIndex(mDriverUniforms->getType().getStruct()->fields(), fieldName); + } + + TIntermSymbol *angleUniformsRef = new TIntermSymbol(mDriverUniforms); + TConstantUnion *uniformIndex = new TConstantUnion; + uniformIndex->setIConst(static_cast(fieldIndex)); + TIntermConstantUnion *indexRef = + new TIntermConstantUnion(uniformIndex, *StaticType::GetBasic()); + if (mMode == DriverUniformMode::InterfaceBlock) + { + return new TIntermBinary(EOpIndexDirectInterfaceBlock, angleUniformsRef, indexRef); + } + return new TIntermBinary(EOpIndexDirectStruct, angleUniformsRef, indexRef); +} + +TIntermTyped *DriverUniform::getAcbBufferOffsets() const +{ + return createDriverUniformRef(kAcbBufferOffsets); +} + +TIntermTyped *DriverUniform::getDepthRange() const +{ + ASSERT(mEmulatedDepthRangeType != nullptr); + + TIntermTyped *depthRangeRef = createDriverUniformRef(kDepthRange); + TIntermTyped *nearRef = new TIntermSwizzle(depthRangeRef, {0}); + TIntermTyped *farRef = new TIntermSwizzle(depthRangeRef->deepCopy(), {1}); + TIntermTyped *diff = new TIntermBinary(EOpSub, farRef, nearRef); + + TIntermSequence args = { + nearRef->deepCopy(), + farRef->deepCopy(), + diff, + }; + + return TIntermAggregate::CreateConstructor(*mEmulatedDepthRangeType, &args); +} + +TIntermTyped *DriverUniform::getViewportZScale() const +{ + ASSERT(mEmulatedDepthRangeType != nullptr); + + TIntermTyped *depthRangeRef = createDriverUniformRef(kDepthRange); + TIntermTyped *nearRef = new TIntermSwizzle(depthRangeRef, {0}); + TIntermTyped *farRef = new TIntermSwizzle(depthRangeRef->deepCopy(), {1}); + + TIntermTyped *isNegative = new TIntermBinary(EOpLessThan, farRef, nearRef); + + return new TIntermTernary(isNegative, CreateFloatNode(-1, EbpMedium), + CreateFloatNode(1, EbpMedium)); +} + +TIntermTyped *DriverUniform::getHalfRenderArea() const +{ + TIntermTyped *renderAreaRef = createDriverUniformRef(kRenderArea); + TIntermTyped *width = new TIntermBinary(EOpBitwiseAnd, renderAreaRef, CreateUIntNode(0xFFFF)); + TIntermTyped *height = + new TIntermBinary(EOpBitShiftRight, renderAreaRef->deepCopy(), CreateUIntNode(16)); + + TIntermSequence widthArgs = { + width, + }; + TIntermTyped *widthAsFloat = + TIntermAggregate::CreateConstructor(*StaticType::GetBasic(), &widthArgs); + + TIntermSequence heightArgs = { + height, + }; + TIntermTyped *heightAsFloat = TIntermAggregate::CreateConstructor( + *StaticType::GetBasic(), &heightArgs); + + TIntermSequence args = { + widthAsFloat, + heightAsFloat, + }; + + TIntermTyped *renderArea = + TIntermAggregate::CreateConstructor(*StaticType::GetBasic(), &args); + return new TIntermBinary(EOpVectorTimesScalar, renderArea, CreateFloatNode(0.5, EbpMedium)); +} + +TIntermTyped *DriverUniform::getFlipXY(TSymbolTable *symbolTable, DriverUniformFlip stage) const +{ + TIntermTyped *flipXY = createDriverUniformRef(kFlipXY); + TIntermTyped *values = CreateBuiltInUnaryFunctionCallNode( + "unpackSnorm4x8", flipXY, *symbolTable, + GetESSLOrGLSLVersion(symbolTable->getShaderSpec(), 310, 400)); + + if (stage == DriverUniformFlip::Fragment) + { + return new TIntermSwizzle(values, {0, 1}); + } + + return new TIntermSwizzle(values, {2, 3}); +} + +TIntermTyped *DriverUniform::getNegFlipXY(TSymbolTable *symbolTable, DriverUniformFlip stage) const +{ + TIntermTyped *flipXY = getFlipXY(symbolTable, stage); + + constexpr std::array kMultiplier = {1, -1}; + return new TIntermBinary(EOpMul, flipXY, CreateVecNode(kMultiplier.data(), 2, EbpLow)); +} + +TIntermTyped *DriverUniform::getDither() const +{ + return createDriverUniformRef(kDither); +} + +TIntermTyped *DriverUniform::getSwapXY() const +{ + TIntermTyped *miscRef = createDriverUniformRef(kMisc); + TIntermTyped *swapXY = new TIntermBinary(EOpBitwiseAnd, miscRef, + CreateUIntNode(vk::kDriverUniformsMiscSwapXYMask)); + + TIntermSequence args = { + swapXY, + }; + return TIntermAggregate::CreateConstructor(*StaticType::GetBasic(), + &args); +} + +TIntermTyped *DriverUniform::getAdvancedBlendEquation() const +{ + TIntermTyped *miscRef = createDriverUniformRef(kMisc); + TIntermTyped *equation = + new TIntermBinary(EOpBitShiftRight, miscRef, + CreateUIntNode(vk::kDriverUniformsMiscAdvancedBlendEquationOffset)); + equation = new TIntermBinary(EOpBitwiseAnd, equation, + CreateUIntNode(vk::kDriverUniformsMiscAdvancedBlendEquationMask)); + + return equation; +} + +TIntermTyped *DriverUniform::getNumSamples() const +{ + TIntermTyped *miscRef = createDriverUniformRef(kMisc); + TIntermTyped *sampleCount = new TIntermBinary( + EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscSampleCountOffset)); + sampleCount = new TIntermBinary(EOpBitwiseAnd, sampleCount, + CreateUIntNode(vk::kDriverUniformsMiscSampleCountMask)); + + return sampleCount; +} + +TIntermTyped *DriverUniform::getClipDistancesEnabled() const +{ + TIntermTyped *miscRef = createDriverUniformRef(kMisc); + TIntermTyped *enabledMask = new TIntermBinary( + EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscEnabledClipPlanesOffset)); + enabledMask = new TIntermBinary(EOpBitwiseAnd, enabledMask, + CreateUIntNode(vk::kDriverUniformsMiscEnabledClipPlanesMask)); + + return enabledMask; +} + +TIntermTyped *DriverUniform::getTransformDepth() const +{ + TIntermTyped *miscRef = createDriverUniformRef(kMisc); + TIntermTyped *transformDepth = new TIntermBinary( + EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscTransformDepthOffset)); + transformDepth = new TIntermBinary(EOpBitwiseAnd, transformDepth, + CreateUIntNode(vk::kDriverUniformsMiscTransformDepthMask)); + + TIntermSequence args = { + transformDepth, + }; + return TIntermAggregate::CreateConstructor(*StaticType::GetBasic(), + &args); +} + +// +// Class DriverUniformExtended +// +TFieldList *DriverUniformExtended::createUniformFields(TSymbolTable *symbolTable) +{ + TFieldList *driverFieldList = DriverUniform::createUniformFields(symbolTable); + + constexpr size_t kNumGraphicsDriverUniformsExt = 4; + constexpr std::array + kGraphicsDriverUniformNamesExt = { + {kXfbBufferOffsets, kXfbVerticesPerInstance, kUnused, kUnused2}}; + + const std::array kDriverUniformTypesExt = {{ + // xfbBufferOffsets: uvec4 + new TType(EbtInt, EbpHigh, EvqGlobal, 4), + // xfbVerticesPerInstance: uint + new TType(EbtInt, EbpHigh, EvqGlobal), + // unused: uvec3 + new TType(EbtUInt, EbpHigh, EvqGlobal), + new TType(EbtUInt, EbpHigh, EvqGlobal, 2), + }}; + + for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniformsExt; ++uniformIndex) + { + TField *driverUniformField = + new TField(kDriverUniformTypesExt[uniformIndex], + ImmutableString(kGraphicsDriverUniformNamesExt[uniformIndex]), TSourceLoc(), + SymbolType::AngleInternal); + driverFieldList->push_back(driverUniformField); + } + + return driverFieldList; +} + +TIntermTyped *DriverUniformExtended::getXfbBufferOffsets() const +{ + return createDriverUniformRef(kXfbBufferOffsets); +} + +TIntermTyped *DriverUniformExtended::getXfbVerticesPerInstance() const +{ + return createDriverUniformRef(kXfbVerticesPerInstance); +} + +TIntermTyped *MakeSwapXMultiplier(TIntermTyped *swapped) +{ + // float(!swapped) + TIntermSequence args = { + new TIntermUnary(EOpLogicalNot, swapped, nullptr), + }; + return TIntermAggregate::CreateConstructor(*StaticType::GetBasic(), &args); +} + +TIntermTyped *MakeSwapYMultiplier(TIntermTyped *swapped) +{ + // float(swapped) + TIntermSequence args = { + swapped, + }; + return TIntermAggregate::CreateConstructor(*StaticType::GetBasic(), &args); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/DriverUniform.h b/gfx/angle/checkout/src/compiler/translator/tree_util/DriverUniform.h new file mode 100644 index 0000000000..53eebae74d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/DriverUniform.h @@ -0,0 +1,110 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// DriverUniform.h: Add code to support driver uniforms +// + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_DRIVERUNIFORM_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_DRIVERUNIFORM_H_ + +#include "common/angleutils.h" +#include "compiler/translator/Types.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TIntermNode; +class TSymbolTable; +class TIntermTyped; +class TIntermSwizzle; +class TIntermBinary; + +enum class DriverUniformMode +{ + // Define the driver uniforms as an interface block. Used by the + // Vulkan and Metal/SPIR-V backends. + InterfaceBlock, + + // Define the driver uniforms as a structure. Used by the + // direct-to-MSL Metal backend. + Structure +}; + +enum class DriverUniformFlip +{ + // Flip uniforms for fragment shaders + Fragment, + // Flip uniforms for pre-rasterization stages. These differ from the fragment values by whether + // the viewport needs to be flipped, and whether negative viewports are supported. + PreFragment, +}; + +class DriverUniform +{ + public: + DriverUniform(DriverUniformMode mode) + : mMode(mode), mDriverUniforms(nullptr), mEmulatedDepthRangeType(nullptr) + {} + virtual ~DriverUniform() = default; + + bool addComputeDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable); + bool addGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable); + + TIntermTyped *getAcbBufferOffsets() const; + TIntermTyped *getDepthRange() const; + TIntermTyped *getViewportZScale() const; + TIntermTyped *getHalfRenderArea() const; + TIntermTyped *getFlipXY(TSymbolTable *symbolTable, DriverUniformFlip stage) const; + // Returns vec2(flip.x, -flip.y) + TIntermTyped *getNegFlipXY(TSymbolTable *symbolTable, DriverUniformFlip stage) const; + TIntermTyped *getDither() const; + TIntermTyped *getSwapXY() const; + TIntermTyped *getAdvancedBlendEquation() const; + TIntermTyped *getNumSamples() const; + TIntermTyped *getClipDistancesEnabled() const; + TIntermTyped *getTransformDepth() const; + + virtual TIntermTyped *getViewport() const { return nullptr; } + virtual TIntermTyped *getXfbBufferOffsets() const { return nullptr; } + virtual TIntermTyped *getXfbVerticesPerInstance() const { return nullptr; } + + const TVariable *getDriverUniformsVariable() const { return mDriverUniforms; } + + protected: + TIntermTyped *createDriverUniformRef(const char *fieldName) const; + virtual TFieldList *createUniformFields(TSymbolTable *symbolTable); + const TType *createEmulatedDepthRangeType(TSymbolTable *symbolTable); + + const DriverUniformMode mMode; + const TVariable *mDriverUniforms; + TType *mEmulatedDepthRangeType; +}; + +class DriverUniformExtended : public DriverUniform +{ + public: + DriverUniformExtended(DriverUniformMode mode) : DriverUniform(mode) {} + ~DriverUniformExtended() override {} + + TIntermTyped *getXfbBufferOffsets() const override; + TIntermTyped *getXfbVerticesPerInstance() const override; + + protected: + TFieldList *createUniformFields(TSymbolTable *symbolTable) override; +}; + +// Returns either (1,0) or (0,1) based on whether X and Y should remain as-is or swapped +// respectively. dot((x,y), multiplier) will yield x, and dot((x,y), multiplier.yx) will yield y in +// the possibly-swapped coordinates. +// +// Each component is separately returned by a function +TIntermTyped *MakeSwapXMultiplier(TIntermTyped *swapped); +TIntermTyped *MakeSwapYMultiplier(TIntermTyped *swapped); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_DRIVERUNIFORM_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/FindFunction.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/FindFunction.cpp new file mode 100644 index 0000000000..198040df14 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/FindFunction.cpp @@ -0,0 +1,32 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FindFunction.cpp: Find functions. + +#include "compiler/translator/tree_util/FindFunction.h" + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Symbol.h" + +namespace sh +{ + +size_t FindFirstFunctionDefinitionIndex(TIntermBlock *root) +{ + const TIntermSequence &sequence = *root->getSequence(); + for (size_t index = 0; index < sequence.size(); ++index) + { + TIntermNode *node = sequence[index]; + TIntermFunctionDefinition *nodeFunction = node->getAsFunctionDefinition(); + if (nodeFunction != nullptr) + { + return index; + } + } + return std::numeric_limits::max(); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/FindFunction.h b/gfx/angle/checkout/src/compiler/translator/tree_util/FindFunction.h new file mode 100644 index 0000000000..ced6b7e96e --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/FindFunction.h @@ -0,0 +1,21 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FindFunction.h: Adds functions to find functions + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_FINDFUNCTION_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_FINDFUNCTION_H_ + +#include + +namespace sh +{ +class TIntermBlock; + +size_t FindFirstFunctionDefinitionIndex(TIntermBlock *root); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_FINDFUNCTION_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/FindMain.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/FindMain.cpp new file mode 100644 index 0000000000..833948602a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/FindMain.cpp @@ -0,0 +1,54 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FindMain.cpp: Find the main() function definition in a given AST. + +#include "compiler/translator/tree_util/FindMain.h" + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Symbol.h" + +namespace sh +{ + +size_t FindMainIndex(TIntermBlock *root) +{ + const TIntermSequence &sequence = *root->getSequence(); + for (size_t index = 0; index < sequence.size(); ++index) + { + TIntermNode *node = sequence[index]; + TIntermFunctionDefinition *nodeFunction = node->getAsFunctionDefinition(); + if (nodeFunction != nullptr && nodeFunction->getFunction()->isMain()) + { + return index; + } + } + return std::numeric_limits::max(); +} + +TIntermFunctionDefinition *FindMain(TIntermBlock *root) +{ + for (TIntermNode *node : *root->getSequence()) + { + TIntermFunctionDefinition *nodeFunction = node->getAsFunctionDefinition(); + if (nodeFunction != nullptr && nodeFunction->getFunction()->isMain()) + { + return nodeFunction; + } + } + return nullptr; +} + +TIntermBlock *FindMainBody(TIntermBlock *root) +{ + TIntermFunctionDefinition *main = FindMain(root); + ASSERT(main != nullptr); + TIntermBlock *mainBody = main->getBody(); + ASSERT(mainBody != nullptr); + return mainBody; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/FindMain.h b/gfx/angle/checkout/src/compiler/translator/tree_util/FindMain.h new file mode 100644 index 0000000000..bbdcbe978a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/FindMain.h @@ -0,0 +1,24 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FindMain.h: Adds functions to get the main function definition and its body. + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_FINDMAIN_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_FINDMAIN_H_ + +#include + +namespace sh +{ +class TIntermBlock; +class TIntermFunctionDefinition; + +size_t FindMainIndex(TIntermBlock *root); +TIntermFunctionDefinition *FindMain(TIntermBlock *root); +TIntermBlock *FindMainBody(TIntermBlock *root); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_FINDMAIN_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/FindPreciseNodes.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/FindPreciseNodes.cpp new file mode 100644 index 0000000000..2943117314 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/FindPreciseNodes.cpp @@ -0,0 +1,703 @@ +// +// Copyright 2021 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// FindPreciseNodes.cpp: Propagates |precise| to AST nodes. +// +// The high level algorithm is as follows. For every node that "assigns" to a precise object, +// subobject (a precise struct whose field is being assigned) or superobject (a struct with a +// precise field), two things happen: +// +// - The operation is marked precise if it's an arithmetic operation +// - The right hand side of the assignment is made precise. If only a subobject is precise, only +// the corresponding subobject of the right hand side is made precise. +// + +#include "compiler/translator/tree_util/FindPreciseNodes.h" + +#include "common/hash_utils.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +// An access chain applied to a variable. The |precise|-ness of a node does not change when +// indexing arrays, selecting matrix columns or swizzle vectors. This access chain thus only +// includes block field selections. The access chain is used to identify the part of an object +// that is or should be |precise|. If both a.b.c and a.b are precise, only a.b is every considered. +class AccessChain +{ + public: + AccessChain() = default; + + bool operator==(const AccessChain &other) const { return mChain == other.mChain; } + + const TVariable *build(TIntermTyped *lvalue); + + const TVector &getChain() const { return mChain; } + + void reduceChain(size_t newSize) + { + ASSERT(newSize <= mChain.size()); + mChain.resize(newSize); + } + void clear() { reduceChain(0); } + void push_back(size_t index) { mChain.push_back(index); } + void pop_front(size_t n); + void append(const AccessChain &other) + { + mChain.insert(mChain.end(), other.mChain.begin(), other.mChain.end()); + } + bool removePrefix(const AccessChain &other); + + private: + TVector mChain; +}; + +bool IsIndexOp(TOperator op) +{ + switch (op) + { + case EOpIndexDirect: + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: + case EOpIndexIndirect: + return true; + default: + return false; + } +} + +const TVariable *AccessChain::build(TIntermTyped *lvalue) +{ + if (lvalue->getAsSwizzleNode()) + { + return build(lvalue->getAsSwizzleNode()->getOperand()); + } + if (lvalue->getAsSymbolNode()) + { + const TVariable *var = &lvalue->getAsSymbolNode()->variable(); + + // For fields of nameless interface blocks, add the field index too. + if (var->getType().getInterfaceBlock() != nullptr) + { + mChain.push_back(var->getType().getInterfaceBlockFieldIndex()); + } + + return var; + } + TIntermBinary *binary = lvalue->getAsBinaryNode(); + ASSERT(binary); + + TOperator op = binary->getOp(); + ASSERT(IsIndexOp(op)); + + const TVariable *var = build(binary->getLeft()); + + if (op == EOpIndexDirectStruct || op == EOpIndexDirectInterfaceBlock) + { + int fieldIndex = binary->getRight()->getAsConstantUnion()->getIConst(0); + mChain.push_back(fieldIndex); + } + + return var; +} + +void AccessChain::pop_front(size_t n) +{ + std::rotate(mChain.begin(), mChain.begin() + n, mChain.end()); + reduceChain(mChain.size() - n); +} + +bool AccessChain::removePrefix(const AccessChain &other) +{ + // First, make sure the common part of the two access chains match. + size_t commonSize = std::min(mChain.size(), other.mChain.size()); + + for (size_t index = 0; index < commonSize; ++index) + { + if (mChain[index] != other.mChain[index]) + { + return false; + } + } + + // Remove the common part from the access chain. If other is a deeper access chain, this access + // chain will become empty. + pop_front(commonSize); + + return true; +} + +AccessChain GetAssignmentAccessChain(TIntermOperator *node) +{ + // The assignment is either a unary or a binary node, and the lvalue is always the first child. + AccessChain lvalueAccessChain; + lvalueAccessChain.build(node->getChildNode(0)->getAsTyped()); + return lvalueAccessChain; +} + +template +void TraverseIndexNodesOnly(TIntermNode *node, Traverser *traverser) +{ + if (node->getAsSwizzleNode()) + { + node = node->getAsSwizzleNode()->getOperand(); + } + + if (node->getAsSymbolNode()) + { + return; + } + + TIntermBinary *binary = node->getAsBinaryNode(); + ASSERT(binary); + + TOperator op = binary->getOp(); + ASSERT(IsIndexOp(op)); + + if (op == EOpIndexIndirect) + { + binary->getRight()->traverse(traverser); + } + + TraverseIndexNodesOnly(binary->getLeft(), traverser); +} + +// An object, which could be a sub-object of a variable. +struct ObjectAndAccessChain +{ + const TVariable *variable; + AccessChain accessChain; +}; + +bool operator==(const ObjectAndAccessChain &a, const ObjectAndAccessChain &b) +{ + return a.variable == b.variable && a.accessChain == b.accessChain; +} + +struct ObjectAndAccessChainHash +{ + size_t operator()(const ObjectAndAccessChain &object) const + { + size_t result = angle::ComputeGenericHash(&object.variable, sizeof(object.variable)); + if (!object.accessChain.getChain().empty()) + { + result = + result ^ angle::ComputeGenericHash(object.accessChain.getChain().data(), + object.accessChain.getChain().size() * + sizeof(object.accessChain.getChain()[0])); + } + return result; + } +}; + +// A map from variables to AST nodes that modify them (i.e. nodes where IsAssignment(op)). +using VariableToAssignmentNodeMap = angle::HashMap>; +// A set of |return| nodes from functions with a |precise| return value. +using PreciseReturnNodes = angle::HashSet; +// A set of precise objects that need processing, or have been processed. +using PreciseObjectSet = angle::HashSet; + +struct ASTInfo +{ + // Generic information about the tree: + VariableToAssignmentNodeMap variableAssignmentNodeMap; + // Information pertaining to |precise| expressions: + PreciseReturnNodes preciseReturnNodes; + PreciseObjectSet preciseObjectsToProcess; + PreciseObjectSet preciseObjectsVisited; +}; + +int GetObjectPreciseSubChainLength(const ObjectAndAccessChain &object) +{ + const TType &type = object.variable->getType(); + + if (type.isPrecise()) + { + return 0; + } + + const TFieldListCollection *block = type.getInterfaceBlock(); + if (block == nullptr) + { + block = type.getStruct(); + } + const TVector &accessChain = object.accessChain.getChain(); + + for (size_t length = 0; length < accessChain.size(); ++length) + { + ASSERT(block != nullptr); + + const TField *field = block->fields()[accessChain[length]]; + if (field->type()->isPrecise()) + { + return static_cast(length + 1); + } + + block = field->type()->getStruct(); + } + + return -1; +} + +void AddPreciseObject(ASTInfo *info, const ObjectAndAccessChain &object) +{ + if (info->preciseObjectsVisited.count(object) > 0) + { + return; + } + + info->preciseObjectsToProcess.insert(object); + info->preciseObjectsVisited.insert(object); +} + +void AddPreciseSubObjects(ASTInfo *info, const ObjectAndAccessChain &object); + +void AddObjectIfPrecise(ASTInfo *info, const ObjectAndAccessChain &object) +{ + // See if the access chain is already precise, and if so add the minimum access chain that is + // precise. + int preciseSubChainLength = GetObjectPreciseSubChainLength(object); + if (preciseSubChainLength == -1) + { + // If the access chain is not precise, see if there are any fields of it that are precise, + // and add those individually. + AddPreciseSubObjects(info, object); + return; + } + + ObjectAndAccessChain preciseObject = object; + preciseObject.accessChain.reduceChain(preciseSubChainLength); + + AddPreciseObject(info, preciseObject); +} + +void AddPreciseSubObjects(ASTInfo *info, const ObjectAndAccessChain &object) +{ + const TFieldListCollection *block = object.variable->getType().getInterfaceBlock(); + if (block == nullptr) + { + block = object.variable->getType().getStruct(); + } + const TVector &accessChain = object.accessChain.getChain(); + + for (size_t length = 0; length < accessChain.size(); ++length) + { + block = block->fields()[accessChain[length]]->type()->getStruct(); + } + + if (block == nullptr) + { + return; + } + + for (size_t fieldIndex = 0; fieldIndex < block->fields().size(); ++fieldIndex) + { + ObjectAndAccessChain subObject = object; + subObject.accessChain.push_back(fieldIndex); + + // If the field is precise, add it as a precise subobject. Otherwise recurse. + if (block->fields()[fieldIndex]->type()->isPrecise()) + { + AddPreciseObject(info, subObject); + } + else + { + AddPreciseSubObjects(info, subObject); + } + } +} + +bool IsArithmeticOp(TOperator op) +{ + switch (op) + { + case EOpNegative: + + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + + case EOpAdd: + case EOpSub: + case EOpMul: + case EOpDiv: + case EOpIMod: + + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: + + case EOpAddAssign: + case EOpSubAssign: + + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + + case EOpDivAssign: + case EOpIModAssign: + + case EOpDot: + return true; + default: + return false; + } +} + +// A traverser that gathers the following information, used to kick off processing: +// +// - For each variable, the AST nodes that modify it. +// - The set of |precise| return AST node. +// - The set of |precise| access chains assigned to. +// +class InfoGatherTraverser : public TIntermTraverser +{ + public: + InfoGatherTraverser(ASTInfo *info) : TIntermTraverser(true, false, false), mInfo(info) {} + + bool visitUnary(Visit visit, TIntermUnary *node) override + { + // If the node is an assignment (i.e. ++ and --), store the relevant information. + if (!IsAssignment(node->getOp())) + { + return true; + } + + visitLvalue(node, node->getOperand()); + return false; + } + + bool visitBinary(Visit visit, TIntermBinary *node) override + { + if (IsAssignment(node->getOp())) + { + visitLvalue(node, node->getLeft()); + + node->getRight()->traverse(this); + + return false; + } + + return true; + } + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + const TIntermSequence &sequence = *(node->getSequence()); + TIntermSymbol *symbol = sequence.front()->getAsSymbolNode(); + TIntermBinary *initNode = sequence.front()->getAsBinaryNode(); + TIntermTyped *initExpression = nullptr; + + if (symbol == nullptr) + { + ASSERT(initNode->getOp() == EOpInitialize); + + symbol = initNode->getLeft()->getAsSymbolNode(); + initExpression = initNode->getRight(); + } + + ASSERT(symbol); + ObjectAndAccessChain object = {&symbol->variable(), {}}; + AddObjectIfPrecise(mInfo, object); + + if (initExpression) + { + mInfo->variableAssignmentNodeMap[object.variable].push_back(initNode); + + // Visit the init expression, which may itself have assignments. + initExpression->traverse(this); + } + + return false; + } + + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override + { + mCurrentFunction = node->getFunction(); + + for (size_t paramIndex = 0; paramIndex < mCurrentFunction->getParamCount(); ++paramIndex) + { + ObjectAndAccessChain param = {mCurrentFunction->getParam(paramIndex), {}}; + AddObjectIfPrecise(mInfo, param); + } + + return true; + } + + bool visitBranch(Visit visit, TIntermBranch *node) override + { + if (node->getFlowOp() == EOpReturn && node->getChildCount() == 1 && + mCurrentFunction->getReturnType().isPrecise()) + { + mInfo->preciseReturnNodes.insert(node); + } + + return true; + } + + bool visitGlobalQualifierDeclaration(Visit visit, + TIntermGlobalQualifierDeclaration *node) override + { + if (node->isPrecise()) + { + ObjectAndAccessChain preciseObject = {&node->getSymbol()->variable(), {}}; + AddPreciseObject(mInfo, preciseObject); + } + + return false; + } + + private: + void visitLvalue(TIntermOperator *assignmentNode, TIntermTyped *lvalueNode) + { + AccessChain lvalueChain; + const TVariable *lvalueBase = lvalueChain.build(lvalueNode); + mInfo->variableAssignmentNodeMap[lvalueBase].push_back(assignmentNode); + + ObjectAndAccessChain lvalue = {lvalueBase, lvalueChain}; + AddObjectIfPrecise(mInfo, lvalue); + + TraverseIndexNodesOnly(lvalueNode, this); + } + + ASTInfo *mInfo = nullptr; + const TFunction *mCurrentFunction = nullptr; +}; + +// A traverser that, given an access chain, traverses an expression and marks parts of it |precise|. +// For example, in the expression |Struct1(a, Struct2(b, c), d)|: +// +// - Given access chain [1], both |b| and |c| are marked precise. +// - Given access chain [1, 0], only |b| is marked precise. +// +// When access chain is empty, arithmetic nodes are marked |precise| and any access chains found in +// their children is recursively added for processing. +// +// The access chain given to the traverser is derived from the left hand side of an assignment, +// while the traverser is run on the right hand side. +class PropagatePreciseTraverser : public TIntermTraverser +{ + public: + PropagatePreciseTraverser(ASTInfo *info) : TIntermTraverser(true, false, false), mInfo(info) {} + + void propagatePrecise(TIntermNode *expression, const AccessChain &accessChain) + { + mCurrentAccessChain = accessChain; + expression->traverse(this); + } + + bool visitUnary(Visit visit, TIntermUnary *node) override + { + // Unary operations cannot be applied to structures. + ASSERT(mCurrentAccessChain.getChain().empty()); + + // Mark arithmetic nodes as |precise|. + if (IsArithmeticOp(node->getOp())) + { + node->setIsPrecise(); + } + + // Mark the operand itself |precise| too. + return true; + } + + bool visitBinary(Visit visit, TIntermBinary *node) override + { + if (IsIndexOp(node->getOp())) + { + // Append the remaining access chain with that of the node, and mark that as |precise|. + // For example, if we are evaluating an expression and expecting to mark the access + // chain [1, 3] as |precise|, and the node itself has access chain [0, 2] applied to + // variable V, then what ends up being |precise| is V with access chain [0, 2, 1, 3]. + AccessChain nodeAccessChain; + const TVariable *baseVariable = nodeAccessChain.build(node); + nodeAccessChain.append(mCurrentAccessChain); + + ObjectAndAccessChain preciseObject = {baseVariable, nodeAccessChain}; + AddPreciseObject(mInfo, preciseObject); + + // Visit index nodes, each of which should be considered |precise| in its entirety. + mCurrentAccessChain.clear(); + TraverseIndexNodesOnly(node, this); + + return false; + } + + if (node->getOp() == EOpComma) + { + // For expr1,expr2, consider only expr2 as that's the one whose calculation is relevant. + node->getRight()->traverse(this); + return false; + } + + // Mark arithmetic nodes as |precise|. + if (IsArithmeticOp(node->getOp())) + { + node->setIsPrecise(); + } + + if (IsAssignment(node->getOp()) || node->getOp() == EOpInitialize) + { + // If the node itself is a[...] op= expr, consider only expr as |precise|, as that's the + // one whose calculation is significant. + node->getRight()->traverse(this); + + // The indices used on the left hand side are also significant in their entirety. + mCurrentAccessChain.clear(); + TraverseIndexNodesOnly(node->getLeft(), this); + + return false; + } + + // Binary operations cannot be applied to structures. + ASSERT(mCurrentAccessChain.getChain().empty()); + + // Mark the operands themselves |precise| too. + return true; + } + + void visitSymbol(TIntermSymbol *symbol) override + { + // Mark the symbol together with the current access chain as |precise|. + ObjectAndAccessChain preciseObject = {&symbol->variable(), mCurrentAccessChain}; + AddPreciseObject(mInfo, preciseObject); + } + + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + // If this is a struct constructor and the access chain is not empty, only apply |precise| + // to the field selected by the access chain. + const TType &type = node->getType(); + const bool isStructConstructor = + node->getOp() == EOpConstruct && type.getStruct() != nullptr && !type.isArray(); + + if (!mCurrentAccessChain.getChain().empty() && isStructConstructor) + { + size_t selectedFieldIndex = mCurrentAccessChain.getChain().front(); + mCurrentAccessChain.pop_front(1); + + ASSERT(selectedFieldIndex < node->getChildCount()); + + // Visit only said field. + node->getChildNode(selectedFieldIndex)->traverse(this); + return false; + } + + // If this is an array constructor, each element is equally |precise| with the same access + // chain. Otherwise there cannot be any access chain for constructors. + if (node->getOp() == EOpConstruct) + { + ASSERT(type.isArray() || mCurrentAccessChain.getChain().empty()); + return true; + } + + // Otherwise this is a function call. The access chain is irrelevant and every (non-out) + // parameter of the function call should be considered |precise|. + mCurrentAccessChain.clear(); + + const TFunction *function = node->getFunction(); + ASSERT(function); + + for (size_t paramIndex = 0; paramIndex < function->getParamCount(); ++paramIndex) + { + if (function->getParam(paramIndex)->getType().getQualifier() != EvqParamOut) + { + node->getChildNode(paramIndex)->traverse(this); + } + } + + // Mark arithmetic nodes as |precise|. + if (IsArithmeticOp(node->getOp())) + { + node->setIsPrecise(); + } + + return false; + } + + private: + ASTInfo *mInfo = nullptr; + AccessChain mCurrentAccessChain; +}; +} // anonymous namespace + +void FindPreciseNodes(TCompiler *compiler, TIntermBlock *root) +{ + ASTInfo info; + + InfoGatherTraverser infoGather(&info); + root->traverse(&infoGather); + + PropagatePreciseTraverser propagator(&info); + + // First, get return expressions out of the way by propagating |precise|. + for (TIntermBranch *returnNode : info.preciseReturnNodes) + { + ASSERT(returnNode->getChildCount() == 1); + propagator.propagatePrecise(returnNode->getChildNode(0), {}); + } + + // Now take |precise| access chains one by one, and propagate their |precise|-ness to the right + // hand side of all assignments in which they are on the left hand side, as well as the + // arithmetic expression that assigns to them. + + while (!info.preciseObjectsToProcess.empty()) + { + // Get one |precise| object to process. + auto first = info.preciseObjectsToProcess.begin(); + const ObjectAndAccessChain toProcess = *first; + info.preciseObjectsToProcess.erase(first); + + // Propagate |precise| to every node where it's assigned to. + const TVector &assignmentNodes = + info.variableAssignmentNodeMap[toProcess.variable]; + for (TIntermOperator *assignmentNode : assignmentNodes) + { + AccessChain assignmentAccessChain = GetAssignmentAccessChain(assignmentNode); + + // There are two possibilities: + // + // - The assignment is to a bigger access chain than that which is being processed, in + // which case the entire right hand side is marked |precise|, + // - The assignment is to a smaller access chain, in which case only the subobject of + // the right hand side that corresponds to the remaining part of the access chain must + // be marked |precise|. + // + // For example, if processing |a.b.c| as a |precise| access chain: + // + // - If the assignment is to |a.b.c.d|, then the entire right hand side must be + // |precise|. + // - If the assignment is to |a.b|, only the |.c| part of the right hand side expression + // must be |precise|. + // - If the assignment is to |a.e|, there is nothing to do. + // + AccessChain remainingAccessChain = toProcess.accessChain; + if (!remainingAccessChain.removePrefix(assignmentAccessChain)) + { + continue; + } + + propagator.propagatePrecise(assignmentNode, remainingAccessChain); + } + } + + // The AST nodes now contain information gathered by this post-processing step, and so the tree + // must no longer be transformed. + compiler->enableValidateNoMoreTransformations(); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/FindPreciseNodes.h b/gfx/angle/checkout/src/compiler/translator/tree_util/FindPreciseNodes.h new file mode 100644 index 0000000000..1992ff15af --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/FindPreciseNodes.h @@ -0,0 +1,25 @@ +// +// Copyright 2021 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// FindPreciseNodes.h: Propagates |precise| to AST nodes. In SPIR-V, the corresponding decoration +// (NoContraction) is applied on the intermediate result of operations that affect the |precise| +// variables, not the variables themselves. + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_FINDPRECISENODES_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_FINDPRECISENODES_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; + +void FindPreciseNodes(TCompiler *compiler, TIntermBlock *root); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_FINDPRECISENODES_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/FindSymbolNode.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/FindSymbolNode.cpp new file mode 100644 index 0000000000..2951399390 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/FindSymbolNode.cpp @@ -0,0 +1,53 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// FindSymbol.cpp: +// Utility for finding a symbol node inside an AST tree. + +#include "compiler/translator/tree_util/FindSymbolNode.h" + +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class SymbolFinder : public TIntermTraverser +{ + public: + SymbolFinder(const ImmutableString &symbolName) + : TIntermTraverser(true, false, false), mSymbolName(symbolName), mNodeFound(nullptr) + {} + + void visitSymbol(TIntermSymbol *node) override + { + if (node->variable().symbolType() != SymbolType::Empty && node->getName() == mSymbolName) + { + mNodeFound = node; + } + } + + bool isFound() const { return mNodeFound != nullptr; } + const TIntermSymbol *getNode() const { return mNodeFound; } + + private: + ImmutableString mSymbolName; + TIntermSymbol *mNodeFound; +}; + +} // anonymous namespace + +const TIntermSymbol *FindSymbolNode(TIntermNode *root, const ImmutableString &symbolName) +{ + SymbolFinder finder(symbolName); + root->traverse(&finder); + return finder.getNode(); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/FindSymbolNode.h b/gfx/angle/checkout/src/compiler/translator/tree_util/FindSymbolNode.h new file mode 100644 index 0000000000..09349484a4 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/FindSymbolNode.h @@ -0,0 +1,23 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// FindSymbolNode.h: +// Utility for finding a symbol node inside an AST tree. + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_FINDSYMBOLNODE_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_FINDSYMBOLNODE_H_ + +namespace sh +{ + +class ImmutableString; +class TIntermNode; +class TIntermSymbol; + +const TIntermSymbol *FindSymbolNode(TIntermNode *root, const ImmutableString &symbolName); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_FINDSYMBOLNODE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/IntermNodePatternMatcher.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermNodePatternMatcher.cpp new file mode 100644 index 0000000000..59241bcf7a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermNodePatternMatcher.cpp @@ -0,0 +1,213 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// IntermNodePatternMatcher is a helper class for matching node trees to given patterns. +// It can be used whenever the same checks for certain node structures are common to multiple AST +// traversers. +// + +#include "compiler/translator/tree_util/IntermNodePatternMatcher.h" + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +bool ContainsMatrixNode(const TIntermSequence &sequence) +{ + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + TIntermTyped *node = sequence[ii]->getAsTyped(); + if (node && node->isMatrix()) + return true; + } + return false; +} + +bool ContainsVectorNode(const TIntermSequence &sequence) +{ + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + TIntermTyped *node = sequence[ii]->getAsTyped(); + if (node && node->isVector()) + return true; + } + return false; +} + +} // anonymous namespace + +IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask) {} + +// static +bool IntermNodePatternMatcher::IsDynamicIndexingOfNonSSBOVectorOrMatrix(TIntermBinary *node) +{ + return IsDynamicIndexingOfVectorOrMatrix(node) && !IsInShaderStorageBlock(node->getLeft()); +} + +// static +bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node) +{ + return node->getOp() == EOpIndexIndirect && !node->getLeft()->isArray() && + node->getLeft()->getBasicType() != EbtStruct; +} + +// static +bool IntermNodePatternMatcher::IsDynamicIndexingOfSwizzledVector(TIntermBinary *node) +{ + return IsDynamicIndexingOfVectorOrMatrix(node) && node->getLeft()->getAsSwizzleNode(); +} + +bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode) const +{ + if ((mMask & kExpressionReturningArray) != 0) + { + if (node->isArray() && node->getOp() == EOpAssign && parentNode != nullptr && + !parentNode->getAsBlock()) + { + return true; + } + } + + if ((mMask & kUnfoldedShortCircuitExpression) != 0) + { + if (node->getRight()->hasSideEffects() && + (node->getOp() == EOpLogicalOr || node->getOp() == EOpLogicalAnd)) + { + return true; + } + } + return false; +} + +bool IntermNodePatternMatcher::match(TIntermUnary *node) const +{ + if ((mMask & kArrayLengthMethod) != 0) + { + if (node->getOp() == EOpArrayLength) + { + return true; + } + } + return false; +} + +bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode) const +{ + // L-value tracking information is needed to check for dynamic indexing in L-value. + // Traversers that don't track l-values can still use this class and match binary nodes with + // this variation of this method if they don't need to check for dynamic indexing in l-values. + ASSERT((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) == 0); + return matchInternal(node, parentNode); +} + +bool IntermNodePatternMatcher::match(TIntermBinary *node, + TIntermNode *parentNode, + bool isLValueRequiredHere) const +{ + if (matchInternal(node, parentNode)) + { + return true; + } + if ((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) != 0) + { + if (isLValueRequiredHere && IsDynamicIndexingOfVectorOrMatrix(node)) + { + return true; + } + } + return false; +} + +bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode) const +{ + if ((mMask & kExpressionReturningArray) != 0) + { + if (parentNode != nullptr) + { + TIntermBinary *parentBinary = parentNode->getAsBinaryNode(); + bool parentIsAssignment = + (parentBinary != nullptr && + (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize)); + + if (node->getType().isArray() && !parentIsAssignment && + (node->isConstructor() || node->isFunctionCall() || + (BuiltInGroup::IsBuiltIn(node->getOp()) && + !BuiltInGroup::IsMath(node->getOp()))) && + !parentNode->getAsBlock()) + { + return true; + } + } + } + if ((mMask & kScalarizedVecOrMatConstructor) != 0) + { + if (node->getOp() == EOpConstruct) + { + if (node->getType().isVector() && ContainsMatrixNode(*(node->getSequence()))) + { + return true; + } + else if (node->getType().isMatrix() && ContainsVectorNode(*(node->getSequence()))) + { + return true; + } + } + } + return false; +} + +bool IntermNodePatternMatcher::match(TIntermTernary *node) const +{ + if ((mMask & kUnfoldedShortCircuitExpression) != 0) + { + return true; + } + return false; +} + +bool IntermNodePatternMatcher::match(TIntermDeclaration *node) const +{ + if ((mMask & kMultiDeclaration) != 0) + { + if (node->getSequence()->size() > 1) + { + return true; + } + } + if ((mMask & kArrayDeclaration) != 0) + { + if (node->getSequence()->front()->getAsTyped()->getType().isStructureContainingArrays()) + { + return true; + } + // Need to check from all declarators whether they are arrays since that may vary between + // declarators. + for (TIntermNode *declarator : *node->getSequence()) + { + if (declarator->getAsTyped()->isArray()) + { + return true; + } + } + } + if ((mMask & kNamelessStructDeclaration) != 0) + { + TIntermTyped *declarator = node->getSequence()->front()->getAsTyped(); + if (declarator->getBasicType() == EbtStruct && + declarator->getType().getStruct()->symbolType() == SymbolType::Empty) + { + return true; + } + } + return false; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/IntermNodePatternMatcher.h b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermNodePatternMatcher.h new file mode 100644 index 0000000000..b8321b930c --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermNodePatternMatcher.h @@ -0,0 +1,81 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// IntermNodePatternMatcher is a helper class for matching node trees to given patterns. +// It can be used whenever the same checks for certain node structures are common to multiple AST +// traversers. +// + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_INTERMNODEPATTERNMATCHER_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_INTERMNODEPATTERNMATCHER_H_ + +namespace sh +{ + +class TIntermAggregate; +class TIntermBinary; +class TIntermDeclaration; +class TIntermNode; +class TIntermTernary; +class TIntermUnary; + +class IntermNodePatternMatcher +{ + public: + static bool IsDynamicIndexingOfNonSSBOVectorOrMatrix(TIntermBinary *node); + static bool IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node); + static bool IsDynamicIndexingOfSwizzledVector(TIntermBinary *node); + + enum PatternType : unsigned int + { + // Matches expressions that are unfolded to if statements by UnfoldShortCircuitToIf + kUnfoldedShortCircuitExpression = 1u << 0u, + + // Matches expressions that return arrays with the exception of simple statements where a + // constructor or function call result is assigned. + kExpressionReturningArray = 1u << 1u, + + // Matches dynamic indexing of vectors or matrices in l-values. + kDynamicIndexingOfVectorOrMatrixInLValue = 1u << 2u, + + // Matches declarations with more than one declared variables. + kMultiDeclaration = 1u << 3u, + + // Matches declarations of arrays. + kArrayDeclaration = 1u << 4u, + + // Matches declarations of structs where the struct type does not have a name. + kNamelessStructDeclaration = 1u << 5u, + + // Matches array length() method. + kArrayLengthMethod = 1u << 6u, + + // Matches a vector or matrix constructor whose arguments are scalarized by the + // scalarizeVecOrMatConstructorArguments workaround. + kScalarizedVecOrMatConstructor = 1u << 7u, + }; + IntermNodePatternMatcher(const unsigned int mask); + + bool match(TIntermUnary *node) const; + + bool match(TIntermBinary *node, TIntermNode *parentNode) const; + + // Use this version for checking binary node matches in case you're using flag + // kDynamicIndexingOfVectorOrMatrixInLValue. + bool match(TIntermBinary *node, TIntermNode *parentNode, bool isLValueRequiredHere) const; + + bool match(TIntermAggregate *node, TIntermNode *parentNode) const; + bool match(TIntermTernary *node) const; + bool match(TIntermDeclaration *node) const; + + private: + const unsigned int mMask; + + bool matchInternal(TIntermBinary *node, TIntermNode *parentNode) const; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_INTERMNODEPATTERNMATCHER_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/IntermNode_util.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermNode_util.cpp new file mode 100644 index 0000000000..a7bb211425 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermNode_util.cpp @@ -0,0 +1,436 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// IntermNode_util.cpp: High-level utilities for creating AST nodes and node hierarchies. Mostly +// meant to be used in AST transforms. + +#include "compiler/translator/tree_util/IntermNode_util.h" + +#include "compiler/translator/FunctionLookup.h" +#include "compiler/translator/SymbolTable.h" + +namespace sh +{ + +namespace +{ + +const TFunction *LookUpBuiltInFunction(const char *name, + const TIntermSequence *arguments, + const TSymbolTable &symbolTable, + int shaderVersion) +{ + const ImmutableString &mangledName = TFunctionLookup::GetMangledName(name, *arguments); + const TSymbol *symbol = symbolTable.findBuiltIn(mangledName, shaderVersion); + if (symbol) + { + ASSERT(symbol->isFunction()); + return static_cast(symbol); + } + return nullptr; +} + +} // anonymous namespace + +TIntermFunctionPrototype *CreateInternalFunctionPrototypeNode(const TFunction &func) +{ + return new TIntermFunctionPrototype(&func); +} + +TIntermFunctionDefinition *CreateInternalFunctionDefinitionNode(const TFunction &func, + TIntermBlock *functionBody) +{ + return new TIntermFunctionDefinition(new TIntermFunctionPrototype(&func), functionBody); +} + +TIntermTyped *CreateZeroNode(const TType &type) +{ + TType constType(type); + constType.setQualifier(EvqConst); + + if (!type.isArray() && type.getBasicType() != EbtStruct) + { + size_t size = constType.getObjectSize(); + TConstantUnion *u = new TConstantUnion[size]; + for (size_t i = 0; i < size; ++i) + { + switch (type.getBasicType()) + { + case EbtFloat: + u[i].setFConst(0.0f); + break; + case EbtInt: + u[i].setIConst(0); + break; + case EbtUInt: + u[i].setUConst(0u); + break; + case EbtBool: + u[i].setBConst(false); + break; + default: + // CreateZeroNode is called by ParseContext that keeps parsing even when an + // error occurs, so it is possible for CreateZeroNode to be called with + // non-basic types. This happens only on error condition but CreateZeroNode + // needs to return a value with the correct type to continue the type check. + // That's why we handle non-basic type by setting whatever value, we just need + // the type to be right. + u[i].setIConst(42); + break; + } + } + + TIntermConstantUnion *node = new TIntermConstantUnion(u, constType); + return node; + } + + TIntermSequence arguments; + + if (type.isArray()) + { + TType elementType(type); + elementType.toArrayElementType(); + + size_t arraySize = type.getOutermostArraySize(); + for (size_t i = 0; i < arraySize; ++i) + { + arguments.push_back(CreateZeroNode(elementType)); + } + } + else + { + ASSERT(type.getBasicType() == EbtStruct); + + const TStructure *structure = type.getStruct(); + for (const auto &field : structure->fields()) + { + arguments.push_back(CreateZeroNode(*field->type())); + } + } + + return TIntermAggregate::CreateConstructor(constType, &arguments); +} + +TIntermConstantUnion *CreateFloatNode(float value, TPrecision precision) +{ + TConstantUnion *u = new TConstantUnion[1]; + u[0].setFConst(value); + + TType type(EbtFloat, precision, EvqConst, 1); + return new TIntermConstantUnion(u, type); +} + +TIntermConstantUnion *CreateVecNode(const float values[], + unsigned int vecSize, + TPrecision precision) +{ + TConstantUnion *u = new TConstantUnion[vecSize]; + for (unsigned int channel = 0; channel < vecSize; ++channel) + { + u[channel].setFConst(values[channel]); + } + + TType type(EbtFloat, precision, EvqConst, static_cast(vecSize)); + return new TIntermConstantUnion(u, type); +} + +TIntermConstantUnion *CreateUVecNode(const unsigned int values[], + unsigned int vecSize, + TPrecision precision) +{ + TConstantUnion *u = new TConstantUnion[vecSize]; + for (unsigned int channel = 0; channel < vecSize; ++channel) + { + u[channel].setUConst(values[channel]); + } + + TType type(EbtUInt, precision, EvqConst, static_cast(vecSize)); + return new TIntermConstantUnion(u, type); +} + +TIntermConstantUnion *CreateIndexNode(int index) +{ + TConstantUnion *u = new TConstantUnion[1]; + u[0].setIConst(index); + + TType type(EbtInt, EbpHigh, EvqConst, 1); + return new TIntermConstantUnion(u, type); +} + +TIntermConstantUnion *CreateUIntNode(unsigned int value) +{ + TConstantUnion *u = new TConstantUnion[1]; + u[0].setUConst(value); + + TType type(EbtUInt, EbpHigh, EvqConst, 1); + return new TIntermConstantUnion(u, type); +} + +TIntermConstantUnion *CreateBoolNode(bool value) +{ + TConstantUnion *u = new TConstantUnion[1]; + u[0].setBConst(value); + + TType type(EbtBool, EbpUndefined, EvqConst, 1); + return new TIntermConstantUnion(u, type); +} + +TVariable *CreateTempVariable(TSymbolTable *symbolTable, const TType *type) +{ + ASSERT(symbolTable != nullptr); + // TODO(oetuaho): Might be useful to sanitize layout qualifier etc. on the type of the created + // variable. This might need to be done in other places as well. + return new TVariable(symbolTable, kEmptyImmutableString, type, SymbolType::AngleInternal); +} + +TVariable *CreateTempVariable(TSymbolTable *symbolTable, const TType *type, TQualifier qualifier) +{ + ASSERT(symbolTable != nullptr); + if (type->getQualifier() == qualifier) + { + return CreateTempVariable(symbolTable, type); + } + TType *typeWithQualifier = new TType(*type); + typeWithQualifier->setQualifier(qualifier); + return CreateTempVariable(symbolTable, typeWithQualifier); +} + +TIntermSymbol *CreateTempSymbolNode(const TVariable *tempVariable) +{ + ASSERT(tempVariable->symbolType() == SymbolType::AngleInternal); + ASSERT(tempVariable->getType().getQualifier() == EvqTemporary || + tempVariable->getType().getQualifier() == EvqConst || + tempVariable->getType().getQualifier() == EvqGlobal); + return new TIntermSymbol(tempVariable); +} + +TIntermDeclaration *CreateTempDeclarationNode(const TVariable *tempVariable) +{ + TIntermDeclaration *tempDeclaration = new TIntermDeclaration(); + tempDeclaration->appendDeclarator(CreateTempSymbolNode(tempVariable)); + return tempDeclaration; +} + +TIntermDeclaration *CreateTempInitDeclarationNode(const TVariable *tempVariable, + TIntermTyped *initializer) +{ + ASSERT(initializer != nullptr); + TIntermSymbol *tempSymbol = CreateTempSymbolNode(tempVariable); + TIntermDeclaration *tempDeclaration = new TIntermDeclaration(); + TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer); + tempDeclaration->appendDeclarator(tempInit); + return tempDeclaration; +} + +TIntermBinary *CreateTempAssignmentNode(const TVariable *tempVariable, TIntermTyped *rightNode) +{ + ASSERT(rightNode != nullptr); + TIntermSymbol *tempSymbol = CreateTempSymbolNode(tempVariable); + return new TIntermBinary(EOpAssign, tempSymbol, rightNode); +} + +TVariable *DeclareTempVariable(TSymbolTable *symbolTable, + const TType *type, + TQualifier qualifier, + TIntermDeclaration **declarationOut) +{ + TVariable *variable = CreateTempVariable(symbolTable, type, qualifier); + *declarationOut = CreateTempDeclarationNode(variable); + return variable; +} + +TVariable *DeclareTempVariable(TSymbolTable *symbolTable, + TIntermTyped *initializer, + TQualifier qualifier, + TIntermDeclaration **declarationOut) +{ + TVariable *variable = + CreateTempVariable(symbolTable, new TType(initializer->getType()), qualifier); + *declarationOut = CreateTempInitDeclarationNode(variable, initializer); + return variable; +} + +std::pair DeclareStructure( + TIntermBlock *root, + TSymbolTable *symbolTable, + TFieldList *fieldList, + TQualifier qualifier, + const TMemoryQualifier &memoryQualifier, + uint32_t arraySize, + const ImmutableString &structTypeName, + const ImmutableString *structInstanceName) +{ + TStructure *structure = + new TStructure(symbolTable, structTypeName, fieldList, SymbolType::AngleInternal); + + auto makeStructureType = [&](bool isStructSpecifier) { + TType *structureType = new TType(structure, isStructSpecifier); + structureType->setQualifier(qualifier); + structureType->setMemoryQualifier(memoryQualifier); + if (arraySize > 0) + { + structureType->makeArray(arraySize); + } + return structureType; + }; + + TIntermSequence insertSequence; + + TVariable *typeVar = new TVariable(symbolTable, kEmptyImmutableString, makeStructureType(true), + SymbolType::Empty); + insertSequence.push_back(new TIntermDeclaration{typeVar}); + + TVariable *instanceVar = nullptr; + if (structInstanceName) + { + instanceVar = new TVariable(symbolTable, *structInstanceName, makeStructureType(false), + SymbolType::AngleInternal); + insertSequence.push_back(new TIntermDeclaration{instanceVar}); + } + + size_t firstFunctionIndex = FindFirstFunctionDefinitionIndex(root); + root->insertChildNodes(firstFunctionIndex, insertSequence); + + return {typeVar, instanceVar}; +} + +const TVariable *DeclareInterfaceBlock(TIntermBlock *root, + TSymbolTable *symbolTable, + TFieldList *fieldList, + TQualifier qualifier, + const TLayoutQualifier &layoutQualifier, + const TMemoryQualifier &memoryQualifier, + uint32_t arraySize, + const ImmutableString &blockTypeName, + const ImmutableString &blockVariableName) +{ + // Define an interface block. + TInterfaceBlock *interfaceBlock = new TInterfaceBlock( + symbolTable, blockTypeName, fieldList, layoutQualifier, SymbolType::AngleInternal); + + // Turn the inteface block into a declaration. + TType *interfaceBlockType = new TType(interfaceBlock, qualifier, layoutQualifier); + interfaceBlockType->setMemoryQualifier(memoryQualifier); + if (arraySize > 0) + { + interfaceBlockType->makeArray(arraySize); + } + + TIntermDeclaration *interfaceBlockDecl = new TIntermDeclaration; + TVariable *interfaceBlockVar = + new TVariable(symbolTable, blockVariableName, interfaceBlockType, + blockVariableName.empty() ? SymbolType::Empty : SymbolType::AngleInternal); + TIntermSymbol *interfaceBlockDeclarator = new TIntermSymbol(interfaceBlockVar); + interfaceBlockDecl->appendDeclarator(interfaceBlockDeclarator); + + // Insert the declarations before the first function. + TIntermSequence insertSequence; + insertSequence.push_back(interfaceBlockDecl); + + size_t firstFunctionIndex = FindFirstFunctionDefinitionIndex(root); + root->insertChildNodes(firstFunctionIndex, insertSequence); + + return interfaceBlockVar; +} + +TIntermBlock *EnsureBlock(TIntermNode *node) +{ + if (node == nullptr) + return nullptr; + TIntermBlock *blockNode = node->getAsBlock(); + if (blockNode != nullptr) + return blockNode; + + blockNode = new TIntermBlock(); + blockNode->setLine(node->getLine()); + blockNode->appendStatement(node); + return blockNode; +} + +TIntermSymbol *ReferenceGlobalVariable(const ImmutableString &name, const TSymbolTable &symbolTable) +{ + const TSymbol *symbol = symbolTable.findGlobal(name); + ASSERT(symbol && symbol->isVariable()); + return new TIntermSymbol(static_cast(symbol)); +} + +TIntermSymbol *ReferenceBuiltInVariable(const ImmutableString &name, + const TSymbolTable &symbolTable, + int shaderVersion) +{ + const TVariable *var = + static_cast(symbolTable.findBuiltIn(name, shaderVersion)); + ASSERT(var); + return new TIntermSymbol(var); +} + +TIntermTyped *CreateBuiltInFunctionCallNode(const char *name, + TIntermSequence *arguments, + const TSymbolTable &symbolTable, + int shaderVersion) +{ + const TFunction *fn = LookUpBuiltInFunction(name, arguments, symbolTable, shaderVersion); + ASSERT(fn); + TOperator op = fn->getBuiltInOp(); + if (BuiltInGroup::IsMath(op) && arguments->size() == 1) + { + return new TIntermUnary(op, arguments->at(0)->getAsTyped(), fn); + } + return TIntermAggregate::CreateBuiltInFunctionCall(*fn, arguments); +} + +TIntermTyped *CreateBuiltInFunctionCallNode(const char *name, + const std::initializer_list &arguments, + const TSymbolTable &symbolTable, + int shaderVersion) +{ + TIntermSequence argSequence(arguments); + return CreateBuiltInFunctionCallNode(name, &argSequence, symbolTable, shaderVersion); +} + +TIntermTyped *CreateBuiltInUnaryFunctionCallNode(const char *name, + TIntermTyped *argument, + const TSymbolTable &symbolTable, + int shaderVersion) +{ + return CreateBuiltInFunctionCallNode(name, {argument}, symbolTable, shaderVersion); +} + +int GetESSLOrGLSLVersion(ShShaderSpec spec, int esslVersion, int glslVersion) +{ + return IsDesktopGLSpec(spec) ? glslVersion : esslVersion; +} + +// Returns true if a block ends in a branch (break, continue, return, etc). This is only correct +// after PruneNoOps, because it expects empty blocks after a branch to have been already pruned, +// i.e. a block can only end in a branch if its last statement is a branch or is a block ending in +// branch. +bool EndsInBranch(TIntermBlock *block) +{ + while (block != nullptr) + { + // Get the last statement of the block. + TIntermSequence &statements = *block->getSequence(); + if (statements.empty()) + { + return false; + } + + TIntermNode *lastStatement = statements.back(); + + // If it's a branch itself, we have the answer. + if (lastStatement->getAsBranchNode()) + { + return true; + } + + // Otherwise, see if it's a block that ends in a branch + block = lastStatement->getAsBlock(); + } + + return false; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/IntermNode_util.h b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermNode_util.h new file mode 100644 index 0000000000..5cf0a117d3 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermNode_util.h @@ -0,0 +1,128 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// IntermNode_util.h: High-level utilities for creating AST nodes and node hierarchies. Mostly meant +// to be used in AST transforms. + +#ifndef COMPILER_TRANSLATOR_INTERMNODEUTIL_H_ +#define COMPILER_TRANSLATOR_INTERMNODEUTIL_H_ + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/tree_util/FindFunction.h" + +namespace sh +{ + +class TSymbolTable; +class TVariable; + +TIntermFunctionPrototype *CreateInternalFunctionPrototypeNode(const TFunction &func); +TIntermFunctionDefinition *CreateInternalFunctionDefinitionNode(const TFunction &func, + TIntermBlock *functionBody); + +TIntermTyped *CreateZeroNode(const TType &type); +TIntermConstantUnion *CreateFloatNode(float value, TPrecision precision); +TIntermConstantUnion *CreateVecNode(const float values[], + unsigned int vecSize, + TPrecision precision); +TIntermConstantUnion *CreateUVecNode(const unsigned int values[], + unsigned int vecSize, + TPrecision precision); +TIntermConstantUnion *CreateIndexNode(int index); +TIntermConstantUnion *CreateUIntNode(unsigned int value); +TIntermConstantUnion *CreateBoolNode(bool value); + +TVariable *CreateTempVariable(TSymbolTable *symbolTable, const TType *type); +TVariable *CreateTempVariable(TSymbolTable *symbolTable, const TType *type, TQualifier qualifier); + +TIntermSymbol *CreateTempSymbolNode(const TVariable *tempVariable); +TIntermDeclaration *CreateTempDeclarationNode(const TVariable *tempVariable); +TIntermDeclaration *CreateTempInitDeclarationNode(const TVariable *tempVariable, + TIntermTyped *initializer); +TIntermBinary *CreateTempAssignmentNode(const TVariable *tempVariable, TIntermTyped *rightNode); + +TVariable *DeclareTempVariable(TSymbolTable *symbolTable, + const TType *type, + TQualifier qualifier, + TIntermDeclaration **declarationOut); +TVariable *DeclareTempVariable(TSymbolTable *symbolTable, + TIntermTyped *initializer, + TQualifier qualifier, + TIntermDeclaration **declarationOut); +std::pair DeclareStructure( + TIntermBlock *root, + TSymbolTable *symbolTable, + TFieldList *fieldList, + TQualifier qualifier, + const TMemoryQualifier &memoryQualifier, + uint32_t arraySize, + const ImmutableString &structTypeName, + const ImmutableString *structInstanceName); +const TVariable *DeclareInterfaceBlock(TIntermBlock *root, + TSymbolTable *symbolTable, + TFieldList *fieldList, + TQualifier qualifier, + const TLayoutQualifier &layoutQualifier, + const TMemoryQualifier &memoryQualifier, + uint32_t arraySize, + const ImmutableString &blockTypeName, + const ImmutableString &blockVariableName); + +// If the input node is nullptr, return nullptr. +// If the input node is a block node, return it. +// If the input node is not a block node, put it inside a block node and return that. +TIntermBlock *EnsureBlock(TIntermNode *node); + +// Should be called from inside Compiler::compileTreeImpl() where the global level is in scope. +TIntermSymbol *ReferenceGlobalVariable(const ImmutableString &name, + const TSymbolTable &symbolTable); + +// Note: this can't access desktop GLSL built-ins. Those can only be accessed directly through +// BuiltIn.h. +TIntermSymbol *ReferenceBuiltInVariable(const ImmutableString &name, + const TSymbolTable &symbolTable, + int shaderVersion); + +TIntermTyped *CreateBuiltInFunctionCallNode(const char *name, + TIntermSequence *arguments, + const TSymbolTable &symbolTable, + int shaderVersion); +TIntermTyped *CreateBuiltInFunctionCallNode(const char *name, + const std::initializer_list &arguments, + const TSymbolTable &symbolTable, + int shaderVersion); +TIntermTyped *CreateBuiltInUnaryFunctionCallNode(const char *name, + TIntermTyped *argument, + const TSymbolTable &symbolTable, + int shaderVersion); + +int GetESSLOrGLSLVersion(ShShaderSpec spec, int esslVersion, int glslVersion); + +inline void GetSwizzleIndex(TVector *indexOut) {} + +template +void GetSwizzleIndex(TVector *indexOut, T arg, ArgsT... args) +{ + indexOut->push_back(arg); + GetSwizzleIndex(indexOut, args...); +} + +template +TIntermSwizzle *CreateSwizzle(TIntermTyped *reference, ArgsT... args) +{ + TVector swizzleIndex; + GetSwizzleIndex(&swizzleIndex, args...); + return new TIntermSwizzle(reference, swizzleIndex); +} + +// Returns true if a block ends in a branch (break, continue, return, etc). This is only correct +// after PruneNoOps, because it expects empty blocks after a branch to have been already pruned, +// i.e. a block can only end in a branch if its last statement is a branch or is a block ending in +// branch. +bool EndsInBranch(TIntermBlock *block); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_INTERMNODEUTIL_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/IntermRebuild.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermRebuild.cpp new file mode 100644 index 0000000000..667535fa63 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermRebuild.cpp @@ -0,0 +1,1046 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/AsNode.h" +#include "compiler/translator/tree_util/IntermRebuild.h" + +#define GUARD2(cond, failVal) \ + do \ + { \ + if (!(cond)) \ + { \ + return failVal; \ + } \ + } while (false) + +#define GUARD(cond) GUARD2(cond, nullptr) + +namespace sh +{ + +template +ANGLE_INLINE bool AllBits(T haystack, U needle) +{ + return (haystack & needle) == needle; +} + +template +ANGLE_INLINE bool AnyBits(T haystack, U needle) +{ + return (haystack & needle) != 0; +} + +//////////////////////////////////////////////////////////////////////////////// + +TIntermRebuild::BaseResult::BaseResult(BaseResult &other) + : mAction(other.mAction), + mVisit(other.mVisit), + mSingle(other.mSingle), + mMulti(std::move(other.mMulti)) +{} + +TIntermRebuild::BaseResult::BaseResult(TIntermNode &node, VisitBits visit) + : mAction(Action::ReplaceSingle), mVisit(visit), mSingle(&node) +{} + +TIntermRebuild::BaseResult::BaseResult(TIntermNode *node, VisitBits visit) + : mAction(node ? Action::ReplaceSingle : Action::Drop), + mVisit(node ? visit : VisitBits::Neither), + mSingle(node) +{} + +TIntermRebuild::BaseResult::BaseResult(std::nullptr_t) + : mAction(Action::Drop), mVisit(VisitBits::Neither), mSingle(nullptr) +{} + +TIntermRebuild::BaseResult::BaseResult(Fail) + : mAction(Action::Fail), mVisit(VisitBits::Neither), mSingle(nullptr) +{} + +TIntermRebuild::BaseResult::BaseResult(std::vector &&nodes) + : mAction(Action::ReplaceMulti), + mVisit(VisitBits::Neither), + mSingle(nullptr), + mMulti(std::move(nodes)) +{} + +void TIntermRebuild::BaseResult::moveAssignImpl(BaseResult &other) +{ + mAction = other.mAction; + mVisit = other.mVisit; + mSingle = other.mSingle; + mMulti = std::move(other.mMulti); +} + +TIntermRebuild::BaseResult TIntermRebuild::BaseResult::Multi(std::vector &&nodes) +{ + auto it = std::remove(nodes.begin(), nodes.end(), nullptr); + nodes.erase(it, nodes.end()); + return std::move(nodes); +} + +bool TIntermRebuild::BaseResult::isFail() const +{ + return mAction == Action::Fail; +} + +bool TIntermRebuild::BaseResult::isDrop() const +{ + return mAction == Action::Drop; +} + +TIntermNode *TIntermRebuild::BaseResult::single() const +{ + return mSingle; +} + +const std::vector *TIntermRebuild::BaseResult::multi() const +{ + if (mAction == Action::ReplaceMulti) + { + return &mMulti; + } + return nullptr; +} + +//////////////////////////////////////////////////////////////////////////////// + +using PreResult = TIntermRebuild::PreResult; + +PreResult::PreResult(TIntermNode &node, VisitBits visit) : BaseResult(node, visit) {} +PreResult::PreResult(TIntermNode *node, VisitBits visit) : BaseResult(node, visit) {} +PreResult::PreResult(std::nullptr_t) : BaseResult(nullptr) {} +PreResult::PreResult(Fail) : BaseResult(Fail()) {} + +PreResult::PreResult(BaseResult &&other) : BaseResult(other) {} +PreResult::PreResult(PreResult &&other) : BaseResult(other) {} + +void PreResult::operator=(PreResult &&other) +{ + moveAssignImpl(other); +} + +//////////////////////////////////////////////////////////////////////////////// + +using PostResult = TIntermRebuild::PostResult; + +PostResult::PostResult(TIntermNode &node) : BaseResult(node, VisitBits::Neither) {} +PostResult::PostResult(TIntermNode *node) : BaseResult(node, VisitBits::Neither) {} +PostResult::PostResult(std::nullptr_t) : BaseResult(nullptr) {} +PostResult::PostResult(Fail) : BaseResult(Fail()) {} + +PostResult::PostResult(PostResult &&other) : BaseResult(other) {} +PostResult::PostResult(BaseResult &&other) : BaseResult(other) {} + +void PostResult::operator=(PostResult &&other) +{ + moveAssignImpl(other); +} + +//////////////////////////////////////////////////////////////////////////////// + +TIntermRebuild::TIntermRebuild(TCompiler &compiler, bool preVisit, bool postVisit) + : mCompiler(compiler), + mSymbolTable(compiler.getSymbolTable()), + mPreVisit(preVisit), + mPostVisit(postVisit) +{ + ASSERT(preVisit || postVisit); +} + +TIntermRebuild::~TIntermRebuild() +{ + ASSERT(!mNodeStack.value); + ASSERT(!mNodeStack.tail); +} + +const TFunction *TIntermRebuild::getParentFunction() const +{ + return mParentFunc; +} + +TIntermNode *TIntermRebuild::getParentNode(size_t offset) const +{ + ASSERT(mNodeStack.tail); + auto parent = *mNodeStack.tail; + while (offset > 0) + { + --offset; + ASSERT(parent.tail); + parent = *parent.tail; + } + return parent.value; +} + +bool TIntermRebuild::rebuildRoot(TIntermBlock &root) +{ + if (!rebuildInPlace(root)) + { + return false; + } + return mCompiler.validateAST(&root); +} + +bool TIntermRebuild::rebuildInPlace(TIntermAggregate &node) +{ + return rebuildInPlaceImpl(node); +} + +bool TIntermRebuild::rebuildInPlace(TIntermBlock &node) +{ + return rebuildInPlaceImpl(node); +} + +bool TIntermRebuild::rebuildInPlace(TIntermDeclaration &node) +{ + return rebuildInPlaceImpl(node); +} + +template +bool TIntermRebuild::rebuildInPlaceImpl(Node &node) +{ + auto *newNode = traverseAnyAs(node); + if (!newNode) + { + return false; + } + + if (newNode != &node) + { + *node.getSequence() = std::move(*newNode->getSequence()); + } + + return true; +} + +PostResult TIntermRebuild::rebuild(TIntermNode &node) +{ + return traverseAny(node); +} + +//////////////////////////////////////////////////////////////////////////////// + +template +Node *TIntermRebuild::traverseAnyAs(TIntermNode &node) +{ + PostResult result(traverseAny(node)); + if (result.mAction == Action::Fail || !result.mSingle) + { + return nullptr; + } + return asNode(result.mSingle); +} + +template +bool TIntermRebuild::traverseAnyAs(TIntermNode &node, Node *&out) +{ + PostResult result(traverseAny(node)); + if (result.mAction == Action::Fail || result.mAction == Action::ReplaceMulti) + { + return false; + } + if (!result.mSingle) + { + return true; + } + out = asNode(result.mSingle); + return out != nullptr; +} + +bool TIntermRebuild::traverseAggregateBaseChildren(TIntermAggregateBase &node) +{ + auto *const children = node.getSequence(); + ASSERT(children); + TIntermSequence newChildren; + + for (TIntermNode *child : *children) + { + ASSERT(child); + PostResult result(traverseAny(*child)); + + switch (result.mAction) + { + case Action::ReplaceSingle: + newChildren.push_back(result.mSingle); + break; + + case Action::ReplaceMulti: + for (TIntermNode *newNode : result.mMulti) + { + if (newNode) + { + newChildren.push_back(newNode); + } + } + break; + + case Action::Drop: + break; + + case Action::Fail: + return false; + + default: + ASSERT(false); + return false; + } + } + + *children = std::move(newChildren); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// + +struct TIntermRebuild::NodeStackGuard +{ + ConsList oldNodeStack; + ConsList &nodeStack; + NodeStackGuard(ConsList &nodeStack, TIntermNode *node) + : oldNodeStack(nodeStack), nodeStack(nodeStack) + { + nodeStack = {node, &oldNodeStack}; + } + ~NodeStackGuard() { nodeStack = oldNodeStack; } +}; + +PostResult TIntermRebuild::traverseAny(TIntermNode &originalNode) +{ + PreResult preResult = traversePre(originalNode); + if (!preResult.mSingle) + { + ASSERT(preResult.mVisit == VisitBits::Neither); + return std::move(preResult); + } + + TIntermNode *currNode = preResult.mSingle; + const VisitBits visit = preResult.mVisit; + const NodeType currNodeType = getNodeType(*currNode); + + currNode = traverseChildren(currNodeType, originalNode, *currNode, visit); + if (!currNode) + { + return Fail(); + } + + return traversePost(currNodeType, originalNode, *currNode, visit); +} + +PreResult TIntermRebuild::traversePre(TIntermNode &originalNode) +{ + if (!mPreVisit) + { + return {originalNode, VisitBits::Both}; + } + + NodeStackGuard guard(mNodeStack, &originalNode); + + const NodeType originalNodeType = getNodeType(originalNode); + + switch (originalNodeType) + { + case NodeType::Unknown: + ASSERT(false); + return Fail(); + case NodeType::Symbol: + return visitSymbolPre(*originalNode.getAsSymbolNode()); + case NodeType::ConstantUnion: + return visitConstantUnionPre(*originalNode.getAsConstantUnion()); + case NodeType::FunctionPrototype: + return visitFunctionPrototypePre(*originalNode.getAsFunctionPrototypeNode()); + case NodeType::PreprocessorDirective: + return visitPreprocessorDirectivePre(*originalNode.getAsPreprocessorDirective()); + case NodeType::Unary: + return visitUnaryPre(*originalNode.getAsUnaryNode()); + case NodeType::Binary: + return visitBinaryPre(*originalNode.getAsBinaryNode()); + case NodeType::Ternary: + return visitTernaryPre(*originalNode.getAsTernaryNode()); + case NodeType::Swizzle: + return visitSwizzlePre(*originalNode.getAsSwizzleNode()); + case NodeType::IfElse: + return visitIfElsePre(*originalNode.getAsIfElseNode()); + case NodeType::Switch: + return visitSwitchPre(*originalNode.getAsSwitchNode()); + case NodeType::Case: + return visitCasePre(*originalNode.getAsCaseNode()); + case NodeType::FunctionDefinition: + return visitFunctionDefinitionPre(*originalNode.getAsFunctionDefinition()); + case NodeType::Aggregate: + return visitAggregatePre(*originalNode.getAsAggregate()); + case NodeType::Block: + return visitBlockPre(*originalNode.getAsBlock()); + case NodeType::GlobalQualifierDeclaration: + return visitGlobalQualifierDeclarationPre( + *originalNode.getAsGlobalQualifierDeclarationNode()); + case NodeType::Declaration: + return visitDeclarationPre(*originalNode.getAsDeclarationNode()); + case NodeType::Loop: + return visitLoopPre(*originalNode.getAsLoopNode()); + case NodeType::Branch: + return visitBranchPre(*originalNode.getAsBranchNode()); + default: + ASSERT(false); + return Fail(); + } +} + +TIntermNode *TIntermRebuild::traverseChildren(NodeType currNodeType, + const TIntermNode &originalNode, + TIntermNode &currNode, + VisitBits visit) +{ + if (!AnyBits(visit, VisitBits::Children)) + { + return &currNode; + } + + if (AnyBits(visit, VisitBits::ChildrenRequiresSame) && &originalNode != &currNode) + { + return &currNode; + } + + NodeStackGuard guard(mNodeStack, &currNode); + + switch (currNodeType) + { + case NodeType::Unknown: + ASSERT(false); + return nullptr; + case NodeType::Symbol: + return &currNode; + case NodeType::ConstantUnion: + return &currNode; + case NodeType::FunctionPrototype: + return &currNode; + case NodeType::PreprocessorDirective: + return &currNode; + case NodeType::Unary: + return traverseUnaryChildren(*currNode.getAsUnaryNode()); + case NodeType::Binary: + return traverseBinaryChildren(*currNode.getAsBinaryNode()); + case NodeType::Ternary: + return traverseTernaryChildren(*currNode.getAsTernaryNode()); + case NodeType::Swizzle: + return traverseSwizzleChildren(*currNode.getAsSwizzleNode()); + case NodeType::IfElse: + return traverseIfElseChildren(*currNode.getAsIfElseNode()); + case NodeType::Switch: + return traverseSwitchChildren(*currNode.getAsSwitchNode()); + case NodeType::Case: + return traverseCaseChildren(*currNode.getAsCaseNode()); + case NodeType::FunctionDefinition: + return traverseFunctionDefinitionChildren(*currNode.getAsFunctionDefinition()); + case NodeType::Aggregate: + return traverseAggregateChildren(*currNode.getAsAggregate()); + case NodeType::Block: + return traverseBlockChildren(*currNode.getAsBlock()); + case NodeType::GlobalQualifierDeclaration: + return traverseGlobalQualifierDeclarationChildren( + *currNode.getAsGlobalQualifierDeclarationNode()); + case NodeType::Declaration: + return traverseDeclarationChildren(*currNode.getAsDeclarationNode()); + case NodeType::Loop: + return traverseLoopChildren(*currNode.getAsLoopNode()); + case NodeType::Branch: + return traverseBranchChildren(*currNode.getAsBranchNode()); + default: + ASSERT(false); + return nullptr; + } +} + +PostResult TIntermRebuild::traversePost(NodeType currNodeType, + const TIntermNode &originalNode, + TIntermNode &currNode, + VisitBits visit) +{ + if (!mPostVisit) + { + return currNode; + } + + if (!AnyBits(visit, VisitBits::Post)) + { + return currNode; + } + + if (AnyBits(visit, VisitBits::PostRequiresSame) && &originalNode != &currNode) + { + return currNode; + } + + NodeStackGuard guard(mNodeStack, &currNode); + + switch (currNodeType) + { + case NodeType::Unknown: + ASSERT(false); + return Fail(); + case NodeType::Symbol: + return visitSymbolPost(*currNode.getAsSymbolNode()); + case NodeType::ConstantUnion: + return visitConstantUnionPost(*currNode.getAsConstantUnion()); + case NodeType::FunctionPrototype: + return visitFunctionPrototypePost(*currNode.getAsFunctionPrototypeNode()); + case NodeType::PreprocessorDirective: + return visitPreprocessorDirectivePost(*currNode.getAsPreprocessorDirective()); + case NodeType::Unary: + return visitUnaryPost(*currNode.getAsUnaryNode()); + case NodeType::Binary: + return visitBinaryPost(*currNode.getAsBinaryNode()); + case NodeType::Ternary: + return visitTernaryPost(*currNode.getAsTernaryNode()); + case NodeType::Swizzle: + return visitSwizzlePost(*currNode.getAsSwizzleNode()); + case NodeType::IfElse: + return visitIfElsePost(*currNode.getAsIfElseNode()); + case NodeType::Switch: + return visitSwitchPost(*currNode.getAsSwitchNode()); + case NodeType::Case: + return visitCasePost(*currNode.getAsCaseNode()); + case NodeType::FunctionDefinition: + return visitFunctionDefinitionPost(*currNode.getAsFunctionDefinition()); + case NodeType::Aggregate: + return visitAggregatePost(*currNode.getAsAggregate()); + case NodeType::Block: + return visitBlockPost(*currNode.getAsBlock()); + case NodeType::GlobalQualifierDeclaration: + return visitGlobalQualifierDeclarationPost( + *currNode.getAsGlobalQualifierDeclarationNode()); + case NodeType::Declaration: + return visitDeclarationPost(*currNode.getAsDeclarationNode()); + case NodeType::Loop: + return visitLoopPost(*currNode.getAsLoopNode()); + case NodeType::Branch: + return visitBranchPost(*currNode.getAsBranchNode()); + default: + ASSERT(false); + return Fail(); + } +} + +//////////////////////////////////////////////////////////////////////////////// + +TIntermNode *TIntermRebuild::traverseAggregateChildren(TIntermAggregate &node) +{ + if (traverseAggregateBaseChildren(node)) + { + return &node; + } + return nullptr; +} + +TIntermNode *TIntermRebuild::traverseBlockChildren(TIntermBlock &node) +{ + if (traverseAggregateBaseChildren(node)) + { + return &node; + } + return nullptr; +} + +TIntermNode *TIntermRebuild::traverseDeclarationChildren(TIntermDeclaration &node) +{ + if (traverseAggregateBaseChildren(node)) + { + return &node; + } + return nullptr; +} + +TIntermNode *TIntermRebuild::traverseSwizzleChildren(TIntermSwizzle &node) +{ + auto *const operand = node.getOperand(); + ASSERT(operand); + + auto *newOperand = traverseAnyAs(*operand); + GUARD(newOperand); + + if (newOperand != operand) + { + return new TIntermSwizzle(newOperand, node.getSwizzleOffsets()); + } + + return &node; +} + +TIntermNode *TIntermRebuild::traverseBinaryChildren(TIntermBinary &node) +{ + auto *const left = node.getLeft(); + ASSERT(left); + auto *const right = node.getRight(); + ASSERT(right); + + auto *const newLeft = traverseAnyAs(*left); + GUARD(newLeft); + auto *const newRight = traverseAnyAs(*right); + GUARD(newRight); + + if (newLeft != left || newRight != right) + { + TOperator op = node.getOp(); + switch (op) + { + case TOperator::EOpIndexDirectStruct: + { + if (newLeft->getType().getInterfaceBlock()) + { + op = TOperator::EOpIndexDirectInterfaceBlock; + } + } + break; + + case TOperator::EOpIndexDirectInterfaceBlock: + { + if (newLeft->getType().getStruct()) + { + op = TOperator::EOpIndexDirectStruct; + } + } + break; + + case TOperator::EOpComma: + return TIntermBinary::CreateComma(newLeft, newRight, mCompiler.getShaderVersion()); + + default: + break; + } + + return new TIntermBinary(op, newLeft, newRight); + } + + return &node; +} + +TIntermNode *TIntermRebuild::traverseUnaryChildren(TIntermUnary &node) +{ + auto *const operand = node.getOperand(); + ASSERT(operand); + + auto *const newOperand = traverseAnyAs(*operand); + GUARD(newOperand); + + if (newOperand != operand) + { + return new TIntermUnary(node.getOp(), newOperand, node.getFunction()); + } + + return &node; +} + +TIntermNode *TIntermRebuild::traverseTernaryChildren(TIntermTernary &node) +{ + auto *const cond = node.getCondition(); + ASSERT(cond); + auto *const true_ = node.getTrueExpression(); + ASSERT(true_); + auto *const false_ = node.getFalseExpression(); + ASSERT(false_); + + auto *const newCond = traverseAnyAs(*cond); + GUARD(newCond); + auto *const newTrue = traverseAnyAs(*true_); + GUARD(newTrue); + auto *const newFalse = traverseAnyAs(*false_); + GUARD(newFalse); + + if (newCond != cond || newTrue != true_ || newFalse != false_) + { + return new TIntermTernary(newCond, newTrue, newFalse); + } + + return &node; +} + +TIntermNode *TIntermRebuild::traverseIfElseChildren(TIntermIfElse &node) +{ + auto *const cond = node.getCondition(); + ASSERT(cond); + auto *const true_ = node.getTrueBlock(); + auto *const false_ = node.getFalseBlock(); + + auto *const newCond = traverseAnyAs(*cond); + GUARD(newCond); + TIntermBlock *newTrue = nullptr; + if (true_) + { + GUARD(traverseAnyAs(*true_, newTrue)); + } + TIntermBlock *newFalse = nullptr; + if (false_) + { + GUARD(traverseAnyAs(*false_, newFalse)); + } + + if (newCond != cond || newTrue != true_ || newFalse != false_) + { + return new TIntermIfElse(newCond, newTrue, newFalse); + } + + return &node; +} + +TIntermNode *TIntermRebuild::traverseSwitchChildren(TIntermSwitch &node) +{ + auto *const init = node.getInit(); + ASSERT(init); + auto *const stmts = node.getStatementList(); + ASSERT(stmts); + + auto *const newInit = traverseAnyAs(*init); + GUARD(newInit); + auto *const newStmts = traverseAnyAs(*stmts); + GUARD(newStmts); + + if (newInit != init || newStmts != stmts) + { + return new TIntermSwitch(newInit, newStmts); + } + + return &node; +} + +TIntermNode *TIntermRebuild::traverseCaseChildren(TIntermCase &node) +{ + auto *const cond = node.getCondition(); + + TIntermTyped *newCond = nullptr; + if (cond) + { + GUARD(traverseAnyAs(*cond, newCond)); + } + + if (newCond != cond) + { + return new TIntermCase(newCond); + } + + return &node; +} + +TIntermNode *TIntermRebuild::traverseFunctionDefinitionChildren(TIntermFunctionDefinition &node) +{ + GUARD(!mParentFunc); // Function definitions cannot be nested. + mParentFunc = node.getFunction(); + struct OnExit + { + const TFunction *&parentFunc; + OnExit(const TFunction *&parentFunc) : parentFunc(parentFunc) {} + ~OnExit() { parentFunc = nullptr; } + } onExit(mParentFunc); + + auto *const proto = node.getFunctionPrototype(); + ASSERT(proto); + auto *const body = node.getBody(); + ASSERT(body); + + auto *const newProto = traverseAnyAs(*proto); + GUARD(newProto); + auto *const newBody = traverseAnyAs(*body); + GUARD(newBody); + + if (newProto != proto || newBody != body) + { + return new TIntermFunctionDefinition(newProto, newBody); + } + + return &node; +} + +TIntermNode *TIntermRebuild::traverseGlobalQualifierDeclarationChildren( + TIntermGlobalQualifierDeclaration &node) +{ + auto *const symbol = node.getSymbol(); + ASSERT(symbol); + + auto *const newSymbol = traverseAnyAs(*symbol); + GUARD(newSymbol); + + if (newSymbol != symbol) + { + return new TIntermGlobalQualifierDeclaration(newSymbol, node.isPrecise(), node.getLine()); + } + + return &node; +} + +TIntermNode *TIntermRebuild::traverseLoopChildren(TIntermLoop &node) +{ + const TLoopType loopType = node.getType(); + + auto *const init = node.getInit(); + auto *const cond = node.getCondition(); + auto *const expr = node.getExpression(); + auto *const body = node.getBody(); + ASSERT(body); + +#if defined(ANGLE_ENABLE_ASSERTS) + switch (loopType) + { + case TLoopType::ELoopFor: + break; + case TLoopType::ELoopWhile: + case TLoopType::ELoopDoWhile: + ASSERT(cond); + ASSERT(!init && !expr); + break; + default: + ASSERT(false); + break; + } +#endif + + auto *const newBody = traverseAnyAs(*body); + GUARD(newBody); + TIntermNode *newInit = nullptr; + if (init) + { + GUARD(traverseAnyAs(*init, newInit)); + } + TIntermTyped *newCond = nullptr; + if (cond) + { + GUARD(traverseAnyAs(*cond, newCond)); + } + TIntermTyped *newExpr = nullptr; + if (expr) + { + GUARD(traverseAnyAs(*expr, newExpr)); + } + + if (newInit != init || newCond != cond || newExpr != expr || newBody != body) + { + switch (loopType) + { + case TLoopType::ELoopFor: + GUARD(newBody); + break; + case TLoopType::ELoopWhile: + case TLoopType::ELoopDoWhile: + GUARD(newCond && newBody); + GUARD(!newInit && !newExpr); + break; + default: + ASSERT(false); + break; + } + return new TIntermLoop(loopType, newInit, newCond, newExpr, newBody); + } + + return &node; +} + +TIntermNode *TIntermRebuild::traverseBranchChildren(TIntermBranch &node) +{ + auto *const expr = node.getExpression(); + + TIntermTyped *newExpr = nullptr; + if (expr) + { + GUARD(traverseAnyAs(*expr, newExpr)); + } + + if (newExpr != expr) + { + return new TIntermBranch(node.getFlowOp(), newExpr); + } + + return &node; +} + +//////////////////////////////////////////////////////////////////////////////// + +PreResult TIntermRebuild::visitSymbolPre(TIntermSymbol &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitConstantUnionPre(TIntermConstantUnion &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitFunctionPrototypePre(TIntermFunctionPrototype &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitPreprocessorDirectivePre(TIntermPreprocessorDirective &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitUnaryPre(TIntermUnary &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitBinaryPre(TIntermBinary &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitTernaryPre(TIntermTernary &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitSwizzlePre(TIntermSwizzle &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitIfElsePre(TIntermIfElse &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitSwitchPre(TIntermSwitch &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitCasePre(TIntermCase &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitLoopPre(TIntermLoop &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitBranchPre(TIntermBranch &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitDeclarationPre(TIntermDeclaration &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitBlockPre(TIntermBlock &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitAggregatePre(TIntermAggregate &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitFunctionDefinitionPre(TIntermFunctionDefinition &node) +{ + return {node, VisitBits::Both}; +} + +PreResult TIntermRebuild::visitGlobalQualifierDeclarationPre( + TIntermGlobalQualifierDeclaration &node) +{ + return {node, VisitBits::Both}; +} + +//////////////////////////////////////////////////////////////////////////////// + +PostResult TIntermRebuild::visitSymbolPost(TIntermSymbol &node) +{ + return node; +} + +PostResult TIntermRebuild::visitConstantUnionPost(TIntermConstantUnion &node) +{ + return node; +} + +PostResult TIntermRebuild::visitFunctionPrototypePost(TIntermFunctionPrototype &node) +{ + return node; +} + +PostResult TIntermRebuild::visitPreprocessorDirectivePost(TIntermPreprocessorDirective &node) +{ + return node; +} + +PostResult TIntermRebuild::visitUnaryPost(TIntermUnary &node) +{ + return node; +} + +PostResult TIntermRebuild::visitBinaryPost(TIntermBinary &node) +{ + return node; +} + +PostResult TIntermRebuild::visitTernaryPost(TIntermTernary &node) +{ + return node; +} + +PostResult TIntermRebuild::visitSwizzlePost(TIntermSwizzle &node) +{ + return node; +} + +PostResult TIntermRebuild::visitIfElsePost(TIntermIfElse &node) +{ + return node; +} + +PostResult TIntermRebuild::visitSwitchPost(TIntermSwitch &node) +{ + return node; +} + +PostResult TIntermRebuild::visitCasePost(TIntermCase &node) +{ + return node; +} + +PostResult TIntermRebuild::visitLoopPost(TIntermLoop &node) +{ + return node; +} + +PostResult TIntermRebuild::visitBranchPost(TIntermBranch &node) +{ + return node; +} + +PostResult TIntermRebuild::visitDeclarationPost(TIntermDeclaration &node) +{ + return node; +} + +PostResult TIntermRebuild::visitBlockPost(TIntermBlock &node) +{ + return node; +} + +PostResult TIntermRebuild::visitAggregatePost(TIntermAggregate &node) +{ + return node; +} + +PostResult TIntermRebuild::visitFunctionDefinitionPost(TIntermFunctionDefinition &node) +{ + return node; +} + +PostResult TIntermRebuild::visitGlobalQualifierDeclarationPost( + TIntermGlobalQualifierDeclaration &node) +{ + return node; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/IntermRebuild.h b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermRebuild.h new file mode 100644 index 0000000000..7907d283ef --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermRebuild.h @@ -0,0 +1,328 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TRANSLATORMETALDIRECT_INTERMREBUILD_H_ +#define COMPILER_TRANSLATOR_TRANSLATORMETALDIRECT_INTERMREBUILD_H_ + +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/NodeType.h" + +namespace sh +{ + +// Walks the tree to rebuild nodes. +// This class is intended to be derived with overridden visitXXX functions. +// +// Each visitXXX function that does not have a Visit parameter simply has the visitor called +// exactly once, regardless of (preVisit) or (postVisit) values. + +// Each visitXXX function that has a Visit parameter behaves as follows: +// * If (preVisit): +// - The node is visited before children are traversed. +// - The returned value is used to replace the visited node. The returned value may be the same +// as the original node. +// - If multiple nodes are returned, children and post visits of the returned nodes are not +// preformed, even if it is a singleton collection. +// * If (childVisit) +// - If any new children are returned, the node is automatically rebuilt with the new children +// before post visit. +// - Depending on the type of the node, null children may be discarded. +// - Ill-typed children cause rebuild errors. Ill-typed means the node to automatically rebuild +// cannot accept a child of a certain type as input to its constructor. +// - Only instances of TIntermAggregateBase can accept Multi results for any of its children. +// If supplied, the nodes are spliced children at the spot of the original child. +// * If (postVisit) +// - The node is visited after any children are traversed. +// - Only after such a rebuild (or lack thereof), the post-visit is performed. +// +// Nodes in visit functions are allowed to be modified in place, including TIntermAggregateBase +// child sequences. +// +// The default implementations of all the visitXXX functions support full pre and post traversal +// without modifying the visited nodes. +// +class TIntermRebuild : angle::NonCopyable +{ + + enum class Action + { + ReplaceSingle, + ReplaceMulti, + Drop, + Fail, + }; + + public: + struct Fail + {}; + + enum VisitBits : size_t + { + // No bits are set. + Empty = 0u, + + // Allow visit of returned node's children. + Children = 1u << 0u, + + // Allow post visit of returned node. + Post = 1u << 1u, + + // If (Children) bit, only visit if the returned node is the same as the original node. + ChildrenRequiresSame = 1u << 2u, + + // If (Post) bit, only visit if the returned node is the same as the original node. + PostRequiresSame = 1u << 3u, + + RequireSame = ChildrenRequiresSame | PostRequiresSame, + Neither = Empty, + Both = Children | Post, + BothWhenSame = Both | RequireSame, + }; + + private: + struct NodeStackGuard; + + template + struct ConsList + { + T value; + ConsList *tail; + }; + + class BaseResult + { + BaseResult(const BaseResult &) = delete; + BaseResult &operator=(const BaseResult &) = delete; + + public: + BaseResult(BaseResult &&other) = default; + BaseResult(BaseResult &other); // For subclass move constructor impls + BaseResult(TIntermNode &node, VisitBits visit); + BaseResult(TIntermNode *node, VisitBits visit); + BaseResult(std::nullptr_t); + BaseResult(Fail); + BaseResult(std::vector &&nodes); + + void moveAssignImpl(BaseResult &other); // For subclass move assign impls + + static BaseResult Multi(std::vector &&nodes); + + template + static BaseResult Multi(Iter nodesBegin, Iter nodesEnd) + { + std::vector nodes; + for (Iter nodesCurr = nodesBegin; nodesCurr != nodesEnd; ++nodesCurr) + { + nodes.push_back(*nodesCurr); + } + return std::move(nodes); + } + + bool isFail() const; + bool isDrop() const; + TIntermNode *single() const; + const std::vector *multi() const; + + public: + Action mAction; + VisitBits mVisit; + TIntermNode *mSingle; + std::vector mMulti; + }; + + public: + class PreResult : private BaseResult + { + friend class TIntermRebuild; + + public: + PreResult(PreResult &&other); + PreResult(TIntermNode &node, VisitBits visit = VisitBits::BothWhenSame); + PreResult(TIntermNode *node, VisitBits visit = VisitBits::BothWhenSame); + PreResult(std::nullptr_t); // Used to drop a node. + PreResult(Fail); // Used to signal failure. + + void operator=(PreResult &&other); + + static PreResult Multi(std::vector &&nodes) + { + return BaseResult::Multi(std::move(nodes)); + } + + template + static PreResult Multi(Iter nodesBegin, Iter nodesEnd) + { + return BaseResult::Multi(nodesBegin, nodesEnd); + } + + using BaseResult::isDrop; + using BaseResult::isFail; + using BaseResult::multi; + using BaseResult::single; + + private: + PreResult(BaseResult &&other); + }; + + class PostResult : private BaseResult + { + friend class TIntermRebuild; + + public: + PostResult(PostResult &&other); + PostResult(TIntermNode &node); + PostResult(TIntermNode *node); + PostResult(std::nullptr_t); // Used to drop a node + PostResult(Fail); // Used to signal failure. + + void operator=(PostResult &&other); + + static PostResult Multi(std::vector &&nodes) + { + return BaseResult::Multi(std::move(nodes)); + } + + template + static PostResult Multi(Iter nodesBegin, Iter nodesEnd) + { + return BaseResult::Multi(nodesBegin, nodesEnd); + } + + using BaseResult::isDrop; + using BaseResult::isFail; + using BaseResult::multi; + using BaseResult::single; + + private: + PostResult(BaseResult &&other); + }; + + public: + TIntermRebuild(TCompiler &compiler, bool preVisit, bool postVisit); + + virtual ~TIntermRebuild(); + + // Rebuilds the tree starting at the provided root. If a new node would be returned for the + // root, the root node's children become that of the new node instead. Returns false if failure + // occurred. + [[nodiscard]] bool rebuildRoot(TIntermBlock &root); + + protected: + virtual PreResult visitSymbolPre(TIntermSymbol &node); + virtual PreResult visitConstantUnionPre(TIntermConstantUnion &node); + virtual PreResult visitFunctionPrototypePre(TIntermFunctionPrototype &node); + virtual PreResult visitPreprocessorDirectivePre(TIntermPreprocessorDirective &node); + virtual PreResult visitUnaryPre(TIntermUnary &node); + virtual PreResult visitBinaryPre(TIntermBinary &node); + virtual PreResult visitTernaryPre(TIntermTernary &node); + virtual PreResult visitSwizzlePre(TIntermSwizzle &node); + virtual PreResult visitIfElsePre(TIntermIfElse &node); + virtual PreResult visitSwitchPre(TIntermSwitch &node); + virtual PreResult visitCasePre(TIntermCase &node); + virtual PreResult visitLoopPre(TIntermLoop &node); + virtual PreResult visitBranchPre(TIntermBranch &node); + virtual PreResult visitDeclarationPre(TIntermDeclaration &node); + virtual PreResult visitBlockPre(TIntermBlock &node); + virtual PreResult visitAggregatePre(TIntermAggregate &node); + virtual PreResult visitFunctionDefinitionPre(TIntermFunctionDefinition &node); + virtual PreResult visitGlobalQualifierDeclarationPre(TIntermGlobalQualifierDeclaration &node); + + virtual PostResult visitSymbolPost(TIntermSymbol &node); + virtual PostResult visitConstantUnionPost(TIntermConstantUnion &node); + virtual PostResult visitFunctionPrototypePost(TIntermFunctionPrototype &node); + virtual PostResult visitPreprocessorDirectivePost(TIntermPreprocessorDirective &node); + virtual PostResult visitUnaryPost(TIntermUnary &node); + virtual PostResult visitBinaryPost(TIntermBinary &node); + virtual PostResult visitTernaryPost(TIntermTernary &node); + virtual PostResult visitSwizzlePost(TIntermSwizzle &node); + virtual PostResult visitIfElsePost(TIntermIfElse &node); + virtual PostResult visitSwitchPost(TIntermSwitch &node); + virtual PostResult visitCasePost(TIntermCase &node); + virtual PostResult visitLoopPost(TIntermLoop &node); + virtual PostResult visitBranchPost(TIntermBranch &node); + virtual PostResult visitDeclarationPost(TIntermDeclaration &node); + virtual PostResult visitBlockPost(TIntermBlock &node); + virtual PostResult visitAggregatePost(TIntermAggregate &node); + virtual PostResult visitFunctionDefinitionPost(TIntermFunctionDefinition &node); + virtual PostResult visitGlobalQualifierDeclarationPost(TIntermGlobalQualifierDeclaration &node); + + // Can be used to rebuild a specific node during a traversal. Useful for fine control of + // rebuilding a node's children. + [[nodiscard]] PostResult rebuild(TIntermNode &node); + + // Rebuilds the provided node in place. If a new node would be returned, the old node's children + // become that of the new node instead. Returns false if failure occurred. + [[nodiscard]] bool rebuildInPlace(TIntermAggregate &node); + + // Rebuilds the provided node in place. If a new node would be returned, the old node's children + // become that of the new node instead. Returns false if failure occurred. + [[nodiscard]] bool rebuildInPlace(TIntermBlock &node); + + // Rebuilds the provided node in place. If a new node would be returned, the old node's children + // become that of the new node instead. Returns false if failure occurred. + [[nodiscard]] bool rebuildInPlace(TIntermDeclaration &node); + + // If currently at or below a function declaration body, this returns the function that encloses + // the currently visited node. (This returns null if at a function declaration node.) + const TFunction *getParentFunction() const; + + TIntermNode *getParentNode(size_t offset = 0) const; + + private: + template + [[nodiscard]] bool rebuildInPlaceImpl(Node &node); + + PostResult traverseAny(TIntermNode &node); + + template + Node *traverseAnyAs(TIntermNode &node); + + template + bool traverseAnyAs(TIntermNode &node, Node *&out); + + PreResult traversePre(TIntermNode &originalNode); + TIntermNode *traverseChildren(NodeType currNodeType, + const TIntermNode &originalNode, + TIntermNode &currNode, + VisitBits visit); + PostResult traversePost(NodeType nodeType, + const TIntermNode &originalNode, + TIntermNode &currNode, + VisitBits visit); + + bool traverseAggregateBaseChildren(TIntermAggregateBase &node); + + TIntermNode *traverseUnaryChildren(TIntermUnary &node); + TIntermNode *traverseBinaryChildren(TIntermBinary &node); + TIntermNode *traverseTernaryChildren(TIntermTernary &node); + TIntermNode *traverseSwizzleChildren(TIntermSwizzle &node); + TIntermNode *traverseIfElseChildren(TIntermIfElse &node); + TIntermNode *traverseSwitchChildren(TIntermSwitch &node); + TIntermNode *traverseCaseChildren(TIntermCase &node); + TIntermNode *traverseLoopChildren(TIntermLoop &node); + TIntermNode *traverseBranchChildren(TIntermBranch &node); + TIntermNode *traverseDeclarationChildren(TIntermDeclaration &node); + TIntermNode *traverseBlockChildren(TIntermBlock &node); + TIntermNode *traverseAggregateChildren(TIntermAggregate &node); + TIntermNode *traverseFunctionDefinitionChildren(TIntermFunctionDefinition &node); + TIntermNode *traverseGlobalQualifierDeclarationChildren( + TIntermGlobalQualifierDeclaration &node); + + protected: + TCompiler &mCompiler; + TSymbolTable &mSymbolTable; + const TFunction *mParentFunc = nullptr; + GetNodeType getNodeType; + + private: + ConsList mNodeStack{nullptr, nullptr}; + bool mPreVisit; + bool mPostVisit; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TRANSLATORMETALDIRECT_INTERMREBUILD_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp new file mode 100644 index 0000000000..c4bbe1fa4d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp @@ -0,0 +1,708 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/tree_util/IntermTraverse.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +// Traverse the intermediate representation tree, and call a node type specific visit function for +// each node. Traversal is done recursively through the node member function traverse(). Nodes with +// children can have their whole subtree skipped if preVisit is turned on and the type specific +// function returns false. +template +void TIntermTraverser::traverse(T *node) +{ + ScopedNodeInTraversalPath addToPath(this, node); + if (!addToPath.isWithinDepthLimit()) + return; + + bool visit = true; + + // Visit the node before children if pre-visiting. + if (preVisit) + visit = node->visit(PreVisit, this); + + if (visit) + { + size_t childIndex = 0; + size_t childCount = node->getChildCount(); + + while (childIndex < childCount && visit) + { + mCurrentChildIndex = childIndex; + node->getChildNode(childIndex)->traverse(this); + mCurrentChildIndex = childIndex; + + if (inVisit && childIndex != childCount - 1) + { + visit = node->visit(InVisit, this); + } + ++childIndex; + } + + if (visit && postVisit) + node->visit(PostVisit, this); + } +} + +// Instantiate template for RewriteAtomicFunctionExpressions, in case this gets inlined thus not +// exported from the TU. +template void TIntermTraverser::traverse(TIntermNode *); + +void TIntermNode::traverse(TIntermTraverser *it) +{ + it->traverse(this); +} + +void TIntermSymbol::traverse(TIntermTraverser *it) +{ + TIntermTraverser::ScopedNodeInTraversalPath addToPath(it, this); + it->visitSymbol(this); +} + +void TIntermConstantUnion::traverse(TIntermTraverser *it) +{ + TIntermTraverser::ScopedNodeInTraversalPath addToPath(it, this); + it->visitConstantUnion(this); +} + +void TIntermFunctionPrototype::traverse(TIntermTraverser *it) +{ + TIntermTraverser::ScopedNodeInTraversalPath addToPath(it, this); + it->visitFunctionPrototype(this); +} + +void TIntermBinary::traverse(TIntermTraverser *it) +{ + it->traverseBinary(this); +} + +void TIntermUnary::traverse(TIntermTraverser *it) +{ + it->traverseUnary(this); +} + +void TIntermFunctionDefinition::traverse(TIntermTraverser *it) +{ + it->traverseFunctionDefinition(this); +} + +void TIntermBlock::traverse(TIntermTraverser *it) +{ + it->traverseBlock(this); +} + +void TIntermAggregate::traverse(TIntermTraverser *it) +{ + it->traverseAggregate(this); +} + +void TIntermLoop::traverse(TIntermTraverser *it) +{ + it->traverseLoop(this); +} + +void TIntermPreprocessorDirective::traverse(TIntermTraverser *it) +{ + it->visitPreprocessorDirective(this); +} + +bool TIntermSymbol::visit(Visit visit, TIntermTraverser *it) +{ + it->visitSymbol(this); + return false; +} + +bool TIntermConstantUnion::visit(Visit visit, TIntermTraverser *it) +{ + it->visitConstantUnion(this); + return false; +} + +bool TIntermFunctionPrototype::visit(Visit visit, TIntermTraverser *it) +{ + it->visitFunctionPrototype(this); + return false; +} + +bool TIntermFunctionDefinition::visit(Visit visit, TIntermTraverser *it) +{ + return it->visitFunctionDefinition(visit, this); +} + +bool TIntermUnary::visit(Visit visit, TIntermTraverser *it) +{ + return it->visitUnary(visit, this); +} + +bool TIntermSwizzle::visit(Visit visit, TIntermTraverser *it) +{ + return it->visitSwizzle(visit, this); +} + +bool TIntermBinary::visit(Visit visit, TIntermTraverser *it) +{ + return it->visitBinary(visit, this); +} + +bool TIntermTernary::visit(Visit visit, TIntermTraverser *it) +{ + return it->visitTernary(visit, this); +} + +bool TIntermAggregate::visit(Visit visit, TIntermTraverser *it) +{ + return it->visitAggregate(visit, this); +} + +bool TIntermDeclaration::visit(Visit visit, TIntermTraverser *it) +{ + return it->visitDeclaration(visit, this); +} + +bool TIntermGlobalQualifierDeclaration::visit(Visit visit, TIntermTraverser *it) +{ + return it->visitGlobalQualifierDeclaration(visit, this); +} + +bool TIntermBlock::visit(Visit visit, TIntermTraverser *it) +{ + return it->visitBlock(visit, this); +} + +bool TIntermIfElse::visit(Visit visit, TIntermTraverser *it) +{ + return it->visitIfElse(visit, this); +} + +bool TIntermLoop::visit(Visit visit, TIntermTraverser *it) +{ + return it->visitLoop(visit, this); +} + +bool TIntermBranch::visit(Visit visit, TIntermTraverser *it) +{ + return it->visitBranch(visit, this); +} + +bool TIntermSwitch::visit(Visit visit, TIntermTraverser *it) +{ + return it->visitSwitch(visit, this); +} + +bool TIntermCase::visit(Visit visit, TIntermTraverser *it) +{ + return it->visitCase(visit, this); +} + +bool TIntermPreprocessorDirective::visit(Visit visit, TIntermTraverser *it) +{ + it->visitPreprocessorDirective(this); + return false; +} + +TIntermTraverser::TIntermTraverser(bool preVisit, + bool inVisit, + bool postVisit, + TSymbolTable *symbolTable) + : preVisit(preVisit), + inVisit(inVisit), + postVisit(postVisit), + mMaxDepth(0), + mMaxAllowedDepth(std::numeric_limits::max()), + mInGlobalScope(true), + mSymbolTable(symbolTable), + mCurrentChildIndex(0) +{ + // Only enabling inVisit is not supported. + ASSERT(!(inVisit && !preVisit && !postVisit)); +} + +TIntermTraverser::~TIntermTraverser() {} + +void TIntermTraverser::setMaxAllowedDepth(int depth) +{ + mMaxAllowedDepth = depth; +} + +const TIntermBlock *TIntermTraverser::getParentBlock() const +{ + if (!mParentBlockStack.empty()) + { + return mParentBlockStack.back().node; + } + return nullptr; +} + +void TIntermTraverser::pushParentBlock(TIntermBlock *node) +{ + mParentBlockStack.push_back(ParentBlock(node, 0)); +} + +void TIntermTraverser::incrementParentBlockPos() +{ + ++mParentBlockStack.back().pos; +} + +void TIntermTraverser::popParentBlock() +{ + ASSERT(!mParentBlockStack.empty()); + mParentBlockStack.pop_back(); +} + +void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions) +{ + TIntermSequence emptyInsertionsAfter; + insertStatementsInParentBlock(insertions, emptyInsertionsAfter); +} + +void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore, + const TIntermSequence &insertionsAfter) +{ + ASSERT(!mParentBlockStack.empty()); + ParentBlock &parentBlock = mParentBlockStack.back(); + if (mPath.back() == parentBlock.node) + { + ASSERT(mParentBlockStack.size() >= 2u); + // The current node is a block node, so the parent block is not the topmost one in the block + // stack, but the one below that. + parentBlock = mParentBlockStack.at(mParentBlockStack.size() - 2u); + } + NodeInsertMultipleEntry insert(parentBlock.node, parentBlock.pos, insertionsBefore, + insertionsAfter); + mInsertions.push_back(insert); +} + +void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement) +{ + TIntermSequence insertions; + insertions.push_back(statement); + insertStatementsInParentBlock(insertions); +} + +void TIntermTraverser::insertStatementsInBlockAtPosition(TIntermBlock *parent, + size_t position, + const TIntermSequence &insertionsBefore, + const TIntermSequence &insertionsAfter) +{ + ASSERT(parent); + ASSERT(position >= 0); + ASSERT(position < parent->getChildCount()); + + mInsertions.emplace_back(parent, position, insertionsBefore, insertionsAfter); +} + +void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter) +{ + mInFunctionCallOutParameter = inOutParameter; +} + +bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const +{ + return mInFunctionCallOutParameter; +} + +void TIntermTraverser::traverseBinary(TIntermBinary *node) +{ + traverse(node); +} + +void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node) +{ + ScopedNodeInTraversalPath addToPath(this, node); + if (!addToPath.isWithinDepthLimit()) + return; + + bool visit = true; + + // visit the node before children if pre-visiting. + if (preVisit) + visit = node->visit(PreVisit, this); + + // Visit the children, in the right order. + if (visit) + { + if (node->isAssignment()) + { + ASSERT(!isLValueRequiredHere()); + setOperatorRequiresLValue(true); + } + + node->getLeft()->traverse(this); + + if (node->isAssignment()) + setOperatorRequiresLValue(false); + + if (inVisit) + visit = node->visit(InVisit, this); + + if (visit) + { + // Some binary operations like indexing can be inside an expression which must be an + // l-value. + bool parentOperatorRequiresLValue = operatorRequiresLValue(); + bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter(); + + // Index is not required to be an l-value even when the surrounding expression is + // required to be an l-value. + TOperator op = node->getOp(); + if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock || + op == EOpIndexDirectStruct || op == EOpIndexIndirect) + { + setOperatorRequiresLValue(false); + setInFunctionCallOutParameter(false); + } + + node->getRight()->traverse(this); + + setOperatorRequiresLValue(parentOperatorRequiresLValue); + setInFunctionCallOutParameter(parentInFunctionCallOutParameter); + + // Visit the node after the children, if requested and the traversal + // hasn't been cancelled yet. + if (postVisit) + visit = node->visit(PostVisit, this); + } + } +} + +void TIntermTraverser::traverseUnary(TIntermUnary *node) +{ + traverse(node); +} + +void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node) +{ + ScopedNodeInTraversalPath addToPath(this, node); + if (!addToPath.isWithinDepthLimit()) + return; + + bool visit = true; + + if (preVisit) + visit = node->visit(PreVisit, this); + + if (visit) + { + ASSERT(!operatorRequiresLValue()); + switch (node->getOp()) + { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + setOperatorRequiresLValue(true); + break; + default: + break; + } + + node->getOperand()->traverse(this); + + setOperatorRequiresLValue(false); + + if (postVisit) + visit = node->visit(PostVisit, this); + } +} + +// Traverse a function definition node. This keeps track of global scope. +void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node) +{ + ScopedNodeInTraversalPath addToPath(this, node); + if (!addToPath.isWithinDepthLimit()) + return; + + bool visit = true; + + if (preVisit) + visit = node->visit(PreVisit, this); + + if (visit) + { + mCurrentChildIndex = 0; + node->getFunctionPrototype()->traverse(this); + mCurrentChildIndex = 0; + + if (inVisit) + visit = node->visit(InVisit, this); + if (visit) + { + mInGlobalScope = false; + mCurrentChildIndex = 1; + node->getBody()->traverse(this); + mCurrentChildIndex = 1; + mInGlobalScope = true; + if (postVisit) + visit = node->visit(PostVisit, this); + } + } +} + +// Traverse a block node. This keeps track of the position of traversed child nodes within the block +// so that nodes may be inserted before or after them. +void TIntermTraverser::traverseBlock(TIntermBlock *node) +{ + ScopedNodeInTraversalPath addToPath(this, node); + if (!addToPath.isWithinDepthLimit()) + return; + + pushParentBlock(node); + + bool visit = true; + + TIntermSequence *sequence = node->getSequence(); + + if (preVisit) + visit = node->visit(PreVisit, this); + + if (visit) + { + for (size_t childIndex = 0; childIndex < sequence->size(); ++childIndex) + { + TIntermNode *child = (*sequence)[childIndex]; + if (visit) + { + mCurrentChildIndex = childIndex; + child->traverse(this); + mCurrentChildIndex = childIndex; + + if (inVisit) + { + if (child != sequence->back()) + visit = node->visit(InVisit, this); + } + + incrementParentBlockPos(); + } + } + + if (visit && postVisit) + visit = node->visit(PostVisit, this); + } + + popParentBlock(); +} + +void TIntermTraverser::traverseAggregate(TIntermAggregate *node) +{ + traverse(node); +} + +bool TIntermTraverser::CompareInsertion(const NodeInsertMultipleEntry &a, + const NodeInsertMultipleEntry &b) +{ + if (a.parent != b.parent) + { + return a.parent < b.parent; + } + return a.position < b.position; +} + +bool TIntermTraverser::updateTree(TCompiler *compiler, TIntermNode *node) +{ + // Sort the insertions so that insertion position is increasing and same position insertions are + // not reordered. The insertions are processed in reverse order so that multiple insertions to + // the same parent node are handled correctly. + std::stable_sort(mInsertions.begin(), mInsertions.end(), CompareInsertion); + for (size_t ii = 0; ii < mInsertions.size(); ++ii) + { + // If two insertions are to the same position, insert them in the order they were specified. + // The std::stable_sort call above will automatically guarantee this. + const NodeInsertMultipleEntry &insertion = mInsertions[mInsertions.size() - ii - 1]; + ASSERT(insertion.parent); + if (!insertion.insertionsAfter.empty()) + { + bool inserted = insertion.parent->insertChildNodes(insertion.position + 1, + insertion.insertionsAfter); + ASSERT(inserted); + } + if (!insertion.insertionsBefore.empty()) + { + bool inserted = + insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore); + ASSERT(inserted); + } + } + for (size_t ii = 0; ii < mReplacements.size(); ++ii) + { + const NodeUpdateEntry &replacement = mReplacements[ii]; + ASSERT(replacement.parent); + bool replaced = + replacement.parent->replaceChildNode(replacement.original, replacement.replacement); + ASSERT(replaced); + + // Make sure the precision is not accidentally dropped. It's ok if the precision is not the + // same, as the transformations are allowed to replace an expression with one that is + // temporarily evaluated at a different (likely higher) precision. + TIntermTyped *originalAsTyped = replacement.original->getAsTyped(); + TIntermTyped *replacementAsTyped = + replacement.replacement ? replacement.replacement->getAsTyped() : nullptr; + if (originalAsTyped != nullptr && replacementAsTyped != nullptr) + { + const TType &originalType = originalAsTyped->getType(); + const TType &replacementType = replacementAsTyped->getType(); + ASSERT(!IsPrecisionApplicableToType(originalType.getBasicType()) || + !IsPrecisionApplicableToType(replacementType.getBasicType()) || + originalType.getPrecision() == EbpUndefined || + replacementType.getPrecision() != EbpUndefined); + } + + if (!replacement.originalBecomesChildOfReplacement) + { + // In AST traversing, a parent is visited before its children. + // After we replace a node, if its immediate child is to + // be replaced, we need to make sure we don't update the replaced + // node; instead, we update the replacement node. + for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj) + { + NodeUpdateEntry &replacement2 = mReplacements[jj]; + if (replacement2.parent == replacement.original) + replacement2.parent = replacement.replacement; + } + } + } + for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii) + { + const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii]; + ASSERT(replacement.parent); + bool replaced = replacement.parent->replaceChildNodeWithMultiple(replacement.original, + replacement.replacements); + ASSERT(replaced); + } + + clearReplacementQueue(); + + return compiler->validateAST(node); +} + +void TIntermTraverser::clearReplacementQueue() +{ + mReplacements.clear(); + mMultiReplacements.clear(); + mInsertions.clear(); +} + +void TIntermTraverser::queueReplacement(TIntermNode *replacement, OriginalNode originalStatus) +{ + queueReplacementWithParent(getParentNode(), mPath.back(), replacement, originalStatus); +} + +void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent, + TIntermNode *original, + TIntermNode *replacement, + OriginalNode originalStatus) +{ + bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD); + mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild)); +} + +void TIntermTraverser::queueAccessChainReplacement(TIntermTyped *replacement) +{ + uint32_t ancestorIndex = 0; + TIntermTyped *toReplace = nullptr; + while (true) + { + TIntermNode *ancestor = getAncestorNode(ancestorIndex); + ASSERT(ancestor != nullptr); + + TIntermBinary *asBinary = ancestor->getAsBinaryNode(); + if (asBinary == nullptr || + (asBinary->getOp() != EOpIndexDirect && asBinary->getOp() != EOpIndexIndirect)) + { + break; + } + + replacement = new TIntermBinary(asBinary->getOp(), replacement, asBinary->getRight()); + toReplace = asBinary; + + ++ancestorIndex; + } + + if (toReplace == nullptr) + { + queueReplacement(replacement, OriginalNode::IS_DROPPED); + } + else + { + queueReplacementWithParent(getAncestorNode(ancestorIndex), toReplace, replacement, + OriginalNode::IS_DROPPED); + } +} + +TLValueTrackingTraverser::TLValueTrackingTraverser(bool preVisitIn, + bool inVisitIn, + bool postVisitIn, + TSymbolTable *symbolTable) + : TIntermTraverser(preVisitIn, inVisitIn, postVisitIn, symbolTable), + mOperatorRequiresLValue(false), + mInFunctionCallOutParameter(false) +{ + ASSERT(symbolTable); +} + +void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node) +{ + ScopedNodeInTraversalPath addToPath(this, node); + if (!addToPath.isWithinDepthLimit()) + return; + + bool visit = true; + + TIntermSequence *sequence = node->getSequence(); + + if (preVisit) + visit = node->visit(PreVisit, this); + + if (visit) + { + size_t paramIndex = 0u; + for (auto *child : *sequence) + { + if (visit) + { + if (node->getFunction()) + { + // Both built-ins and user defined functions should have the function symbol + // set. + ASSERT(paramIndex < node->getFunction()->getParamCount()); + TQualifier qualifier = + node->getFunction()->getParam(paramIndex)->getType().getQualifier(); + setInFunctionCallOutParameter(qualifier == EvqParamOut || + qualifier == EvqParamInOut); + ++paramIndex; + } + else + { + ASSERT(node->isConstructor()); + } + child->traverse(this); + if (inVisit) + { + if (child != sequence->back()) + visit = node->visit(InVisit, this); + } + } + } + setInFunctionCallOutParameter(false); + + if (visit && postVisit) + visit = node->visit(PostVisit, this); + } +} + +void TIntermTraverser::traverseLoop(TIntermLoop *node) +{ + traverse(node); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.h b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.h new file mode 100644 index 0000000000..3a48556a1f --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.h @@ -0,0 +1,379 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// IntermTraverse.h : base classes for AST traversers that walk the AST and +// also have the ability to transform it by replacing nodes. + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_INTERMTRAVERSE_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_INTERMTRAVERSE_H_ + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/tree_util/Visit.h" + +namespace sh +{ + +class TCompiler; +class TSymbolTable; +class TSymbolUniqueId; + +// For traversing the tree. User should derive from this class overriding the visit functions, +// and then pass an object of the subclass to a traverse method of a node. +// +// The traverse*() functions may also be overridden to do other bookkeeping on the tree to provide +// contextual information to the visit functions, such as whether the node is the target of an +// assignment. This is complex to maintain and so should only be done in special cases. +// +// When using this, just fill in the methods for nodes you want visited. +// Return false from a pre-visit to skip visiting that node's subtree. +// +// See also how to write AST transformations documentation: +// https://github.com/google/angle/blob/master/doc/WritingShaderASTTransformations.md +class TIntermTraverser : angle::NonCopyable +{ + public: + POOL_ALLOCATOR_NEW_DELETE + TIntermTraverser(bool preVisitIn, + bool inVisitIn, + bool postVisitIn, + TSymbolTable *symbolTable = nullptr); + virtual ~TIntermTraverser(); + + virtual void visitSymbol(TIntermSymbol *node) {} + virtual void visitConstantUnion(TIntermConstantUnion *node) {} + virtual bool visitSwizzle(Visit visit, TIntermSwizzle *node) { return true; } + virtual bool visitBinary(Visit visit, TIntermBinary *node) { return true; } + virtual bool visitUnary(Visit visit, TIntermUnary *node) { return true; } + virtual bool visitTernary(Visit visit, TIntermTernary *node) { return true; } + virtual bool visitIfElse(Visit visit, TIntermIfElse *node) { return true; } + virtual bool visitSwitch(Visit visit, TIntermSwitch *node) { return true; } + virtual bool visitCase(Visit visit, TIntermCase *node) { return true; } + virtual void visitFunctionPrototype(TIntermFunctionPrototype *node) {} + virtual bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) + { + return true; + } + virtual bool visitAggregate(Visit visit, TIntermAggregate *node) { return true; } + virtual bool visitBlock(Visit visit, TIntermBlock *node) { return true; } + virtual bool visitGlobalQualifierDeclaration(Visit visit, + TIntermGlobalQualifierDeclaration *node) + { + return true; + } + virtual bool visitDeclaration(Visit visit, TIntermDeclaration *node) { return true; } + virtual bool visitLoop(Visit visit, TIntermLoop *node) { return true; } + virtual bool visitBranch(Visit visit, TIntermBranch *node) { return true; } + virtual void visitPreprocessorDirective(TIntermPreprocessorDirective *node) {} + + // The traverse functions contain logic for iterating over the children of the node + // and calling the visit functions in the appropriate places. They also track some + // context that may be used by the visit functions. + + // The generic traverse() function is used for nodes that don't need special handling. + // It's templated in order to avoid virtual function calls, this gains around 2% compiler + // performance. + template + void traverse(T *node); + + // Specialized traverse functions are implemented for node types where traversal logic may need + // to be overridden or where some special bookkeeping needs to be done. + virtual void traverseBinary(TIntermBinary *node); + virtual void traverseUnary(TIntermUnary *node); + virtual void traverseFunctionDefinition(TIntermFunctionDefinition *node); + virtual void traverseAggregate(TIntermAggregate *node); + virtual void traverseBlock(TIntermBlock *node); + virtual void traverseLoop(TIntermLoop *node); + + int getMaxDepth() const { return mMaxDepth; } + + // If traversers need to replace nodes, they can add the replacements in + // mReplacements/mMultiReplacements during traversal and the user of the traverser should call + // this function after traversal to perform them. + // + // Compiler is used to validate the tree. Node is the same given to traverse(). Returns false + // if the tree is invalid after update. + [[nodiscard]] bool updateTree(TCompiler *compiler, TIntermNode *node); + + protected: + void setMaxAllowedDepth(int depth); + + // Should only be called from traverse*() functions + bool incrementDepth(TIntermNode *current) + { + mMaxDepth = std::max(mMaxDepth, static_cast(mPath.size())); + mPath.push_back(current); + return mMaxDepth < mMaxAllowedDepth; + } + + // Should only be called from traverse*() functions + void decrementDepth() { mPath.pop_back(); } + + int getCurrentTraversalDepth() const { return static_cast(mPath.size()) - 1; } + int getCurrentBlockDepth() const { return static_cast(mParentBlockStack.size()) - 1; } + + // RAII helper for incrementDepth/decrementDepth + class [[nodiscard]] ScopedNodeInTraversalPath + { + public: + ScopedNodeInTraversalPath(TIntermTraverser *traverser, TIntermNode *current) + : mTraverser(traverser) + { + mWithinDepthLimit = mTraverser->incrementDepth(current); + } + ~ScopedNodeInTraversalPath() { mTraverser->decrementDepth(); } + + bool isWithinDepthLimit() { return mWithinDepthLimit; } + + private: + TIntermTraverser *mTraverser; + bool mWithinDepthLimit; + }; + // Optimized traversal functions for leaf nodes directly access ScopedNodeInTraversalPath. + friend void TIntermSymbol::traverse(TIntermTraverser *); + friend void TIntermConstantUnion::traverse(TIntermTraverser *); + friend void TIntermFunctionPrototype::traverse(TIntermTraverser *); + + TIntermNode *getParentNode() const + { + return mPath.size() <= 1 ? nullptr : mPath[mPath.size() - 2u]; + } + + // Return the nth ancestor of the node being traversed. getAncestorNode(0) == getParentNode() + TIntermNode *getAncestorNode(unsigned int n) const + { + if (mPath.size() > n + 1u) + { + return mPath[mPath.size() - n - 2u]; + } + return nullptr; + } + + // Returns what child index is currently being visited. For example when visiting the children + // of an aggregate, it can be used to find out which argument of the parent (aggregate) node + // they correspond to. Only valid in the PreVisit call of the child. + size_t getParentChildIndex(Visit visit) const + { + ASSERT(visit == PreVisit); + return mCurrentChildIndex; + } + // Returns what child index has just been processed. Only valid in the InVisit and PostVisit + // calls of the parent node. + size_t getLastTraversedChildIndex(Visit visit) const + { + ASSERT(visit != PreVisit); + return mCurrentChildIndex; + } + + const TIntermBlock *getParentBlock() const; + + TIntermNode *getRootNode() const + { + ASSERT(!mPath.empty()); + return mPath.front(); + } + + void pushParentBlock(TIntermBlock *node); + void incrementParentBlockPos(); + void popParentBlock(); + + // To replace a single node with multiple nodes in the parent aggregate. May be used with blocks + // but also with other nodes like declarations. + struct NodeReplaceWithMultipleEntry + { + NodeReplaceWithMultipleEntry(TIntermAggregateBase *parentIn, + TIntermNode *originalIn, + TIntermSequence &&replacementsIn) + : parent(parentIn), original(originalIn), replacements(std::move(replacementsIn)) + {} + + TIntermAggregateBase *parent; + TIntermNode *original; + TIntermSequence replacements; + }; + + // Helper to insert statements in the parent block of the node currently being traversed. + // The statements will be inserted before the node being traversed once updateTree is called. + // Should only be called during PreVisit or PostVisit if called from block nodes. + // Note that two insertions to the same position in the same block are not supported. + void insertStatementsInParentBlock(const TIntermSequence &insertions); + + // Same as above, but supports simultaneous insertion of statements before and after the node + // currently being traversed. + void insertStatementsInParentBlock(const TIntermSequence &insertionsBefore, + const TIntermSequence &insertionsAfter); + + // Helper to insert a single statement. + void insertStatementInParentBlock(TIntermNode *statement); + + // Explicitly specify where to insert statements. The statements are inserted before and after + // the specified position. The statements will be inserted once updateTree is called. Note that + // two insertions to the same position in the same block are not supported. + void insertStatementsInBlockAtPosition(TIntermBlock *parent, + size_t position, + const TIntermSequence &insertionsBefore, + const TIntermSequence &insertionsAfter); + + enum class OriginalNode + { + BECOMES_CHILD, + IS_DROPPED + }; + + void clearReplacementQueue(); + + // Replace the node currently being visited with replacement. + void queueReplacement(TIntermNode *replacement, OriginalNode originalStatus); + // Explicitly specify a node to replace with replacement. + void queueReplacementWithParent(TIntermNode *parent, + TIntermNode *original, + TIntermNode *replacement, + OriginalNode originalStatus); + // Walk the ancestors and replace the access chain that leads to this symbol. This fixes up the + // types of the intermediate nodes, so it should be used when the type of the symbol changes. + // The AST transformation must still visit the (indirect) index nodes to transform the + // expression inside those nodes. Note that due to the way these replacements work, the AST + // transformation should not attempt to replace the actual index node itself, but only a subnode + // of that. + // + // Node 1 Node 6 + // EOpIndexDirect EOpIndexDirect + // / \ / \ + // Node 2 Node 3 Node 7 Node 3 + // EOpIndexIndirect N --> replaced with --> EOpIndexIndirect N + // / \ / \ + // Node 4 Node 5 Node 8 Node 5 + // symbol expression replacement expression + // ^ ^ + // | | + // This symbol is being replaced, This node is directly placed in the + // and the replacement is given new access chain, and its parent is + // to this function. is changed. This is why a + // replacment attempt for this node + // itself will not work. + // + void queueAccessChainReplacement(TIntermTyped *replacement); + + const bool preVisit; + const bool inVisit; + const bool postVisit; + + int mMaxDepth; + int mMaxAllowedDepth; + + bool mInGlobalScope; + + // During traversing, save all the changes that need to happen into + // mReplacements/mMultiReplacements, then do them by calling updateTree(). + // Multi replacements are processed after single replacements. + std::vector mMultiReplacements; + + TSymbolTable *mSymbolTable; + + private: + // To insert multiple nodes into the parent block. + struct NodeInsertMultipleEntry + { + NodeInsertMultipleEntry(TIntermBlock *_parent, + TIntermSequence::size_type _position, + TIntermSequence _insertionsBefore, + TIntermSequence _insertionsAfter) + : parent(_parent), + position(_position), + insertionsBefore(_insertionsBefore), + insertionsAfter(_insertionsAfter) + {} + + TIntermBlock *parent; + TIntermSequence::size_type position; + TIntermSequence insertionsBefore; + TIntermSequence insertionsAfter; + }; + + static bool CompareInsertion(const NodeInsertMultipleEntry &a, + const NodeInsertMultipleEntry &b); + + // To replace a single node with another on the parent node + struct NodeUpdateEntry + { + NodeUpdateEntry(TIntermNode *_parent, + TIntermNode *_original, + TIntermNode *_replacement, + bool _originalBecomesChildOfReplacement) + : parent(_parent), + original(_original), + replacement(_replacement), + originalBecomesChildOfReplacement(_originalBecomesChildOfReplacement) + {} + + TIntermNode *parent; + TIntermNode *original; + TIntermNode *replacement; + bool originalBecomesChildOfReplacement; + }; + + struct ParentBlock + { + ParentBlock(TIntermBlock *nodeIn, TIntermSequence::size_type posIn) + : node(nodeIn), pos(posIn) + {} + + TIntermBlock *node; + TIntermSequence::size_type pos; + }; + + std::vector mInsertions; + std::vector mReplacements; + + // All the nodes from root to the current node during traversing. + TVector mPath; + // The current child of parent being traversed. + size_t mCurrentChildIndex; + + // All the code blocks from the root to the current node's parent during traversal. + std::vector mParentBlockStack; +}; + +// Traverser parent class that tracks where a node is a destination of a write operation and so is +// required to be an l-value. +class TLValueTrackingTraverser : public TIntermTraverser +{ + public: + TLValueTrackingTraverser(bool preVisit, + bool inVisit, + bool postVisit, + TSymbolTable *symbolTable); + ~TLValueTrackingTraverser() override {} + + void traverseBinary(TIntermBinary *node) final; + void traverseUnary(TIntermUnary *node) final; + void traverseAggregate(TIntermAggregate *node) final; + + protected: + bool isLValueRequiredHere() const + { + return mOperatorRequiresLValue || mInFunctionCallOutParameter; + } + + private: + // Track whether an l-value is required in the node that is currently being traversed by the + // surrounding operator. + // Use isLValueRequiredHere to check all conditions which require an l-value. + void setOperatorRequiresLValue(bool lValueRequired) + { + mOperatorRequiresLValue = lValueRequired; + } + bool operatorRequiresLValue() const { return mOperatorRequiresLValue; } + + // Track whether an l-value is required inside a function call. + void setInFunctionCallOutParameter(bool inOutParameter); + bool isInFunctionCallOutParameter() const; + + bool mOperatorRequiresLValue; + bool mInFunctionCallOutParameter; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_INTERMTRAVERSE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/NodeSearch.h b/gfx/angle/checkout/src/compiler/translator/tree_util/NodeSearch.h new file mode 100644 index 0000000000..7764a2ebe3 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/NodeSearch.h @@ -0,0 +1,56 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// NodeSearch.h: Utilities for searching translator node graphs +// + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_NODESEARCH_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_NODESEARCH_H_ + +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +template +class NodeSearchTraverser : public TIntermTraverser +{ + public: + NodeSearchTraverser() : TIntermTraverser(true, false, false), mFound(false) {} + + bool found() const { return mFound; } + + static bool search(TIntermNode *node) + { + Parent searchTraverser; + node->traverse(&searchTraverser); + return searchTraverser.found(); + } + + protected: + bool mFound; +}; + +class FindDiscard : public NodeSearchTraverser +{ + public: + bool visitBranch(Visit visit, TIntermBranch *node) override + { + switch (node->getFlowOp()) + { + case EOpKill: + mFound = true; + break; + + default: + break; + } + + return !mFound; + } +}; +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_NODESEARCH_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/NodeType.h b/gfx/angle/checkout/src/compiler/translator/tree_util/NodeType.h new file mode 100644 index 0000000000..4ab63dbebb --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/NodeType.h @@ -0,0 +1,155 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TRANSLATORMETALDIRECT_NODETYPE_H_ +#define COMPILER_TRANSLATOR_TRANSLATORMETALDIRECT_NODETYPE_H_ + +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +enum class NodeType +{ + Unknown, + Symbol, + ConstantUnion, + FunctionPrototype, + PreprocessorDirective, + Unary, + Binary, + Ternary, + Swizzle, + IfElse, + Switch, + Case, + FunctionDefinition, + Aggregate, + Block, + GlobalQualifierDeclaration, + Declaration, + Loop, + Branch, +}; + +// This is a function like object instead of a function that stack allocates this because +// TIntermTraverser is a heavy object to construct. +class GetNodeType : private TIntermTraverser +{ + NodeType nodeType; + + public: + GetNodeType() : TIntermTraverser(true, false, false) {} + + NodeType operator()(TIntermNode &node) + { + node.visit(Visit::PreVisit, this); + return nodeType; + } + + private: + void visitSymbol(TIntermSymbol *) override { nodeType = NodeType::Symbol; } + + void visitConstantUnion(TIntermConstantUnion *) override { nodeType = NodeType::ConstantUnion; } + + void visitFunctionPrototype(TIntermFunctionPrototype *) override + { + nodeType = NodeType::FunctionPrototype; + } + + void visitPreprocessorDirective(TIntermPreprocessorDirective *) override + { + nodeType = NodeType::PreprocessorDirective; + } + + bool visitSwizzle(Visit, TIntermSwizzle *) override + { + nodeType = NodeType::Swizzle; + return false; + } + + bool visitBinary(Visit, TIntermBinary *) override + { + nodeType = NodeType::Binary; + return false; + } + + bool visitUnary(Visit, TIntermUnary *) override + { + nodeType = NodeType::Unary; + return false; + } + + bool visitTernary(Visit, TIntermTernary *) override + { + nodeType = NodeType::Ternary; + return false; + } + + bool visitIfElse(Visit, TIntermIfElse *) override + { + nodeType = NodeType::IfElse; + return false; + } + + bool visitSwitch(Visit, TIntermSwitch *) override + { + nodeType = NodeType::Switch; + return false; + } + + bool visitCase(Visit, TIntermCase *) override + { + nodeType = NodeType::Case; + return false; + } + + bool visitFunctionDefinition(Visit, TIntermFunctionDefinition *) override + { + nodeType = NodeType::FunctionDefinition; + return false; + } + + bool visitAggregate(Visit, TIntermAggregate *) override + { + nodeType = NodeType::Aggregate; + return false; + } + + bool visitBlock(Visit, TIntermBlock *) override + { + nodeType = NodeType::Block; + return false; + } + + bool visitGlobalQualifierDeclaration(Visit, TIntermGlobalQualifierDeclaration *) override + { + nodeType = NodeType::GlobalQualifierDeclaration; + return false; + } + + bool visitDeclaration(Visit, TIntermDeclaration *) override + { + nodeType = NodeType::Declaration; + return false; + } + + bool visitLoop(Visit, TIntermLoop *) override + { + nodeType = NodeType::Loop; + return false; + } + + bool visitBranch(Visit, TIntermBranch *) override + { + nodeType = NodeType::Branch; + return false; + } +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TRANSLATORMETALDIRECT_NODETYPE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.cpp new file mode 100644 index 0000000000..ddbb22685d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.cpp @@ -0,0 +1,175 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. Use of this +// source code is governed by a BSD-style license that can be found in the +// LICENSE file. +// +// ReplaceArrayOfMatrixVarying: Find any references to array of matrices varying +// and replace it with array of vectors. +// + +#include "compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.h" + +#include + +#include "common/bitset_utils.h" +#include "common/debug.h" +#include "common/utilities.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/BuiltIn.h" +#include "compiler/translator/tree_util/FindMain.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" +#include "compiler/translator/tree_util/RunAtTheEndOfShader.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +// We create two variables to replace the given varying: +// - The new varying which is an array of vectors to be used at input/ouput only. +// - The new global variable which is a same type as given variable, to temporarily be used +// as replacements for assignments, arithmetic ops and so on. During input/ouput phrase, this temp +// variable will be copied from/to the array of vectors variable above. +// NOTE(hqle): Consider eliminating the need for using temp variable. + +namespace +{ +class CollectVaryingTraverser : public TIntermTraverser +{ + public: + CollectVaryingTraverser(std::vector *varyingsOut) + : TIntermTraverser(true, false, false), mVaryingsOut(varyingsOut) + {} + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + const TIntermSequence &sequence = *(node->getSequence()); + + if (sequence.size() != 1) + { + return false; + } + + TIntermTyped *variableType = sequence.front()->getAsTyped(); + if (!variableType || !IsVarying(variableType->getQualifier()) || + !variableType->isMatrix() || !variableType->isArray()) + { + return false; + } + + TIntermSymbol *variableSymbol = variableType->getAsSymbolNode(); + if (!variableSymbol) + { + return false; + } + + mVaryingsOut->push_back(&variableSymbol->variable()); + + return false; + } + + private: + std::vector *mVaryingsOut; +}; +} // namespace + +[[nodiscard]] bool ReplaceArrayOfMatrixVarying(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const TVariable *varying) +{ + const TType &type = varying->getType(); + + // Create global variable to temporarily acts as the given variable in places such as + // arithmetic, assignments an so on. + TType *tmpReplacementType = new TType(type); + tmpReplacementType->setQualifier(EvqGlobal); + + TVariable *tempReplaceVar = new TVariable( + symbolTable, ImmutableString(std::string("ANGLE_AOM_Temp_") + varying->name().data()), + tmpReplacementType, SymbolType::AngleInternal); + + if (!ReplaceVariable(compiler, root, varying, tempReplaceVar)) + { + return false; + } + + // Create array of vectors type + TType *varyingReplaceType = new TType(type); + varyingReplaceType->toMatrixColumnType(); + varyingReplaceType->toArrayElementType(); + varyingReplaceType->makeArray(type.getCols() * type.getOutermostArraySize()); + + TVariable *varyingReplaceVar = + new TVariable(symbolTable, varying->name(), varyingReplaceType, SymbolType::UserDefined); + + TIntermSymbol *varyingReplaceDeclarator = new TIntermSymbol(varyingReplaceVar); + TIntermDeclaration *varyingReplaceDecl = new TIntermDeclaration; + varyingReplaceDecl->appendDeclarator(varyingReplaceDeclarator); + root->insertStatement(0, varyingReplaceDecl); + + // Copy from/to the temp variable + TIntermBlock *reassignBlock = new TIntermBlock; + TIntermSymbol *tempReplaceSymbol = new TIntermSymbol(tempReplaceVar); + TIntermSymbol *varyingReplaceSymbol = new TIntermSymbol(varyingReplaceVar); + bool isInput = IsVaryingIn(type.getQualifier()); + + for (unsigned int i = 0; i < type.getOutermostArraySize(); ++i) + { + TIntermBinary *tempMatrixIndexed = + new TIntermBinary(EOpIndexDirect, tempReplaceSymbol->deepCopy(), CreateIndexNode(i)); + for (uint8_t col = 0; col < type.getCols(); ++col) + { + + TIntermBinary *tempMatrixColIndexed = new TIntermBinary( + EOpIndexDirect, tempMatrixIndexed->deepCopy(), CreateIndexNode(col)); + TIntermBinary *vectorIndexed = + new TIntermBinary(EOpIndexDirect, varyingReplaceSymbol->deepCopy(), + CreateIndexNode(i * type.getCols() + col)); + TIntermBinary *assignment; + if (isInput) + { + assignment = new TIntermBinary(EOpAssign, tempMatrixColIndexed, vectorIndexed); + } + else + { + assignment = new TIntermBinary(EOpAssign, vectorIndexed, tempMatrixColIndexed); + } + reassignBlock->appendStatement(assignment); + } + } + + if (isInput) + { + TIntermFunctionDefinition *main = FindMain(root); + main->getBody()->insertStatement(0, reassignBlock); + return compiler->validateAST(root); + } + else + { + return RunAtTheEndOfShader(compiler, root, reassignBlock, symbolTable); + } +} + +[[nodiscard]] bool ReplaceArrayOfMatrixVaryings(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable) +{ + std::vector arrayOfMatrixVars; + CollectVaryingTraverser varCollector(&arrayOfMatrixVars); + root->traverse(&varCollector); + + for (const TVariable *var : arrayOfMatrixVars) + { + if (!ReplaceArrayOfMatrixVarying(compiler, root, symbolTable, var)) + { + return false; + } + } + + return true; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.h b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.h new file mode 100644 index 0000000000..62b6b320af --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.h @@ -0,0 +1,33 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. Use of this +// source code is governed by a BSD-style license that can be found in the +// LICENSE file. +// +// ReplaceArrayOfMatrixVarying: Find any references to array of matrices varying +// and replace it with array of vectors. +// + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_REPLACEARRAYOFMATRIXVARYING_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_REPLACEARRAYOFMATRIXVARYING_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TSymbolTable; +class TVariable; + +[[nodiscard]] bool ReplaceArrayOfMatrixVarying(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const TVariable *varying); + +[[nodiscard]] bool ReplaceArrayOfMatrixVaryings(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); +} // namespace sh + +#endif diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceClipCullDistanceVariable.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceClipCullDistanceVariable.cpp new file mode 100644 index 0000000000..a8379f48f1 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceClipCullDistanceVariable.cpp @@ -0,0 +1,591 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ReplaceClipCullDistanceVariable.cpp: Find any references to gl_ClipDistance or gl_CullDistance +// and replace it with ANGLEClipDistance or ANGLECullDistance. +// + +#include "compiler/translator/tree_util/ReplaceClipCullDistanceVariable.h" + +#include "common/bitset_utils.h" +#include "common/debug.h" +#include "common/utilities.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/BuiltIn.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" +#include "compiler/translator/tree_util/RunAtTheBeginningOfShader.h" +#include "compiler/translator/tree_util/RunAtTheEndOfShader.h" + +namespace sh +{ +namespace +{ + +using ClipCullDistanceIdxSet = angle::BitSet<32>; + +typedef TIntermNode *AssignFunc(const unsigned int index, + TIntermSymbol *left, + TIntermSymbol *right, + const TIntermTyped *enableFlags); + +template +const Variable *FindVariable(const std::vector &mVars, const ImmutableString &name) +{ + for (const Variable &var : mVars) + { + if (name == var.instanceName) + { + return &var; + } + } + + return nullptr; +} + +// Traverse the tree and collect the redeclaration and all constant index references of +// gl_ClipDistance/gl_CullDistance +class GLClipCullDistanceReferenceTraverser : public TIntermTraverser +{ + public: + GLClipCullDistanceReferenceTraverser(const TIntermSymbol **redeclaredSymOut, + bool *nonConstIdxUsedOut, + unsigned int *maxConstIdxOut, + ClipCullDistanceIdxSet *constIndicesOut, + TQualifier targetQualifier) + : TIntermTraverser(true, false, false), + mRedeclaredSym(redeclaredSymOut), + mUseNonConstClipCullDistanceIndex(nonConstIdxUsedOut), + mMaxConstClipCullDistanceIndex(maxConstIdxOut), + mConstClipCullDistanceIndices(constIndicesOut), + mTargetQualifier(targetQualifier) + { + *mRedeclaredSym = nullptr; + *mUseNonConstClipCullDistanceIndex = false; + *mMaxConstClipCullDistanceIndex = 0; + mConstClipCullDistanceIndices->reset(); + } + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + // If gl_ClipDistance/gl_CullDistance is redeclared, we need to collect its information + const TIntermSequence &sequence = *(node->getSequence()); + + if (sequence.size() != 1) + { + return true; + } + + TIntermSymbol *variable = sequence.front()->getAsSymbolNode(); + if (variable == nullptr || variable->getType().getQualifier() != mTargetQualifier) + { + return true; + } + + *mRedeclaredSym = variable->getAsSymbolNode(); + + return true; + } + + bool visitBinary(Visit visit, TIntermBinary *node) override + { + TOperator op = node->getOp(); + if (op != EOpIndexDirect && op != EOpIndexIndirect) + { + return true; + } + + // gl_ClipDistance / gl_CullDistance + TIntermTyped *left = node->getLeft()->getAsTyped(); + if (!left) + { + return true; + } + + ASSERT(op == EOpIndexDirect || op == EOpIndexIndirect); + + TIntermSymbol *clipCullDistance = left->getAsSymbolNode(); + if (!clipCullDistance) + { + return true; + } + if (clipCullDistance->getType().getQualifier() != mTargetQualifier) + { + return true; + } + + const TConstantUnion *constIdx = node->getRight()->getConstantValue(); + if (!constIdx) + { + *mUseNonConstClipCullDistanceIndex = true; + } + else + { + unsigned int idx = 0; + switch (constIdx->getType()) + { + case EbtInt: + idx = constIdx->getIConst(); + break; + case EbtUInt: + idx = constIdx->getUConst(); + break; + case EbtFloat: + idx = static_cast(constIdx->getFConst()); + break; + case EbtBool: + idx = constIdx->getBConst() ? 1 : 0; + break; + default: + UNREACHABLE(); + break; + } + ASSERT(idx < mConstClipCullDistanceIndices->size()); + mConstClipCullDistanceIndices->set(idx); + + *mMaxConstClipCullDistanceIndex = std::max(*mMaxConstClipCullDistanceIndex, idx); + } + + return true; + } + + private: + const TIntermSymbol **mRedeclaredSym; + // Flag indicating whether there is at least one reference of gl_ClipDistance with non-constant + // index + bool *mUseNonConstClipCullDistanceIndex; + // Max constant index that is used to reference gl_ClipDistance + unsigned int *mMaxConstClipCullDistanceIndex; + // List of constant index reference of gl_ClipDistance + ClipCullDistanceIdxSet *mConstClipCullDistanceIndices; + // Qualifier for gl_ClipDistance/gl_CullDistance + const TQualifier mTargetQualifier; +}; + +// Replace all symbolic occurrences of given variables except one symbol. +class ReplaceVariableExceptOneTraverser : public TIntermTraverser +{ + public: + ReplaceVariableExceptOneTraverser(const TVariable *toBeReplaced, + const TIntermTyped *replacement, + const TIntermSymbol *exception) + : TIntermTraverser(true, false, false), + mToBeReplaced(toBeReplaced), + mException(exception), + mReplacement(replacement) + {} + + void visitSymbol(TIntermSymbol *node) override + { + if (&node->variable() == mToBeReplaced && node != mException) + { + queueReplacement(mReplacement->deepCopy(), OriginalNode::IS_DROPPED); + } + } + + private: + const TVariable *const mToBeReplaced; + const TIntermSymbol *const mException; + const TIntermTyped *const mReplacement; +}; + +TIntermNode *simpleAssignFunc(const unsigned int index, + TIntermSymbol *leftSymbol, + TIntermSymbol *rightSymbol, + const TIntermTyped * /*enableFlags*/) +{ + // leftSymbol[index] = rightSymbol[index] + // E.g., ANGLEClipDistance[index] = gl_ClipDistance[index] + TIntermBinary *left = + new TIntermBinary(EOpIndexDirect, leftSymbol->deepCopy(), CreateIndexNode(index)); + TIntermBinary *right = + new TIntermBinary(EOpIndexDirect, rightSymbol->deepCopy(), CreateIndexNode(index)); + + return new TIntermBinary(EOpAssign, left, right); +} + +// This is only used for gl_ClipDistance +TIntermNode *assignFuncWithEnableFlags(const unsigned int index, + TIntermSymbol *leftSymbol, + TIntermSymbol *rightSymbol, + const TIntermTyped *enableFlags) +{ + // if (ANGLEUniforms.clipDistancesEnabled & (0x1 << index)) + // gl_ClipDistance[index] = ANGLEClipDistance[index]; + // else + // gl_ClipDistance[index] = 0; + TIntermConstantUnion *bitMask = CreateUIntNode(0x1 << index); + TIntermBinary *bitwiseAnd = new TIntermBinary(EOpBitwiseAnd, enableFlags->deepCopy(), bitMask); + TIntermBinary *nonZero = new TIntermBinary(EOpNotEqual, bitwiseAnd, CreateUIntNode(0)); + + TIntermBinary *left = + new TIntermBinary(EOpIndexDirect, leftSymbol->deepCopy(), CreateIndexNode(index)); + TIntermBinary *right = + new TIntermBinary(EOpIndexDirect, rightSymbol->deepCopy(), CreateIndexNode(index)); + TIntermBinary *assignment = new TIntermBinary(EOpAssign, left, right); + TIntermBlock *trueBlock = new TIntermBlock(); + trueBlock->appendStatement(assignment); + + TIntermBinary *zeroAssignment = + new TIntermBinary(EOpAssign, left->deepCopy(), CreateFloatNode(0, EbpMedium)); + TIntermBlock *falseBlock = new TIntermBlock(); + falseBlock->appendStatement(zeroAssignment); + + return new TIntermIfElse(nonZero, trueBlock, falseBlock); +} + +class ReplaceClipCullDistanceAssignments : angle::NonCopyable +{ + public: + ReplaceClipCullDistanceAssignments(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const TVariable *glClipCullDistanceVar, + const TIntermSymbol *redeclaredGlClipDistance, + const ImmutableString &angleVarName) + : mCompiler(compiler), + mRoot(root), + mSymbolTable(symbolTable), + mGlVar(glClipCullDistanceVar), + mRedeclaredGLVar(redeclaredGlClipDistance), + mANGLEVarName(angleVarName) + { + mEnabledDistances = 0; + } + + unsigned int getEnabledClipCullDistance(const bool useNonConstIndex, + const unsigned int maxConstIndex); + const TVariable *declareANGLEVariable(const TVariable *originalVariable); + bool assignOriginalValueToANGLEVariable(const GLenum shaderType); + bool assignANGLEValueToOriginalVariable(const GLenum shaderType, + const bool isRedeclared, + const TIntermTyped *enableFlags, + const ClipCullDistanceIdxSet *constIndices); + + private: + bool assignOriginalValueToANGLEVariableImpl(); + bool assignANGLEValueToOriginalVariableImpl(const bool isRedeclared, + const TIntermTyped *enableFlags, + const ClipCullDistanceIdxSet *constIndices, + AssignFunc assignFunc); + + // Common variables for replacing gl_Clip/CullDistances with ANGLEClip/CullDistances + TCompiler *mCompiler; + TIntermBlock *mRoot; + TSymbolTable *mSymbolTable; + + const TVariable *mGlVar; + const TIntermSymbol *mRedeclaredGLVar; + const ImmutableString mANGLEVarName; + + unsigned int mEnabledDistances; + const TVariable *mANGLEVar; +}; + +unsigned int ReplaceClipCullDistanceAssignments::getEnabledClipCullDistance( + const bool useNonConstIndex, + const unsigned int maxConstIndex) +{ + if (mRedeclaredGLVar) + { + // If array is redeclared by user, use that redeclared size. + mEnabledDistances = mRedeclaredGLVar->getType().getOutermostArraySize(); + } + else if (!useNonConstIndex) + { + ASSERT(maxConstIndex < mGlVar->getType().getOutermostArraySize()); + // Only use constant index, then use max array index used. + mEnabledDistances = maxConstIndex + 1; + } + + return mEnabledDistances; +} + +const TVariable *ReplaceClipCullDistanceAssignments::declareANGLEVariable( + const TVariable *originalVariable) +{ + ASSERT(mEnabledDistances > 0); + + TType *clipCullDistanceType = new TType(originalVariable->getType()); + clipCullDistanceType->setQualifier(EvqGlobal); + clipCullDistanceType->toArrayBaseType(); + clipCullDistanceType->makeArray(mEnabledDistances); + + mANGLEVar = + new TVariable(mSymbolTable, mANGLEVarName, clipCullDistanceType, SymbolType::AngleInternal); + + TIntermSymbol *clipCullDistanceDeclarator = new TIntermSymbol(mANGLEVar); + TIntermDeclaration *clipCullDistanceDecl = new TIntermDeclaration; + clipCullDistanceDecl->appendDeclarator(clipCullDistanceDeclarator); + + // Must declare ANGLEClipdistance/ANGLECullDistance before any function, since + // gl_ClipDistance/gl_CullDistance might be accessed within a function declared before main. + mRoot->insertStatement(0, clipCullDistanceDecl); + + return mANGLEVar; +} + +bool ReplaceClipCullDistanceAssignments::assignOriginalValueToANGLEVariableImpl() +{ + ASSERT(mEnabledDistances > 0); + + TIntermBlock *readBlock = new TIntermBlock; + TIntermSymbol *glClipCullDistanceSymbol = new TIntermSymbol(mGlVar); + TIntermSymbol *clipCullDistanceSymbol = new TIntermSymbol(mANGLEVar); + + for (unsigned int i = 0; i < mEnabledDistances; i++) + { + readBlock->appendStatement( + simpleAssignFunc(i, clipCullDistanceSymbol, glClipCullDistanceSymbol, nullptr)); + } + + return RunAtTheBeginningOfShader(mCompiler, mRoot, readBlock); +} + +bool ReplaceClipCullDistanceAssignments::assignANGLEValueToOriginalVariableImpl( + const bool isRedeclared, + const TIntermTyped *enableFlags, + const ClipCullDistanceIdxSet *constIndices, + AssignFunc assignFunc) +{ + ASSERT(mEnabledDistances > 0); + + TIntermBlock *assignBlock = new TIntermBlock; + TIntermSymbol *glClipCullDistanceSymbol = new TIntermSymbol(mGlVar); + TIntermSymbol *clipCullDistanceSymbol = new TIntermSymbol(mANGLEVar); + + // The array size is decided by either redeclaring the variable or accessing the variable with a + // integral constant index. And this size is the count of the enabled value. So, if the index + // which is greater than the array size, is used to access the variable, this access will be + // ignored. + if (isRedeclared || !constIndices) + { + for (unsigned int i = 0; i < mEnabledDistances; ++i) + { + assignBlock->appendStatement( + assignFunc(i, glClipCullDistanceSymbol, clipCullDistanceSymbol, enableFlags)); + } + } + else + { + // Assign ANGLEClip/CullDistance[i]'s value to gl_Clip/CullDistance[i] if i is in the + // constant indices list. Those elements whose index is not in the constant index list will + // be zeroise for initialization. + for (unsigned int i = 0; i < mEnabledDistances; ++i) + { + if (constIndices->test(i)) + { + assignBlock->appendStatement( + assignFunc(i, glClipCullDistanceSymbol, clipCullDistanceSymbol, enableFlags)); + } + else + { + // gl_Clip/CullDistance[i] = 0; + TIntermBinary *left = new TIntermBinary( + EOpIndexDirect, glClipCullDistanceSymbol->deepCopy(), CreateIndexNode(i)); + TIntermBinary *zeroAssignment = + new TIntermBinary(EOpAssign, left, CreateFloatNode(0, EbpMedium)); + assignBlock->appendStatement(zeroAssignment); + } + } + } + + return RunAtTheEndOfShader(mCompiler, mRoot, assignBlock, mSymbolTable); +} + +[[nodiscard]] bool ReplaceClipCullDistanceAssignments::assignOriginalValueToANGLEVariable( + const GLenum shaderType) +{ + switch (shaderType) + { + case GL_VERTEX_SHADER: + // Vertex shader can use gl_Clip/CullDistance as a output only + break; + case GL_FRAGMENT_SHADER: + { + // These shader types can use gl_Clip/CullDistance as input + if (!assignOriginalValueToANGLEVariableImpl()) + { + return false; + } + break; + } + default: + { + UNREACHABLE(); + return false; + } + } + + return true; +} + +[[nodiscard]] bool ReplaceClipCullDistanceAssignments::assignANGLEValueToOriginalVariable( + const GLenum shaderType, + const bool isRedeclared, + const TIntermTyped *enableFlags, + const ClipCullDistanceIdxSet *constIndices) +{ + switch (shaderType) + { + case GL_VERTEX_SHADER: + { + // Vertex shader can use gl_Clip/CullDistance as output. + // If the enabled gl_Clip/CullDistances are not initialized, results are undefined. + // EXT_clip_cull_distance spec : + // The shader must also set all values in gl_ClipDistance that have been enabled via the + // OpenGL ES API, or results are undefined. Values written into gl_ClipDistance for + // planes that are not enabled have no effect. + // ... + // Shaders writing gl_CullDistance must write all enabled distances, or culling results + // are undefined. + if (!assignANGLEValueToOriginalVariableImpl( + isRedeclared, enableFlags, constIndices, + enableFlags ? assignFuncWithEnableFlags : simpleAssignFunc)) + { + return false; + } + break; + } + case GL_FRAGMENT_SHADER: + // Fragment shader can use gl_Clip/CullDistance as input only + break; + default: + { + UNREACHABLE(); + return false; + } + } + + return true; +} + +// Common code to transform gl_ClipDistance and gl_CullDistance. Comments reference +// gl_ClipDistance, but are also applicable to gl_CullDistance. +[[nodiscard]] bool ReplaceClipCullDistanceAssignmentsImpl( + TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const GLenum shaderType, + const TIntermTyped *clipDistanceEnableFlags, + const char *builtInName, + const char *replacementName, + TQualifier builtInQualifier) +{ + // Collect all constant index references of gl_ClipDistance + ImmutableString name(builtInName); + ClipCullDistanceIdxSet constIndices; + bool useNonConstIndex = false; + const TIntermSymbol *redeclaredBuiltIn = nullptr; + unsigned int maxConstIndex = 0; + GLClipCullDistanceReferenceTraverser indexTraverser( + &redeclaredBuiltIn, &useNonConstIndex, &maxConstIndex, &constIndices, builtInQualifier); + root->traverse(&indexTraverser); + if (!useNonConstIndex && constIndices.none()) + { + // No references of gl_ClipDistance + return true; + } + + // Retrieve gl_ClipDistance variable reference + // Search user redeclared gl_ClipDistance first + const TVariable *builtInVar = nullptr; + if (redeclaredBuiltIn) + { + builtInVar = &redeclaredBuiltIn->variable(); + } + else + { + // User defined not found, find in built-in table + builtInVar = static_cast( + symbolTable->findBuiltIn(name, compiler->getShaderVersion())); + } + if (!builtInVar) + { + return false; + } + + ReplaceClipCullDistanceAssignments replacementUtils(compiler, root, symbolTable, builtInVar, + redeclaredBuiltIn, + ImmutableString(replacementName)); + + // Declare a global variable substituting gl_ClipDistance + unsigned int enabledClipDistances = + replacementUtils.getEnabledClipCullDistance(useNonConstIndex, maxConstIndex); + if (!enabledClipDistances) + { + // Spec : + // The gl_ClipDistance array is predeclared as unsized and must be explicitly sized by the + // shader either redeclaring it with a size or implicitly sized by indexing it only with + // integral constant expressions. + return false; + } + + const TVariable *replacementVar = replacementUtils.declareANGLEVariable(builtInVar); + + // Replace gl_ClipDistance reference with ANGLEClipDistance, except the declaration + ReplaceVariableExceptOneTraverser replaceTraverser(builtInVar, + new TIntermSymbol(replacementVar), + /** exception */ redeclaredBuiltIn); + root->traverse(&replaceTraverser); + if (!replaceTraverser.updateTree(compiler, root)) + { + return false; + } + + // Read gl_ClipDistance to ANGLEClipDistance for getting a original data + if (!replacementUtils.assignOriginalValueToANGLEVariable(shaderType)) + { + return false; + } + + // Reassign ANGLEClipDistance to gl_ClipDistance but ignore those that are disabled + const bool isRedeclared = redeclaredBuiltIn != nullptr; + if (!replacementUtils.assignANGLEValueToOriginalVariable( + shaderType, isRedeclared, clipDistanceEnableFlags, &constIndices)) + { + return false; + } + + // If not redeclared, replace the built-in with one that is appropriately sized + if (!isRedeclared) + { + TType *resizedType = new TType(builtInVar->getType()); + resizedType->setArraySize(0, enabledClipDistances); + + TVariable *resizedVar = new TVariable(symbolTable, name, resizedType, SymbolType::BuiltIn); + + return ReplaceVariable(compiler, root, builtInVar, resizedVar); + } + + return true; +} + +} // anonymous namespace + +[[nodiscard]] bool ReplaceClipDistanceAssignments(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const GLenum shaderType, + const TIntermTyped *clipDistanceEnableFlags) +{ + return ReplaceClipCullDistanceAssignmentsImpl(compiler, root, symbolTable, shaderType, + clipDistanceEnableFlags, "gl_ClipDistance", + "ANGLEClipDistance", EvqClipDistance); +} + +[[nodiscard]] bool ReplaceCullDistanceAssignments(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const GLenum shaderType) +{ + return ReplaceClipCullDistanceAssignmentsImpl(compiler, root, symbolTable, shaderType, nullptr, + "gl_CullDistance", "ANGLECullDistance", + EvqCullDistance); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceClipCullDistanceVariable.h b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceClipCullDistanceVariable.h new file mode 100644 index 0000000000..93d19f9fe2 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceClipCullDistanceVariable.h @@ -0,0 +1,43 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ReplaceClipCullDistanceVariable.h: Find any references to gl_ClipDistance or gl_CullDistance and +// replace it with ANGLEClipDistance or ANGLECullDistance. +// + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_REPLACECLIPCULLDISTANCEVARIABLE_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_REPLACECLIPCULLDISTANCEVARIABLE_H_ + +#include "GLSLANG/ShaderLang.h" +#include "common/angleutils.h" + +namespace sh +{ + +struct InterfaceBlock; +class TCompiler; +class TIntermBlock; +class TSymbolTable; +class TIntermTyped; + +// Replace every gl_ClipDistance assignment with assignment to "ANGLEClipDistance", +// then at the end of shader re-assign the values of this global variable to gl_ClipDistance. +// This to solve some complex usages such as user passing gl_ClipDistance as output reference +// to a function. +// Furthermore, at the end shader, some disabled gl_ClipDistance[i] can be skipped from the +// assignment. +[[nodiscard]] bool ReplaceClipDistanceAssignments(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const GLenum shaderType, + const TIntermTyped *clipDistanceEnableFlags); + +[[nodiscard]] bool ReplaceCullDistanceAssignments(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const GLenum shaderType); +} // namespace sh + +#endif diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceShadowingVariables.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceShadowingVariables.cpp new file mode 100644 index 0000000000..47842eaade --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceShadowingVariables.cpp @@ -0,0 +1,142 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ReplaceShadowingVariables.cpp: Replace all references to any variable in the AST that is +// a redefinition of a variable in a nested scope. This is a useful for ESSL 1.00 shaders +// where the spec section "4.2.3. Redeclaring Variables" states "However, a nested scope can +// override an outer scope's declaration of a particular variable name." This is changed in +// later spec versions, such as ESSL 3.20 spec which states "If [a variable] is declared as +// a parameter in a function definition, it is scoped until the end of that function +// definition. A function's parameter declarations and body together form a single scope." +// +// So this class is useful when translating from ESSL 1.00 shaders, where function body var +// redefinition is allowed, to later shader versions where it's not allowed. +// + +#include "compiler/translator/tree_util/ReplaceShadowingVariables.h" +#include "compiler/translator/tree_util/ReplaceVariable.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +#include + +namespace sh +{ + +namespace +{ + +// Custom struct to queue up any replacements until after AST traversal +struct DeferredReplacementBlock +{ + const TVariable *originalVariable; // variable to be replaced + TVariable *replacementVariable; // variable to replace originalVar with + TIntermBlock *functionBody; // function body where replacement occurs +}; + +class ReplaceShadowingVariablesTraverser : public TIntermTraverser +{ + public: + ReplaceShadowingVariablesTraverser(TSymbolTable *symbolTable) + : TIntermTraverser(true, true, true, symbolTable), mParameterNames{}, mFunctionBody(nullptr) + {} + + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override + { + // In pre-visit of function, record params + if (visit == PreVisit) + { + ASSERT(mParameterNames.size() == 0); + const TFunction *func = node->getFunctionPrototype()->getFunction(); + // Grab all of the parameter names from the function prototype + size_t paramCount = func->getParamCount(); + for (size_t i = 0; i < paramCount; ++i) + { + mParameterNames.emplace(std::string(func->getParam(i)->name().data())); + } + if (mParameterNames.size() > 0) + mFunctionBody = node->getBody(); + } + else if (visit == PostVisit) + { + // Clear data saved from function definition + mParameterNames.clear(); + mFunctionBody = nullptr; + } + return true; + } + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + if (visit == PreVisit && mParameterNames.size() != 0) + { + TIntermSequence *decls = node->getSequence(); + for (auto &declVector : *decls) + { + // no init case + TIntermSymbol *symNode = declVector->getAsSymbolNode(); + if (symNode == nullptr) + { + // init case + TIntermBinary *binaryNode = declVector->getAsBinaryNode(); + ASSERT(binaryNode->getOp() == EOpInitialize); + symNode = binaryNode->getLeft()->getAsSymbolNode(); + } + ASSERT(symNode != nullptr); + std::string varName = std::string(symNode->variable().name().data()); + if (mParameterNames.count(varName) > 0) + { + // We found a redefined var so queue replacement + mReplacements.emplace_back(DeferredReplacementBlock{ + &symNode->variable(), + CreateTempVariable(mSymbolTable, &symNode->variable().getType()), + mFunctionBody}); + } + } + } + return true; + } + // Perform replacement of vars for any deferred replacements that were identified + [[nodiscard]] bool executeReplacements(TCompiler *compiler) + { + for (DeferredReplacementBlock &replace : mReplacements) + { + if (!ReplaceVariable(compiler, replace.functionBody, replace.originalVariable, + replace.replacementVariable)) + { + return false; + } + } + mReplacements.clear(); + return true; + } + + private: + std::unordered_set mParameterNames; + TIntermBlock *mFunctionBody; + std::vector mReplacements; +}; + +} // anonymous namespace + +// Replaces every occurrence of a variable with another variable. +[[nodiscard]] bool ReplaceShadowingVariables(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable) +{ + ReplaceShadowingVariablesTraverser traverser(symbolTable); + root->traverse(&traverser); + if (!traverser.executeReplacements(compiler)) + { + return false; + } + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceShadowingVariables.h b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceShadowingVariables.h new file mode 100644 index 0000000000..f6da350f5f --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceShadowingVariables.h @@ -0,0 +1,26 @@ +// +// Copyright 2019 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ReplaceShadowingVariables.h: Find any variables that are redefined within a nested +// scope and replace them with a newly named variable. + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_REPLACESHADOWINGVARIABLES_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_REPLACESHADOWINGVARIABLES_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TSymbolTable; + +[[nodiscard]] bool ReplaceShadowingVariables(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_REPLACESHADOWINGVARIABLES_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.cpp new file mode 100644 index 0000000000..697cfe6c74 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.cpp @@ -0,0 +1,145 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ReplaceVariable.cpp: Replace all references to a specific variable in the AST with references to +// another variable. + +#include "compiler/translator/tree_util/ReplaceVariable.h" + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class ReplaceVariableTraverser : public TIntermTraverser +{ + public: + ReplaceVariableTraverser(const TVariable *toBeReplaced, const TIntermTyped *replacement) + : TIntermTraverser(true, false, false), + mToBeReplaced(toBeReplaced), + mReplacement(replacement) + {} + + void visitSymbol(TIntermSymbol *node) override + { + if (&node->variable() == mToBeReplaced) + { + queueReplacement(mReplacement->deepCopy(), OriginalNode::IS_DROPPED); + } + } + + private: + const TVariable *const mToBeReplaced; + const TIntermTyped *const mReplacement; +}; + +class ReplaceVariablesTraverser : public TIntermTraverser +{ + public: + ReplaceVariablesTraverser(const VariableReplacementMap &variableMap) + : TIntermTraverser(true, false, false), mVariableMap(variableMap) + {} + + void visitSymbol(TIntermSymbol *node) override + { + auto iter = mVariableMap.find(&node->variable()); + if (iter != mVariableMap.end()) + { + queueReplacement(iter->second->deepCopy(), OriginalNode::IS_DROPPED); + } + } + + private: + const VariableReplacementMap &mVariableMap; +}; + +class GetDeclaratorReplacementsTraverser : public TIntermTraverser +{ + public: + GetDeclaratorReplacementsTraverser(TSymbolTable *symbolTable, + VariableReplacementMap *variableMap) + : TIntermTraverser(true, false, false, symbolTable), mVariableMap(variableMap) + {} + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + const TIntermSequence &sequence = *(node->getSequence()); + + for (TIntermNode *decl : sequence) + { + TIntermSymbol *asSymbol = decl->getAsSymbolNode(); + TIntermBinary *asBinary = decl->getAsBinaryNode(); + + if (asBinary != nullptr) + { + ASSERT(asBinary->getOp() == EOpInitialize); + asSymbol = asBinary->getLeft()->getAsSymbolNode(); + } + + ASSERT(asSymbol); + const TVariable &variable = asSymbol->variable(); + + ASSERT(mVariableMap->find(&variable) == mVariableMap->end()); + + const TVariable *replacementVariable = new TVariable( + mSymbolTable, variable.name(), &variable.getType(), variable.symbolType()); + + (*mVariableMap)[&variable] = new TIntermSymbol(replacementVariable); + } + + return false; + } + + private: + VariableReplacementMap *mVariableMap; +}; + +} // anonymous namespace + +// Replaces every occurrence of a variable with another variable. +[[nodiscard]] bool ReplaceVariable(TCompiler *compiler, + TIntermBlock *root, + const TVariable *toBeReplaced, + const TVariable *replacement) +{ + ReplaceVariableTraverser traverser(toBeReplaced, new TIntermSymbol(replacement)); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +[[nodiscard]] bool ReplaceVariables(TCompiler *compiler, + TIntermBlock *root, + const VariableReplacementMap &variableMap) +{ + ReplaceVariablesTraverser traverser(variableMap); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +void GetDeclaratorReplacements(TSymbolTable *symbolTable, + TIntermBlock *root, + VariableReplacementMap *variableMap) +{ + GetDeclaratorReplacementsTraverser traverser(symbolTable, variableMap); + root->traverse(&traverser); +} + +// Replaces every occurrence of a variable with a TIntermNode. +[[nodiscard]] bool ReplaceVariableWithTyped(TCompiler *compiler, + TIntermBlock *root, + const TVariable *toBeReplaced, + const TIntermTyped *replacement) +{ + ReplaceVariableTraverser traverser(toBeReplaced, replacement); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.h b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.h new file mode 100644 index 0000000000..e96bbc7a82 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.h @@ -0,0 +1,48 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ReplaceVariable.h: Replace all references to a specific variable in the AST with references to +// another variable. + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_REPLACEVARIABLE_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_REPLACEVARIABLE_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TIntermTyped; +class TSymbolTable; +class TVariable; + +[[nodiscard]] bool ReplaceVariable(TCompiler *compiler, + TIntermBlock *root, + const TVariable *toBeReplaced, + const TVariable *replacement); +[[nodiscard]] bool ReplaceVariableWithTyped(TCompiler *compiler, + TIntermBlock *root, + const TVariable *toBeReplaced, + const TIntermTyped *replacement); + +using VariableReplacementMap = angle::HashMap; + +// Replace a set of variables with their corresponding expression. +[[nodiscard]] bool ReplaceVariables(TCompiler *compiler, + TIntermBlock *root, + const VariableReplacementMap &variableMap); + +// Find all declarators, and replace the TVariable they are declaring with a duplicate. This is +// used to support deepCopy of TIntermBlock and TIntermLoop nodes that include declarations. +// Replacements already present in variableMap are preserved. +void GetDeclaratorReplacements(TSymbolTable *symbolTable, + TIntermBlock *root, + VariableReplacementMap *variableMap); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_REPLACEVARIABLE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/RewriteSampleMaskVariable.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/RewriteSampleMaskVariable.cpp new file mode 100644 index 0000000000..a81d230492 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/RewriteSampleMaskVariable.cpp @@ -0,0 +1,198 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteSampleMaskVariable.cpp: Find any references to gl_SampleMask and gl_SampleMaskIn, and +// rewrite it with ANGLESampleMask or ANGLESampleMaskIn. +// + +#include "compiler/translator/tree_util/RewriteSampleMaskVariable.h" + +#include "common/bitset_utils.h" +#include "common/debug.h" +#include "common/utilities.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/BuiltIn.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/tree_util/RunAtTheEndOfShader.h" + +namespace sh +{ +namespace +{ +constexpr int kMaxIndexForSampleMaskVar = 0; +constexpr int kFullSampleMask = 0xFFFFFFFF; + +// Traverse the tree and collect the redeclaration and replace all non constant index references of +// gl_SampleMask or gl_SampleMaskIn with constant index references +class GLSampleMaskRelatedReferenceTraverser : public TIntermTraverser +{ + public: + GLSampleMaskRelatedReferenceTraverser(const TIntermSymbol **redeclaredSymOut, + const ImmutableString &targetStr) + : TIntermTraverser(true, false, false), + mRedeclaredSym(redeclaredSymOut), + mTargetStr(targetStr) + { + *mRedeclaredSym = nullptr; + } + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + // If gl_SampleMask is redeclared, we need to collect its information + const TIntermSequence &sequence = *(node->getSequence()); + + if (sequence.size() != 1) + { + return true; + } + + TIntermTyped *variable = sequence.front()->getAsTyped(); + TIntermSymbol *symbol = variable->getAsSymbolNode(); + if (symbol == nullptr || symbol->getName() != mTargetStr) + { + return true; + } + + *mRedeclaredSym = symbol; + + return true; + } + + bool visitBinary(Visit visit, TIntermBinary *node) override + { + TOperator op = node->getOp(); + if (op != EOpIndexDirect && op != EOpIndexIndirect) + { + return true; + } + TIntermSymbol *left = node->getLeft()->getAsSymbolNode(); + if (!left) + { + return true; + } + if (left->getName() != mTargetStr) + { + return true; + } + const TConstantUnion *constIdx = node->getRight()->getConstantValue(); + if (!constIdx) + { + if (node->getRight()->hasSideEffects()) + { + insertStatementInParentBlock(node->getRight()); + } + + queueReplacementWithParent(node, node->getRight(), + CreateIndexNode(kMaxIndexForSampleMaskVar), + OriginalNode::IS_DROPPED); + } + + return true; + } + + private: + const TIntermSymbol **mRedeclaredSym; + const ImmutableString mTargetStr; +}; + +} // anonymous namespace + +[[nodiscard]] bool RewriteSampleMask(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const TIntermTyped *numSamplesUniform) +{ + const TIntermSymbol *redeclaredGLSampleMask = nullptr; + GLSampleMaskRelatedReferenceTraverser indexTraverser(&redeclaredGLSampleMask, + ImmutableString("gl_SampleMask")); + + root->traverse(&indexTraverser); + if (!indexTraverser.updateTree(compiler, root)) + { + return false; + } + + // Retrieve gl_SampleMask variable reference + // Search user redeclared it first + const TVariable *glSampleMaskVar = nullptr; + if (redeclaredGLSampleMask) + { + glSampleMaskVar = &redeclaredGLSampleMask->variable(); + } + else + { + // User defined not found, find in built-in table + glSampleMaskVar = static_cast(symbolTable->findBuiltIn( + ImmutableString("gl_SampleMask"), compiler->getShaderVersion())); + } + if (!glSampleMaskVar) + { + return false; + } + + // Current ANGLE assumes that the maximum number of samples is less than or equal to + // VK_SAMPLE_COUNT_32_BIT. So, the size of gl_SampleMask array is always one. + const unsigned int arraySizeOfSampleMask = glSampleMaskVar->getType().getOutermostArraySize(); + ASSERT(arraySizeOfSampleMask == 1); + + TIntermSymbol *glSampleMaskSymbol = new TIntermSymbol(glSampleMaskVar); + + // if (ANGLEUniforms.numSamples == 1) + // { + // gl_SampleMask[0] = int(0xFFFFFFFF); + // } + TIntermConstantUnion *singleSampleCount = CreateUIntNode(1); + TIntermBinary *equalTo = + new TIntermBinary(EOpEqual, numSamplesUniform->deepCopy(), singleSampleCount); + + TIntermBlock *trueBlock = new TIntermBlock(); + + TIntermBinary *sampleMaskVar = new TIntermBinary(EOpIndexDirect, glSampleMaskSymbol->deepCopy(), + CreateIndexNode(kMaxIndexForSampleMaskVar)); + TIntermConstantUnion *fullSampleMask = CreateIndexNode(kFullSampleMask); + TIntermBinary *assignment = new TIntermBinary(EOpAssign, sampleMaskVar, fullSampleMask); + + trueBlock->appendStatement(assignment); + + TIntermIfElse *multiSampleOrNot = new TIntermIfElse(equalTo, trueBlock, nullptr); + + return RunAtTheEndOfShader(compiler, root, multiSampleOrNot, symbolTable); +} + +[[nodiscard]] bool RewriteSampleMaskIn(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable) +{ + const TIntermSymbol *redeclaredGLSampleMaskIn = nullptr; + GLSampleMaskRelatedReferenceTraverser indexTraverser(&redeclaredGLSampleMaskIn, + ImmutableString("gl_SampleMaskIn")); + + root->traverse(&indexTraverser); + if (!indexTraverser.updateTree(compiler, root)) + { + return false; + } + + // Retrieve gl_SampleMaskIn variable reference + const TVariable *glSampleMaskInVar = nullptr; + glSampleMaskInVar = static_cast( + symbolTable->findBuiltIn(ImmutableString("gl_SampleMaskIn"), compiler->getShaderVersion())); + if (!glSampleMaskInVar) + { + return false; + } + + // Current ANGLE assumes that the maximum number of samples is less than or equal to + // VK_SAMPLE_COUNT_32_BIT. So, the size of gl_SampleMask array is always one. + const unsigned int arraySizeOfSampleMaskIn = + glSampleMaskInVar->getType().getOutermostArraySize(); + ASSERT(arraySizeOfSampleMaskIn == 1); + + return true; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/RewriteSampleMaskVariable.h b/gfx/angle/checkout/src/compiler/translator/tree_util/RewriteSampleMaskVariable.h new file mode 100644 index 0000000000..20f19313b2 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/RewriteSampleMaskVariable.h @@ -0,0 +1,38 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteSampleMaskVariable.cpp: Find any references to gl_SampleMask and gl_SampleMaskIn, and +// rewrite it with ANGLESampleMask or ANGLESampleMaskIn. +// + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_REWRITESAMPLEMASKVARIABLE_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_REWRITESAMPLEMASKVARIABLE_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TSymbolTable; +class TIntermTyped; + +// Rewrite every gl_SampleMask or gl_SampleMaskIn to "ANGLESampleMask" or "ANGLESampleMaskIn", then +// at the end of shader re-assign the values of this global variable to gl_SampleMask and +// gl_SampleMaskIn. This to solve the problem which the non constant index is used for the unsized +// array problem. +[[nodiscard]] bool RewriteSampleMask(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + const TIntermTyped *numSamplesUniform); + +[[nodiscard]] bool RewriteSampleMaskIn(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_REWRITESAMPLEMASKVARIABLE_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheBeginningOfShader.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheBeginningOfShader.cpp new file mode 100644 index 0000000000..99be6add13 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheBeginningOfShader.cpp @@ -0,0 +1,35 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RunAtTheBeginningOfShader.cpp: Add code to be run at the beginning of the shader. +// void main() { body } +// => +// void main() +// { +// codeToRun +// body +// } +// + +#include "compiler/translator/tree_util/RunAtTheBeginningOfShader.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/FindMain.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +bool RunAtTheBeginningOfShader(TCompiler *compiler, TIntermBlock *root, TIntermNode *codeToRun) +{ + TIntermFunctionDefinition *main = FindMain(root); + main->getBody()->insertStatement(0, codeToRun); + return compiler->validateAST(root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheBeginningOfShader.h b/gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheBeginningOfShader.h new file mode 100644 index 0000000000..23ed9f9372 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheBeginningOfShader.h @@ -0,0 +1,27 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RunAtTheBeginningOfShader.h: Add code to be run at the beginning of the shader. +// + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_RUNATTHEBEGINNINGOFSHADER_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_RUNATTHEBEGINNINGOFSHADER_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TIntermNode; + +[[nodiscard]] bool RunAtTheBeginningOfShader(TCompiler *compiler, + TIntermBlock *root, + TIntermNode *codeToRun); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_RUNATTHEBEGINNINGOFSHADER_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheEndOfShader.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheEndOfShader.cpp new file mode 100644 index 0000000000..daf99185ab --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheEndOfShader.cpp @@ -0,0 +1,129 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RunAtTheEndOfShader.cpp: Add code to be run at the end of the shader. In case main() contains a +// return statement, this is done by replacing the main() function with another function that calls +// the old main, like this: +// +// void main() { body } +// => +// void main0() { body } +// void main() +// { +// main0(); +// codeToRun +// } +// +// This way the code will get run even if the return statement inside main is executed. +// +// This is done if main ends in an unconditional |discard| as well, to help with SPIR-V generation +// that expects no dead-code to be present after branches in a block. To avoid bugs when |discard| +// is wrapped in unconditional blocks, any |discard| in main() is used as a signal to wrap it. +// + +#include "compiler/translator/tree_util/RunAtTheEndOfShader.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/FindMain.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +constexpr const ImmutableString kMainString("main"); + +class ContainsReturnOrDiscardTraverser : public TIntermTraverser +{ + public: + ContainsReturnOrDiscardTraverser() + : TIntermTraverser(true, false, false), mContainsReturnOrDiscard(false) + {} + + bool visitBranch(Visit visit, TIntermBranch *node) override + { + if (node->getFlowOp() == EOpReturn || node->getFlowOp() == EOpKill) + { + mContainsReturnOrDiscard = true; + } + return false; + } + + bool containsReturnOrDiscard() { return mContainsReturnOrDiscard; } + + private: + bool mContainsReturnOrDiscard; +}; + +bool ContainsReturnOrDiscard(TIntermNode *node) +{ + ContainsReturnOrDiscardTraverser traverser; + node->traverse(&traverser); + return traverser.containsReturnOrDiscard(); +} + +void WrapMainAndAppend(TIntermBlock *root, + TIntermFunctionDefinition *main, + TIntermNode *codeToRun, + TSymbolTable *symbolTable) +{ + // Replace main() with main0() with the same body. + TFunction *oldMain = + new TFunction(symbolTable, kEmptyImmutableString, SymbolType::AngleInternal, + StaticType::GetBasic(), false); + TIntermFunctionDefinition *oldMainDefinition = + CreateInternalFunctionDefinitionNode(*oldMain, main->getBody()); + + bool replaced = root->replaceChildNode(main, oldMainDefinition); + ASSERT(replaced); + + // void main() + TFunction *newMain = new TFunction(symbolTable, kMainString, SymbolType::UserDefined, + StaticType::GetBasic(), false); + TIntermFunctionPrototype *newMainProto = new TIntermFunctionPrototype(newMain); + + // { + // main0(); + // codeToRun + // } + TIntermBlock *newMainBody = new TIntermBlock(); + TIntermSequence emptySequence; + TIntermAggregate *oldMainCall = TIntermAggregate::CreateFunctionCall(*oldMain, &emptySequence); + newMainBody->appendStatement(oldMainCall); + newMainBody->appendStatement(codeToRun); + + // Add the new main() to the root node. + TIntermFunctionDefinition *newMainDefinition = + new TIntermFunctionDefinition(newMainProto, newMainBody); + root->appendStatement(newMainDefinition); +} + +} // anonymous namespace + +bool RunAtTheEndOfShader(TCompiler *compiler, + TIntermBlock *root, + TIntermNode *codeToRun, + TSymbolTable *symbolTable) +{ + TIntermFunctionDefinition *main = FindMain(root); + if (ContainsReturnOrDiscard(main)) + { + WrapMainAndAppend(root, main, codeToRun, symbolTable); + } + else + { + main->getBody()->appendStatement(codeToRun); + } + + return compiler->validateAST(root); +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheEndOfShader.h b/gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheEndOfShader.h new file mode 100644 index 0000000000..cfa5fb1fab --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/RunAtTheEndOfShader.h @@ -0,0 +1,29 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RunAtTheEndOfShader.h: Add code to be run at the end of the shader. +// + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_RUNATTHEENDOFSHADER_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_RUNATTHEENDOFSHADER_H_ + +#include "common/angleutils.h" + +namespace sh +{ + +class TCompiler; +class TIntermBlock; +class TIntermNode; +class TSymbolTable; + +[[nodiscard]] bool RunAtTheEndOfShader(TCompiler *compiler, + TIntermBlock *root, + TIntermNode *codeToRun, + TSymbolTable *symbolTable); + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_RUNATTHEENDOFSHADER_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/SpecializationConstant.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/SpecializationConstant.cpp new file mode 100644 index 0000000000..6a7254802c --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/SpecializationConstant.cpp @@ -0,0 +1,122 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SpecializationConst.cpp: Add code to generate AST node for various specialization constants. +// + +#include "compiler/translator/tree_util/SpecializationConstant.h" +#include "common/PackedEnums.h" +#include "common/angleutils.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" + +namespace sh +{ + +namespace +{ +// Specialization constant names +constexpr ImmutableString kSurfaceRotationSpecConstVarName = + ImmutableString("ANGLESurfaceRotation"); +constexpr ImmutableString kDitherSpecConstVarName = ImmutableString("ANGLEDither"); + +const TType *MakeSpecConst(const TType &type, vk::SpecializationConstantId id) +{ + // Create a new type with the EvqSpecConst qualifier + TType *specConstType = new TType(type); + specConstType->setQualifier(EvqSpecConst); + + // Set the constant_id of the spec const + TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); + layoutQualifier.location = static_cast(id); + specConstType->setLayoutQualifier(layoutQualifier); + + return specConstType; +} +} // anonymous namespace + +SpecConst::SpecConst(TSymbolTable *symbolTable, + const ShCompileOptions &compileOptions, + GLenum shaderType) + : mSymbolTable(symbolTable), + mCompileOptions(compileOptions), + mSurfaceRotationVar(nullptr), + mDitherVar(nullptr) +{ + if (shaderType == GL_FRAGMENT_SHADER || shaderType == GL_COMPUTE_SHADER) + { + return; + } + + // Mark SpecConstUsage::Rotation unconditionally. gl_Position is always rotated. + if (mCompileOptions.useSpecializationConstant) + { + mUsageBits.set(vk::SpecConstUsage::Rotation); + } +} + +SpecConst::~SpecConst() {} + +void SpecConst::declareSpecConsts(TIntermBlock *root) +{ + // Add specialization constant declarations. The default value of the specialization + // constant is irrelevant, as it will be set when creating the pipeline. + // Only emit specialized const declaration if it has been referenced. + if (mSurfaceRotationVar != nullptr) + { + TIntermDeclaration *decl = new TIntermDeclaration(); + decl->appendDeclarator( + new TIntermBinary(EOpInitialize, getRotation(), CreateBoolNode(false))); + + root->insertStatement(0, decl); + } + + if (mDitherVar != nullptr) + { + TIntermDeclaration *decl = new TIntermDeclaration(); + decl->appendDeclarator(new TIntermBinary(EOpInitialize, getDither(), CreateUIntNode(0))); + + root->insertStatement(0, decl); + } +} + +TIntermSymbol *SpecConst::getRotation() +{ + if (mSurfaceRotationVar == nullptr) + { + const TType *type = MakeSpecConst(*StaticType::GetBasic(), + vk::SpecializationConstantId::SurfaceRotation); + + mSurfaceRotationVar = new TVariable(mSymbolTable, kSurfaceRotationSpecConstVarName, type, + SymbolType::AngleInternal); + } + return new TIntermSymbol(mSurfaceRotationVar); +} + +TIntermTyped *SpecConst::getSwapXY() +{ + if (!mCompileOptions.useSpecializationConstant) + { + return nullptr; + } + mUsageBits.set(vk::SpecConstUsage::Rotation); + return getRotation(); +} + +TIntermTyped *SpecConst::getDither() +{ + if (mDitherVar == nullptr) + { + const TType *type = MakeSpecConst(*StaticType::GetBasic(), + vk::SpecializationConstantId::Dither); + + mDitherVar = + new TVariable(mSymbolTable, kDitherSpecConstVarName, type, SymbolType::AngleInternal); + mUsageBits.set(vk::SpecConstUsage::Dither); + } + return new TIntermSymbol(mDitherVar); +} +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/SpecializationConstant.h b/gfx/angle/checkout/src/compiler/translator/tree_util/SpecializationConstant.h new file mode 100644 index 0000000000..6644706567 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/SpecializationConstant.h @@ -0,0 +1,55 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SpecializationConst.h: Add code to generate AST node for specialization constant. +// + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_SPECIALIZATIONCONSTANT_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_SPECIALIZATIONCONSTANT_H_ + +#include "common/angleutils.h" +#include "compiler/translator/Compiler.h" +#include "compiler/translator/SymbolTable.h" + +class TIntermBlock; +class TIntermTyped; +class TIntermSymbol; +class TVariable; + +namespace sh +{ + +class SpecConst +{ + public: + SpecConst(TSymbolTable *symbolTable, const ShCompileOptions &compileOptions, GLenum shaderType); + virtual ~SpecConst(); + + // Flip/rotation + // Returns a boolean: should X and Y be swapped? + TIntermTyped *getSwapXY(); + + // Dither emulation + TIntermTyped *getDither(); + + void declareSpecConsts(TIntermBlock *root); + SpecConstUsageBits getSpecConstUsageBits() const { return mUsageBits; } + + private: + TIntermSymbol *getRotation(); + + // If unsupported, this should be set to null. + TSymbolTable *mSymbolTable; + const ShCompileOptions &mCompileOptions; + + TVariable *mSurfaceRotationVar; + TVariable *mDitherVar; + + // Bit is set if YFlip or Rotation has been used + SpecConstUsageBits mUsageBits; +}; +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_SPECIALIZATIONCONSTANT_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/Visit.h b/gfx/angle/checkout/src/compiler/translator/tree_util/Visit.h new file mode 100644 index 0000000000..36a8f14a52 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/Visit.h @@ -0,0 +1,22 @@ +// +// Copyright 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TREEUTIL_VISIT_H_ +#define COMPILER_TRANSLATOR_TREEUTIL_VISIT_H_ + +namespace sh +{ + +enum Visit +{ + PreVisit, + InVisit, + PostVisit +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_TREEUTIL_VISIT_H_ diff --git a/gfx/angle/checkout/src/compiler/translator/util.cpp b/gfx/angle/checkout/src/compiler/translator/util.cpp new file mode 100644 index 0000000000..f1dd8c2fb3 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/util.cpp @@ -0,0 +1,1023 @@ +// +// Copyright 2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/util.h" + +#include + +#include "common/utilities.h" +#include "compiler/preprocessor/numeric_lex.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/SymbolTable.h" + +bool atoi_clamp(const char *str, unsigned int *value) +{ + bool success = angle::pp::numeric_lex_int(str, value); + if (!success) + *value = std::numeric_limits::max(); + return success; +} + +namespace sh +{ + +namespace +{ +// [primarySize-1][secondarySize-1] is the GL type with a basic type of float. +constexpr GLenum kFloatGLType[4][4] = { + // float1xS only makes sense for S == 1 + { + GL_FLOAT, + GL_NONE, + GL_NONE, + GL_NONE, + }, + // float2xS is vec2 for S == 1, and mat2xS o.w. + { + GL_FLOAT_VEC2, + GL_FLOAT_MAT2, + GL_FLOAT_MAT2x3, + GL_FLOAT_MAT2x4, + }, + // float3xS is vec3 for S == 1, and mat3xS o.w. + { + GL_FLOAT_VEC3, + GL_FLOAT_MAT3x2, + GL_FLOAT_MAT3, + GL_FLOAT_MAT3x4, + }, + // float4xS is vec4 for S == 1, and mat4xS o.w. + { + GL_FLOAT_VEC4, + GL_FLOAT_MAT4x2, + GL_FLOAT_MAT4x3, + GL_FLOAT_MAT4, + }, +}; +// [primarySize-1] is the GL type with a basic type of int. +constexpr GLenum kIntGLType[4] = {GL_INT, GL_INT_VEC2, GL_INT_VEC3, GL_INT_VEC4}; +// [primarySize-1] is the GL type with a basic type of uint. +constexpr GLenum kUIntGLType[4] = {GL_UNSIGNED_INT, GL_UNSIGNED_INT_VEC2, GL_UNSIGNED_INT_VEC3, + GL_UNSIGNED_INT_VEC4}; +// [primarySize-1] is the GL type with a basic type of bool. +constexpr GLenum kBoolGLType[4] = {GL_BOOL, GL_BOOL_VEC2, GL_BOOL_VEC3, GL_BOOL_VEC4}; + +bool IsInterpolationIn(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqSmoothIn: + case EvqFlatIn: + case EvqNoPerspectiveIn: + case EvqCentroidIn: + case EvqSampleIn: + return true; + default: + return false; + } +} + +bool IsInterpolationOut(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqSmoothOut: + case EvqFlatOut: + case EvqNoPerspectiveOut: + case EvqCentroidOut: + case EvqSampleOut: + return true; + default: + return false; + } +} +} // anonymous namespace + +float NumericLexFloat32OutOfRangeToInfinity(const std::string &str) +{ + // Parses a decimal string using scientific notation into a floating point number. + // Out-of-range values are converted to infinity. Values that are too small to be + // represented are converted to zero. + + // The mantissa in decimal scientific notation. The magnitude of the mantissa integer does not + // matter. + unsigned int decimalMantissa = 0; + size_t i = 0; + bool decimalPointSeen = false; + bool nonZeroSeenInMantissa = false; + + // The exponent offset reflects the position of the decimal point. + int exponentOffset = -1; + + // This is just a counter for how many decimal digits are written to decimalMantissa. + int mantissaDecimalDigits = 0; + + while (i < str.length()) + { + const char c = str[i]; + if (c == 'e' || c == 'E') + { + break; + } + if (c == '.') + { + decimalPointSeen = true; + ++i; + continue; + } + + unsigned int digit = static_cast(c - '0'); + ASSERT(digit < 10u); + if (digit != 0u) + { + nonZeroSeenInMantissa = true; + } + if (nonZeroSeenInMantissa) + { + // Add bits to the mantissa until space runs out in 32-bit int. This should be + // enough precision to make the resulting binary mantissa accurate to 1 ULP. + if (decimalMantissa <= (std::numeric_limits::max() - 9u) / 10u) + { + decimalMantissa = decimalMantissa * 10u + digit; + ++mantissaDecimalDigits; + } + if (!decimalPointSeen) + { + ++exponentOffset; + } + } + else if (decimalPointSeen) + { + --exponentOffset; + } + ++i; + } + if (decimalMantissa == 0) + { + return 0.0f; + } + int exponent = 0; + if (i < str.length()) + { + ASSERT(str[i] == 'e' || str[i] == 'E'); + ++i; + bool exponentOutOfRange = false; + bool negativeExponent = false; + if (str[i] == '-') + { + negativeExponent = true; + ++i; + } + else if (str[i] == '+') + { + ++i; + } + while (i < str.length()) + { + const char c = str[i]; + unsigned int digit = static_cast(c - '0'); + ASSERT(digit < 10u); + if (exponent <= (std::numeric_limits::max() - 9) / 10) + { + exponent = exponent * 10 + digit; + } + else + { + exponentOutOfRange = true; + } + ++i; + } + if (negativeExponent) + { + exponent = -exponent; + } + if (exponentOutOfRange) + { + if (negativeExponent) + { + return 0.0f; + } + else + { + return std::numeric_limits::infinity(); + } + } + } + // Do the calculation in 64-bit to avoid overflow. + long long exponentLong = + static_cast(exponent) + static_cast(exponentOffset); + if (exponentLong > std::numeric_limits::max_exponent10) + { + return std::numeric_limits::infinity(); + } + else if (exponentLong < std::numeric_limits::min_exponent10) + { + return 0.0f; + } + // The exponent is in range, so we need to actually evaluate the float. + exponent = static_cast(exponentLong); + double value = decimalMantissa; + + // Calculate the exponent offset to normalize the mantissa. + int normalizationExponentOffset = 1 - mantissaDecimalDigits; + // Apply the exponent. + value *= std::pow(10.0, static_cast(exponent + normalizationExponentOffset)); + if (value > static_cast(std::numeric_limits::max())) + { + return std::numeric_limits::infinity(); + } + if (value < static_cast(std::numeric_limits::min())) + { + return 0.0f; + } + return static_cast(value); +} + +bool strtof_clamp(const std::string &str, float *value) +{ + // Custom float parsing that can handle the following corner cases: + // 1. The decimal mantissa is very small but the exponent is very large, putting the resulting + // number inside the float range. + // 2. The decimal mantissa is very large but the exponent is very small, putting the resulting + // number inside the float range. + // 3. The value is out-of-range and should be evaluated as infinity. + // 4. The value is too small and should be evaluated as zero. + // See ESSL 3.00.6 section 4.1.4 for the relevant specification. + *value = NumericLexFloat32OutOfRangeToInfinity(str); + return !gl::isInf(*value); +} + +GLenum GLVariableType(const TType &type) +{ + switch (type.getBasicType()) + { + case EbtFloat: + ASSERT(type.getNominalSize() >= 1 && type.getNominalSize() <= 4); + ASSERT(type.getSecondarySize() >= 1 && type.getSecondarySize() <= 4); + + return kFloatGLType[type.getNominalSize() - 1][type.getSecondarySize() - 1]; + + case EbtInt: + ASSERT(type.getNominalSize() >= 1 && type.getNominalSize() <= 4); + ASSERT(type.getSecondarySize() == 1); + + return kIntGLType[type.getNominalSize() - 1]; + + case EbtUInt: + ASSERT(type.getNominalSize() >= 1 && type.getNominalSize() <= 4); + ASSERT(type.getSecondarySize() == 1); + + return kUIntGLType[type.getNominalSize() - 1]; + + case EbtBool: + ASSERT(type.getNominalSize() >= 1 && type.getNominalSize() <= 4); + ASSERT(type.getSecondarySize() == 1); + + return kBoolGLType[type.getNominalSize() - 1]; + + case EbtSampler2D: + return GL_SAMPLER_2D; + case EbtSampler3D: + return GL_SAMPLER_3D; + case EbtSamplerCube: + return GL_SAMPLER_CUBE; + case EbtSamplerExternalOES: + return GL_SAMPLER_EXTERNAL_OES; + case EbtSamplerExternal2DY2YEXT: + return GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT; + case EbtSampler2DRect: + return GL_SAMPLER_2D_RECT_ANGLE; + case EbtSampler2DArray: + return GL_SAMPLER_2D_ARRAY; + case EbtSampler2DMS: + return GL_SAMPLER_2D_MULTISAMPLE; + case EbtSampler2DMSArray: + return GL_SAMPLER_2D_MULTISAMPLE_ARRAY; + case EbtSamplerCubeArray: + return GL_SAMPLER_CUBE_MAP_ARRAY; + case EbtSamplerBuffer: + return GL_SAMPLER_BUFFER; + case EbtISampler2D: + return GL_INT_SAMPLER_2D; + case EbtISampler3D: + return GL_INT_SAMPLER_3D; + case EbtISamplerCube: + return GL_INT_SAMPLER_CUBE; + case EbtISampler2DArray: + return GL_INT_SAMPLER_2D_ARRAY; + case EbtISampler2DMS: + return GL_INT_SAMPLER_2D_MULTISAMPLE; + case EbtISampler2DMSArray: + return GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY; + case EbtISamplerCubeArray: + return GL_INT_SAMPLER_CUBE_MAP_ARRAY; + case EbtISamplerBuffer: + return GL_INT_SAMPLER_BUFFER; + case EbtUSampler2D: + return GL_UNSIGNED_INT_SAMPLER_2D; + case EbtUSampler3D: + return GL_UNSIGNED_INT_SAMPLER_3D; + case EbtUSamplerCube: + return GL_UNSIGNED_INT_SAMPLER_CUBE; + case EbtUSampler2DArray: + return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY; + case EbtUSampler2DMS: + return GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE; + case EbtUSampler2DMSArray: + return GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY; + case EbtUSamplerCubeArray: + return GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY; + case EbtUSamplerBuffer: + return GL_UNSIGNED_INT_SAMPLER_BUFFER; + case EbtSampler2DShadow: + return GL_SAMPLER_2D_SHADOW; + case EbtSamplerCubeShadow: + return GL_SAMPLER_CUBE_SHADOW; + case EbtSampler2DArrayShadow: + return GL_SAMPLER_2D_ARRAY_SHADOW; + case EbtSamplerCubeArrayShadow: + return GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW; + case EbtImage2D: + return GL_IMAGE_2D; + case EbtIImage2D: + return GL_INT_IMAGE_2D; + case EbtUImage2D: + return GL_UNSIGNED_INT_IMAGE_2D; + case EbtImage2DArray: + return GL_IMAGE_2D_ARRAY; + case EbtIImage2DArray: + return GL_INT_IMAGE_2D_ARRAY; + case EbtUImage2DArray: + return GL_UNSIGNED_INT_IMAGE_2D_ARRAY; + case EbtImage3D: + return GL_IMAGE_3D; + case EbtIImage3D: + return GL_INT_IMAGE_3D; + case EbtUImage3D: + return GL_UNSIGNED_INT_IMAGE_3D; + case EbtImageCube: + return GL_IMAGE_CUBE; + case EbtIImageCube: + return GL_INT_IMAGE_CUBE; + case EbtUImageCube: + return GL_UNSIGNED_INT_IMAGE_CUBE; + case EbtImageCubeArray: + return GL_IMAGE_CUBE_MAP_ARRAY; + case EbtIImageCubeArray: + return GL_INT_IMAGE_CUBE_MAP_ARRAY; + case EbtUImageCubeArray: + return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY; + case EbtImageBuffer: + return GL_IMAGE_BUFFER; + case EbtIImageBuffer: + return GL_INT_IMAGE_BUFFER; + case EbtUImageBuffer: + return GL_UNSIGNED_INT_IMAGE_BUFFER; + case EbtAtomicCounter: + return GL_UNSIGNED_INT_ATOMIC_COUNTER; + case EbtSamplerVideoWEBGL: + return GL_SAMPLER_VIDEO_IMAGE_WEBGL; + case EbtPixelLocalANGLE: + case EbtIPixelLocalANGLE: + case EbtUPixelLocalANGLE: + // TODO(anglebug.com/7279): For now, we can expect PLS handles to be rewritten to images + // before anyone calls into here. + [[fallthrough]]; + default: + UNREACHABLE(); + return GL_NONE; + } +} + +GLenum GLVariablePrecision(const TType &type) +{ + if (type.getBasicType() == EbtFloat) + { + switch (type.getPrecision()) + { + case EbpHigh: + return GL_HIGH_FLOAT; + case EbpMedium: + return GL_MEDIUM_FLOAT; + case EbpLow: + return GL_LOW_FLOAT; + case EbpUndefined: + // Desktop specs do not use precision + return GL_NONE; + default: + UNREACHABLE(); + } + } + else if (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt) + { + switch (type.getPrecision()) + { + case EbpHigh: + return GL_HIGH_INT; + case EbpMedium: + return GL_MEDIUM_INT; + case EbpLow: + return GL_LOW_INT; + case EbpUndefined: + // Desktop specs do not use precision + return GL_NONE; + default: + UNREACHABLE(); + } + } + + // Other types (boolean, sampler) don't have a precision + return GL_NONE; +} + +ImmutableString ArrayString(const TType &type) +{ + if (!type.isArray()) + return ImmutableString(""); + + const TSpan &arraySizes = type.getArraySizes(); + constexpr const size_t kMaxDecimalDigitsPerSize = 10u; + ImmutableStringBuilder arrayString(arraySizes.size() * (kMaxDecimalDigitsPerSize + 2u)); + for (auto arraySizeIter = arraySizes.rbegin(); arraySizeIter != arraySizes.rend(); + ++arraySizeIter) + { + arrayString << "["; + if (*arraySizeIter > 0) + { + arrayString.appendDecimal(*arraySizeIter); + } + arrayString << "]"; + } + return arrayString; +} + +ImmutableString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap) +{ + if (type.getBasicType() == EbtStruct) + return HashName(type.getStruct(), hashFunction, nameMap); + else + return ImmutableString(type.getBuiltInTypeNameString()); +} + +bool IsVaryingOut(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqVaryingOut: + case EvqSmoothOut: + case EvqFlatOut: + case EvqNoPerspectiveOut: + case EvqCentroidOut: + case EvqVertexOut: + case EvqGeometryOut: + case EvqTessControlOut: + case EvqTessEvaluationOut: + case EvqSampleOut: + case EvqPatchOut: + return true; + + default: + break; + } + + return false; +} + +bool IsVaryingIn(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqVaryingIn: + case EvqSmoothIn: + case EvqFlatIn: + case EvqNoPerspectiveIn: + case EvqCentroidIn: + case EvqFragmentIn: + case EvqGeometryIn: + case EvqTessControlIn: + case EvqTessEvaluationIn: + case EvqSampleIn: + case EvqPatchIn: + return true; + + default: + break; + } + + return false; +} + +bool IsVarying(TQualifier qualifier) +{ + return IsVaryingIn(qualifier) || IsVaryingOut(qualifier); +} + +bool IsMatrixGLType(GLenum type) +{ + switch (type) + { + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: + return true; + default: + return false; + } +} + +bool IsGeometryShaderInput(GLenum shaderType, TQualifier qualifier) +{ + return (qualifier == EvqGeometryIn) || + ((shaderType == GL_GEOMETRY_SHADER_EXT) && IsInterpolationIn(qualifier)); +} + +bool IsTessellationControlShaderInput(GLenum shaderType, TQualifier qualifier) +{ + return qualifier == EvqTessControlIn || + ((shaderType == GL_TESS_CONTROL_SHADER) && IsInterpolationIn(qualifier)); +} + +bool IsTessellationControlShaderOutput(GLenum shaderType, TQualifier qualifier) +{ + return qualifier == EvqTessControlOut || + ((shaderType == GL_TESS_CONTROL_SHADER) && IsInterpolationOut(qualifier)); +} + +bool IsTessellationEvaluationShaderInput(GLenum shaderType, TQualifier qualifier) +{ + return qualifier == EvqTessEvaluationIn || + ((shaderType == GL_TESS_EVALUATION_SHADER) && IsInterpolationIn(qualifier)); +} + +InterpolationType GetInterpolationType(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqFlatIn: + case EvqFlatOut: + // The auxiliary storage qualifier patch is not used for interpolation + // it is a compile-time error to use interpolation qualifiers with patch + case EvqPatchIn: + case EvqPatchOut: + return INTERPOLATION_FLAT; + + case EvqNoPerspectiveIn: + case EvqNoPerspectiveOut: + return INTERPOLATION_NOPERSPECTIVE; + + case EvqSmoothIn: + case EvqSmoothOut: + case EvqVertexOut: + case EvqFragmentIn: + case EvqVaryingIn: + case EvqVaryingOut: + case EvqGeometryIn: + case EvqGeometryOut: + case EvqTessControlIn: + case EvqTessControlOut: + case EvqTessEvaluationIn: + case EvqTessEvaluationOut: + return INTERPOLATION_SMOOTH; + + case EvqCentroidIn: + case EvqCentroidOut: + return INTERPOLATION_CENTROID; + + case EvqSampleIn: + case EvqSampleOut: + return INTERPOLATION_SAMPLE; + default: + UNREACHABLE(); + return INTERPOLATION_SMOOTH; + } +} + +// a field may not have qualifer without in or out. +InterpolationType GetFieldInterpolationType(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqFlat: + return INTERPOLATION_FLAT; + case EvqNoPerspective: + return INTERPOLATION_NOPERSPECTIVE; + case EvqSmooth: + return INTERPOLATION_SMOOTH; + case EvqCentroid: + return INTERPOLATION_CENTROID; + default: + return GetInterpolationType(qualifier); + } +} + +TType GetShaderVariableBasicType(const sh::ShaderVariable &var) +{ + switch (var.type) + { + case GL_BOOL: + return TType(EbtBool); + case GL_BOOL_VEC2: + return TType(EbtBool, 2); + case GL_BOOL_VEC3: + return TType(EbtBool, 3); + case GL_BOOL_VEC4: + return TType(EbtBool, 4); + case GL_FLOAT: + return TType(EbtFloat); + case GL_FLOAT_VEC2: + return TType(EbtFloat, 2); + case GL_FLOAT_VEC3: + return TType(EbtFloat, 3); + case GL_FLOAT_VEC4: + return TType(EbtFloat, 4); + case GL_FLOAT_MAT2: + return TType(EbtFloat, 2, 2); + case GL_FLOAT_MAT3: + return TType(EbtFloat, 3, 3); + case GL_FLOAT_MAT4: + return TType(EbtFloat, 4, 4); + case GL_FLOAT_MAT2x3: + return TType(EbtFloat, 2, 3); + case GL_FLOAT_MAT2x4: + return TType(EbtFloat, 2, 4); + case GL_FLOAT_MAT3x2: + return TType(EbtFloat, 3, 2); + case GL_FLOAT_MAT3x4: + return TType(EbtFloat, 3, 4); + case GL_FLOAT_MAT4x2: + return TType(EbtFloat, 4, 2); + case GL_FLOAT_MAT4x3: + return TType(EbtFloat, 4, 3); + case GL_INT: + return TType(EbtInt); + case GL_INT_VEC2: + return TType(EbtInt, 2); + case GL_INT_VEC3: + return TType(EbtInt, 3); + case GL_INT_VEC4: + return TType(EbtInt, 4); + case GL_UNSIGNED_INT: + return TType(EbtUInt); + case GL_UNSIGNED_INT_VEC2: + return TType(EbtUInt, 2); + case GL_UNSIGNED_INT_VEC3: + return TType(EbtUInt, 3); + case GL_UNSIGNED_INT_VEC4: + return TType(EbtUInt, 4); + default: + UNREACHABLE(); + return TType(); + } +} + +void DeclareGlobalVariable(TIntermBlock *root, const TVariable *variable) +{ + TIntermDeclaration *declaration = new TIntermDeclaration(); + declaration->appendDeclarator(new TIntermSymbol(variable)); + + TIntermSequence *globalSequence = root->getSequence(); + globalSequence->insert(globalSequence->begin(), declaration); +} + +// GLSL ES 1.0.17 4.6.1 The Invariant Qualifier +bool CanBeInvariantESSL1(TQualifier qualifier) +{ + return IsVaryingIn(qualifier) || IsVaryingOut(qualifier) || + IsBuiltinOutputVariable(qualifier) || + (IsBuiltinFragmentInputVariable(qualifier) && qualifier != EvqFrontFacing); +} + +// GLSL ES 3.00 Revision 6, 4.6.1 The Invariant Qualifier +// GLSL ES 3.10 Revision 4, 4.8.1 The Invariant Qualifier +bool CanBeInvariantESSL3OrGreater(TQualifier qualifier) +{ + return IsVaryingOut(qualifier) || qualifier == EvqFragmentOut || + IsBuiltinOutputVariable(qualifier) || qualifier == EvqFragmentInOut; +} + +bool IsBuiltinOutputVariable(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqPosition: + case EvqPointSize: + case EvqFragDepth: + case EvqFragColor: + case EvqSecondaryFragColorEXT: + case EvqFragData: + case EvqSecondaryFragDataEXT: + case EvqClipDistance: + case EvqCullDistance: + case EvqLastFragData: + case EvqSampleMask: + return true; + default: + break; + } + return false; +} + +bool IsBuiltinFragmentInputVariable(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqFragCoord: + case EvqPointCoord: + case EvqFrontFacing: + case EvqHelperInvocation: + case EvqLastFragData: + return true; + default: + break; + } + return false; +} + +bool IsShaderOutput(TQualifier qualifier) +{ + return IsVaryingOut(qualifier) || IsBuiltinOutputVariable(qualifier); +} + +bool IsFragmentOutput(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqFragmentOut: + case EvqFragmentInOut: + return true; + default: + return false; + } +} + +bool IsOutputESSL(ShShaderOutput output) +{ + return output == SH_ESSL_OUTPUT; +} + +bool IsOutputGLSL(ShShaderOutput output) +{ + switch (output) + { + case SH_GLSL_130_OUTPUT: + case SH_GLSL_140_OUTPUT: + case SH_GLSL_150_CORE_OUTPUT: + case SH_GLSL_330_CORE_OUTPUT: + case SH_GLSL_400_CORE_OUTPUT: + case SH_GLSL_410_CORE_OUTPUT: + case SH_GLSL_420_CORE_OUTPUT: + case SH_GLSL_430_CORE_OUTPUT: + case SH_GLSL_440_CORE_OUTPUT: + case SH_GLSL_450_CORE_OUTPUT: + case SH_GLSL_COMPATIBILITY_OUTPUT: + return true; + default: + break; + } + return false; +} +bool IsOutputHLSL(ShShaderOutput output) +{ + switch (output) + { + case SH_HLSL_3_0_OUTPUT: + case SH_HLSL_4_1_OUTPUT: + case SH_HLSL_4_0_FL9_3_OUTPUT: + return true; + default: + break; + } + return false; +} +bool IsOutputVulkan(ShShaderOutput output) +{ + return output == SH_SPIRV_VULKAN_OUTPUT; +} +bool IsOutputMetal(ShShaderOutput output) +{ + return output == SH_SPIRV_METAL_OUTPUT; +} +bool IsOutputMetalDirect(ShShaderOutput output) +{ + return output == SH_MSL_METAL_OUTPUT; +} + +bool IsInShaderStorageBlock(TIntermTyped *node) +{ + TIntermSwizzle *swizzleNode = node->getAsSwizzleNode(); + if (swizzleNode) + { + return IsInShaderStorageBlock(swizzleNode->getOperand()); + } + + TIntermBinary *binaryNode = node->getAsBinaryNode(); + if (binaryNode) + { + switch (binaryNode->getOp()) + { + case EOpIndexDirectInterfaceBlock: + case EOpIndexIndirect: + case EOpIndexDirect: + case EOpIndexDirectStruct: + return IsInShaderStorageBlock(binaryNode->getLeft()); + default: + return false; + } + } + + const TType &type = node->getType(); + return type.getQualifier() == EvqBuffer; +} + +GLenum GetImageInternalFormatType(TLayoutImageInternalFormat iifq) +{ + switch (iifq) + { + case EiifRGBA32F: + return GL_RGBA32F; + case EiifRGBA16F: + return GL_RGBA16F; + case EiifR32F: + return GL_R32F; + case EiifRGBA32UI: + return GL_RGBA32UI; + case EiifRGBA16UI: + return GL_RGBA16UI; + case EiifRGBA8UI: + return GL_RGBA8UI; + case EiifR32UI: + return GL_R32UI; + case EiifRGBA32I: + return GL_RGBA32I; + case EiifRGBA16I: + return GL_RGBA16I; + case EiifRGBA8I: + return GL_RGBA8I; + case EiifR32I: + return GL_R32I; + case EiifRGBA8: + return GL_RGBA8; + case EiifRGBA8_SNORM: + return GL_RGBA8_SNORM; + default: + return GL_NONE; + } +} + +bool IsSpecWithFunctionBodyNewScope(ShShaderSpec shaderSpec, int shaderVersion) +{ + return (shaderVersion == 100 && !sh::IsWebGLBasedSpec(shaderSpec)); +} + +ImplicitTypeConversion GetConversion(TBasicType t1, TBasicType t2) +{ + if (t1 == t2) + return ImplicitTypeConversion::Same; + + switch (t1) + { + case EbtInt: + switch (t2) + { + case EbtInt: + UNREACHABLE(); + break; + case EbtUInt: + return ImplicitTypeConversion::Invalid; + case EbtFloat: + return ImplicitTypeConversion::Left; + default: + return ImplicitTypeConversion::Invalid; + } + break; + case EbtUInt: + switch (t2) + { + case EbtInt: + return ImplicitTypeConversion::Invalid; + case EbtUInt: + UNREACHABLE(); + break; + case EbtFloat: + return ImplicitTypeConversion::Left; + default: + return ImplicitTypeConversion::Invalid; + } + break; + case EbtFloat: + switch (t2) + { + case EbtInt: + case EbtUInt: + return ImplicitTypeConversion::Right; + case EbtFloat: + UNREACHABLE(); + break; + default: + return ImplicitTypeConversion::Invalid; + } + break; + default: + return ImplicitTypeConversion::Invalid; + } + return ImplicitTypeConversion::Invalid; +} + +bool IsValidImplicitConversion(sh::ImplicitTypeConversion conversion, TOperator op) +{ + switch (conversion) + { + case sh::ImplicitTypeConversion::Same: + return true; + case sh::ImplicitTypeConversion::Left: + switch (op) + { + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + case EOpAdd: + case EOpSub: + case EOpMul: + case EOpDiv: + return true; + default: + break; + } + break; + case sh::ImplicitTypeConversion::Right: + switch (op) + { + case EOpAssign: + case EOpInitialize: + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + case EOpAdd: + case EOpSub: + case EOpMul: + case EOpDiv: + case EOpAddAssign: + case EOpSubAssign: + case EOpMulAssign: + case EOpDivAssign: + return true; + default: + break; + } + break; + case sh::ImplicitTypeConversion::Invalid: + break; + } + return false; +} + +bool IsPrecisionApplicableToType(TBasicType type) +{ + switch (type) + { + case EbtInt: + case EbtUInt: + case EbtFloat: + // TODO: find all types where precision is applicable; for example samplers. + // http://anglebug.com/6132 + return true; + default: + return false; + } +} + +bool IsRedeclarableBuiltIn(const ImmutableString &name) +{ + return name == "gl_ClipDistance" || name == "gl_CullDistance" || name == "gl_LastFragData" || + name == "gl_PerVertex" || name == "gl_Position" || name == "gl_PointSize"; +} + +size_t FindFieldIndex(const TFieldList &fieldList, const char *fieldName) +{ + for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex) + { + if (strcmp(fieldList[fieldIndex]->name().data(), fieldName) == 0) + { + return fieldIndex; + } + } + UNREACHABLE(); + return 0; +} + +} // namespace sh diff --git a/gfx/angle/checkout/src/compiler/translator/util.h b/gfx/angle/checkout/src/compiler/translator/util.h new file mode 100644 index 0000000000..7d7a929f8a --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/util.h @@ -0,0 +1,108 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_UTIL_H_ +#define COMPILER_TRANSLATOR_UTIL_H_ + +#include + +#include +#include "angle_gl.h" + +#include "compiler/translator/HashNames.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/Operator_autogen.h" +#include "compiler/translator/Types.h" + +// If overflow happens, clamp the value to UINT_MIN or UINT_MAX. +// Return false if overflow happens. +bool atoi_clamp(const char *str, unsigned int *value); + +namespace sh +{ + +// Keeps track of whether an implicit conversion from int/uint to float is possible. +// These conversions are supported in desktop GLSL shaders only. +// Also keeps track of which side of operation should be converted. +enum class ImplicitTypeConversion +{ + Same, + Left, + Right, + Invalid, +}; + +class TIntermBlock; +class TSymbolTable; +class TIntermTyped; + +float NumericLexFloat32OutOfRangeToInfinity(const std::string &str); + +// strtof_clamp is like strtof but +// 1. it forces C locale, i.e. forcing '.' as decimal point. +// 2. it sets the value to infinity if overflow happens. +// 3. str should be guaranteed to be in the valid format for a floating point number as defined +// by the grammar in the ESSL 3.00.6 spec section 4.1.4. +// Return false if overflow happens. +bool strtof_clamp(const std::string &str, float *value); + +GLenum GLVariableType(const TType &type); +GLenum GLVariablePrecision(const TType &type); +bool IsVaryingIn(TQualifier qualifier); +bool IsVaryingOut(TQualifier qualifier); +bool IsVarying(TQualifier qualifier); +bool IsMatrixGLType(GLenum type); +bool IsGeometryShaderInput(GLenum shaderType, TQualifier qualifier); +bool IsTessellationControlShaderInput(GLenum shaderType, TQualifier qualifier); +bool IsTessellationControlShaderOutput(GLenum shaderType, TQualifier qualifier); +bool IsTessellationEvaluationShaderInput(GLenum shaderType, TQualifier qualifier); +InterpolationType GetInterpolationType(TQualifier qualifier); +InterpolationType GetFieldInterpolationType(TQualifier qualifier); + +// Returns array brackets including size with outermost array size first, as specified in GLSL ES +// 3.10 section 4.1.9. +ImmutableString ArrayString(const TType &type); + +ImmutableString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap); + +TType GetShaderVariableBasicType(const sh::ShaderVariable &var); + +void DeclareGlobalVariable(TIntermBlock *root, const TVariable *variable); + +bool IsBuiltinOutputVariable(TQualifier qualifier); +bool IsBuiltinFragmentInputVariable(TQualifier qualifier); +bool CanBeInvariantESSL1(TQualifier qualifier); +bool CanBeInvariantESSL3OrGreater(TQualifier qualifier); +bool IsShaderOutput(TQualifier qualifier); +bool IsFragmentOutput(TQualifier qualifier); +bool IsOutputESSL(ShShaderOutput output); +bool IsOutputGLSL(ShShaderOutput output); +bool IsOutputHLSL(ShShaderOutput output); +bool IsOutputVulkan(ShShaderOutput output); +bool IsOutputMetal(ShShaderOutput output); +bool IsOutputMetalDirect(ShShaderOutput output); + +bool IsInShaderStorageBlock(TIntermTyped *node); + +GLenum GetImageInternalFormatType(TLayoutImageInternalFormat iifq); +// ESSL 1.00 shaders nest function body scope within function parameter scope +bool IsSpecWithFunctionBodyNewScope(ShShaderSpec shaderSpec, int shaderVersion); + +// Helper functions for implicit conversions +ImplicitTypeConversion GetConversion(TBasicType t1, TBasicType t2); + +bool IsValidImplicitConversion(ImplicitTypeConversion conversion, TOperator op); + +// Whether the given basic type requires precision. +bool IsPrecisionApplicableToType(TBasicType type); + +// Whether this is the name of a built-in that can be redeclared by the shader. +bool IsRedeclarableBuiltIn(const ImmutableString &name); + +size_t FindFieldIndex(const TFieldList &fieldList, const char *fieldName); +} // namespace sh + +#endif // COMPILER_TRANSLATOR_UTIL_H_ -- cgit v1.2.3