summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp462
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h63
-rw-r--r--src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp59
-rw-r--r--src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h20
-rw-r--r--src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp58
-rw-r--r--src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h22
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp213
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h22
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BaseTypes.h1073
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp107
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h23
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp355
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h183
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp293
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h40
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp184
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h27
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Cache.cpp99
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Cache.h84
-rw-r--r--src/3rdparty/angle/src/compiler/translator/CallDAG.cpp346
-rw-r--r--src/3rdparty/angle/src/compiler/translator/CallDAG.h79
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp47
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ClampPointSize.h22
-rw-r--r--src/3rdparty/angle/src/compiler/translator/CodeGen.cpp75
-rw-r--r--src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp869
-rw-r--r--src/3rdparty/angle/src/compiler/translator/CollectVariables.h37
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Common.h138
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Compiler.cpp1169
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Compiler.h308
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp681
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ConstantUnion.h117
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp221
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h48
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp147
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h32
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp105
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Diagnostics.h67
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp203
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h57
-rw-r--r--src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp129
-rw-r--r--src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h31
-rw-r--r--src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp751
-rw-r--r--src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h73
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp153
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h29
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp96
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h60
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp105
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h44
-rw-r--r--src/3rdparty/angle/src/compiler/translator/FindMain.cpp38
-rw-r--r--src/3rdparty/angle/src/compiler/translator/FindMain.h23
-rw-r--r--src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp58
-rw-r--r--src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h27
-rw-r--r--src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp75
-rw-r--r--src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h30
-rw-r--r--src/3rdparty/angle/src/compiler/translator/HashNames.cpp72
-rw-r--r--src/3rdparty/angle/src/compiler/translator/HashNames.h28
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp304
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h76
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InfoSink.cpp40
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InfoSink.h120
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Initialize.cpp1135
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Initialize.h38
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp37
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeDll.h15
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h13
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp290
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeVariables.h53
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNode.cpp3330
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNode.h917
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp157
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h75
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp254
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNode_util.h60
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp983
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermTraverse.h355
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp51
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h20
-rw-r--r--src/3rdparty/angle/src/compiler/translator/NodeSearch.h56
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Operator.cpp385
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Operator.h255
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp47
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputESSL.h37
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp110
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputGLSL.h36
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp1357
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h122
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp3084
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputHLSL.h248
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputTree.cpp682
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputTree.h22
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp80
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h34
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ParamType.h102
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ParseContext.cpp6022
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ParseContext.h657
-rw-r--r--src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp360
-rw-r--r--src/3rdparty/angle/src/compiler/translator/PoolAlloc.h319
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Pragma.h31
-rw-r--r--src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp156
-rw-r--r--src/3rdparty/angle/src/compiler/translator/PruneNoOps.h24
-rw-r--r--src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp784
-rw-r--r--src/3rdparty/angle/src/compiler/translator/QualifierTypes.h191
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp167
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h28
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp76
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h45
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp83
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h29
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp550
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h27
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp56
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h18
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp43
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h18
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp116
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h21
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemovePow.cpp97
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemovePow.h21
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp270
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h27
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp358
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h24
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp159
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h23
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp120
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h22
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp154
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h28
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp94
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h19
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp112
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h20
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp112
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h23
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp238
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h27
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp38
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SearchSymbol.h33
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp92
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h29
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp79
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h26
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp126
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h23
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Severity.h22
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp578
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp586
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp300
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h25
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp171
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h28
-rw-r--r--src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp594
-rw-r--r--src/3rdparty/angle/src/compiler/translator/StructureHLSL.h98
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp622
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SymbolTable.h545
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp28
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h36
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp1322
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h76
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp184
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h35
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp339
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h38
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp161
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h41
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp173
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h34
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Types.cpp1072
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Types.h509
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp59
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h33
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp186
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h25
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp600
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UniformHLSL.h110
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp105
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h30
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp970
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h129
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp120
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h23
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp444
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h27
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp29
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h21
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp174
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h30
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp319
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h28
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp174
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h25
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp413
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VariablePacker.h32
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp284
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h25
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp143
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VersionGLSL.h76
-rw-r--r--src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp132
-rw-r--r--src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h22
-rw-r--r--src/3rdparty/angle/src/compiler/translator/blocklayout.cpp281
-rw-r--r--src/3rdparty/angle/src/compiler/translator/blocklayout.h144
-rw-r--r--src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp166
-rw-r--r--src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h68
-rw-r--r--src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json1382
-rw-r--r--src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp859
-rw-r--r--src/3rdparty/angle/src/compiler/translator/glslang.h24
-rw-r--r--src/3rdparty/angle/src/compiler/translator/glslang.l697
-rw-r--r--src/3rdparty/angle/src/compiler/translator/glslang.y1468
-rw-r--r--src/3rdparty/angle/src/compiler/translator/length_limits.h26
-rw-r--r--src/3rdparty/angle/src/compiler/translator/util.cpp714
-rw-r--r--src/3rdparty/angle/src/compiler/translator/util.h63
212 files changed, 0 insertions, 55469 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp
deleted file mode 100644
index b04fc28259..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp
+++ /dev/null
@@ -1,462 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-// Analysis of the AST needed for HLSL generation
-
-#include "compiler/translator/ASTMetadataHLSL.h"
-
-#include "compiler/translator/CallDAG.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.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("texture2D");
- mGradientBuiltinFunctions.insert("texture2DProj");
- mGradientBuiltinFunctions.insert("textureCube");
-
- // ESSL 300 builtin gradient functions
- mGradientBuiltinFunctions.insert("texture");
- mGradientBuiltinFunctions.insert("textureProj");
- mGradientBuiltinFunctions.insert("textureOffset");
- mGradientBuiltinFunctions.insert("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 visitUnary(Visit visit, TIntermUnary *node) override
- {
- if (visit == PreVisit)
- {
- switch (node->getOp())
- {
- case EOpDFdx:
- case EOpDFdy:
- case EOpFwidth:
- onGradient();
- default:
- break;
- }
- }
-
- return true;
- }
-
- bool visitAggregate(Visit visit, TIntermAggregate *node) override
- {
- if (visit == PreVisit)
- {
- if (node->getOp() == EOpCallFunctionInAST)
- {
- size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo());
- ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
-
- if ((*mMetadataList)[calleeIndex].mUsesGradient)
- {
- onGradient();
- }
- }
- else if (node->getOp() == EOpCallBuiltInFunction)
- {
- if (mGradientBuiltinFunctions.find(node->getFunctionSymbolInfo()->getName()) !=
- 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<TIntermNode *> mParents;
-
- // A list of builtin functions that use gradients
- std::set<TString> 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->getFunctionSymbolInfo());
- 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<TIntermNode *> mLoopsAndSwitches;
- std::vector<TIntermIfElse *> 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->getFunctionSymbolInfo());
- 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;
-};
-}
-
-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/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h b/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h
deleted file mode 100644
index 550a522b86..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-// Defines analyses of the AST needed for HLSL generation
-
-#ifndef COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_
-#define COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_
-
-#include <set>
-#include <vector>
-
-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<TIntermNode *> mControlFlowsContainingGradient;
-
- // Remember information about the discontinuous loops and which functions
- // are called in such loops.
- bool mCalledInDiscontinuousLoop;
- bool mHasGradientLoopInCallGraph;
- std::set<TIntermLoop *> mDiscontinuousLoops;
- std::set<TIntermIfElse *> mIfsContainingGradientLoop;
-
- // Will we need to generate a Lod0 version of the function.
- bool mNeedsLod0;
-};
-
-typedef std::vector<ASTMetadataHLSL> 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/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp b/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp
deleted file mode 100644
index 6a05104233..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-// Copyright (c) 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/AddAndTrueToLoopCondition.h"
-
-#include "compiler/translator/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.
- TConstantUnion *trueConstant = new TConstantUnion();
- trueConstant->setBConst(true);
- TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, TType(EbtBool));
-
- // CONDITION && true.
- TIntermBinary *andOp = new TIntermBinary(EOpLogicalAnd, loop->getCondition(), trueValue);
- loop->setCondition(andOp);
-
- return true;
- }
-};
-
-} // anonymous namespace
-
-void AddAndTrueToLoopCondition(TIntermNode *root)
-{
- AddAndTrueToLoopConditionTraverser traverser;
- root->traverse(&traverser);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h b/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h
deleted file mode 100644
index 34debe0ed9..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Copyright (c) 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_ADDANDTRUETOLOOPCONDITION_H_
-#define COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
-
-class TIntermNode;
-namespace sh
-{
-
-void AddAndTrueToLoopCondition(TIntermNode *root);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp b/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp
deleted file mode 100644
index 4dfe60c0bc..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-// Copyright (c) 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/AddDefaultReturnStatements.h"
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/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
-
-void AddDefaultReturnStatements(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);
- }
- }
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h b/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h
deleted file mode 100644
index 40a70ad8c2..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 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_ADDDEFAULTRETURNSTATEMENTS_H_
-#define COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
-
-class TIntermBlock;
-
-namespace sh
-{
-
-void AddDefaultReturnStatements(TIntermBlock *root);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp b/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
deleted file mode 100644
index 17721fb0dc..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// The ArrayReturnValueToOutParameter function changes return values of an array type to out
-// parameters in function definitions, prototypes, and call sites.
-
-#include "compiler/translator/ArrayReturnValueToOutParameter.h"
-
-#include <map>
-
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-namespace
-{
-
-void CopyAggregateChildren(TIntermAggregateBase *from, TIntermAggregateBase *to)
-{
- const TIntermSequence *fromSequence = from->getSequence();
- for (size_t ii = 0; ii < fromSequence->size(); ++ii)
- {
- to->getSequence()->push_back(fromSequence->at(ii));
- }
-}
-
-TIntermSymbol *CreateReturnValueSymbol(const TSymbolUniqueId &id, const TType &type)
-{
- TIntermSymbol *node = new TIntermSymbol(id, "angle_return", type);
- node->setInternal(true);
- node->getTypePointer()->setQualifier(EvqOut);
- return node;
-}
-
-TIntermAggregate *CreateReplacementCall(TIntermAggregate *originalCall,
- TIntermTyped *returnValueTarget)
-{
- TIntermSequence *replacementArguments = new TIntermSequence();
- TIntermSequence *originalArguments = originalCall->getSequence();
- for (auto &arg : *originalArguments)
- {
- replacementArguments->push_back(arg);
- }
- replacementArguments->push_back(returnValueTarget);
- TIntermAggregate *replacementCall = TIntermAggregate::CreateFunctionCall(
- TType(EbtVoid), originalCall->getFunctionSymbolInfo()->getId(),
- originalCall->getFunctionSymbolInfo()->getNameObj(), replacementArguments);
- replacementCall->setLine(originalCall->getLine());
- return replacementCall;
-}
-
-class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser
-{
- public:
- static void apply(TIntermNode *root, TSymbolTable *symbolTable);
-
- private:
- ArrayReturnValueToOutParameterTraverser(TSymbolTable *symbolTable);
-
- bool visitFunctionPrototype(Visit visit, 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;
-
- // Set when traversal is inside a function with array return value.
- TIntermFunctionDefinition *mFunctionWithArrayReturnValue;
-
- // Map from function symbol ids to array return value ids.
- std::map<int, TSymbolUniqueId *> mReturnValueIds;
-};
-
-void ArrayReturnValueToOutParameterTraverser::apply(TIntermNode *root, TSymbolTable *symbolTable)
-{
- ArrayReturnValueToOutParameterTraverser arrayReturnValueToOutParam(symbolTable);
- root->traverse(&arrayReturnValueToOutParam);
- arrayReturnValueToOutParam.updateTree();
-}
-
-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;
-}
-
-bool ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(Visit visit,
- TIntermFunctionPrototype *node)
-{
- if (visit == PreVisit && node->isArray())
- {
- // Replace the whole prototype node with another node that has the out parameter
- // added. Also set the function to return void.
- TIntermFunctionPrototype *replacement =
- new TIntermFunctionPrototype(TType(EbtVoid), node->getFunctionSymbolInfo()->getId());
- CopyAggregateChildren(node, replacement);
- const TSymbolUniqueId &functionId = node->getFunctionSymbolInfo()->getId();
- if (mReturnValueIds.find(functionId.get()) == mReturnValueIds.end())
- {
- mReturnValueIds[functionId.get()] = new TSymbolUniqueId(mSymbolTable);
- }
- replacement->getSequence()->push_back(
- CreateReturnValueSymbol(*mReturnValueIds[functionId.get()], node->getType()));
- *replacement->getFunctionSymbolInfo() = *node->getFunctionSymbolInfo();
- replacement->setLine(node->getLine());
-
- queueReplacement(replacement, OriginalNode::IS_DROPPED);
- }
- return false;
-}
-
-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)
- {
- nextTemporaryId();
- TIntermSequence replacements;
- replacements.push_back(createTempDeclaration(node->getType()));
- TIntermSymbol *returnSymbol = createTempSymbol(node->getType());
- replacements.push_back(CreateReplacementCall(node, returnSymbol));
- mMultiReplacements.push_back(
- NodeReplaceWithMultipleEntry(parentBlock, node, 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->getFunctionSymbolInfo()->getId();
- ASSERT(mReturnValueIds.find(functionId.get()) != mReturnValueIds.end());
- const TSymbolUniqueId &returnValueId = *mReturnValueIds[functionId.get()];
- TIntermSymbol *returnValueSymbol =
- CreateReturnValueSymbol(returnValueId, expression->getType());
- 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.push_back(
- NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, 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
-
-void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable)
-{
- ArrayReturnValueToOutParameterTraverser::apply(root, symbolTable);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h b/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h
deleted file mode 100644
index 469c7a3b14..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// The ArrayReturnValueToOutParameter function changes return values of an array type to out
-// parameters in function definitions, prototypes and call sites.
-
-#ifndef COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
-#define COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
-
-namespace sh
-{
-
-class TIntermNode;
-class TSymbolTable;
-
-void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h
deleted file mode 100644
index b2070f3baf..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h
+++ /dev/null
@@ -1,1073 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#ifndef COMPILER_TRANSLATOR_BASETYPES_H_
-#define COMPILER_TRANSLATOR_BASETYPES_H_
-
-#include <algorithm>
-#include <array>
-
-#include "common/debug.h"
-#include "GLSLANG/ShaderLang.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,
- EbtInt,
- EbtUInt,
- EbtBool,
- EbtGVec4, // non type: represents vec4, ivec4, and uvec4
- EbtGenType, // non type: represents float, vec2, vec3, and vec4
- EbtGenIType, // non type: represents int, ivec2, ivec3, and ivec4
- EbtGenUType, // non type: represents uint, uvec2, uvec3, and uvec4
- EbtGenBType, // non type: represents bool, bvec2, bvec3, and bvec4
- EbtVec, // non type: represents vec2, vec3, and vec4
- EbtIVec, // non type: represents ivec2, ivec3, and ivec4
- EbtUVec, // non type: represents uvec2, uvec3, and uvec4
- EbtBVec, // non type: represents bvec2, bvec3, and bvec4
- EbtYuvCscStandardEXT, // Only valid if EXT_YUV_target exists.
- EbtGuardSamplerBegin, // non type: see implementation of IsSampler()
- EbtSampler2D,
- 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,
- EbtISampler2D,
- EbtISampler3D,
- EbtISamplerCube,
- EbtISampler2DArray,
- EbtISampler2DMS,
- EbtUSampler2D,
- EbtUSampler3D,
- EbtUSamplerCube,
- EbtUSampler2DArray,
- EbtUSampler2DMS,
- EbtSampler2DShadow,
- EbtSamplerCubeShadow,
- EbtSampler2DArrayShadow,
- EbtGuardSamplerEnd, // non type: see implementation of IsSampler()
- EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D
- EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D
- EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube
- EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and
- // usampler2DArray
- EbtGSampler2DMS, // non type: represents sampler2DMS, isampler2DMS, and usampler2DMS
-
- // images
- EbtGuardImageBegin,
- EbtImage2D,
- EbtIImage2D,
- EbtUImage2D,
- EbtImage3D,
- EbtIImage3D,
- EbtUImage3D,
- EbtImage2DArray,
- EbtIImage2DArray,
- EbtUImage2DArray,
- EbtImageCube,
- EbtIImageCube,
- EbtUImageCube,
- EbtGuardImageEnd,
-
- EbtGuardGImageBegin,
- EbtGImage2D, // non type: represents image2D, uimage2D, iimage2D
- EbtGImage3D, // non type: represents image3D, uimage3D, iimage3D
- EbtGImage2DArray, // non type: represents image2DArray, uimage2DArray, iimage2DArray
- EbtGImageCube, // non type: represents imageCube, uimageCube, iimageCube
- EbtGuardGImageEnd,
-
- EbtStruct,
- EbtInterfaceBlock,
- EbtAddress, // should be deprecated??
-
- EbtAtomicCounter,
-
- // end of list
- EbtLast
-};
-
-inline TBasicType convertGImageToFloatImage(TBasicType type)
-{
- switch (type)
- {
- case EbtGImage2D:
- return EbtImage2D;
- case EbtGImage3D:
- return EbtImage3D;
- case EbtGImage2DArray:
- return EbtImage2DArray;
- case EbtGImageCube:
- return EbtImageCube;
- default:
- UNREACHABLE();
- }
- return EbtLast;
-}
-
-inline TBasicType convertGImageToIntImage(TBasicType type)
-{
- switch (type)
- {
- case EbtGImage2D:
- return EbtIImage2D;
- case EbtGImage3D:
- return EbtIImage3D;
- case EbtGImage2DArray:
- return EbtIImage2DArray;
- case EbtGImageCube:
- return EbtIImageCube;
- default:
- UNREACHABLE();
- }
- return EbtLast;
-}
-
-inline TBasicType convertGImageToUnsignedImage(TBasicType type)
-{
- switch (type)
- {
- case EbtGImage2D:
- return EbtUImage2D;
- case EbtGImage3D:
- return EbtUImage3D;
- case EbtGImage2DArray:
- return EbtUImage2DArray;
- case EbtGImageCube:
- return EbtUImageCube;
- default:
- UNREACHABLE();
- }
- return EbtLast;
-}
-
-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 IsGImage(TBasicType type)
-{
- return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd;
-}
-
-inline bool IsAtomicCounter(TBasicType type)
-{
- return type == EbtAtomicCounter;
-}
-
-inline bool IsOpaqueType(TBasicType type)
-{
- return IsSampler(type) || IsImage(type) || IsAtomicCounter(type);
-}
-
-inline bool IsIntegerSampler(TBasicType type)
-{
- switch (type)
- {
- case EbtISampler2D:
- case EbtISampler3D:
- case EbtISamplerCube:
- case EbtISampler2DArray:
- case EbtISampler2DMS:
- case EbtUSampler2D:
- case EbtUSampler3D:
- case EbtUSamplerCube:
- case EbtUSampler2DArray:
- case EbtUSampler2DMS:
- return true;
- case EbtSampler2D:
- case EbtSampler3D:
- case EbtSamplerCube:
- case EbtSamplerExternalOES:
- case EbtSamplerExternal2DY2YEXT:
- case EbtSampler2DRect:
- case EbtSampler2DArray:
- case EbtSampler2DShadow:
- case EbtSamplerCubeShadow:
- case EbtSampler2DArrayShadow:
- case EbtSampler2DMS:
- return false;
- default:
- assert(!IsSampler(type));
- }
-
- return false;
-}
-
-inline bool IsSampler2DMS(TBasicType type)
-{
- switch (type)
- {
- case EbtSampler2DMS:
- case EbtISampler2DMS:
- case EbtUSampler2DMS:
- return true;
- default:
- return false;
- }
-}
-
-inline bool IsFloatImage(TBasicType type)
-{
- switch (type)
- {
- case EbtImage2D:
- case EbtImage3D:
- case EbtImage2DArray:
- case EbtImageCube:
- return true;
- default:
- break;
- }
-
- return false;
-}
-
-inline bool IsIntegerImage(TBasicType type)
-{
-
- switch (type)
- {
- case EbtIImage2D:
- case EbtIImage3D:
- case EbtIImage2DArray:
- case EbtIImageCube:
- return true;
- default:
- break;
- }
-
- return false;
-}
-
-inline bool IsUnsignedImage(TBasicType type)
-{
-
- switch (type)
- {
- case EbtUImage2D:
- case EbtUImage3D:
- case EbtUImage2DArray:
- case EbtUImageCube:
- return true;
- default:
- break;
- }
-
- return false;
-}
-
-inline bool IsSampler2D(TBasicType type)
-{
- switch (type)
- {
- case EbtSampler2D:
- case EbtISampler2D:
- case EbtUSampler2D:
- case EbtSampler2DArray:
- case EbtISampler2DArray:
- case EbtUSampler2DArray:
- case EbtSampler2DRect:
- case EbtSamplerExternalOES:
- case EbtSamplerExternal2DY2YEXT:
- case EbtSampler2DShadow:
- case EbtSampler2DArrayShadow:
- case EbtSampler2DMS:
- case EbtISampler2DMS:
- case EbtUSampler2DMS:
- return true;
- case EbtSampler3D:
- case EbtISampler3D:
- case EbtUSampler3D:
- case EbtISamplerCube:
- case EbtUSamplerCube:
- case EbtSamplerCube:
- case EbtSamplerCubeShadow:
- 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 EbtISampler2D:
- case EbtISampler3D:
- case EbtISampler2DArray:
- case EbtISampler2DMS:
- case EbtUSampler2D:
- case EbtUSampler3D:
- case EbtUSampler2DArray:
- case EbtUSampler2DMS:
- case EbtSampler2DShadow:
- case EbtSampler2DArrayShadow:
- 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 EbtISampler2D:
- case EbtISamplerCube:
- case EbtISampler2DArray:
- case EbtISampler2DMS:
- case EbtUSampler2D:
- case EbtUSamplerCube:
- case EbtUSampler2DArray:
- case EbtUSampler2DMS:
- case EbtSampler2DShadow:
- case EbtSamplerCubeShadow:
- case EbtSampler2DArrayShadow:
- return false;
- default:
- assert(!IsSampler(type));
- }
-
- return false;
-}
-
-inline bool IsSamplerArray(TBasicType type)
-{
- switch (type)
- {
- case EbtSampler2DArray:
- case EbtISampler2DArray:
- case EbtUSampler2DArray:
- case EbtSampler2DArrayShadow:
- 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:
- return false;
- default:
- assert(!IsSampler(type));
- }
-
- return false;
-}
-
-inline bool IsShadowSampler(TBasicType type)
-{
- switch (type)
- {
- case EbtSampler2DShadow:
- case EbtSamplerCubeShadow:
- case EbtSampler2DArrayShadow:
- return true;
- case EbtISampler2D:
- case EbtISampler3D:
- case EbtISamplerCube:
- case EbtISampler2DArray:
- case EbtISampler2DMS:
- case EbtUSampler2D:
- case EbtUSampler3D:
- case EbtUSamplerCube:
- case EbtUSampler2DArray:
- case EbtUSampler2DMS:
- case EbtSampler2D:
- case EbtSampler3D:
- case EbtSamplerCube:
- case EbtSamplerExternalOES:
- case EbtSamplerExternal2DY2YEXT:
- case EbtSampler2DRect:
- case EbtSampler2DArray:
- case EbtSampler2DMS:
- return false;
- default:
- assert(!IsSampler(type));
- }
-
- return false;
-}
-
-inline bool IsImage2D(TBasicType type)
-{
- switch (type)
- {
- case EbtImage2D:
- case EbtIImage2D:
- case EbtUImage2D:
- return true;
- case EbtImage3D:
- case EbtIImage3D:
- case EbtUImage3D:
- case EbtImage2DArray:
- case EbtIImage2DArray:
- case EbtUImage2DArray:
- case EbtImageCube:
- case EbtIImageCube:
- case EbtUImageCube:
- 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:
- return false;
- default:
- assert(!IsImage(type));
- }
-
- return false;
-}
-
-inline bool IsImage2DArray(TBasicType type)
-{
- switch (type)
- {
- case EbtImage2DArray:
- case EbtIImage2DArray:
- case EbtUImage2DArray:
- return true;
- case EbtImage2D:
- case EbtIImage2D:
- case EbtUImage2D:
- case EbtImage3D:
- case EbtIImage3D:
- case EbtUImage3D:
- case EbtImageCube:
- case EbtIImageCube:
- case EbtUImageCube:
- 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:
- return false;
- default:
- assert(!IsImage(type));
- }
-
- 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 and non-output parameters in functions
- 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
-
- EvqVertexIn, // Vertex shader input
- EvqFragmentOut, // Fragment shader output
- EvqVertexOut, // Vertex shader output
- EvqFragmentIn, // Fragment shader input
-
- // parameters
- EvqIn,
- EvqOut,
- EvqInOut,
- EvqConstReadOnly,
-
- // built-ins read by vertex shader
- EvqInstanceID,
- EvqVertexID,
-
- // built-ins written by vertex shader
- EvqPosition,
- EvqPointSize,
-
- // built-ins read by fragment shader
- EvqFragCoord,
- EvqFrontFacing,
- EvqPointCoord,
-
- // built-ins written by fragment shader
- EvqFragColor,
- EvqFragData,
-
- EvqFragDepth, // gl_FragDepth for ESSL300.
- EvqFragDepthEXT, // gl_FragDepthEXT for ESSL100, EXT_frag_depth.
-
- EvqSecondaryFragColorEXT, // EXT_blend_func_extended
- EvqSecondaryFragDataEXT, // EXT_blend_func_extended
-
- EvqViewIDOVR, // OVR_multiview
- EvqViewportIndex, // gl_ViewportIndex
-
- // 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
- EvqCentroid, // Incomplete qualifier
- EvqSmoothOut,
- EvqFlatOut,
- EvqCentroidOut, // Implies smooth
- EvqSmoothIn,
- EvqFlatIn,
- EvqCentroidIn, // Implies smooth
-
- // 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 OES_geometry_shader qualifiers
- EvqGeometryIn,
- EvqGeometryOut,
- EvqPerVertexIn, // gl_in
- EvqPrimitiveIDIn, // gl_PrimitiveIDIn
- EvqInvocationID, // gl_InvocationID
- EvqPrimitiveID, // gl_PrimitiveID
- EvqLayer, // gl_Layer
-
- // end of list
- EvqLast
-};
-
-inline bool IsQualifierUnspecified(TQualifier qualifier)
-{
- return (qualifier == EvqTemporary || qualifier == EvqGlobal);
-}
-
-enum TLayoutImageInternalFormat
-{
- EiifUnspecified,
- EiifRGBA32F,
- EiifRGBA16F,
- EiifR32F,
- EiifRGBA32UI,
- EiifRGBA16UI,
- EiifRGBA8UI,
- EiifR32UI,
- EiifRGBA32I,
- EiifRGBA16I,
- EiifRGBA8I,
- EiifR32I,
- EiifRGBA8,
- EiifRGBA8_SNORM
-};
-
-enum TLayoutMatrixPacking
-{
- EmpUnspecified,
- EmpRowMajor,
- EmpColumnMajor
-};
-
-enum TLayoutBlockStorage
-{
- EbsUnspecified,
- EbsShared,
- EbsPacked,
- EbsStd140,
- EbsStd430
-};
-
-enum TYuvCscStandardEXT
-{
- EycsUndefined,
- EycsItu601,
- EycsItu601FullRange,
- EycsItu709
-};
-
-enum TLayoutPrimitiveType
-{
- EptUndefined,
- EptPoints,
- EptLines,
- EptLinesAdjacency,
- EptTriangles,
- EptTrianglesAdjacency,
- EptLineStrip,
- EptTriangleStrip
-};
-
-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 &&
- matrixPacking == EmpUnspecified && blockStorage == EbsUnspecified &&
- !localSize.isAnyValueSet() && imageInternalFormat == EiifUnspecified &&
- primitiveType == EptUndefined && invocations == 0 && maxVertices == -1;
- }
-
- bool isCombinationValid() const
- {
- bool workSizeSpecified = localSize.isAnyValueSet();
- bool numViewsSet = (numViews != -1);
- bool geometryShaderSpecified =
- (primitiveType != EptUndefined) || (invocations != 0) || (maxVertices != -1);
- bool otherLayoutQualifiersSpecified =
- (location != -1 || binding != -1 || matrixPacking != EmpUnspecified ||
- blockStorage != EbsUnspecified || imageInternalFormat != EiifUnspecified);
-
- // we can have either the work group size specified, or number of views,
- // or yuv layout qualifier, or the other layout qualifiers.
- return (workSizeSpecified ? 1 : 0) + (numViewsSet ? 1 : 0) + (yuv ? 1 : 0) +
- (otherLayoutQualifiersSpecified ? 1 : 0) + (geometryShaderSpecified ? 1 : 0) <=
- 1;
- }
-
- bool isLocalSizeEqual(const sh::WorkGroupSize &localSizeIn) const
- {
- return localSize.isWorkGroupSizeMatching(localSizeIn);
- }
-
- int location;
- unsigned int locationsSpecified;
- TLayoutMatrixPacking matrixPacking;
- TLayoutBlockStorage blockStorage;
-
- // Compute shader layout qualifiers.
- sh::WorkGroupSize localSize;
-
- int binding;
- int offset;
-
- // Image format layout qualifier
- TLayoutImageInternalFormat imageInternalFormat;
-
- // OVR_multiview num_views.
- int numViews;
-
- // EXT_YUV_target yuv layout qualifier.
- bool yuv;
-
- // OES_geometry_shader layout qualifiers.
- TLayoutPrimitiveType primitiveType;
- int invocations;
- int maxVertices;
-
- private:
- explicit constexpr TLayoutQualifier(int /*placeholder*/)
- : location(-1),
- locationsSpecified(0),
- matrixPacking(EmpUnspecified),
- blockStorage(EbsUnspecified),
- localSize(-1),
- binding(-1),
- offset(-1),
- imageInternalFormat(EiifUnspecified),
- numViews(-1),
- yuv(false),
- primitiveType(EptUndefined),
- invocations(0),
- maxVertices(-1)
- {
- }
-};
-
-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";
- }
-}
-
-//
-// This is just for debug and error message print out, carried along with the definitions above.
-//
-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 EvqVertexIn: return "in";
- case EvqFragmentOut: return "out";
- case EvqVertexOut: return "out";
- case EvqFragmentIn: return "in";
- case EvqIn: return "in";
- case EvqOut: return "out";
- case EvqInOut: return "inout";
- case EvqConstReadOnly: return "const";
- case EvqInstanceID: return "InstanceID";
- case EvqVertexID: return "VertexID";
- case EvqPosition: return "Position";
- case EvqPointSize: return "PointSize";
- case EvqFragCoord: return "FragCoord";
- case EvqFrontFacing: return "FrontFacing";
- case EvqPointCoord: return "PointCoord";
- case EvqFragColor: return "FragColor";
- case EvqFragData: return "FragData";
- case EvqFragDepthEXT: return "FragDepth";
- case EvqFragDepth: return "FragDepth";
- case EvqSecondaryFragColorEXT: return "SecondaryFragColorEXT";
- case EvqSecondaryFragDataEXT: return "SecondaryFragDataEXT";
- case EvqViewIDOVR: return "ViewIDOVR";
- case EvqViewportIndex: return "ViewportIndex";
- case EvqLayer: return "Layer";
- case EvqLastFragColor: return "LastFragColor";
- case EvqLastFragData: return "LastFragData";
- case EvqSmoothOut: return "smooth out";
- case EvqCentroidOut: return "smooth centroid out";
- case EvqFlatOut: return "flat out";
- case EvqSmoothIn: return "smooth in";
- case EvqFlatIn: return "flat in";
- case EvqCentroidIn: return "smooth centroid in";
- case EvqCentroid: return "centroid";
- case EvqFlat: return "flat";
- 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";
- 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 std::string &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";
- }
-}
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_BASETYPES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp b/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
deleted file mode 100644
index d6a1e025de..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-//
-// Copyright (c) 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 "BreakVariableAliasingInInnerLoops.h"
-
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/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)
- {
- 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<B>(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)
- {
- if (visit == PreVisit)
- {
- mLoopLevel++;
- }
- else
- {
- ASSERT(mLoopLevel > 0);
- mLoopLevel--;
- }
-
- return true;
- }
-
- private:
- int mLoopLevel = 0;
-};
-
-} // anonymous namespace
-
-void BreakVariableAliasingInInnerLoops(TIntermNode *root)
-{
- AliasingBreaker breaker;
- root->traverse(&breaker);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h b/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h
deleted file mode 100644
index b1d906f919..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright (c) 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_BREAKVARIABLEALIASINGININNERLOOPS_H_
-#define COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
-
-class TIntermNode;
-
-namespace sh
-{
-
-void BreakVariableAliasingInInnerLoops(TIntermNode *root);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp
deleted file mode 100644
index 905e634fd1..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp
+++ /dev/null
@@ -1,355 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#include "compiler/translator/BuiltInFunctionEmulator.h"
-#include "angle_gl.h"
-#include "compiler/translator/Cache.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.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 (visit == PreVisit)
- {
- bool needToEmulate =
- mEmulator.setFunctionCalled(node->getOp(), node->getOperand()->getType());
- if (needToEmulate)
- node->setUseEmulatedFunction();
- }
- return true;
- }
-
- bool visitAggregate(Visit visit, TIntermAggregate *node) override
- {
- if (visit == PreVisit)
- {
- // Here we handle all the built-in functions mapped to ops, not just the ones that are
- // currently identified as problematic.
- if (node->isConstructor() || node->isFunctionCall())
- {
- return true;
- }
- const TIntermSequence &sequence = *(node->getSequence());
- bool needToEmulate = false;
- // Right now we only handle built-in functions with two to four parameters.
- if (sequence.size() == 2)
- {
- TIntermTyped *param1 = sequence[0]->getAsTyped();
- TIntermTyped *param2 = sequence[1]->getAsTyped();
- if (!param1 || !param2)
- return true;
- needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
- param2->getType());
- }
- else if (sequence.size() == 3)
- {
- TIntermTyped *param1 = sequence[0]->getAsTyped();
- TIntermTyped *param2 = sequence[1]->getAsTyped();
- TIntermTyped *param3 = sequence[2]->getAsTyped();
- if (!param1 || !param2 || !param3)
- return true;
- needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
- param2->getType(), param3->getType());
- }
- else if (sequence.size() == 4)
- {
- TIntermTyped *param1 = sequence[0]->getAsTyped();
- TIntermTyped *param2 = sequence[1]->getAsTyped();
- TIntermTyped *param3 = sequence[2]->getAsTyped();
- TIntermTyped *param4 = sequence[3]->getAsTyped();
- if (!param1 || !param2 || !param3 || !param4)
- return true;
- needToEmulate =
- mEmulator.setFunctionCalled(node->getOp(), param1->getType(), param2->getType(),
- param3->getType(), param4->getType());
- }
- else
- {
- return true;
- }
-
- if (needToEmulate)
- node->setUseEmulatedFunction();
- }
- return true;
- }
-
- private:
- BuiltInFunctionEmulator &mEmulator;
-};
-
-BuiltInFunctionEmulator::BuiltInFunctionEmulator()
-{
-}
-
-FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
- const TType *param,
- const char *emulatedFunctionDefinition)
-{
- FunctionId id(op, param);
- mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
- return id;
-}
-
-FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
- const TType *param1,
- const TType *param2,
- const char *emulatedFunctionDefinition)
-{
- FunctionId id(op, param1, param2);
- mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
- return id;
-}
-
-FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
- const FunctionId &dependency,
- TOperator op,
- const TType *param1,
- const TType *param2,
- const char *emulatedFunctionDefinition)
-{
- FunctionId id(op, param1, param2);
- mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
- mFunctionDependencies[id] = dependency;
- return id;
-}
-
-FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
- const TType *param1,
- const TType *param2,
- const TType *param3,
- const char *emulatedFunctionDefinition)
-{
- FunctionId id(op, param1, param2, param3);
- mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
- return id;
-}
-
-FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
- const TType *param1,
- const TType *param2,
- const TType *param3,
- const TType *param4,
- const char *emulatedFunctionDefinition)
-{
- FunctionId id(op, param1, param2, param3, param4);
- mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
- return id;
-}
-
-FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
- const FunctionId &dependency,
- TOperator op,
- const TType *param1,
- const TType *param2,
- const TType *param3,
- const TType *param4,
- const char *emulatedFunctionDefinition)
-{
- FunctionId id(op, param1, param2, param3, param4);
- mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
- mFunctionDependencies[id] = dependency;
- return id;
-}
-
-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";
- }
-}
-
-bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, const TType &param)
-{
- return setFunctionCalled(FunctionId(op, &param));
-}
-
-bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
- const TType &param1,
- const TType &param2)
-{
- return setFunctionCalled(FunctionId(op, &param1, &param2));
-}
-
-bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
- const TType &param1,
- const TType &param2,
- const TType &param3)
-{
- return setFunctionCalled(FunctionId(op, &param1, &param2, &param3));
-}
-
-bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
- const TType &param1,
- const TType &param2,
- const TType &param3,
- const TType &param4)
-{
- return setFunctionCalled(FunctionId(op, &param1, &param2, &param3, &param4));
-}
-
-const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &functionId) const
-{
- for (const auto &queryFunction : mQueryFunctions)
- {
- const char *result = queryFunction(functionId);
- if (result)
- {
- return result;
- }
- }
-
- const auto &result = mEmulatedFunctions.find(functionId);
- if (result != mEmulatedFunctions.end())
- {
- return result->second.c_str();
- }
-
- return nullptr;
-}
-
-bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId)
-{
- if (!findEmulatedFunction(functionId))
- {
- return false;
- }
-
- for (size_t i = 0; i < mFunctions.size(); ++i)
- {
- if (mFunctions[i] == functionId)
- return true;
- }
- // If the function depends on another, mark the dependency as called.
- auto dependency = mFunctionDependencies.find(functionId);
- if (dependency != mFunctionDependencies.end())
- {
- setFunctionCalled((*dependency).second);
- }
- // Copy the functionId if it needs to be stored, to make sure that the TType pointers inside
- // remain valid and constant.
- mFunctions.push_back(functionId.getCopy());
- 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";
-}
-
-FunctionId::FunctionId()
- : mOp(EOpNull),
- mParam1(TCache::getType(EbtVoid)),
- mParam2(TCache::getType(EbtVoid)),
- mParam3(TCache::getType(EbtVoid)),
- mParam4(TCache::getType(EbtVoid))
-{
-}
-
-FunctionId::FunctionId(TOperator op, const TType *param)
- : mOp(op),
- mParam1(param),
- mParam2(TCache::getType(EbtVoid)),
- mParam3(TCache::getType(EbtVoid)),
- mParam4(TCache::getType(EbtVoid))
-{
-}
-
-FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2)
- : mOp(op),
- mParam1(param1),
- mParam2(param2),
- mParam3(TCache::getType(EbtVoid)),
- mParam4(TCache::getType(EbtVoid))
-{
-}
-
-FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3)
- : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(TCache::getType(EbtVoid))
-{
-}
-
-FunctionId::FunctionId(TOperator op,
- const TType *param1,
- const TType *param2,
- const TType *param3,
- const TType *param4)
- : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(param4)
-{
-}
-
-bool FunctionId::operator==(const FunctionId &other) const
-{
- return (mOp == other.mOp && *mParam1 == *other.mParam1 && *mParam2 == *other.mParam2 &&
- *mParam3 == *other.mParam3 && *mParam4 == *other.mParam4);
-}
-
-bool FunctionId::operator<(const FunctionId &other) const
-{
- if (mOp != other.mOp)
- return mOp < other.mOp;
- if (*mParam1 != *other.mParam1)
- return *mParam1 < *other.mParam1;
- if (*mParam2 != *other.mParam2)
- return *mParam2 < *other.mParam2;
- if (*mParam3 != *other.mParam3)
- return *mParam3 < *other.mParam3;
- if (*mParam4 != *other.mParam4)
- return *mParam4 < *other.mParam4;
- return false; // all fields are equal
-}
-
-FunctionId FunctionId::getCopy() const
-{
- return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3),
- new TType(*mParam4));
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h
deleted file mode 100644
index 5f15f66224..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h
+++ /dev/null
@@ -1,183 +0,0 @@
-//
-// Copyright (c) 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"
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/ParamType.h"
-
-namespace sh
-{
-
-struct MiniFunctionId
-{
- constexpr MiniFunctionId(TOperator op = EOpNull,
- ParamType paramType1 = ParamType::Void,
- ParamType paramType2 = ParamType::Void,
- ParamType paramType3 = ParamType::Void,
- ParamType paramType4 = ParamType::Void)
- : op(op),
- paramType1(paramType1),
- paramType2(paramType2),
- paramType3(paramType3),
- paramType4(paramType4)
- {
- }
-
- TOperator op;
- ParamType paramType1;
- ParamType paramType2;
- ParamType paramType3;
- ParamType paramType4;
-};
-
-class FunctionId final
-{
- public:
- FunctionId();
- FunctionId(TOperator op, const TType *param);
- FunctionId(TOperator op, const TType *param1, const TType *param2);
- FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3);
- FunctionId(TOperator op,
- const TType *param1,
- const TType *param2,
- const TType *param3,
- const TType *param4);
-
- FunctionId(const FunctionId &) = default;
- FunctionId &operator=(const FunctionId &) = default;
-
- bool operator==(const FunctionId &other) const;
- bool operator<(const FunctionId &other) const;
-
- FunctionId getCopy() const;
-
- private:
- friend bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId);
- TOperator mOp;
-
- // The memory that these TType objects use is freed by PoolAllocator. The
- // BuiltInFunctionEmulator's lifetime can extend until after the memory pool is freed, but
- // that's not an issue since this class never destructs these objects.
- const TType *mParam1;
- const TType *mParam2;
- const TType *mParam3;
- const TType *mParam4;
-};
-
-inline bool operator==(ParamType paramType, const TType *type)
-{
- return SameParamType(paramType, type->getBasicType(), type->getNominalSize(),
- type->getSecondarySize());
-}
-
-inline bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId)
-{
- return miniId.op == functionId.mOp && miniId.paramType1 == functionId.mParam1 &&
- miniId.paramType2 == functionId.mParam2 && miniId.paramType3 == functionId.mParam3 &&
- miniId.paramType4 == functionId.mParam4;
-}
-
-using BuiltinQueryFunc = const char *(const FunctionId &);
-
-//
-// 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.
- FunctionId addEmulatedFunction(TOperator op,
- const TType *param,
- const char *emulatedFunctionDefinition);
- FunctionId addEmulatedFunction(TOperator op,
- const TType *param1,
- const TType *param2,
- const char *emulatedFunctionDefinition);
- FunctionId addEmulatedFunction(TOperator op,
- const TType *param1,
- const TType *param2,
- const TType *param3,
- const char *emulatedFunctionDefinition);
- FunctionId addEmulatedFunction(TOperator op,
- const TType *param1,
- const TType *param2,
- const TType *param3,
- const TType *param4,
- const char *emulatedFunctionDefinition);
-
- FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
- TOperator op,
- const TType *param1,
- const TType *param2,
- const char *emulatedFunctionDefinition);
- FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
- TOperator op,
- const TType *param1,
- const TType *param2,
- const TType *param3,
- const TType *param4,
- 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(TOperator op, const TType &param);
- bool setFunctionCalled(TOperator op, const TType &param1, const TType &param2);
- bool setFunctionCalled(TOperator op,
- const TType &param1,
- const TType &param2,
- const TType &param3);
- bool setFunctionCalled(TOperator op,
- const TType &param1,
- const TType &param2,
- const TType &param3,
- const TType &param4);
-
- bool setFunctionCalled(const FunctionId &functionId);
-
- const char *findEmulatedFunction(const FunctionId &functionId) const;
-
- // Map from function id to emulated function definition
- std::map<FunctionId, std::string> mEmulatedFunctions;
-
- // Map from dependent functions to their dependencies. This structure allows each function to
- // have at most one dependency.
- std::map<FunctionId, FunctionId> mFunctionDependencies;
-
- // Called function ids
- std::vector<FunctionId> mFunctions;
-
- // Constexpr function tables.
- std::vector<BuiltinQueryFunc *> mQueryFunctions;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
deleted file mode 100644
index 27ee04da35..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
+++ /dev/null
@@ -1,293 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#include "angle_gl.h"
-#include "compiler/translator/BuiltInFunctionEmulator.h"
-#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
-#include "compiler/translator/Cache.h"
-#include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/VersionGLSL.h"
-
-namespace sh
-{
-
-void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
- sh::GLenum shaderType)
-{
- if (shaderType == GL_VERTEX_SHADER)
- {
- const TType *int1 = TCache::getType(EbtInt);
- emu->addEmulatedFunction(EOpAbs, 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;
-
- const TType *float1 = TCache::getType(EbtFloat);
- const TType *float2 = TCache::getType(EbtFloat, 2);
- const TType *float3 = TCache::getType(EbtFloat, 3);
- const TType *float4 = TCache::getType(EbtFloat, 4);
-
- // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false.
- emu->addEmulatedFunction(
- EOpIsNan, float1,
- "bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }");
- emu->addEmulatedFunction(
- EOpIsNan, 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(
- EOpIsNan, 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(
- EOpIsNan, 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)
-{
- const TType *float1 = TCache::getType(EbtFloat);
- auto floatFuncId = emu->addEmulatedFunction(
- EOpAtan, 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");
- for (int dim = 2; dim <= 4; ++dim)
- {
- const TType *floatVec = TCache::getType(EbtFloat, static_cast<unsigned char>(dim));
- std::stringstream ss;
- 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(floatFuncId, EOpAtan, floatVec, floatVec,
- 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)
- {
- const TType *float2 = TCache::getType(EbtFloat, 2);
- const TType *uint1 = TCache::getType(EbtUInt);
-
- // clang-format off
- emu->addEmulatedFunction(EOpPackUnorm2x16, 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(EOpUnpackUnorm2x16, 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)
- {
- const TType *float2 = TCache::getType(EbtFloat, 2);
- const TType *uint1 = TCache::getType(EbtUInt);
-
- // clang-format off
- emu->addEmulatedFunction(EOpPackSnorm2x16, 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(EOpUnpackSnorm2x16, 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(EOpPackHalf2x16, 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(EOpUnpackHalf2x16, 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/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h
deleted file mode 100644
index e1b4779bd5..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Copyright (c) 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/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
deleted file mode 100644
index e78d86d00a..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-//
-// Copyright (c) 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 "angle_gl.h"
-#include "compiler/translator/BuiltInFunctionEmulator.h"
-#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
-#include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/VersionGLSL.h"
-
-namespace sh
-{
-
-// Defined in emulated_builtin_functions_hlsl_autogen.cpp.
-const char *FindHLSLFunction(const FunctionId &functionID);
-
-void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
- int targetGLSLVersion)
-{
- if (targetGLSLVersion < GLSL_VERSION_130)
- return;
-
- TType *float1 = new TType(EbtFloat);
- TType *float2 = new TType(EbtFloat, 2);
- TType *float3 = new TType(EbtFloat, 3);
- TType *float4 = new TType(EbtFloat, 4);
-
- emu->addEmulatedFunction(EOpIsNan, float1,
- "bool isnan_emu(float x)\n"
- "{\n"
- " return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n"
- "}\n"
- "\n");
-
- emu->addEmulatedFunction(
- EOpIsNan, 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(
- EOpIsNan, 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(
- EOpIsNan, 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)
-{
- TType *int1 = new TType(EbtInt);
- TType *int2 = new TType(EbtInt, 2);
- TType *int3 = new TType(EbtInt, 3);
- TType *int4 = new TType(EbtInt, 4);
- TType *uint1 = new TType(EbtUInt);
- TType *uint2 = new TType(EbtUInt, 2);
- TType *uint3 = new TType(EbtUInt, 3);
- TType *uint4 = new TType(EbtUInt, 4);
-
- 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
- FunctionId umulExtendedUint1 = emu->addEmulatedFunction(
- EOpUmulExtended, 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(
- umulExtendedUint1, EOpUmulExtended, 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(
- umulExtendedUint1, EOpUmulExtended, 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(
- umulExtendedUint1, EOpUmulExtended, 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.
- FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency(
- umulExtendedUint1, EOpImulExtended, 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(
- imulExtendedInt1, EOpImulExtended, 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(
- imulExtendedInt1, EOpImulExtended, 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(
- imulExtendedInt1, EOpImulExtended, 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/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h
deleted file mode 100644
index 48da73f58e..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// Copyright (c) 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/src/3rdparty/angle/src/compiler/translator/Cache.cpp b/src/3rdparty/angle/src/compiler/translator/Cache.cpp
deleted file mode 100644
index 417e82403a..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Cache.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-//
-// Copyright (c) 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.
-//
-
-// Cache.cpp: Implements a cache for various commonly created objects.
-
-#include <limits>
-
-#include "common/angleutils.h"
-#include "common/debug.h"
-#include "compiler/translator/Cache.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class TScopedAllocator : angle::NonCopyable
-{
- public:
- TScopedAllocator(TPoolAllocator *allocator) : mPreviousAllocator(GetGlobalPoolAllocator())
- {
- SetGlobalPoolAllocator(allocator);
- }
- ~TScopedAllocator() { SetGlobalPoolAllocator(mPreviousAllocator); }
-
- private:
- TPoolAllocator *mPreviousAllocator;
-};
-
-} // namespace
-
-TCache::TypeKey::TypeKey(TBasicType basicType,
- TPrecision precision,
- TQualifier qualifier,
- unsigned char primarySize,
- unsigned char secondarySize)
-{
- static_assert(sizeof(components) <= sizeof(value), "TypeKey::value is too small");
-
- const size_t MaxEnumValue = std::numeric_limits<EnumComponentType>::max();
-
- // TODO: change to static_assert() once we deprecate MSVC 2013 support
- ASSERT(MaxEnumValue >= EbtLast && MaxEnumValue >= EbpLast && MaxEnumValue >= EvqLast &&
- "TypeKey::EnumComponentType is too small");
-
- value = 0;
- components.basicType = static_cast<EnumComponentType>(basicType);
- components.precision = static_cast<EnumComponentType>(precision);
- components.qualifier = static_cast<EnumComponentType>(qualifier);
- components.primarySize = primarySize;
- components.secondarySize = secondarySize;
-}
-
-TCache *TCache::sCache = nullptr;
-
-TCache::TCache()
-{
-}
-
-void TCache::initialize()
-{
- if (sCache == nullptr)
- {
- sCache = new TCache();
- }
-}
-
-void TCache::destroy()
-{
- SafeDelete(sCache);
-}
-
-const TType *TCache::getType(TBasicType basicType,
- TPrecision precision,
- TQualifier qualifier,
- unsigned char primarySize,
- unsigned char secondarySize)
-{
- TypeKey key(basicType, precision, qualifier, primarySize, secondarySize);
- auto it = sCache->mTypes.find(key);
- if (it != sCache->mTypes.end())
- {
- return it->second;
- }
-
- TScopedAllocator scopedAllocator(&sCache->mAllocator);
-
- TType *type = new TType(basicType, precision, qualifier, primarySize, secondarySize);
- type->realize();
- sCache->mTypes.insert(std::make_pair(key, type));
-
- return type;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/Cache.h b/src/3rdparty/angle/src/compiler/translator/Cache.h
deleted file mode 100644
index a182b07f51..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Cache.h
+++ /dev/null
@@ -1,84 +0,0 @@
-//
-// Copyright (c) 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.
-//
-
-// Cache.h: Implements a cache for various commonly created objects.
-
-#ifndef COMPILER_TRANSLATOR_CACHE_H_
-#define COMPILER_TRANSLATOR_CACHE_H_
-
-#include <stdint.h>
-#include <string.h>
-#include <map>
-
-#include "compiler/translator/Types.h"
-#include "compiler/translator/PoolAlloc.h"
-
-namespace sh
-{
-
-class TCache
-{
- public:
- static void initialize();
- static void destroy();
-
- static const TType *getType(TBasicType basicType, TPrecision precision)
- {
- return getType(basicType, precision, EvqTemporary, 1, 1);
- }
- static const TType *getType(TBasicType basicType,
- unsigned char primarySize = 1,
- unsigned char secondarySize = 1)
- {
- return getType(basicType, EbpUndefined, EvqGlobal, primarySize, secondarySize);
- }
- static const TType *getType(TBasicType basicType,
- TQualifier qualifier,
- unsigned char primarySize = 1,
- unsigned char secondarySize = 1)
- {
- return getType(basicType, EbpUndefined, qualifier, primarySize, secondarySize);
- }
- static const TType *getType(TBasicType basicType,
- TPrecision precision,
- TQualifier qualifier,
- unsigned char primarySize,
- unsigned char secondarySize);
-
- private:
- TCache();
-
- union TypeKey {
- TypeKey(TBasicType basicType,
- TPrecision precision,
- TQualifier qualifier,
- unsigned char primarySize,
- unsigned char secondarySize);
-
- typedef uint8_t EnumComponentType;
- struct
- {
- EnumComponentType basicType;
- EnumComponentType precision;
- EnumComponentType qualifier;
- unsigned char primarySize;
- unsigned char secondarySize;
- } components;
- uint64_t value;
-
- bool operator<(const TypeKey &other) const { return value < other.value; }
- };
- typedef std::map<TypeKey, const TType *> TypeMap;
-
- TypeMap mTypes;
- TPoolAllocator mAllocator;
-
- static TCache *sCache;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_CACHE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/CallDAG.cpp b/src/3rdparty/angle/src/compiler/translator/CallDAG.cpp
deleted file mode 100644
index 5f54e80898..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/CallDAG.cpp
+++ /dev/null
@@ -1,346 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-// 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/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.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, true),
- mDiagnostics(diagnostics),
- mCurrentFunction(nullptr),
- mCurrentIndex(0)
- {
- }
-
- InitResult assignIndices()
- {
- int skipped = 0;
- for (auto &it : mFunctions)
- {
- // Skip unimplemented functions
- if (it.second.node)
- {
- 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<Record> *records, std::map<int, int> *idToIndex)
- {
- ASSERT(records->empty());
- ASSERT(idToIndex->empty());
-
- records->resize(mCurrentIndex);
-
- for (auto &it : mFunctions)
- {
- CreatorFunctionData &data = it.second;
- // Skip unimplemented functions
- if (!data.node)
- {
- continue;
- }
- ASSERT(data.index < records->size());
- Record &record = (*records)[data.index];
-
- record.name = data.name.data();
- record.node = data.node;
-
- record.callees.reserve(data.callees.size());
- for (auto &callee : data.callees)
- {
- record.callees.push_back(static_cast<int>(callee->index));
- }
-
- (*idToIndex)[data.node->getFunctionSymbolInfo()->getId().get()] =
- static_cast<int>(data.index);
- }
- }
-
- private:
- struct CreatorFunctionData
- {
- CreatorFunctionData() : node(nullptr), index(0), indexAssigned(false), visiting(false) {}
-
- std::set<CreatorFunctionData *> callees;
- TIntermFunctionDefinition *node;
- TString name;
- size_t index;
- bool indexAssigned;
- bool visiting;
- };
-
- bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override
- {
- // Create the record if need be and remember the node.
- if (visit == PreVisit)
- {
- auto it = mFunctions.find(node->getFunctionSymbolInfo()->getId().get());
-
- if (it == mFunctions.end())
- {
- mCurrentFunction = &mFunctions[node->getFunctionSymbolInfo()->getId().get()];
- mCurrentFunction->name = node->getFunctionSymbolInfo()->getName();
- }
- else
- {
- mCurrentFunction = &it->second;
- ASSERT(mCurrentFunction->name == node->getFunctionSymbolInfo()->getName());
- }
-
- mCurrentFunction->node = node;
- }
- else if (visit == PostVisit)
- {
- mCurrentFunction = nullptr;
- }
- return true;
- }
-
- bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override
- {
- ASSERT(visit == PreVisit);
- if (mCurrentFunction != nullptr)
- {
- return false;
- }
-
- // Function declaration, create an empty record.
- auto &record = mFunctions[node->getFunctionSymbolInfo()->getId().get()];
- record.name = node->getFunctionSymbolInfo()->getName();
-
- // No need to traverse the parameters.
- return false;
- }
-
- // Aggregates the AST node for each function as well as the name of the functions called by it
- bool visitAggregate(Visit visit, TIntermAggregate *node) override
- {
- if (visit == PreVisit && node->getOp() == EOpCallFunctionInAST)
- {
- // Function call, add the callees
- auto it = mFunctions.find(node->getFunctionSymbolInfo()->getId().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<CreatorFunctionData *> functionsToProcess;
- functionsToProcess.push_back(root);
-
- InitResult result = INITDAG_SUCCESS;
-
- std::stringstream errorStream;
-
- 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->node)
- {
- 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<int, CreatorFunctionData> mFunctions;
- CreatorFunctionData *mCurrentFunction;
- size_t mCurrentIndex;
-};
-
-// CallDAG
-
-CallDAG::CallDAG()
-{
-}
-
-CallDAG::~CallDAG()
-{
-}
-
-const size_t CallDAG::InvalidIndex = std::numeric_limits<size_t>::max();
-
-size_t CallDAG::findIndex(const TFunctionSymbolInfo *functionInfo) const
-{
- auto it = mFunctionIdToIndex.find(functionInfo->getId().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];
-}
-
-const CallDAG::Record &CallDAG::getRecord(const TIntermAggregate *function) const
-{
- size_t index = findIndex(function->getFunctionSymbolInfo());
- 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/src/3rdparty/angle/src/compiler/translator/CallDAG.h b/src/3rdparty/angle/src/compiler/translator/CallDAG.h
deleted file mode 100644
index 155081c9a2..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/CallDAG.h
+++ /dev/null
@@ -1,79 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-// 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 <map>
-
-#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 function.
-// Records are accessed by index but a function symbol id can be converted
-// to the index of the corresponding record. The records mostly contain the
-// AST node of the function 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
- {
- std::string name;
- TIntermFunctionDefinition *node;
- std::vector<int> 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 TFunctionSymbolInfo *functionInfo) const;
-
- const Record &getRecordFromIndex(size_t index) const;
- const Record &getRecord(const TIntermAggregate *function) const;
- size_t size() const;
- void clear();
-
- const static size_t InvalidIndex;
-
- private:
- std::vector<Record> mRecords;
- std::map<int, int> mFunctionIdToIndex;
-
- class CallDAGCreator;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_CALLDAG_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp b/src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp
deleted file mode 100644
index 8598a137f5..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-//
-// Copyright (c) 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/ClampPointSize.h"
-
-#include "compiler/translator/FindSymbolNode.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/RunAtTheEndOfShader.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbolTable)
-{
- // Only clamp gl_PointSize if it's used in the shader.
- if (!FindSymbolNode(root, TString("gl_PointSize"), EbtFloat))
- {
- return;
- }
-
- TIntermSymbol *pointSizeNode = ReferenceBuiltInVariable("gl_PointSize", *symbolTable, 100);
-
- TConstantUnion *maxPointSizeConstant = new TConstantUnion();
- maxPointSizeConstant->setFConst(maxPointSize);
- TIntermConstantUnion *maxPointSizeNode =
- new TIntermConstantUnion(maxPointSizeConstant, TType(EbtFloat, EbpHigh, EvqConst));
-
- // min(gl_PointSize, maxPointSize)
- TIntermSequence *minArguments = new TIntermSequence();
- 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);
-
- RunAtTheEndOfShader(root, assignPointSize, symbolTable);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ClampPointSize.h b/src/3rdparty/angle/src/compiler/translator/ClampPointSize.h
deleted file mode 100644
index 0c71ae6b0d..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ClampPointSize.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 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_CLAMPPOINTSIZE_H_
-#define COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
-
-namespace sh
-{
-
-class TIntermBlock;
-class TSymbolTable;
-
-void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbolTable);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp
deleted file mode 100644
index 3e25cc2339..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-//
-// Copyright (c) 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
-
-#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
-
- // 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/src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp b/src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp
deleted file mode 100644
index bd8cbc971a..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp
+++ /dev/null
@@ -1,869 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.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;
- }
-}
-
-// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
-BlockType GetBlockType(TQualifier qualifier)
-{
- switch (qualifier)
- {
- case EvqUniform:
- return BlockType::BLOCK_UNIFORM;
- case EvqBuffer:
- return BlockType::BLOCK_BUFFER;
- case EvqPerVertexIn:
- return BlockType::BLOCK_IN;
- default:
- UNREACHABLE();
- return BlockType::BLOCK_UNIFORM;
- }
-}
-
-template <class VarT>
-VarT *FindVariable(const TString &name, std::vector<VarT> *infoList)
-{
- // TODO(zmo): optimize this function.
- for (size_t ii = 0; ii < infoList->size(); ++ii)
- {
- if ((*infoList)[ii].name.c_str() == name)
- return &((*infoList)[ii]);
- }
-
- return nullptr;
-}
-
-// Note that this shouldn't be called for interface blocks - static use information is collected for
-// individual fields in case of interface blocks.
-void MarkStaticallyUsed(ShaderVariable *variable)
-{
- if (!variable->staticUse)
- {
- if (variable->isStruct())
- {
- // Conservatively assume all fields are statically used as well.
- for (auto &field : variable->fields)
- {
- MarkStaticallyUsed(&field);
- }
- }
- variable->staticUse = true;
- }
-}
-
-ShaderVariable *FindVariableInInterfaceBlock(const TString &name,
- const TInterfaceBlock *interfaceBlock,
- std::vector<InterfaceBlock> *infoList)
-{
- ASSERT(interfaceBlock);
- InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList);
- ASSERT(namedBlock);
-
- // Set static use on the parent interface block here
- namedBlock->staticUse = true;
- return FindVariable(name, &namedBlock->fields);
-}
-
-// Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs,
-// and interface blocks.
-class CollectVariablesTraverser : public TIntermTraverser
-{
- public:
- CollectVariablesTraverser(std::vector<Attribute> *attribs,
- std::vector<OutputVariable> *outputVariables,
- std::vector<Uniform> *uniforms,
- std::vector<Varying> *inputVaryings,
- std::vector<Varying> *outputVaryings,
- std::vector<InterfaceBlock> *uniformBlocks,
- std::vector<InterfaceBlock> *shaderStorageBlocks,
- std::vector<InterfaceBlock> *inBlocks,
- ShHashFunction64 hashFunction,
- TSymbolTable *symbolTable,
- int shaderVersion,
- GLenum shaderType,
- const TExtensionBehavior &extensionBehavior);
-
- void visitSymbol(TIntermSymbol *symbol) override;
- bool visitDeclaration(Visit, TIntermDeclaration *node) override;
- bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
-
- private:
- std::string getMappedName(const TName &name) const;
-
- void setCommonVariableProperties(const TType &type,
- const TName &name,
- ShaderVariable *variableOut) const;
-
- Attribute recordAttribute(const TIntermSymbol &variable) const;
- OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
- Varying recordVarying(const TIntermSymbol &variable) const;
- void recordInterfaceBlock(const TType &interfaceBlockType,
- InterfaceBlock *interfaceBlock) const;
- Uniform recordUniform(const TIntermSymbol &variable) const;
-
- void setBuiltInInfoFromSymbolTable(const char *name, ShaderVariable *info);
-
- void recordBuiltInVaryingUsed(const char *name,
- bool *addedFlag,
- std::vector<Varying> *varyings);
- void recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag);
- void recordBuiltInAttributeUsed(const char *name, bool *addedFlag);
- InterfaceBlock *recordGLInUsed(const TType &glInType);
- InterfaceBlock *findNamedInterfaceBlock(const TString &name) const;
-
- std::vector<Attribute> *mAttribs;
- std::vector<OutputVariable> *mOutputVariables;
- std::vector<Uniform> *mUniforms;
- std::vector<Varying> *mInputVaryings;
- std::vector<Varying> *mOutputVaryings;
- std::vector<InterfaceBlock> *mUniformBlocks;
- std::vector<InterfaceBlock> *mShaderStorageBlocks;
- std::vector<InterfaceBlock> *mInBlocks;
-
- std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
-
- // Shader uniforms
- bool mDepthRangeAdded;
-
- // Vertex Shader builtins
- bool mInstanceIDAdded;
- bool mVertexIDAdded;
- bool mPointSizeAdded;
-
- // Vertex Shader and Geometry Shader builtins
- bool mPositionAdded;
-
- // Fragment Shader builtins
- bool mPointCoordAdded;
- bool mFrontFacingAdded;
- bool mFragCoordAdded;
- bool mLastFragDataAdded;
- bool mFragColorAdded;
- bool mFragDataAdded;
- bool mFragDepthEXTAdded;
- bool mFragDepthAdded;
- bool mSecondaryFragColorEXTAdded;
- bool mSecondaryFragDataEXTAdded;
-
- // Geometry Shader builtins
- bool mPerVertexInAdded;
- bool mPrimitiveIDInAdded;
- bool mInvocationIDAdded;
-
- // Geometry Shader and Fragment Shader builtins
- bool mPrimitiveIDAdded;
- bool mLayerAdded;
-
- ShHashFunction64 mHashFunction;
-
- int mShaderVersion;
- GLenum mShaderType;
- const TExtensionBehavior &mExtensionBehavior;
-};
-
-CollectVariablesTraverser::CollectVariablesTraverser(
- std::vector<sh::Attribute> *attribs,
- std::vector<sh::OutputVariable> *outputVariables,
- std::vector<sh::Uniform> *uniforms,
- std::vector<sh::Varying> *inputVaryings,
- std::vector<sh::Varying> *outputVaryings,
- std::vector<sh::InterfaceBlock> *uniformBlocks,
- std::vector<sh::InterfaceBlock> *shaderStorageBlocks,
- std::vector<sh::InterfaceBlock> *inBlocks,
- ShHashFunction64 hashFunction,
- TSymbolTable *symbolTable,
- int shaderVersion,
- GLenum shaderType,
- const TExtensionBehavior &extensionBehavior)
- : TIntermTraverser(true, false, false, symbolTable),
- mAttribs(attribs),
- mOutputVariables(outputVariables),
- mUniforms(uniforms),
- mInputVaryings(inputVaryings),
- mOutputVaryings(outputVaryings),
- mUniformBlocks(uniformBlocks),
- mShaderStorageBlocks(shaderStorageBlocks),
- mInBlocks(inBlocks),
- mDepthRangeAdded(false),
- mInstanceIDAdded(false),
- mVertexIDAdded(false),
- mPointSizeAdded(false),
- mPositionAdded(false),
- mPointCoordAdded(false),
- mFrontFacingAdded(false),
- mFragCoordAdded(false),
- mLastFragDataAdded(false),
- mFragColorAdded(false),
- mFragDataAdded(false),
- mFragDepthEXTAdded(false),
- mFragDepthAdded(false),
- mSecondaryFragColorEXTAdded(false),
- mSecondaryFragDataEXTAdded(false),
- mPerVertexInAdded(false),
- mPrimitiveIDInAdded(false),
- mInvocationIDAdded(false),
- mPrimitiveIDAdded(false),
- mLayerAdded(false),
- mHashFunction(hashFunction),
- mShaderVersion(shaderVersion),
- mShaderType(shaderType),
- mExtensionBehavior(extensionBehavior)
-{
-}
-
-std::string CollectVariablesTraverser::getMappedName(const TName &name) const
-{
- return HashName(name, mHashFunction, nullptr).c_str();
-}
-
-void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const char *name,
- ShaderVariable *info)
-{
- TVariable *symbolTableVar =
- reinterpret_cast<TVariable *>(mSymbolTable->findBuiltIn(name, mShaderVersion));
- ASSERT(symbolTableVar);
- const TType &type = symbolTableVar->getType();
-
- info->name = name;
- info->mappedName = name;
- info->type = GLVariableType(type);
- info->precision = GLVariablePrecision(type);
- if (auto *arraySizes = type.getArraySizes())
- {
- info->arraySizes.assign(arraySizes->begin(), arraySizes->end());
- }
-}
-
-void CollectVariablesTraverser::recordBuiltInVaryingUsed(const char *name,
- bool *addedFlag,
- std::vector<Varying> *varyings)
-{
- ASSERT(varyings);
- if (!(*addedFlag))
- {
- Varying info;
- setBuiltInInfoFromSymbolTable(name, &info);
- info.staticUse = true;
- info.isInvariant = mSymbolTable->isVaryingInvariant(name);
- varyings->push_back(info);
- (*addedFlag) = true;
- }
-}
-
-void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag)
-{
- if (!(*addedFlag))
- {
- OutputVariable info;
- setBuiltInInfoFromSymbolTable(name, &info);
- info.staticUse = true;
- mOutputVariables->push_back(info);
- (*addedFlag) = true;
- }
-}
-
-void CollectVariablesTraverser::recordBuiltInAttributeUsed(const char *name, bool *addedFlag)
-{
- if (!(*addedFlag))
- {
- Attribute info;
- setBuiltInInfoFromSymbolTable(name, &info);
- info.staticUse = true;
- info.location = -1;
- mAttribs->push_back(info);
- (*addedFlag) = true;
- }
-}
-
-InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
-{
- if (!mPerVertexInAdded)
- {
- ASSERT(glInType.getQualifier() == EvqPerVertexIn);
- InterfaceBlock info;
- recordInterfaceBlock(glInType, &info);
- info.staticUse = true;
-
- mPerVertexInAdded = true;
- mInBlocks->push_back(info);
- return &mInBlocks->back();
- }
- else
- {
- return FindVariable("gl_PerVertex", mInBlocks);
- }
-}
-
-// We want to check whether a uniform/varying is statically used
-// because we only count the used ones in packing computing.
-// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
-// toward varying counting if they are statically used in a fragment
-// shader.
-void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
-{
- ASSERT(symbol != nullptr);
-
- if (symbol->getName().isInternal())
- {
- // Internal variables are not collected.
- return;
- }
-
- ShaderVariable *var = nullptr;
- const TString &symbolName = symbol->getName().getString();
-
- if (IsVaryingIn(symbol->getQualifier()))
- {
- var = FindVariable(symbolName, mInputVaryings);
- }
- else if (IsVaryingOut(symbol->getQualifier()))
- {
- var = FindVariable(symbolName, mOutputVaryings);
- }
- else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
- {
- UNREACHABLE();
- }
- else if (symbolName == "gl_DepthRange")
- {
- ASSERT(symbol->getQualifier() == EvqUniform);
-
- if (!mDepthRangeAdded)
- {
- Uniform info;
- const char kName[] = "gl_DepthRange";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_NONE;
- info.precision = GL_NONE;
- info.staticUse = true;
-
- ShaderVariable nearInfo(GL_FLOAT);
- const char kNearName[] = "near";
- nearInfo.name = kNearName;
- nearInfo.mappedName = kNearName;
- nearInfo.precision = GL_HIGH_FLOAT;
- nearInfo.staticUse = true;
-
- ShaderVariable farInfo(GL_FLOAT);
- const char kFarName[] = "far";
- farInfo.name = kFarName;
- farInfo.mappedName = kFarName;
- farInfo.precision = GL_HIGH_FLOAT;
- farInfo.staticUse = true;
-
- ShaderVariable diffInfo(GL_FLOAT);
- const char kDiffName[] = "diff";
- diffInfo.name = kDiffName;
- diffInfo.mappedName = kDiffName;
- diffInfo.precision = GL_HIGH_FLOAT;
- diffInfo.staticUse = true;
-
- info.fields.push_back(nearInfo);
- info.fields.push_back(farInfo);
- info.fields.push_back(diffInfo);
-
- mUniforms->push_back(info);
- mDepthRangeAdded = true;
- }
- }
- else
- {
- switch (symbol->getQualifier())
- {
- case EvqAttribute:
- case EvqVertexIn:
- var = FindVariable(symbolName, mAttribs);
- break;
- case EvqFragmentOut:
- var = FindVariable(symbolName, mOutputVariables);
- break;
- case EvqUniform:
- {
- const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
- if (interfaceBlock)
- {
- var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks);
- }
- else
- {
- var = FindVariable(symbolName, mUniforms);
- }
-
- // It's an internal error to reference an undefined user uniform
- ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
- }
- break;
- case EvqBuffer:
- {
- const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
- var =
- FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
- }
- break;
- case EvqFragCoord:
- recordBuiltInVaryingUsed("gl_FragCoord", &mFragCoordAdded, mInputVaryings);
- return;
- case EvqFrontFacing:
- recordBuiltInVaryingUsed("gl_FrontFacing", &mFrontFacingAdded, mInputVaryings);
- return;
- case EvqPointCoord:
- recordBuiltInVaryingUsed("gl_PointCoord", &mPointCoordAdded, mInputVaryings);
- return;
- case EvqInstanceID:
- // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set,
- // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
- // InstanceID. gl_InstanceID is not added to the symbol table for ESSL1 shaders
- // which makes it necessary to populate the type information explicitly instead of
- // extracting it from the symbol table.
- if (!mInstanceIDAdded)
- {
- Attribute info;
- const char kName[] = "gl_InstanceID";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_INT;
- info.precision = GL_HIGH_INT; // Defined by spec.
- info.staticUse = true;
- info.location = -1;
- mAttribs->push_back(info);
- mInstanceIDAdded = true;
- }
- return;
- case EvqVertexID:
- recordBuiltInAttributeUsed("gl_VertexID", &mVertexIDAdded);
- return;
- case EvqPosition:
- recordBuiltInVaryingUsed("gl_Position", &mPositionAdded, mOutputVaryings);
- return;
- case EvqPointSize:
- recordBuiltInVaryingUsed("gl_PointSize", &mPointSizeAdded, mOutputVaryings);
- return;
- case EvqLastFragData:
- recordBuiltInVaryingUsed("gl_LastFragData", &mLastFragDataAdded, mInputVaryings);
- return;
- case EvqFragColor:
- recordBuiltInFragmentOutputUsed("gl_FragColor", &mFragColorAdded);
- return;
- case EvqFragData:
- if (!mFragDataAdded)
- {
- OutputVariable info;
- setBuiltInInfoFromSymbolTable("gl_FragData", &info);
- if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
- {
- ASSERT(info.arraySizes.size() == 1u);
- info.arraySizes.back() = 1u;
- }
- info.staticUse = true;
- mOutputVariables->push_back(info);
- mFragDataAdded = true;
- }
- return;
- case EvqFragDepthEXT:
- recordBuiltInFragmentOutputUsed("gl_FragDepthEXT", &mFragDepthEXTAdded);
- return;
- case EvqFragDepth:
- recordBuiltInFragmentOutputUsed("gl_FragDepth", &mFragDepthAdded);
- return;
- case EvqSecondaryFragColorEXT:
- recordBuiltInFragmentOutputUsed("gl_SecondaryFragColorEXT",
- &mSecondaryFragColorEXTAdded);
- return;
- case EvqSecondaryFragDataEXT:
- recordBuiltInFragmentOutputUsed("gl_SecondaryFragDataEXT",
- &mSecondaryFragDataEXTAdded);
- return;
- case EvqInvocationID:
- recordBuiltInVaryingUsed("gl_InvocationID", &mInvocationIDAdded, mInputVaryings);
- break;
- case EvqPrimitiveIDIn:
- recordBuiltInVaryingUsed("gl_PrimitiveIDIn", &mPrimitiveIDInAdded, mInputVaryings);
- break;
- case EvqPrimitiveID:
- if (mShaderType == GL_GEOMETRY_SHADER_OES)
- {
- recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mOutputVaryings);
- }
- else
- {
- ASSERT(mShaderType == GL_FRAGMENT_SHADER);
- recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mInputVaryings);
- }
- break;
- case EvqLayer:
- if (mShaderType == GL_GEOMETRY_SHADER_OES)
- {
- recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mOutputVaryings);
- }
- else if (mShaderType == GL_FRAGMENT_SHADER)
- {
- recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mInputVaryings);
- }
- else
- {
- ASSERT(mShaderType == GL_VERTEX_SHADER &&
- IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview));
- }
- break;
- default:
- break;
- }
- }
- if (var)
- {
- MarkStaticallyUsed(var);
- }
-}
-
-void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
- const TName &name,
- ShaderVariable *variableOut) const
-{
- ASSERT(variableOut);
-
- const TStructure *structure = type.getStruct();
-
- if (!structure)
- {
- variableOut->type = GLVariableType(type);
- variableOut->precision = GLVariablePrecision(type);
- }
- else
- {
- // Structures use a NONE type that isn't exposed outside ANGLE.
- variableOut->type = GL_NONE;
- variableOut->structName = structure->name().c_str();
-
- const TFieldList &fields = structure->fields();
-
- for (TField *field : fields)
- {
- // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
- // ShaderVariable objects.
- ShaderVariable fieldVariable;
- setCommonVariableProperties(*field->type(), TName(field->name()), &fieldVariable);
- variableOut->fields.push_back(fieldVariable);
- }
- }
- variableOut->name = name.getString().c_str();
- variableOut->mappedName = getMappedName(name);
-
- if (auto *arraySizes = type.getArraySizes())
- {
- variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end());
- }
-}
-
-Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
-{
- const TType &type = variable.getType();
- ASSERT(!type.getStruct());
-
- Attribute attribute;
- setCommonVariableProperties(type, variable.getName(), &attribute);
-
- attribute.location = type.getLayoutQualifier().location;
- return attribute;
-}
-
-OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const
-{
- const TType &type = variable.getType();
- ASSERT(!type.getStruct());
-
- OutputVariable outputVariable;
- setCommonVariableProperties(type, variable.getName(), &outputVariable);
-
- outputVariable.location = type.getLayoutQualifier().location;
- return outputVariable;
-}
-
-Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const
-{
- const TType &type = variable.getType();
-
- Varying varying;
- setCommonVariableProperties(type, variable.getName(), &varying);
- varying.location = type.getLayoutQualifier().location;
-
- switch (type.getQualifier())
- {
- case EvqVaryingIn:
- case EvqVaryingOut:
- case EvqVertexOut:
- case EvqSmoothOut:
- case EvqFlatOut:
- case EvqCentroidOut:
- case EvqGeometryOut:
- if (mSymbolTable->isVaryingInvariant(std::string(variable.getSymbol().c_str())) ||
- type.isInvariant())
- {
- varying.isInvariant = true;
- }
- break;
- default:
- break;
- }
-
- varying.interpolation = GetInterpolationType(type.getQualifier());
- return varying;
-}
-
-// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
-void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlockType,
- InterfaceBlock *interfaceBlock) const
-{
- ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock);
- ASSERT(interfaceBlock);
-
- const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
- ASSERT(blockType);
-
- interfaceBlock->name = blockType->name().c_str();
- interfaceBlock->mappedName = getMappedName(TName(blockType->name()));
- interfaceBlock->instanceName =
- (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
- 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)
- {
- interfaceBlock->isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
- interfaceBlock->binding = blockType->blockBinding();
- interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage());
- }
-
- // Gather field information
- for (const TField *field : blockType->fields())
- {
- const TType &fieldType = *field->type();
-
- InterfaceBlockField fieldVariable;
- setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable);
- fieldVariable.isRowMajorLayout =
- (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
- interfaceBlock->fields.push_back(fieldVariable);
- }
-}
-
-Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
-{
- Uniform uniform;
- setCommonVariableProperties(variable.getType(), variable.getName(), &uniform);
- uniform.binding = variable.getType().getLayoutQualifier().binding;
- uniform.location = variable.getType().getLayoutQualifier().location;
- uniform.offset = variable.getType().getLayoutQualifier().offset;
- 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 == 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.getName().isInternal())
- {
- // Internal variables are not collected.
- continue;
- }
-
- // TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
- if (typedNode.getBasicType() == EbtInterfaceBlock)
- {
- InterfaceBlock interfaceBlock;
- recordInterfaceBlock(variable.getType(), &interfaceBlock);
-
- switch (qualifier)
- {
- case EvqUniform:
- mUniformBlocks->push_back(interfaceBlock);
- break;
- case EvqBuffer:
- mShaderStorageBlocks->push_back(interfaceBlock);
- break;
- default:
- UNREACHABLE();
- }
- }
- else
- {
- switch (qualifier)
- {
- case EvqAttribute:
- case EvqVertexIn:
- mAttribs->push_back(recordAttribute(variable));
- break;
- case EvqFragmentOut:
- 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;
-}
-
-// TODO(jiawei.shao@intel.com): add search on mInBlocks and mOutBlocks when implementing
-// GL_OES_shader_io_blocks.
-InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock(const TString &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 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)
- {
- TIntermTyped *interfaceNode = interfaceIndexingNode->getLeft()->getAsTyped();
- ASSERT(interfaceNode);
-
- const TType &interfaceType = interfaceNode->getType();
- if (interfaceType.getQualifier() == EvqPerVertexIn)
- {
- namedBlock = recordGLInUsed(interfaceType);
- ASSERT(namedBlock);
-
- // We need to continue traversing to collect useful variables in the index
- // expression of gl_in.
- traverseIndexExpression = true;
- }
- }
-
- const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
- if (!namedBlock)
- {
- namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
- }
- ASSERT(namedBlock);
- namedBlock->staticUse = true;
- unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
- ASSERT(fieldIndex < namedBlock->fields.size());
- namedBlock->fields[fieldIndex].staticUse = true;
-
- if (traverseIndexExpression)
- {
- ASSERT(interfaceIndexingNode);
- interfaceIndexingNode->getRight()->traverse(this);
- }
- return false;
- }
-
- return true;
-}
-
-} // anonymous namespace
-
-void CollectVariables(TIntermBlock *root,
- std::vector<Attribute> *attributes,
- std::vector<OutputVariable> *outputVariables,
- std::vector<Uniform> *uniforms,
- std::vector<Varying> *inputVaryings,
- std::vector<Varying> *outputVaryings,
- std::vector<InterfaceBlock> *uniformBlocks,
- std::vector<InterfaceBlock> *shaderStorageBlocks,
- std::vector<InterfaceBlock> *inBlocks,
- ShHashFunction64 hashFunction,
- TSymbolTable *symbolTable,
- int shaderVersion,
- GLenum shaderType,
- const TExtensionBehavior &extensionBehavior)
-{
- CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
- outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
- hashFunction, symbolTable, shaderVersion, shaderType,
- extensionBehavior);
- root->traverse(&collect);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/CollectVariables.h b/src/3rdparty/angle/src/compiler/translator/CollectVariables.h
deleted file mode 100644
index 4d0d1192e0..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/CollectVariables.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// CollectVariables.h: Collect lists of shader interface variables based on the AST.
-
-#ifndef COMPILER_TRANSLATOR_COLLECTVARIABLES_H_
-#define COMPILER_TRANSLATOR_COLLECTVARIABLES_H_
-
-#include <GLSLANG/ShaderLang.h>
-
-#include "compiler/translator/ExtensionBehavior.h"
-
-namespace sh
-{
-
-class TIntermBlock;
-class TSymbolTable;
-
-void CollectVariables(TIntermBlock *root,
- std::vector<Attribute> *attributes,
- std::vector<OutputVariable> *outputVariables,
- std::vector<Uniform> *uniforms,
- std::vector<Varying> *inputVaryings,
- std::vector<Varying> *outputVaryings,
- std::vector<InterfaceBlock> *uniformBlocks,
- std::vector<InterfaceBlock> *shaderStorageBlocks,
- std::vector<InterfaceBlock> *inBlocks,
- ShHashFunction64 hashFunction,
- TSymbolTable *symbolTable,
- int shaderVersion,
- GLenum shaderType,
- const TExtensionBehavior &extensionBehavior);
-}
-
-#endif // COMPILER_TRANSLATOR_COLLECTVARIABLES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Common.h b/src/3rdparty/angle/src/compiler/translator/Common.h
deleted file mode 100644
index cb3a680d85..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Common.h
+++ /dev/null
@@ -1,138 +0,0 @@
-//
-// Copyright (c) 2002-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_COMMON_H_
-#define COMPILER_TRANSLATOR_COMMON_H_
-
-#include <map>
-#include <sstream>
-#include <string>
-#include <unordered_map>
-#include <vector>
-#include <limits>
-#include <stdio.h>
-
-#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;
-};
-
-//
-// 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<char> TStringAllocator;
-typedef std::basic_string<char, std::char_traits<char>, TStringAllocator> TString;
-typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
-inline TString *NewPoolTString(const char *s)
-{
- void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TString));
- return new (memory) TString(s);
-}
-
-//
-// Persistent string memory. Should only be used for strings that survive
-// across compiles.
-//
-#define TPersistString std::string
-#define TPersistStringStream std::ostringstream
-
-//
-// Pool allocator versions of vectors, lists, and maps
-//
-template <class T>
-class TVector : public std::vector<T, pool_allocator<T>>
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
-
- typedef typename std::vector<T, pool_allocator<T>>::size_type size_type;
- TVector() : std::vector<T, pool_allocator<T>>() {}
- TVector(const pool_allocator<T> &a) : std::vector<T, pool_allocator<T>>(a) {}
- TVector(size_type i) : std::vector<T, pool_allocator<T>>(i) {}
-};
-
-template <class K, class D, class H = std::hash<K>, class CMP = std::equal_to<K>>
-class TUnorderedMap : public std::unordered_map<K, D, H, CMP, pool_allocator<std::pair<const K, D>>>
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- typedef pool_allocator<std::pair<const K, D>> tAllocator;
-
- TUnorderedMap() : std::unordered_map<K, D, H, CMP, tAllocator>() {}
- // use correct two-stage name lookup supported in gcc 3.4 and above
- TUnorderedMap(const tAllocator &a)
- : std::unordered_map<K, D, H, CMP, tAllocator>(
- std::unordered_map<K, D, H, CMP, tAllocator>::key_compare(),
- a)
- {
- }
-};
-
-template <class K, class D, class CMP = std::less<K>>
-class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D>>>
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- typedef pool_allocator<std::pair<const K, D>> tAllocator;
-
- TMap() : std::map<K, D, CMP, tAllocator>() {}
- // use correct two-stage name lookup supported in gcc 3.4 and above
- TMap(const tAllocator &a)
- : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a)
- {
- }
-};
-
-// Integer to TString conversion
-template <typename T>
-inline TString str(T i)
-{
- ASSERT(std::numeric_limits<T>::is_integer);
- char buffer[((8 * sizeof(T)) / 3) + 3];
- const char *formatStr = std::numeric_limits<T>::is_signed ? "%d" : "%u";
- snprintf(buffer, sizeof(buffer), formatStr, i);
- return buffer;
-}
-
-} // namespace sh
-
-namespace std
-{
-template <>
-struct hash<sh::TString>
-{
- size_t operator()(const sh::TString &s) const
- {
- return angle::PMurHash32(0, s.data(), static_cast<int>(s.length()));
- }
-};
-} // namespace std
-
-#endif // COMPILER_TRANSLATOR_COMMON_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp
deleted file mode 100644
index 2f411cb58c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp
+++ /dev/null
@@ -1,1169 +0,0 @@
-//
-// Copyright (c) 2002-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/Compiler.h"
-
-#include <sstream>
-
-#include "angle_gl.h"
-#include "common/utilities.h"
-#include "compiler/translator/AddAndTrueToLoopCondition.h"
-#include "compiler/translator/Cache.h"
-#include "compiler/translator/CallDAG.h"
-#include "compiler/translator/ClampPointSize.h"
-#include "compiler/translator/CollectVariables.h"
-#include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h"
-#include "compiler/translator/DeferGlobalInitializers.h"
-#include "compiler/translator/EmulateGLFragColorBroadcast.h"
-#include "compiler/translator/EmulatePrecision.h"
-#include "compiler/translator/Initialize.h"
-#include "compiler/translator/InitializeVariables.h"
-#include "compiler/translator/IntermNodePatternMatcher.h"
-#include "compiler/translator/IsASTDepthBelowLimit.h"
-#include "compiler/translator/OutputTree.h"
-#include "compiler/translator/ParseContext.h"
-#include "compiler/translator/PruneNoOps.h"
-#include "compiler/translator/RegenerateStructNames.h"
-#include "compiler/translator/RemoveArrayLengthMethod.h"
-#include "compiler/translator/RemoveEmptySwitchStatements.h"
-#include "compiler/translator/RemoveInvariantDeclaration.h"
-#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h"
-#include "compiler/translator/RemovePow.h"
-#include "compiler/translator/RemoveUnreferencedVariables.h"
-#include "compiler/translator/RewriteDoWhile.h"
-#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
-#include "compiler/translator/SeparateDeclarations.h"
-#include "compiler/translator/SimplifyLoopConditions.h"
-#include "compiler/translator/SplitSequenceOperator.h"
-#include "compiler/translator/UnfoldShortCircuitAST.h"
-#include "compiler/translator/UseInterfaceBlockFields.h"
-#include "compiler/translator/ValidateLimitations.h"
-#include "compiler/translator/ValidateMaxParameters.h"
-#include "compiler/translator/ValidateOutputs.h"
-#include "compiler/translator/ValidateVaryingLocations.h"
-#include "compiler/translator/VariablePacker.h"
-#include "compiler/translator/VectorizeVectorScalarArithmetic.h"
-#include "compiler/translator/util.h"
-#include "third_party/compiler/ArrayBoundsClamper.h"
-
-namespace sh
-{
-
-namespace
-{
-
-#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
-void DumpFuzzerCase(char const *const *shaderStrings,
- size_t numStrings,
- uint32_t type,
- uint32_t spec,
- uint32_t output,
- uint64_t options)
-{
- static int fileIndex = 0;
-
- std::ostringstream o;
- o << "corpus/" << fileIndex++ << ".sample";
- std::string s = o.str();
-
- // Must match the input format of the fuzzer
- FILE *f = fopen(s.c_str(), "w");
- fwrite(&type, sizeof(type), 1, f);
- fwrite(&spec, sizeof(spec), 1, f);
- fwrite(&output, sizeof(output), 1, f);
- fwrite(&options, sizeof(options), 1, f);
-
- char zero[128 - 20] = {0};
- fwrite(&zero, 128 - 20, 1, f);
-
- for (size_t i = 0; i < numStrings; i++)
- {
- fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f);
- }
- fwrite(&zero, 1, 1, f);
-
- fclose(f);
-}
-#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
-} // anonymous namespace
-
-bool IsWebGLBasedSpec(ShShaderSpec spec)
-{
- return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC);
-}
-
-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,
- ShCompileOptions compileOptions)
-{
- if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 &&
- shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
- return true;
-
- if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
- 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_OES:
- return resources.MaxGeometryUniformComponents / 4;
- default:
- UNREACHABLE();
- return -1;
- }
-}
-
-namespace
-{
-
-class TScopedPoolAllocator
-{
- public:
- TScopedPoolAllocator(TPoolAllocator *allocator) : mAllocator(allocator)
- {
- mAllocator->push();
- SetGlobalPoolAllocator(mAllocator);
- }
- ~TScopedPoolAllocator()
- {
- SetGlobalPoolAllocator(nullptr);
- mAllocator->pop();
- }
-
- private:
- TPoolAllocator *mAllocator;
-};
-
-class TScopedSymbolTableLevel
-{
- public:
- TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
- {
- ASSERT(mTable->atBuiltInLevel());
- mTable->push();
- }
- ~TScopedSymbolTableLevel()
- {
- while (!mTable->atBuiltInLevel())
- mTable->pop();
- }
-
- private:
- TSymbolTable *mTable;
-};
-
-int MapSpecToShaderVersion(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;
- default:
- UNREACHABLE();
- return 0;
- }
-}
-
-} // namespace
-
-TShHandleBase::TShHandleBase()
-{
- allocator.push();
- SetGlobalPoolAllocator(&allocator);
-}
-
-TShHandleBase::~TShHandleBase()
-{
- SetGlobalPoolAllocator(nullptr);
- allocator.popAll();
-}
-
-TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
- : variablesCollected(false),
- mGLPositionInitialized(false),
- shaderType(type),
- shaderSpec(spec),
- outputType(output),
- maxUniformVectors(0),
- maxExpressionComplexity(0),
- maxCallStackDepth(0),
- maxFunctionParameters(0),
- fragmentPrecisionHigh(false),
- clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
- builtInFunctionEmulator(),
- mDiagnostics(infoSink.info),
- mSourcePath(nullptr),
- mComputeShaderLocalSizeDeclared(false),
- mComputeShaderLocalSize(1),
- mGeometryShaderMaxVertices(-1),
- mGeometryShaderInvocations(0),
- mGeometryShaderInputPrimitiveType(EptUndefined),
- mGeometryShaderOutputPrimitiveType(EptUndefined)
-{
-}
-
-TCompiler::~TCompiler()
-{
-}
-
-bool TCompiler::shouldRunLoopAndIndexingValidation(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(shaderSpec) && shaderVersion == 100) ||
- (compileOptions & SH_VALIDATE_LOOP_INDEXING);
-}
-
-bool TCompiler::Init(const ShBuiltInResources &resources)
-{
- shaderVersion = 100;
-
- maxUniformVectors = GetMaxUniformVectorsForShaderType(shaderType, resources);
-
- maxExpressionComplexity = resources.MaxExpressionComplexity;
- maxCallStackDepth = resources.MaxCallStackDepth;
- maxFunctionParameters = resources.MaxFunctionParameters;
-
- SetGlobalPoolAllocator(&allocator);
-
- // Generate built-in symbol table.
- if (!InitBuiltInSymbolTable(resources))
- return false;
- InitExtensionBehavior(resources, extensionBehavior);
- fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
-
- arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
- clampingStrategy = resources.ArrayIndexClampingStrategy;
-
- hashFunction = resources.HashFunction;
-
- return true;
-}
-
-TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
- size_t numStrings,
- ShCompileOptions compileOptions)
-{
- return compileTreeImpl(shaderStrings, numStrings, compileOptions);
-}
-
-TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
- size_t numStrings,
- const ShCompileOptions compileOptions)
-{
- clearResults();
-
- ASSERT(numStrings > 0);
- ASSERT(GetGlobalPoolAllocator());
-
- // Reset the extension behavior for each compilation unit.
- ResetExtensionBehavior(extensionBehavior);
-
- // First string is path of source file if flag is set. The actual source follows.
- size_t firstSource = 0;
- if (compileOptions & SH_SOURCE_PATH)
- {
- mSourcePath = shaderStrings[0];
- ++firstSource;
- }
-
- TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec,
- compileOptions, true, &mDiagnostics, getResources());
-
- parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
-
- // We preserve symbols at the built-in level from compile-to-compile.
- // Start pushing the user-defined symbols at global level.
- TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
-
- // Parse shader.
- if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,
- &parseContext) != 0)
- {
- return nullptr;
- }
-
- if (parseContext.getTreeRoot() == nullptr)
- {
- return nullptr;
- }
-
- setASTMetadata(parseContext);
-
- if (MapSpecToShaderVersion(shaderSpec) < shaderVersion)
- {
- mDiagnostics.globalError("unsupported shader version");
- return nullptr;
- }
-
- TIntermBlock *root = parseContext.getTreeRoot();
- if (!checkAndSimplifyAST(root, parseContext, compileOptions))
- {
- return nullptr;
- }
-
- return root;
-}
-
-void TCompiler::setASTMetadata(const TParseContext &parseContext)
-{
- shaderVersion = parseContext.getShaderVersion();
-
- mPragma = parseContext.pragma();
- symbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
-
- mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
- mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize();
-
- mNumViews = parseContext.getNumViews();
-
- // Highp might have been auto-enabled based on shader version
- fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh();
-
- if (shaderType == GL_GEOMETRY_SHADER_OES)
- {
- mGeometryShaderInputPrimitiveType = parseContext.getGeometryShaderInputPrimitiveType();
- mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType();
- mGeometryShaderMaxVertices = parseContext.getGeometryShaderMaxVertices();
- mGeometryShaderInvocations = parseContext.getGeometryShaderInvocations();
- }
-}
-
-bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
- const TParseContext &parseContext,
- ShCompileOptions compileOptions)
-{
- // Disallow expressions deemed too complex.
- if ((compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY) && !limitExpressionComplexity(root))
- {
- 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.
- // After this empty declarations are not allowed in the AST.
- PruneNoOps(root);
-
- // 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 may have left switch
- // statements that only contained an empty declaration inside the final case in an invalid
- // state. Relies on that PruneNoOps has already been run.
- RemoveNoOpCasesFromEndOfSwitchStatements(root, &symbolTable);
-
- // Remove empty switch statements - this makes output simpler.
- RemoveEmptySwitchStatements(root);
-
- // Create the function DAG and check there is no recursion
- if (!initCallDag(root))
- {
- return false;
- }
-
- if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) && !checkCallDepth())
- {
- return false;
- }
-
- // Checks which functions are used and if "main" exists
- functionMetadata.clear();
- functionMetadata.resize(mCallDag.size());
- if (!tagUsedFunctions())
- {
- return false;
- }
-
- if (!(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS))
- {
- pruneUnusedFunctions(root);
- }
-
- if (shaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, shaderType))
- {
- return false;
- }
-
- if (shaderVersion >= 300 && shaderType == GL_FRAGMENT_SHADER &&
- !ValidateOutputs(root, getExtensionBehavior(), compileResources.MaxDrawBuffers,
- &mDiagnostics))
- {
- return false;
- }
-
- if (shouldRunLoopAndIndexingValidation(compileOptions) &&
- !ValidateLimitations(root, shaderType, &symbolTable, shaderVersion, &mDiagnostics))
- {
- return false;
- }
-
- // Fail compilation if precision emulation not supported.
- if (getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision &&
- !EmulatePrecision::SupportedInLanguage(outputType))
- {
- mDiagnostics.globalError("Precision emulation not supported for this output type.");
- return false;
- }
-
- // Clamping uniform array bounds needs to happen after validateLimitations pass.
- if (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)
- {
- arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
- }
-
- if ((compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) &&
- parseContext.isExtensionEnabled(TExtension::OVR_multiview) &&
- getShaderType() != GL_COMPUTE_SHADER)
- {
- DeclareAndInitBuiltinsForInstancedMultiview(root, mNumViews, shaderType, compileOptions,
- outputType, &symbolTable);
- }
-
- // This pass might emit short circuits so keep it before the short circuit unfolding
- if (compileOptions & SH_REWRITE_DO_WHILE_LOOPS)
- RewriteDoWhile(root, &symbolTable);
-
- if (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION)
- sh::AddAndTrueToLoopCondition(root);
-
- if (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)
- {
- UnfoldShortCircuitAST unfoldShortCircuit;
- root->traverse(&unfoldShortCircuit);
- unfoldShortCircuit.updateTree();
- }
-
- if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
- {
- RemovePow(root);
- }
-
- if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
- {
- RegenerateStructNames gen(&symbolTable, shaderVersion);
- root->traverse(&gen);
- }
-
- if (shaderType == GL_FRAGMENT_SHADER && shaderVersion == 100 &&
- compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 &&
- IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers))
- {
- EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables,
- &symbolTable, shaderVersion);
- }
-
- // 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.
- SimplifyLoopConditions(
- root,
- IntermNodePatternMatcher::kMultiDeclaration | IntermNodePatternMatcher::kArrayLengthMethod,
- &getSymbolTable(), getShaderVersion());
-
- // Note that separate declarations need to be run before other AST transformations that
- // generate new statements from expressions.
- SeparateDeclarations(root);
-
- SplitSequenceOperator(root, IntermNodePatternMatcher::kArrayLengthMethod, &getSymbolTable(),
- getShaderVersion());
-
- RemoveArrayLengthMethod(root);
-
- RemoveUnreferencedVariables(root, &symbolTable);
-
- // Built-in function emulation needs to happen after validateLimitations pass.
- // TODO(jmadill): Remove global pool allocator.
- GetGlobalPoolAllocator()->lock();
- initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
- GetGlobalPoolAllocator()->unlock();
- builtInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
-
- if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
- {
- ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh, &symbolTable);
- }
-
- if (shouldCollectVariables(compileOptions))
- {
- ASSERT(!variablesCollected);
- CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings,
- &outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks,
- hashFunction, &symbolTable, shaderVersion, shaderType, extensionBehavior);
- collectInterfaceBlocks();
- variablesCollected = true;
- if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
- {
- useAllMembersInUnusedStandardAndSharedBlocks(root);
- }
- if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
- {
- // 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, uniforms))
- {
- mDiagnostics.globalError("too many uniforms");
- return false;
- }
- }
- if (compileOptions & SH_INIT_OUTPUT_VARIABLES)
- {
- initializeOutputVariables(root);
- }
- }
-
- // Removing invariant declarations must be done after collecting variables.
- // Otherwise, built-in invariant declarations don't apply.
- if (RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions))
- {
- RemoveInvariantDeclaration(root);
- }
-
- // 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 (shaderType == GL_VERTEX_SHADER && !mGLPositionInitialized &&
- ((compileOptions & SH_INIT_GL_POSITION) || (outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
- {
- initializeGLPosition(root);
- mGLPositionInitialized = true;
- }
-
- // 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.
- bool initializeLocalsAndGlobals =
- (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType());
- bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES);
- DeferGlobalInitializers(root, initializeLocalsAndGlobals, canUseLoopsToInitialize, &symbolTable);
-
- 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))
- {
- SimplifyLoopConditions(root,
- IntermNodePatternMatcher::kArrayDeclaration |
- IntermNodePatternMatcher::kNamelessStructDeclaration,
- &getSymbolTable(), getShaderVersion());
- }
-
- InitializeUninitializedLocals(root, getShaderVersion(), canUseLoopsToInitialize,
- &getSymbolTable());
- }
-
- if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE))
- {
- ClampPointSize(root, compileResources.MaxPointSize, &getSymbolTable());
- }
-
- if (compileOptions & SH_REWRITE_VECTOR_SCALAR_ARITHMETIC)
- {
- VectorizeVectorScalarArithmetic(root, &getSymbolTable());
- }
-
- return true;
-}
-
-bool TCompiler::compile(const char *const shaderStrings[],
- size_t numStrings,
- ShCompileOptions compileOptionsIn)
-{
-#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
- DumpFuzzerCase(shaderStrings, numStrings, shaderType, shaderSpec, outputType, compileOptionsIn);
-#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
-
- 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 |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
- }
-
- TScopedPoolAllocator scopedAlloc(&allocator);
- TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
-
- if (root)
- {
- if (compileOptions & SH_INTERMEDIATE_TREE)
- OutputTree(root, infoSink.info);
-
- if (compileOptions & SH_OBJECT_CODE)
- {
- PerformanceDiagnostics perfDiagnostics(&mDiagnostics);
- translate(root, compileOptions, &perfDiagnostics);
- }
-
- // 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;
- }
-
- compileResources = resources;
- setResourceString();
-
- ASSERT(symbolTable.isEmpty());
- symbolTable.push(); // COMMON_BUILTINS
- symbolTable.push(); // ESSL1_BUILTINS
- symbolTable.push(); // ESSL3_BUILTINS
- symbolTable.push(); // ESSL3_1_BUILTINS
- symbolTable.push(); // GLSL_BUILTINS
-
- switch (shaderType)
- {
- case GL_FRAGMENT_SHADER:
- symbolTable.setDefaultPrecision(EbtInt, EbpMedium);
- break;
- case GL_VERTEX_SHADER:
- case GL_COMPUTE_SHADER:
- case GL_GEOMETRY_SHADER_OES:
- symbolTable.setDefaultPrecision(EbtInt, EbpHigh);
- symbolTable.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);
-
- symbolTable.setDefaultPrecision(EbtAtomicCounter, EbpHigh);
-
- InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
-
- IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
-
- return true;
-}
-
-void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType)
-{
- ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd);
- symbolTable.setDefaultPrecision(samplerType, EbpLow);
-}
-
-void TCompiler::setResourceString()
-{
- std::ostringstream strstream;
-
- // clang-format off
- strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs
- << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
- << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
- << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits
- << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits
- << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits
- << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors
- << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
- << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
- << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
- << ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3
- << ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external
- << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
- << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
- << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
- << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
- << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
- << ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters
- << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended
- << ":EXT_frag_depth:" << compileResources.EXT_frag_depth
- << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
- << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
- << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
- << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
- << ":OVR_multiview:" << compileResources.OVR_multiview
- << ":EXT_YUV_target:" << compileResources.EXT_YUV_target
- << ":OES_geometry_shader:" << compileResources.OES_geometry_shader
- << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
- << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
- << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
- << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
- << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
- << ":MaxViewsOVR:" << compileResources.MaxViewsOVR
- << ":NV_draw_buffers:" << compileResources.NV_draw_buffers
- << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision
- << ":MinProgramTextureGatherOffset:" << compileResources.MinProgramTextureGatherOffset
- << ":MaxProgramTextureGatherOffset:" << compileResources.MaxProgramTextureGatherOffset
- << ":MaxImageUnits:" << compileResources.MaxImageUnits
- << ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms
- << ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms
- << ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms
- << ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms
- << ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources
- << ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0]
- << ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1]
- << ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2]
- << ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0]
- << ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1]
- << ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2]
- << ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents
- << ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits
- << ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters
- << ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers
- << ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters
- << ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters
- << ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters
- << ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings
- << ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers
- << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers
- << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers
- << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize
- << ":MaxGeometryUniformComponents:" << compileResources.MaxGeometryUniformComponents
- << ":MaxGeometryUniformBlocks:" << compileResources.MaxGeometryUniformBlocks
- << ":MaxGeometryInputComponents:" << compileResources.MaxGeometryInputComponents
- << ":MaxGeometryOutputComponents:" << compileResources.MaxGeometryOutputComponents
- << ":MaxGeometryOutputVertices:" << compileResources.MaxGeometryOutputVertices
- << ":MaxGeometryTotalOutputComponents:" << compileResources.MaxGeometryTotalOutputComponents
- << ":MaxGeometryTextureImageUnits:" << compileResources.MaxGeometryTextureImageUnits
- << ":MaxGeometryAtomicCounterBuffers:" << compileResources.MaxGeometryAtomicCounterBuffers
- << ":MaxGeometryAtomicCounters:" << compileResources.MaxGeometryAtomicCounters
- << ":MaxGeometryShaderStorageBlocks:" << compileResources.MaxGeometryShaderStorageBlocks
- << ":MaxGeometryShaderInvocations:" << compileResources.MaxGeometryShaderInvocations
- << ":MaxGeometryImageUniforms:" << compileResources.MaxGeometryImageUniforms;
- // clang-format on
-
- builtInResourcesString = strstream.str();
-}
-
-void TCompiler::collectInterfaceBlocks()
-{
- ASSERT(interfaceBlocks.empty());
- interfaceBlocks.reserve(uniformBlocks.size() + shaderStorageBlocks.size() + inBlocks.size());
- interfaceBlocks.insert(interfaceBlocks.end(), uniformBlocks.begin(), uniformBlocks.end());
- interfaceBlocks.insert(interfaceBlocks.end(), shaderStorageBlocks.begin(),
- shaderStorageBlocks.end());
- interfaceBlocks.insert(interfaceBlocks.end(), inBlocks.begin(), inBlocks.end());
-}
-
-void TCompiler::clearResults()
-{
- arrayBoundsClamper.Cleanup();
- infoSink.info.erase();
- infoSink.obj.erase();
- infoSink.debug.erase();
- mDiagnostics.resetErrorCount();
-
- attributes.clear();
- outputVariables.clear();
- uniforms.clear();
- inputVaryings.clear();
- outputVaryings.clear();
- interfaceBlocks.clear();
- uniformBlocks.clear();
- shaderStorageBlocks.clear();
- inBlocks.clear();
- variablesCollected = false;
- mGLPositionInitialized = false;
-
- mNumViews = -1;
-
- mGeometryShaderInputPrimitiveType = EptUndefined;
- mGeometryShaderOutputPrimitiveType = EptUndefined;
- mGeometryShaderInvocations = 0;
- mGeometryShaderMaxVertices = -1;
-
- builtInFunctionEmulator.cleanup();
-
- nameMap.clear();
-
- mSourcePath = nullptr;
-}
-
-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<int> depths(mCallDag.size());
-
- for (size_t i = 0; i < mCallDag.size(); i++)
- {
- int depth = 0;
- auto &record = mCallDag.getRecordFromIndex(i);
-
- for (auto &calleeIndex : record.callees)
- {
- depth = std::max(depth, depths[calleeIndex] + 1);
- }
-
- depths[i] = depth;
-
- if (depth >= maxCallStackDepth)
- {
- // Trace back the function chain to have a meaningful info log.
- std::stringstream errorStream;
- errorStream << "Call stack too deep (larger than " << maxCallStackDepth
- << ") with the following call chain: " << record.name;
-
- int currentFunction = static_cast<int>(i);
- int currentDepth = depth;
-
- while (currentFunction != -1)
- {
- errorStream << " -> " << mCallDag.getRecordFromIndex(currentFunction).name;
-
- int nextFunction = -1;
- for (auto &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).name == "main")
- {
- internalTagUsedFunction(i);
- return true;
- }
- }
-
- mDiagnostics.globalError("Missing main()");
- return false;
-}
-
-void TCompiler::internalTagUsedFunction(size_t index)
-{
- if (functionMetadata[index].used)
- {
- return;
- }
-
- functionMetadata[index].used = true;
-
- for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)
- {
- internalTagUsedFunction(calleeIndex);
- }
-}
-
-// A predicate for the stl that returns if a top-level node is unused
-class TCompiler::UnusedPredicate
-{
- public:
- UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)
- : mCallDag(callDag), mMetadatas(metadatas)
- {
- }
-
- bool operator()(TIntermNode *node)
- {
- const TIntermFunctionPrototype *asFunctionPrototype = node->getAsFunctionPrototypeNode();
- const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();
-
- const TFunctionSymbolInfo *functionInfo = nullptr;
-
- if (asFunctionDefinition)
- {
- functionInfo = asFunctionDefinition->getFunctionSymbolInfo();
- }
- else if (asFunctionPrototype)
- {
- functionInfo = asFunctionPrototype->getFunctionSymbolInfo();
- }
- if (functionInfo == nullptr)
- {
- return false;
- }
-
- size_t callDagIndex = mCallDag->findIndex(functionInfo);
- if (callDagIndex == CallDAG::InvalidIndex)
- {
- // This happens only for unimplemented prototypes which are thus unused
- ASSERT(asFunctionPrototype);
- return true;
- }
-
- ASSERT(callDagIndex < mMetadatas->size());
- return !(*mMetadatas)[callDagIndex].used;
- }
-
- private:
- const CallDAG *mCallDag;
- const std::vector<FunctionMetadata> *mMetadatas;
-};
-
-void TCompiler::pruneUnusedFunctions(TIntermBlock *root)
-{
- UnusedPredicate isUnused(&mCallDag, &functionMetadata);
- TIntermSequence *sequence = root->getSequence();
-
- if (!sequence->empty())
- {
- sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused),
- sequence->end());
- }
-}
-
-bool TCompiler::limitExpressionComplexity(TIntermBlock *root)
-{
- if (!IsASTDepthBelowLimit(root, maxExpressionComplexity))
- {
- mDiagnostics.globalError("Expression too complex.");
- return false;
- }
-
- if (!ValidateMaxParameters(root, maxFunctionParameters))
- {
- mDiagnostics.globalError("Function has too many parameters.");
- return false;
- }
-
- return true;
-}
-
-bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)
-{
- return (compileOptions & SH_VARIABLES) != 0;
-}
-
-bool TCompiler::wereVariablesCollected() const
-{
- return variablesCollected;
-}
-
-void TCompiler::initializeGLPosition(TIntermBlock *root)
-{
- InitVariableList list;
- sh::ShaderVariable var(GL_FLOAT_VEC4);
- var.name = "gl_Position";
- list.push_back(var);
- InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false);
-}
-
-void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
-{
- sh::InterfaceBlockList list;
-
- for (auto block : uniformBlocks)
- {
- if (!block.staticUse &&
- (block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED))
- {
- list.push_back(block);
- }
- }
-
- sh::UseInterfaceBlockFields(root, list, symbolTable);
-}
-
-void TCompiler::initializeOutputVariables(TIntermBlock *root)
-{
- InitVariableList list;
- if (shaderType == GL_VERTEX_SHADER || shaderType == GL_GEOMETRY_SHADER_OES)
- {
- for (auto var : outputVaryings)
- {
- list.push_back(var);
- if (var.name == "gl_Position")
- {
- ASSERT(!mGLPositionInitialized);
- mGLPositionInitialized = true;
- }
- }
- }
- else
- {
- ASSERT(shaderType == GL_FRAGMENT_SHADER);
- for (auto var : outputVariables)
- {
- list.push_back(var);
- }
- }
- InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false);
-}
-
-const TExtensionBehavior &TCompiler::getExtensionBehavior() const
-{
- return extensionBehavior;
-}
-
-const char *TCompiler::getSourcePath() const
-{
- return mSourcePath;
-}
-
-const ShBuiltInResources &TCompiler::getResources() const
-{
- return compileResources;
-}
-
-const ArrayBoundsClamper &TCompiler::getArrayBoundsClamper() const
-{
- return arrayBoundsClamper;
-}
-
-ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
-{
- return clampingStrategy;
-}
-
-const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const
-{
- return builtInFunctionEmulator;
-}
-
-void TCompiler::writePragma(ShCompileOptions compileOptions)
-{
- if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL))
- {
- TInfoSinkBase &sink = infoSink.obj;
- if (mPragma.stdgl.invariantAll)
- sink << "#pragma STDGL invariant(all)\n";
- }
-}
-
-bool TCompiler::isVaryingDefined(const char *varyingName)
-{
- ASSERT(variablesCollected);
- for (size_t ii = 0; ii < inputVaryings.size(); ++ii)
- {
- if (inputVaryings[ii].name == varyingName)
- {
- return true;
- }
- }
- for (size_t ii = 0; ii < outputVaryings.size(); ++ii)
- {
- if (outputVaryings[ii].name == varyingName)
- {
- return true;
- }
- }
-
- return false;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.h b/src/3rdparty/angle/src/compiler/translator/Compiler.h
deleted file mode 100644
index 753cfb8e7b..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Compiler.h
+++ /dev/null
@@ -1,308 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#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 <GLSLANG/ShaderVars.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 "third_party/compiler/ArrayBoundsClamper.h"
-
-namespace sh
-{
-
-class TCompiler;
-class TParseContext;
-#ifdef ANGLE_ENABLE_HLSL
-class TranslatorHLSL;
-#endif // ANGLE_ENABLE_HLSL
-
-//
-// Helper function to identify specs that are based on the WebGL spec.
-//
-bool IsWebGLBasedSpec(ShShaderSpec spec);
-
-//
-// 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,
- 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
-
- protected:
- // Memory allocator. Allocates and tracks memory required by the compiler.
- // Deallocates all memory when compiler is destructed.
- TPoolAllocator allocator;
-};
-
-//
-// 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,
- ShCompileOptions compileOptions);
-
- bool compile(const char *const shaderStrings[],
- size_t numStrings,
- ShCompileOptions compileOptions);
-
- // Get results of the last compilation.
- int getShaderVersion() const { return shaderVersion; }
- TInfoSink &getInfoSink() { return infoSink; }
-
- 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<sh::Attribute> &getAttributes() const { return attributes; }
- const std::vector<sh::OutputVariable> &getOutputVariables() const { return outputVariables; }
- const std::vector<sh::Uniform> &getUniforms() const { return uniforms; }
- const std::vector<sh::Varying> &getInputVaryings() const { return inputVaryings; }
- const std::vector<sh::Varying> &getOutputVaryings() const { return outputVaryings; }
- const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return interfaceBlocks; }
- const std::vector<sh::InterfaceBlock> &getUniformBlocks() const { return uniformBlocks; }
- const std::vector<sh::InterfaceBlock> &getShaderStorageBlocks() const
- {
- return shaderStorageBlocks;
- }
- const std::vector<sh::InterfaceBlock> &getInBlocks() const { return inBlocks; }
-
- ShHashFunction64 getHashFunction() const { return hashFunction; }
- NameMap &getNameMap() { return nameMap; }
- TSymbolTable &getSymbolTable() { return symbolTable; }
- ShShaderSpec getShaderSpec() const { return shaderSpec; }
- ShShaderOutput getOutputType() const { return outputType; }
- const std::string &getBuiltInResourcesString() const { return builtInResourcesString; }
-
- bool shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const;
-
- // Get the resources set by InitBuiltInSymbolTable
- const ShBuiltInResources &getResources() const;
-
- int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; }
- int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; }
- TLayoutPrimitiveType getGeometryShaderInputPrimitiveType() const
- {
- return mGeometryShaderInputPrimitiveType;
- }
- TLayoutPrimitiveType getGeometryShaderOutputPrimitiveType() const
- {
- return mGeometryShaderOutputPrimitiveType;
- }
-
- sh::GLenum getShaderType() const { return shaderType; }
-
- protected:
- // 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();
- // Add emulated functions to the built-in function emulator.
- virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
- ShCompileOptions compileOptions){};
- // Translate to object code. May generate performance warnings through the diagnostics.
- virtual void translate(TIntermBlock *root,
- ShCompileOptions compileOptions,
- PerformanceDiagnostics *perfDiagnostics) = 0;
- // 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.
- void useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root);
- // Insert statements to initialize output variables in the beginning of main().
- // This is to avoid undefined behaviors.
- void 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.
- void initializeGLPosition(TIntermBlock *root);
- // Return true if the maximum expression complexity is below the limit.
- bool limitExpressionComplexity(TIntermBlock *root);
- // Get built-in extensions with default behavior.
- const TExtensionBehavior &getExtensionBehavior() const;
- const char *getSourcePath() const;
- const TPragma &getPragma() const { return mPragma; }
- void writePragma(ShCompileOptions compileOptions);
- // Relies on collectVariables having been called.
- bool isVaryingDefined(const char *varyingName);
-
- const ArrayBoundsClamper &getArrayBoundsClamper() const;
- ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
- const BuiltInFunctionEmulator &getBuiltInFunctionEmulator() const;
-
- virtual bool shouldFlattenPragmaStdglInvariantAll() = 0;
- virtual bool shouldCollectVariables(ShCompileOptions compileOptions);
-
- bool wereVariablesCollected() const;
- std::vector<sh::Attribute> attributes;
- std::vector<sh::OutputVariable> outputVariables;
- std::vector<sh::Uniform> uniforms;
- std::vector<sh::Varying> inputVaryings;
- std::vector<sh::Varying> outputVaryings;
- std::vector<sh::InterfaceBlock> interfaceBlocks;
- std::vector<sh::InterfaceBlock> uniformBlocks;
- std::vector<sh::InterfaceBlock> shaderStorageBlocks;
- std::vector<sh::InterfaceBlock> inBlocks;
-
- private:
- // 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 initSamplerDefaultPrecision(TBasicType samplerType);
-
- void collectInterfaceBlocks();
-
- bool variablesCollected;
-
- bool mGLPositionInitialized;
-
- // Removes unused function declarations and prototypes from the AST
- class UnusedPredicate;
- void 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);
-
- // Does checks that need to be run after parsing is complete and returns true if they pass.
- bool checkAndSimplifyAST(TIntermBlock *root,
- const TParseContext &parseContext,
- ShCompileOptions compileOptions);
-
- sh::GLenum shaderType;
- ShShaderSpec shaderSpec;
- ShShaderOutput outputType;
-
- struct FunctionMetadata
- {
- FunctionMetadata() : used(false) {}
- bool used;
- };
-
- CallDAG mCallDag;
- std::vector<FunctionMetadata> functionMetadata;
-
- int maxUniformVectors;
- int maxExpressionComplexity;
- int maxCallStackDepth;
- int maxFunctionParameters;
-
- ShBuiltInResources compileResources;
- std::string builtInResourcesString;
-
- // Built-in symbol table for the given language, spec, and resources.
- // It is preserved from compile-to-compile.
- TSymbolTable symbolTable;
- // Built-in extensions with default behavior.
- TExtensionBehavior extensionBehavior;
- bool fragmentPrecisionHigh;
-
- ArrayBoundsClamper arrayBoundsClamper;
- ShArrayIndexClampingStrategy clampingStrategy;
- BuiltInFunctionEmulator builtInFunctionEmulator;
-
- // Results of compilation.
- int shaderVersion;
- TInfoSink infoSink; // Output sink.
- TDiagnostics mDiagnostics;
- const char *mSourcePath; // Path of source file or NULL
-
- // 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;
-
- // name hashing.
- ShHashFunction64 hashFunction;
- NameMap nameMap;
-
- TPragma mPragma;
-};
-
-//
-// 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 *);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_COMPILER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp
deleted file mode 100644
index 7004aedee3..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp
+++ /dev/null
@@ -1,681 +0,0 @@
-//
-// 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"
-
-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;
-}
-
-int TConstantUnion::getIConst() const
-{
- ASSERT(type == EbtInt);
- return iConst;
-}
-
-unsigned int TConstantUnion::getUConst() const
-{
- ASSERT(type == EbtUInt);
- return uConst;
-}
-
-float TConstantUnion::getFConst() const
-{
- ASSERT(type == EbtFloat);
- return fConst;
-}
-
-bool TConstantUnion::getBConst() const
-{
- ASSERT(type == EbtBool);
- return bConst;
-}
-
-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<float>(constant.getIConst()));
- break;
- case EbtUInt:
- setFConst(static_cast<float>(constant.getUConst()));
- break;
- case EbtBool:
- setFConst(static_cast<float>(constant.getBConst()));
- break;
- case EbtFloat:
- setFConst(static_cast<float>(constant.getFConst()));
- break;
- default:
- return false;
- }
- break;
- case EbtInt:
- switch (constant.type)
- {
- case EbtInt:
- setIConst(static_cast<int>(constant.getIConst()));
- break;
- case EbtUInt:
- setIConst(static_cast<int>(constant.getUConst()));
- break;
- case EbtBool:
- setIConst(static_cast<int>(constant.getBConst()));
- break;
- case EbtFloat:
- setIConst(static_cast<int>(constant.getFConst()));
- break;
- default:
- return false;
- }
- break;
- case EbtUInt:
- switch (constant.type)
- {
- case EbtInt:
- setUConst(static_cast<unsigned int>(constant.getIConst()));
- break;
- case EbtUInt:
- setUConst(static_cast<unsigned int>(constant.getUConst()));
- break;
- case EbtBool:
- setUConst(static_cast<unsigned int>(constant.getBConst()));
- break;
- case EbtFloat:
- setUConst(static_cast<unsigned int>(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;
- default:
- return false;
- }
-
- return true;
-}
-
-bool TConstantUnion::operator==(const int i) const
-{
- return i == iConst;
-}
-
-bool TConstantUnion::operator==(const unsigned int u) const
-{
- return u == uConst;
-}
-
-bool TConstantUnion::operator==(const float f) const
-{
- 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
-{
- if (constant.type != type)
- return false;
-
- 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;
- }
-}
-
-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
-{
- ASSERT(type == constant.type);
- 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
- }
-}
-
-bool TConstantUnion::operator<(const TConstantUnion &constant) const
-{
- ASSERT(type == constant.type);
- 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
- }
-}
-
-// static
-TConstantUnion TConstantUnion::add(const TConstantUnion &lhs,
- const TConstantUnion &rhs,
- TDiagnostics *diag,
- const TSourceLoc &line)
-{
- TConstantUnion returnValue;
- ASSERT(lhs.type == rhs.type);
- switch (lhs.type)
- {
- case EbtInt:
- returnValue.setIConst(gl::WrappingSum<int>(lhs.iConst, rhs.iConst));
- break;
- case EbtUInt:
- returnValue.setUConst(gl::WrappingSum<unsigned int>(lhs.uConst, rhs.uConst));
- break;
- case EbtFloat:
- returnValue.setFConst(CheckedSum(lhs.fConst, rhs.fConst, diag, line));
- break;
- default:
- UNREACHABLE();
- }
-
- return returnValue;
-}
-
-// static
-TConstantUnion TConstantUnion::sub(const TConstantUnion &lhs,
- const TConstantUnion &rhs,
- TDiagnostics *diag,
- const TSourceLoc &line)
-{
- TConstantUnion returnValue;
- ASSERT(lhs.type == rhs.type);
- switch (lhs.type)
- {
- case EbtInt:
- returnValue.setIConst(gl::WrappingDiff<int>(lhs.iConst, rhs.iConst));
- break;
- case EbtUInt:
- returnValue.setUConst(gl::WrappingDiff<unsigned int>(lhs.uConst, rhs.uConst));
- break;
- case EbtFloat:
- returnValue.setFConst(CheckedDiff(lhs.fConst, rhs.fConst, diag, line));
- break;
- default:
- UNREACHABLE();
- }
-
- return returnValue;
-}
-
-// static
-TConstantUnion TConstantUnion::mul(const TConstantUnion &lhs,
- const TConstantUnion &rhs,
- TDiagnostics *diag,
- const TSourceLoc &line)
-{
- TConstantUnion returnValue;
- ASSERT(lhs.type == rhs.type);
- 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();
- }
-
- 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<unsigned int>(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<int>::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<int>(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<int>(static_cast<uint32_t>(lhs.iConst) << rhs.iConst));
- break;
- case EbtUInt:
- returnValue.setIConst(
- static_cast<int>(static_cast<uint32_t>(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/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h
deleted file mode 100644
index c1b3db9070..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h
+++ /dev/null
@@ -1,117 +0,0 @@
-//
-// Copyright (c) 2002-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_CONSTANTUNION_H_
-#define COMPILER_TRANSLATOR_CONSTANTUNION_H_
-
-#include <assert.h>
-
-#include "compiler/translator/Common.h"
-#include "compiler/translator/BaseTypes.h"
-
-namespace sh
-{
-
-class TDiagnostics;
-
-class TConstantUnion
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- TConstantUnion();
-
- 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;
- 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/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp b/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp
deleted file mode 100644
index ce9828f1f9..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp
+++ /dev/null
@@ -1,221 +0,0 @@
-//
-// Copyright (c) 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/DeclareAndInitBuiltinsForInstancedMultiview.h"
-
-#include "compiler/translator/FindMain.h"
-#include "compiler/translator/InitializeVariables.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/util.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class ReplaceVariableTraverser : public TIntermTraverser
-{
- public:
- ReplaceVariableTraverser(const TString &symbolName, TIntermSymbol *newSymbol)
- : TIntermTraverser(true, false, false), mSymbolName(symbolName), mNewSymbol(newSymbol)
- {
- }
-
- void visitSymbol(TIntermSymbol *node) override
- {
- TName &name = node->getName();
- if (name.getString() == mSymbolName)
- {
- queueReplacement(mNewSymbol->deepCopy(), OriginalNode::IS_DROPPED);
- }
- }
-
- private:
- TString mSymbolName;
- TIntermSymbol *mNewSymbol;
-};
-
-TIntermSymbol *CreateGLInstanceIDSymbol(const TSymbolTable &symbolTable)
-{
- return ReferenceBuiltInVariable("gl_InstanceID", symbolTable, 300);
-}
-
-// Adds the InstanceID and ViewID_OVR initializers to the end of the initializers' sequence.
-void InitializeViewIDAndInstanceID(TIntermTyped *viewIDSymbol,
- TIntermTyped *instanceIDSymbol,
- 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, EbpHigh, EvqConst));
-
- // Create a uint(gl_InstanceID) node.
- TIntermSequence *glInstanceIDSymbolCastArguments = new TIntermSequence();
- glInstanceIDSymbolCastArguments->push_back(CreateGLInstanceIDSymbol(symbolTable));
- 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 = new TIntermSequence();
- 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, instanceIDSymbol->deepCopy(), 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, viewIDSymbol->deepCopy(), normalizedViewID);
- initializers->push_back(viewIDInitializer);
-}
-
-// Replaces every occurrence of a symbol with the name specified in symbolName with newSymbolNode.
-void ReplaceSymbol(TIntermBlock *root, const TString &symbolName, TIntermSymbol *newSymbolNode)
-{
- ReplaceVariableTraverser traverser(symbolName, newSymbolNode);
- root->traverse(&traverser);
- traverser.updateTree();
-}
-
-void DeclareGlobalVariable(TIntermBlock *root, TIntermTyped *typedNode)
-{
- TIntermSequence *globalSequence = root->getSequence();
- TIntermDeclaration *declaration = new TIntermDeclaration();
- declaration->appendDeclarator(typedNode->deepCopy());
- globalSequence->insert(globalSequence->begin(), declaration);
-}
-
-// 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(TIntermTyped *viewIDSymbol,
- TIntermTyped *multiviewBaseViewLayerIndexSymbol,
- TIntermSequence *initializers,
- const TSymbolTable &symbolTable)
-{
- // Create an int(ViewID_OVR) node.
- TIntermSequence *viewIDSymbolCastArguments = new TIntermSequence();
- viewIDSymbolCastArguments->push_back(viewIDSymbol);
- TIntermAggregate *viewIDAsInt = TIntermAggregate::CreateConstructor(
- TType(EbtInt, EbpHigh, EvqTemporary), viewIDSymbolCastArguments);
-
- // Create a gl_ViewportIndex node.
- TIntermSymbol *viewportIndexSymbol =
- ReferenceBuiltInVariable("gl_ViewportIndex", symbolTable, 0);
-
- // 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 = ReferenceBuiltInVariable("gl_Layer", symbolTable, 0);
-
- // Create an int(ViewID_OVR) + multiviewBaseViewLayerIndex node
- TIntermBinary *sumOfViewIDAndBaseViewIndex =
- new TIntermBinary(EOpAdd, viewIDAsInt->deepCopy(), multiviewBaseViewLayerIndexSymbol);
-
- // 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, multiviewBaseViewLayerIndexSymbol->deepCopy(),
- 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
-
-void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
- unsigned numberOfViews,
- GLenum shaderType,
- ShCompileOptions compileOptions,
- ShShaderOutput shaderOutput,
- TSymbolTable *symbolTable)
-{
- ASSERT(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER);
-
- TQualifier viewIDQualifier = (shaderType == GL_VERTEX_SHADER) ? EvqFlatOut : EvqFlatIn;
- TIntermSymbol *viewIDSymbol = new TIntermSymbol(symbolTable->nextUniqueId(), "ViewID_OVR",
- TType(EbtUInt, EbpHigh, viewIDQualifier));
- viewIDSymbol->setInternal(true);
-
- DeclareGlobalVariable(root, viewIDSymbol);
- ReplaceSymbol(root, "gl_ViewID_OVR", viewIDSymbol);
- if (shaderType == GL_VERTEX_SHADER)
- {
- // Replacing gl_InstanceID with InstanceID should happen before adding the initializers of
- // InstanceID and ViewID.
- TIntermSymbol *instanceIDSymbol = new TIntermSymbol(
- symbolTable->nextUniqueId(), "InstanceID", TType(EbtInt, EbpHigh, EvqGlobal));
- instanceIDSymbol->setInternal(true);
- DeclareGlobalVariable(root, instanceIDSymbol);
- ReplaceSymbol(root, "gl_InstanceID", instanceIDSymbol);
-
- TIntermSequence *initializers = new TIntermSequence();
- InitializeViewIDAndInstanceID(viewIDSymbol, instanceIDSymbol, 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 & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u;
- // 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.
- TIntermSymbol *multiviewBaseViewLayerIndexSymbol =
- new TIntermSymbol(symbolTable->nextUniqueId(), "multiviewBaseViewLayerIndex",
- TType(EbtInt, EbpHigh, EvqUniform));
- multiviewBaseViewLayerIndexSymbol->setInternal(true);
- DeclareGlobalVariable(root, multiviewBaseViewLayerIndexSymbol);
-
- // Setting a value to gl_ViewportIndex or gl_Layer should happen after ViewID_OVR's
- // initialization.
- SelectViewIndexInVertexShader(viewIDSymbol->deepCopy(),
- multiviewBaseViewLayerIndexSymbol->deepCopy(),
- 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);
- }
-}
-
-} // namespace sh \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h b/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h
deleted file mode 100644
index b4ab05fd0e..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// Copyright (c) 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 SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER 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_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
-#define COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
-
-#include "GLSLANG/ShaderLang.h"
-#include "angle_gl.h"
-
-namespace sh
-{
-
-class TIntermBlock;
-class TSymbolTable;
-
-void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
- unsigned numberOfViews,
- GLenum shaderType,
- ShCompileOptions compileOptions,
- ShShaderOutput shaderOutput,
- TSymbolTable *symbolTable);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp b/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp
deleted file mode 100644
index 67d51ea87b..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-//
-// Copyright (c) 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/DeferGlobalInitializers.h"
-
-#include "compiler/translator/FindMain.h"
-#include "compiler/translator/InitializeVariables.h"
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-namespace
-{
-
-void GetDeferredInitializers(TIntermDeclaration *declaration,
- bool initializeUninitializedGlobals,
- bool canUseLoopsToInitialize,
- TIntermSequence *deferredInitializersOut,
- 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->getAsConstantUnion() == nullptr &&
- !expression->isConstructorWithOnlyConstantUnionParameters())))
- {
- // 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 has not been constant
- // folded, 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)
- {
- symbolNode->getTypePointer()->setQualifier(EvqGlobal);
- }
-
- 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.
- if (symbolNode->getName().isInternal())
- return;
-
- if (symbolNode->getQualifier() == EvqGlobal && symbolNode->getSymbol() != "")
- {
- TIntermSequence *initCode =
- CreateInitCode(symbolNode, canUseLoopsToInitialize, 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);
-
- TSymbolUniqueId initGlobalsFunctionId(symbolTable);
-
- const char *kInitGlobalsFunctionName = "initGlobals";
-
- TIntermFunctionPrototype *initGlobalsFunctionPrototype =
- CreateInternalFunctionPrototypeNode(TType(), kInitGlobalsFunctionName, initGlobalsFunctionId);
- root->getSequence()->insert(root->getSequence()->begin(), initGlobalsFunctionPrototype);
- TIntermFunctionDefinition *initGlobalsFunctionDefinition = CreateInternalFunctionDefinitionNode(
- TType(), kInitGlobalsFunctionName, initGlobalsBlock, initGlobalsFunctionId);
- root->appendStatement(initGlobalsFunctionDefinition);
-
- TIntermAggregate *initGlobalsCall = CreateInternalFunctionCallNode(
- TType(), kInitGlobalsFunctionName, initGlobalsFunctionId, new TIntermSequence());
-
- TIntermBlock *mainBody = FindMainBody(root);
- mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initGlobalsCall);
-}
-
-} // namespace
-
-void DeferGlobalInitializers(TIntermBlock *root,
- bool initializeUninitializedGlobals,
- bool canUseLoopsToInitialize,
- TSymbolTable *symbolTable)
-{
- TIntermSequence *deferredInitializers = new TIntermSequence();
-
- // 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, deferredInitializers, symbolTable);
- }
- }
-
- // Add the function with initialization and the call to that.
- if (!deferredInitializers->empty())
- {
- InsertInitCallToMain(root, deferredInitializers, symbolTable);
- }
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h b/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h
deleted file mode 100644
index 86930a585f..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// Copyright (c) 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_DEFERGLOBALINITIALIZERS_H_
-#define COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
-
-namespace sh
-{
-
-class TIntermBlock;
-class TSymbolTable;
-
-void DeferGlobalInitializers(TIntermBlock *root,
- bool initializeUninitializedGlobals,
- bool canUseLoopsToInitialize,
- TSymbolTable *symbolTable);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp
deleted file mode 100644
index 1744e5ab3e..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-//
-// Copyright (c) 2012-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.
-//
-
-#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 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 pp::SourceLocation &loc, const char *reason, const char *token)
-{
- writeInfo(SH_ERROR, loc, reason, token);
-}
-
-void TDiagnostics::warning(const 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)
-{
- 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)
-{
- pp::SourceLocation srcLoc;
- srcLoc.file = loc.first_file;
- srcLoc.line = loc.first_line;
- warning(srcLoc, reason, token);
-}
-
-void TDiagnostics::print(ID id, const 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/src/3rdparty/angle/src/compiler/translator/Diagnostics.h b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h
deleted file mode 100644
index 55b88991df..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h
+++ /dev/null
@@ -1,67 +0,0 @@
-//
-// Copyright (c) 2012-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.
-//
-
-#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 pp::Diagnostics, angle::NonCopyable
-{
- public:
- TDiagnostics(TInfoSinkBase &infoSink);
- ~TDiagnostics() override;
-
- int numErrors() const { return mNumErrors; }
- int numWarnings() const { return mNumWarnings; }
-
- void error(const pp::SourceLocation &loc, const char *reason, const char *token);
- void warning(const 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 pp::SourceLocation &loc,
- const char *reason,
- const char *token);
-
- void print(ID id, const 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/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp
deleted file mode 100644
index 485e66670c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-//
-// Copyright (c) 2012-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.
-//
-
-#include "compiler/translator/DirectiveHandler.h"
-
-#include <sstream>
-
-#include "angle_gl.h"
-#include "common/debug.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,
- bool debugShaderPrecisionSupported)
- : mExtensionBehavior(extBehavior),
- mDiagnostics(diagnostics),
- mShaderVersion(shaderVersion),
- mShaderType(shaderType),
- mDebugShaderPrecisionSupported(debugShaderPrecisionSupported)
-{
-}
-
-TDirectiveHandler::~TDirectiveHandler()
-{
-}
-
-void TDirectiveHandler::handleError(const pp::SourceLocation &loc, const std::string &msg)
-{
- mDiagnostics.error(loc, msg.c_str(), "");
-}
-
-void TDirectiveHandler::handlePragma(const 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 kDebugShaderPrecision[] = "webgl_debug_shader_precision";
- 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 if (name == kDebugShaderPrecision && mDebugShaderPrecisionSupported)
- {
- if (value == kOn)
- mPragma.debugShaderPrecision = true;
- else if (value == kOff)
- mPragma.debugShaderPrecision = false;
- else
- invalidValue = true;
- }
- else
- {
- mDiagnostics.report(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 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;
- 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 pp::SourceLocation &loc, int version)
-{
- if (version == 100 || version == 300 || version == 310)
- {
- mShaderVersion = version;
- }
- else
- {
- std::stringstream stream;
- stream << version;
- std::string str = stream.str();
- mDiagnostics.error(loc, "version number not supported", str.c_str());
- }
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h
deleted file mode 100644
index 8e8cb9bbf6..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h
+++ /dev/null
@@ -1,57 +0,0 @@
-//
-// Copyright (c) 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 "common/angleutils.h"
-#include "compiler/translator/ExtensionBehavior.h"
-#include "compiler/translator/Pragma.h"
-#include "compiler/preprocessor/DirectiveHandlerBase.h"
-#include "GLSLANG/ShaderLang.h"
-
-namespace sh
-{
-class TDiagnostics;
-
-class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable
-{
- public:
- TDirectiveHandler(TExtensionBehavior &extBehavior,
- TDiagnostics &diagnostics,
- int &shaderVersion,
- sh::GLenum shaderType,
- bool debugShaderPrecisionSupported);
- ~TDirectiveHandler() override;
-
- const TPragma &pragma() const { return mPragma; }
- const TExtensionBehavior &extensionBehavior() const { return mExtensionBehavior; }
-
- void handleError(const pp::SourceLocation &loc, const std::string &msg) override;
-
- void handlePragma(const pp::SourceLocation &loc,
- const std::string &name,
- const std::string &value,
- bool stdgl) override;
-
- void handleExtension(const pp::SourceLocation &loc,
- const std::string &name,
- const std::string &behavior) override;
-
- void handleVersion(const pp::SourceLocation &loc, int version) override;
-
- private:
- TPragma mPragma;
- TExtensionBehavior &mExtensionBehavior;
- TDiagnostics &mDiagnostics;
- int &mShaderVersion;
- sh::GLenum mShaderType;
- bool mDebugShaderPrecisionSupported;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp b/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp
deleted file mode 100644
index 189ea341eb..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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/EmulateGLFragColorBroadcast.h"
-
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/RunAtTheEndOfShader.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class GLFragColorBroadcastTraverser : public TIntermTraverser
-{
- public:
- GLFragColorBroadcastTraverser(int maxDrawBuffers, TSymbolTable *symbolTable, int shaderVersion)
- : TIntermTraverser(true, false, false, symbolTable),
- mGLFragColorUsed(false),
- mMaxDrawBuffers(maxDrawBuffers),
- mShaderVersion(shaderVersion)
- {
- }
-
- void broadcastGLFragColor(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(TString("gl_FragData"), *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->getSymbol() == "gl_FragColor")
- {
- queueReplacement(constructGLFragDataNode(0), OriginalNode::IS_DROPPED);
- mGLFragColorUsed = true;
- }
-}
-
-void GLFragColorBroadcastTraverser::broadcastGLFragColor(TIntermBlock *root)
-{
- ASSERT(mMaxDrawBuffers > 1);
- if (!mGLFragColorUsed)
- {
- return;
- }
-
- 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));
- }
- RunAtTheEndOfShader(root, broadcastBlock, mSymbolTable);
-}
-
-} // namespace anonymous
-
-void EmulateGLFragColorBroadcast(TIntermBlock *root,
- int maxDrawBuffers,
- std::vector<sh::OutputVariable> *outputVariables,
- TSymbolTable *symbolTable,
- int shaderVersion)
-{
- ASSERT(maxDrawBuffers > 1);
- GLFragColorBroadcastTraverser traverser(maxDrawBuffers, symbolTable, shaderVersion);
- root->traverse(&traverser);
- if (traverser.isGLFragColorUsed())
- {
- traverser.updateTree();
- traverser.broadcastGLFragColor(root);
- 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);
- }
- }
- }
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h b/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h
deleted file mode 100644
index e652b7e07e..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// Emulate gl_FragColor broadcast behaviors in ES2 where
-// GL_EXT_draw_buffers is explicitly enabled in a fragment shader.
-//
-
-#ifndef COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
-#define COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
-
-#include <vector>
-
-namespace sh
-{
-struct OutputVariable;
-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.
-void EmulateGLFragColorBroadcast(TIntermBlock *root,
- int maxDrawBuffers,
- std::vector<OutputVariable> *outputVariables,
- TSymbolTable *symbolTable,
- int shaderVersion);
-}
-
-#endif // COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp
deleted file mode 100644
index ba09fd77df..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp
+++ /dev/null
@@ -1,751 +0,0 @@
-//
-// Copyright (c) 2002-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/EmulatePrecision.h"
-
-#include <memory>
-
-namespace sh
-{
-
-namespace
-{
-
-class RoundingHelperWriter : angle::NonCopyable
-{
- public:
- static RoundingHelperWriter *createHelperWriter(const ShShaderOutput outputLanguage);
-
- void writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion);
- void writeCompoundAssignmentHelper(TInfoSinkBase &sink,
- const char *lType,
- const char *rType,
- const char *opStr,
- const char *opNameStr);
-
- virtual ~RoundingHelperWriter() {}
-
- protected:
- RoundingHelperWriter(const ShShaderOutput outputLanguage) : mOutputLanguage(outputLanguage) {}
- RoundingHelperWriter() = delete;
-
- const ShShaderOutput mOutputLanguage;
-
- private:
- virtual std::string getTypeString(const char *glslType) = 0;
- virtual void writeFloatRoundingHelpers(TInfoSinkBase &sink) = 0;
- virtual void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) = 0;
- virtual void writeMatrixRoundingHelper(TInfoSinkBase &sink,
- const unsigned int columns,
- const unsigned int rows,
- const char *functionName) = 0;
-};
-
-class RoundingHelperWriterGLSL : public RoundingHelperWriter
-{
- public:
- RoundingHelperWriterGLSL(const ShShaderOutput outputLanguage)
- : RoundingHelperWriter(outputLanguage)
- {
- }
-
- private:
- std::string getTypeString(const char *glslType) override;
- void writeFloatRoundingHelpers(TInfoSinkBase &sink) override;
- void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override;
- void writeMatrixRoundingHelper(TInfoSinkBase &sink,
- const unsigned int columns,
- const unsigned int rows,
- const char *functionName) override;
-};
-
-class RoundingHelperWriterESSL : public RoundingHelperWriterGLSL
-{
- public:
- RoundingHelperWriterESSL(const ShShaderOutput outputLanguage)
- : RoundingHelperWriterGLSL(outputLanguage)
- {
- }
-
- private:
- std::string getTypeString(const char *glslType) override;
-};
-
-class RoundingHelperWriterHLSL : public RoundingHelperWriter
-{
- public:
- RoundingHelperWriterHLSL(const ShShaderOutput outputLanguage)
- : RoundingHelperWriter(outputLanguage)
- {
- }
-
- private:
- std::string getTypeString(const char *glslType) override;
- void writeFloatRoundingHelpers(TInfoSinkBase &sink) override;
- void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override;
- void writeMatrixRoundingHelper(TInfoSinkBase &sink,
- const unsigned int columns,
- const unsigned int rows,
- const char *functionName) override;
-};
-
-RoundingHelperWriter *RoundingHelperWriter::createHelperWriter(const ShShaderOutput outputLanguage)
-{
- ASSERT(EmulatePrecision::SupportedInLanguage(outputLanguage));
- switch (outputLanguage)
- {
- case SH_HLSL_4_1_OUTPUT:
- return new RoundingHelperWriterHLSL(outputLanguage);
- case SH_ESSL_OUTPUT:
- return new RoundingHelperWriterESSL(outputLanguage);
- default:
- return new RoundingHelperWriterGLSL(outputLanguage);
- }
-}
-
-void RoundingHelperWriter::writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion)
-{
- // Write the angle_frm functions that round floating point numbers to
- // half precision, and angle_frl functions that round them to minimum lowp
- // precision.
-
- writeFloatRoundingHelpers(sink);
- writeVectorRoundingHelpers(sink, 2);
- writeVectorRoundingHelpers(sink, 3);
- writeVectorRoundingHelpers(sink, 4);
- if (shaderVersion > 100)
- {
- for (unsigned int columns = 2; columns <= 4; ++columns)
- {
- for (unsigned int rows = 2; rows <= 4; ++rows)
- {
- writeMatrixRoundingHelper(sink, columns, rows, "angle_frm");
- writeMatrixRoundingHelper(sink, columns, rows, "angle_frl");
- }
- }
- }
- else
- {
- for (unsigned int size = 2; size <= 4; ++size)
- {
- writeMatrixRoundingHelper(sink, size, size, "angle_frm");
- writeMatrixRoundingHelper(sink, size, size, "angle_frl");
- }
- }
-}
-
-void RoundingHelperWriter::writeCompoundAssignmentHelper(TInfoSinkBase &sink,
- const char *lType,
- const char *rType,
- const char *opStr,
- const char *opNameStr)
-{
- std::string lTypeStr = getTypeString(lType);
- std::string rTypeStr = getTypeString(rType);
-
- // Note that y should be passed through angle_frm at the function call site,
- // but x can't be passed through angle_frm there since it is an inout parameter.
- // So only pass x and the result through angle_frm here.
- // clang-format off
- sink <<
- lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
- " x = angle_frm(angle_frm(x) " << opStr << " y);\n"
- " return x;\n"
- "}\n";
- sink <<
- lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
- " x = angle_frl(angle_frl(x) " << opStr << " y);\n"
- " return x;\n"
- "}\n";
- // clang-format on
-}
-
-std::string RoundingHelperWriterGLSL::getTypeString(const char *glslType)
-{
- return glslType;
-}
-
-std::string RoundingHelperWriterESSL::getTypeString(const char *glslType)
-{
- std::stringstream typeStrStr;
- typeStrStr << "highp " << glslType;
- return typeStrStr.str();
-}
-
-void RoundingHelperWriterGLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink)
-{
- // Unoptimized version of angle_frm for single floats:
- //
- // int webgl_maxNormalExponent(in int exponentBits)
- // {
- // int possibleExponents = int(exp2(float(exponentBits)));
- // int exponentBias = possibleExponents / 2 - 1;
- // int allExponentBitsOne = possibleExponents - 1;
- // return (allExponentBitsOne - 1) - exponentBias;
- // }
- //
- // float angle_frm(in float x)
- // {
- // int mantissaBits = 10;
- // int exponentBits = 5;
- // float possibleMantissas = exp2(float(mantissaBits));
- // float mantissaMax = 2.0 - 1.0 / possibleMantissas;
- // int maxNE = webgl_maxNormalExponent(exponentBits);
- // float max = exp2(float(maxNE)) * mantissaMax;
- // if (x > max)
- // {
- // return max;
- // }
- // if (x < -max)
- // {
- // return -max;
- // }
- // float exponent = floor(log2(abs(x)));
- // if (abs(x) == 0.0 || exponent < -float(maxNE))
- // {
- // return 0.0 * sign(x)
- // }
- // x = x * exp2(-(exponent - float(mantissaBits)));
- // x = sign(x) * floor(abs(x));
- // return x * exp2(exponent - float(mantissaBits));
- // }
-
- // All numbers with a magnitude less than 2^-15 are subnormal, and are
- // flushed to zero.
-
- // Note the constant numbers below:
- // a) 65504 is the maximum possible mantissa (1.1111111111 in binary) times
- // 2^15, the maximum normal exponent.
- // b) 10.0 is the number of mantissa bits.
- // c) -25.0 is the minimum normal half-float exponent -15.0 minus the number
- // of mantissa bits.
- // d) + 1e-30 is to make sure the argument of log2() won't be zero. It can
- // only affect the result of log2 on x where abs(x) < 1e-22. Since these
- // numbers will be flushed to zero either way (2^-15 is the smallest
- // normal positive number), this does not introduce any error.
-
- std::string floatType = getTypeString("float");
-
- // clang-format off
- sink <<
- floatType << " angle_frm(in " << floatType << " x) {\n"
- " x = clamp(x, -65504.0, 65504.0);\n"
- " " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n"
- " bool isNonZero = (exponent >= -25.0);\n"
- " x = x * exp2(-exponent);\n"
- " x = sign(x) * floor(abs(x));\n"
- " return x * exp2(exponent) * float(isNonZero);\n"
- "}\n";
-
- sink <<
- floatType << " angle_frl(in " << floatType << " x) {\n"
- " x = clamp(x, -2.0, 2.0);\n"
- " x = x * 256.0;\n"
- " x = sign(x) * floor(abs(x));\n"
- " return x * 0.00390625;\n"
- "}\n";
- // clang-format on
-}
-
-void RoundingHelperWriterGLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink,
- const unsigned int size)
-{
- std::stringstream vecTypeStrStr;
- vecTypeStrStr << "vec" << size;
- std::string vecType = getTypeString(vecTypeStrStr.str().c_str());
-
- // clang-format off
- sink <<
- vecType << " angle_frm(in " << vecType << " v) {\n"
- " v = clamp(v, -65504.0, 65504.0);\n"
- " " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
- " bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n"
- " v = v * exp2(-exponent);\n"
- " v = sign(v) * floor(abs(v));\n"
- " return v * exp2(exponent) * vec" << size << "(isNonZero);\n"
- "}\n";
-
- sink <<
- vecType << " angle_frl(in " << vecType << " v) {\n"
- " v = clamp(v, -2.0, 2.0);\n"
- " v = v * 256.0;\n"
- " v = sign(v) * floor(abs(v));\n"
- " return v * 0.00390625;\n"
- "}\n";
- // clang-format on
-}
-
-void RoundingHelperWriterGLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink,
- const unsigned int columns,
- const unsigned int rows,
- const char *functionName)
-{
- std::stringstream matTypeStrStr;
- matTypeStrStr << "mat" << columns;
- if (rows != columns)
- {
- matTypeStrStr << "x" << rows;
- }
- std::string matType = getTypeString(matTypeStrStr.str().c_str());
-
- sink << matType << " " << functionName << "(in " << matType << " m) {\n"
- << " " << matType << " rounded;\n";
-
- for (unsigned int i = 0; i < columns; ++i)
- {
- sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
- }
-
- sink << " return rounded;\n"
- "}\n";
-}
-
-static const char *GetHLSLTypeStr(const char *floatTypeStr)
-{
- if (strcmp(floatTypeStr, "float") == 0)
- {
- return "float";
- }
- if (strcmp(floatTypeStr, "vec2") == 0)
- {
- return "float2";
- }
- if (strcmp(floatTypeStr, "vec3") == 0)
- {
- return "float3";
- }
- if (strcmp(floatTypeStr, "vec4") == 0)
- {
- return "float4";
- }
- if (strcmp(floatTypeStr, "mat2") == 0)
- {
- return "float2x2";
- }
- if (strcmp(floatTypeStr, "mat3") == 0)
- {
- return "float3x3";
- }
- if (strcmp(floatTypeStr, "mat4") == 0)
- {
- return "float4x4";
- }
- if (strcmp(floatTypeStr, "mat2x3") == 0)
- {
- return "float2x3";
- }
- if (strcmp(floatTypeStr, "mat2x4") == 0)
- {
- return "float2x4";
- }
- if (strcmp(floatTypeStr, "mat3x2") == 0)
- {
- return "float3x2";
- }
- if (strcmp(floatTypeStr, "mat3x4") == 0)
- {
- return "float3x4";
- }
- if (strcmp(floatTypeStr, "mat4x2") == 0)
- {
- return "float4x2";
- }
- if (strcmp(floatTypeStr, "mat4x3") == 0)
- {
- return "float4x3";
- }
- UNREACHABLE();
- return nullptr;
-}
-
-std::string RoundingHelperWriterHLSL::getTypeString(const char *glslType)
-{
- return GetHLSLTypeStr(glslType);
-}
-
-void RoundingHelperWriterHLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink)
-{
- // In HLSL scalars are the same as 1-vectors.
- writeVectorRoundingHelpers(sink, 1);
-}
-
-void RoundingHelperWriterHLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink,
- const unsigned int size)
-{
- std::stringstream vecTypeStrStr;
- vecTypeStrStr << "float" << size;
- std::string vecType = vecTypeStrStr.str();
-
- // clang-format off
- sink <<
- vecType << " angle_frm(" << vecType << " v) {\n"
- " v = clamp(v, -65504.0, 65504.0);\n"
- " " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
- " bool" << size << " isNonZero = exponent < -25.0;\n"
- " v = v * exp2(-exponent);\n"
- " v = sign(v) * floor(abs(v));\n"
- " return v * exp2(exponent) * (float" << size << ")(isNonZero);\n"
- "}\n";
-
- sink <<
- vecType << " angle_frl(" << vecType << " v) {\n"
- " v = clamp(v, -2.0, 2.0);\n"
- " v = v * 256.0;\n"
- " v = sign(v) * floor(abs(v));\n"
- " return v * 0.00390625;\n"
- "}\n";
- // clang-format on
-}
-
-void RoundingHelperWriterHLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink,
- const unsigned int columns,
- const unsigned int rows,
- const char *functionName)
-{
- std::stringstream matTypeStrStr;
- matTypeStrStr << "float" << columns << "x" << rows;
- std::string matType = matTypeStrStr.str();
-
- sink << matType << " " << functionName << "(" << matType << " m) {\n"
- << " " << matType << " rounded;\n";
-
- for (unsigned int i = 0; i < columns; ++i)
- {
- sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
- }
-
- sink << " return rounded;\n"
- "}\n";
-}
-
-bool canRoundFloat(const TType &type)
-{
- return type.getBasicType() == EbtFloat && !type.isArray() &&
- (type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium);
-}
-
-TIntermAggregate *createInternalFunctionCallNode(const TType &type,
- TString name,
- TIntermSequence *arguments)
-{
- TName nameObj(name);
- nameObj.setInternal(true);
- TIntermAggregate *callNode =
- TIntermAggregate::Create(type, EOpCallInternalRawFunction, arguments);
- callNode->getFunctionSymbolInfo()->setNameObj(nameObj);
- return callNode;
-}
-
-TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild)
-{
- TString roundFunctionName;
- if (roundedChild->getPrecision() == EbpMedium)
- roundFunctionName = "angle_frm";
- else
- roundFunctionName = "angle_frl";
- TIntermSequence *arguments = new TIntermSequence();
- arguments->push_back(roundedChild);
- TIntermAggregate *callNode =
- createInternalFunctionCallNode(roundedChild->getType(), roundFunctionName, arguments);
- callNode->getFunctionSymbolInfo()->setKnownToNotHaveSideEffects(true);
- return callNode;
-}
-
-TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left,
- TIntermTyped *right,
- const char *opNameStr)
-{
- std::stringstream strstr;
- if (left->getPrecision() == EbpMedium)
- strstr << "angle_compound_" << opNameStr << "_frm";
- else
- strstr << "angle_compound_" << opNameStr << "_frl";
- TString functionName = strstr.str().c_str();
- TIntermSequence *arguments = new TIntermSequence();
- arguments->push_back(left);
- arguments->push_back(right);
- return createInternalFunctionCallNode(left->getType(), functionName, arguments);
-}
-
-bool ParentUsesResult(TIntermNode *parent, TIntermTyped *node)
-{
- if (!parent)
- {
- return false;
- }
-
- TIntermBlock *blockParent = parent->getAsBlock();
- // If the parent is a block, the result is not assigned anywhere,
- // so rounding it is not needed. In particular, this can avoid a lot of
- // unnecessary rounding of unused return values of assignment.
- if (blockParent)
- {
- return false;
- }
- TIntermBinary *binaryParent = parent->getAsBinaryNode();
- if (binaryParent && binaryParent->getOp() == EOpComma && (binaryParent->getRight() != node))
- {
- return false;
- }
- return true;
-}
-
-bool ParentConstructorTakesCareOfRounding(TIntermNode *parent, TIntermTyped *node)
-{
- if (!parent)
- {
- return false;
- }
- TIntermAggregate *parentConstructor = parent->getAsAggregate();
- if (!parentConstructor || parentConstructor->getOp() != EOpConstruct)
- {
- return false;
- }
- if (parentConstructor->getPrecision() != node->getPrecision())
- {
- return false;
- }
- return canRoundFloat(parentConstructor->getType());
-}
-
-} // namespace anonymous
-
-EmulatePrecision::EmulatePrecision(TSymbolTable *symbolTable, int shaderVersion)
- : TLValueTrackingTraverser(true, true, true, symbolTable, shaderVersion),
- mDeclaringVariables(false)
-{
-}
-
-void EmulatePrecision::visitSymbol(TIntermSymbol *node)
-{
- TIntermNode *parent = getParentNode();
- if (canRoundFloat(node->getType()) && ParentUsesResult(parent, node) &&
- !ParentConstructorTakesCareOfRounding(parent, node) && !mDeclaringVariables &&
- !isLValueRequiredHere())
- {
- TIntermNode *replacement = createRoundingFunctionCallNode(node);
- queueReplacement(replacement, OriginalNode::BECOMES_CHILD);
- }
-}
-
-bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
-{
- bool visitChildren = true;
-
- TOperator op = node->getOp();
-
- // RHS of initialize is not being declared.
- if (op == EOpInitialize && visit == InVisit)
- mDeclaringVariables = false;
-
- if ((op == EOpIndexDirectStruct) && visit == InVisit)
- visitChildren = false;
-
- if (visit != PreVisit)
- return visitChildren;
-
- const TType &type = node->getType();
- bool roundFloat = canRoundFloat(type);
-
- if (roundFloat)
- {
- switch (op)
- {
- // Math operators that can result in a float may need to apply rounding to the return
- // value. Note that in the case of assignment, the rounding is applied to its return
- // value here, not the value being assigned.
- case EOpAssign:
- case EOpAdd:
- case EOpSub:
- case EOpMul:
- case EOpDiv:
- case EOpVectorTimesScalar:
- case EOpVectorTimesMatrix:
- case EOpMatrixTimesVector:
- case EOpMatrixTimesScalar:
- case EOpMatrixTimesMatrix:
- {
- TIntermNode *parent = getParentNode();
- if (!ParentUsesResult(parent, node) ||
- ParentConstructorTakesCareOfRounding(parent, node))
- {
- break;
- }
- TIntermNode *replacement = createRoundingFunctionCallNode(node);
- queueReplacement(replacement, OriginalNode::BECOMES_CHILD);
- break;
- }
-
- // Compound assignment cases need to replace the operator with a function call.
- case EOpAddAssign:
- {
- mEmulateCompoundAdd.insert(
- TypePair(type.getBuiltInTypeNameString(),
- node->getRight()->getType().getBuiltInTypeNameString()));
- TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
- node->getLeft(), node->getRight(), "add");
- queueReplacement(replacement, OriginalNode::IS_DROPPED);
- break;
- }
- case EOpSubAssign:
- {
- mEmulateCompoundSub.insert(
- TypePair(type.getBuiltInTypeNameString(),
- node->getRight()->getType().getBuiltInTypeNameString()));
- TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
- node->getLeft(), node->getRight(), "sub");
- queueReplacement(replacement, OriginalNode::IS_DROPPED);
- break;
- }
- case EOpMulAssign:
- case EOpVectorTimesMatrixAssign:
- case EOpVectorTimesScalarAssign:
- case EOpMatrixTimesScalarAssign:
- case EOpMatrixTimesMatrixAssign:
- {
- mEmulateCompoundMul.insert(
- TypePair(type.getBuiltInTypeNameString(),
- node->getRight()->getType().getBuiltInTypeNameString()));
- TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
- node->getLeft(), node->getRight(), "mul");
- queueReplacement(replacement, OriginalNode::IS_DROPPED);
- break;
- }
- case EOpDivAssign:
- {
- mEmulateCompoundDiv.insert(
- TypePair(type.getBuiltInTypeNameString(),
- node->getRight()->getType().getBuiltInTypeNameString()));
- TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
- node->getLeft(), node->getRight(), "div");
- queueReplacement(replacement, OriginalNode::IS_DROPPED);
- break;
- }
- default:
- // The rest of the binary operations should not need precision emulation.
- break;
- }
- }
- return visitChildren;
-}
-
-bool EmulatePrecision::visitDeclaration(Visit visit, TIntermDeclaration *node)
-{
- // Variable or interface block declaration.
- if (visit == PreVisit)
- {
- mDeclaringVariables = true;
- }
- else if (visit == InVisit)
- {
- mDeclaringVariables = true;
- }
- else
- {
- mDeclaringVariables = false;
- }
- return true;
-}
-
-bool EmulatePrecision::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
-{
- return false;
-}
-
-bool EmulatePrecision::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
-{
- return false;
-}
-
-bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- if (visit != PreVisit)
- return true;
- switch (node->getOp())
- {
- case EOpCallInternalRawFunction:
- case EOpCallFunctionInAST:
- // User-defined function return values are not rounded. The calculations that produced
- // the value inside the function definition should have been rounded.
- break;
- case EOpConstruct:
- if (node->getBasicType() == EbtStruct)
- {
- break;
- }
- default:
- TIntermNode *parent = getParentNode();
- if (canRoundFloat(node->getType()) && ParentUsesResult(parent, node) &&
- !ParentConstructorTakesCareOfRounding(parent, node))
- {
- TIntermNode *replacement = createRoundingFunctionCallNode(node);
- queueReplacement(replacement, OriginalNode::BECOMES_CHILD);
- }
- break;
- }
- return true;
-}
-
-bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node)
-{
- switch (node->getOp())
- {
- case EOpNegative:
- case EOpLogicalNot:
- case EOpPostIncrement:
- case EOpPostDecrement:
- case EOpPreIncrement:
- case EOpPreDecrement:
- case EOpLogicalNotComponentWise:
- break;
- default:
- if (canRoundFloat(node->getType()) && visit == PreVisit)
- {
- TIntermNode *replacement = createRoundingFunctionCallNode(node);
- queueReplacement(replacement, OriginalNode::BECOMES_CHILD);
- }
- break;
- }
-
- return true;
-}
-
-void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase &sink,
- const int shaderVersion,
- const ShShaderOutput outputLanguage)
-{
- std::unique_ptr<RoundingHelperWriter> roundingHelperWriter(
- RoundingHelperWriter::createHelperWriter(outputLanguage));
-
- roundingHelperWriter->writeCommonRoundingHelpers(sink, shaderVersion);
-
- EmulationSet::const_iterator it;
- for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++)
- roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "+", "add");
- for (it = mEmulateCompoundSub.begin(); it != mEmulateCompoundSub.end(); it++)
- roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "-", "sub");
- for (it = mEmulateCompoundDiv.begin(); it != mEmulateCompoundDiv.end(); it++)
- roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "/", "div");
- for (it = mEmulateCompoundMul.begin(); it != mEmulateCompoundMul.end(); it++)
- roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "*", "mul");
-}
-
-// static
-bool EmulatePrecision::SupportedInLanguage(const ShShaderOutput outputLanguage)
-{
- switch (outputLanguage)
- {
- case SH_HLSL_4_1_OUTPUT:
- case SH_ESSL_OUTPUT:
- return true;
- default:
- // Other languages not yet supported
- return (outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
- sh::IsGLSL130OrNewer(outputLanguage));
- }
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h
deleted file mode 100644
index 8044465410..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//
-// Copyright (c) 2002-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_EMULATE_PRECISION_H_
-#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
-
-#include "GLSLANG/ShaderLang.h"
-#include "common/angleutils.h"
-#include "compiler/translator/Compiler.h"
-#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermTraverse.h"
-
-// This class gathers all compound assignments from the AST and can then write
-// the functions required for their precision emulation. This way there is no
-// need to write a huge number of variations of the emulated compound assignment
-// to every translated shader with emulation enabled.
-
-namespace sh
-{
-
-class EmulatePrecision : public TLValueTrackingTraverser
-{
- public:
- EmulatePrecision(TSymbolTable *symbolTable, int shaderVersion);
-
- void visitSymbol(TIntermSymbol *node) override;
- bool visitBinary(Visit visit, TIntermBinary *node) override;
- bool visitUnary(Visit visit, TIntermUnary *node) override;
- bool visitAggregate(Visit visit, TIntermAggregate *node) override;
- bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
- bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
- bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
-
- void writeEmulationHelpers(TInfoSinkBase &sink,
- const int shaderVersion,
- const ShShaderOutput outputLanguage);
-
- static bool SupportedInLanguage(const ShShaderOutput outputLanguage);
-
- private:
- struct TypePair
- {
- TypePair(const char *l, const char *r) : lType(l), rType(r) {}
-
- const char *lType;
- const char *rType;
- };
-
- struct TypePairComparator
- {
- bool operator()(const TypePair &l, const TypePair &r) const
- {
- if (l.lType == r.lType)
- return l.rType < r.rType;
- return l.lType < r.lType;
- }
- };
-
- typedef std::set<TypePair, TypePairComparator> EmulationSet;
- EmulationSet mEmulateCompoundAdd;
- EmulationSet mEmulateCompoundSub;
- EmulationSet mEmulateCompoundMul;
- EmulationSet mEmulateCompoundDiv;
-
- bool mDeclaringVariables;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp b/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp
deleted file mode 100644
index f17dd73657..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-//
-// Copyright (c) 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/ExpandIntegerPowExpressions.h"
-
-#include <cmath>
-#include <cstdlib>
-
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class Traverser : public TIntermTraverser
-{
- public:
- static void Apply(TIntermNode *root, TSymbolTable *symbolTable);
-
- private:
- Traverser(TSymbolTable *symbolTable);
- bool visitAggregate(Visit visit, TIntermAggregate *node) override;
- void nextIteration();
-
- bool mFound = false;
-};
-
-// static
-void Traverser::Apply(TIntermNode *root, TSymbolTable *symbolTable)
-{
- Traverser traverser(symbolTable);
- do
- {
- traverser.nextIteration();
- root->traverse(&traverser);
- if (traverser.mFound)
- {
- traverser.updateTree();
- }
- } while (traverser.mFound);
-}
-
-Traverser::Traverser(TSymbolTable *symbolTable) : TIntermTraverser(true, false, false, symbolTable)
-{
-}
-
-void Traverser::nextIteration()
-{
- mFound = false;
- nextTemporaryId();
-}
-
-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 *constantNode = sequence->at(1)->getAsConstantUnion();
-
- // Test 1: check for a single constant.
- if (!constantNode || constantNode->getNominalSize() != 1)
- {
- return true;
- }
-
- const TConstantUnion *constant = constantNode->getUnionArrayPointer();
-
- TConstantUnion asFloat;
- asFloat.cast(EbtFloat, *constant);
-
- float value = asFloat.getFConst();
-
- // Test 2: value is in the problematic range.
- if (value < -5.0f || value > 9.0f)
- {
- return true;
- }
-
- // Test 3: value is integer or pretty close to an integer.
- float absval = std::abs(value);
- float frac = absval - std::round(absval);
- if (frac > 0.0001f)
- {
- return true;
- }
-
- // Test 4: skip -1, 0, and 1
- int exponent = static_cast<int>(value);
- int n = std::abs(exponent);
- if (n < 2)
- {
- return true;
- }
-
- // Potential problem case detected, apply workaround.
- nextTemporaryId();
-
- TIntermTyped *lhs = sequence->at(0)->getAsTyped();
- ASSERT(lhs);
-
- TIntermDeclaration *init = createTempInitDeclaration(lhs);
- TIntermTyped *current = createTempSymbol(lhs->getType());
-
- insertStatementInParentBlock(init);
-
- // Create a chain of n-1 multiples.
- for (int i = 1; i < n; ++i)
- {
- TIntermBinary *mul = new TIntermBinary(EOpMul, current, createTempSymbol(lhs->getType()));
- 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
-
-void ExpandIntegerPowExpressions(TIntermNode *root, TSymbolTable *symbolTable)
-{
- Traverser::Apply(root, symbolTable);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h b/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h
deleted file mode 100644
index 0074e5d663..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Copyright (c) 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_EXPANDINTEGERPOWEXPRESSIONS_H_
-#define COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_
-
-namespace sh
-{
-
-class TIntermNode;
-class TSymbolTable;
-
-void ExpandIntegerPowExpressions(TIntermNode *root, TSymbolTable *symbolTable);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp
deleted file mode 100644
index 3f910b9050..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-//
-// Copyright (c) 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 <string.h>
-
-#define LIST_EXTENSIONS(OP) \
- OP(ARB_texture_rectangle) \
- OP(ARM_shader_framebuffer_fetch) \
- OP(EXT_blend_func_extended) \
- OP(EXT_draw_buffers) \
- OP(EXT_frag_depth) \
- OP(EXT_geometry_shader) \
- OP(EXT_shader_framebuffer_fetch) \
- OP(EXT_shader_texture_lod) \
- OP(EXT_YUV_target) \
- OP(NV_EGL_stream_consumer_external) \
- OP(NV_shader_framebuffer_fetch) \
- OP(OES_EGL_image_external) \
- OP(OES_EGL_image_external_essl3) \
- OP(OES_geometry_shader) \
- OP(OES_standard_derivatives) \
- OP(OVR_multiview)
-
-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/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h
deleted file mode 100644
index 09cc03f10f..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// ExtensionBehavior.h: Extension name enumeration and data structures for storing extension
-// behavior.
-
-#ifndef COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
-#define COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
-
-#include <map>
-
-namespace sh
-{
-
-enum class TExtension
-{
- UNDEFINED, // Special value used to indicate no extension.
-
- ARB_texture_rectangle,
- ARM_shader_framebuffer_fetch,
- EXT_blend_func_extended,
- EXT_draw_buffers,
- EXT_frag_depth,
- EXT_geometry_shader,
- EXT_shader_framebuffer_fetch,
- EXT_shader_texture_lod,
- EXT_YUV_target,
- NV_EGL_stream_consumer_external,
- NV_shader_framebuffer_fetch,
- OES_EGL_image_external,
- OES_EGL_image_external_essl3,
- OES_geometry_shader,
- OES_standard_derivatives,
- OVR_multiview
-};
-
-enum TBehavior
-{
- 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<TExtension, TBehavior> TExtensionBehavior;
-
-bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, TExtension extension);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp
deleted file mode 100644
index 5b5dc580e9..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-//
-// Copyright (c) 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<std::string> &TExtensionGLSL::getEnabledExtensions() const
-{
- return mEnabledExtensions;
-}
-
-const std::set<std::string> &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;
-
- default:
- break;
- }
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h b/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h
deleted file mode 100644
index a1b9cb2225..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright (c) 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 <set>
-#include <string>
-
-#include "compiler/translator/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<std::string> &getEnabledExtensions() const;
- const std::set<std::string> &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<std::string> mEnabledExtensions;
- std::set<std::string> mRequiredExtensions;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_EXTENSIONGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/FindMain.cpp b/src/3rdparty/angle/src/compiler/translator/FindMain.cpp
deleted file mode 100644
index 7417fbac8a..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/FindMain.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Copyright (c) 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/FindMain.h"
-
-#include "compiler/translator/IntermNode.h"
-
-namespace sh
-{
-
-TIntermFunctionDefinition *FindMain(TIntermBlock *root)
-{
- for (TIntermNode *node : *root->getSequence())
- {
- TIntermFunctionDefinition *nodeFunction = node->getAsFunctionDefinition();
- if (nodeFunction != nullptr && nodeFunction->getFunctionSymbolInfo()->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/src/3rdparty/angle/src/compiler/translator/FindMain.h b/src/3rdparty/angle/src/compiler/translator/FindMain.h
deleted file mode 100644
index bf2c45d871..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/FindMain.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright (c) 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_FINDMAIN_H_
-#define COMPILER_TRANSLATOR_FINDMAIN_H_
-
-namespace sh
-{
-
-class TIntermBlock;
-class TIntermFunctionDefinition;
-
-TIntermFunctionDefinition *FindMain(TIntermBlock *root);
-TIntermBlock *FindMainBody(TIntermBlock *root);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_FINDMAIN_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp b/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp
deleted file mode 100644
index a2a10f128d..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-// Copyright (c) 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/FindSymbolNode.h"
-
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class SymbolFinder : public TIntermTraverser
-{
- public:
- SymbolFinder(const TString &symbolName, TBasicType basicType)
- : TIntermTraverser(true, false, false),
- mSymbolName(symbolName),
- mNodeFound(nullptr),
- mBasicType(basicType)
- {
- }
-
- void visitSymbol(TIntermSymbol *node)
- {
- if (node->getBasicType() == mBasicType && node->getSymbol() == mSymbolName)
- {
- mNodeFound = node;
- }
- }
-
- bool isFound() const { return mNodeFound != nullptr; }
- const TIntermSymbol *getNode() const { return mNodeFound; }
-
- private:
- TString mSymbolName;
- TIntermSymbol *mNodeFound;
- TBasicType mBasicType;
-};
-
-} // anonymous namespace
-
-const TIntermSymbol *FindSymbolNode(TIntermNode *root,
- const TString &symbolName,
- TBasicType basicType)
-{
- SymbolFinder finder(symbolName, basicType);
- root->traverse(&finder);
- return finder.getNode();
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h b/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h
deleted file mode 100644
index 08dfb9a222..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// Copyright (c) 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_FIND_SYMBOL_H_
-#define COMPILER_TRANSLATOR_FIND_SYMBOL_H_
-
-#include "compiler/translator/BaseTypes.h"
-#include "compiler/translator/Common.h"
-
-namespace sh
-{
-
-class TIntermNode;
-class TIntermSymbol;
-
-const TIntermSymbol *FindSymbolNode(TIntermNode *root,
- const TString &symbolName,
- TBasicType basicType);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_FIND_SYMBOL_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp
deleted file mode 100644
index fba837f55c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-//
-// Copyright (c) 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/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class FlagStd140StructsTraverser : public TIntermTraverser
-{
- public:
- FlagStd140StructsTraverser() : TIntermTraverser(true, false, false) {}
-
- const std::vector<MappedStruct> getMappedStructs() const { return mMappedStructs; }
-
- protected:
- bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
-
- private:
- void mapBlockStructMembers(TIntermSymbol *blockDeclarator, TInterfaceBlock *block);
-
- std::vector<MappedStruct> mMappedStructs;
-};
-
-void FlagStd140StructsTraverser::mapBlockStructMembers(TIntermSymbol *blockDeclarator,
- 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)
- {
- TInterfaceBlock *block = declarator->getType().getInterfaceBlock();
- if (block->blockStorage() == EbsStd140)
- {
- mapBlockStructMembers(declarator->getAsSymbolNode(), block);
- }
- }
- return false;
-}
-
-} // anonymous namespace
-
-std::vector<MappedStruct> FlagStd140Structs(TIntermNode *node)
-{
- FlagStd140StructsTraverser flaggingTraversal;
-
- node->traverse(&flaggingTraversal);
-
- return flaggingTraversal.getMappedStructs();
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h
deleted file mode 100644
index f548d8b6ed..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// Copyright (c) 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 <vector>
-
-namespace sh
-{
-
-class TField;
-class TIntermNode;
-class TIntermSymbol;
-
-struct MappedStruct
-{
- TIntermSymbol *blockDeclarator;
- TField *field;
-};
-
-std::vector<MappedStruct> FlagStd140Structs(TIntermNode *node);
-}
-
-#endif // COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.cpp b/src/3rdparty/angle/src/compiler/translator/HashNames.cpp
deleted file mode 100644
index 6bc90faf94..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/HashNames.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-//
-// Copyright (c) 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/IntermNode.h"
-
-namespace sh
-{
-
-namespace
-{
-
-// GLSL ES 3.00.6 section 3.9: the maximum length of an identifier is 1024 characters.
-static const unsigned int kESSLMaxIdentifierLength = 1024u;
-
-static const char *kHashedNamePrefix = "webgl_";
-
-// 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.
-static const char *kUnhashedNamePrefix = "_u";
-static const unsigned int kUnhashedNamePrefixLength = 2u;
-
-TString HashName(const TString &name, ShHashFunction64 hashFunction)
-{
- ASSERT(!name.empty());
- ASSERT(hashFunction);
- khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
- TStringStream stream;
- stream << kHashedNamePrefix << std::hex << number;
- TString hashedName = stream.str();
- return hashedName;
-}
-
-} // anonymous namespace
-
-TString HashName(const TName &name, ShHashFunction64 hashFunction, NameMap *nameMap)
-{
- if (name.getString().empty() || name.isInternal())
- {
- return name.getString();
- }
- if (hashFunction == nullptr)
- {
- if (name.getString().length() + kUnhashedNamePrefixLength > 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.getString();
- }
- return kUnhashedNamePrefix + name.getString();
- }
- if (nameMap)
- {
- NameMap::const_iterator it = nameMap->find(name.getString().c_str());
- if (it != nameMap->end())
- return it->second.c_str();
- }
- TString hashedName = HashName(name.getString(), hashFunction);
- if (nameMap)
- {
- (*nameMap)[name.getString().c_str()] = hashedName.c_str();
- }
- return hashedName;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.h b/src/3rdparty/angle/src/compiler/translator/HashNames.h
deleted file mode 100644
index 28e861b309..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/HashNames.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Copyright (c) 2002-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_HASHNAMES_H_
-#define COMPILER_TRANSLATOR_HASHNAMES_H_
-
-#include <map>
-
-#include "GLSLANG/ShaderLang.h"
-#include "compiler/translator/Common.h"
-
-namespace sh
-{
-
-typedef std::map<TPersistString, TPersistString> NameMap;
-
-class TName;
-
-// 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.
-TString HashName(const TName &name, ShHashFunction64 hashFunction, NameMap *nameMap);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_HASHNAMES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp
deleted file mode 100644
index 40b5e1f1e2..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp
+++ /dev/null
@@ -1,304 +0,0 @@
-//
-// Copyright (c) 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/UtilsHLSL.h"
-
-namespace sh
-{
-
-// static
-void ImageFunctionHLSL::OutputImageFunctionArgumentList(
- TInfoSinkBase &out,
- const ImageFunctionHLSL::ImageFunction &imageFunction)
-{
- if (imageFunction.readonly)
- {
- out << TextureString(imageFunction.image, imageFunction.imageInternalFormat) << " tex";
- }
- else
- {
- out << RWTextureString(imageFunction.image, imageFunction.imageInternalFormat) << " tex";
- }
-
- 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;
- default:
- UNREACHABLE();
- }
-
- if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE)
- {
- switch (imageFunction.image)
- {
- case EbtImage2D:
- case EbtImage3D:
- case EbtImageCube:
- case EbtImage2DArray:
- out << ", float4 data";
- break;
- case EbtIImage2D:
- case EbtIImage3D:
- case EbtIImageCube:
- case EbtIImage2DArray:
- out << ", int4 data";
- break;
- case EbtUImage2D:
- case EbtUImage3D:
- case EbtUImageCube:
- case EbtUImage2DArray:
- out << ", uint4 data";
- break;
- default:
- UNREACHABLE();
- }
- }
- }
-}
-
-// static
-void ImageFunctionHLSL::OutputImageSizeFunctionBody(
- TInfoSinkBase &out,
- const ImageFunctionHLSL::ImageFunction &imageFunction,
- const TString &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
- UNREACHABLE();
-
- if (strcmp(imageFunction.getReturnType(), "int3") == 0)
- {
- out << " return int3(width, height, depth);\n";
- }
- else
- {
- out << " return int2(width, height);\n";
- }
-}
-
-// static
-void ImageFunctionHLSL::OutputImageLoadFunctionBody(
- TInfoSinkBase &out,
- const ImageFunctionHLSL::ImageFunction &imageFunction,
- const TString &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
- UNREACHABLE();
-}
-
-// static
-void ImageFunctionHLSL::OutputImageStoreFunctionBody(
- TInfoSinkBase &out,
- const ImageFunctionHLSL::ImageFunction &imageFunction,
- const TString &imageReference)
-{
- if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||
- IsImage2D(imageFunction.image) || IsImageCube(imageFunction.image))
- {
- out << " " << imageReference << "[p] = data;\n";
- }
- else
- UNREACHABLE();
-}
-
-TString ImageFunctionHLSL::ImageFunction::name() const
-{
- TString name = "gl_image";
- if (readonly)
- {
- name += TextureTypeSuffix(image, imageInternalFormat);
- }
- else
- {
- name += RWTextureTypeSuffix(image, imageInternalFormat);
- }
-
- switch (method)
- {
- case Method::SIZE:
- name += "Size";
- break;
- case Method::LOAD:
- name += "Load";
- break;
- case Method::STORE:
- name += "Store";
- break;
- default:
- UNREACHABLE();
- }
-
- return name;
-}
-
-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";
- default:
- UNREACHABLE();
- }
- }
- else if (method == ImageFunction::Method::LOAD)
- {
- switch (image)
- {
- case EbtImage2D:
- case EbtImage3D:
- case EbtImageCube:
- case EbtImage2DArray:
- return "float4";
- case EbtIImage2D:
- case EbtIImage3D:
- case EbtIImageCube:
- case EbtIImage2DArray:
- return "int4";
- 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, imageInternalFormat, readonly, method) <
- std::tie(rhs.image, rhs.imageInternalFormat, rhs.readonly, rhs.method);
-}
-
-TString ImageFunctionHLSL::useImageFunction(const TString &name,
- const TBasicType &type,
- TLayoutImageInternalFormat imageInternalFormat,
- bool readonly)
-{
- ASSERT(IsImage(type));
- ImageFunction imageFunction;
- imageFunction.image = type;
- imageFunction.imageInternalFormat = imageInternalFormat;
- imageFunction.readonly = readonly;
-
- 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)
- {
- // Function header
- out << imageFunction.getReturnType() << " " << imageFunction.name() << "(";
-
- OutputImageFunctionArgumentList(out, imageFunction);
-
- out << ")\n"
- "{\n";
-
- TString imageReference("tex");
-
- 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/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h b/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h
deleted file mode 100644
index 9db17a6bbf..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// Copyright (c) 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 <set>
-
-#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.
- TString useImageFunction(const TString &name,
- const TBasicType &type,
- TLayoutImageInternalFormat imageInternalFormat,
- bool readonly);
-
- void imageFunctionHeader(TInfoSinkBase &out);
-
- 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
- };
-
- TString name() const;
-
- bool operator<(const ImageFunction &rhs) const;
-
- const char *getReturnType() const;
-
- TBasicType image;
- TLayoutImageInternalFormat imageInternalFormat;
- bool readonly;
- Method method;
- };
-
- static void OutputImageFunctionArgumentList(
- TInfoSinkBase &out,
- const ImageFunctionHLSL::ImageFunction &imageFunction);
- static void OutputImageSizeFunctionBody(TInfoSinkBase &out,
- const ImageFunctionHLSL::ImageFunction &imageFunction,
- const TString &imageReference);
- static void OutputImageLoadFunctionBody(TInfoSinkBase &out,
- const ImageFunctionHLSL::ImageFunction &imageFunction,
- const TString &imageReference);
- static void OutputImageStoreFunctionBody(TInfoSinkBase &out,
- const ImageFunctionHLSL::ImageFunction &imageFunction,
- const TString &imageReference);
- using ImageFunctionSet = std::set<ImageFunction>;
- ImageFunctionSet mUsesImage;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp b/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp
deleted file mode 100644
index db26aa67e8..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Copyright (c) 2002-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/InfoSink.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;
- }
-}
-
-void TInfoSinkBase::location(int file, int line)
-{
- TPersistStringStream stream;
- if (line)
- stream << file << ":" << line;
- else
- stream << file << ":? ";
- stream << ": ";
-
- sink.append(stream.str());
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/InfoSink.h b/src/3rdparty/angle/src/compiler/translator/InfoSink.h
deleted file mode 100644
index 2705f48d59..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/InfoSink.h
+++ /dev/null
@@ -1,120 +0,0 @@
-//
-// Copyright (c) 2002-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_INFOSINK_H_
-#define COMPILER_TRANSLATOR_INFOSINK_H_
-
-#include <math.h>
-#include <stdlib.h>
-#include "compiler/translator/Common.h"
-#include "compiler/translator/Severity.h"
-
-namespace sh
-{
-
-// Returns the fractional part of the given floating-point number.
-inline float fractionalPart(float f)
-{
- float intPart = 0.0f;
- return modff(f, &intPart);
-}
-
-//
-// 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 <typename T>
- TInfoSinkBase &operator<<(const T &t)
- {
- TPersistStringStream stream;
- 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;
- }
- // 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;
- 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(); }
- int size() { return static_cast<int>(sink.size()); }
-
- const TPersistString &str() const { return sink; }
- const char *c_str() const { return sink.c_str(); }
-
- void prefix(Severity severity);
- void location(int file, int line);
-
- private:
- TPersistString sink;
-};
-
-class TInfoSink
-{
- public:
- TInfoSinkBase info;
- TInfoSinkBase debug;
- TInfoSinkBase obj;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_INFOSINK_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp
deleted file mode 100644
index 6f8baee96b..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp
+++ /dev/null
@@ -1,1135 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-//
-// Create symbols that declare built-in definitions, add built-ins that
-// cannot be expressed in the files, and establish mappings between
-// built-in functions and operators.
-//
-
-#include "compiler/translator/Initialize.h"
-#include "compiler/translator/Cache.h"
-
-#include "compiler/translator/IntermNode.h"
-#include "angle_gl.h"
-
-namespace sh
-{
-
-void InsertBuiltInFunctions(sh::GLenum type,
- ShShaderSpec spec,
- const ShBuiltInResources &resources,
- TSymbolTable &symbolTable)
-{
- const TType *voidType = TCache::getType(EbtVoid);
- const TType *float1 = TCache::getType(EbtFloat);
- const TType *float2 = TCache::getType(EbtFloat, 2);
- const TType *float3 = TCache::getType(EbtFloat, 3);
- const TType *float4 = TCache::getType(EbtFloat, 4);
- const TType *int1 = TCache::getType(EbtInt);
- const TType *int2 = TCache::getType(EbtInt, 2);
- const TType *int3 = TCache::getType(EbtInt, 3);
- const TType *uint1 = TCache::getType(EbtUInt);
- const TType *bool1 = TCache::getType(EbtBool);
- const TType *genType = TCache::getType(EbtGenType);
- const TType *genIType = TCache::getType(EbtGenIType);
- const TType *genUType = TCache::getType(EbtGenUType);
- const TType *genBType = TCache::getType(EbtGenBType);
-
- //
- // Angle and Trigonometric Functions.
- //
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpRadians, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDegrees, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSin, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCos, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpTan, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAsin, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAcos, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAtan, genType, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAtan, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpSinh, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpCosh, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTanh, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAsinh, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAcosh, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAtanh, genType, genType);
-
- //
- // Exponential Functions.
- //
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpPow, genType, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpExp, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLog, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpExp2, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLog2, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSqrt, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpInverseSqrt, genType, genType);
-
- //
- // Common Functions.
- //
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAbs, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAbs, genIType, genIType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSign, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpSign, genIType, genIType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFloor, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTrunc, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpRound, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpRoundEven, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCeil, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFract, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMod, genType, genType, float1);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMod, genType, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMin, genType, genType, float1);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMin, genType, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genIType, genIType, genIType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genIType, genIType, int1);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genUType, genUType, genUType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genUType, genUType, uint1);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMax, genType, genType, float1);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMax, genType, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genIType, genIType, genIType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genIType, genIType, int1);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genUType, genUType, genUType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genUType, genUType, uint1);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpClamp, genType, genType, float1, float1);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpClamp, genType, genType, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genIType, genIType, int1, int1);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genIType, genIType, genIType, genIType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genUType, genUType, uint1, uint1);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genUType, genUType, genUType, genUType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMix, genType, genType, genType, float1);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMix, genType, genType, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMix, genType, genType, genType, genBType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpStep, genType, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpStep, genType, float1, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSmoothStep, genType, genType, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSmoothStep, genType, float1, float1, genType);
-
- const TType *outGenType = TCache::getType(EbtGenType, EvqOut);
- const TType *outGenIType = TCache::getType(EbtGenIType, EvqOut);
-
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpModf, genType, genType, outGenType);
-
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIsNan, genBType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIsInf, genBType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFloatBitsToInt, genIType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFloatBitsToUint, genUType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIntBitsToFloat, genType, genIType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUintBitsToFloat, genType, genUType);
-
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFrexp, genType, genType, outGenIType);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpLdexp, genType, genType, genIType);
-
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackSnorm2x16, uint1, float2);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackUnorm2x16, uint1, float2);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackHalf2x16, uint1, float2);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackSnorm2x16, float2, uint1);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackUnorm2x16, float2, uint1);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackHalf2x16, float2, uint1);
-
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpPackUnorm4x8, uint1, float4);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpPackSnorm4x8, uint1, float4);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUnpackUnorm4x8, float4, uint1);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUnpackSnorm4x8, float4, uint1);
-
- //
- // Geometric Functions.
- //
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLength, float1, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDistance, float1, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDot, float1, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCross, float3, float3, float3);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNormalize, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFaceforward, genType, genType, genType,
- genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpReflect, genType, genType, genType);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpRefract, genType, genType, genType, float1);
-
- const TType *mat2 = TCache::getType(EbtFloat, 2, 2);
- const TType *mat3 = TCache::getType(EbtFloat, 3, 3);
- const TType *mat4 = TCache::getType(EbtFloat, 4, 4);
- const TType *mat2x3 = TCache::getType(EbtFloat, 2, 3);
- const TType *mat3x2 = TCache::getType(EbtFloat, 3, 2);
- const TType *mat2x4 = TCache::getType(EbtFloat, 2, 4);
- const TType *mat4x2 = TCache::getType(EbtFloat, 4, 2);
- const TType *mat3x4 = TCache::getType(EbtFloat, 3, 4);
- const TType *mat4x3 = TCache::getType(EbtFloat, 4, 3);
-
- //
- // Matrix Functions.
- //
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat2, mat2, mat2);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat3, mat3, mat3);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat4, mat4, mat4);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat2x3, mat2x3, mat2x3);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat3x2, mat3x2, mat3x2);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat2x4, mat2x4, mat2x4);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat4x2, mat4x2, mat4x2);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat3x4, mat3x4, mat3x4);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat4x3, mat4x3, mat4x3);
-
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2, float2, float2);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3, float3, float3);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4, float4, float4);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2x3, float3, float2);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3x2, float2, float3);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2x4, float4, float2);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4x2, float2, float4);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3x4, float4, float3);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4x3, float3, float4);
-
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2, mat2);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3, mat3);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4, mat4);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2x3, mat3x2);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3x2, mat2x3);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2x4, mat4x2);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4x2, mat2x4);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3x4, mat4x3);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4x3, mat3x4);
-
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat2);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat3);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat4);
-
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat2, mat2);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat3, mat3);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat4, mat4);
-
- const TType *vec = TCache::getType(EbtVec);
- const TType *ivec = TCache::getType(EbtIVec);
- const TType *uvec = TCache::getType(EbtUVec);
- const TType *bvec = TCache::getType(EbtBVec);
-
- //
- // Vector relational functions.
- //
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanComponentWise, bvec, vec, vec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanComponentWise, bvec, ivec, ivec);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpLessThanComponentWise, bvec, uvec, uvec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanEqualComponentWise, bvec, vec, vec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanEqualComponentWise, bvec, ivec, ivec);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpLessThanEqualComponentWise, bvec, uvec, uvec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanComponentWise, bvec, vec, vec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanComponentWise, bvec, ivec, ivec);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpGreaterThanComponentWise, bvec, uvec, uvec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, vec, vec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, ivec,
- ivec);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, uvec, uvec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, vec, vec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, ivec, ivec);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpEqualComponentWise, bvec, uvec, uvec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, bvec, bvec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, vec, vec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, ivec, ivec);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpNotEqualComponentWise, bvec, uvec, uvec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, bvec, bvec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAny, bool1, bvec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAll, bool1, bvec);
- symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLogicalNotComponentWise, bvec, bvec);
-
- //
- // Integer functions
- //
- const TType *outGenUType = TCache::getType(EbtGenUType, EvqOut);
-
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldExtract, genIType, genIType, int1,
- int1);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldExtract, genUType, genUType, int1,
- int1);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldInsert, genIType, genIType, genIType,
- int1, int1);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldInsert, genUType, genUType, genUType,
- int1, int1);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldReverse, genIType, genIType);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldReverse, genUType, genUType);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitCount, genIType, genIType);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitCount, genIType, genUType);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindLSB, genIType, genIType);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindLSB, genIType, genUType);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindMSB, genIType, genIType);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindMSB, genIType, genUType);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUaddCarry, genUType, genUType, genUType,
- outGenUType);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUsubBorrow, genUType, genUType, genUType,
- outGenUType);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUmulExtended, voidType, genUType, genUType,
- outGenUType, outGenUType);
- symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpImulExtended, voidType, genIType, genIType,
- outGenIType, outGenIType);
-
- const TType *sampler2D = TCache::getType(EbtSampler2D);
- const TType *samplerCube = TCache::getType(EbtSamplerCube);
-
- //
- // Texture Functions for GLSL ES 1.0
- //
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3);
-
- if (resources.OES_EGL_image_external || resources.NV_EGL_stream_consumer_external)
- {
- const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
-
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", samplerExternalOES, float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES,
- float3);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES,
- float4);
- }
-
- if (resources.ARB_texture_rectangle)
- {
- const TType *sampler2DRect = TCache::getType(EbtSampler2DRect);
-
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRect", sampler2DRect, float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect,
- float3);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect,
- float4);
- }
-
- if (resources.EXT_shader_texture_lod)
- {
- /* The *Grad* variants are new to both vertex and fragment shaders; the fragment
- * shader specific pieces are added separately below.
- */
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
- "texture2DGradEXT", sampler2D, float2, float2, float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
- "texture2DProjGradEXT", sampler2D, float3, float2, float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
- "texture2DProjGradEXT", sampler2D, float4, float2, float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
- "textureCubeGradEXT", samplerCube, float3, float3, float3);
- }
-
- if (type == GL_FRAGMENT_SHADER)
- {
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3,
- float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4,
- float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3,
- float1);
-
- if (resources.OES_standard_derivatives)
- {
- symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpDFdx,
- TExtension::OES_standard_derivatives, genType, genType);
- symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpDFdy,
- TExtension::OES_standard_derivatives, genType, genType);
- symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpFwidth,
- TExtension::OES_standard_derivatives, genType, genType);
- }
-
- if (resources.EXT_shader_texture_lod)
- {
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
- "texture2DLodEXT", sampler2D, float2, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
- "texture2DProjLodEXT", sampler2D, float3, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
- "texture2DProjLodEXT", sampler2D, float4, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
- "textureCubeLodEXT", samplerCube, float3, float1);
- }
- }
-
- if (type == GL_VERTEX_SHADER)
- {
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLod", sampler2D, float2,
- float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float3,
- float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float4,
- float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeLod", samplerCube, float3,
- float1);
- }
-
- const TType *gvec4 = TCache::getType(EbtGVec4);
-
- const TType *gsampler2D = TCache::getType(EbtGSampler2D);
- const TType *gsamplerCube = TCache::getType(EbtGSamplerCube);
- const TType *gsampler3D = TCache::getType(EbtGSampler3D);
- const TType *gsampler2DArray = TCache::getType(EbtGSampler2DArray);
- const TType *gsampler2DMS = TCache::getType(EbtGSampler2DMS);
-
- //
- // Texture Functions for GLSL ES 3.0
- //
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2D, float2, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler3D, float3, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsamplerCube, float3, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2DArray, float3, float1);
-
- if (resources.OES_EGL_image_external_essl3)
- {
- const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texture", samplerExternalOES, float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
- float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
- float4);
- }
-
- if (resources.EXT_YUV_target)
- {
- const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texture",
- samplerExternal2DY2YEXT, float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "textureProj",
- samplerExternal2DY2YEXT, float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "textureProj",
- samplerExternal2DY2YEXT, float4);
-
- const TType *yuvCscStandardEXT = TCache::getType(EbtYuvCscStandardEXT);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float3, "rgb_2_yuv",
- float3, yuvCscStandardEXT);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float3, "yuv_2_rgb",
- float3, yuvCscStandardEXT);
- }
-
- if (type == GL_FRAGMENT_SHADER)
- {
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3,
- float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4, float1);
-
- if (resources.OES_EGL_image_external_essl3)
- {
- const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texture", samplerExternalOES, float2,
- float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
- float3, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
- float4, float1);
- }
-
- if (resources.EXT_YUV_target)
- {
- const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texture",
- samplerExternal2DY2YEXT, float2, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4,
- "textureProj", samplerExternal2DY2YEXT, float3, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4,
- "textureProj", samplerExternal2DY2YEXT, float4, float1);
- }
- }
-
- const TType *sampler2DShadow = TCache::getType(EbtSampler2DShadow);
- const TType *samplerCubeShadow = TCache::getType(EbtSamplerCubeShadow);
- const TType *sampler2DArrayShadow = TCache::getType(EbtSampler2DArrayShadow);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DArrayShadow, float4);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProj", sampler2DShadow, float4);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLod", sampler2DShadow, float3,
- float1);
-
- if (type == GL_FRAGMENT_SHADER)
- {
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3,
- float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4,
- float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProj", sampler2DShadow, float4,
- float1);
- }
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsampler2D, int1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", gsampler3D, int1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsamplerCube, int1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", gsampler2DArray, int1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", sampler2DShadow, int1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerCubeShadow, int1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", sampler2DArrayShadow, int1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsampler2DMS);
-
- if (resources.OES_EGL_image_external_essl3)
- {
- const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerExternalOES, int1);
- }
-
- if (resources.EXT_YUV_target)
- {
- const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, int2, "textureSize",
- samplerExternal2DY2YEXT, int1);
- }
-
- if (type == GL_FRAGMENT_SHADER)
- {
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDFdx, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDFdy, genType, genType);
- symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFwidth, genType, genType);
- }
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3,
- int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3,
- int2);
-
- if (type == GL_FRAGMENT_SHADER)
- {
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2,
- float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3,
- float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3,
- int2, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3,
- int2, float1);
- }
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, int3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, float4,
- int2);
-
- if (type == GL_FRAGMENT_SHADER)
- {
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3,
- int2, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4,
- int2, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4,
- int3, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow,
- float4, int2, float1);
- }
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler2D, float2, float1,
- int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler3D, float3, float1,
- int3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLodOffset", sampler2DShadow, float3,
- float1, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler2DArray, float3,
- float1, int2);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler2D, float3, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler2D, float4, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler3D, float4, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjLod", sampler2DShadow, float4,
- float1);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler2D, float3,
- float1, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler2D, float4,
- float1, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler3D, float4,
- float1, int3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjLodOffset", sampler2DShadow,
- float4, float1, int2);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler2D, int2, int1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler3D, int3, int1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler2DArray, int3, int1);
-
- if (resources.OES_EGL_image_external_essl3)
- {
- const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texelFetch", samplerExternalOES, int2,
- int1);
- }
-
- if (resources.EXT_YUV_target)
- {
- const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texelFetch",
- samplerExternal2DY2YEXT, int2, int1);
- }
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2D, int2, int1,
- int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler3D, int3, int1,
- int3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2DArray, int3,
- int1, int2);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler2D, float2, float2,
- float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler3D, float3, float3,
- float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsamplerCube, float3, float3,
- float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", sampler2DShadow, float3,
- float2, float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", samplerCubeShadow, float4,
- float3, float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler2DArray, float3, float2,
- float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", sampler2DArrayShadow, float4,
- float2, float2);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler2D, float2,
- float2, float2, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler3D, float3,
- float3, float3, int3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGradOffset", sampler2DShadow, float3,
- float2, float2, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler2DArray, float3,
- float2, float2, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGradOffset", sampler2DArrayShadow,
- float4, float2, float2, int2);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler2D, float3, float2,
- float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler2D, float4, float2,
- float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler3D, float4, float3,
- float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGrad", sampler2DShadow, float4,
- float2, float2);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler2D, float3,
- float2, float2, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler2D, float4,
- float2, float2, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler3D, float4,
- float3, float3, int3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGradOffset", sampler2DShadow,
- float4, float2, float2, int2);
-
- const TType *atomicCounter = TCache::getType(EbtAtomicCounter);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounter", atomicCounter);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounterIncrement", atomicCounter);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounterDecrement", atomicCounter);
-
- // Insert all atomic memory functions
- const TType *int1InOut = TCache::getType(EbtInt, EvqInOut);
- const TType *uint1InOut = TCache::getType(EbtUInt, EvqInOut);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicAdd", uint1InOut, uint1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicAdd", int1InOut, int1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicMin", uint1InOut, uint1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicMin", int1InOut, int1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicMax", uint1InOut, uint1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicMax", int1InOut, int1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicAnd", uint1InOut, uint1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicAnd", int1InOut, int1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicOr", uint1InOut, uint1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicOr", int1InOut, int1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicXor", uint1InOut, uint1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicXor", int1InOut, int1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicExchange", uint1InOut, uint1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicExchange", int1InOut, int1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCompSwap", uint1InOut, uint1, uint1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicCompSwap", int1InOut, int1, int1);
-
- const TType *gimage2D = TCache::getType(EbtGImage2D);
- const TType *gimage3D = TCache::getType(EbtGImage3D);
- const TType *gimage2DArray = TCache::getType(EbtGImage2DArray);
- const TType *gimageCube = TCache::getType(EbtGImageCube);
-
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage2D, int2, gvec4);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage3D, int3, gvec4);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage2DArray, int3, gvec4);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimageCube, int3, gvec4);
-
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage2D, int2);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage3D, int3);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage2DArray, int3);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimageCube, int3);
-
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int2, "imageSize", gimage2D);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage3D);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage2DArray);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int2, "imageSize", gimageCube);
-
- symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrier, voidType,
- "memoryBarrier");
- symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierAtomicCounter,
- voidType, "memoryBarrierAtomicCounter");
- symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierBuffer,
- voidType, "memoryBarrierBuffer");
- symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierImage, voidType,
- "memoryBarrierImage");
-
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "texelFetch", gsampler2DMS, int2, int1);
-
- // Insert all variations of textureGather.
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2D, float2);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2D, float2, int1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2DArray, float3);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2DArray, float3,
- int1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsamplerCube, float3);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsamplerCube, float3, int1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DShadow, float2);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DShadow, float2,
- float1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DArrayShadow,
- float3);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DArrayShadow,
- float3, float1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", samplerCubeShadow, float3);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", samplerCubeShadow, float3,
- float1);
-
- // Insert all variations of textureGatherOffset.
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2D, float2,
- int2);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2D, float2,
- int2, int1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2DArray,
- float3, int2);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2DArray,
- float3, int2, int1);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGatherOffset", sampler2DShadow,
- float2, float1, int2);
- symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGatherOffset", sampler2DArrayShadow,
- float3, float1, int2);
-
- if (type == GL_COMPUTE_SHADER)
- {
- symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpBarrier, voidType,
- "barrier");
- symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierShared,
- voidType, "memoryBarrierShared");
- symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpGroupMemoryBarrier,
- voidType, "groupMemoryBarrier");
- }
-
- if (type == GL_GEOMETRY_SHADER_OES)
- {
- TExtension extension = TExtension::OES_geometry_shader;
- symbolTable.insertBuiltInFunctionNoParametersExt(ESSL3_1_BUILTINS, extension, EOpEmitVertex,
- voidType, "EmitVertex");
- symbolTable.insertBuiltInFunctionNoParametersExt(ESSL3_1_BUILTINS, extension,
- EOpEndPrimitive, voidType, "EndPrimitive");
- }
-
- //
- // Depth range in window coordinates
- //
- TFieldList *fields = NewPoolTFieldList();
- TSourceLoc zeroSourceLoc = {0, 0, 0, 0};
- auto highpFloat1 = new TType(EbtFloat, EbpHigh, EvqGlobal, 1);
- TField *near = new TField(highpFloat1, NewPoolTString("near"), zeroSourceLoc);
- TField *far = new TField(highpFloat1, NewPoolTString("far"), zeroSourceLoc);
- TField *diff = new TField(highpFloat1, NewPoolTString("diff"), zeroSourceLoc);
- fields->push_back(near);
- fields->push_back(far);
- fields->push_back(diff);
- TStructure *depthRangeStruct =
- new TStructure(&symbolTable, NewPoolTString("gl_DepthRangeParameters"), fields);
- symbolTable.insertStructType(COMMON_BUILTINS, depthRangeStruct);
- TType depthRangeType(depthRangeStruct);
- depthRangeType.setQualifier(EvqUniform);
- symbolTable.insertVariable(COMMON_BUILTINS, "gl_DepthRange", depthRangeType);
-
- //
- // Implementation dependent built-in constants.
- //
- symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexAttribs", resources.MaxVertexAttribs,
- EbpMedium);
- symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexUniformVectors",
- resources.MaxVertexUniformVectors, EbpMedium);
- symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexTextureImageUnits",
- resources.MaxVertexTextureImageUnits, EbpMedium);
- symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxCombinedTextureImageUnits",
- resources.MaxCombinedTextureImageUnits, EbpMedium);
- symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxTextureImageUnits",
- resources.MaxTextureImageUnits, EbpMedium);
- symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxFragmentUniformVectors",
- resources.MaxFragmentUniformVectors, EbpMedium);
-
- symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxVaryingVectors", resources.MaxVaryingVectors,
- EbpMedium);
-
- symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers,
- EbpMedium);
- if (resources.EXT_blend_func_extended)
- {
- symbolTable.insertConstIntExt(COMMON_BUILTINS, TExtension::EXT_blend_func_extended,
- "gl_MaxDualSourceDrawBuffersEXT",
- resources.MaxDualSourceDrawBuffers, EbpMedium);
- }
-
- symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors",
- resources.MaxVertexOutputVectors, EbpMedium);
- symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxFragmentInputVectors",
- resources.MaxFragmentInputVectors, EbpMedium);
- symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MinProgramTexelOffset",
- resources.MinProgramTexelOffset, EbpMedium);
- symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxProgramTexelOffset",
- resources.MaxProgramTexelOffset, EbpMedium);
-
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxImageUnits", resources.MaxImageUnits,
- EbpMedium);
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexImageUniforms",
- resources.MaxVertexImageUniforms, EbpMedium);
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentImageUniforms",
- resources.MaxFragmentImageUniforms, EbpMedium);
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeImageUniforms",
- resources.MaxComputeImageUniforms, EbpMedium);
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedImageUniforms",
- resources.MaxCombinedImageUniforms, EbpMedium);
-
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedShaderOutputResources",
- resources.MaxCombinedShaderOutputResources, EbpMedium);
-
- symbolTable.insertConstIvec3(ESSL3_1_BUILTINS, "gl_MaxComputeWorkGroupCount",
- resources.MaxComputeWorkGroupCount, EbpHigh);
- symbolTable.insertConstIvec3(ESSL3_1_BUILTINS, "gl_MaxComputeWorkGroupSize",
- resources.MaxComputeWorkGroupSize, EbpHigh);
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeUniformComponents",
- resources.MaxComputeUniformComponents, EbpMedium);
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeTextureImageUnits",
- resources.MaxComputeTextureImageUnits, EbpMedium);
-
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeAtomicCounters",
- resources.MaxComputeAtomicCounters, EbpMedium);
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeAtomicCounterBuffers",
- resources.MaxComputeAtomicCounterBuffers, EbpMedium);
-
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexAtomicCounters",
- resources.MaxVertexAtomicCounters, EbpMedium);
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentAtomicCounters",
- resources.MaxFragmentAtomicCounters, EbpMedium);
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedAtomicCounters",
- resources.MaxCombinedAtomicCounters, EbpMedium);
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxAtomicCounterBindings",
- resources.MaxAtomicCounterBindings, EbpMedium);
-
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexAtomicCounterBuffers",
- resources.MaxVertexAtomicCounterBuffers, EbpMedium);
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentAtomicCounterBuffers",
- resources.MaxFragmentAtomicCounterBuffers, EbpMedium);
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedAtomicCounterBuffers",
- resources.MaxCombinedAtomicCounterBuffers, EbpMedium);
- symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxAtomicCounterBufferSize",
- resources.MaxAtomicCounterBufferSize, EbpMedium);
-
- if (resources.OES_geometry_shader)
- {
- TExtension ext = TExtension::OES_geometry_shader;
- symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryInputComponents",
- resources.MaxGeometryInputComponents, EbpMedium);
- symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryOutputComponents",
- resources.MaxGeometryOutputComponents, EbpMedium);
- symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryImageUniforms",
- resources.MaxGeometryImageUniforms, EbpMedium);
- symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryTextureImageUnits",
- resources.MaxGeometryTextureImageUnits, EbpMedium);
- symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryOutputVertices",
- resources.MaxGeometryOutputVertices, EbpMedium);
- symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryTotalOutputComponents",
- resources.MaxGeometryTotalOutputComponents, EbpMedium);
- symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryUniformComponents",
- resources.MaxGeometryUniformComponents, EbpMedium);
- symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryAtomicCounters",
- resources.MaxGeometryAtomicCounters, EbpMedium);
- symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryAtomicCounterBuffers",
- resources.MaxGeometryAtomicCounterBuffers, EbpMedium);
- }
-}
-
-void IdentifyBuiltIns(sh::GLenum type,
- ShShaderSpec spec,
- const ShBuiltInResources &resources,
- TSymbolTable &symbolTable)
-{
- //
- // Insert some special built-in variables that are not in
- // the built-in header files.
- //
-
- if (resources.OVR_multiview && type != GL_COMPUTE_SHADER)
- {
- symbolTable.insertVariableExt(ESSL3_BUILTINS, TExtension::OVR_multiview, "gl_ViewID_OVR",
- TType(EbtUInt, EbpHigh, EvqViewIDOVR, 1));
-
- // ESSL 1.00 doesn't have unsigned integers, so gl_ViewID_OVR is a signed integer in ESSL
- // 1.00. This is specified in the WEBGL_multiview spec.
- symbolTable.insertVariableExt(ESSL1_BUILTINS, TExtension::OVR_multiview, "gl_ViewID_OVR",
- TType(EbtInt, EbpHigh, EvqViewIDOVR, 1));
- }
-
- switch (type)
- {
- case GL_FRAGMENT_SHADER:
- {
- symbolTable.insertVariable(COMMON_BUILTINS, "gl_FragCoord",
- TType(EbtFloat, EbpMedium, EvqFragCoord, 4));
- symbolTable.insertVariable(COMMON_BUILTINS, "gl_FrontFacing",
- TType(EbtBool, EbpUndefined, EvqFrontFacing, 1));
- symbolTable.insertVariable(COMMON_BUILTINS, "gl_PointCoord",
- TType(EbtFloat, EbpMedium, EvqPointCoord, 2));
-
- symbolTable.insertVariable(ESSL1_BUILTINS, "gl_FragColor",
- TType(EbtFloat, EbpMedium, EvqFragColor, 4));
- TType fragData(EbtFloat, EbpMedium, EvqFragData, 4);
- if (spec != SH_WEBGL2_SPEC && spec != SH_WEBGL3_SPEC)
- {
- fragData.makeArray(resources.MaxDrawBuffers);
- }
- else
- {
- fragData.makeArray(1u);
- }
- symbolTable.insertVariable(ESSL1_BUILTINS, "gl_FragData", fragData);
-
- if (resources.EXT_blend_func_extended)
- {
- symbolTable.insertVariableExt(
- ESSL1_BUILTINS, TExtension::EXT_blend_func_extended, "gl_SecondaryFragColorEXT",
- TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4));
- TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1);
- secondaryFragData.makeArray(resources.MaxDualSourceDrawBuffers);
- symbolTable.insertVariableExt(ESSL1_BUILTINS, TExtension::EXT_blend_func_extended,
- "gl_SecondaryFragDataEXT", secondaryFragData);
- }
-
- if (resources.EXT_frag_depth)
- {
- symbolTable.insertVariableExt(
- ESSL1_BUILTINS, TExtension::EXT_frag_depth, "gl_FragDepthEXT",
- TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium,
- EvqFragDepthEXT, 1));
- }
-
- symbolTable.insertVariable(ESSL3_BUILTINS, "gl_FragDepth",
- TType(EbtFloat, EbpHigh, EvqFragDepth, 1));
-
- if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch)
- {
- TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1);
- lastFragData.makeArray(resources.MaxDrawBuffers);
-
- if (resources.EXT_shader_framebuffer_fetch)
- {
- symbolTable.insertVariableExt(ESSL1_BUILTINS,
- TExtension::EXT_shader_framebuffer_fetch,
- "gl_LastFragData", lastFragData);
- }
- else if (resources.NV_shader_framebuffer_fetch)
- {
- symbolTable.insertVariableExt(
- ESSL1_BUILTINS, TExtension::NV_shader_framebuffer_fetch, "gl_LastFragColor",
- TType(EbtFloat, EbpMedium, EvqLastFragColor, 4));
- symbolTable.insertVariableExt(ESSL1_BUILTINS,
- TExtension::NV_shader_framebuffer_fetch,
- "gl_LastFragData", lastFragData);
- }
- }
- else if (resources.ARM_shader_framebuffer_fetch)
- {
- symbolTable.insertVariableExt(
- ESSL1_BUILTINS, TExtension::ARM_shader_framebuffer_fetch, "gl_LastFragColorARM",
- TType(EbtFloat, EbpMedium, EvqLastFragColor, 4));
- }
-
- if (resources.OES_geometry_shader)
- {
- TExtension extension = TExtension::OES_geometry_shader;
- symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveID",
- TType(EbtInt, EbpHigh, EvqPrimitiveID, 1));
- symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Layer",
- TType(EbtInt, EbpHigh, EvqLayer, 1));
- }
-
- break;
- }
- case GL_VERTEX_SHADER:
- {
- symbolTable.insertVariable(COMMON_BUILTINS, "gl_Position",
- TType(EbtFloat, EbpHigh, EvqPosition, 4));
- symbolTable.insertVariable(COMMON_BUILTINS, "gl_PointSize",
- TType(EbtFloat, EbpMedium, EvqPointSize, 1));
- symbolTable.insertVariable(ESSL3_BUILTINS, "gl_InstanceID",
- TType(EbtInt, EbpHigh, EvqInstanceID, 1));
- symbolTable.insertVariable(ESSL3_BUILTINS, "gl_VertexID",
- TType(EbtInt, EbpHigh, EvqVertexID, 1));
-
- // For internal use by ANGLE - not exposed to the parser.
- symbolTable.insertVariable(GLSL_BUILTINS, "gl_ViewportIndex",
- TType(EbtInt, EbpHigh, EvqViewportIndex));
- // gl_Layer exists in other shader stages in ESSL, but not in vertex shader so far.
- symbolTable.insertVariable(GLSL_BUILTINS, "gl_Layer", TType(EbtInt, EbpHigh, EvqLayer));
- break;
- }
- case GL_COMPUTE_SHADER:
- {
- symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_NumWorkGroups",
- TType(EbtUInt, EbpUndefined, EvqNumWorkGroups, 3));
- symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_WorkGroupSize",
- TType(EbtUInt, EbpUndefined, EvqWorkGroupSize, 3));
- symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_WorkGroupID",
- TType(EbtUInt, EbpUndefined, EvqWorkGroupID, 3));
- symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_LocalInvocationID",
- TType(EbtUInt, EbpUndefined, EvqLocalInvocationID, 3));
- symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_GlobalInvocationID",
- TType(EbtUInt, EbpUndefined, EvqGlobalInvocationID, 3));
- symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_LocalInvocationIndex",
- TType(EbtUInt, EbpUndefined, EvqLocalInvocationIndex, 1));
- break;
- }
-
- case GL_GEOMETRY_SHADER_OES:
- {
- TExtension extension = TExtension::OES_geometry_shader;
-
- // Add built-in interface block gl_PerVertex and the built-in array gl_in.
- // TODO(jiawei.shao@intel.com): implement GL_OES_geometry_point_size.
- const TString *glPerVertexString = NewPoolTString("gl_PerVertex");
- symbolTable.insertInterfaceBlockNameExt(ESSL3_1_BUILTINS, extension, glPerVertexString);
-
- TFieldList *fieldList = NewPoolTFieldList();
- TSourceLoc zeroSourceLoc = {0, 0, 0, 0};
- TField *glPositionField = new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4),
- NewPoolTString("gl_Position"), zeroSourceLoc);
- fieldList->push_back(glPositionField);
-
- TInterfaceBlock *glInBlock = new TInterfaceBlock(
- glPerVertexString, fieldList, NewPoolTString("gl_in"), TLayoutQualifier::Create());
-
- // The array size of gl_in is undefined until we get a valid input primitive
- // declaration.
- TType glInType(glInBlock, EvqPerVertexIn, TLayoutQualifier::Create());
- glInType.makeArray(0u);
- symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_in", glInType);
-
- TType glPositionType(EbtFloat, EbpHigh, EvqPosition, 4);
- glPositionType.setInterfaceBlock(new TInterfaceBlock(
- glPerVertexString, fieldList, nullptr, TLayoutQualifier::Create()));
- symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Position",
- glPositionType);
- symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveIDIn",
- TType(EbtInt, EbpHigh, EvqPrimitiveIDIn, 1));
- symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_InvocationID",
- TType(EbtInt, EbpHigh, EvqInvocationID, 1));
- symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveID",
- TType(EbtInt, EbpHigh, EvqPrimitiveID, 1));
- symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Layer",
- TType(EbtInt, EbpHigh, EvqLayer, 1));
-
- break;
- }
- default:
- UNREACHABLE();
- }
-}
-
-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_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.NV_shader_framebuffer_fetch)
- {
- extBehavior[TExtension::NV_shader_framebuffer_fetch] = 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.EXT_YUV_target)
- {
- extBehavior[TExtension::EXT_YUV_target] = EBhUndefined;
- }
- if (resources.OES_geometry_shader)
- {
- extBehavior[TExtension::OES_geometry_shader] = EBhUndefined;
- extBehavior[TExtension::EXT_geometry_shader] = EBhUndefined;
- }
-}
-
-void ResetExtensionBehavior(TExtensionBehavior &extBehavior)
-{
- for (auto &ext : extBehavior)
- {
- if (ext.first == TExtension::ARB_texture_rectangle)
- {
- ext.second = EBhEnable;
- }
- else
- {
- ext.second = EBhUndefined;
- }
- }
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.h b/src/3rdparty/angle/src/compiler/translator/Initialize.h
deleted file mode 100644
index 2e61218a0f..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Initialize.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#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 InsertBuiltInFunctions(sh::GLenum type,
- ShShaderSpec spec,
- const ShBuiltInResources &resources,
- TSymbolTable &table);
-
-void IdentifyBuiltIns(sh::GLenum type,
- ShShaderSpec spec,
- const ShBuiltInResources &resources,
- TSymbolTable &symbolTable);
-
-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(TExtensionBehavior &extensionBehavior);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_INITIALIZE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp
deleted file mode 100644
index 43c215f52b..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Copyright (c) 2002-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/Cache.h"
-#include "compiler/translator/InitializeDll.h"
-#include "compiler/translator/InitializeGlobals.h"
-
-#include "common/platform.h"
-
-#include <assert.h>
-
-namespace sh
-{
-
-bool InitProcess()
-{
- if (!InitializePoolIndex())
- {
- assert(0 && "InitProcess(): Failed to initalize global pool");
- return false;
- }
-
- TCache::initialize();
-
- return true;
-}
-
-void DetachProcess()
-{
- FreePoolIndex();
- TCache::destroy();
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h b/src/3rdparty/angle/src/compiler/translator/InitializeDll.h
deleted file mode 100644
index 87f7251470..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-// Copyright (c) 2002-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_INITIALIZEDLL_H_
-#define COMPILER_TRANSLATOR_INITIALIZEDLL_H_
-
-namespace sh
-{
-bool InitProcess();
-void DetachProcess();
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_INITIALIZEDLL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h b/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h
deleted file mode 100644
index 9a67ed0e04..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h
+++ /dev/null
@@ -1,13 +0,0 @@
-//
-// Copyright (c) 2002-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_INITIALIZEGLOBALS_H_
-#define COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_
-
-bool InitializePoolIndex();
-void FreePoolIndex();
-
-#endif // COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp
deleted file mode 100644
index aa1a042fac..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#include "compiler/translator/InitializeVariables.h"
-
-#include "angle_gl.h"
-#include "common/debug.h"
-#include "compiler/translator/FindMain.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/util.h"
-
-namespace sh
-{
-
-namespace
-{
-
-void AddArrayZeroInitSequence(const TIntermTyped *initializedNode,
- bool canUseLoopsToInitialize,
- TIntermSequence *initSequenceOut,
- TSymbolTable *symbolTable);
-
-void AddStructZeroInitSequence(const TIntermTyped *initializedNode,
- bool canUseLoopsToInitialize,
- 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,
- TIntermSequence *initSequenceOut,
- TSymbolTable *symbolTable)
-{
- if (initializedNode->isArray())
- {
- AddArrayZeroInitSequence(initializedNode, canUseLoopsToInitialize, initSequenceOut,
- symbolTable);
- }
- else if (initializedNode->getType().isStructureContainingArrays() ||
- initializedNode->getType().isNamelessStruct())
- {
- AddStructZeroInitSequence(initializedNode, canUseLoopsToInitialize, initSequenceOut,
- symbolTable);
- }
- else
- {
- initSequenceOut->push_back(CreateZeroInitAssignment(initializedNode));
- }
-}
-
-void AddStructZeroInitSequence(const TIntermTyped *initializedNode,
- bool canUseLoopsToInitialize,
- TIntermSequence *initSequenceOut,
- TSymbolTable *symbolTable)
-{
- ASSERT(initializedNode->getBasicType() == EbtStruct);
- const TStructure *structType = initializedNode->getType().getStruct();
- for (int i = 0; i < static_cast<int>(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, initSequenceOut, symbolTable);
- }
-}
-
-void AddArrayZeroInitStatementList(const TIntermTyped *initializedNode,
- bool canUseLoopsToInitialize,
- 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, initSequenceOut, symbolTable);
- }
-}
-
-void AddArrayZeroInitForLoop(const TIntermTyped *initializedNode,
- TIntermSequence *initSequenceOut,
- TSymbolTable *symbolTable)
-{
- ASSERT(initializedNode->isArray());
- TSymbolUniqueId indexSymbol(symbolTable);
-
- TIntermSymbol *indexSymbolNode = CreateTempSymbolNode(indexSymbol, TType(EbtInt), EvqTemporary);
- TIntermDeclaration *indexInit =
- CreateTempInitDeclarationNode(indexSymbol, CreateZeroNode(TType(EbtInt)), EvqTemporary);
- TIntermConstantUnion *arraySizeNode = CreateIndexNode(initializedNode->getOutermostArraySize());
- TIntermBinary *indexSmallerThanSize =
- new TIntermBinary(EOpLessThan, indexSymbolNode->deepCopy(), arraySizeNode);
- TIntermUnary *indexIncrement = new TIntermUnary(EOpPreIncrement, indexSymbolNode->deepCopy());
-
- TIntermBlock *forLoopBody = new TIntermBlock();
- TIntermSequence *forLoopBodySeq = forLoopBody->getSequence();
-
- TIntermBinary *element = new TIntermBinary(EOpIndexIndirect, initializedNode->deepCopy(),
- indexSymbolNode->deepCopy());
- AddZeroInitSequence(element, true, forLoopBodySeq, symbolTable);
-
- TIntermLoop *forLoop =
- new TIntermLoop(ELoopFor, indexInit, indexSmallerThanSize, indexIncrement, forLoopBody);
- initSequenceOut->push_back(forLoop);
-}
-
-void AddArrayZeroInitSequence(const TIntermTyped *initializedNode,
- bool canUseLoopsToInitialize,
- 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, initSequenceOut,
- symbolTable);
- }
- else
- {
- AddArrayZeroInitForLoop(initializedNode, initSequenceOut, symbolTable);
- }
-}
-
-void InsertInitCode(TIntermSequence *mainBody,
- const InitVariableList &variables,
- TSymbolTable *symbolTable,
- int shaderVersion,
- const TExtensionBehavior &extensionBehavior,
- bool canUseLoopsToInitialize)
-{
- for (const auto &var : variables)
- {
- TString name = TString(var.name.c_str());
- size_t pos = name.find_last_of('[');
- if (pos != TString::npos)
- {
- name = name.substr(0, pos);
- }
-
- TIntermTyped *initializedSymbol = nullptr;
- if (var.isBuiltIn())
- {
- initializedSymbol = ReferenceBuiltInVariable(name, *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
- {
- initializedSymbol = ReferenceGlobalVariable(name, *symbolTable);
- }
- ASSERT(initializedSymbol != nullptr);
-
- TIntermSequence *initCode =
- CreateInitCode(initializedSymbol, canUseLoopsToInitialize, symbolTable);
- mainBody->insert(mainBody->begin(), initCode->begin(), initCode->end());
- }
-}
-
-class InitializeLocalsTraverser : public TIntermTraverser
-{
- public:
- InitializeLocalsTraverser(int shaderVersion,
- TSymbolTable *symbolTable,
- bool canUseLoopsToInitialize)
- : TIntermTraverser(true, false, false, symbolTable),
- mShaderVersion(shaderVersion),
- mCanUseLoopsToInitialize(canUseLoopsToInitialize)
- {
- }
-
- 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->getSymbol() == "")
- {
- 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);
- insertStatementsInParentBlock(
- TIntermSequence(),
- *CreateInitCode(symbol, mCanUseLoopsToInitialize, mSymbolTable));
- }
- else
- {
- TIntermBinary *init =
- new TIntermBinary(EOpInitialize, symbol, CreateZeroNode(symbol->getType()));
- queueReplacementWithParent(node, symbol, init, OriginalNode::BECOMES_CHILD);
- }
- }
- }
- return false;
- }
-
- private:
- int mShaderVersion;
- bool mCanUseLoopsToInitialize;
-};
-
-} // namespace anonymous
-
-TIntermSequence *CreateInitCode(const TIntermTyped *initializedSymbol,
- bool canUseLoopsToInitialize,
- TSymbolTable *symbolTable)
-{
- TIntermSequence *initCode = new TIntermSequence();
- AddZeroInitSequence(initializedSymbol, canUseLoopsToInitialize, initCode, symbolTable);
- return initCode;
-}
-
-void InitializeUninitializedLocals(TIntermBlock *root,
- int shaderVersion,
- bool canUseLoopsToInitialize,
- TSymbolTable *symbolTable)
-{
- InitializeLocalsTraverser traverser(shaderVersion, symbolTable, canUseLoopsToInitialize);
- root->traverse(&traverser);
- traverser.updateTree();
-}
-
-void InitializeVariables(TIntermBlock *root,
- const InitVariableList &vars,
- TSymbolTable *symbolTable,
- int shaderVersion,
- const TExtensionBehavior &extensionBehavior,
- bool canUseLoopsToInitialize)
-{
- TIntermBlock *body = FindMainBody(root);
- InsertInitCode(body->getSequence(), vars, symbolTable, shaderVersion, extensionBehavior,
- canUseLoopsToInitialize);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h
deleted file mode 100644
index 1a7b3c0f24..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#ifndef COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
-#define COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
-
-#include <GLSLANG/ShaderLang.h>
-
-#include "compiler/translator/ExtensionBehavior.h"
-#include "compiler/translator/IntermNode.h"
-
-namespace sh
-{
-class TSymbolTable;
-
-typedef std::vector<sh::ShaderVariable> 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.
-
-// Return 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.
-TIntermSequence *CreateInitCode(const TIntermTyped *initializedSymbol,
- bool canUseLoopsToInitialize,
- TSymbolTable *symbolTable);
-
-// Initialize all uninitialized local variables, so that undefined behavior is avoided.
-void InitializeUninitializedLocals(TIntermBlock *root,
- int shaderVersion,
- bool canUseLoopsToInitialize,
- 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.
-void InitializeVariables(TIntermBlock *root,
- const InitVariableList &vars,
- TSymbolTable *symbolTable,
- int shaderVersion,
- const TExtensionBehavior &extensionBehavior,
- bool canUseLoopsToInitialize);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp
deleted file mode 100644
index a57ffcb4bc..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp
+++ /dev/null
@@ -1,3330 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-//
-// Build the intermediate representation.
-//
-
-#include <float.h>
-#include <limits.h>
-#include <math.h>
-#include <stdlib.h>
-#include <algorithm>
-#include <vector>
-
-#include "common/mathutil.h"
-#include "common/matrix_utils.h"
-#include "compiler/translator/Diagnostics.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 (unsigned int i = 0; i < size; ++i)
- constUnion[i] = constant;
-
- return constUnion;
-}
-
-void UndefinedConstantFoldingError(const TSourceLoc &loc,
- TOperator op,
- TBasicType basicType,
- TDiagnostics *diagnostics,
- TConstantUnion *result)
-{
- diagnostics->warning(loc, "operation result is undefined for the values passed in",
- GetOperatorString(op));
-
- 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,
- TQualifier qualifier)
-{
- if (constArray == nullptr)
- {
- return nullptr;
- }
- TIntermTyped *folded = new TIntermConstantUnion(constArray, originalNode->getType());
- folded->getTypePointer()->setQualifier(qualifier);
- folded->setLine(originalNode->getLine());
- return folded;
-}
-
-angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray,
- const unsigned int &rows,
- const unsigned int &cols)
-{
- std::vector<float> 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<float>(elements, cols, rows).transpose();
-}
-
-angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray, const unsigned int &size)
-{
- std::vector<float> 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<float>(elements, size).transpose();
-}
-
-void SetUnionArrayFromMatrix(const angle::Matrix<float> &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<float> result = m.transpose();
- std::vector<float> resultElements = result.elements();
- for (size_t i = 0; i < resultElements.size(); i++)
- resultArray[i].setFConst(resultElements[i]);
-}
-
-} // namespace anonymous
-
-////////////////////////////////////////////////////////////////
-//
-// Member functions of the nodes used for building the tree.
-//
-////////////////////////////////////////////////////////////////
-
-void TIntermTyped::setTypePreservePrecision(const TType &t)
-{
- TPrecision precision = getPrecision();
- mType = t;
- ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined);
- mType.setPrecision(precision);
-}
-
-#define REPLACE_IF_IS(node, type, original, replacement) \
- if (node == original) \
- { \
- node = static_cast<type *>(replacement); \
- return true; \
- }
-
-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;
-}
-
-bool TIntermBranch::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
-{
- REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement);
- return false;
-}
-
-bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
-{
- ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
- REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
- return false;
-}
-
-bool TIntermBinary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
-{
- REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement);
- REPLACE_IF_IS(mRight, TIntermTyped, original, replacement);
- return false;
-}
-
-bool TIntermUnary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
-{
- ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
- REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
- return false;
-}
-
-bool TIntermInvariantDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
-{
- REPLACE_IF_IS(mSymbol, TIntermSymbol, original, replacement);
- return false;
-}
-
-bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
-{
- REPLACE_IF_IS(mPrototype, TIntermFunctionPrototype, original, replacement);
- REPLACE_IF_IS(mBody, TIntermBlock, original, replacement);
- return false;
-}
-
-bool TIntermAggregate::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
-{
- return replaceChildNodeInternal(original, replacement);
-}
-
-bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
-{
- return replaceChildNodeInternal(original, replacement);
-}
-
-bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
-{
- return replaceChildNodeInternal(original, replacement);
-}
-
-bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
-{
- return replaceChildNodeInternal(original, replacement);
-}
-
-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;
-}
-
-TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TFunction &func,
- TIntermSequence *arguments)
-{
- TIntermAggregate *callNode =
- new TIntermAggregate(func.getReturnType(), EOpCallFunctionInAST, arguments);
- callNode->getFunctionSymbolInfo()->setFromFunction(func);
- return callNode;
-}
-
-TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TType &type,
- const TSymbolUniqueId &id,
- const TName &name,
- TIntermSequence *arguments)
-{
- TIntermAggregate *callNode = new TIntermAggregate(type, EOpCallFunctionInAST, arguments);
- callNode->getFunctionSymbolInfo()->setId(id);
- callNode->getFunctionSymbolInfo()->setNameObj(name);
- return callNode;
-}
-
-TIntermAggregate *TIntermAggregate::CreateBuiltInFunctionCall(const TFunction &func,
- TIntermSequence *arguments)
-{
- TIntermAggregate *callNode =
- new TIntermAggregate(func.getReturnType(), EOpCallBuiltInFunction, arguments);
- callNode->getFunctionSymbolInfo()->setFromFunction(func);
- // Note that name needs to be set before texture function type is determined.
- callNode->setBuiltInFunctionPrecision();
- return callNode;
-}
-
-TIntermAggregate *TIntermAggregate::CreateConstructor(const TType &type,
- TIntermSequence *arguments)
-{
- return new TIntermAggregate(type, EOpConstruct, arguments);
-}
-
-TIntermAggregate *TIntermAggregate::Create(const TType &type,
- TOperator op,
- TIntermSequence *arguments)
-{
- TIntermAggregate *node = new TIntermAggregate(type, op, arguments);
- ASSERT(op != EOpCallFunctionInAST); // Should use CreateFunctionCall
- ASSERT(op != EOpCallBuiltInFunction); // Should use CreateBuiltInFunctionCall
- ASSERT(!node->isConstructor()); // Should use CreateConstructor
- return node;
-}
-
-TIntermAggregate::TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments)
- : TIntermOperator(op), mUseEmulatedFunction(false), mGotPrecisionFromChildren(false)
-{
- if (arguments != nullptr)
- {
- mArguments.swap(*arguments);
- }
- setTypePrecisionAndQualifier(type);
-}
-
-void TIntermAggregate::setTypePrecisionAndQualifier(const TType &type)
-{
- setType(type);
- mType.setQualifier(EvqTemporary);
- if (!isFunctionCall())
- {
- if (isConstructor())
- {
- // Structs should not be precision qualified, the individual members may be.
- // Built-in types on the other hand should be precision qualified.
- if (getBasicType() != EbtStruct)
- {
- setPrecisionFromChildren();
- }
- }
- else
- {
- setPrecisionForBuiltInOp();
- }
- if (areChildrenConstQualified())
- {
- mType.setQualifier(EvqConst);
- }
- }
-}
-
-bool TIntermAggregate::areChildrenConstQualified()
-{
- for (TIntermNode *&arg : mArguments)
- {
- TIntermTyped *typedArg = arg->getAsTyped();
- if (typedArg && typedArg->getQualifier() != EvqConst)
- {
- return false;
- }
- }
- return true;
-}
-
-void TIntermAggregate::setPrecisionFromChildren()
-{
- mGotPrecisionFromChildren = true;
- if (getBasicType() == EbtBool)
- {
- mType.setPrecision(EbpUndefined);
- return;
- }
-
- TPrecision precision = EbpUndefined;
- TIntermSequence::iterator childIter = mArguments.begin();
- while (childIter != mArguments.end())
- {
- TIntermTyped *typed = (*childIter)->getAsTyped();
- if (typed)
- precision = GetHigherPrecision(typed->getPrecision(), precision);
- ++childIter;
- }
- mType.setPrecision(precision);
-}
-
-void TIntermAggregate::setPrecisionForBuiltInOp()
-{
- ASSERT(!isConstructor());
- ASSERT(!isFunctionCall());
- if (!setPrecisionForSpecialBuiltInOp())
- {
- setPrecisionFromChildren();
- }
-}
-
-bool TIntermAggregate::setPrecisionForSpecialBuiltInOp()
-{
- switch (mOp)
- {
- case EOpBitfieldExtract:
- mType.setPrecision(mArguments[0]->getAsTyped()->getPrecision());
- mGotPrecisionFromChildren = true;
- return true;
- case EOpBitfieldInsert:
- mType.setPrecision(GetHigherPrecision(mArguments[0]->getAsTyped()->getPrecision(),
- mArguments[1]->getAsTyped()->getPrecision()));
- mGotPrecisionFromChildren = true;
- return true;
- case EOpUaddCarry:
- case EOpUsubBorrow:
- mType.setPrecision(EbpHigh);
- return true;
- default:
- return false;
- }
-}
-
-void TIntermAggregate::setBuiltInFunctionPrecision()
-{
- // All built-ins returning bool should be handled as ops, not functions.
- ASSERT(getBasicType() != EbtBool);
- ASSERT(mOp == EOpCallBuiltInFunction);
-
- TPrecision precision = EbpUndefined;
- for (TIntermNode *arg : mArguments)
- {
- TIntermTyped *typed = arg->getAsTyped();
- // ESSL spec section 8: texture functions get their precision from the sampler.
- if (typed && IsSampler(typed->getBasicType()))
- {
- precision = typed->getPrecision();
- break;
- }
- }
- // ESSL 3.0 spec section 8: textureSize always gets highp precision.
- // All other functions that take a sampler are assumed to be texture functions.
- if (mFunctionInfo.getName().find("textureSize") == 0)
- mType.setPrecision(EbpHigh);
- else
- mType.setPrecision(precision);
-}
-
-TString TIntermAggregate::getSymbolTableMangledName() const
-{
- ASSERT(!isConstructor());
- switch (mOp)
- {
- case EOpCallInternalRawFunction:
- case EOpCallBuiltInFunction:
- case EOpCallFunctionInAST:
- return TFunction::GetMangledNameFromCall(mFunctionInfo.getName(), mArguments);
- default:
- TString opString = GetOperatorString(mOp);
- return TFunction::GetMangledNameFromCall(opString, mArguments);
- }
-}
-
-bool TIntermAggregate::hasSideEffects() const
-{
- if (isFunctionCall() && mFunctionInfo.isKnownToNotHaveSideEffects())
- {
- for (TIntermNode *arg : mArguments)
- {
- if (arg->getAsTyped()->hasSideEffects())
- {
- return true;
- }
- }
- return false;
- }
- // Conservatively assume most aggregate operators have side-effects
- return true;
-}
-
-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 TIntermFunctionPrototype::appendParameter(TIntermSymbol *parameter)
-{
- ASSERT(parameter != nullptr);
- mParameters.push_back(parameter);
-}
-
-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);
-}
-
-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;
-}
-
-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;
-}
-
-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;
-}
-
-bool TIntermCase::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
-{
- REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
- return false;
-}
-
-TIntermTyped::TIntermTyped(const TIntermTyped &node) : TIntermNode(), mType(node.mType)
-{
- // 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 besides handling fields in TIntermTyped.
- mLine = node.mLine;
-}
-
-bool TIntermTyped::isConstructorWithOnlyConstantUnionParameters()
-{
- TIntermAggregate *constructor = getAsAggregate();
- if (!constructor || !constructor->isConstructor())
- {
- return false;
- }
- for (TIntermNode *&node : *constructor->getSequence())
- {
- if (!node->getAsConstantUnion())
- return false;
- }
- return true;
-}
-
-TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) : TIntermTyped(node)
-{
- mUnionArrayPointer = node.mUnionArrayPointer;
-}
-
-void TFunctionSymbolInfo::setFromFunction(const TFunction &function)
-{
- setName(function.getName());
- setId(TSymbolUniqueId(function));
-}
-
-TFunctionSymbolInfo::TFunctionSymbolInfo(const TSymbolUniqueId &id)
- : mId(new TSymbolUniqueId(id)), mKnownToNotHaveSideEffects(false)
-{
-}
-
-TFunctionSymbolInfo::TFunctionSymbolInfo(const TFunctionSymbolInfo &info)
- : mName(info.mName), mId(nullptr), mKnownToNotHaveSideEffects(info.mKnownToNotHaveSideEffects)
-{
- if (info.mId)
- {
- mId = new TSymbolUniqueId(*info.mId);
- }
-}
-
-TFunctionSymbolInfo &TFunctionSymbolInfo::operator=(const TFunctionSymbolInfo &info)
-{
- mName = info.mName;
- if (info.mId)
- {
- mId = new TSymbolUniqueId(*info.mId);
- }
- else
- {
- mId = nullptr;
- }
- return *this;
-}
-
-void TFunctionSymbolInfo::setId(const TSymbolUniqueId &id)
-{
- mId = new TSymbolUniqueId(id);
-}
-
-const TSymbolUniqueId &TFunctionSymbolInfo::getId() const
-{
- ASSERT(mId);
- return *mId;
-}
-
-TIntermAggregate::TIntermAggregate(const TIntermAggregate &node)
- : TIntermOperator(node),
- mUseEmulatedFunction(node.mUseEmulatedFunction),
- mGotPrecisionFromChildren(node.mGotPrecisionFromChildren),
- mFunctionInfo(node.mFunctionInfo)
-{
- 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 = new TIntermSequence();
- copySeq->insert(copySeq->begin(), getSequence()->begin(), getSequence()->end());
- TIntermAggregate *copyNode = new TIntermAggregate(mType, mOp, copySeq);
- *copyNode->getFunctionSymbolInfo() = mFunctionInfo;
- copyNode->setLine(mLine);
- return copyNode;
-}
-
-TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermTyped(node)
-{
- TIntermTyped *operandCopy = node.mOperand->deepCopy();
- ASSERT(operandCopy != nullptr);
- mOperand = operandCopy;
- mSwizzleOffsets = node.mSwizzleOffsets;
-}
-
-TIntermBinary::TIntermBinary(const TIntermBinary &node)
- : TIntermOperator(node), mAddIndexClamp(node.mAddIndexClamp)
-{
- 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)
-{
- TIntermTyped *operandCopy = node.mOperand->deepCopy();
- ASSERT(operandCopy != nullptr);
- mOperand = operandCopy;
-}
-
-TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermTyped(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 EOpCallBuiltInFunction:
- 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, EbpUndefined, EvqConst));
- return;
- }
-
- TQualifier resultQualifier = EvqTemporary;
- if (mOperand->getQualifier() == EvqConst)
- resultQualifier = EvqConst;
-
- unsigned char operandPrimarySize =
- static_cast<unsigned char>(mOperand->getType().getNominalSize());
- switch (mOp)
- {
- case EOpFloatBitsToInt:
- setType(TType(EbtInt, EbpHigh, resultQualifier, operandPrimarySize));
- break;
- case EOpFloatBitsToUint:
- setType(TType(EbtUInt, EbpHigh, resultQualifier, operandPrimarySize));
- break;
- case EOpIntBitsToFloat:
- case EOpUintBitsToFloat:
- setType(TType(EbtFloat, EbpHigh, resultQualifier, operandPrimarySize));
- break;
- case EOpPackSnorm2x16:
- case EOpPackUnorm2x16:
- case EOpPackHalf2x16:
- case EOpPackUnorm4x8:
- case EOpPackSnorm4x8:
- setType(TType(EbtUInt, EbpHigh, resultQualifier));
- break;
- case EOpUnpackSnorm2x16:
- case EOpUnpackUnorm2x16:
- setType(TType(EbtFloat, EbpHigh, resultQualifier, 2));
- break;
- case EOpUnpackHalf2x16:
- setType(TType(EbtFloat, EbpMedium, resultQualifier, 2));
- break;
- case EOpUnpackUnorm4x8:
- case EOpUnpackSnorm4x8:
- setType(TType(EbtFloat, EbpMedium, resultQualifier, 4));
- break;
- case EOpAny:
- case EOpAll:
- setType(TType(EbtBool, EbpUndefined, resultQualifier));
- break;
- case EOpLength:
- case EOpDeterminant:
- setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier));
- break;
- case EOpTranspose:
- setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier,
- static_cast<unsigned char>(mOperand->getType().getRows()),
- static_cast<unsigned char>(mOperand->getType().getCols())));
- break;
- case EOpIsInf:
- case EOpIsNan:
- setType(TType(EbtBool, EbpUndefined, resultQualifier, operandPrimarySize));
- break;
- case EOpBitfieldReverse:
- setType(TType(mOperand->getBasicType(), EbpHigh, resultQualifier, operandPrimarySize));
- break;
- case EOpBitCount:
- setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
- break;
- case EOpFindLSB:
- setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
- break;
- case EOpFindMSB:
- setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
- break;
- default:
- setType(mOperand->getType());
- mType.setQualifier(resultQualifier);
- break;
- }
-}
-
-TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets)
- : TIntermTyped(TType(EbtFloat, EbpUndefined)),
- mOperand(operand),
- mSwizzleOffsets(swizzleOffsets)
-{
- ASSERT(mSwizzleOffsets.size() <= 4);
- promote();
-}
-
-TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand)
- : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false)
-{
- promote();
-}
-
-TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right)
- : TIntermOperator(op), mLeft(left), mRight(right), mAddIndexClamp(false)
-{
- promote();
-}
-
-TIntermInvariantDeclaration::TIntermInvariantDeclaration(TIntermSymbol *symbol, const TSourceLoc &line)
- : TIntermNode(), mSymbol(symbol)
-{
- ASSERT(symbol);
- setLine(line);
-}
-
-TIntermTernary::TIntermTernary(TIntermTyped *cond,
- TIntermTyped *trueExpression,
- TIntermTyped *falseExpression)
- : TIntermTyped(trueExpression->getType()),
- mCondition(cond),
- mTrueExpression(trueExpression),
- mFalseExpression(falseExpression)
-{
- getTypePointer()->setQualifier(
- TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression));
-}
-
-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;
- }
-}
-
-TIntermIfElse::TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB)
- : TIntermNode(), mCondition(cond), mTrueBlock(trueB), mFalseBlock(falseB)
-{
- // Prune empty false blocks so that there won't be unnecessary operations done on it.
- if (mFalseBlock && mFalseBlock->getSequence()->empty())
- {
- mFalseBlock = nullptr;
- }
-}
-
-TIntermSwitch::TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList)
- : TIntermNode(), mInit(init), mStatementList(statementList)
-{
- ASSERT(mStatementList);
-}
-
-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;
-}
-
-TIntermTyped *TIntermTernary::fold()
-{
- if (mCondition->getAsConstantUnion())
- {
- if (mCondition->getAsConstantUnion()->getBConst(0))
- {
- mTrueExpression->getTypePointer()->setQualifier(mType.getQualifier());
- return mTrueExpression;
- }
- else
- {
- mFalseExpression->getTypePointer()->setQualifier(mType.getQualifier());
- return mFalseExpression;
- }
- }
- return this;
-}
-
-void TIntermSwizzle::promote()
-{
- TQualifier resultQualifier = EvqTemporary;
- if (mOperand->getQualifier() == EvqConst)
- resultQualifier = EvqConst;
-
- auto numFields = mSwizzleOffsets.size();
- setType(TType(mOperand->getBasicType(), mOperand->getPrecision(), resultQualifier,
- static_cast<unsigned char>(numFields)));
-}
-
-bool TIntermSwizzle::hasDuplicateOffsets() const
-{
- int offsetCount[4] = {0u, 0u, 0u, 0u};
- for (const auto offset : mSwizzleOffsets)
- {
- offsetCount[offset]++;
- if (offsetCount[offset] > 1)
- {
- return true;
- }
- }
- return false;
-}
-
-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 (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst)
- {
- resultQualifier = EvqTemporary;
- getTypePointer()->setQualifier(EvqTemporary);
- }
-
- // Handle indexing ops.
- switch (mOp)
- {
- case EOpIndexDirect:
- case EOpIndexIndirect:
- if (mLeft->isArray())
- {
- mType.toArrayElementType();
- }
- else if (mLeft->isMatrix())
- {
- setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier,
- static_cast<unsigned char>(mLeft->getRows())));
- }
- else if (mLeft->isVector())
- {
- setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier));
- }
- else
- {
- UNREACHABLE();
- }
- return;
- case EOpIndexDirectStruct:
- {
- const TFieldList &fields = mLeft->getType().getStruct()->fields();
- const int i = mRight->getAsConstantUnion()->getIConst(0);
- setType(*fields[i]->type());
- getTypePointer()->setQualifier(resultQualifier);
- return;
- }
- case EOpIndexDirectInterfaceBlock:
- {
- const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields();
- const int i = mRight->getAsConstantUnion()->getIConst(0);
- setType(*fields[i]->type());
- getTypePointer()->setQualifier(resultQualifier);
- return;
- }
- default:
- break;
- }
-
- ASSERT(mLeft->isArray() == mRight->isArray());
-
- // The result gets promoted to the highest precision.
- TPrecision higherPrecision = GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision());
- getTypePointer()->setPrecision(higherPrecision);
-
- const int nominalSize = std::max(mLeft->getNominalSize(), mRight->getNominalSize());
-
- //
- // All scalars or structs. Code after this test assumes this case is removed!
- //
- if (nominalSize == 1)
- {
- switch (mOp)
- {
- //
- // Promote to conditional
- //
- case EOpEqual:
- case EOpNotEqual:
- case EOpLessThan:
- case EOpGreaterThan:
- case EOpLessThanEqual:
- case EOpGreaterThanEqual:
- 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);
- setType(TType(EbtBool, EbpUndefined, resultQualifier));
- break;
-
- default:
- break;
- }
- return;
- }
-
- // If we reach here, at least one of the operands is vector or matrix.
- // The other operand could be a scalar, vector, or matrix.
- TBasicType basicType = mLeft->getBasicType();
-
- switch (mOp)
- {
- case EOpMul:
- break;
- case EOpMatrixTimesScalar:
- if (mRight->isMatrix())
- {
- setType(TType(basicType, higherPrecision, resultQualifier,
- static_cast<unsigned char>(mRight->getCols()),
- static_cast<unsigned char>(mRight->getRows())));
- }
- break;
- case EOpMatrixTimesVector:
- setType(TType(basicType, higherPrecision, resultQualifier,
- static_cast<unsigned char>(mLeft->getRows()), 1));
- break;
- case EOpMatrixTimesMatrix:
- setType(TType(basicType, higherPrecision, resultQualifier,
- static_cast<unsigned char>(mRight->getCols()),
- static_cast<unsigned char>(mLeft->getRows())));
- break;
- case EOpVectorTimesScalar:
- setType(TType(basicType, higherPrecision, resultQualifier,
- static_cast<unsigned char>(nominalSize), 1));
- break;
- case EOpVectorTimesMatrix:
- setType(TType(basicType, higherPrecision, resultQualifier,
- static_cast<unsigned char>(mRight->getCols()), 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:
- {
- const int secondarySize =
- std::max(mLeft->getSecondarySize(), mRight->getSecondarySize());
- setType(TType(basicType, higherPrecision, resultQualifier,
- static_cast<unsigned char>(nominalSize),
- static_cast<unsigned char>(secondarySize)));
- ASSERT(!mLeft->isArray() && !mRight->isArray());
- 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;
-
- case EOpIndexDirect:
- case EOpIndexIndirect:
- case EOpIndexDirectInterfaceBlock:
- case EOpIndexDirectStruct:
- // These ops should be already fully handled.
- UNREACHABLE();
- break;
- default:
- UNREACHABLE();
- break;
- }
-}
-
-const TConstantUnion *TIntermConstantUnion::foldIndexing(int index)
-{
- if (isArray())
- {
- ASSERT(index < static_cast<int>(getType().getOutermostArraySize()));
- TType arrayElementType = getType();
- arrayElementType.toArrayElementType();
- size_t arrayElementSize = arrayElementType.getObjectSize();
- return &mUnionArrayPointer[arrayElementSize * index];
- }
- else if (isMatrix())
- {
- ASSERT(index < getType().getCols());
- int size = getType().getRows();
- return &mUnionArrayPointer[size * index];
- }
- else if (isVector())
- {
- ASSERT(index < getType().getNominalSize());
- return &mUnionArrayPointer[index];
- }
- else
- {
- UNREACHABLE();
- return nullptr;
- }
-}
-
-TIntermTyped *TIntermSwizzle::fold()
-{
- 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] = *operandConstant->foldIndexing(mSwizzleOffsets.at(i));
- }
- return CreateFoldedNode(constArray, this, mType.getQualifier());
-}
-
-TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
-{
- TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion();
- TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion();
- switch (mOp)
- {
- case EOpComma:
- {
- if (mLeft->hasSideEffects())
- {
- return this;
- }
- mRight->getTypePointer()->setQualifier(mType.getQualifier());
- return mRight;
- }
- case EOpIndexDirect:
- {
- if (leftConstant == nullptr || rightConstant == nullptr)
- {
- return this;
- }
- int index = rightConstant->getIConst(0);
-
- const TConstantUnion *constArray = leftConstant->foldIndexing(index);
- if (!constArray)
- {
- return this;
- }
- return CreateFoldedNode(constArray, this, mType.getQualifier());
- }
- case EOpIndexDirectStruct:
- {
- if (leftConstant == nullptr || rightConstant == nullptr)
- {
- return this;
- }
- const TFieldList &fields = mLeft->getType().getStruct()->fields();
- size_t index = static_cast<size_t>(rightConstant->getIConst(0));
-
- size_t previousFieldsSize = 0;
- for (size_t i = 0; i < index; ++i)
- {
- previousFieldsSize += fields[i]->type()->getObjectSize();
- }
-
- const TConstantUnion *constArray = leftConstant->getUnionArrayPointer();
- return CreateFoldedNode(constArray + previousFieldsSize, this, mType.getQualifier());
- }
- case EOpIndexIndirect:
- case EOpIndexDirectInterfaceBlock:
- // Can never be constant folded.
- return this;
- default:
- {
- if (leftConstant == nullptr || rightConstant == nullptr)
- {
- return this;
- }
- TConstantUnion *constArray =
- leftConstant->foldBinary(mOp, rightConstant, diagnostics, mLeft->getLine());
- if (!constArray)
- {
- return this;
- }
-
- // Nodes may be constant folded without being qualified as constant.
- return CreateFoldedNode(constArray, this, mType.getQualifier());
- }
- }
-}
-
-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, diagnostics);
- break;
- }
- }
- if (constArray == nullptr)
- {
- return this;
- }
-
- // Nodes may be constant folded without being qualified as constant.
- return CreateFoldedNode(constArray, this, mType.getQualifier());
-}
-
-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;
- }
- }
- TConstantUnion *constArray = nullptr;
- if (isConstructor())
- constArray = TIntermConstantUnion::FoldAggregateConstructor(this);
- else
- constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics);
-
- // Nodes may be constant folded without being qualified as constant.
- return CreateFoldedNode(constArray, this, getQualifier());
-}
-
-//
-// 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.
-//
-TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op,
- TIntermConstantUnion *rightNode,
- TDiagnostics *diagnostics,
- const TSourceLoc &line)
-{
- const TConstantUnion *leftArray = getUnionArrayPointer();
- const TConstantUnion *rightArray = rightNode->getUnionArrayPointer();
-
- ASSERT(leftArray && rightArray);
-
- size_t objectSize = getType().getObjectSize();
-
- // for a case like float f = vec4(2, 3, 4, 5) + 1.2;
- if (rightNode->getType().getObjectSize() == 1 && objectSize > 1)
- {
- rightArray = Vectorize(*rightNode->getUnionArrayPointer(), objectSize);
- }
- else if (rightNode->getType().getObjectSize() > 1 && objectSize == 1)
- {
- // for a case like float f = 1.2 + vec4(2, 3, 4, 5);
- leftArray = Vectorize(*getUnionArrayPointer(), rightNode->getType().getObjectSize());
- objectSize = rightNode->getType().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(getType().getBasicType() == EbtFloat && rightNode->getBasicType() == EbtFloat);
-
- const int leftCols = getCols();
- const int leftRows = getRows();
- const int rightCols = rightNode->getType().getCols();
- const int rightRows = rightNode->getType().getRows();
- const int resultCols = rightCols;
- const int resultRows = leftRows;
-
- resultArray = new TConstantUnion[resultCols * resultRows];
- for (int row = 0; row < resultRows; row++)
- {
- for (int column = 0; column < resultCols; column++)
- {
- resultArray[resultRows * column + row].setFConst(0.0f);
- for (int 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++)
- {
- switch (getType().getBasicType())
- {
- case EbtFloat:
- {
- ASSERT(op == EOpDiv);
- float dividend = leftArray[i].getFConst();
- float divisor = rightArray[i].getFConst();
- if (divisor == 0.0f)
- {
- if (dividend == 0.0f)
- {
- diagnostics->warning(
- getLine(),
- "Zero divided by zero during constant folding generated NaN",
- "/");
- resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
- }
- else
- {
- diagnostics->warning(getLine(),
- "Divide by zero during constant folding", "/");
- bool negativeResult =
- std::signbit(dividend) != std::signbit(divisor);
- resultArray[i].setFConst(
- negativeResult ? -std::numeric_limits<float>::infinity()
- : std::numeric_limits<float>::infinity());
- }
- }
- else if (gl::isInf(dividend) && gl::isInf(divisor))
- {
- diagnostics->warning(getLine(),
- "Infinity divided by infinity during constant "
- "folding generated NaN",
- "/");
- resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
- }
- else
- {
- float result = dividend / divisor;
- if (!gl::isInf(dividend) && gl::isInf(result))
- {
- diagnostics->warning(
- getLine(), "Constant folded division overflowed to infinity",
- "/");
- }
- resultArray[i].setFConst(result);
- }
- break;
- }
- case EbtInt:
- if (rightArray[i] == 0)
- {
- diagnostics->warning(
- getLine(), "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(getLine(),
- "Negative modulus operator operand "
- "encountered during constant folding",
- "%");
- resultArray[i].setIConst(0);
- }
- else
- {
- resultArray[i].setIConst(lhs % divisor);
- }
- }
- }
- break;
-
- case EbtUInt:
- if (rightArray[i] == 0)
- {
- diagnostics->warning(
- getLine(), "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(rightNode->getBasicType() == EbtFloat);
-
- const int matrixCols = getCols();
- const int matrixRows = getRows();
-
- resultArray = new TConstantUnion[matrixRows];
-
- for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
- {
- resultArray[matrixRow].setFConst(0.0f);
- for (int 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(getType().getBasicType() == EbtFloat);
-
- const int matrixCols = rightNode->getType().getCols();
- const int matrixRows = rightNode->getType().getRows();
-
- resultArray = new TConstantUnion[matrixCols];
-
- for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++)
- {
- resultArray[matrixCol].setFConst(0.0f);
- for (int 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(getType().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 = getUnionArrayPointer();
- 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<float> result =
- GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose();
- SetUnionArrayFromMatrix(result, resultArray);
- break;
- }
-
- case EOpDeterminant:
- {
- ASSERT(getType().getBasicType() == EbtFloat);
- unsigned int size = getType().getNominalSize();
- ASSERT(size >= 2 && size <= 4);
- resultArray = new TConstantUnion();
- resultArray->setFConst(GetMatrix(operandArray, size).determinant());
- break;
- }
-
- case EOpInverse:
- {
- ASSERT(getType().getBasicType() == EbtFloat);
- unsigned int size = getType().getNominalSize();
- ASSERT(size >= 2 && size <= 4);
- resultArray = new TConstantUnion[objectSize];
- angle::Matrix<float> 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,
- 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 = getUnionArrayPointer();
- 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<int>::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<int>::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<unsigned int>(
- -static_cast<int>(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<unsigned int>(
- static_cast<int>(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(), op, 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(), op, 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(), op, 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(), op, 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<int32_t>(operandArray[0].getFConst()));
- break;
-
- case EOpFloatBitsToUint:
- ASSERT(getType().getBasicType() == EbtFloat);
- resultArray[i].setUConst(gl::bitCast<uint32_t>(operandArray[0].getFConst()));
- break;
-
- case EOpIntBitsToFloat:
- ASSERT(getType().getBasicType() == EbtInt);
- resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getIConst()));
- break;
-
- case EOpUintBitsToFloat:
- ASSERT(getType().getBasicType() == EbtUInt);
- resultArray[i].setFConst(gl::bitCast<float>(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(), op, 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(), op, 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(), op, 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(), op, getType().getBasicType(),
- diagnostics, &resultArray[i]);
- else
- {
- foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
- resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
- }
- break;
-
- case EOpLogicalNotComponentWise:
- 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)
- resultArray[i].setFConst(x / length);
- else
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
- diagnostics, &resultArray[i]);
- break;
- }
- case EOpBitfieldReverse:
- {
- uint32_t value;
- if (getType().getBasicType() == EbtInt)
- {
- value = static_cast<uint32_t>(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<int32_t>(result));
- }
- else
- {
- resultArray[i].setUConst(result);
- }
- break;
- }
- case EOpBitCount:
- {
- uint32_t value;
- if (getType().getBasicType() == EbtInt)
- {
- value = static_cast<uint32_t>(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<uint32_t>(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<uint32_t>(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;
- }
- case EOpDFdx:
- case EOpDFdy:
- case EOpFwidth:
- ASSERT(getType().getBasicType() == EbtFloat);
- // Derivatives of constant arguments should be 0.
- resultArray[i].setFConst(0.0f);
- break;
-
- default:
- return nullptr;
- }
- }
-
- return resultArray;
-}
-
-void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter,
- FloatTypeUnaryFunc builtinFunc,
- TConstantUnion *result) const
-{
- ASSERT(builtinFunc);
-
- ASSERT(getType().getBasicType() == EbtFloat);
- result->setFConst(builtinFunc(parameter.getFConst()));
-}
-
-// static
-TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate)
-{
- ASSERT(aggregate->getSequence()->size() > 0u);
- size_t resultSize = aggregate->getType().getObjectSize();
- TConstantUnion *resultArray = new TConstantUnion[resultSize];
- TBasicType basicType = aggregate->getBasicType();
-
- size_t resultIndex = 0u;
-
- if (aggregate->getSequence()->size() == 1u)
- {
- TIntermNode *argument = aggregate->getSequence()->front();
- TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion();
- const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
- // Check the special case of constructing a matrix diagonal from a single scalar,
- // or a vector from a single scalar.
- if (argumentConstant->getType().getObjectSize() == 1u)
- {
- if (aggregate->isMatrix())
- {
- int resultCols = aggregate->getType().getCols();
- int resultRows = aggregate->getType().getRows();
- for (int col = 0; col < resultCols; ++col)
- {
- for (int row = 0; row < resultRows; ++row)
- {
- if (col == row)
- {
- resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
- }
- else
- {
- resultArray[resultIndex].setFConst(0.0f);
- }
- ++resultIndex;
- }
- }
- }
- else
- {
- while (resultIndex < resultSize)
- {
- resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
- ++resultIndex;
- }
- }
- ASSERT(resultIndex == resultSize);
- return resultArray;
- }
- else if (aggregate->isMatrix() && argumentConstant->isMatrix())
- {
- // The special case of constructing a matrix from a matrix.
- int argumentCols = argumentConstant->getType().getCols();
- int argumentRows = argumentConstant->getType().getRows();
- int resultCols = aggregate->getType().getCols();
- int resultRows = aggregate->getType().getRows();
- for (int col = 0; col < resultCols; ++col)
- {
- for (int row = 0; row < resultRows; ++row)
- {
- if (col < argumentCols && row < argumentRows)
- {
- resultArray[resultIndex].cast(basicType,
- argumentUnionArray[col * argumentRows + row]);
- }
- else if (col == row)
- {
- resultArray[resultIndex].setFConst(1.0f);
- }
- else
- {
- resultArray[resultIndex].setFConst(0.0f);
- }
- ++resultIndex;
- }
- }
- ASSERT(resultIndex == resultSize);
- return resultArray;
- }
- }
-
- for (TIntermNode *&argument : *aggregate->getSequence())
- {
- TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion();
- size_t argumentSize = argumentConstant->getType().getObjectSize();
- const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
- for (size_t i = 0u; i < argumentSize; ++i)
- {
- if (resultIndex >= resultSize)
- break;
- resultArray[resultIndex].cast(basicType, argumentUnionArray[i]);
- ++resultIndex;
- }
- }
- ASSERT(resultIndex == resultSize);
- return resultArray;
-}
-
-bool TIntermAggregate::CanFoldAggregateBuiltInOp(TOperator op)
-{
- switch (op)
- {
- case EOpAtan:
- case EOpPow:
- case EOpMod:
- case EOpMin:
- case EOpMax:
- case EOpClamp:
- case EOpMix:
- case EOpStep:
- case EOpSmoothStep:
- case EOpLdexp:
- case EOpMulMatrixComponentWise:
- 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:
- return true;
- default:
- return false;
- }
-}
-
-// static
-TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate,
- TDiagnostics *diagnostics)
-{
- TOperator op = aggregate->getOp();
- TIntermSequence *arguments = aggregate->getSequence();
- unsigned int argsCount = static_cast<unsigned int>(arguments->size());
- std::vector<const TConstantUnion *> unionArrays(argsCount);
- std::vector<size_t> 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->getUnionArrayPointer();
- 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, op, 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, op, basicType, diagnostics, &resultArray[i]);
- else if (x == 0.0f && y <= 0.0f)
- UndefinedConstantFoldingError(loc, op, 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 EOpMulMatrixComponentWise:
- {
- ASSERT(basicType == EbtFloat && (*arguments)[0]->getAsTyped()->isMatrix() &&
- (*arguments)[1]->getAsTyped()->isMatrix());
- // Perform component-wise matrix multiplication.
- resultArray = new TConstantUnion[maxObjectSize];
- int size = (*arguments)[0]->getAsTyped()->getNominalSize();
- angle::Matrix<float> result =
- GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size));
- 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<float> result =
- GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
- .outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(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, op, 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, op, 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, op, basicType, diagnostics,
- &resultArray[i]);
- else
- resultArray[i].setUConst(gl::clamp(x, min, max));
- break;
- }
- default:
- UNREACHABLE();
- break;
- }
- }
- break;
- }
-
- case EOpMix:
- {
- 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();
- TBasicType type = (*arguments)[2]->getAsTyped()->getType().getBasicType();
- if (type == EbtFloat)
- {
- // 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();
- resultArray[i].setFConst(a ? y : x);
- }
- }
- 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, op, 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 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, op, 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, op, 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<uint32_t>(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<int32_t>(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, op, 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<uint32_t>(unionArrays[0][i].getIConst());
- uint32_t insert = static_cast<uint32_t>(unionArrays[1][i].getIConst());
- uint32_t resultUnsigned =
- (base & baseMask) | ((insert << offset) & insertMask);
- resultArray[i].setIConst(static_cast<int32_t>(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;
- }
-
- default:
- UNREACHABLE();
- return nullptr;
- }
- return resultArray;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.h b/src/3rdparty/angle/src/compiler/translator/IntermNode.h
deleted file mode 100644
index 2170916201..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/IntermNode.h
+++ /dev/null
@@ -1,917 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-//
-// 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 <algorithm>
-#include <queue>
-
-#include "common/angleutils.h"
-#include "compiler/translator/Common.h"
-#include "compiler/translator/ConstantUnion.h"
-#include "compiler/translator/Operator.h"
-#include "compiler/translator/SymbolUniqueId.h"
-#include "compiler/translator/Types.h"
-
-namespace sh
-{
-
-class TDiagnostics;
-
-class TIntermTraverser;
-class TIntermAggregate;
-class TIntermBlock;
-class TIntermInvariantDeclaration;
-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 TIntermRaw;
-class TIntermBranch;
-
-class TSymbolTable;
-class TFunction;
-
-// Encapsulate an identifier string and track whether it is coming from the original shader code
-// (not internal) or from ANGLE (internal). Usually internal names shouldn't be decorated or hashed.
-class TName
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- explicit TName(const TString &name) : mName(name), mIsInternal(false) {}
- TName() : mName(), mIsInternal(false) {}
- TName(const TName &) = default;
- TName &operator=(const TName &) = default;
-
- const TString &getString() const { return mName; }
- void setString(const TString &string) { mName = string; }
- bool isInternal() const { return mIsInternal; }
- void setInternal(bool isInternal) { mIsInternal = isInternal; }
-
- private:
- TString mName;
- bool mIsInternal;
-};
-
-//
-// 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 *) = 0;
- virtual TIntermTyped *getAsTyped() { return 0; }
- virtual TIntermConstantUnion *getAsConstantUnion() { return 0; }
- virtual TIntermFunctionDefinition *getAsFunctionDefinition() { return nullptr; }
- virtual TIntermAggregate *getAsAggregate() { return 0; }
- virtual TIntermBlock *getAsBlock() { return nullptr; }
- virtual TIntermFunctionPrototype *getAsFunctionPrototypeNode() { return nullptr; }
- virtual TIntermInvariantDeclaration *getAsInvariantDeclarationNode() { return nullptr; }
- virtual TIntermDeclaration *getAsDeclarationNode() { return nullptr; }
- virtual TIntermSwizzle *getAsSwizzleNode() { return nullptr; }
- virtual TIntermBinary *getAsBinaryNode() { return 0; }
- virtual TIntermUnary *getAsUnaryNode() { return 0; }
- virtual TIntermTernary *getAsTernaryNode() { return nullptr; }
- virtual TIntermIfElse *getAsIfElseNode() { return nullptr; }
- virtual TIntermSwitch *getAsSwitchNode() { return 0; }
- virtual TIntermCase *getAsCaseNode() { return 0; }
- virtual TIntermSymbol *getAsSymbolNode() { return 0; }
- virtual TIntermLoop *getAsLoopNode() { return 0; }
- virtual TIntermRaw *getAsRawNode() { return 0; }
- virtual TIntermBranch *getAsBranchNode() { return 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(const TType &t) : mType(t) {}
-
- virtual TIntermTyped *deepCopy() const = 0;
-
- TIntermTyped *getAsTyped() override { return this; }
-
- // 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;
-
- void setType(const TType &t) { mType = t; }
- void setTypePreservePrecision(const TType &t);
- const TType &getType() const { return mType; }
- TType *getTypePointer() { return &mType; }
-
- TBasicType getBasicType() const { return mType.getBasicType(); }
- TQualifier getQualifier() const { return mType.getQualifier(); }
- TPrecision getPrecision() const { return mType.getPrecision(); }
- TMemoryQualifier getMemoryQualifier() const { return mType.getMemoryQualifier(); }
- int getCols() const { return mType.getCols(); }
- int getRows() const { return mType.getRows(); }
- int getNominalSize() const { return mType.getNominalSize(); }
- int getSecondarySize() const { return mType.getSecondarySize(); }
-
- bool isInterfaceBlock() const { return mType.isInterfaceBlock(); }
- bool isMatrix() const { return mType.isMatrix(); }
- bool isArray() const { return mType.isArray(); }
- bool isVector() const { return mType.isVector(); }
- bool isScalar() const { return mType.isScalar(); }
- bool isScalarInt() const { return mType.isScalarInt(); }
- const char *getBasicString() const { return mType.getBasicString(); }
- TString getCompleteString() const { return mType.getCompleteString(); }
-
- unsigned int getOutermostArraySize() const { return mType.getOutermostArraySize(); }
-
- bool isConstructorWithOnlyConstantUnionParameters();
-
- protected:
- TType mType;
-
- TIntermTyped(const TIntermTyped &node);
-};
-
-//
-// 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) override;
- 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; }
-
- protected:
- TLoopType mType;
- TIntermNode *mInit; // for-loop initialization
- TIntermTyped *mCond; // loop exit condition
- TIntermTyped *mExpr; // for-loop expression
- TIntermBlock *mBody; // loop body
-};
-
-//
-// Handle break, continue, return, and kill.
-//
-class TIntermBranch : public TIntermNode
-{
- public:
- TIntermBranch(TOperator op, TIntermTyped *e) : mFlowOp(op), mExpression(e) {}
-
- void traverse(TIntermTraverser *it) override;
- TIntermBranch *getAsBranchNode() override { return this; }
- bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
-
- TOperator getFlowOp() { return mFlowOp; }
- TIntermTyped *getExpression() { return mExpression; }
-
- protected:
- TOperator mFlowOp;
- TIntermTyped *mExpression; // non-zero except for "return exp;" statements
-};
-
-//
-// Nodes that correspond to symbols or constants in the source code.
-//
-class TIntermSymbol : public TIntermTyped
-{
- public:
- // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym.
- // If sym comes from per process globalpoolallocator, then it causes increased memory usage
- // per compile it is essential to use "symbol = sym" to assign to symbol
- TIntermSymbol(const TSymbolUniqueId &id, const TString &symbol, const TType &type)
- : TIntermTyped(type), mId(id), mSymbol(symbol)
- {
- }
-
- TIntermTyped *deepCopy() const override { return new TIntermSymbol(*this); }
-
- bool hasSideEffects() const override { return false; }
-
- int getId() const { return mId.get(); }
- const TString &getSymbol() const { return mSymbol.getString(); }
- const TName &getName() const { return mSymbol; }
- TName &getName() { return mSymbol; }
-
- void setInternal(bool internal) { mSymbol.setInternal(internal); }
-
- void traverse(TIntermTraverser *it) override;
- TIntermSymbol *getAsSymbolNode() override { return this; }
- bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
-
- protected:
- const TSymbolUniqueId mId;
- TName mSymbol;
-
- private:
- TIntermSymbol(const TIntermSymbol &) = default; // Note: not deleted, just private!
-};
-
-// A Raw node stores raw code, that the translator will insert verbatim
-// into the output stream. Useful for transformation operations that make
-// complex code that might not fit naturally into the GLSL model.
-class TIntermRaw : public TIntermTyped
-{
- public:
- TIntermRaw(const TType &type, const TString &rawText) : TIntermTyped(type), mRawText(rawText) {}
- TIntermRaw(const TIntermRaw &) = delete;
-
- TIntermTyped *deepCopy() const override
- {
- UNREACHABLE();
- return nullptr;
- }
-
- bool hasSideEffects() const override { return false; }
-
- TString getRawText() const { return mRawText; }
-
- void traverse(TIntermTraverser *it) override;
-
- TIntermRaw *getAsRawNode() override { return this; }
- bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
-
- protected:
- TString mRawText;
-};
-
-// 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 TIntermTyped
-{
- public:
- TIntermConstantUnion(const TConstantUnion *unionPointer, const TType &type)
- : TIntermTyped(type), mUnionArrayPointer(unionPointer)
- {
- ASSERT(unionPointer);
- }
-
- TIntermTyped *deepCopy() const override { return new TIntermConstantUnion(*this); }
-
- bool hasSideEffects() const override { return false; }
-
- const TConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; }
-
- 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;
- }
-
- void replaceConstantUnion(const TConstantUnion *safeConstantUnion)
- {
- ASSERT(safeConstantUnion);
- // Previous union pointer freed on pool deallocation.
- mUnionArrayPointer = safeConstantUnion;
- }
-
- TIntermConstantUnion *getAsConstantUnion() override { return this; }
- void traverse(TIntermTraverser *it) override;
- bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
-
- TConstantUnion *foldBinary(TOperator op,
- TIntermConstantUnion *rightNode,
- TDiagnostics *diagnostics,
- const TSourceLoc &line);
- const TConstantUnion *foldIndexing(int index);
- TConstantUnion *foldUnaryNonComponentWise(TOperator op);
- TConstantUnion *foldUnaryComponentWise(TOperator op, TDiagnostics *diagnostics);
-
- static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate);
- static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate,
- TDiagnostics *diagnostics);
-
- 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 &parameter,
- FloatTypeUnaryFunc builtinFunc,
- TConstantUnion *result) const;
-
- TIntermConstantUnion(const TIntermConstantUnion &node); // Note: not deleted, just private!
-};
-
-//
-// Intermediate class for node types that hold operators.
-//
-class TIntermOperator : public TIntermTyped
-{
- public:
- TOperator getOp() const { return mOp; }
-
- bool isAssignment() const;
- bool isMultiplication() const;
- bool isConstructor() const;
-
- // Returns true for calls mapped to EOpCall*, false for built-ins that have their own specific
- // ops.
- bool isFunctionCall() const;
-
- bool hasSideEffects() const override { return isAssignment(); }
-
- protected:
- TIntermOperator(TOperator op) : TIntermTyped(TType(EbtFloat, EbpUndefined)), mOp(op) {}
- TIntermOperator(TOperator op, const TType &type) : TIntermTyped(type), mOp(op) {}
-
- TIntermOperator(const TIntermOperator &) = default;
-
- const TOperator mOp;
-};
-
-// Node for vector swizzles.
-class TIntermSwizzle : public TIntermTyped
-{
- public:
- // This constructor determines the type of the node based on the operand.
- TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets);
-
- TIntermTyped *deepCopy() const override { return new TIntermSwizzle(*this); }
-
- TIntermSwizzle *getAsSwizzleNode() override { return this; };
- void traverse(TIntermTraverser *it) override;
- bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
-
- bool hasSideEffects() const override { return mOperand->hasSideEffects(); }
-
- TIntermTyped *getOperand() { return mOperand; }
- void writeOffsetsAsXYZW(TInfoSinkBase *out) const;
-
- bool hasDuplicateOffsets() const;
- bool offsetsMatch(int offset) const;
-
- TIntermTyped *fold();
-
- protected:
- TIntermTyped *mOperand;
- TVector<int> mSwizzleOffsets;
-
- private:
- void promote();
-
- 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);
-
- TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); }
-
- static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right);
- static TOperator GetMulAssignOpBasedOnOperands(const TType &left, const TType &right);
- static TQualifier GetCommaQualifier(int shaderVersion,
- const TIntermTyped *left,
- const TIntermTyped *right);
-
- TIntermBinary *getAsBinaryNode() override { return this; };
- void traverse(TIntermTraverser *it) override;
- 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);
-
- void setAddIndexClamp() { mAddIndexClamp = true; }
- bool getAddIndexClamp() { return mAddIndexClamp; }
-
- protected:
- TIntermTyped *mLeft;
- TIntermTyped *mRight;
-
- // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
- bool mAddIndexClamp;
-
- private:
- void promote();
-
- TIntermBinary(const TIntermBinary &node); // Note: not deleted, just private!
-};
-
-//
-// Nodes for unary math operators.
-//
-class TIntermUnary : public TIntermOperator
-{
- public:
- TIntermUnary(TOperator op, TIntermTyped *operand);
-
- TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
-
- void traverse(TIntermTraverser *it) override;
- TIntermUnary *getAsUnaryNode() override { return this; }
- bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
-
- bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); }
-
- TIntermTyped *getOperand() { return mOperand; }
- TIntermTyped *fold(TDiagnostics *diagnostics);
-
- 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;
-
- private:
- void promote();
-
- TIntermUnary(const TIntermUnary &node); // note: not deleted, just private!
-};
-
-class TFunctionSymbolInfo
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- TFunctionSymbolInfo(const TSymbolUniqueId &id);
- TFunctionSymbolInfo() : mId(nullptr), mKnownToNotHaveSideEffects(false) {}
-
- TFunctionSymbolInfo(const TFunctionSymbolInfo &info);
- TFunctionSymbolInfo &operator=(const TFunctionSymbolInfo &info);
-
- void setFromFunction(const TFunction &function);
-
- void setNameObj(const TName &name) { mName = name; }
- const TName &getNameObj() const { return mName; }
-
- const TString &getName() const { return mName.getString(); }
- void setName(const TString &name) { mName.setString(name); }
- bool isMain() const { return mName.getString() == "main"; }
-
- void setKnownToNotHaveSideEffects(bool knownToNotHaveSideEffects)
- {
- mKnownToNotHaveSideEffects = knownToNotHaveSideEffects;
- }
- bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; }
-
- void setId(const TSymbolUniqueId &functionId);
- const TSymbolUniqueId &getId() const;
-
- bool isImageFunction() const
- {
- return getName() == "imageSize" || getName() == "imageLoad" || getName() == "imageStore";
- }
-
- private:
- TName mName;
- TSymbolUniqueId *mId;
- bool mKnownToNotHaveSideEffects;
-};
-
-typedef TVector<TIntermNode *> TIntermSequence;
-typedef TVector<int> TQualifierList;
-
-//
-// This is just to help yacc.
-//
-struct TIntermFunctionCallOrMethod
-{
- TIntermSequence *arguments;
- TIntermNode *thisNode;
-};
-
-// 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);
-
- // If using this, ensure that there's a consistent function definition with the same symbol id
- // added to the AST.
- static TIntermAggregate *CreateFunctionCall(const TType &type,
- const TSymbolUniqueId &id,
- const TName &name,
- TIntermSequence *arguments);
-
- static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func,
- TIntermSequence *arguments);
- static TIntermAggregate *CreateConstructor(const TType &type,
- TIntermSequence *arguments);
- static TIntermAggregate *Create(const TType &type, TOperator op, TIntermSequence *arguments);
- ~TIntermAggregate() {}
-
- // Note: only supported for nodes that can be a part of an expression.
- TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); }
-
- TIntermAggregate *shallowCopy() const;
-
- TIntermAggregate *getAsAggregate() override { return this; }
- void traverse(TIntermTraverser *it) override;
- bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
-
- bool hasSideEffects() const override;
-
- static bool CanFoldAggregateBuiltInOp(TOperator op);
- TIntermTyped *fold(TDiagnostics *diagnostics);
-
- TIntermSequence *getSequence() override { return &mArguments; }
- const TIntermSequence *getSequence() const override { return &mArguments; }
-
- TString getSymbolTableMangledName() const;
-
- void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
- bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
-
- // Returns true if changing parameter precision may affect the return value.
- bool gotPrecisionFromChildren() const { return mGotPrecisionFromChildren; }
-
- TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
- const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
-
- 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;
-
- bool mGotPrecisionFromChildren;
-
- TFunctionSymbolInfo mFunctionInfo;
-
- private:
- TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments);
-
- TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private!
-
- void setTypePrecisionAndQualifier(const TType &type);
-
- bool areChildrenConstQualified();
-
- void setPrecisionFromChildren();
-
- void setPrecisionForBuiltInOp();
-
- // Returns true if precision was set according to special rules for this built-in.
- bool setPrecisionForSpecialBuiltInOp();
-
- // Used for built-in functions under EOpCallBuiltInFunction. The function name in the symbol
- // info needs to be set before calling this.
- void setBuiltInFunctionPrecision();
-};
-
-// 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() {}
- ~TIntermBlock() {}
-
- TIntermBlock *getAsBlock() override { return this; }
- void traverse(TIntermTraverser *it) override;
- bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
-
- // Only intended for initially building the block.
- void appendStatement(TIntermNode *statement);
-
- TIntermSequence *getSequence() override { return &mStatements; }
- const TIntermSequence *getSequence() const override { return &mStatements; }
-
- protected:
- TIntermSequence mStatements;
-};
-
-// 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 TIntermAggregateBase
-{
- public:
- // TODO(oetuaho@nvidia.com): See if TFunctionSymbolInfo could be added to constructor
- // parameters.
- TIntermFunctionPrototype(const TType &type, const TSymbolUniqueId &id)
- : TIntermTyped(type), mFunctionInfo(id)
- {
- }
- ~TIntermFunctionPrototype() {}
-
- TIntermFunctionPrototype *getAsFunctionPrototypeNode() override { return this; }
- void traverse(TIntermTraverser *it) override;
- bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
-
- TIntermTyped *deepCopy() const override
- {
- UNREACHABLE();
- return nullptr;
- }
- bool hasSideEffects() const override
- {
- UNREACHABLE();
- return true;
- }
-
- // Only intended for initially building the declaration.
- void appendParameter(TIntermSymbol *parameter);
-
- TIntermSequence *getSequence() override { return &mParameters; }
- const TIntermSequence *getSequence() const override { return &mParameters; }
-
- TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
- const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
-
- protected:
- TIntermSequence mParameters;
-
- TFunctionSymbolInfo mFunctionInfo;
-};
-
-// 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) override;
- bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
-
- TIntermFunctionPrototype *getFunctionPrototype() const { return mPrototype; }
- TIntermBlock *getBody() const { return mBody; }
-
- const TFunctionSymbolInfo *getFunctionSymbolInfo() const
- {
- return mPrototype->getFunctionSymbolInfo();
- }
-
- 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() {}
-
- TIntermDeclaration *getAsDeclarationNode() override { return this; }
- void traverse(TIntermTraverser *it) override;
- 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; }
- protected:
- TIntermSequence mDeclarators;
-};
-
-// Specialized declarations for attributing invariance.
-class TIntermInvariantDeclaration : public TIntermNode
-{
- public:
- TIntermInvariantDeclaration(TIntermSymbol *symbol, const TSourceLoc &line);
-
- virtual TIntermInvariantDeclaration *getAsInvariantDeclarationNode() override { return this; }
-
- TIntermSymbol *getSymbol() { return mSymbol; }
-
- void traverse(TIntermTraverser *it) override;
- bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
-
- private:
- TIntermSymbol *mSymbol;
-};
-
-// For ternary operators like a ? b : c.
-class TIntermTernary : public TIntermTyped
-{
- public:
- TIntermTernary(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression);
-
- void traverse(TIntermTraverser *it) override;
- bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
-
- TIntermTyped *getCondition() const { return mCondition; }
- TIntermTyped *getTrueExpression() const { return mTrueExpression; }
- TIntermTyped *getFalseExpression() const { return mFalseExpression; }
- TIntermTernary *getAsTernaryNode() override { return this; }
-
- TIntermTyped *deepCopy() const override { return new TIntermTernary(*this); }
-
- bool hasSideEffects() const override
- {
- return mCondition->hasSideEffects() || mTrueExpression->hasSideEffects() ||
- mFalseExpression->hasSideEffects();
- }
-
- TIntermTyped *fold();
-
- private:
- TIntermTernary(const TIntermTernary &node); // Note: not deleted, just private!
-
- static TQualifier DetermineQualifier(TIntermTyped *cond,
- TIntermTyped *trueExpression,
- TIntermTyped *falseExpression);
-
- TIntermTyped *mCondition;
- TIntermTyped *mTrueExpression;
- TIntermTyped *mFalseExpression;
-};
-
-class TIntermIfElse : public TIntermNode
-{
- public:
- TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB);
-
- void traverse(TIntermTraverser *it) override;
- bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
-
- TIntermTyped *getCondition() const { return mCondition; }
- TIntermBlock *getTrueBlock() const { return mTrueBlock; }
- TIntermBlock *getFalseBlock() const { return mFalseBlock; }
- TIntermIfElse *getAsIfElseNode() override { return this; }
-
- protected:
- TIntermTyped *mCondition;
- TIntermBlock *mTrueBlock;
- TIntermBlock *mFalseBlock;
-};
-
-//
-// Switch statement.
-//
-class TIntermSwitch : public TIntermNode
-{
- public:
- TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList);
-
- void traverse(TIntermTraverser *it) override;
- bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
-
- TIntermSwitch *getAsSwitchNode() override { return this; }
-
- TIntermTyped *getInit() { return mInit; }
- TIntermBlock *getStatementList() { return mStatementList; }
-
- // Must be called with a non-null statementList.
- void setStatementList(TIntermBlock *statementList);
-
- protected:
- TIntermTyped *mInit;
- TIntermBlock *mStatementList;
-};
-
-//
-// Case label.
-//
-class TIntermCase : public TIntermNode
-{
- public:
- TIntermCase(TIntermTyped *condition) : TIntermNode(), mCondition(condition) {}
-
- void traverse(TIntermTraverser *it) override;
- bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
-
- TIntermCase *getAsCaseNode() override { return this; }
-
- bool hasCondition() const { return mCondition != nullptr; }
- TIntermTyped *getCondition() const { return mCondition; }
-
- protected:
- TIntermTyped *mCondition;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_INTERMNODE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp
deleted file mode 100644
index 567e8f7440..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-//
-// Copyright (c) 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/IntermNodePatternMatcher.h"
-
-#include "compiler/translator/IntermNode.h"
-
-namespace sh
-{
-
-IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask)
-{
-}
-
-// static
-bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node)
-{
- return node->getOp() == EOpIndexIndirect && !node->getLeft()->isArray() &&
- node->getLeft()->getBasicType() != EbtStruct;
-}
-
-bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode)
-{
- 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)
-{
- if ((mMask & kArrayLengthMethod) != 0)
- {
- if (node->getOp() == EOpArrayLength)
- {
- return true;
- }
- }
- return false;
-}
-
-bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode)
-{
- // 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)
-{
- 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)
-{
- 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()) && !parentNode->getAsBlock())
- {
- return true;
- }
- }
- }
- return false;
-}
-
-bool IntermNodePatternMatcher::match(TIntermTernary *node)
-{
- if ((mMask & kUnfoldedShortCircuitExpression) != 0)
- {
- return true;
- }
- return false;
-}
-
-bool IntermNodePatternMatcher::match(TIntermDeclaration *node)
-{
- 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()->name() == "")
- {
- return true;
- }
- }
- return false;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h b/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h
deleted file mode 100644
index 997fc2ef10..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h
+++ /dev/null
@@ -1,75 +0,0 @@
-//
-// Copyright (c) 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_INTERMNODEPATTERNMATCHER_H_
-#define COMPILER_TRANSLATOR_INTERMNODEPATTERNMATCHER_H_
-
-namespace sh
-{
-
-class TIntermAggregate;
-class TIntermBinary;
-class TIntermDeclaration;
-class TIntermNode;
-class TIntermTernary;
-class TIntermUnary;
-
-class IntermNodePatternMatcher
-{
- public:
- static bool IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node);
-
- enum PatternType
- {
- // Matches expressions that are unfolded to if statements by UnfoldShortCircuitToIf
- kUnfoldedShortCircuitExpression = 0x0001,
-
- // Matches expressions that return arrays with the exception of simple statements where a
- // constructor or function call result is assigned.
- kExpressionReturningArray = 0x0001 << 1,
-
- // Matches dynamic indexing of vectors or matrices in l-values.
- kDynamicIndexingOfVectorOrMatrixInLValue = 0x0001 << 2,
-
- // Matches declarations with more than one declared variables.
- kMultiDeclaration = 0x0001 << 3,
-
- // Matches declarations of arrays.
- kArrayDeclaration = 0x0001 << 4,
-
- // Matches declarations of structs where the struct type does not have a name.
- kNamelessStructDeclaration = 0x0001 << 5,
-
- // Matches array length() method.
- kArrayLengthMethod = 0x0001 << 6
- };
- IntermNodePatternMatcher(const unsigned int mask);
-
- bool match(TIntermUnary *node);
-
- bool match(TIntermBinary *node, TIntermNode *parentNode);
-
- // Use this version for checking binary node matches in case you're using flag
- // kDynamicIndexingOfVectorOrMatrixInLValue.
- bool match(TIntermBinary *node, TIntermNode *parentNode, bool isLValueRequiredHere);
-
- bool match(TIntermAggregate *node, TIntermNode *parentNode);
- bool match(TIntermTernary *node);
- bool match(TIntermDeclaration *node);
-
- private:
- const unsigned int mMask;
-
- bool matchInternal(TIntermBinary *node, TIntermNode *parentNode);
-};
-
-} // namespace sh
-
-#endif
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp
deleted file mode 100644
index 9f1f596c43..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-//
-// Copyright (c) 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/IntermNode_util.h"
-
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-namespace
-{
-
-TName GetInternalFunctionName(const char *name)
-{
- TString nameStr(name);
- TName nameObj(nameStr);
- nameObj.setInternal(true);
- return nameObj;
-}
-
-const TFunction *LookUpBuiltInFunction(const TString &name,
- const TIntermSequence *arguments,
- const TSymbolTable &symbolTable,
- int shaderVersion)
-{
- TString mangledName = TFunction::GetMangledNameFromCall(name, *arguments);
- TSymbol *symbol = symbolTable.findBuiltIn(mangledName, shaderVersion);
- if (symbol)
- {
- ASSERT(symbol->isFunction());
- return static_cast<const TFunction *>(symbol);
- }
- return nullptr;
-}
-
-} // anonymous namespace
-
-TIntermFunctionPrototype *CreateInternalFunctionPrototypeNode(const TType &returnType,
- const char *name,
- const TSymbolUniqueId &functionId)
-{
- TIntermFunctionPrototype *functionNode = new TIntermFunctionPrototype(returnType, functionId);
- functionNode->getFunctionSymbolInfo()->setNameObj(GetInternalFunctionName(name));
- return functionNode;
-}
-
-TIntermFunctionDefinition *CreateInternalFunctionDefinitionNode(const TType &returnType,
- const char *name,
- TIntermBlock *functionBody,
- const TSymbolUniqueId &functionId)
-{
- TIntermFunctionPrototype *prototypeNode =
- CreateInternalFunctionPrototypeNode(returnType, name, functionId);
- return new TIntermFunctionDefinition(prototypeNode, functionBody);
-}
-
-TIntermAggregate *CreateInternalFunctionCallNode(const TType &returnType,
- const char *name,
- const TSymbolUniqueId &functionId,
- TIntermSequence *arguments)
-{
- TIntermAggregate *functionNode = TIntermAggregate::CreateFunctionCall(
- returnType, functionId, GetInternalFunctionName(name), arguments);
- return functionNode;
-}
-
-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 typecheck.
- // 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;
- }
-
- if (type.getBasicType() == EbtVoid)
- {
- // Void array. This happens only on error condition, similarly to the case above. We don't
- // have a constructor operator for void, so this needs special handling. We'll end up with a
- // value without the array type, but that should not be a problem.
- while (constType.isArray())
- {
- constType.toArrayElementType();
- }
- return CreateZeroNode(constType);
- }
-
- TIntermSequence *arguments = new TIntermSequence();
-
- 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 *CreateIndexNode(int index)
-{
- TConstantUnion *u = new TConstantUnion[1];
- u[0].setIConst(index);
-
- TType type(EbtInt, EbpUndefined, EvqConst, 1);
- TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
- return node;
-}
-
-TIntermConstantUnion *CreateBoolNode(bool value)
-{
- TConstantUnion *u = new TConstantUnion[1];
- u[0].setBConst(value);
-
- TType type(EbtBool, EbpUndefined, EvqConst, 1);
- TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
- return node;
-}
-
-TIntermSymbol *CreateTempSymbolNode(const TSymbolUniqueId &id,
- const TType &type,
- TQualifier qualifier)
-{
- TInfoSinkBase symbolNameOut;
- symbolNameOut << "s" << id.get();
- TString symbolName = symbolNameOut.c_str();
-
- TIntermSymbol *node = new TIntermSymbol(id, symbolName, type);
- node->setInternal(true);
-
- ASSERT(qualifier == EvqTemporary || qualifier == EvqConst || qualifier == EvqGlobal);
- node->getTypePointer()->setQualifier(qualifier);
-
- // TODO(oetuaho): Might be useful to sanitize layout qualifier etc. on the type of the created
- // symbol. This might need to be done in other places as well.
- return node;
-}
-
-TIntermDeclaration *CreateTempInitDeclarationNode(const TSymbolUniqueId &id,
- TIntermTyped *initializer,
- TQualifier qualifier)
-{
- ASSERT(initializer != nullptr);
- TIntermSymbol *tempSymbol = CreateTempSymbolNode(id, initializer->getType(), qualifier);
- TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
- TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer);
- tempDeclaration->appendDeclarator(tempInit);
- return tempDeclaration;
-}
-
-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 TString &name, const TSymbolTable &symbolTable)
-{
- TVariable *var = reinterpret_cast<TVariable *>(symbolTable.findGlobal(name));
- ASSERT(var);
- return new TIntermSymbol(var->getUniqueId(), name, var->getType());
-}
-
-TIntermSymbol *ReferenceBuiltInVariable(const TString &name,
- const TSymbolTable &symbolTable,
- int shaderVersion)
-{
- const TVariable *var =
- reinterpret_cast<const TVariable *>(symbolTable.findBuiltIn(name, shaderVersion, true));
- ASSERT(var);
- return new TIntermSymbol(var->getUniqueId(), name, var->getType());
-}
-
-TIntermTyped *CreateBuiltInFunctionCallNode(const TString &name,
- TIntermSequence *arguments,
- const TSymbolTable &symbolTable,
- int shaderVersion)
-{
- const TFunction *fn = LookUpBuiltInFunction(name, arguments, symbolTable, shaderVersion);
- ASSERT(fn);
- TOperator op = fn->getBuiltInOp();
- if (op != EOpNull)
- {
- if (arguments->size() == 1)
- {
- return new TIntermUnary(op, arguments->at(0)->getAsTyped());
- }
- return TIntermAggregate::Create(fn->getReturnType(), op, arguments);
- }
- return TIntermAggregate::CreateBuiltInFunctionCall(*fn, arguments);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode_util.h b/src/3rdparty/angle/src/compiler/translator/IntermNode_util.h
deleted file mode 100644
index 6f3b0674f0..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/IntermNode_util.h
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// Copyright (c) 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"
-
-namespace sh
-{
-
-TIntermFunctionPrototype *CreateInternalFunctionPrototypeNode(const TType &returnType,
- const char *name,
- const TSymbolUniqueId &functionId);
-TIntermFunctionDefinition *CreateInternalFunctionDefinitionNode(const TType &returnType,
- const char *name,
- TIntermBlock *functionBody,
- const TSymbolUniqueId &functionId);
-TIntermAggregate *CreateInternalFunctionCallNode(const TType &returnType,
- const char *name,
- const TSymbolUniqueId &functionId,
- TIntermSequence *arguments);
-
-TIntermTyped *CreateZeroNode(const TType &type);
-TIntermConstantUnion *CreateIndexNode(int index);
-TIntermConstantUnion *CreateBoolNode(bool value);
-
-TIntermSymbol *CreateTempSymbolNode(const TSymbolUniqueId &id,
- const TType &type,
- TQualifier qualifier);
-TIntermDeclaration *CreateTempInitDeclarationNode(const TSymbolUniqueId &id,
- TIntermTyped *initializer,
- TQualifier qualifier);
-
-// 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 TString &name, const TSymbolTable &symbolTable);
-
-// Note: this can access desktop GLSL built-ins that are hidden from the parser.
-TIntermSymbol *ReferenceBuiltInVariable(const TString &name,
- const TSymbolTable &symbolTable,
- int shaderVersion);
-
-TIntermTyped *CreateBuiltInFunctionCallNode(const TString &name,
- TIntermSequence *arguments,
- const TSymbolTable &symbolTable,
- int shaderVersion);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_INTERMNODEUTIL_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp
deleted file mode 100644
index 6c25c6c35a..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp
+++ /dev/null
@@ -1,983 +0,0 @@
-//
-// Copyright (c) 2002-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/IntermTraverse.h"
-
-#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-void TIntermSymbol::traverse(TIntermTraverser *it)
-{
- it->traverseSymbol(this);
-}
-
-void TIntermRaw::traverse(TIntermTraverser *it)
-{
- it->traverseRaw(this);
-}
-
-void TIntermConstantUnion::traverse(TIntermTraverser *it)
-{
- it->traverseConstantUnion(this);
-}
-
-void TIntermSwizzle::traverse(TIntermTraverser *it)
-{
- it->traverseSwizzle(this);
-}
-
-void TIntermBinary::traverse(TIntermTraverser *it)
-{
- it->traverseBinary(this);
-}
-
-void TIntermUnary::traverse(TIntermTraverser *it)
-{
- it->traverseUnary(this);
-}
-
-void TIntermTernary::traverse(TIntermTraverser *it)
-{
- it->traverseTernary(this);
-}
-
-void TIntermIfElse::traverse(TIntermTraverser *it)
-{
- it->traverseIfElse(this);
-}
-
-void TIntermSwitch::traverse(TIntermTraverser *it)
-{
- it->traverseSwitch(this);
-}
-
-void TIntermCase::traverse(TIntermTraverser *it)
-{
- it->traverseCase(this);
-}
-
-void TIntermFunctionDefinition::traverse(TIntermTraverser *it)
-{
- it->traverseFunctionDefinition(this);
-}
-
-void TIntermBlock::traverse(TIntermTraverser *it)
-{
- it->traverseBlock(this);
-}
-
-void TIntermInvariantDeclaration::traverse(TIntermTraverser *it)
-{
- it->traverseInvariantDeclaration(this);
-}
-
-void TIntermDeclaration::traverse(TIntermTraverser *it)
-{
- it->traverseDeclaration(this);
-}
-
-void TIntermFunctionPrototype::traverse(TIntermTraverser *it)
-{
- it->traverseFunctionPrototype(this);
-}
-
-void TIntermAggregate::traverse(TIntermTraverser *it)
-{
- it->traverseAggregate(this);
-}
-
-void TIntermLoop::traverse(TIntermTraverser *it)
-{
- it->traverseLoop(this);
-}
-
-void TIntermBranch::traverse(TIntermTraverser *it)
-{
- it->traverseBranch(this);
-}
-
-TIntermTraverser::TIntermTraverser(bool preVisit,
- bool inVisit,
- bool postVisit,
- TSymbolTable *symbolTable)
- : preVisit(preVisit),
- inVisit(inVisit),
- postVisit(postVisit),
- mDepth(-1),
- mMaxDepth(0),
- mInGlobalScope(true),
- mSymbolTable(symbolTable),
- mTemporaryId(nullptr)
-{
-}
-
-TIntermTraverser::~TIntermTraverser()
-{
-}
-
-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);
-}
-
-TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
-{
- ASSERT(mTemporaryId != nullptr);
- // nextTemporaryId() needs to be called when the code wants to start using another temporary
- // symbol.
- return CreateTempSymbolNode(*mTemporaryId, type, qualifier);
-}
-
-TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
-{
- return createTempSymbol(type, EvqTemporary);
-}
-
-TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type)
-{
- ASSERT(mTemporaryId != nullptr);
- TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
- tempDeclaration->appendDeclarator(CreateTempSymbolNode(*mTemporaryId, type, EvqTemporary));
- return tempDeclaration;
-}
-
-TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer,
- TQualifier qualifier)
-{
- ASSERT(mTemporaryId != nullptr);
- return CreateTempInitDeclarationNode(*mTemporaryId, initializer, qualifier);
-}
-
-TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
-{
- return createTempInitDeclaration(initializer, EvqTemporary);
-}
-
-TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
-{
- ASSERT(rightNode != nullptr);
- TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
- TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode);
- return assignment;
-}
-
-void TIntermTraverser::nextTemporaryId()
-{
- ASSERT(mSymbolTable);
- if (!mTemporaryId)
- {
- mTemporaryId = new TSymbolUniqueId(mSymbolTable);
- return;
- }
- *mTemporaryId = TSymbolUniqueId(mSymbolTable);
-}
-
-void TLValueTrackingTraverser::addToFunctionMap(const TSymbolUniqueId &id,
- TIntermSequence *paramSequence)
-{
- mFunctionMap[id.get()] = paramSequence;
-}
-
-bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
-{
- ASSERT(callNode->getOp() == EOpCallFunctionInAST);
- return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getId().get()) !=
- mFunctionMap.end());
-}
-
-TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
-{
- ASSERT(isInFunctionMap(callNode));
- return mFunctionMap[callNode->getFunctionSymbolInfo()->getId().get()];
-}
-
-void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
-{
- mInFunctionCallOutParameter = inOutParameter;
-}
-
-bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
-{
- return mInFunctionCallOutParameter;
-}
-
-//
-// Traverse the intermediate representation tree, and
-// call a node type specific function for each node.
-// Done recursively through the member function Traverse().
-// Node types can be skipped if their function to call is 0,
-// but their subtree will still be traversed.
-// Nodes with children can have their whole subtree skipped
-// if preVisit is turned on and the type specific function
-// returns false.
-//
-
-//
-// Traversal functions for terminals are straighforward....
-//
-void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
- visitSymbol(node);
-}
-
-void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
- visitConstantUnion(node);
-}
-
-void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- if (preVisit)
- visit = visitSwizzle(PreVisit, node);
-
- if (visit)
- {
- node->getOperand()->traverse(this);
- }
-
- if (visit && postVisit)
- visitSwizzle(PostVisit, node);
-}
-
-//
-// Traverse a binary node.
-//
-void TIntermTraverser::traverseBinary(TIntermBinary *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- //
- // visit the node before children if pre-visiting.
- //
- if (preVisit)
- visit = visitBinary(PreVisit, node);
-
- //
- // Visit the children, in the right order.
- //
- if (visit)
- {
- if (node->getLeft())
- node->getLeft()->traverse(this);
-
- if (inVisit)
- visit = visitBinary(InVisit, node);
-
- if (visit && node->getRight())
- node->getRight()->traverse(this);
- }
-
- //
- // Visit the node after the children, if requested and the traversal
- // hasn't been cancelled yet.
- //
- if (visit && postVisit)
- visitBinary(PostVisit, node);
-}
-
-void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- //
- // visit the node before children if pre-visiting.
- //
- if (preVisit)
- visit = visitBinary(PreVisit, node);
-
- //
- // Visit the children, in the right order.
- //
- if (visit)
- {
- // Some binary operations like indexing can be inside an expression which must be an
- // l-value.
- bool parentOperatorRequiresLValue = operatorRequiresLValue();
- bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
- if (node->isAssignment())
- {
- ASSERT(!isLValueRequiredHere());
- setOperatorRequiresLValue(true);
- }
-
- if (node->getLeft())
- node->getLeft()->traverse(this);
-
- if (inVisit)
- visit = visitBinary(InVisit, node);
-
- if (node->isAssignment())
- setOperatorRequiresLValue(false);
-
- // 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);
- }
-
- if (visit && node->getRight())
- 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 (visit && postVisit)
- visitBinary(PostVisit, node);
-}
-
-//
-// Traverse a unary node. Same comments in binary node apply here.
-//
-void TIntermTraverser::traverseUnary(TIntermUnary *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- if (preVisit)
- visit = visitUnary(PreVisit, node);
-
- if (visit)
- {
- node->getOperand()->traverse(this);
- }
-
- if (visit && postVisit)
- visitUnary(PostVisit, node);
-}
-
-void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- if (preVisit)
- visit = visitUnary(PreVisit, node);
-
- 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 (visit && postVisit)
- visitUnary(PostVisit, node);
-}
-
-// Traverse a function definition node.
-void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- if (preVisit)
- visit = visitFunctionDefinition(PreVisit, node);
-
- if (visit)
- {
- mInGlobalScope = false;
-
- node->getFunctionPrototype()->traverse(this);
- if (inVisit)
- visit = visitFunctionDefinition(InVisit, node);
- node->getBody()->traverse(this);
-
- mInGlobalScope = true;
- }
-
- if (visit && postVisit)
- visitFunctionDefinition(PostVisit, node);
-}
-
-// Traverse a block node.
-void TIntermTraverser::traverseBlock(TIntermBlock *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
- pushParentBlock(node);
-
- bool visit = true;
-
- TIntermSequence *sequence = node->getSequence();
-
- if (preVisit)
- visit = visitBlock(PreVisit, node);
-
- if (visit)
- {
- for (auto *child : *sequence)
- {
- child->traverse(this);
- if (visit && inVisit)
- {
- if (child != sequence->back())
- visit = visitBlock(InVisit, node);
- }
-
- incrementParentBlockPos();
- }
- }
-
- if (visit && postVisit)
- visitBlock(PostVisit, node);
-
- popParentBlock();
-}
-
-void TIntermTraverser::traverseInvariantDeclaration(TIntermInvariantDeclaration *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- if (preVisit)
- {
- visit = visitInvariantDeclaration(PreVisit, node);
- }
-
- if (visit)
- {
- node->getSymbol()->traverse(this);
- if (postVisit)
- {
- visitInvariantDeclaration(PostVisit, node);
- }
- }
-}
-
-// Traverse a declaration node.
-void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- TIntermSequence *sequence = node->getSequence();
-
- if (preVisit)
- visit = visitDeclaration(PreVisit, node);
-
- if (visit)
- {
- for (auto *child : *sequence)
- {
- child->traverse(this);
- if (visit && inVisit)
- {
- if (child != sequence->back())
- visit = visitDeclaration(InVisit, node);
- }
- }
- }
-
- if (visit && postVisit)
- visitDeclaration(PostVisit, node);
-}
-
-void TIntermTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- TIntermSequence *sequence = node->getSequence();
-
- if (preVisit)
- visit = visitFunctionPrototype(PreVisit, node);
-
- if (visit)
- {
- for (auto *child : *sequence)
- {
- child->traverse(this);
- if (visit && inVisit)
- {
- if (child != sequence->back())
- visit = visitFunctionPrototype(InVisit, node);
- }
- }
- }
-
- if (visit && postVisit)
- visitFunctionPrototype(PostVisit, node);
-}
-
-// Traverse an aggregate node. Same comments in binary node apply here.
-void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- TIntermSequence *sequence = node->getSequence();
-
- if (preVisit)
- visit = visitAggregate(PreVisit, node);
-
- if (visit)
- {
- for (auto *child : *sequence)
- {
- child->traverse(this);
- if (visit && inVisit)
- {
- if (child != sequence->back())
- visit = visitAggregate(InVisit, node);
- }
- }
- }
-
- if (visit && postVisit)
- visitAggregate(PostVisit, 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;
-}
-
-void TIntermTraverser::updateTree()
-{
- // Sort the insertions so that insertion position is decreasing. This way multiple insertions to
- // the same parent node are handled correctly.
- std::sort(mInsertions.begin(), mInsertions.end(), CompareInsertion);
- for (size_t ii = 0; ii < mInsertions.size(); ++ii)
- {
- // We can't know here what the intended ordering of two insertions to the same position is,
- // so it is not supported.
- ASSERT(ii == 0 || mInsertions[ii].position != mInsertions[ii - 1].position ||
- mInsertions[ii].parent != mInsertions[ii - 1].parent);
- const NodeInsertMultipleEntry &insertion = mInsertions[ii];
- 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);
-
- 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();
-}
-
-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));
-}
-
-TLValueTrackingTraverser::TLValueTrackingTraverser(bool preVisit,
- bool inVisit,
- bool postVisit,
- TSymbolTable *symbolTable,
- int shaderVersion)
- : TIntermTraverser(preVisit, inVisit, postVisit, symbolTable),
- mOperatorRequiresLValue(false),
- mInFunctionCallOutParameter(false),
- mShaderVersion(shaderVersion)
-{
- ASSERT(symbolTable);
-}
-
-void TLValueTrackingTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
-{
- TIntermSequence *sequence = node->getSequence();
- addToFunctionMap(node->getFunctionSymbolInfo()->getId(), sequence);
-
- TIntermTraverser::traverseFunctionPrototype(node);
-}
-
-void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- TIntermSequence *sequence = node->getSequence();
-
- if (preVisit)
- visit = visitAggregate(PreVisit, node);
-
- if (visit)
- {
- if (node->getOp() == EOpCallFunctionInAST)
- {
- if (isInFunctionMap(node))
- {
- TIntermSequence *params = getFunctionParameters(node);
- TIntermSequence::iterator paramIter = params->begin();
- for (auto *child : *sequence)
- {
- ASSERT(paramIter != params->end());
- TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
- setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
-
- child->traverse(this);
- if (visit && inVisit)
- {
- if (child != sequence->back())
- visit = visitAggregate(InVisit, node);
- }
-
- ++paramIter;
- }
- }
- else
- {
- // The node might not be in the function map in case we're in the middle of
- // transforming the AST, and have inserted function call nodes without inserting the
- // function definitions yet.
- setInFunctionCallOutParameter(false);
- for (auto *child : *sequence)
- {
- child->traverse(this);
- if (visit && inVisit)
- {
- if (child != sequence->back())
- visit = visitAggregate(InVisit, node);
- }
- }
- }
-
- setInFunctionCallOutParameter(false);
- }
- else
- {
- // Find the built-in function corresponding to this op so that we can determine the
- // in/out qualifiers of its parameters.
- TFunction *builtInFunc = nullptr;
- if (!node->isFunctionCall() && !node->isConstructor())
- {
- builtInFunc = static_cast<TFunction *>(
- mSymbolTable->findBuiltIn(node->getSymbolTableMangledName(), mShaderVersion));
- }
-
- size_t paramIndex = 0;
-
- for (auto *child : *sequence)
- {
- // This assumes that raw functions called with
- // EOpCallInternalRawFunction don't have out parameters.
- TQualifier qualifier = EvqIn;
- if (builtInFunc != nullptr)
- qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
- setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
- child->traverse(this);
-
- if (visit && inVisit)
- {
- if (child != sequence->back())
- visit = visitAggregate(InVisit, node);
- }
-
- ++paramIndex;
- }
-
- setInFunctionCallOutParameter(false);
- }
- }
-
- if (visit && postVisit)
- visitAggregate(PostVisit, node);
-}
-
-//
-// Traverse a ternary node. Same comments in binary node apply here.
-//
-void TIntermTraverser::traverseTernary(TIntermTernary *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- if (preVisit)
- visit = visitTernary(PreVisit, node);
-
- if (visit)
- {
- node->getCondition()->traverse(this);
- if (node->getTrueExpression())
- node->getTrueExpression()->traverse(this);
- if (node->getFalseExpression())
- node->getFalseExpression()->traverse(this);
- }
-
- if (visit && postVisit)
- visitTernary(PostVisit, node);
-}
-
-// Traverse an if-else node. Same comments in binary node apply here.
-void TIntermTraverser::traverseIfElse(TIntermIfElse *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- if (preVisit)
- visit = visitIfElse(PreVisit, node);
-
- if (visit)
- {
- node->getCondition()->traverse(this);
- if (node->getTrueBlock())
- node->getTrueBlock()->traverse(this);
- if (node->getFalseBlock())
- node->getFalseBlock()->traverse(this);
- }
-
- if (visit && postVisit)
- visitIfElse(PostVisit, node);
-}
-
-//
-// Traverse a switch node. Same comments in binary node apply here.
-//
-void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- if (preVisit)
- visit = visitSwitch(PreVisit, node);
-
- if (visit)
- {
- node->getInit()->traverse(this);
- if (inVisit)
- visit = visitSwitch(InVisit, node);
- if (visit && node->getStatementList())
- node->getStatementList()->traverse(this);
- }
-
- if (visit && postVisit)
- visitSwitch(PostVisit, node);
-}
-
-//
-// Traverse a case node. Same comments in binary node apply here.
-//
-void TIntermTraverser::traverseCase(TIntermCase *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- if (preVisit)
- visit = visitCase(PreVisit, node);
-
- if (visit && node->getCondition())
- {
- node->getCondition()->traverse(this);
- }
-
- if (visit && postVisit)
- visitCase(PostVisit, node);
-}
-
-//
-// Traverse a loop node. Same comments in binary node apply here.
-//
-void TIntermTraverser::traverseLoop(TIntermLoop *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- if (preVisit)
- visit = visitLoop(PreVisit, node);
-
- if (visit)
- {
- if (node->getInit())
- node->getInit()->traverse(this);
-
- if (node->getCondition())
- node->getCondition()->traverse(this);
-
- if (node->getBody())
- node->getBody()->traverse(this);
-
- if (node->getExpression())
- node->getExpression()->traverse(this);
- }
-
- if (visit && postVisit)
- visitLoop(PostVisit, node);
-}
-
-//
-// Traverse a branch node. Same comments in binary node apply here.
-//
-void TIntermTraverser::traverseBranch(TIntermBranch *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- if (preVisit)
- visit = visitBranch(PreVisit, node);
-
- if (visit && node->getExpression())
- {
- node->getExpression()->traverse(this);
- }
-
- if (visit && postVisit)
- visitBranch(PostVisit, node);
-}
-
-void TIntermTraverser::traverseRaw(TIntermRaw *node)
-{
- ScopedNodeInTraversalPath addToPath(this, node);
- visitRaw(node);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.h b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.h
deleted file mode 100644
index f0300b586b..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.h
+++ /dev/null
@@ -1,355 +0,0 @@
-//
-// Copyright (c) 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_INTERMTRAVERSE_H_
-#define COMPILER_TRANSLATOR_INTERMTRAVERSE_H_
-
-#include "compiler/translator/IntermNode.h"
-
-namespace sh
-{
-
-class TSymbolTable;
-class TSymbolUniqueId;
-
-enum Visit
-{
- PreVisit,
- InVisit,
- PostVisit
-};
-
-// 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.
-class TIntermTraverser : angle::NonCopyable
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- TIntermTraverser(bool preVisit,
- bool inVisit,
- bool postVisit,
- TSymbolTable *symbolTable = nullptr);
- virtual ~TIntermTraverser();
-
- virtual void visitSymbol(TIntermSymbol *node) {}
- virtual void visitRaw(TIntermRaw *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 bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
- {
- return true;
- }
- 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 visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *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; }
-
- // 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.
- virtual void traverseSymbol(TIntermSymbol *node);
- virtual void traverseRaw(TIntermRaw *node);
- virtual void traverseConstantUnion(TIntermConstantUnion *node);
- virtual void traverseSwizzle(TIntermSwizzle *node);
- virtual void traverseBinary(TIntermBinary *node);
- virtual void traverseUnary(TIntermUnary *node);
- virtual void traverseTernary(TIntermTernary *node);
- virtual void traverseIfElse(TIntermIfElse *node);
- virtual void traverseSwitch(TIntermSwitch *node);
- virtual void traverseCase(TIntermCase *node);
- virtual void traverseFunctionPrototype(TIntermFunctionPrototype *node);
- virtual void traverseFunctionDefinition(TIntermFunctionDefinition *node);
- virtual void traverseAggregate(TIntermAggregate *node);
- virtual void traverseBlock(TIntermBlock *node);
- virtual void traverseInvariantDeclaration(TIntermInvariantDeclaration *node);
- virtual void traverseDeclaration(TIntermDeclaration *node);
- virtual void traverseLoop(TIntermLoop *node);
- virtual void traverseBranch(TIntermBranch *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.
- void updateTree();
-
- protected:
- // Should only be called from traverse*() functions
- void incrementDepth(TIntermNode *current)
- {
- mDepth++;
- mMaxDepth = std::max(mMaxDepth, mDepth);
- mPath.push_back(current);
- }
-
- // Should only be called from traverse*() functions
- void decrementDepth()
- {
- mDepth--;
- mPath.pop_back();
- }
-
- // RAII helper for incrementDepth/decrementDepth
- class ScopedNodeInTraversalPath
- {
- public:
- ScopedNodeInTraversalPath(TIntermTraverser *traverser, TIntermNode *current)
- : mTraverser(traverser)
- {
- mTraverser->incrementDepth(current);
- }
- ~ScopedNodeInTraversalPath() { mTraverser->decrementDepth(); }
-
- private:
- TIntermTraverser *mTraverser;
- };
-
- TIntermNode *getParentNode() { 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)
- {
- if (mPath.size() > n + 1u)
- {
- return mPath[mPath.size() - n - 2u];
- }
- return nullptr;
- }
-
- const TIntermBlock *getParentBlock() const;
-
- 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 *_parent,
- TIntermNode *_original,
- TIntermSequence _replacements)
- : parent(_parent), original(_original), replacements(_replacements)
- {
- }
-
- 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);
-
- // Helper to create a temporary symbol node with the given qualifier.
- TIntermSymbol *createTempSymbol(const TType &type, TQualifier qualifier);
- // Helper to create a temporary symbol node.
- TIntermSymbol *createTempSymbol(const TType &type);
- // Create a node that declares but doesn't initialize a temporary symbol.
- TIntermDeclaration *createTempDeclaration(const TType &type);
- // Create a node that initializes the current temporary symbol with initializer. The symbol will
- // have the given qualifier.
- TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier);
- // Create a node that initializes the current temporary symbol with initializer.
- TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer);
- // Create a node that assigns rightNode to the current temporary symbol.
- TIntermBinary *createTempAssignment(TIntermTyped *rightNode);
- // Increment temporary symbol index.
- void nextTemporaryId();
-
- 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);
-
- const bool preVisit;
- const bool inVisit;
- const bool postVisit;
-
- int mDepth;
- int mMaxDepth;
-
- 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<NodeReplaceWithMultipleEntry> 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<NodeInsertMultipleEntry> mInsertions;
- std::vector<NodeUpdateEntry> mReplacements;
-
- // All the nodes from root to the current node during traversing.
- TVector<TIntermNode *> mPath;
-
- // All the code blocks from the root to the current node's parent during traversal.
- std::vector<ParentBlock> mParentBlockStack;
-
- TSymbolUniqueId *mTemporaryId;
-};
-
-// 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,
- int shaderVersion);
- virtual ~TLValueTrackingTraverser() {}
-
- void traverseBinary(TIntermBinary *node) final;
- void traverseUnary(TIntermUnary *node) final;
- void traverseFunctionPrototype(TIntermFunctionPrototype *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; }
-
- // Add a function encountered during traversal to the function map.
- void addToFunctionMap(const TSymbolUniqueId &id, TIntermSequence *paramSequence);
-
- // Return true if the prototype or definition of the function being called has been encountered
- // during traversal.
- bool isInFunctionMap(const TIntermAggregate *callNode) const;
-
- // Return the parameters sequence from the function definition or prototype.
- TIntermSequence *getFunctionParameters(const TIntermAggregate *callNode);
-
- // Track whether an l-value is required inside a function call.
- void setInFunctionCallOutParameter(bool inOutParameter);
- bool isInFunctionCallOutParameter() const;
-
- bool mOperatorRequiresLValue;
- bool mInFunctionCallOutParameter;
-
- // Map from function symbol id values to their parameter sequences
- TMap<int, TIntermSequence *> mFunctionMap;
-
- const int mShaderVersion;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_INTERMTRAVERSE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp b/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp
deleted file mode 100644
index aaad4f3c68..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-//
-// Copyright (c) 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/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, true, false), mDepthLimit(depthLimit)
- {
- }
-
- bool visitBinary(Visit, TIntermBinary *) override { return depthCheck(); }
- bool visitUnary(Visit, TIntermUnary *) override { return depthCheck(); }
- bool visitTernary(Visit, TIntermTernary *) override { return depthCheck(); }
- bool visitSwizzle(Visit, TIntermSwizzle *) override { return depthCheck(); }
- bool visitIfElse(Visit, TIntermIfElse *) override { return depthCheck(); }
- bool visitAggregate(Visit, TIntermAggregate *) override { return depthCheck(); }
- bool visitBlock(Visit, TIntermBlock *) override { return depthCheck(); }
- bool visitLoop(Visit, TIntermLoop *) override { return depthCheck(); }
- bool visitBranch(Visit, TIntermBranch *) override { return depthCheck(); }
-
- protected:
- bool depthCheck() const { return mMaxDepth < mDepthLimit; }
-
- int mDepthLimit;
-};
-
-} // anonymous namespace
-
-bool IsASTDepthBelowLimit(TIntermNode *root, int maxDepth)
-{
- MaxDepthTraverser traverser(maxDepth + 1);
- root->traverse(&traverser);
-
- return traverser.getMaxDepth() <= maxDepth;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h b/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h
deleted file mode 100644
index ef2f02c974..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Copyright (c) 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/src/3rdparty/angle/src/compiler/translator/NodeSearch.h b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h
deleted file mode 100644
index af86b8bde4..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// NodeSearch.h: Utilities for searching translator node graphs
-//
-
-#ifndef COMPILER_TRANSLATOR_NODESEARCH_H_
-#define COMPILER_TRANSLATOR_NODESEARCH_H_
-
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-template <class Parent>
-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<FindDiscard>
-{
- public:
- virtual bool visitBranch(Visit visit, TIntermBranch *node)
- {
- switch (node->getFlowOp())
- {
- case EOpKill:
- mFound = true;
- break;
-
- default:
- break;
- }
-
- return !mFound;
- }
-};
-}
-
-#endif // COMPILER_TRANSLATOR_NODESEARCH_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Operator.cpp b/src/3rdparty/angle/src/compiler/translator/Operator.cpp
deleted file mode 100644
index 7a2156611a..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Operator.cpp
+++ /dev/null
@@ -1,385 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#include "compiler/translator/Operator.h"
-
-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 EOpEqualComponentWise:
- return "equal";
- case EOpNotEqualComponentWise:
- return "notEqual";
- case EOpLessThanComponentWise:
- return "lessThan";
- case EOpGreaterThanComponentWise:
- return "greaterThan";
- case EOpLessThanEqualComponentWise:
- return "lessThanEqual";
- case EOpGreaterThanEqualComponentWise:
- return "greaterThanEqual";
-
- 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 EOpRadians:
- return "radians";
- case EOpDegrees:
- return "degrees";
- case EOpSin:
- return "sin";
- case EOpCos:
- return "cos";
- case EOpTan:
- return "tan";
- case EOpAsin:
- return "asin";
- case EOpAcos:
- return "acos";
- case EOpAtan:
- return "atan";
-
- case EOpSinh:
- return "sinh";
- case EOpCosh:
- return "cosh";
- case EOpTanh:
- return "tanh";
- case EOpAsinh:
- return "asinh";
- case EOpAcosh:
- return "acosh";
- case EOpAtanh:
- return "atanh";
-
- case EOpPow:
- return "pow";
- case EOpExp:
- return "exp";
- case EOpLog:
- return "log";
- case EOpExp2:
- return "exp2";
- case EOpLog2:
- return "log2";
- case EOpSqrt:
- return "sqrt";
- case EOpInverseSqrt:
- return "inversesqrt";
-
- case EOpAbs:
- return "abs";
- case EOpSign:
- return "sign";
- case EOpFloor:
- return "floor";
- case EOpTrunc:
- return "trunc";
- case EOpRound:
- return "round";
- case EOpRoundEven:
- return "roundEven";
- case EOpCeil:
- return "ceil";
- case EOpFract:
- return "fract";
- case EOpMod:
- return "mod";
- case EOpModf:
- return "modf";
- case EOpMin:
- return "min";
- case EOpMax:
- return "max";
- case EOpClamp:
- return "clamp";
- case EOpMix:
- return "mix";
- case EOpStep:
- return "step";
- case EOpSmoothStep:
- return "smoothstep";
- case EOpIsNan:
- return "isnan";
- case EOpIsInf:
- return "isinf";
-
- case EOpFloatBitsToInt:
- return "floatBitsToInt";
- case EOpFloatBitsToUint:
- return "floatBitsToUint";
- case EOpIntBitsToFloat:
- return "intBitsToFloat";
- case EOpUintBitsToFloat:
- return "uintBitsToFloat";
-
- case EOpFrexp:
- return "frexp";
- case EOpLdexp:
- return "ldexp";
-
- case EOpPackSnorm2x16:
- return "packSnorm2x16";
- case EOpPackUnorm2x16:
- return "packUnorm2x16";
- case EOpPackHalf2x16:
- return "packHalf2x16";
- case EOpUnpackSnorm2x16:
- return "unpackSnorm2x16";
- case EOpUnpackUnorm2x16:
- return "unpackUnorm2x16";
- case EOpUnpackHalf2x16:
- return "unpackHalf2x16";
-
- case EOpPackUnorm4x8:
- return "packUnorm4x8";
- case EOpPackSnorm4x8:
- return "packSnorm4x8";
- case EOpUnpackUnorm4x8:
- return "unpackUnorm4x8";
- case EOpUnpackSnorm4x8:
- return "unpackSnorm4x8";
-
- case EOpLength:
- return "length";
- case EOpDistance:
- return "distance";
- case EOpDot:
- return "dot";
- case EOpCross:
- return "cross";
- case EOpNormalize:
- return "normalize";
- case EOpFaceforward:
- return "faceforward";
- case EOpReflect:
- return "reflect";
- case EOpRefract:
- return "refract";
-
- case EOpDFdx:
- return "dFdx";
- case EOpDFdy:
- return "dFdy";
- case EOpFwidth:
- return "fwidth";
-
- case EOpMulMatrixComponentWise:
- return "matrixCompMult";
- case EOpOuterProduct:
- return "outerProduct";
- case EOpTranspose:
- return "transpose";
- case EOpDeterminant:
- return "determinant";
- case EOpInverse:
- return "inverse";
-
- case EOpAny:
- return "any";
- case EOpAll:
- return "all";
- case EOpLogicalNotComponentWise:
- return "not";
-
- case EOpBitfieldExtract:
- return "bitfieldExtract";
- case EOpBitfieldInsert:
- return "bitfieldInsert";
- case EOpBitfieldReverse:
- return "bitfieldReverse";
- case EOpBitCount:
- return "bitCount";
- case EOpFindLSB:
- return "findLSB";
- case EOpFindMSB:
- return "findMSB";
- case EOpUaddCarry:
- return "uaddCarry";
- case EOpUsubBorrow:
- return "usubBorrow";
- case EOpUmulExtended:
- return "umulExtended";
- case EOpImulExtended:
- return "imulExtended";
-
- case EOpKill:
- return "kill";
- case EOpReturn:
- return "return";
- case EOpBreak:
- return "break";
- case EOpContinue:
- return "continue";
-
- case EOpAssign:
- return "=";
- 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 "|=";
- case EOpBarrier:
- return "barrier";
- case EOpMemoryBarrier:
- return "memoryBarrier";
- case EOpMemoryBarrierAtomicCounter:
- return "memoryBarrierAtomicCounter";
- case EOpMemoryBarrierBuffer:
- return "memoryBarrierBuffer";
- case EOpMemoryBarrierImage:
- return "memoryBarrierImage";
- case EOpMemoryBarrierShared:
- return "memoryBarrierShared";
- case EOpGroupMemoryBarrier:
- return "groupMemoryBarrier";
-
- case EOpEmitVertex:
- return "EmitVertex";
- case EOpEndPrimitive:
- return "EndPrimitive";
- default:
- 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;
- }
-} \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/Operator.h b/src/3rdparty/angle/src/compiler/translator/Operator.h
deleted file mode 100644
index 72f3dbf3f6..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Operator.h
+++ /dev/null
@@ -1,255 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#ifndef COMPILER_TRANSLATOR_OPERATOR_H_
-#define COMPILER_TRANSLATOR_OPERATOR_H_
-
-//
-// Operators used by the high-level (parse tree) representation.
-//
-enum TOperator
-{
- 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.
- EOpCallInternalRawFunction,
-
- // Call a built-in function like a texture or image function.
- EOpCallBuiltInFunction,
-
- //
- // Unary operators
- //
-
- EOpNegative,
- EOpPositive,
- EOpLogicalNot,
- EOpBitwiseNot,
-
- EOpPostIncrement,
- EOpPostDecrement,
- EOpPreIncrement,
- EOpPreDecrement,
-
- EOpArrayLength,
-
- //
- // binary operations (ones with special GLSL syntax are used in TIntermBinary nodes, others in
- // TIntermAggregate nodes)
- //
-
- EOpAdd,
- EOpSub,
- EOpMul,
- EOpDiv,
- EOpIMod,
-
- EOpEqual,
- EOpNotEqual,
- EOpLessThan,
- EOpGreaterThan,
- EOpLessThanEqual,
- EOpGreaterThanEqual,
-
- EOpEqualComponentWise,
- EOpNotEqualComponentWise,
- EOpLessThanComponentWise,
- EOpLessThanEqualComponentWise,
- EOpGreaterThanComponentWise,
- EOpGreaterThanEqualComponentWise,
-
- EOpComma,
-
- EOpVectorTimesScalar,
- EOpVectorTimesMatrix,
- EOpMatrixTimesVector,
- EOpMatrixTimesScalar,
- EOpMatrixTimesMatrix,
-
- EOpLogicalOr,
- EOpLogicalXor,
- EOpLogicalAnd,
-
- EOpBitShiftLeft,
- EOpBitShiftRight,
-
- EOpBitwiseAnd,
- EOpBitwiseXor,
- EOpBitwiseOr,
-
- EOpIndexDirect,
- EOpIndexIndirect,
- EOpIndexDirectStruct,
- EOpIndexDirectInterfaceBlock,
-
- //
- // Built-in functions mapped to operators (either unary or with multiple parameters)
- //
-
- EOpRadians,
- EOpDegrees,
- EOpSin,
- EOpCos,
- EOpTan,
- EOpAsin,
- EOpAcos,
- EOpAtan,
-
- EOpSinh,
- EOpCosh,
- EOpTanh,
- EOpAsinh,
- EOpAcosh,
- EOpAtanh,
-
- EOpPow,
- EOpExp,
- EOpLog,
- EOpExp2,
- EOpLog2,
- EOpSqrt,
- EOpInverseSqrt,
-
- EOpAbs,
- EOpSign,
- EOpFloor,
- EOpTrunc,
- EOpRound,
- EOpRoundEven,
- EOpCeil,
- EOpFract,
- EOpMod,
- EOpModf,
- EOpMin,
- EOpMax,
- EOpClamp,
- EOpMix,
- EOpStep,
- EOpSmoothStep,
- EOpIsNan,
- EOpIsInf,
-
- EOpFloatBitsToInt,
- EOpFloatBitsToUint,
- EOpIntBitsToFloat,
- EOpUintBitsToFloat,
-
- EOpFrexp,
- EOpLdexp,
-
- EOpPackSnorm2x16,
- EOpPackUnorm2x16,
- EOpPackHalf2x16,
- EOpUnpackSnorm2x16,
- EOpUnpackUnorm2x16,
- EOpUnpackHalf2x16,
-
- EOpPackUnorm4x8,
- EOpPackSnorm4x8,
- EOpUnpackUnorm4x8,
- EOpUnpackSnorm4x8,
-
- EOpLength,
- EOpDistance,
- EOpDot,
- EOpCross,
- EOpNormalize,
- EOpFaceforward,
- EOpReflect,
- EOpRefract,
-
- EOpDFdx, // Fragment only, OES_standard_derivatives extension
- EOpDFdy, // Fragment only, OES_standard_derivatives extension
- EOpFwidth, // Fragment only, OES_standard_derivatives extension
-
- EOpMulMatrixComponentWise,
- EOpOuterProduct,
- EOpTranspose,
- EOpDeterminant,
- EOpInverse,
-
- EOpAny,
- EOpAll,
- EOpLogicalNotComponentWise,
-
- EOpBitfieldExtract,
- EOpBitfieldInsert,
- EOpBitfieldReverse,
- EOpBitCount,
- EOpFindLSB,
- EOpFindMSB,
- EOpUaddCarry,
- EOpUsubBorrow,
- EOpUmulExtended,
- EOpImulExtended,
-
- //
- // Branch
- //
-
- EOpKill, // Fragment only
- EOpReturn,
- EOpBreak,
- EOpContinue,
-
- //
- // Constructor
- //
-
- EOpConstruct,
-
- //
- // moves
- //
-
- EOpAssign,
- EOpInitialize,
- EOpAddAssign,
- EOpSubAssign,
-
- EOpMulAssign,
- EOpVectorTimesMatrixAssign,
- EOpVectorTimesScalarAssign,
- EOpMatrixTimesScalarAssign,
- EOpMatrixTimesMatrixAssign,
-
- EOpDivAssign,
- EOpIModAssign,
- EOpBitShiftLeftAssign,
- EOpBitShiftRightAssign,
- EOpBitwiseAndAssign,
- EOpBitwiseXorAssign,
- EOpBitwiseOrAssign,
-
- // barriers
- EOpBarrier,
- EOpMemoryBarrier,
- EOpMemoryBarrierAtomicCounter,
- EOpMemoryBarrierBuffer,
- EOpMemoryBarrierImage,
- EOpMemoryBarrierShared,
- EOpGroupMemoryBarrier,
-
- // Geometry only
- EOpEmitVertex,
- EOpEndPrimitive
-};
-
-// Returns the string corresponding to the operator in GLSL
-const char *GetOperatorString(TOperator op);
-
-// Say whether or not a binary or unary operation changes the value of a variable.
-bool IsAssignment(TOperator op);
-
-#endif // COMPILER_TRANSLATOR_OPERATOR_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp
deleted file mode 100644
index 50626c91c0..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#include "compiler/translator/OutputESSL.h"
-
-namespace sh
-{
-
-TOutputESSL::TOutputESSL(TInfoSinkBase &objSink,
- ShArrayIndexClampingStrategy clampingStrategy,
- ShHashFunction64 hashFunction,
- NameMap &nameMap,
- TSymbolTable *symbolTable,
- sh::GLenum shaderType,
- int shaderVersion,
- bool forceHighp,
- ShCompileOptions compileOptions)
- : TOutputGLSLBase(objSink,
- clampingStrategy,
- hashFunction,
- nameMap,
- symbolTable,
- shaderType,
- shaderVersion,
- SH_ESSL_OUTPUT,
- compileOptions),
- mForceHighp(forceHighp)
-{
-}
-
-bool TOutputESSL::writeVariablePrecision(TPrecision precision)
-{
- if (precision == EbpUndefined)
- return false;
-
- TInfoSinkBase &out = objSink();
- if (mForceHighp)
- out << getPrecisionString(EbpHigh);
- else
- out << getPrecisionString(precision);
- return true;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h
deleted file mode 100644
index e0c7bf2ae6..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#ifndef COMPILER_TRANSLATOR_OUTPUTESSL_H_
-#define COMPILER_TRANSLATOR_OUTPUTESSL_H_
-
-#include "compiler/translator/OutputGLSLBase.h"
-
-namespace sh
-{
-
-class TOutputESSL : public TOutputGLSLBase
-{
- public:
- TOutputESSL(TInfoSinkBase &objSink,
- ShArrayIndexClampingStrategy clampingStrategy,
- ShHashFunction64 hashFunction,
- NameMap &nameMap,
- TSymbolTable *symbolTable,
- sh::GLenum shaderType,
- int shaderVersion,
- bool forceHighp,
- ShCompileOptions compileOptions);
-
- protected:
- bool writeVariablePrecision(TPrecision precision) override;
-
- private:
- bool mForceHighp;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_OUTPUTESSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp
deleted file mode 100644
index 1bad05dab9..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#include "compiler/translator/OutputGLSL.h"
-
-#include "compiler/translator/Compiler.h"
-
-namespace sh
-{
-
-TOutputGLSL::TOutputGLSL(TInfoSinkBase &objSink,
- ShArrayIndexClampingStrategy clampingStrategy,
- ShHashFunction64 hashFunction,
- NameMap &nameMap,
- TSymbolTable *symbolTable,
- sh::GLenum shaderType,
- int shaderVersion,
- ShShaderOutput output,
- ShCompileOptions compileOptions)
- : TOutputGLSLBase(objSink,
- clampingStrategy,
- hashFunction,
- nameMap,
- symbolTable,
- shaderType,
- shaderVersion,
- output,
- compileOptions)
-{
-}
-
-bool TOutputGLSL::writeVariablePrecision(TPrecision)
-{
- return false;
-}
-
-void TOutputGLSL::visitSymbol(TIntermSymbol *node)
-{
- TInfoSinkBase &out = objSink();
-
- const TString &symbol = node->getSymbol();
- if (symbol == "gl_FragDepthEXT")
- {
- out << "gl_FragDepth";
- }
- else if (symbol == "gl_FragColor" && sh::IsGLSL130OrNewer(getShaderOutput()))
- {
- out << "webgl_FragColor";
- }
- else if (symbol == "gl_FragData" && sh::IsGLSL130OrNewer(getShaderOutput()))
- {
- out << "webgl_FragData";
- }
- else if (symbol == "gl_SecondaryFragColorEXT")
- {
- out << "angle_SecondaryFragColor";
- }
- else if (symbol == "gl_SecondaryFragDataEXT")
- {
- out << "angle_SecondaryFragData";
- }
- else
- {
- TOutputGLSLBase::visitSymbol(node);
- }
-}
-
-TString TOutputGLSL::translateTextureFunction(const TString &name)
-{
- 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", "textureCube", "texture",
- "textureCubeLod", "textureLod",
- // Extensions
- "texture2DLodEXT", "textureLod", "texture2DProjLodEXT", "textureProjLod",
- "textureCubeLodEXT", "textureLod", "texture2DGradEXT", "textureGrad",
- "texture2DProjGradEXT", "textureProjGrad", "textureCubeGradEXT", "textureGrad", nullptr,
- nullptr};
- const char **mapping =
- (sh::IsGLSL130OrNewer(getShaderOutput())) ? legacyToCoreRename : simpleRename;
-
- for (int i = 0; mapping[i] != nullptr; i += 2)
- {
- if (name == mapping[i])
- {
- return mapping[i + 1];
- }
- }
-
- return name;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h
deleted file mode 100644
index c80abec1a6..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#ifndef COMPILER_TRANSLATOR_OUTPUTGLSL_H_
-#define COMPILER_TRANSLATOR_OUTPUTGLSL_H_
-
-#include "compiler/translator/OutputGLSLBase.h"
-
-namespace sh
-{
-
-class TOutputGLSL : public TOutputGLSLBase
-{
- public:
- TOutputGLSL(TInfoSinkBase &objSink,
- ShArrayIndexClampingStrategy clampingStrategy,
- ShHashFunction64 hashFunction,
- NameMap &nameMap,
- TSymbolTable *symbolTable,
- sh::GLenum shaderType,
- int shaderVersion,
- ShShaderOutput output,
- ShCompileOptions compileOptions);
-
- protected:
- bool writeVariablePrecision(TPrecision) override;
- void visitSymbol(TIntermSymbol *node) override;
- TString translateTextureFunction(const TString &name) override;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_OUTPUTGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp
deleted file mode 100644
index edaf2ebebf..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp
+++ /dev/null
@@ -1,1357 +0,0 @@
-//
-// Copyright (c) 2002-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/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 <cfloat>
-
-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;
- }
- return true;
-}
-
-class CommaSeparatedListItemPrefixGenerator
-{
- public:
- CommaSeparatedListItemPrefixGenerator() : mFirst(true) {}
- private:
- bool mFirst;
-
- friend TInfoSinkBase &operator<<(TInfoSinkBase &out,
- CommaSeparatedListItemPrefixGenerator &gen);
-};
-
-TInfoSinkBase &operator<<(TInfoSinkBase &out, CommaSeparatedListItemPrefixGenerator &gen)
-{
- if (gen.mFirst)
- {
- gen.mFirst = false;
- }
- else
- {
- out << ", ";
- }
- return out;
-}
-
-} // namespace
-
-TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
- ShArrayIndexClampingStrategy clampingStrategy,
- ShHashFunction64 hashFunction,
- NameMap &nameMap,
- TSymbolTable *symbolTable,
- sh::GLenum shaderType,
- int shaderVersion,
- ShShaderOutput output,
- ShCompileOptions compileOptions)
- : TIntermTraverser(true, true, true, symbolTable),
- mObjSink(objSink),
- mDeclaringVariable(false),
- mClampingStrategy(clampingStrategy),
- mHashFunction(hashFunction),
- mNameMap(nameMap),
- mShaderType(shaderType),
- mShaderVersion(shaderVersion),
- mOutput(output),
- mCompileOptions(compileOptions)
-{
-}
-
-void TOutputGLSLBase::writeInvariantQualifier(const TType &type)
-{
- if (!sh::RemoveInvariant(mShaderType, mShaderVersion, mOutput, mCompileOptions))
- {
- TInfoSinkBase &out = objSink();
- out << "invariant ";
- }
-}
-
-void TOutputGLSLBase::writeFloat(TInfoSinkBase &out, float f)
-{
- if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300)
- {
- out << "uintBitsToFloat(" << gl::bitCast<uint32_t>(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::writeBuiltInFunctionTriplet(Visit visit,
- TOperator op,
- bool useEmulatedFunction)
-{
- TInfoSinkBase &out = objSink();
- if (visit == PreVisit)
- {
- const char *opStr(GetOperatorString(op));
- if (useEmulatedFunction)
- {
- BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, opStr);
- }
- else
- {
- out << opStr;
- }
- out << "(";
- }
- else
- {
- writeTriplet(visit, nullptr, ", ", ")");
- }
-}
-
-void TOutputGLSLBase::writeLayoutQualifier(TIntermTyped *variable)
-{
- const TType &type = variable->getType();
-
- if (!NeedsToWriteLayoutQualifier(type))
- {
- return;
- }
-
- TInfoSinkBase &out = objSink();
- const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
- out << "layout(";
-
- CommaSeparatedListItemPrefixGenerator listItemPrefix;
-
- if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn ||
- IsVarying(type.getQualifier()))
- {
- if (layoutQualifier.location >= 0)
- {
- out << listItemPrefix << "location = " << layoutQualifier.location;
- }
- }
-
- if (type.getQualifier() == EvqFragmentOut)
- {
- if (layoutQualifier.yuv == true)
- {
- out << listItemPrefix << "yuv";
- }
- }
-
- if (IsOpaqueType(type.getBasicType()))
- {
- if (layoutQualifier.binding >= 0)
- {
- out << listItemPrefix << "binding = " << layoutQualifier.binding;
- }
- }
-
- 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;
- }
-
- out << ") ";
-}
-
-const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier)
-{
- if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 &&
- (mCompileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0)
- {
- 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;
- }
- }
- return sh::getQualifierString(qualifier);
-}
-
-void TOutputGLSLBase::writeVariableType(const TType &type)
-{
- TQualifier qualifier = type.getQualifier();
- TInfoSinkBase &out = objSink();
- if (type.isInvariant())
- {
- writeInvariantQualifier(type);
- }
- if (type.getBasicType() == EbtInterfaceBlock)
- {
- TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
- declareInterfaceBlockLayout(interfaceBlock);
- }
- if (qualifier != EvqTemporary && qualifier != EvqGlobal)
- {
- const char *qualifierString = mapQualifierToString(qualifier);
- if (qualifierString && qualifierString[0] != '\0')
- {
- out << qualifierString << " ";
- }
- }
-
- const TMemoryQualifier &memoryQualifier = type.getMemoryQualifier();
- if (memoryQualifier.readonly)
- {
- ASSERT(IsImage(type.getBasicType()));
- out << "readonly ";
- }
-
- if (memoryQualifier.writeonly)
- {
- ASSERT(IsImage(type.getBasicType()));
- out << "writeonly ";
- }
-
- if (memoryQualifier.coherent)
- {
- ASSERT(IsImage(type.getBasicType()));
- out << "coherent ";
- }
-
- if (memoryQualifier.restrictQualifier)
- {
- ASSERT(IsImage(type.getBasicType()));
- out << "restrict ";
- }
-
- if (memoryQualifier.volatileQualifier)
- {
- ASSERT(IsImage(type.getBasicType()));
- out << "volatile ";
- }
-
- // Declare the struct if we have not done so already.
- if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct()))
- {
- const TStructure *structure = type.getStruct();
-
- declareStruct(structure);
-
- if (!structure->name().empty())
- {
- mDeclaredStructs.insert(structure->uniqueId());
- }
- }
- else if (type.getBasicType() == EbtInterfaceBlock)
- {
- TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
- declareInterfaceBlock(interfaceBlock);
- }
- else
- {
- if (writeVariablePrecision(type.getPrecision()))
- out << " ";
- out << getTypeName(type);
- }
-}
-
-void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args)
-{
- TInfoSinkBase &out = objSink();
- for (TIntermSequence::const_iterator iter = args.begin(); iter != args.end(); ++iter)
- {
- const TIntermSymbol *arg = (*iter)->getAsSymbolNode();
- ASSERT(arg != nullptr);
-
- const TType &type = arg->getType();
- writeVariableType(type);
-
- if (!arg->getName().getString().empty())
- out << " " << hashName(arg->getName());
- if (type.isArray())
- out << ArrayString(type);
-
- // Put a comma if this is not the last argument.
- if (iter != args.end() - 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(TName(structure->name())) << "(";
-
- 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 << hashVariableName(node->getName());
-
- if (mDeclaringVariable && node->getType().isArray())
- out << ArrayString(node->getType());
-}
-
-void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node)
-{
- writeConstantUnion(node->getType(), node->getUnionArrayPointer());
-}
-
-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:
- writeTriplet(visit, nullptr, "[", "]");
- break;
- case EOpIndexIndirect:
- if (node->getAddIndexClamp())
- {
- if (visit == InVisit)
- {
- if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
- out << "[int(clamp(float(";
- else
- out << "[webgl_int_clamp(";
- }
- else if (visit == PostVisit)
- {
- TIntermTyped *left = node->getLeft();
- TType leftType = left->getType();
-
- if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
- out << "), 0.0, float(";
- else
- out << ", 0, ";
-
- if (leftType.isUnsizedArray())
- {
- // For runtime-sized arrays in ESSL 3.10 we need to call the length method
- // to get the length to clamp against. See ESSL 3.10 section 4.1.9. Note
- // that a runtime-sized array expression is guaranteed not to have side
- // effects, so it's fine to add the expression to the output twice.
- ASSERT(mShaderVersion >= 310);
- ASSERT(!left->hasSideEffects());
- left->traverse(this);
- out << ".length() - 1";
- }
- else
- {
- int maxSize;
- if (leftType.isArray())
- {
- maxSize = static_cast<int>(leftType.getOutermostArraySize()) - 1;
- }
- else
- {
- maxSize = leftType.getNominalSize() - 1;
- }
- out << maxSize;
- }
- if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
- out << ")))]";
- else
- out << ")]";
- }
- }
- else
- {
- 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)];
-
- TString fieldName = field->name();
- if (!mSymbolTable->findBuiltIn(structure->name(), mShaderVersion))
- fieldName = hashName(TName(fieldName));
-
- out << fieldName;
- 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)];
-
- TString fieldName = field->name();
- if (!mSymbolTable->findBuiltIn(interfaceBlock->name(), mShaderVersion))
- {
- fieldName = hashName(TName(fieldName));
- }
- else
- {
- ASSERT(interfaceBlock->name() == "gl_PerVertex");
- }
-
- out << fieldName;
- 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)
-{
- TString preString;
- TString 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;
-
- case EOpRadians:
- case EOpDegrees:
- case EOpSin:
- case EOpCos:
- case EOpTan:
- case EOpAsin:
- case EOpAcos:
- case EOpAtan:
- case EOpSinh:
- case EOpCosh:
- case EOpTanh:
- case EOpAsinh:
- case EOpAcosh:
- case EOpAtanh:
- case EOpExp:
- case EOpLog:
- case EOpExp2:
- case EOpLog2:
- case EOpSqrt:
- case EOpInverseSqrt:
- case EOpAbs:
- case EOpSign:
- case EOpFloor:
- case EOpTrunc:
- case EOpRound:
- case EOpRoundEven:
- case EOpCeil:
- case EOpFract:
- case EOpIsNan:
- case EOpIsInf:
- case EOpFloatBitsToInt:
- case EOpFloatBitsToUint:
- case EOpIntBitsToFloat:
- case EOpUintBitsToFloat:
- case EOpPackSnorm2x16:
- case EOpPackUnorm2x16:
- case EOpPackHalf2x16:
- case EOpUnpackSnorm2x16:
- case EOpUnpackUnorm2x16:
- case EOpUnpackHalf2x16:
- case EOpPackUnorm4x8:
- case EOpPackSnorm4x8:
- case EOpUnpackUnorm4x8:
- case EOpUnpackSnorm4x8:
- case EOpLength:
- case EOpNormalize:
- case EOpDFdx:
- case EOpDFdy:
- case EOpFwidth:
- case EOpTranspose:
- case EOpDeterminant:
- case EOpInverse:
- case EOpAny:
- case EOpAll:
- case EOpLogicalNotComponentWise:
- case EOpBitfieldReverse:
- case EOpBitCount:
- case EOpFindLSB:
- case EOpFindMSB:
- writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction());
- return true;
- default:
- UNREACHABLE();
- }
-
- writeTriplet(visit, preString.c_str(), nullptr, postString.c_str());
-
- 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 << "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 (mDepth > 0)
- {
- out << "{\n";
- }
-
- for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
- iter != node->getSequence()->end(); ++iter)
- {
- TIntermNode *curNode = *iter;
- ASSERT(curNode != nullptr);
- curNode->traverse(this);
-
- if (isSingleStatement(curNode))
- out << ";\n";
- }
-
- // Scope the blocks except when at the global scope.
- if (mDepth > 0)
- {
- out << "}\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::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
-{
- TInfoSinkBase &out = objSink();
- ASSERT(visit == PreVisit);
- const TIntermSymbol *symbol = node->getSymbol();
- out << "invariant " << hashVariableName(symbol->getName());
- return false;
-}
-
-bool TOutputGLSLBase::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
-{
- TInfoSinkBase &out = objSink();
- ASSERT(visit == PreVisit);
-
- const TType &type = node->getType();
- writeVariableType(type);
- if (type.isArray())
- out << ArrayString(type);
-
- out << " " << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo());
-
- out << "(";
- writeFunctionParameters(*(node->getSequence()));
- out << ")";
-
- return false;
-}
-
-bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- bool visitChildren = true;
- TInfoSinkBase &out = objSink();
- switch (node->getOp())
- {
- case EOpCallFunctionInAST:
- case EOpCallInternalRawFunction:
- case EOpCallBuiltInFunction:
- // Function call.
- if (visit == PreVisit)
- {
- if (node->getOp() == EOpCallBuiltInFunction)
- {
- out << translateTextureFunction(node->getFunctionSymbolInfo()->getName());
- }
- else
- {
- out << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo());
- }
- out << "(";
- }
- else if (visit == InVisit)
- out << ", ";
- else
- out << ")";
- break;
- case EOpConstruct:
- writeConstructorTriplet(visit, node->getType());
- break;
-
- case EOpEqualComponentWise:
- case EOpNotEqualComponentWise:
- case EOpLessThanComponentWise:
- case EOpGreaterThanComponentWise:
- case EOpLessThanEqualComponentWise:
- case EOpGreaterThanEqualComponentWise:
- case EOpMod:
- case EOpModf:
- case EOpPow:
- case EOpAtan:
- case EOpMin:
- case EOpMax:
- case EOpClamp:
- case EOpMix:
- case EOpStep:
- case EOpSmoothStep:
- case EOpFrexp:
- case EOpLdexp:
- case EOpDistance:
- case EOpDot:
- case EOpCross:
- case EOpFaceforward:
- case EOpReflect:
- case EOpRefract:
- case EOpMulMatrixComponentWise:
- case EOpOuterProduct:
- case EOpBitfieldExtract:
- case EOpBitfieldInsert:
- case EOpUaddCarry:
- case EOpUsubBorrow:
- case EOpUmulExtended:
- case EOpImulExtended:
- case EOpBarrier:
- case EOpMemoryBarrier:
- case EOpMemoryBarrierAtomicCounter:
- case EOpMemoryBarrierBuffer:
- case EOpMemoryBarrierImage:
- case EOpMemoryBarrierShared:
- case EOpGroupMemoryBarrier:
- case EOpEmitVertex:
- case EOpEndPrimitive:
- writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction());
- break;
- default:
- UNREACHABLE();
- }
- return visitChildren;
-}
-
-bool TOutputGLSLBase::visitDeclaration(Visit visit, TIntermDeclaration *node)
-{
- TInfoSinkBase &out = objSink();
-
- // Variable declaration.
- if (visit == PreVisit)
- {
- const TIntermSequence &sequence = *(node->getSequence());
- TIntermTyped *variable = sequence.front()->getAsTyped();
- writeLayoutQualifier(variable);
- writeVariableType(variable->getType());
- if (variable->getAsSymbolNode() == nullptr ||
- !variable->getAsSymbolNode()->getSymbol().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)
- {
- 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.
- }
-}
-
-TString TOutputGLSLBase::getTypeName(const TType &type)
-{
- return GetTypeName(type, mHashFunction, &mNameMap);
-}
-
-TString TOutputGLSLBase::hashName(const TName &name)
-{
- return HashName(name, mHashFunction, &mNameMap);
-}
-
-TString TOutputGLSLBase::hashVariableName(const TName &name)
-{
- if (mSymbolTable->findBuiltIn(name.getString(), mShaderVersion) != nullptr ||
- name.getString().substr(0, 3) == "gl_")
- {
- if (mCompileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM &&
- name.getString() == "gl_ViewID_OVR")
- {
- TName uniformName(TString("ViewID_OVR"));
- uniformName.setInternal(true);
- return hashName(uniformName);
- }
- return name.getString();
- }
- return hashName(name);
-}
-
-TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info)
-{
- if (info.isMain())
- {
- return info.getName();
- }
- else
- {
- return hashName(info.getNameObj());
- }
-}
-
-bool TOutputGLSLBase::structDeclared(const TStructure *structure) const
-{
- ASSERT(structure);
- if (structure->name().empty())
- {
- return false;
- }
-
- return (mDeclaredStructs.count(structure->uniqueId()) > 0);
-}
-
-void TOutputGLSLBase::declareStruct(const TStructure *structure)
-{
- TInfoSinkBase &out = objSink();
-
- out << "struct " << hashName(TName(structure->name())) << "{\n";
- const TFieldList &fields = structure->fields();
- for (size_t i = 0; i < fields.size(); ++i)
- {
- const TField *field = fields[i];
- if (writeVariablePrecision(field->type()->getPrecision()))
- out << " ";
- out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
- if (field->type()->isArray())
- out << ArrayString(*field->type());
- out << ";\n";
- }
- out << "}";
-}
-
-void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock)
-{
- 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;
- }
-
- out << ", ";
-
- if (interfaceBlock->blockBinding() > 0)
- {
- out << "binding = " << interfaceBlock->blockBinding();
- out << ", ";
- }
-
- switch (interfaceBlock->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::declareInterfaceBlock(const TInterfaceBlock *interfaceBlock)
-{
- TInfoSinkBase &out = objSink();
-
- out << hashName(TName(interfaceBlock->name())) << "{\n";
- const TFieldList &fields = interfaceBlock->fields();
- for (size_t i = 0; i < fields.size(); ++i)
- {
- const TField *field = fields[i];
- if (writeVariablePrecision(field->type()->getPrecision()))
- out << " ";
- out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
- if (field->type()->isArray())
- out << ArrayString(*field->type());
- out << ";\n";
- }
- out << "}";
-}
-
-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";
- }
-}
-
-// 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 NeedsToWriteLayoutQualifier(const TType &type)
-{
- if (type.getBasicType() == EbtInterfaceBlock)
- {
- return false;
- }
-
- const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
-
- if ((type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn ||
- IsVarying(type.getQualifier())) &&
- layoutQualifier.location >= 0)
- {
- return true;
- }
-
- if (type.getQualifier() == EvqFragmentOut && layoutQualifier.yuv == true)
- {
- return true;
- }
-
- if (IsOpaqueType(type.getBasicType()) && layoutQualifier.binding != -1)
- {
- return true;
- }
-
- if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified)
- {
- return true;
- }
- return false;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h
deleted file mode 100644
index 592a310be4..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h
+++ /dev/null
@@ -1,122 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#ifndef COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
-#define COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
-
-#include <set>
-
-#include "compiler/translator/HashNames.h"
-#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-class TOutputGLSLBase : public TIntermTraverser
-{
- public:
- TOutputGLSLBase(TInfoSinkBase &objSink,
- ShArrayIndexClampingStrategy clampingStrategy,
- ShHashFunction64 hashFunction,
- NameMap &nameMap,
- TSymbolTable *symbolTable,
- sh::GLenum shaderType,
- int shaderVersion,
- ShShaderOutput output,
- 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, which are not
- // hashed.
- TString hashName(const TName &name);
-
- protected:
- TInfoSinkBase &objSink() { return mObjSink; }
- void writeFloat(TInfoSinkBase &out, float f);
- void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr);
- virtual void writeLayoutQualifier(TIntermTyped *variable);
- void writeInvariantQualifier(const TType &type);
- void writeVariableType(const TType &type);
- virtual bool writeVariablePrecision(TPrecision precision) = 0;
- void writeFunctionParameters(const TIntermSequence &args);
- const TConstantUnion *writeConstantUnion(const TType &type, const TConstantUnion *pConstUnion);
- void writeConstructorTriplet(Visit visit, const TType &type);
- TString 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;
- bool visitFunctionPrototype(Visit visit, 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 visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
- bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
- bool visitLoop(Visit visit, TIntermLoop *node) override;
- bool visitBranch(Visit visit, TIntermBranch *node) override;
-
- void visitCodeBlock(TIntermBlock *node);
-
- // Same as hashName(), but without hashing built-in variables.
- TString hashVariableName(const TName &name);
- // Same as hashName(), but without hashing internal functions or "main".
- TString hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info);
- // Used to translate function names for differences between ESSL and GLSL
- virtual TString translateTextureFunction(const TString &name) { return name; }
-
- private:
- bool structDeclared(const TStructure *structure) const;
- void declareStruct(const TStructure *structure);
-
- void declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock);
- void declareInterfaceBlock(const TInterfaceBlock *interfaceBlock);
-
- void writeBuiltInFunctionTriplet(Visit visit, TOperator op, bool useEmulatedFunction);
-
- const char *mapQualifierToString(TQualifier qialifier);
-
- TInfoSinkBase &mObjSink;
- bool mDeclaringVariable;
-
- // This set contains all the ids of the structs from every scope.
- std::set<int> mDeclaredStructs;
-
- ShArrayIndexClampingStrategy mClampingStrategy;
-
- // name hashing.
- ShHashFunction64 mHashFunction;
-
- NameMap &mNameMap;
-
- sh::GLenum mShaderType;
-
- const int mShaderVersion;
-
- ShShaderOutput mOutput;
-
- ShCompileOptions mCompileOptions;
-};
-
-void WriteGeometryShaderLayoutQualifiers(TInfoSinkBase &out,
- sh::TLayoutPrimitiveType inputPrimitive,
- int invocations,
- sh::TLayoutPrimitiveType outputPrimitive,
- int maxVertices);
-
-bool NeedsToWriteLayoutQualifier(const TType &type);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp
deleted file mode 100644
index d5ff761430..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp
+++ /dev/null
@@ -1,3084 +0,0 @@
-//
-// Copyright (c) 2002-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/OutputHLSL.h"
-
-#include <algorithm>
-#include <cfloat>
-#include <stdio.h>
-
-#include "common/angleutils.h"
-#include "common/debug.h"
-#include "common/utilities.h"
-#include "compiler/translator/BuiltInFunctionEmulator.h"
-#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
-#include "compiler/translator/ImageFunctionHLSL.h"
-#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/NodeSearch.h"
-#include "compiler/translator/RemoveSwitchFallThrough.h"
-#include "compiler/translator/SearchSymbol.h"
-#include "compiler/translator/StructureHLSL.h"
-#include "compiler/translator/TextureFunctionHLSL.h"
-#include "compiler/translator/TranslatorHLSL.h"
-#include "compiler/translator/UniformHLSL.h"
-#include "compiler/translator/UtilsHLSL.h"
-#include "compiler/translator/blocklayout.h"
-#include "compiler/translator/util.h"
-
-namespace sh
-{
-
-namespace
-{
-
-TString ArrayHelperFunctionName(const char *prefix, const TType &type)
-{
- TStringStream fnName;
- 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);
-}
-
-bool IsInStd140InterfaceBlock(TIntermTyped *node)
-{
- TIntermBinary *binaryNode = node->getAsBinaryNode();
-
- if (binaryNode)
- {
- return IsInStd140InterfaceBlock(binaryNode->getLeft());
- }
-
- const TType &type = node->getType();
-
- // determine if we are in the standard layout
- const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
- if (interfaceBlock)
- {
- return (interfaceBlock->blockStorage() == EbsStd140);
- }
-
- return false;
-}
-
-} // anonymous namespace
-
-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<uint32_t>(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,
- int shaderVersion,
- const TExtensionBehavior &extensionBehavior,
- const char *sourcePath,
- ShShaderOutput outputType,
- int numRenderTargets,
- const std::vector<Uniform> &uniforms,
- ShCompileOptions compileOptions,
- TSymbolTable *symbolTable,
- PerformanceDiagnostics *perfDiagnostics)
- : TIntermTraverser(true, true, true, symbolTable),
- mShaderType(shaderType),
- mShaderVersion(shaderVersion),
- mExtensionBehavior(extensionBehavior),
- mSourcePath(sourcePath),
- mOutputType(outputType),
- mCompileOptions(compileOptions),
- mNumRenderTargets(numRenderTargets),
- mCurrentFunctionMetadata(nullptr),
- mPerfDiagnostics(perfDiagnostics)
-{
- mInsideFunction = false;
-
- mUsesFragColor = false;
- mUsesFragData = false;
- mUsesDepthRange = false;
- mUsesFragCoord = false;
- mUsesPointCoord = false;
- mUsesFrontFacing = false;
- mUsesPointSize = false;
- mUsesInstanceID = false;
- mHasMultiviewExtensionEnabled =
- IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview);
- mUsesViewID = false;
- mUsesVertexID = false;
- mUsesFragDepth = false;
- mUsesNumWorkGroups = false;
- mUsesWorkGroupID = false;
- mUsesLocalInvocationID = false;
- mUsesGlobalInvocationID = false;
- mUsesLocalInvocationIndex = false;
- mUsesXor = false;
- mUsesDiscardRewriting = false;
- mUsesNestedBreak = false;
- mRequiresIEEEStrictCompiling = false;
-
- mUniqueIndex = 0;
-
- mOutputLod0Function = false;
- mInsideDiscontinuousLoop = false;
- mNestedLoopDepth = 0;
-
- mExcessiveLoopIndex = nullptr;
-
- mStructureHLSL = new StructureHLSL;
- mUniformHLSL = new UniformHLSL(shaderType, mStructureHLSL, outputType, uniforms);
- mTextureFunctionHLSL = new TextureFunctionHLSL;
- mImageFunctionHLSL = new ImageFunctionHLSL;
-
- if (mOutputType == SH_HLSL_3_0_OUTPUT)
- {
- // Fragment shaders need dx_DepthRange, dx_ViewCoords and dx_DepthFront.
- // Vertex shaders need a slightly different set: dx_DepthRange, dx_ViewCoords and
- // dx_ViewAdjust.
- // In both cases total 3 uniform registers need to be reserved.
- mUniformHLSL->reserveUniformRegisters(3);
- }
-
- // Reserve registers for the default uniform block and driver constants
- mUniformHLSL->reserveUniformBlockRegisters(2);
-}
-
-OutputHLSL::~OutputHLSL()
-{
- SafeDelete(mStructureHLSL);
- SafeDelete(mUniformHLSL);
- SafeDelete(mTextureFunctionHLSL);
- SafeDelete(mImageFunctionHLSL);
- 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 & SH_EMULATE_ISNAN_FLOAT_FUNCTION) != 0)
- {
- 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<MappedStruct> 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<std::string, unsigned int> &OutputHLSL::getUniformBlockRegisterMap() const
-{
- return mUniformHLSL->getUniformBlockRegisterMap();
-}
-
-const std::map<std::string, unsigned int> &OutputHLSL::getUniformRegisterMap() const
-{
- return mUniformHLSL->getUniformRegisterMap();
-}
-
-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;
- 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<MappedStruct> &std140Structs) const
-{
- TString mappedStructs;
-
- for (auto &mappedStruct : std140Structs)
- {
- TInterfaceBlock *interfaceBlock =
- mappedStruct.blockDeclarator->getType().getInterfaceBlock();
- const TString &interfaceBlockName = interfaceBlock->name();
- const TName &instanceName = mappedStruct.blockDeclarator->getName();
- if (mReferencedUniformBlocks.count(interfaceBlockName) == 0 &&
- (instanceName.getString() == "" ||
- mReferencedUniformBlocks.count(instanceName.getString()) == 0))
- {
- continue;
- }
-
- 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 (instanceName.getString() != "")
- {
- unsigned int instanceStringArrayIndex = GL_INVALID_INDEX;
- if (isInstanceArray)
- instanceStringArrayIndex = instanceArrayIndex;
- TString instanceString = mUniformHLSL->uniformBlockInstanceString(
- *interfaceBlock, 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());
- }
-
- mappedStructs += " =\n";
- mappedStructs += structInitializerString(0, *structType, originalName);
- mappedStructs += ";\n";
- }
- }
- return mappedStructs;
-}
-
-void OutputHLSL::header(TInfoSinkBase &out,
- const std::vector<MappedStruct> &std140Structs,
- const BuiltInFunctionEmulator *builtInFunctionEmulator) const
-{
- TString varyings;
- TString attributes;
- TString mappedStructs = generateStructMapping(std140Structs);
-
- for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin();
- varying != mReferencedVaryings.end(); varying++)
- {
- const TType &type = varying->second->getType();
- const TString &name = varying->second->getSymbol();
-
- // Program linking depends on this exact format
- varyings += "static " + InterpolationString(type.getQualifier()) + " " + TypeString(type) +
- " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n";
- }
-
- for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin();
- attribute != mReferencedAttributes.end(); attribute++)
- {
- const TType &type = attribute->second->getType();
- const TString &name = attribute->second->getSymbol();
-
- attributes += "static " + TypeString(type) + " " + Decorate(name) + ArrayString(type) +
- " = " + initializer(type) + ";\n";
- }
-
- out << mStructureHLSL->structsHeader();
-
- mUniformHLSL->uniformsHeader(out, mOutputType, mReferencedUniforms, mSymbolTable);
- out << mUniformHLSL->uniformBlocksHeader(mReferencedUniformBlocks);
-
- 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";
-
- if (mShaderType == GL_FRAGMENT_SHADER)
- {
- const bool usingMRTExtension =
- IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers);
-
- out << "// Varyings\n";
- out << varyings;
- out << "\n";
-
- if (mShaderVersion >= 300)
- {
- for (ReferencedSymbols::const_iterator outputVariableIt =
- mReferencedOutputVariables.begin();
- outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++)
- {
- const TString &variableName = outputVariableIt->first;
- const TType &variableType = outputVariableIt->second->getType();
-
- out << "static " + TypeString(variableType) + " out_" + variableName +
- ArrayString(variableType) + " = " + initializer(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 (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";
- }
-
- 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";
- }
-
- 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);\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";
- }
-
- if (mOutputType == SH_HLSL_4_1_OUTPUT)
- {
- mUniformHLSL->samplerMetadataUniforms(out, "c4");
- }
-
- out << "};\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 << "\n";
-
- if (mUsesDepthRange)
- {
- out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, "
- "dx_DepthRange.y, dx_DepthRange.z};\n"
- "\n";
- }
-
- if (!mappedStructs.empty())
- {
- out << "// Structures from std140 blocks with padding removed\n";
- out << "\n";
- out << mappedStructs;
- out << "\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";
- }
- }
- else if (mShaderType == GL_VERTEX_SHADER)
- {
- out << "// Attributes\n";
- out << attributes;
- 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";
- out << varyings;
- 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";
- }
-
- if (mOutputType == SH_HLSL_4_1_OUTPUT)
- {
- mUniformHLSL->samplerMetadataUniforms(out, "c4");
- }
-
- 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"
- "\n";
- }
-
- if (mUsesDepthRange)
- {
- out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, "
- "dx_DepthRange.y, dx_DepthRange.z};\n"
- "\n";
- }
-
- if (!mappedStructs.empty())
- {
- out << "// Structures from std140 blocks with padding removed\n";
- out << "\n";
- out << mappedStructs;
- out << "\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);
- mUniformHLSL->samplerMetadataUniforms(out, "c1");
- out << "};\n";
-
- // Follow built-in variables would be initialized in
- // DynamicHLSL::generateComputeShaderLinkHLSL, if they
- // are used in compute shader.
- if (mUsesWorkGroupID)
- {
- out << "static uint3 gl_WorkGroupID = uint3(0, 0, 0);\n";
- }
-
- if (mUsesLocalInvocationID)
- {
- out << "static uint3 gl_LocalInvocationID = uint3(0, 0, 0);\n";
- }
-
- if (mUsesGlobalInvocationID)
- {
- out << "static uint3 gl_GlobalInvocationID = uint3(0, 0, 0);\n";
- }
-
- if (mUsesLocalInvocationIndex)
- {
- out << "static uint gl_LocalInvocationIndex = uint(0);\n";
- }
- }
-
- bool getDimensionsIgnoresBaseLevel =
- (mCompileOptions & SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL) != 0;
- mTextureFunctionHLSL->textureFunctionHeader(out, mOutputType, getDimensionsIgnoresBaseLevel);
- mImageFunctionHLSL->imageFunctionHeader(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 (mUsesPointSize)
- {
- out << "#define GL_USES_POINT_SIZE\n";
- }
-
- if (mHasMultiviewExtensionEnabled)
- {
- out << "#define GL_ANGLE_MULTIVIEW_ENABLED\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 (mUsesNumWorkGroups)
- {
- out << "#define GL_USES_NUM_WORK_GROUPS\n";
- }
-
- if (mUsesWorkGroupID)
- {
- out << "#define GL_USES_WORK_GROUP_ID\n";
- }
-
- if (mUsesLocalInvocationID)
- {
- out << "#define GL_USES_LOCAL_INVOCATION_ID\n";
- }
-
- if (mUsesGlobalInvocationID)
- {
- out << "#define GL_USES_GLOBAL_INVOCATION_ID\n";
- }
-
- if (mUsesLocalInvocationIndex)
- {
- out << "#define GL_USES_LOCAL_INVOCATION_INDEX\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)
-{
- TInfoSinkBase &out = getInfoSink();
-
- // Handle accessing std140 structs by value
- if (IsInStd140InterfaceBlock(node) && node->getBasicType() == EbtStruct)
- {
- out << "map";
- }
-
- TString name = node->getSymbol();
-
- if (name == "gl_DepthRange")
- {
- mUsesDepthRange = true;
- out << name;
- }
- else
- {
- const TType &nodeType = node->getType();
- TQualifier qualifier = node->getQualifier();
-
- ensureStructDefined(nodeType);
-
- if (qualifier == EvqUniform)
- {
- const TInterfaceBlock *interfaceBlock = nodeType.getInterfaceBlock();
-
- if (interfaceBlock)
- {
- mReferencedUniformBlocks[interfaceBlock->name()] = node;
- }
- else
- {
- mReferencedUniforms[name] = node;
- }
-
- out << DecorateVariableIfNeeded(node->getName());
- }
- else if (qualifier == EvqAttribute || qualifier == EvqVertexIn)
- {
- mReferencedAttributes[name] = node;
- out << Decorate(name);
- }
- else if (IsVarying(qualifier))
- {
- mReferencedVaryings[name] = node;
- out << Decorate(name);
- if (name == "ViewID_OVR")
- {
- mUsesViewID = true;
- }
- }
- else if (qualifier == EvqFragmentOut)
- {
- mReferencedOutputVariables[name] = node;
- 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 == EvqFragCoord)
- {
- mUsesFragCoord = true;
- out << name;
- }
- else if (qualifier == EvqPointCoord)
- {
- mUsesPointCoord = true;
- out << name;
- }
- else if (qualifier == EvqFrontFacing)
- {
- mUsesFrontFacing = 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(node->getName());
- }
- }
-}
-
-void OutputHLSL::visitRaw(TIntermRaw *node)
-{
- getInfoSink() << node->getRawText();
-}
-
-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);
- }
- outputAssign(visit, node->getType(), out);
- break;
- case EOpInitialize:
- if (visit == PreVisit)
- {
- TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode();
- ASSERT(symbolNode);
- TIntermTyped *expression = node->getRight();
-
- // Global initializers must be constant at this point.
- ASSERT(symbolNode->getQualifier() != EvqGlobal ||
- canWriteAsHLSLLiteral(expression));
-
- // 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, expression))
- {
- // Skip initializing the rest of the expression
- return false;
- }
- else if (writeConstantInitialization(out, symbolNode, expression))
- {
- return false;
- }
- }
- else if (visit == InVisit)
- {
- out << " = ";
- }
- 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)
- {
- TInterfaceBlock *interfaceBlock = leftType.getInterfaceBlock();
- const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0);
- mReferencedUniformBlocks[interfaceBlock->instanceName()] =
- node->getLeft()->getAsSymbolNode();
- out << mUniformHLSL->uniformBlockInstanceString(*interfaceBlock, 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
- {
- outputTriplet(out, visit, "", "[", "]");
- }
- }
- break;
- case EOpIndexIndirect:
- // We do not currently support indirect references to interface blocks
- ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock);
- outputTriplet(out, visit, "", "[", "]");
- 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:
- {
- bool structInStd140Block =
- node->getBasicType() == EbtStruct && IsInStd140InterfaceBlock(node->getLeft());
- if (visit == PreVisit && structInStd140Block)
- {
- 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 (structInStd140Block)
- {
- 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:
- outputTriplet(out, visit, "tanh(", "", ")");
- break;
- case EOpAsinh:
- case EOpAcosh:
- case EOpAtanh:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, node->getOp());
- 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->getOp());
- break;
- case EOpCeil:
- outputTriplet(out, visit, "ceil(", "", ")");
- break;
- case EOpFract:
- outputTriplet(out, visit, "frac(", "", ")");
- break;
- case EOpIsNan:
- if (node->getUseEmulatedFunction())
- writeEmulatedFunctionTriplet(out, visit, node->getOp());
- 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->getOp());
- break;
- case EOpLength:
- outputTriplet(out, visit, "length(", "", ")");
- break;
- case EOpNormalize:
- outputTriplet(out, visit, "normalize(", "", ")");
- 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 EOpTranspose:
- outputTriplet(out, visit, "transpose(", "", ")");
- break;
- case EOpDeterminant:
- outputTriplet(out, visit, "determinant(transpose(", "", "))");
- break;
- case EOpInverse:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, node->getOp());
- break;
-
- case EOpAny:
- outputTriplet(out, visit, "any(", "", ")");
- break;
- case EOpAll:
- outputTriplet(out, visit, "all(", "", ")");
- break;
- case EOpLogicalNotComponentWise:
- 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;
- default:
- UNREACHABLE();
- }
-
- return true;
-}
-
-TString OutputHLSL::samplerNamePrefixFromStruct(TIntermTyped *node)
-{
- if (node->getAsSymbolNode())
- {
- return node->getAsSymbolNode()->getSymbol();
- }
- TIntermBinary *nodeBinary = node->getAsBinaryNode();
- switch (nodeBinary->getOp())
- {
- case EOpIndexDirect:
- {
- int index = nodeBinary->getRight()->getAsConstantUnion()->getIConst(0);
-
- TInfoSinkBase prefixSink;
- prefixSink << samplerNamePrefixFromStruct(nodeBinary->getLeft()) << "_" << index;
- return TString(prefixSink.c_str());
- }
- case EOpIndexDirectStruct:
- {
- const TStructure *s = nodeBinary->getLeft()->getAsTyped()->getType().getStruct();
- int index = nodeBinary->getRight()->getAsConstantUnion()->getIConst(0);
- const TField *field = s->fields()[index];
-
- TInfoSinkBase prefixSink;
- prefixSink << samplerNamePrefixFromStruct(nodeBinary->getLeft()) << "_"
- << field->name();
- return TString(prefixSink.c_str());
- }
- default:
- UNREACHABLE();
- return TString("");
- }
-}
-
-bool OutputHLSL::visitBlock(Visit visit, TIntermBlock *node)
-{
- TInfoSinkBase &out = getInfoSink();
-
- if (mInsideFunction)
- {
- outputLineDirective(out, node->getLine().first_line);
- out << "{\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->getAsInvariantDeclarationNode() == nullptr)
- {
- out << ";\n";
- }
- }
-
- if (mInsideFunction)
- {
- outputLineDirective(out, node->getLine().last_line);
- out << "}\n";
- }
-
- return false;
-}
-
-bool OutputHLSL::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
-{
- TInfoSinkBase &out = getInfoSink();
-
- ASSERT(mCurrentFunctionMetadata == nullptr);
-
- size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo());
- ASSERT(index != CallDAG::InvalidIndex);
- mCurrentFunctionMetadata = &mASTMetadataList[index];
-
- out << TypeString(node->getFunctionPrototype()->getType()) << " ";
-
- TIntermSequence *parameters = node->getFunctionPrototype()->getSequence();
-
- if (node->getFunctionSymbolInfo()->isMain())
- {
- out << "gl_main(";
- }
- else
- {
- out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj())
- << DisambiguateFunctionName(parameters) << (mOutputLod0Function ? "Lod0(" : "(");
- }
-
- for (unsigned int i = 0; i < parameters->size(); i++)
- {
- TIntermSymbol *symbol = (*parameters)[i]->getAsSymbolNode();
-
- if (symbol)
- {
- ensureStructDefined(symbol->getType());
-
- out << argumentString(symbol);
-
- if (i < parameters->size() - 1)
- {
- out << ", ";
- }
- }
- else
- UNREACHABLE();
- }
-
- out << ")\n";
-
- mInsideFunction = true;
- // The function body node will output braces.
- node->getBody()->traverse(this);
- mInsideFunction = false;
-
- mCurrentFunctionMetadata = nullptr;
-
- bool needsLod0 = mASTMetadataList[index].mNeedsLod0;
- if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER)
- {
- ASSERT(!node->getFunctionSymbolInfo()->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 *variable = (*sequence)[0]->getAsTyped();
- ASSERT(sequence->size() == 1);
- ASSERT(variable);
-
- if (IsDeclarationWrittenOut(node))
- {
- TInfoSinkBase &out = getInfoSink();
- ensureStructDefined(variable->getType());
-
- if (!variable->getAsSymbolNode() ||
- variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
- {
- if (!mInsideFunction)
- {
- out << "static ";
- }
-
- out << TypeString(variable->getType()) + " ";
-
- TIntermSymbol *symbol = variable->getAsSymbolNode();
-
- if (symbol)
- {
- symbol->traverse(this);
- out << ArrayString(symbol->getType());
- out << " = " + initializer(symbol->getType());
- }
- else
- {
- variable->traverse(this);
- }
- }
- else if (variable->getAsSymbolNode() &&
- variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration
- {
- ASSERT(variable->getBasicType() == EbtStruct);
- // ensureStructDefined has already been called.
- }
- else
- UNREACHABLE();
- }
- else if (IsVaryingOut(variable->getQualifier()))
- {
- TIntermSymbol *symbol = variable->getAsSymbolNode();
- ASSERT(symbol); // Varying declarations can't have initializers.
-
- // Vertex outputs which are declared but not written to should still be declared to
- // allow successful linking.
- mReferencedVaryings[symbol->getSymbol()] = symbol;
- }
- }
- return false;
-}
-
-bool OutputHLSL::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
-{
- // Do not do any translation
- return false;
-}
-
-bool OutputHLSL::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
-{
- TInfoSinkBase &out = getInfoSink();
-
- ASSERT(visit == PreVisit);
- size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo());
- // Skip the prototype if it is not implemented (and thus not used)
- if (index == CallDAG::InvalidIndex)
- {
- return false;
- }
-
- TIntermSequence *arguments = node->getSequence();
-
- TString name = DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
- out << TypeString(node->getType()) << " " << name << DisambiguateFunctionName(arguments)
- << (mOutputLod0Function ? "Lod0(" : "(");
-
- for (unsigned int i = 0; i < arguments->size(); i++)
- {
- TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode();
- ASSERT(symbol != nullptr);
-
- out << argumentString(symbol);
-
- if (i < arguments->size() - 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;
- }
-
- return false;
-}
-
-bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- TInfoSinkBase &out = getInfoSink();
-
- switch (node->getOp())
- {
- case EOpCallBuiltInFunction:
- case EOpCallFunctionInAST:
- case EOpCallInternalRawFunction:
- {
- TIntermSequence *arguments = node->getSequence();
-
- bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function;
- if (node->getOp() == EOpCallFunctionInAST)
- {
- if (node->isArray())
- {
- UNIMPLEMENTED();
- }
- size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo());
- ASSERT(index != CallDAG::InvalidIndex);
- lod0 &= mASTMetadataList[index].mNeedsLod0;
-
- out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
- out << DisambiguateFunctionName(node->getSequence());
- out << (lod0 ? "Lod0(" : "(");
- }
- else if (node->getOp() == EOpCallInternalRawFunction)
- {
- // This path is used for internal functions that don't have their definitions in the
- // AST, such as precision emulation functions.
- out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "(";
- }
- else if (node->getFunctionSymbolInfo()->isImageFunction())
- {
- TString name = node->getFunctionSymbolInfo()->getName();
- TType type = (*arguments)[0]->getAsTyped()->getType();
- TString imageFunctionName = mImageFunctionHLSL->useImageFunction(
- name, type.getBasicType(), type.getLayoutQualifier().imageInternalFormat,
- type.getMemoryQualifier().readonly);
- out << imageFunctionName << "(";
- }
- else
- {
- const TString &name = node->getFunctionSymbolInfo()->getName();
- 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();
- }
- TString 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<TIntermSymbol *> samplerSymbols;
- TString structName = samplerNamePrefixFromStruct(typedArg);
- argType.createSamplerSymbols("angle_" + structName, "", &samplerSymbols,
- nullptr, mSymbolTable);
- for (const TIntermSymbol *sampler : samplerSymbols)
- {
- if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
- {
- out << ", texture_" << sampler->getSymbol();
- out << ", sampler_" << sampler->getSymbol();
- }
- 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->getSymbol();
- }
- }
- }
-
- 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->getOp());
- 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->getOp());
- 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->getOp());
- }
- else
- {
- outputTriplet(out, visit, "lerp(", ", ", ")");
- }
- break;
- }
- case EOpStep:
- outputTriplet(out, visit, "step(", ", ", ")");
- break;
- case EOpSmoothStep:
- outputTriplet(out, visit, "smoothstep(", ", ", ")");
- break;
- case EOpFrexp:
- case EOpLdexp:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, node->getOp());
- 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->getOp());
- break;
- case EOpReflect:
- outputTriplet(out, visit, "reflect(", ", ", ")");
- break;
- case EOpRefract:
- outputTriplet(out, visit, "refract(", ", ", ")");
- break;
- case EOpOuterProduct:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, node->getOp());
- break;
- case EOpMulMatrixComponentWise:
- outputTriplet(out, visit, "(", " * ", ")");
- break;
- case EOpBitfieldExtract:
- case EOpBitfieldInsert:
- case EOpUaddCarry:
- case EOpUsubBorrow:
- case EOpUmulExtended:
- case EOpImulExtended:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, node->getOp());
- break;
- default:
- UNREACHABLE();
- }
-
- 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->getUnionArrayPointer());
-}
-
-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())
- {
- out << "return ";
- }
- 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->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()->getId() == index->getId())
- {
- 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 & SH_LINE_DIRECTIVES) && (line > 0))
- {
- out << "\n";
- out << "#line " << line;
-
- if (mSourcePath)
- {
- out << " \"" << mSourcePath << "\"";
- }
-
- out << "\n";
- }
-}
-
-TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
-{
- TQualifier qualifier = symbol->getQualifier();
- const TType &type = symbol->getType();
- const TName &name = symbol->getName();
- TString nameStr;
-
- if (name.getString().empty()) // HLSL demands named arguments, also for prototypes
- {
- nameStr = "x" + str(mUniqueIndex++);
- }
- else
- {
- nameStr = DecorateVariableIfNeeded(name);
- }
-
- if (IsSampler(type.getBasicType()))
- {
- if (mOutputType == SH_HLSL_4_1_OUTPUT)
- {
- // Samplers are passed as indices to the sampler array.
- ASSERT(qualifier != EvqOut && qualifier != EvqInOut);
- return "const uint " + nameStr + ArrayString(type);
- }
- if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
- {
- return QualifierString(qualifier) + " " + TextureString(type.getBasicType()) +
- " texture_" + nameStr + ArrayString(type) + ", " + QualifierString(qualifier) +
- " " + SamplerString(type.getBasicType()) + " sampler_" + nameStr +
- ArrayString(type);
- }
- }
-
- TStringStream argString;
- argString << 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 != EvqOut && qualifier != EvqInOut);
- TVector<TIntermSymbol *> samplerSymbols;
- type.createSamplerSymbols("angle" + nameStr, "", &samplerSymbols, nullptr, mSymbolTable);
- for (const TIntermSymbol *sampler : samplerSymbols)
- {
- const TType &samplerType = sampler->getType();
- if (mOutputType == SH_HLSL_4_1_OUTPUT)
- {
- argString << ", const uint " << sampler->getSymbol() << ArrayString(samplerType);
- }
- else if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
- {
- ASSERT(IsSampler(samplerType.getBasicType()));
- argString << ", " << QualifierString(qualifier) << " "
- << TextureString(samplerType.getBasicType()) << " texture_"
- << sampler->getSymbol() << ArrayString(samplerType) << ", "
- << QualifierString(qualifier) << " "
- << SamplerString(samplerType.getBasicType()) << " sampler_"
- << sampler->getSymbol() << ArrayString(samplerType);
- }
- else
- {
- ASSERT(IsSampler(samplerType.getBasicType()));
- argString << ", " << QualifierString(qualifier) << " " << TypeString(samplerType)
- << " " << sampler->getSymbol() << ArrayString(samplerType);
- }
- }
- }
-
- return argString.str();
-}
-
-TString OutputHLSL::initializer(const TType &type)
-{
- TString string;
-
- size_t size = type.getObjectSize();
- for (size_t component = 0; component < size; component++)
- {
- string += "0";
-
- if (component + 1 < size)
- {
- string += ", ";
- }
- }
-
- 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)
-{
- 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, TOperator op)
-{
- if (visit == PreVisit)
- {
- const char *opStr = GetOperatorString(op);
- BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, opStr);
- out << "(";
- }
- else
- {
- outputTriplet(out, visit, nullptr, ", ", ")");
- }
-}
-
-bool OutputHLSL::writeSameSymbolInitializer(TInfoSinkBase &out,
- TIntermSymbol *symbolNode,
- TIntermTyped *expression)
-{
- sh::SearchSymbol searchSymbol(symbolNode->getSymbol());
- expression->traverse(&searchSymbol);
-
- if (searchSymbol.foundMatch())
- {
- // 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::canWriteAsHLSLLiteral(TIntermTyped *expression)
-{
- // We support writing constant unions and constructors that only take constant unions as
- // parameters as HLSL literals.
- return !expression->getType().isArrayOfArrays() &&
- (expression->getAsConstantUnion() ||
- expression->isConstructorWithOnlyConstantUnionParameters());
-}
-
-bool OutputHLSL::writeConstantInitialization(TInfoSinkBase &out,
- TIntermSymbol *symbolNode,
- TIntermTyped *initializer)
-{
- if (canWriteAsHLSLLiteral(initializer))
- {
- symbolNode->traverse(this);
- ASSERT(!symbolNode->getType().isArrayOfArrays());
- if (symbolNode->getType().isArray())
- {
- out << "[" << symbolNode->getType().getOutermostArraySize() << "]";
- }
- out << " = {";
- if (initializer->getAsConstantUnion())
- {
- TIntermConstantUnion *nodeConst = initializer->getAsConstantUnion();
- const TConstantUnion *constUnion = nodeConst->getUnionArrayPointer();
- writeConstantUnionArray(out, constUnion, nodeConst->getType().getObjectSize());
- }
- else
- {
- TIntermAggregate *constructor = initializer->getAsAggregate();
- ASSERT(constructor != nullptr);
- for (TIntermNode *&node : *constructor->getSequence())
- {
- TIntermConstantUnion *nodeConst = node->getAsConstantUnion();
- ASSERT(nodeConst);
- const TConstantUnion *constUnion = nodeConst->getUnionArrayPointer();
- writeConstantUnionArray(out, constUnion, nodeConst->getType().getObjectSize());
- if (node != constructor->getSequence()->back())
- {
- out << ", ";
- }
- }
- }
- 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);
- }
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h
deleted file mode 100644
index 014f4f5002..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h
+++ /dev/null
@@ -1,248 +0,0 @@
-//
-// Copyright (c) 2002-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_OUTPUTHLSL_H_
-#define COMPILER_TRANSLATOR_OUTPUTHLSL_H_
-
-#include <list>
-#include <map>
-#include <stack>
-
-#include "angle_gl.h"
-#include "compiler/translator/ASTMetadataHLSL.h"
-#include "compiler/translator/Compiler.h"
-#include "compiler/translator/FlagStd140Structs.h"
-#include "compiler/translator/IntermTraverse.h"
-
-class BuiltInFunctionEmulator;
-
-namespace sh
-{
-class StructureHLSL;
-class TextureFunctionHLSL;
-class TSymbolTable;
-class ImageFunctionHLSL;
-class UnfoldShortCircuit;
-class UniformHLSL;
-
-typedef std::map<TString, TIntermSymbol *> ReferencedSymbols;
-
-class OutputHLSL : public TIntermTraverser
-{
- public:
- OutputHLSL(sh::GLenum shaderType,
- int shaderVersion,
- const TExtensionBehavior &extensionBehavior,
- const char *sourcePath,
- ShShaderOutput outputType,
- int numRenderTargets,
- const std::vector<Uniform> &uniforms,
- ShCompileOptions compileOptions,
- TSymbolTable *symbolTable,
- PerformanceDiagnostics *perfDiagnostics);
-
- ~OutputHLSL();
-
- void output(TIntermNode *treeRoot, TInfoSinkBase &objSink);
-
- const std::map<std::string, unsigned int> &getUniformBlockRegisterMap() const;
- const std::map<std::string, unsigned int> &getUniformRegisterMap() const;
-
- static TString initializer(const TType &type);
-
- TInfoSinkBase &getInfoSink()
- {
- ASSERT(!mInfoSinkStack.empty());
- return *mInfoSinkStack.top();
- }
-
- static bool canWriteAsHLSLLiteral(TIntermTyped *expression);
-
- protected:
- void header(TInfoSinkBase &out,
- const std::vector<MappedStruct> &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 visitRaw(TIntermRaw *) 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;
- bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
- bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
- bool visitAggregate(Visit visit, TIntermAggregate *) override;
- bool visitBlock(Visit visit, TIntermBlock *node) override;
- bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *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);
- TString argumentString(const TIntermSymbol *symbol);
-
- 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, TOperator op);
-
- // 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);
-
- sh::GLenum mShaderType;
- int mShaderVersion;
- const TExtensionBehavior &mExtensionBehavior;
- const char *mSourcePath;
- const ShShaderOutput mOutputType;
- ShCompileOptions mCompileOptions;
-
- bool mInsideFunction;
-
- // 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<TInfoSinkBase *> mInfoSinkStack;
-
- ReferencedSymbols mReferencedUniforms;
- ReferencedSymbols mReferencedUniformBlocks;
- ReferencedSymbols mReferencedAttributes;
- ReferencedSymbols mReferencedVaryings;
- ReferencedSymbols mReferencedOutputVariables;
-
- StructureHLSL *mStructureHLSL;
- UniformHLSL *mUniformHLSL;
- TextureFunctionHLSL *mTextureFunctionHLSL;
- ImageFunctionHLSL *mImageFunctionHLSL;
-
- // Parameters determining what goes in the header output
- bool mUsesFragColor;
- bool mUsesFragData;
- bool mUsesDepthRange;
- bool mUsesFragCoord;
- bool mUsesPointCoord;
- bool mUsesFrontFacing;
- 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;
-
- int mNumRenderTargets;
-
- 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<HelperFunction *> mEqualityFunctions;
-
- struct StructEqualityFunction : public HelperFunction
- {
- const TStructure *structure;
- };
- std::vector<StructEqualityFunction *> mStructEqualityFunctions;
-
- struct ArrayHelperFunction : public HelperFunction
- {
- TType type;
- };
- std::vector<ArrayHelperFunction *> mArrayEqualityFunctions;
-
- std::vector<ArrayHelperFunction> 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<ArrayHelperFunction> mArrayConstructIntoFunctions;
-
- PerformanceDiagnostics *mPerfDiagnostics;
-
- private:
- TString generateStructMapping(const std::vector<MappedStruct> &std140Structs) const;
- TString samplerNamePrefixFromStruct(TIntermTyped *node);
- bool ancestorEvaluatesToSamplerInStruct();
-};
-}
-
-#endif // COMPILER_TRANSLATOR_OUTPUTHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputTree.cpp b/src/3rdparty/angle/src/compiler/translator/OutputTree.cpp
deleted file mode 100644
index 25e8298af3..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/OutputTree.cpp
+++ /dev/null
@@ -1,682 +0,0 @@
-//
-// Copyright (c) 2002-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/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-namespace
-{
-
-void OutputFunction(TInfoSinkBase &out, const char *str, TFunctionSymbolInfo *info)
-{
- const char *internal = info->getNameObj().isInternal() ? " (internal function)" : "";
- out << str << internal << ": " << info->getNameObj().getString() << " (symbol id "
- << info->getId().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) {}
-
- 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;
- bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
- bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
- bool visitAggregate(Visit visit, TIntermAggregate *) override;
- bool visitBlock(Visit visit, TIntermBlock *) override;
- bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
- bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
- bool visitLoop(Visit visit, TIntermLoop *) override;
- bool visitBranch(Visit visit, TIntermBranch *) override;
-
- TInfoSinkBase &mOut;
-};
-
-//
-// 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, mDepth);
-
- mOut << "'" << node->getSymbol() << "' ";
- mOut << "(symbol id " << node->getId() << ") ";
- mOut << "(" << node->getCompleteString() << ")";
- mOut << "\n";
-}
-
-bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
-{
- OutputTreeText(mOut, node, mDepth);
- mOut << "vector swizzle (";
- node->writeOffsetsAsXYZW(&mOut);
- mOut << ")";
-
- mOut << " (" << node->getCompleteString() << ")";
- mOut << "\n";
- return true;
-}
-
-bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
-{
- OutputTreeText(mOut, node, mDepth);
-
- 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 << "<unknown op>";
- }
-
- mOut << " (" << node->getCompleteString() << ")";
-
- 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, mDepth + 1);
-
- // The following code finds the field name from the constant union
- const TConstantUnion *constantUnion = intermConstantUnion->getUnionArrayPointer();
- 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, mDepth);
-
- switch (node->getOp())
- {
- // 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 EOpLogicalNotComponentWise:
- mOut << "component-wise not";
- break;
-
- default:
- mOut << GetOperatorString(node->getOp());
- break;
- }
-
- mOut << " (" << node->getCompleteString() << ")";
-
- mOut << "\n";
-
- return true;
-}
-
-bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
-{
- OutputTreeText(mOut, node, mDepth);
- mOut << "Function Definition:\n";
- mOut << "\n";
- return true;
-}
-
-bool TOutputTraverser::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
-{
- OutputTreeText(mOut, node, mDepth);
- mOut << "Invariant Declaration:\n";
- return true;
-}
-
-bool TOutputTraverser::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
-{
- OutputTreeText(mOut, node, mDepth);
- OutputFunction(mOut, "Function Prototype", node->getFunctionSymbolInfo());
- mOut << " (" << node->getCompleteString() << ")";
- mOut << "\n";
-
- return true;
-}
-
-bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- OutputTreeText(mOut, node, mDepth);
-
- if (node->getOp() == 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 (node->getOp())
- {
- case EOpCallFunctionInAST:
- OutputFunction(mOut, "Call an user-defined function", node->getFunctionSymbolInfo());
- break;
- case EOpCallInternalRawFunction:
- OutputFunction(mOut, "Call an internal function with raw implementation",
- node->getFunctionSymbolInfo());
- break;
- case EOpCallBuiltInFunction:
- OutputFunction(mOut, "Call a built-in function", node->getFunctionSymbolInfo());
- 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 EOpMulMatrixComponentWise:
- mOut << "component-wise multiply";
- break;
-
- default:
- mOut << GetOperatorString(node->getOp());
- break;
- }
-
- mOut << " (" << node->getCompleteString() << ")";
-
- mOut << "\n";
-
- return true;
-}
-
-bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
-{
- OutputTreeText(mOut, node, mDepth);
- mOut << "Code block\n";
-
- return true;
-}
-
-bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
-{
- OutputTreeText(mOut, node, mDepth);
- mOut << "Declaration\n";
-
- return true;
-}
-
-bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
-{
- OutputTreeText(mOut, node, mDepth);
-
- mOut << "Ternary selection";
- mOut << " (" << node->getCompleteString() << ")\n";
-
- ++mDepth;
-
- OutputTreeText(mOut, node, mDepth);
- mOut << "Condition\n";
- node->getCondition()->traverse(this);
-
- OutputTreeText(mOut, node, mDepth);
- if (node->getTrueExpression())
- {
- mOut << "true case\n";
- node->getTrueExpression()->traverse(this);
- }
- if (node->getFalseExpression())
- {
- OutputTreeText(mOut, node, mDepth);
- mOut << "false case\n";
- node->getFalseExpression()->traverse(this);
- }
-
- --mDepth;
-
- return false;
-}
-
-bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
-{
- OutputTreeText(mOut, node, mDepth);
-
- mOut << "If test\n";
-
- ++mDepth;
-
- OutputTreeText(mOut, node, mDepth);
- mOut << "Condition\n";
- node->getCondition()->traverse(this);
-
- OutputTreeText(mOut, node, mDepth);
- if (node->getTrueBlock())
- {
- mOut << "true case\n";
- node->getTrueBlock()->traverse(this);
- }
- else
- {
- mOut << "true case is null\n";
- }
-
- if (node->getFalseBlock())
- {
- OutputTreeText(mOut, node, mDepth);
- mOut << "false case\n";
- node->getFalseBlock()->traverse(this);
- }
-
- --mDepth;
-
- return false;
-}
-
-bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
-{
- OutputTreeText(mOut, node, mDepth);
-
- mOut << "Switch\n";
-
- return true;
-}
-
-bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node)
-{
- OutputTreeText(mOut, node, mDepth);
-
- 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, mDepth);
- switch (node->getUnionArrayPointer()[i].getType())
- {
- case EbtBool:
- if (node->getUnionArrayPointer()[i].getBConst())
- mOut << "true";
- else
- mOut << "false";
-
- mOut << " ("
- << "const bool"
- << ")";
- mOut << "\n";
- break;
- case EbtFloat:
- mOut << node->getUnionArrayPointer()[i].getFConst();
- mOut << " (const float)\n";
- break;
- case EbtInt:
- mOut << node->getUnionArrayPointer()[i].getIConst();
- mOut << " (const int)\n";
- break;
- case EbtUInt:
- mOut << node->getUnionArrayPointer()[i].getUConst();
- mOut << " (const uint)\n";
- break;
- case EbtYuvCscStandardEXT:
- mOut << getYuvCscStandardEXTString(
- node->getUnionArrayPointer()[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, mDepth);
-
- mOut << "Loop with condition ";
- if (node->getType() == ELoopDoWhile)
- mOut << "not ";
- mOut << "tested first\n";
-
- ++mDepth;
-
- OutputTreeText(mOut, node, mDepth);
- if (node->getCondition())
- {
- mOut << "Loop Condition\n";
- node->getCondition()->traverse(this);
- }
- else
- {
- mOut << "No loop condition\n";
- }
-
- OutputTreeText(mOut, node, mDepth);
- if (node->getBody())
- {
- mOut << "Loop Body\n";
- node->getBody()->traverse(this);
- }
- else
- {
- mOut << "No loop body\n";
- }
-
- if (node->getExpression())
- {
- OutputTreeText(mOut, node, mDepth);
- mOut << "Loop Terminal Expression\n";
- node->getExpression()->traverse(this);
- }
-
- --mDepth;
-
- return false;
-}
-
-bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
-{
- OutputTreeText(mOut, node, mDepth);
-
- 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";
- ++mDepth;
- node->getExpression()->traverse(this);
- --mDepth;
- }
- 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/src/3rdparty/angle/src/compiler/translator/OutputTree.h b/src/3rdparty/angle/src/compiler/translator/OutputTree.h
deleted file mode 100644
index 9f11989cb1..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/OutputTree.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 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_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp
deleted file mode 100644
index 6d11deb898..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-//
-// Copyright (c) 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.
-//
-// OutputVulkanGLSL:
-// Code that outputs shaders that fit GL_KHR_vulkan_glsl.
-// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side).
-// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt
-//
-
-#include "compiler/translator/OutputVulkanGLSL.h"
-
-#include "compiler/translator/util.h"
-
-namespace sh
-{
-
-TOutputVulkanGLSL::TOutputVulkanGLSL(TInfoSinkBase &objSink,
- ShArrayIndexClampingStrategy clampingStrategy,
- ShHashFunction64 hashFunction,
- NameMap &nameMap,
- TSymbolTable *symbolTable,
- sh::GLenum shaderType,
- int shaderVersion,
- ShShaderOutput output,
- ShCompileOptions compileOptions)
- : TOutputGLSL(objSink,
- clampingStrategy,
- hashFunction,
- nameMap,
- symbolTable,
- shaderType,
- shaderVersion,
- output,
- compileOptions)
-{
-}
-
-// TODO(jmadill): This is not complete.
-void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
-{
- const TType &type = variable->getType();
-
- bool needsCustomLayout =
- (type.getQualifier() == EvqAttribute || type.getQualifier() == EvqFragmentOut ||
- type.getQualifier() == EvqVertexIn || IsVarying(type.getQualifier()) ||
- IsSampler(type.getBasicType()));
-
- if (!NeedsToWriteLayoutQualifier(type) && !needsCustomLayout)
- {
- return;
- }
-
- TInfoSinkBase &out = objSink();
- const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
- out << "layout(";
-
- // This isn't super clean, but it gets the job done.
- // See corresponding code in GlslangWrapper.cpp.
- // TODO(jmadill): Ensure declarations are separated.
-
- TIntermSymbol *symbol = variable->getAsSymbolNode();
- ASSERT(symbol);
-
- if (needsCustomLayout)
- {
- out << "@@ LAYOUT-" << symbol->getName().getString() << " @@";
- }
-
- if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified)
- {
- ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform);
- out << getImageInternalFormatString(layoutQualifier.imageInternalFormat);
- }
-
- out << ") ";
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h
deleted file mode 100644
index 6e5da8b53e..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Copyright (c) 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.
-//
-// OutputVulkanGLSL:
-// Code that outputs shaders that fit GL_KHR_vulkan_glsl.
-// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side).
-// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt
-//
-
-#include "compiler/translator/OutputGLSL.h"
-
-namespace sh
-{
-
-class TOutputVulkanGLSL : public TOutputGLSL
-{
- public:
- TOutputVulkanGLSL(TInfoSinkBase &objSink,
- ShArrayIndexClampingStrategy clampingStrategy,
- ShHashFunction64 hashFunction,
- NameMap &nameMap,
- TSymbolTable *symbolTable,
- sh::GLenum shaderType,
- int shaderVersion,
- ShShaderOutput output,
- ShCompileOptions compileOptions);
-
- protected:
- void writeLayoutQualifier(TIntermTyped *variable) override;
-};
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ParamType.h b/src/3rdparty/angle/src/compiler/translator/ParamType.h
deleted file mode 100644
index dddb4e9901..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ParamType.h
+++ /dev/null
@@ -1,102 +0,0 @@
-//
-// 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.
-//
-// ParamType:
-// Helper type for built-in function emulator tables. Defines types for parameters.
-
-#ifndef COMPILER_TRANSLATOR_PARAMTYPE_H_
-#define COMPILER_TRANSLATOR_PARAMTYPE_H_
-
-#include "common/angleutils.h"
-#include "compiler/translator/BaseTypes.h"
-
-namespace sh
-{
-
-enum class ParamType : uint8_t
-{
- Void,
- Bool1,
- Bool2,
- Bool3,
- Bool4,
- Float1,
- Float2,
- Float3,
- Float4,
- Int1,
- Int2,
- Int3,
- Int4,
- Mat2,
- Mat3,
- Mat4,
- Uint1,
- Uint2,
- Uint3,
- Uint4,
- Last,
-};
-
-struct ParamTypeInfo
-{
- ParamType self;
- TBasicType basicType;
- int primarySize;
- int secondarySize;
-};
-
-constexpr ParamTypeInfo g_ParamTypeInfo[] = {
- {ParamType::Void, EbtVoid, 1, 1}, {ParamType::Bool1, EbtBool, 1, 1},
- {ParamType::Bool2, EbtBool, 2, 1}, {ParamType::Bool3, EbtBool, 3, 1},
- {ParamType::Bool4, EbtBool, 4, 1}, {ParamType::Float1, EbtFloat, 1, 1},
- {ParamType::Float2, EbtFloat, 2, 1}, {ParamType::Float3, EbtFloat, 3, 1},
- {ParamType::Float4, EbtFloat, 4, 1}, {ParamType::Int1, EbtInt, 1, 1},
- {ParamType::Int2, EbtInt, 2, 1}, {ParamType::Int3, EbtInt, 3, 1},
- {ParamType::Int4, EbtInt, 4, 1}, {ParamType::Mat2, EbtFloat, 2, 2},
- {ParamType::Mat3, EbtFloat, 3, 3}, {ParamType::Mat4, EbtFloat, 4, 4},
- {ParamType::Uint1, EbtUInt, 1, 1}, {ParamType::Uint2, EbtUInt, 2, 1},
- {ParamType::Uint3, EbtUInt, 3, 1}, {ParamType::Uint4, EbtUInt, 4, 1},
-};
-
-constexpr size_t ParamTypeIndex(ParamType paramType)
-{
- return static_cast<size_t>(paramType);
-}
-
-constexpr size_t NumParamTypes()
-{
- return ParamTypeIndex(ParamType::Last);
-}
-
-static_assert(ArraySize(g_ParamTypeInfo) == NumParamTypes(), "Invalid array size");
-
-constexpr TBasicType GetBasicType(ParamType paramType)
-{
- return g_ParamTypeInfo[ParamTypeIndex(paramType)].basicType;
-}
-
-constexpr int GetPrimarySize(ParamType paramType)
-{
- return g_ParamTypeInfo[ParamTypeIndex(paramType)].primarySize;
-}
-
-constexpr int GetSecondarySize(ParamType paramType)
-{
- return g_ParamTypeInfo[ParamTypeIndex(paramType)].secondarySize;
-}
-
-constexpr bool SameParamType(ParamType paramType,
- TBasicType basicType,
- int primarySize,
- int secondarySize)
-{
- return GetBasicType(paramType) == basicType && primarySize == GetPrimarySize(paramType) &&
- secondarySize == GetSecondarySize(paramType);
-}
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_PARAMTYPE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp
deleted file mode 100644
index c97f91d781..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp
+++ /dev/null
@@ -1,6022 +0,0 @@
-//
-// Copyright (c) 2002-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/ParseContext.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-
-#include "common/mathutil.h"
-#include "compiler/preprocessor/SourceLocation.h"
-#include "compiler/translator/Cache.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/ValidateGlobalInitializer.h"
-#include "compiler/translator/ValidateSwitch.h"
-#include "compiler/translator/glslang.h"
-#include "compiler/translator/util.h"
-
-namespace sh
-{
-
-///////////////////////////////////////////////////////////////////////
-//
-// Sub- vector and matrix fields
-//
-////////////////////////////////////////////////////////////////////////
-
-namespace
-{
-
-const int kWebGLMaxStructNesting = 4;
-
-const std::array<const char *, 8> kAtomicBuiltin = {{"atomicAdd", "atomicMin", "atomicMax",
- "atomicAnd", "atomicOr", "atomicXor",
- "atomicExchange", "atomicCompSwap"}};
-
-bool IsAtomicBuiltin(const TString &name)
-{
- for (size_t i = 0; i < kAtomicBuiltin.size(); ++i)
- {
- if (name.compare(kAtomicBuiltin[i]) == 0)
- {
- return true;
- }
- }
- return false;
-}
-
-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->getSymbol().c_str();
- }
- 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;
-}
-
-} // 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<int>(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<gl::RangeI> mSpans;
-};
-
-TParseContext::TParseContext(TSymbolTable &symt,
- TExtensionBehavior &ext,
- sh::GLenum type,
- ShShaderSpec spec,
- ShCompileOptions options,
- bool checksPrecErrors,
- TDiagnostics *diagnostics,
- const ShBuiltInResources &resources)
- : 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),
- mDefaultUniformMatrixPacking(EmpColumnMajor),
- mDefaultUniformBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
- mDefaultBufferMatrixPacking(EmpColumnMajor),
- mDefaultBufferBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
- mDiagnostics(diagnostics),
- mDirectiveHandler(ext,
- *mDiagnostics,
- mShaderVersion,
- mShaderType,
- resources.WEBGL_debug_shader_precision == 1),
- mPreprocessor(mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()),
- mScanner(nullptr),
- mUsesFragData(false),
- mUsesFragColor(false),
- mUsesSecondaryOutputs(false),
- 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),
- mMaxAtomicCounterBindings(resources.MaxAtomicCounterBindings),
- mMaxShaderStorageBufferBindings(resources.MaxShaderStorageBufferBindings),
- mDeclaringFunction(false),
- mGeometryShaderInputPrimitiveType(EptUndefined),
- mGeometryShaderOutputPrimitiveType(EptUndefined),
- mGeometryShaderInvocations(0),
- mGeometryShaderMaxVertices(-1),
- mMaxGeometryShaderInvocations(resources.MaxGeometryShaderInvocations),
- mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices),
- mGeometryShaderInputArraySize(0u)
-{
-}
-
-TParseContext::~TParseContext()
-{
-}
-
-bool TParseContext::parseVectorFields(const TSourceLoc &line,
- const TString &compString,
- int vecSize,
- TVector<int> *fieldOffsets)
-{
- ASSERT(fieldOffsets);
- size_t fieldCount = compString.size();
- if (fieldCount > 4u)
- {
- error(line, "illegal vector field selection", compString.c_str());
- 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.c_str());
- return false;
- }
- }
-
- for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
- {
- if ((*fieldOffsets)[i] >= vecSize)
- {
- error(line, "vector field selection out of range", compString.c_str());
- return false;
- }
-
- if (i > 0)
- {
- if (fieldSet[i] != fieldSet[i - 1])
- {
- error(line, "illegal - vector component fields not from the same set",
- compString.c_str());
- 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::warning(const TSourceLoc &loc, const char *reason, const char *token)
-{
- mDiagnostics->warning(loc, reason, token);
-}
-
-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);
- }
-}
-
-//
-// Same error message for all places assignments don't work.
-//
-void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right)
-{
- std::stringstream reasonStream;
- reasonStream << "cannot convert from '" << right << "' to '" << left << "'";
- std::string reason = reasonStream.str();
- error(line, reason.c_str(), op);
-}
-
-//
-// Same error message for all places unary operations don't work.
-//
-void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand)
-{
- std::stringstream reasonStream;
- reasonStream << "wrong operand type - no operation '" << op
- << "' exists that takes an operand of type " << operand
- << " (or there is no acceptable conversion)";
- std::string reason = reasonStream.str();
- error(line, reason.c_str(), op);
-}
-
-//
-// Same error message for all binary operations don't work.
-//
-void TParseContext::binaryOpError(const TSourceLoc &line,
- const char *op,
- TString left,
- TString right)
-{
- std::stringstream 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)";
- std::string reason = reasonStream.str();
- error(line, reason.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;
- }
- }
- }
-}
-
-// 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)
-{
- TIntermSymbol *symNode = node->getAsSymbolNode();
- TIntermBinary *binaryNode = node->getAsBinaryNode();
- 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;
- }
-
- if (binaryNode)
- {
- switch (binaryNode->getOp())
- {
- case EOpIndexDirect:
- case EOpIndexIndirect:
- case EOpIndexDirectStruct:
- case EOpIndexDirectInterfaceBlock:
- 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 EvqConstReadOnly:
- message = "can't modify a const";
- break;
- case EvqAttribute:
- message = "can't modify an attribute";
- break;
- case EvqFragmentIn:
- case EvqVertexIn:
- case EvqGeometryIn:
- case EvqFlatIn:
- case EvqSmoothIn:
- case EvqCentroidIn:
- 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 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 EvqLayer:
- if (mShaderType == GL_FRAGMENT_SHADER)
- {
- message = "can't modify gl_Layer in a fragment shader";
- }
- 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";
- }
- }
-
- if (message.empty() && binaryNode == 0 && symNode == 0)
- {
- error(line, "l-value required", op);
-
- return false;
- }
-
- //
- // Everything else is okay, no error.
- //
- if (message.empty())
- return true;
-
- //
- // If we get here, we have an error and a message.
- //
- if (symNode)
- {
- const char *symbol = symNode->getSymbol().c_str();
- std::stringstream reasonStream;
- reasonStream << "l-value required (" << message << " \"" << symbol << "\")";
- std::string reason = reasonStream.str();
- error(line, reason.c_str(), op);
- }
- else
- {
- std::stringstream reasonStream;
- reasonStream << "l-value required (" << 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 TString &identifier)
-{
- static const char *reservedErrMsg = "reserved built-in name";
- if (identifier.compare(0, 3, "gl_") == 0)
- {
- error(line, reservedErrMsg, "gl_");
- return false;
- }
- if (sh::IsWebGLBasedSpec(mShaderSpec))
- {
- if (identifier.compare(0, 6, "webgl_") == 0)
- {
- error(line, reservedErrMsg, "webgl_");
- return false;
- }
- if (identifier.compare(0, 7, "_webgl_") == 0)
- {
- error(line, reservedErrMsg, "_webgl_");
- return false;
- }
- }
- if (identifier.find("__") != TString::npos)
- {
- error(line,
- "identifiers containing two consecutive underscores (__) are reserved as "
- "possible future keywords",
- identifier.c_str());
- return false;
- }
- 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)
- {
- 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<size_t>(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 TString &identifier,
- const TBasicType &type)
-{
- if (type == EbtVoid)
- {
- error(line, "illegal use of type 'void'", identifier.c_str());
- 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;
- 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 == EvqOut || qualifier == EvqInOut);
- 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();
-
- // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
- // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
- // fold as array size.
- 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<unsigned int>(signedSize);
- }
-
- if (size == 0u)
- {
- error(line, "array size must be greater than zero", "");
- return 1u;
- }
-
- // 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())
- {
- error(line, "cannot declare arrays of arrays",
- TType(elementType).getCompleteString().c_str());
- 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).
- if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
- sh::IsVarying(elementType.qualifier))
- {
- error(indexLocation, "cannot declare arrays of structs of this qualifier",
- TType(elementType).getCompleteString().c_str());
- return false;
- }
- return checkIsValidQualifierForArray(indexLocation, elementType);
-}
-
-// Enforce non-initializer type/qualifier rules.
-void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
- const TString &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.c_str());
- }
- else
- {
- error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
- }
- }
- // This will make the type sized if it isn't sized yet.
- checkIsNotUnsizedArray(line, "implicitly sized arrays need to be initialized",
- identifier.c_str(), type);
-}
-
-// 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 TString &identifier,
- const TType &type,
- TVariable **variable)
-{
- ASSERT((*variable) == nullptr);
-
- checkBindingIsValid(line, type);
-
- bool needsReservedCheck = true;
-
- // gl_LastFragData may be redeclared with a new precision qualifier
- if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
- {
- const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
- symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
- if (type.isArrayOfArrays())
- {
- error(line, "redeclaration of gl_LastFragData as an array of arrays",
- identifier.c_str());
- return false;
- }
- else if (static_cast<int>(type.getOutermostArraySize()) ==
- maxDrawBuffers->getConstPointer()->getIConst())
- {
- if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
- {
- needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
- }
- }
- else
- {
- error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
- identifier.c_str());
- return false;
- }
- }
-
- if (needsReservedCheck && !checkIsNotReserved(line, identifier))
- return false;
-
- (*variable) = symbolTable.declareVariable(&identifier, type);
- if (!(*variable))
- {
- error(line, "redefinition", identifier.c_str());
- 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(mDiagnostics);
-
- if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
- {
- 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);
- }
-}
-
-template <size_t size>
-bool TParseContext::checkCanUseOneOfExtensions(const TSourceLoc &line,
- const std::array<TExtension, size> &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 (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<TExtension, 1> &extensions);
-template bool TParseContext::checkCanUseOneOfExtensions(
- const TSourceLoc &line,
- const std::array<TExtension, 2> &extensions);
-template bool TParseContext::checkCanUseOneOfExtensions(
- const TSourceLoc &line,
- const std::array<TExtension, 3> &extensions);
-
-bool TParseContext::checkCanUseExtension(const TSourceLoc &line, TExtension extension)
-{
- ASSERT(extension != TExtension::UNDEFINED);
- ASSERT(extension != TExtension::EXT_geometry_shader);
- if (extension == TExtension::OES_geometry_shader)
- {
- // OES_geometry_shader and EXT_geometry_shader are always interchangeable.
- constexpr std::array<TExtension, 2u> extensions{
- {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}};
- return checkCanUseOneOfExtensions(line, extensions);
- }
- return checkCanUseOneOfExtensions(line, std::array<TExtension, 1u>{{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 multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous
- // parsing steps. So it needs to be checked here.
- if (isExtensionEnabled(TExtension::OVR_multiview) && 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 >= 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", "");
- }
-}
-
-// 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 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);
- }
- }
-
- // 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
- {
- 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 (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::checkLayoutQualifierSupported(const TSourceLoc &location,
- const TString &layoutQualifierName,
- int versionRequired)
-{
-
- if (mShaderVersion < versionRequired)
- {
- error(location, "invalid layout qualifier: not supported", layoutQualifierName.c_str());
- }
-}
-
-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)
- {
- error(location, "invalid layout qualifier: only valid when used with images",
- getImageInternalFormatString(internalFormat));
- }
-}
-
-void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
-{
- if (binding != -1)
- {
- 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::checkUniformLocationInRange(const TSourceLoc &location,
- int objectLocationCount,
- const TLayoutQualifier &layoutQualifier)
-{
- int loc = layoutQualifier.location;
- if (loc >= 0 && loc + objectLocationCount > mMaxUniformLocations)
- {
- error(location, "Uniform 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::functionCallRValueLValueErrorCheck(const TFunction *fnCandidate,
- TIntermAggregate *fnCall)
-{
- for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
- {
- TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
- TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
- if (!IsImage(argument->getBasicType()) && (IsQualifierUnspecified(qual) || qual == EvqIn ||
- qual == EvqInOut || qual == EvqConstReadOnly))
- {
- if (argument->getMemoryQualifier().writeonly)
- {
- error(argument->getLine(),
- "Writeonly value cannot be passed for 'in' or 'inout' parameters.",
- fnCall->getFunctionSymbolInfo()->getName().c_str());
- return;
- }
- }
- if (qual == EvqOut || qual == EvqInOut)
- {
- if (!checkCanBeLValue(argument->getLine(), "assign", argument))
- {
- error(argument->getLine(),
- "Constant value cannot be passed for 'out' or 'inout' parameters.",
- fnCall->getFunctionSymbolInfo()->getName().c_str());
- 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");
- }
- }
-}
-
-bool TParseContext::isExtensionEnabled(TExtension extension) const
-{
- return IsExtensionEnabled(extensionBehavior(), extension);
-}
-
-void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
- const char *extName,
- const char *behavior)
-{
- 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)
-{
- 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 TString *name,
- const TSymbol *symbol)
-{
- if (!symbol)
- {
- error(location, "undeclared identifier", name->c_str());
- return nullptr;
- }
-
- if (!symbol->isVariable())
- {
- error(location, "variable expected", name->c_str());
- return nullptr;
- }
-
- const TVariable *variable = static_cast<const TVariable *>(symbol);
-
- if (variable->getExtension() != TExtension::UNDEFINED)
- {
- checkCanUseExtension(location, variable->getExtension());
- }
-
- // Reject shaders using both gl_FragData and gl_FragColor
- TQualifier qualifier = variable->getType().getQualifier();
- if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
- {
- mUsesFragData = true;
- }
- else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
- {
- mUsesFragColor = true;
- }
- if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
- {
- mUsesSecondaryOutputs = true;
- }
-
- // This validation is not quite correct - it's only an error to write to
- // both FragData and FragColor. For simplicity, and because users shouldn't
- // be rewarded for reading from undefined varaibles, return an error
- // if they are both referenced, rather than assigned.
- if (mUsesFragData && mUsesFragColor)
- {
- const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
- if (mUsesSecondaryOutputs)
- {
- errorMessage =
- "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
- " and (gl_FragColor, gl_SecondaryFragColorEXT)";
- }
- error(location, errorMessage, name->c_str());
- }
-
- // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
- if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
- qualifier == EvqWorkGroupSize)
- {
- error(location,
- "It is an error to use gl_WorkGroupSize before declaring the local group size",
- "gl_WorkGroupSize");
- }
- return variable;
-}
-
-TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
- const TString *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())
- {
- 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<unsigned int>(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(mGeometryShaderInputArraySize > 0u);
-
- node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), variableType);
- node->getTypePointer()->sizeOutermostUnsizedArray(mGeometryShaderInputArraySize);
- }
- else
- {
- node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), variableType);
- }
- ASSERT(node != nullptr);
- node->setLine(location);
- return node;
-}
-
-// 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 TString &identifier,
- TType type,
- TIntermTyped *initializer,
- TIntermBinary **initNode)
-{
- ASSERT(initNode != nullptr);
- ASSERT(*initNode == nullptr);
-
- TVariable *variable = 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.
- auto *arraySizes = initializer->getType().getArraySizes();
- type.sizeUnsizedArrays(arraySizes);
- }
- if (!declareVariable(line, identifier, type, &variable))
- {
- return false;
- }
-
- bool globalInitWarning = false;
- if (symbolTable.atGlobalLevel() &&
- !ValidateGlobalInitializer(initializer, this, &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
- //
- TQualifier qualifier = variable->getType().getQualifier();
- if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
- {
- error(line, " cannot initialize this type of qualifier ",
- variable->getType().getQualifierString());
- return false;
- }
- //
- // test for and propagate constant
- //
-
- if (qualifier == EvqConst)
- {
- if (qualifier != initializer->getType().getQualifier())
- {
- std::stringstream reasonStream;
- reasonStream << "assigning non-constant to '" << variable->getType().getCompleteString()
- << "'";
- std::string reason = reasonStream.str();
- error(line, reason.c_str(), "=");
- variable->getType().setQualifier(EvqTemporary);
- return false;
- }
- if (type != initializer->getType())
- {
- error(line, " non-matching types for const initializer ",
- variable->getType().getQualifierString());
- variable->getType().setQualifier(EvqTemporary);
- return false;
- }
-
- // Save the constant folded value to the variable if possible. For example array
- // initializers are not folded, since that way copying the array literal to multiple places
- // in the shader is avoided.
- // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
- // it would be beneficial.
- if (initializer->getAsConstantUnion())
- {
- variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
- ASSERT(*initNode == nullptr);
- return true;
- }
- else if (initializer->getAsSymbolNode())
- {
- const TSymbol *symbol =
- symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
- const TVariable *tVar = static_cast<const TVariable *>(symbol);
-
- const TConstantUnion *constArray = tVar->getConstPointer();
- if (constArray)
- {
- variable->shareConstPointer(constArray);
- ASSERT(*initNode == nullptr);
- return true;
- }
- }
- }
-
- TIntermSymbol *intermSymbol =
- new TIntermSymbol(variable->getUniqueId(), variable->getName(), variable->getType());
- intermSymbol->setLine(line);
- *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
- if (*initNode == nullptr)
- {
- assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
- return false;
- }
-
- return true;
-}
-
-TIntermNode *TParseContext::addConditionInitializer(const TPublicType &pType,
- const TString &identifier,
- TIntermTyped *initializer,
- const TSourceLoc &loc)
-{
- checkIsScalarBool(loc, pType);
- TIntermBinary *initNode = nullptr;
- TType type(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)
- {
- typedCond = cond->getAsTyped();
- }
- if (cond == nullptr || typedCond)
- {
- if (type == ELoopDoWhile)
- {
- 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);
-
- // 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));
- 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.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);
-
- 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)
- {
- 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:
- // 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));
- if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
- {
- 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<const TStorageQualifierWrapper &>(qualifier);
- if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
- !symbolTable.atGlobalLevel())
- {
- error(storageQualifier.getLine(),
- "Local variables can only use the const storage qualifier.",
- storageQualifier.getQualifierString().c_str());
- }
- }
-}
-
-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)
-{
- if (!IsAtomicCounter(type->getBasicType()))
- {
- return;
- }
-
- 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::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location,
- const char *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(mGeometryShaderInputArraySize > 0u);
- type->sizeOutermostUnsizedArray(mGeometryShaderInputArraySize);
- }
- 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.
- error(location,
- "Missing a valid input primitive declaration before declaring an unsized "
- "array input",
- token);
- }
- }
- else if (type->isArray())
- {
- setGeometryShaderInputArraySize(type->getOutermostArraySize(), location);
- }
- else
- {
- error(location, "Geometry shader input variable must be declared as an array", token);
- }
- }
-}
-
-TIntermDeclaration *TParseContext::parseSingleDeclaration(
- TPublicType &publicType,
- const TSourceLoc &identifierOrTypeLocation,
- const TString &identifier)
-{
- TType type(publicType);
- if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
- 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.
- //
- // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
- // the specification, but there are desktop OpenGL drivers that expect that this is the
- // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
- if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
- {
- type.setInvariant(true);
- }
- }
-
- checkGeometryShaderInputAndSetArraySize(identifierOrTypeLocation, identifier.c_str(), &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)
- {
- symbol = new TIntermSymbol(symbolTable.getEmptySymbolId(), "", type);
- }
- else if (IsAtomicCounter(publicType.getBasicType()))
- {
- setAtomicCounterBindingDefaultOffset(publicType, identifierOrTypeLocation);
- }
- }
- else
- {
- nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
-
- checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &type);
-
- checkAtomicCounterOffsetDoesNotOverlap(false, identifierOrTypeLocation, &type);
-
- TVariable *variable = nullptr;
- declareVariable(identifierOrTypeLocation, identifier, type, &variable);
-
- if (variable)
- {
- symbol = new TIntermSymbol(variable->getUniqueId(), identifier, type);
- }
- }
-
- 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 TString &identifier,
- const TSourceLoc &indexLocation,
- const TVector<unsigned int> &arraySizes)
-{
- mDeferredNonEmptyDeclarationErrorCheck = false;
-
- declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier,
- identifierLocation);
-
- nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
-
- checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
-
- TType arrayType(elementType);
- arrayType.makeArrays(arraySizes);
-
- checkGeometryShaderInputAndSetArraySize(indexLocation, identifier.c_str(), &arrayType);
-
- checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &arrayType);
-
- checkAtomicCounterOffsetDoesNotOverlap(false, identifierLocation, &arrayType);
-
- TVariable *variable = nullptr;
- declareVariable(identifierLocation, identifier, arrayType, &variable);
-
- TIntermDeclaration *declaration = new TIntermDeclaration();
- declaration->setLine(identifierLocation);
-
- if (variable)
- {
- TIntermSymbol *symbol = new TIntermSymbol(variable->getUniqueId(), identifier, arrayType);
- symbol->setLine(identifierLocation);
- declaration->appendDeclarator(symbol);
- }
-
- return declaration;
-}
-
-TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
- const TSourceLoc &identifierLocation,
- const TString &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(publicType);
- if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode))
- {
- if (initNode)
- {
- declaration->appendDeclarator(initNode);
- }
- }
- return declaration;
-}
-
-TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
- TPublicType &elementType,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &indexLocation,
- const TVector<unsigned int> &arraySizes,
- const TSourceLoc &initLocation,
- TIntermTyped *initializer)
-{
- mDeferredNonEmptyDeclarationErrorCheck = false;
-
- declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier,
- identifierLocation);
-
- nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
-
- checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
-
- TType arrayType(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;
-}
-
-TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
- const TTypeQualifierBuilder &typeQualifierBuilder,
- const TSourceLoc &identifierLoc,
- const TString *identifier,
- const TSymbol *symbol)
-{
- TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
-
- if (!typeQualifier.invariant)
- {
- error(identifierLoc, "Expected invariant", identifier->c_str());
- return nullptr;
- }
- if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
- {
- return nullptr;
- }
- if (!symbol)
- {
- error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
- return nullptr;
- }
- if (!IsQualifierUnspecified(typeQualifier.qualifier))
- {
- error(identifierLoc, "invariant declaration specifies qualifier",
- getQualifierString(typeQualifier.qualifier));
- }
- if (typeQualifier.precision != EbpUndefined)
- {
- error(identifierLoc, "invariant declaration specifies precision",
- getPrecisionString(typeQualifier.precision));
- }
- if (!typeQualifier.layoutQualifier.isEmpty())
- {
- error(identifierLoc, "invariant 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(std::string(identifier->c_str()));
-
- TIntermSymbol *intermSymbol = new TIntermSymbol(variable->getUniqueId(), *identifier, type);
- intermSymbol->setLine(identifierLoc);
-
- return new TIntermInvariantDeclaration(intermSymbol, identifierLoc);
-}
-
-void TParseContext::parseDeclarator(TPublicType &publicType,
- const TSourceLoc &identifierLocation,
- const TString &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);
-
- TVariable *variable = nullptr;
- TType type(publicType);
-
- checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier.c_str(), &type);
-
- checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &type);
-
- checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, &type);
-
- declareVariable(identifierLocation, identifier, type, &variable);
-
- if (variable)
- {
- TIntermSymbol *symbol = new TIntermSymbol(variable->getUniqueId(), identifier, type);
- symbol->setLine(identifierLocation);
- declarationOut->appendDeclarator(symbol);
- }
-}
-
-void TParseContext::parseArrayDeclarator(TPublicType &elementType,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &arrayLocation,
- const TVector<unsigned int> &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(elementType);
- arrayType.makeArrays(arraySizes);
-
- checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier.c_str(), &arrayType);
-
- checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &arrayType);
-
- checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, &arrayType);
-
- TVariable *variable = nullptr;
- declareVariable(identifierLocation, identifier, arrayType, &variable);
-
- if (variable)
- {
- TIntermSymbol *symbol =
- new TIntermSymbol(variable->getUniqueId(), identifier, arrayType);
- symbol->setLine(identifierLocation);
- declarationOut->appendDeclarator(symbol);
- }
- }
-}
-
-void TParseContext::parseInitDeclarator(const TPublicType &publicType,
- const TSourceLoc &identifierLocation,
- const TString &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(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 TString &identifier,
- const TSourceLoc &indexLocation,
- const TVector<unsigned int> &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(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 (mGeometryShaderInputArraySize == 0u)
- {
- mGeometryShaderInputArraySize = inputArraySize;
- }
- else if (mGeometryShaderInputArraySize != inputArraySize)
- {
- error(line,
- "Array size or input primitive declaration doesn't match the size of earlier sized "
- "array inputs.",
- "layout");
- }
-}
-
-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;
- }
- }
-
- // 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;
-}
-
-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;
- }
-
- 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);
-
- 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<const TVariable *>(
- symbolTable.findBuiltIn("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;
- 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 (isExtensionEnabled(TExtension::OVR_multiview) &&
- 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 (!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 above",
- "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.getName());
-
- TIntermFunctionPrototype *prototype =
- new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function));
- // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
- // point to the data that already exists in the symbol table.
- prototype->getFunctionSymbolInfo()->setFromFunction(function);
- prototype->setLine(location);
-
- for (size_t i = 0; i < function.getParamCount(); i++)
- {
- const TConstParameter &param = function.getParam(i);
-
- TIntermSymbol *symbol = nullptr;
-
- // 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.name != nullptr)
- {
- // Insert the parameter in the symbol table.
- if (insertParametersToSymbolTable)
- {
- TVariable *variable = symbolTable.declareVariable(param.name, *param.type);
- if (variable)
- {
- symbol = new TIntermSymbol(variable->getUniqueId(), variable->getName(),
- variable->getType());
- }
- else
- {
- error(location, "redefinition", param.name->c_str());
- }
- }
- // Unsized type of a named parameter should have already been checked and sanitized.
- ASSERT(!param.type->isUnsizedArray());
- }
- else
- {
- if (param.type->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.
- }
- }
- if (!symbol)
- {
- // The parameter had no name or declaring the symbol failed - either way, add a nameless
- // symbol.
- symbol = new TIntermSymbol(symbolTable.getEmptySymbolId(), "", *param.type);
- }
- symbol->setLine(location);
- prototype->appendParameter(symbol);
- }
- 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.
- TFunction *function = static_cast<TFunction *>(
- symbolTable.find(parsedFunction.getMangledName(), getShaderVersion()));
- if (function->hasPrototypeDeclaration() && 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");
- }
- function->setHasPrototypeDeclaration();
-
- 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)
-{
- // 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->getFunctionSymbolInfo()->getName().c_str());
- }
-
- 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,
- TFunction **function,
- TIntermFunctionPrototype **prototypeOut)
-{
- ASSERT(function);
- ASSERT(*function);
- const TSymbol *builtIn =
- symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
-
- if (builtIn)
- {
- error(location, "built-in functions cannot be redefined", (*function)->getName().c_str());
- }
- else
- {
- TFunction *prevDec = static_cast<TFunction *>(
- symbolTable.find((*function)->getMangledName(), getShaderVersion()));
-
- // Note: 'prevDec' 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 != prevDec)
- {
- // Swap the parameters of the previous declaration to the parameters of the function
- // definition (parameter names may differ).
- prevDec->swapParameters(**function);
-
- // The function definition will share the same symbol as any previous declaration.
- *function = prevDec;
- }
-
- if ((*function)->isDefined())
- {
- error(location, "function already has a body", (*function)->getName().c_str());
- }
-
- (*function)->setDefined();
- }
-
- // Remember the return type for later checking for return statements.
- mCurrentFunctionType = &((*function)->getReturnType());
- mFunctionReturnsValue = false;
-
- *prototypeOut = createPrototypeNodeFromFunction(**function, location, true);
- setLoopNestingLevel(0);
-}
-
-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.
- //
- // Return types and parameter qualifiers must match in all redeclarations, so those are checked
- // here.
- //
- TFunction *prevDec =
- static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
-
- for (size_t i = 0u; i < function->getParamCount(); ++i)
- {
- auto &param = function->getParam(i);
- if (param.type->isStructSpecifier())
- {
- // ESSL 3.00.6 section 12.10.
- error(location, "Function parameter type cannot be a structure definition",
- function->getName().c_str());
- }
- }
-
- if (getShaderVersion() >= 300 &&
- symbolTable.hasUnmangledBuiltInForShaderVersion(function->getName().c_str(),
- getShaderVersion()))
- {
- // 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->getName().c_str());
- }
- else 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).type->getQualifier() !=
- function->getParam(i).type->getQualifier())
- {
- error(location,
- "function must have the same parameter qualifiers in all of its declarations",
- function->getParam(i).type->getQualifierString());
- }
- }
- }
-
- //
- // Check for previously declared variables using the same name.
- //
- TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
- if (prevSym)
- {
- if (!prevSym->isFunction())
- {
- error(location, "redefinition of a function", function->getName().c_str());
- }
- }
- else
- {
- // Insert the unmangled name to detect potential future redefinition as a variable.
- symbolTable.getOuterLevel()->insertUnmangled(function);
- }
-
- // We're at the inner scope level of the function's arguments and body statement.
- // Add the function prototype to the surrounding scope instead.
- symbolTable.getOuterLevel()->insert(function);
-
- // Raise error message if main function takes any parameters or return anything other than void
- if (function->getName() == "main")
- {
- 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());
- }
- }
-
- //
- // 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 TString *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
- error(location, "structures containing arrays can't be function return values",
- TType(type).getCompleteString().c_str());
- }
- }
-
- // Add the function as a prototype after parsing it (we do not support recursion)
- return new TFunction(&symbolTable, name, new TType(type));
-}
-
-TFunction *TParseContext::addNonConstructorFunc(const TString *name, const TSourceLoc &loc)
-{
- const TType *returnType = TCache::getType(EbtVoid, EbpUndefined);
- return new TFunction(&symbolTable, name, returnType);
-}
-
-TFunction *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 new TFunction(&symbolTable, nullptr, type, EOpConstruct);
-}
-
-void TParseContext::checkIsNotUnsizedArray(const TSourceLoc &line,
- const char *errorMessage,
- const char *token,
- TType *arrayType)
-{
- if (arrayType->isUnsizedArray())
- {
- error(line, errorMessage, token);
- arrayType->sizeUnsizedArrays(nullptr);
- }
-}
-
-TParameter TParseContext::parseParameterDeclarator(TType *type,
- const TString *name,
- const TSourceLoc &nameLoc)
-{
- ASSERT(type);
- checkIsNotUnsizedArray(nameLoc, "function parameter array must specify a size", name->c_str(),
- type);
- if (type->getBasicType() == EbtVoid)
- {
- error(nameLoc, "illegal use of type 'void'", name->c_str());
- }
- checkIsNotReserved(nameLoc, *name);
- TParameter param = {name, type};
- return param;
-}
-
-TParameter TParseContext::parseParameterDeclarator(const TPublicType &publicType,
- const TString *name,
- const TSourceLoc &nameLoc)
-{
- TType *type = new TType(publicType);
- return parseParameterDeclarator(type, name, nameLoc);
-}
-
-TParameter TParseContext::parseParameterArrayDeclarator(const TString *name,
- const TSourceLoc &nameLoc,
- const TVector<unsigned int> &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(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)
- {
- 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(TIntermSequence *arguments,
- TType type,
- const TSourceLoc &line)
-{
- if (type.isUnsizedArray())
- {
- if (!checkUnsizedArrayConstructorArgumentDimensionality(arguments, type, line))
- {
- type.sizeUnsizedArrays(nullptr);
- return CreateZeroNode(type);
- }
- TIntermTyped *firstElement = arguments->at(0)->getAsTyped();
- ASSERT(firstElement);
- if (type.getOutermostArraySize() == 0u)
- {
- type.sizeOutermostUnsizedArray(static_cast<unsigned int>(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);
-
- // TODO(oetuaho@nvidia.com): Add support for folding array constructors.
- if (!constructorNode->isArray())
- {
- return constructorNode->fold(mDiagnostics);
- }
- return constructorNode;
-}
-
-//
-// Interface/uniform blocks
-// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
-//
-TIntermDeclaration *TParseContext::addInterfaceBlock(
- const TTypeQualifierBuilder &typeQualifierBuilder,
- const TSourceLoc &nameLine,
- const TString &blockName,
- TFieldList *fieldList,
- const TString *instanceName,
- const TSourceLoc &instanceLine,
- TIntermTyped *arrayIndex,
- const TSourceLoc &arrayIndexLine)
-{
- checkIsNotReserved(nameLine, blockName);
-
- TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
-
- 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 != EvqUniform && typeQualifier.qualifier != EvqBuffer)
- {
- 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 member", "invariant");
- }
-
- if (typeQualifier.qualifier != EvqBuffer)
- {
- checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
- }
-
- // add array index
- unsigned int arraySize = 0;
- if (arrayIndex != nullptr)
- {
- arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
- }
-
- if (mShaderVersion < 310)
- {
- checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
- }
- else
- {
- checkBlockBindingIsValid(typeQualifier.line, typeQualifier.qualifier,
- typeQualifier.layoutQualifier.binding, arraySize);
- }
-
- checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
-
- TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
- 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);
-
- if (!symbolTable.declareInterfaceBlockName(&blockName))
- {
- error(nameLine, "redefinition of an interface block name", blockName.c_str());
- }
-
- // 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;
- default:
- error(field->line(), "invalid qualifier on interface block member",
- getQualifierString(qualifier));
- break;
- }
-
- if (fieldType->isInvariant())
- {
- error(field->line(), "invalid qualifier on interface block member", "invariant");
- }
-
- // check layout qualifiers
- TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
- checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
- 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().c_str(), 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);
- }
- }
-
- TInterfaceBlock *interfaceBlock =
- new TInterfaceBlock(&blockName, fieldList, instanceName, blockLayoutQualifier);
- TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier);
- if (arrayIndex != nullptr)
- {
- interfaceBlockType.makeArray(arraySize);
- }
-
- TString symbolName = "";
- const TSymbolUniqueId *symbolId = nullptr;
-
- if (!instanceName)
- {
- // define symbols for the members of the interface block
- for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
- {
- TField *field = (*fieldList)[memberIndex];
- TType *fieldType = field->type();
-
- // set parent pointer of the field variable
- fieldType->setInterfaceBlock(interfaceBlock);
-
- TVariable *fieldVariable = symbolTable.declareVariable(&field->name(), *fieldType);
-
- if (fieldVariable)
- {
- fieldVariable->setQualifier(typeQualifier.qualifier);
- }
- else
- {
- error(field->line(), "redefinition of an interface block member name",
- field->name().c_str());
- }
- }
- symbolId = &symbolTable.getEmptySymbolId();
- }
- else
- {
- checkIsNotReserved(instanceLine, *instanceName);
-
- // add a symbol for this interface block
- TVariable *instanceTypeDef = symbolTable.declareVariable(instanceName, interfaceBlockType);
- if (instanceTypeDef)
- {
- instanceTypeDef->setQualifier(typeQualifier.qualifier);
- symbolId = &instanceTypeDef->getUniqueId();
- }
- else
- {
- error(instanceLine, "redefinition of an interface block instance name",
- instanceName->c_str());
- }
- symbolName = *instanceName;
- }
-
- TIntermDeclaration *declaration = nullptr;
-
- if (symbolId)
- {
- TIntermSymbol *blockSymbol = new TIntermSymbol(*symbolId, symbolName, interfaceBlockType);
- blockSymbol->setLine(typeQualifier.line);
- declaration = new TIntermDeclaration();
- declaration->appendDeclarator(blockSymbol);
- declaration->setLine(nameLine);
- }
-
- exitStructDeclaration();
- return declaration;
-}
-
-void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &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;
- reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
- << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
- std::string reason = reasonStream.str();
- error(line, reason.c_str(), field.name().c_str());
- 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()->getSymbol().c_str());
- }
- else
- {
- error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
- }
-
- return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
- }
-
- if (baseExpression->getQualifier() == EvqPerVertexIn)
- {
- ASSERT(mShaderType == GL_GEOMETRY_SHADER_OES);
- if (mGeometryShaderInputPrimitiveType == EptUndefined)
- {
- error(location, "missing input primitive declaration before indexing gl_in.", "[");
- return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
- }
- }
-
- TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
-
- // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
- // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
- // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
- // index is a constant expression.
- if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
- {
- if (baseExpression->isInterfaceBlock())
- {
- // TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
- switch (baseExpression->getQualifier())
- {
- case EvqPerVertexIn:
- break;
- case EvqUniform:
- case EvqBuffer:
- error(location,
- "array indexes for uniform block arrays and shader storage block arrays "
- "must be constant integral expressions",
- "[");
- break;
- default:
- // 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", "[");
- }
- }
-
- 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<int>(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)
- {
- 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 if (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);
- indexConstantUnion->replaceConstantUnion(safeConstantUnion);
- indexConstantUnion->getTypePointer()->setBasicType(EbtInt);
- }
-
- TIntermBinary *node =
- new TIntermBinary(EOpIndexDirect, baseExpression, indexExpression);
- node->setLine(location);
- return node->fold(mDiagnostics);
- }
- }
-
- 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);
- if (index >= arraySize)
- {
- std::stringstream reasonStream;
- 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 TString &fieldString,
- const TSourceLoc &fieldLocation)
-{
- if (baseExpression->isArray())
- {
- error(fieldLocation, "cannot apply dot operator to an array", ".");
- return baseExpression;
- }
-
- if (baseExpression->isVector())
- {
- TVector<int> 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();
- }
- 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 node->fold(mDiagnostics);
- }
- else
- {
- error(dotLocation, " no such field in structure", fieldString.c_str());
- 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.c_str());
- return baseExpression;
- }
- }
- }
- else
- {
- if (mShaderVersion < 300)
- {
- error(dotLocation, " field selection requires structure or vector on left hand side",
- fieldString.c_str());
- }
- else
- {
- error(dotLocation,
- " field selection requires structure, vector, or interface block on left hand "
- "side",
- fieldString.c_str());
- }
- return baseExpression;
- }
-}
-
-TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &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.c_str());
- }
- else if (qualifierType == "yuv" && mShaderType == GL_FRAGMENT_SHADER)
- {
- if (checkCanUseExtension(qualifierTypeLine, TExtension::EXT_YUV_target))
- {
- qualifier.yuv = 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")
- {
- checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
- qualifier.imageInternalFormat = EiifR32F;
- }
- else if (qualifierType == "rgba8")
- {
- 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")
- {
- 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")
- {
- checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
- qualifier.imageInternalFormat = EiifRGBA8UI;
- }
- else if (qualifierType == "r32ui")
- {
- checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
- qualifier.imageInternalFormat = EiifR32UI;
- }
- else if (qualifierType == "points" && mShaderType == GL_GEOMETRY_SHADER_OES &&
- checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
- {
- checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
- qualifier.primitiveType = EptPoints;
- }
- else if (qualifierType == "lines" && mShaderType == GL_GEOMETRY_SHADER_OES &&
- checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
- {
- checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
- qualifier.primitiveType = EptLines;
- }
- else if (qualifierType == "lines_adjacency" && mShaderType == GL_GEOMETRY_SHADER_OES &&
- checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
- {
- checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
- qualifier.primitiveType = EptLinesAdjacency;
- }
- else if (qualifierType == "triangles" && mShaderType == GL_GEOMETRY_SHADER_OES &&
- checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
- {
- checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
- qualifier.primitiveType = EptTriangles;
- }
- else if (qualifierType == "triangles_adjacency" && mShaderType == GL_GEOMETRY_SHADER_OES &&
- checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
- {
- checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
- qualifier.primitiveType = EptTrianglesAdjacency;
- }
- else if (qualifierType == "line_strip" && mShaderType == GL_GEOMETRY_SHADER_OES &&
- checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
- {
- checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
- qualifier.primitiveType = EptLineStrip;
- }
- else if (qualifierType == "triangle_strip" && mShaderType == GL_GEOMETRY_SHADER_OES &&
- checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
- {
- checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
- qualifier.primitiveType = EptTriangleStrip;
- }
-
- else
- {
- error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
- }
-
- return qualifier;
-}
-
-void TParseContext::parseLocalSize(const TString &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;
- 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;
- }
-}
-
-TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &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")
- {
- 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 (checkCanUseExtension(qualifierTypeLine, TExtension::OVR_multiview))
- {
- parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
- }
- }
- else if (qualifierType == "invocations" && mShaderType == GL_GEOMETRY_SHADER_OES &&
- checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
- {
- parseInvocations(intValue, intValueLine, intValueString, &qualifier.invocations);
- }
- else if (qualifierType == "max_vertices" && mShaderType == GL_GEOMETRY_SHADER_OES &&
- checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
- {
- parseMaxVertices(intValue, intValueLine, intValueString, &qualifier.maxVertices);
- }
-
- else
- {
- error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
- }
-
- 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(EvqIn, loc);
- }
-
- switch (getShaderType())
- {
- case GL_VERTEX_SHADER:
- {
- if (mShaderVersion < 300 && !isExtensionEnabled(TExtension::OVR_multiview))
- {
- 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)
- {
- 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_OES:
- {
- return new TStorageQualifierWrapper(EvqGeometryIn, loc);
- }
- default:
- {
- UNREACHABLE();
- return new TStorageQualifierWrapper(EvqLast, loc);
- }
- }
-}
-
-TStorageQualifierWrapper *TParseContext::parseOutQualifier(const TSourceLoc &loc)
-{
- if (declaringFunction())
- {
- return new TStorageQualifierWrapper(EvqOut, loc);
- }
- switch (getShaderType())
- {
- case GL_VERTEX_SHADER:
- {
- if (mShaderVersion < 300)
- {
- 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)
- {
- 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(EvqLast, loc);
- }
- case GL_GEOMETRY_SHADER_OES:
- {
- return new TStorageQualifierWrapper(EvqGeometryOut, loc);
- }
- default:
- {
- UNREACHABLE();
- return new TStorageQualifierWrapper(EvqLast, loc);
- }
- }
-}
-
-TStorageQualifierWrapper *TParseContext::parseInOutQualifier(const TSourceLoc &loc)
-{
- if (!declaringFunction())
- {
- error(loc, "invalid qualifier: can be only used with function parameters", "inout");
- }
- return new TStorageQualifierWrapper(EvqInOut, loc);
-}
-
-TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
- TLayoutQualifier rightQualifier,
- const TSourceLoc &rightQualifierLocation)
-{
- return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
- mDiagnostics);
-}
-
-TField *TParseContext::parseStructDeclarator(TString *identifier, const TSourceLoc &loc)
-{
- checkIsNotReserved(loc, *identifier);
- TType *type = new TType(EbtVoid, EbpUndefined);
- return new TField(type, identifier, loc);
-}
-
-TField *TParseContext::parseStructArrayDeclarator(TString *identifier,
- const TSourceLoc &loc,
- const TVector<unsigned int> &arraySizes,
- const TSourceLoc &arraySizeLoc)
-{
- checkIsNotReserved(loc, *identifier);
-
- TType *type = new TType(EbtVoid, EbpUndefined);
- type->makeArrays(arraySizes);
-
- return new TField(type, identifier, loc);
-}
-
-void TParseContext::checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin,
- const TFieldList::const_iterator end,
- const TString &name,
- const TSourceLoc &location)
-{
- for (auto fieldIter = begin; fieldIter != end; ++fieldIter)
- {
- if ((*fieldIter)->name() == name)
- {
- error(location, "duplicate field name in structure", name.c_str());
- }
- }
-}
-
-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,
- TFieldList *fieldList)
-{
- TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
-
- typeSpecifier->qualifier = typeQualifier.qualifier;
- typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
- typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
- typeSpecifier->invariant = typeQualifier.invariant;
- if (typeQualifier.precision != EbpUndefined)
- {
- typeSpecifier->precision = typeQualifier.precision;
- }
- return addStructDeclaratorList(*typeSpecifier, fieldList);
-}
-
-TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
- TFieldList *declaratorList)
-{
- checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
- typeSpecifier.getBasicType());
-
- checkIsNonVoid(typeSpecifier.getLine(), (*declaratorList)[0]->name(),
- typeSpecifier.getBasicType());
-
- checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
-
- for (TField *declarator : *declaratorList)
- {
- // Don't allow arrays of arrays in ESSL < 3.10.
- if (declarator->type()->isArray())
- {
- checkArrayElementIsNotArray(typeSpecifier.getLine(), typeSpecifier);
- }
-
- auto *declaratorArraySizes = declarator->type()->getArraySizes();
-
- TType *type = declarator->type();
- *type = TType(typeSpecifier);
- if (declaratorArraySizes != nullptr)
- {
- for (unsigned int arraySize : *declaratorArraySizes)
- {
- type->makeArray(arraySize);
- }
- }
-
- checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *declarator);
- }
-
- return declaratorList;
-}
-
-TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
- const TSourceLoc &nameLine,
- const TString *structName,
- TFieldList *fieldList)
-{
- TStructure *structure = new TStructure(&symbolTable, structName, fieldList);
-
- // 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 (!structName->empty())
- {
- checkIsNotReserved(nameLine, *structName);
- if (!symbolTable.declareStructType(structure))
- {
- error(nameLine, "redefinition of a struct", structName->c_str());
- }
- }
-
- // 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.
- if (IsImage(field.type()->getBasicType()) || IsAtomicCounter(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().c_str(), field.type());
-
- checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
-
- 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, mShaderVersion, mDiagnostics, statementList, loc))
- {
- ASSERT(mDiagnostics->numErrors() > 0);
- return nullptr;
- }
-
- 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();
- // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
- // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
- // fold in case labels.
- 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)
-{
- ASSERT(child != nullptr);
-
- switch (op)
- {
- case EOpLogicalNot:
- if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
- child->isVector())
- {
- unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
- return nullptr;
- }
- break;
- case EOpBitwiseNot:
- if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
- child->isMatrix() || child->isArray())
- {
- unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
- 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() ||
- IsOpaqueType(child->getBasicType()))
- {
- unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
- return nullptr;
- }
- // Operators for built-ins are already type checked against their prototype.
- default:
- break;
- }
-
- if (child->getMemoryQualifier().writeonly)
- {
- unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
- return nullptr;
- }
-
- TIntermUnary *node = new TIntermUnary(op, child);
- 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);
- 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);
-}
-
-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;
- case EOpIndexDirectStruct:
- UNREACHABLE();
-
- default:
- 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;
- }
-
- // GLSL ES 1.00 and 3.00 do not support implicit type casting.
- // So the basic type should usually match.
- if (!isBitShift && left->getBasicType() != right->getBasicType())
- {
- 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);
- node->setLine(loc);
-
- // See if we can fold constants.
- return node->fold(mDiagnostics);
-}
-
-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->getCompleteString(),
- right->getCompleteString());
- 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->getCompleteString(),
- right->getCompleteString());
- node = CreateBoolNode(false);
- node->setLine(loc);
- }
- return node;
-}
-
-TIntermBinary *TParseContext::createAssign(TOperator op,
- TIntermTyped *left,
- TIntermTyped *right,
- const TSourceLoc &loc)
-{
- if (binaryOpCommonCheck(op, left, right, loc))
- {
- if (op == EOpMulAssign)
- {
- op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
- if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
- {
- return nullptr;
- }
- }
- TIntermBinary *node = new TIntermBinary(op, left, right);
- node->setLine(loc);
-
- return node;
- }
- return nullptr;
-}
-
-TIntermTyped *TParseContext::addAssign(TOperator op,
- TIntermTyped *left,
- TIntermTyped *right,
- const TSourceLoc &loc)
-{
- checkCanBeLValue(loc, "assign", left);
- TIntermTyped *node = createAssign(op, left, right, loc);
- if (node == nullptr)
- {
- assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
- return left;
- }
- 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 = new TIntermBinary(EOpComma, left, right);
- TQualifier resultQualifier = TIntermBinary::GetCommaQualifier(mShaderVersion, left, right);
- commaNode->getTypePointer()->setQualifier(resultQualifier);
- return commaNode->fold(mDiagnostics);
-}
-
-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");
- }
- break;
- case EOpKill:
- if (mShaderType != GL_FRAGMENT_SHADER)
- {
- error(loc, "discard supported in fragment shaders only", "discard");
- }
- break;
- default:
- UNREACHABLE();
- break;
- }
- return addBranch(op, nullptr, loc);
-}
-
-TIntermBranch *TParseContext::addBranch(TOperator op,
- TIntermTyped *expression,
- const TSourceLoc &loc)
-{
- if (expression != nullptr)
- {
- 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::checkTextureGather(TIntermAggregate *functionCall)
-{
- ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
- const TString &name = functionCall->getFunctionSymbolInfo()->getName();
- bool isTextureGather = (name == "textureGather");
- bool isTextureGatherOffset = (name == "textureGatherOffset");
- if (isTextureGather || isTextureGatherOffset)
- {
- 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 ((isTextureGather && arguments->size() == 3u) ||
- (isTextureGatherOffset && arguments->size() == 4u))
- {
- componentNode = arguments->back();
- }
- break;
- case EbtSamplerCube:
- case EbtISamplerCube:
- case EbtUSamplerCube:
- ASSERT(!isTextureGatherOffset);
- if (arguments->size() == 3u)
- {
- componentNode = arguments->back();
- }
- break;
- case EbtSampler2DShadow:
- case EbtSampler2DArrayShadow:
- case EbtSamplerCubeShadow:
- 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",
- name.c_str());
- }
- else
- {
- int component = componentConstantUnion->getIConst(0);
- if (component < 0 || component > 3)
- {
- error(functionCall->getLine(), "Component must be in the range [0;3]",
- name.c_str());
- }
- }
- }
- }
-}
-
-void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
-{
- ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
- const TString &name = functionCall->getFunctionSymbolInfo()->getName();
- TIntermNode *offset = nullptr;
- TIntermSequence *arguments = functionCall->getSequence();
- bool useTextureGatherOffsetConstraints = false;
- if (name == "texelFetchOffset" || name == "textureLodOffset" ||
- name == "textureProjLodOffset" || name == "textureGradOffset" ||
- name == "textureProjGradOffset")
- {
- offset = arguments->back();
- }
- else if (name == "textureOffset" || name == "textureProjOffset")
- {
- // A bias parameter might follow the offset parameter.
- ASSERT(arguments->size() >= 3);
- offset = (*arguments)[2];
- }
- else if (name == "textureGatherOffset")
- {
- ASSERT(arguments->size() >= 3u);
- const TIntermTyped *sampler = arguments->front()->getAsTyped();
- ASSERT(sampler != nullptr);
- switch (sampler->getBasicType())
- {
- case EbtSampler2D:
- case EbtISampler2D:
- case EbtUSampler2D:
- case EbtSampler2DArray:
- case EbtISampler2DArray:
- case EbtUSampler2DArray:
- offset = (*arguments)[2];
- break;
- case EbtSampler2DShadow:
- case EbtSampler2DArrayShadow:
- offset = (*arguments)[3];
- break;
- default:
- UNREACHABLE();
- break;
- }
- useTextureGatherOffsetConstraints = true;
- }
- if (offset != nullptr)
- {
- TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
- if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
- {
- error(functionCall->getLine(), "Texture offset must be a constant expression",
- name.c_str());
- }
- else
- {
- ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
- size_t size = offsetConstantUnion->getType().getObjectSize();
- const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
- int minOffsetValue = useTextureGatherOffsetConstraints ? mMinProgramTextureGatherOffset
- : mMinProgramTexelOffset;
- int maxOffsetValue = useTextureGatherOffsetConstraints ? mMaxProgramTextureGatherOffset
- : mMaxProgramTexelOffset;
- for (size_t i = 0u; i < size; ++i)
- {
- int offsetValue = values[i].getIConst();
- if (offsetValue > maxOffsetValue || offsetValue < minOffsetValue)
- {
- std::stringstream tokenStream;
- tokenStream << offsetValue;
- std::string token = tokenStream.str();
- error(offset->getLine(), "Texture offset value out of valid range",
- token.c_str());
- }
- }
- }
- }
-}
-
-void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall)
-{
- const TString &name = functionCall->getFunctionSymbolInfo()->getName();
- if (IsAtomicBuiltin(name))
- {
- TIntermSequence *arguments = functionCall->getSequence();
- TIntermTyped *memNode = (*arguments)[0]->getAsTyped();
-
- if (IsBufferOrSharedVariable(memNode))
- {
- return;
- }
-
- while (memNode->getAsBinaryNode())
- {
- memNode = memNode->getAsBinaryNode()->getLeft();
- 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.",
- functionCall->getFunctionSymbolInfo()->getName().c_str());
- }
-}
-
-// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
-void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
-{
- ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
- const TString &name = functionCall->getFunctionSymbolInfo()->getName();
-
- if (name.compare(0, 5, "image") == 0)
- {
- TIntermSequence *arguments = functionCall->getSequence();
- TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
-
- const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
-
- if (name.compare(5, 5, "Store") == 0)
- {
- if (memoryQualifier.readonly)
- {
- error(imageNode->getLine(),
- "'imageStore' cannot be used with images qualified as 'readonly'",
- GetImageArgumentToken(imageNode));
- }
- }
- else if (name.compare(5, 4, "Load") == 0)
- {
- if (memoryQualifier.writeonly)
- {
- error(imageNode->getLine(),
- "'imageLoad' 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).type;
- 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));
- }
- }
- }
-}
-
-TIntermSequence *TParseContext::createEmptyArgumentsList()
-{
- return new TIntermSequence();
-}
-
-TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
- TIntermSequence *arguments,
- TIntermNode *thisNode,
- const TSourceLoc &loc)
-{
- if (thisNode != nullptr)
- {
- return addMethod(fnCall, arguments, thisNode, loc);
- }
-
- TOperator op = fnCall->getBuiltInOp();
- if (op == EOpConstruct)
- {
- return addConstructor(arguments, fnCall->getReturnType(), loc);
- }
- else
- {
- ASSERT(op == EOpNull);
- return addNonConstructorFunctionCall(fnCall, arguments, loc);
- }
-}
-
-TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
- TIntermSequence *arguments,
- TIntermNode *thisNode,
- const TSourceLoc &loc)
-{
- TIntermTyped *typedThis = thisNode->getAsTyped();
- // 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->getName() below is safe.
- if (fnCall->getName() != "length")
- {
- error(loc, "invalid method", fnCall->getName().c_str());
- }
- else if (!arguments->empty())
- {
- error(loc, "method takes no parameters", "length");
- }
- else if (typedThis == nullptr || !typedThis->isArray())
- {
- error(loc, "length can only be called on arrays", "length");
- }
- else if (typedThis->getQualifier() == EvqPerVertexIn &&
- mGeometryShaderInputPrimitiveType == EptUndefined)
- {
- ASSERT(mShaderType == GL_GEOMETRY_SHADER_OES);
- error(loc, "missing input primitive declaration before calling length on gl_in", "length");
- }
- else
- {
- TIntermUnary *node = new TIntermUnary(EOpArrayLength, typedThis);
- node->setLine(loc);
- return node->fold(mDiagnostics);
- }
- return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst));
-}
-
-TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
- TIntermSequence *arguments,
- const TSourceLoc &loc)
-{
- // First find by unmangled name to check whether the function name has been
- // hidden by a variable name or struct typename.
- // If a function is found, check for one with a matching argument list.
- bool builtIn;
- const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn);
- if (symbol != nullptr && !symbol->isFunction())
- {
- error(loc, "function name expected", fnCall->getName().c_str());
- }
- else
- {
- symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments),
- mShaderVersion, &builtIn);
- if (symbol == nullptr)
- {
- error(loc, "no matching overloaded function found", fnCall->getName().c_str());
- }
- else
- {
- const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
- //
- // A declared function.
- //
- if (builtIn && fnCandidate->getExtension() != TExtension::UNDEFINED)
- {
- checkCanUseExtension(loc, fnCandidate->getExtension());
- }
- TOperator op = fnCandidate->getBuiltInOp();
- if (builtIn && op != EOpNull)
- {
- // A function call mapped to a built-in operation.
- if (fnCandidate->getParamCount() == 1)
- {
- // Treat it like a built-in unary operator.
- TIntermNode *unaryParamNode = arguments->front();
- TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
- ASSERT(callNode != nullptr);
- return callNode;
- }
- else
- {
- TIntermAggregate *callNode =
- TIntermAggregate::Create(fnCandidate->getReturnType(), op, arguments);
- callNode->setLine(loc);
-
- // Some built-in functions have out parameters too.
- functionCallRValueLValueErrorCheck(fnCandidate, callNode);
-
- if (TIntermAggregate::CanFoldAggregateBuiltInOp(callNode->getOp()))
- {
- // 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
- {
- return callNode;
- }
- }
- }
- else
- {
- // This is a real function call
- TIntermAggregate *callNode = nullptr;
-
- // If builtIn == false, the function is user defined - could be an overloaded
- // built-in as well.
- // if builtIn == true, it's a builtIn function with no op associated with it.
- // This needs to happen after the function info including name is set.
- if (builtIn)
- {
- callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, arguments);
- checkTextureOffsetConst(callNode);
- checkTextureGather(callNode);
- checkImageMemoryAccessForBuiltinFunctions(callNode);
- checkAtomicMemoryBuiltinFunctions(callNode);
- }
- else
- {
- callNode = TIntermAggregate::CreateFunctionCall(*fnCandidate, arguments);
- checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
- }
-
- functionCallRValueLValueErrorCheck(fnCandidate, callNode);
-
- callNode->setLine(loc);
-
- return callNode;
- }
- }
- }
-
- // Error message was already written. Put on a dummy 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())
- {
- std::stringstream reasonStream;
- reasonStream << "mismatching ternary operator operand types '"
- << trueExpression->getCompleteString() << " and '"
- << falseExpression->getCompleteString() << "'";
- std::string reason = reasonStream.str();
- error(loc, reason.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;
- }
-
- // Note that the node resulting from here can be a constant union without being qualified as
- // constant.
- TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression);
- node->setLine(loc);
-
- return node->fold();
-}
-
-//
-// 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/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h
deleted file mode 100644
index 8bfdbd5e3f..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ParseContext.h
+++ /dev/null
@@ -1,657 +0,0 @@
-//
-// Copyright (c) 2002-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_PARSECONTEXT_H_
-#define COMPILER_TRANSLATOR_PARSECONTEXT_H_
-
-#include "compiler/translator/Compiler.h"
-#include "compiler/translator/Diagnostics.h"
-#include "compiler/translator/DirectiveHandler.h"
-#include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/QualifierTypes.h"
-#include "compiler/preprocessor/Preprocessor.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,
- ShCompileOptions options,
- bool checksPrecErrors,
- TDiagnostics *diagnostics,
- const ShBuiltInResources &resources);
- ~TParseContext();
-
- const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; }
- 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 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) { mTreeRoot = treeRoot; }
-
- bool getFragmentPrecisionHigh() const
- {
- return mFragmentPrecisionHighOnESSL1 || mShaderVersion >= 300;
- }
- void setFragmentPrecisionHighOnESSL1(bool fragmentPrecisionHigh)
- {
- mFragmentPrecisionHighOnESSL1 = fragmentPrecisionHigh;
- }
-
- 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; }
-
- 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 TString *name,
- const TSymbol *symbol);
- TIntermTyped *parseVariableIdentifier(const TSourceLoc &location,
- const TString *name,
- const TSymbol *symbol);
-
- // Look at a '.' field selector string and change it into offsets for a vector.
- bool parseVectorFields(const TSourceLoc &line,
- const TString &compString,
- int vecSize,
- TVector<int> *fieldOffsets);
-
- void assignError(const TSourceLoc &line, const char *op, TString left, TString right);
- void unaryOpError(const TSourceLoc &line, const char *op, TString operand);
- void binaryOpError(const TSourceLoc &line, const char *op, TString left, TString right);
-
- // Check functions - the ones that return bool return false if an error was generated.
-
- bool checkIsNotReserved(const TSourceLoc &line, const TString &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 checkIsNonVoid(const TSourceLoc &line, const TString &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 <size_t size>
- bool checkCanUseOneOfExtensions(const TSourceLoc &line,
- const std::array<TExtension, size> &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 checkLayoutQualifierSupported(const TSourceLoc &location,
- const TString &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);
- 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);
-
- // 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 TString &identifier,
- TType type,
- TIntermTyped *initializer,
- TIntermBinary **initNode);
- TIntermNode *addConditionInitializer(const TPublicType &pType,
- const TString &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 TString &identifier);
- TIntermDeclaration *parseSingleArrayDeclaration(TPublicType &elementType,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &indexLocation,
- const TVector<unsigned int> &arraySizes);
- TIntermDeclaration *parseSingleInitDeclaration(const TPublicType &publicType,
- const TSourceLoc &identifierLocation,
- const TString &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 TString &identifier,
- const TSourceLoc &indexLocation,
- const TVector<unsigned int> &arraySizes,
- const TSourceLoc &initLocation,
- TIntermTyped *initializer);
-
- TIntermInvariantDeclaration *parseInvariantDeclaration(
- const TTypeQualifierBuilder &typeQualifierBuilder,
- const TSourceLoc &identifierLoc,
- const TString *identifier,
- const TSymbol *symbol);
-
- void parseDeclarator(TPublicType &publicType,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- TIntermDeclaration *declarationOut);
- void parseArrayDeclarator(TPublicType &elementType,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &arrayLocation,
- const TVector<unsigned int> &arraySizes,
- TIntermDeclaration *declarationOut);
- void parseInitDeclarator(const TPublicType &publicType,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &initLocation,
- TIntermTyped *initializer,
- TIntermDeclaration *declarationOut);
-
- // Parse a declarator like "a[n] = initializer"
- void parseArrayInitDeclarator(const TPublicType &elementType,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &indexLocation,
- const TVector<unsigned int> &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,
- TFunction **function,
- TIntermFunctionPrototype **prototypeOut);
- TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function);
- TFunction *parseFunctionHeader(const TPublicType &type,
- const TString *name,
- const TSourceLoc &location);
- TFunction *addNonConstructorFunc(const TString *name, const TSourceLoc &loc);
- TFunction *addConstructorFunc(const TPublicType &publicType);
- TParameter parseParameterDeclarator(const TPublicType &publicType,
- const TString *name,
- const TSourceLoc &nameLoc);
-
- TParameter parseParameterArrayDeclarator(const TString *name,
- const TSourceLoc &nameLoc,
- const TVector<unsigned int> &arraySizes,
- const TSourceLoc &arrayLoc,
- TPublicType *elementType);
-
- TIntermTyped *addIndexExpression(TIntermTyped *baseExpression,
- const TSourceLoc &location,
- TIntermTyped *indexExpression);
- TIntermTyped *addFieldSelectionExpression(TIntermTyped *baseExpression,
- const TSourceLoc &dotLocation,
- const TString &fieldString,
- const TSourceLoc &fieldLocation);
-
- // Parse declarator for a single field
- TField *parseStructDeclarator(TString *identifier, const TSourceLoc &loc);
- TField *parseStructArrayDeclarator(TString *identifier,
- const TSourceLoc &loc,
- const TVector<unsigned int> &arraySizes,
- const TSourceLoc &arraySizeLoc);
-
- void checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin,
- const TFieldList::const_iterator end,
- const TString &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,
- TFieldList *fieldList);
- TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList);
- TTypeSpecifierNonArray addStructure(const TSourceLoc &structLine,
- const TSourceLoc &nameLine,
- const TString *structName,
- TFieldList *fieldList);
-
- TIntermDeclaration *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder,
- const TSourceLoc &nameLine,
- const TString &blockName,
- TFieldList *fieldList,
- const TString *instanceName,
- const TSourceLoc &instanceLine,
- TIntermTyped *arrayIndex,
- const TSourceLoc &arrayIndexLine);
-
- void parseLocalSize(const TString &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);
- TLayoutQualifier parseLayoutQualifier(const TString &qualifierType,
- const TSourceLoc &qualifierTypeLine);
- TLayoutQualifier parseLayoutQualifier(const TString &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 TString &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 checkTextureGather(TIntermAggregate *functionCall);
- void checkTextureOffsetConst(TIntermAggregate *functionCall);
- void checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall);
- void checkImageMemoryAccessForUserDefinedFunctions(const TFunction *functionDefinition,
- const TIntermAggregate *functionCall);
- void checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall);
- TIntermSequence *createEmptyArgumentsList();
-
- // fnCall is only storing the built-in op, and function name or constructor type. arguments
- // has the arguments.
- TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall,
- TIntermSequence *arguments,
- TIntermNode *thisNode,
- 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;
- }
-
- // 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;
-
- // 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 TString &identifier,
- const TType &type,
- TVariable **variable);
-
- void checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
- const TString &identifier,
- TType *type);
-
- TParameter parseParameterDeclarator(TType *type,
- const TString *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 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 checkUniformLocationInRange(const TSourceLoc &location,
- int objectLocationCount,
- const TLayoutQualifier &layoutQualifier);
-
- void checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv);
-
- bool checkUnsizedArrayConstructorArgumentDimensionality(TIntermSequence *arguments,
- TType type,
- const TSourceLoc &line);
-
- // Will set the size of the outermost array according to geometry shader input layout.
- void checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location,
- const char *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 char *token,
- TType *arrayType);
-
- TIntermTyped *addBinaryMathInternal(TOperator op,
- TIntermTyped *left,
- TIntermTyped *right,
- const TSourceLoc &loc);
- TIntermBinary *createAssign(TOperator op,
- TIntermTyped *left,
- TIntermTyped *right,
- const TSourceLoc &loc);
- TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
-
- TIntermTyped *addMethod(TFunction *fnCall,
- TIntermSequence *arguments,
- TIntermNode *thisNode,
- const TSourceLoc &loc);
- TIntermTyped *addConstructor(TIntermSequence *arguments,
- TType type,
- const TSourceLoc &line);
- TIntermTyped *addNonConstructorFunctionCall(TFunction *fnCall,
- TIntermSequence *arguments,
- const TSourceLoc &loc);
-
- // 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);
-
- // 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 or fragment language (future: pack or unpack)
- ShShaderSpec mShaderSpec; // The language specification compiler conforms to - GLES2 or WebGL.
- 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.
- TLayoutMatrixPacking mDefaultUniformMatrixPacking;
- TLayoutBlockStorage mDefaultUniformBlockStorage;
- TLayoutMatrixPacking mDefaultBufferMatrixPacking;
- TLayoutBlockStorage mDefaultBufferBlockStorage;
- TString mHashErrMsg;
- TDiagnostics *mDiagnostics;
- TDirectiveHandler mDirectiveHandler;
- pp::Preprocessor mPreprocessor;
- void *mScanner;
- bool mUsesFragData; // track if we are using both gl_FragData and gl_FragColor
- bool mUsesFragColor;
- bool mUsesSecondaryOutputs; // Track if we are using either gl_SecondaryFragData or
- // gl_Secondary FragColor or both.
- 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 mMaxAtomicCounterBindings;
- int mMaxShaderStorageBufferBindings;
-
- // keeps track whether we are declaring / defining a function
- bool mDeclaringFunction;
-
- // Track the state of each atomic counter binding.
- std::map<int, AtomicCounterBindingState> mAtomicCounterBindingStates;
-
- // Track the geometry shader global parameters declared in layout.
- TLayoutPrimitiveType mGeometryShaderInputPrimitiveType;
- TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType;
- int mGeometryShaderInvocations;
- int mGeometryShaderMaxVertices;
- int mMaxGeometryShaderInvocations;
- int mMaxGeometryShaderMaxVertices;
-
- // Track if all input array sizes are same and matches the latter input primitive declaration.
- unsigned int mGeometryShaderInputArraySize;
-};
-
-int PaParseStrings(size_t count,
- const char *const string[],
- const int length[],
- TParseContext *context);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_PARSECONTEXT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp
deleted file mode 100644
index 0f1cd8b5c9..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp
+++ /dev/null
@@ -1,360 +0,0 @@
-//
-// Copyright (c) 2002-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/PoolAlloc.h"
-
-#include <stdint.h>
-#include <stdio.h>
-#include <assert.h>
-
-#include "common/angleutils.h"
-#include "common/debug.h"
-#include "common/platform.h"
-#include "common/tls.h"
-#include "compiler/translator/InitializeGlobals.h"
-
-TLSIndex PoolIndex = TLS_INVALID_INDEX;
-
-bool InitializePoolIndex()
-{
- assert(PoolIndex == TLS_INVALID_INDEX);
-
- PoolIndex = CreateTLSIndex();
- return PoolIndex != TLS_INVALID_INDEX;
-}
-
-void FreePoolIndex()
-{
- assert(PoolIndex != TLS_INVALID_INDEX);
-
- DestroyTLSIndex(PoolIndex);
- PoolIndex = TLS_INVALID_INDEX;
-}
-
-TPoolAllocator *GetGlobalPoolAllocator()
-{
- assert(PoolIndex != TLS_INVALID_INDEX);
- return static_cast<TPoolAllocator *>(GetTLSValue(PoolIndex));
-}
-
-void SetGlobalPoolAllocator(TPoolAllocator *poolAllocator)
-{
- assert(PoolIndex != TLS_INVALID_INDEX);
- SetTLSValue(PoolIndex, poolAllocator);
-}
-
-//
-// Implement the functionality of the TPoolAllocator class, which
-// is documented in PoolAlloc.h.
-//
-TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment)
- : alignment(allocationAlignment),
-#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
- pageSize(growthIncrement),
- freeList(0),
- inUseList(0),
- numCalls(0),
- totalBytes(0),
-#endif
- mLocked(false)
-{
- //
- // Adjust alignment to be at least pointer aligned and
- // power of 2.
- //
- size_t minAlign = sizeof(void *);
- alignment &= ~(minAlign - 1);
- if (alignment < minAlign)
- alignment = minAlign;
- size_t a = 1;
- while (a < alignment)
- a <<= 1;
- alignment = a;
- alignmentMask = a - 1;
-
-#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
- //
- // Don't allow page sizes we know are smaller than all common
- // OS page sizes.
- //
- if (pageSize < 4 * 1024)
- pageSize = 4 * 1024;
-
- //
- // A large currentPageOffset indicates a new page needs to
- // be obtained to allocate memory.
- //
- currentPageOffset = pageSize;
-
- //
- // Align header skip
- //
- headerSkip = minAlign;
- if (headerSkip < sizeof(tHeader))
- {
- headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
- }
-#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
- mStack.push_back({});
-#endif
-}
-
-TPoolAllocator::~TPoolAllocator()
-{
-#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
- while (inUseList)
- {
- tHeader *next = inUseList->nextPage;
- inUseList->~tHeader();
- delete[] reinterpret_cast<char *>(inUseList);
- inUseList = next;
- }
-
- // We should not check the guard blocks
- // here, because we did it already when the block was
- // placed into the free list.
- //
- while (freeList)
- {
- tHeader *next = freeList->nextPage;
- delete[] reinterpret_cast<char *>(freeList);
- freeList = next;
- }
-#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
- for (auto &allocs : mStack)
- {
- for (auto alloc : allocs)
- {
- free(alloc);
- }
- }
- mStack.clear();
-#endif
-}
-
-// Support MSVC++ 6.0
-const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
-const unsigned char TAllocation::guardBlockEndVal = 0xfe;
-const unsigned char TAllocation::userDataFill = 0xcd;
-
-#ifdef GUARD_BLOCKS
-const size_t TAllocation::guardBlockSize = 16;
-#else
-const size_t TAllocation::guardBlockSize = 0;
-#endif
-
-//
-// Check a single guard block for damage
-//
-void TAllocation::checkGuardBlock(unsigned char *blockMem,
- unsigned char val,
- const char *locText) const
-{
-#ifdef GUARD_BLOCKS
- for (size_t x = 0; x < guardBlockSize; x++)
- {
- if (blockMem[x] != val)
- {
- char assertMsg[80];
-
-// We don't print the assert message. It's here just to be helpful.
-#if defined(_MSC_VER)
- snprintf(assertMsg, sizeof(assertMsg),
- "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n", locText, size, data());
-#else
- snprintf(assertMsg, sizeof(assertMsg),
- "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n", locText, size, data());
-#endif
- assert(0 && "PoolAlloc: Damage in guard block");
- }
- }
-#endif
-}
-
-void TPoolAllocator::push()
-{
-#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
- tAllocState state = {currentPageOffset, inUseList};
-
- mStack.push_back(state);
-
- //
- // Indicate there is no current page to allocate from.
- //
- currentPageOffset = pageSize;
-#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
- mStack.push_back({});
-#endif
-}
-
-//
-// Do a mass-deallocation of all the individual allocations
-// that have occurred since the last push(), or since the
-// last pop(), or since the object's creation.
-//
-// The deallocated pages are saved for future allocations.
-//
-void TPoolAllocator::pop()
-{
- if (mStack.size() < 1)
- return;
-
-#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
- tHeader *page = mStack.back().page;
- currentPageOffset = mStack.back().offset;
-
- while (inUseList != page)
- {
- // invoke destructor to free allocation list
- inUseList->~tHeader();
-
- tHeader *nextInUse = inUseList->nextPage;
- if (inUseList->pageCount > 1)
- delete[] reinterpret_cast<char *>(inUseList);
- else
- {
- inUseList->nextPage = freeList;
- freeList = inUseList;
- }
- inUseList = nextInUse;
- }
-
- mStack.pop_back();
-#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
- for (auto &alloc : mStack.back())
- {
- free(alloc);
- }
- mStack.pop_back();
-#endif
-}
-
-//
-// Do a mass-deallocation of all the individual allocations
-// that have occurred.
-//
-void TPoolAllocator::popAll()
-{
- while (mStack.size() > 0)
- pop();
-}
-
-void *TPoolAllocator::allocate(size_t numBytes)
-{
- ASSERT(!mLocked);
-
-#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
- //
- // Just keep some interesting statistics.
- //
- ++numCalls;
- totalBytes += numBytes;
-
- // If we are using guard blocks, all allocations are bracketed by
- // them: [guardblock][allocation][guardblock]. numBytes is how
- // much memory the caller asked for. allocationSize is the total
- // size including guard blocks. In release build,
- // guardBlockSize=0 and this all gets optimized away.
- size_t allocationSize = TAllocation::allocationSize(numBytes);
- // Detect integer overflow.
- if (allocationSize < numBytes)
- return 0;
-
- //
- // Do the allocation, most likely case first, for efficiency.
- // This step could be moved to be inline sometime.
- //
- if (allocationSize <= pageSize - currentPageOffset)
- {
- //
- // Safe to allocate from currentPageOffset.
- //
- unsigned char *memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
- currentPageOffset += allocationSize;
- currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;
-
- return initializeAllocation(inUseList, memory, numBytes);
- }
-
- if (allocationSize > pageSize - headerSkip)
- {
- //
- // Do a multi-page allocation. Don't mix these with the others.
- // The OS is efficient and allocating and free-ing multiple pages.
- //
- size_t numBytesToAlloc = allocationSize + headerSkip;
- // Detect integer overflow.
- if (numBytesToAlloc < allocationSize)
- return 0;
-
- tHeader *memory = reinterpret_cast<tHeader *>(::new char[numBytesToAlloc]);
- if (memory == 0)
- return 0;
-
- // Use placement-new to initialize header
- new (memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
- inUseList = memory;
-
- currentPageOffset = pageSize; // make next allocation come from a new page
-
- // No guard blocks for multi-page allocations (yet)
- return reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(memory) + headerSkip);
- }
-
- //
- // Need a simple page to allocate from.
- //
- tHeader *memory;
- if (freeList)
- {
- memory = freeList;
- freeList = freeList->nextPage;
- }
- else
- {
- memory = reinterpret_cast<tHeader *>(::new char[pageSize]);
- if (memory == 0)
- return 0;
- }
-
- // Use placement-new to initialize header
- new (memory) tHeader(inUseList, 1);
- inUseList = memory;
-
- unsigned char *ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
- currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
-
- return initializeAllocation(inUseList, ret, numBytes);
-#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
- void *alloc = malloc(numBytes + alignmentMask);
- mStack.back().push_back(alloc);
-
- intptr_t intAlloc = reinterpret_cast<intptr_t>(alloc);
- intAlloc = (intAlloc + alignmentMask) & ~alignmentMask;
- return reinterpret_cast<void *>(intAlloc);
-#endif
-}
-
-void TPoolAllocator::lock()
-{
- ASSERT(!mLocked);
- mLocked = true;
-}
-
-void TPoolAllocator::unlock()
-{
- ASSERT(mLocked);
- mLocked = false;
-}
-
-//
-// Check all allocations in a list for damage by calling check on each.
-//
-void TAllocation::checkAllocList() const
-{
- for (const TAllocation *alloc = this; alloc != 0; alloc = alloc->prevAlloc)
- alloc->check();
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h
deleted file mode 100644
index ad63bc4cd6..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h
+++ /dev/null
@@ -1,319 +0,0 @@
-//
-// Copyright (c) 2002-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_POOLALLOC_H_
-#define COMPILER_TRANSLATOR_POOLALLOC_H_
-
-#ifdef _DEBUG
-#define GUARD_BLOCKS // define to enable guard block sanity checking
-#endif
-
-//
-// This header defines an allocator that can be used to efficiently
-// allocate a large number of small requests for heap memory, with the
-// intention that they are not individually deallocated, but rather
-// collectively deallocated at one time.
-//
-// This simultaneously
-//
-// * Makes each individual allocation much more efficient; the
-// typical allocation is trivial.
-// * Completely avoids the cost of doing individual deallocation.
-// * Saves the trouble of tracking down and plugging a large class of leaks.
-//
-// Individual classes can use this allocator by supplying their own
-// new and delete methods.
-//
-// STL containers can use this allocator by using the pool_allocator
-// class as the allocator (second) template argument.
-//
-
-#include <stddef.h>
-#include <string.h>
-#include <vector>
-
-// If we are using guard blocks, we must track each indivual
-// allocation. If we aren't using guard blocks, these
-// never get instantiated, so won't have any impact.
-//
-
-class TAllocation
-{
- public:
- TAllocation(size_t size, unsigned char *mem, TAllocation *prev = 0)
- : size(size), mem(mem), prevAlloc(prev)
- {
-// Allocations are bracketed:
-// [allocationHeader][initialGuardBlock][userData][finalGuardBlock]
-// This would be cleaner with if (guardBlockSize)..., but that
-// makes the compiler print warnings about 0 length memsets,
-// even with the if() protecting them.
-#ifdef GUARD_BLOCKS
- memset(preGuard(), guardBlockBeginVal, guardBlockSize);
- memset(data(), userDataFill, size);
- memset(postGuard(), guardBlockEndVal, guardBlockSize);
-#endif
- }
-
- void check() const
- {
- checkGuardBlock(preGuard(), guardBlockBeginVal, "before");
- checkGuardBlock(postGuard(), guardBlockEndVal, "after");
- }
-
- void checkAllocList() const;
-
- // Return total size needed to accomodate user buffer of 'size',
- // plus our tracking data.
- inline static size_t allocationSize(size_t size)
- {
- return size + 2 * guardBlockSize + headerSize();
- }
-
- // Offset from surrounding buffer to get to user data buffer.
- inline static unsigned char *offsetAllocation(unsigned char *m)
- {
- return m + guardBlockSize + headerSize();
- }
-
- private:
- void checkGuardBlock(unsigned char *blockMem, unsigned char val, const char *locText) const;
-
- // Find offsets to pre and post guard blocks, and user data buffer
- unsigned char *preGuard() const { return mem + headerSize(); }
- unsigned char *data() const { return preGuard() + guardBlockSize; }
- unsigned char *postGuard() const { return data() + size; }
-
- size_t size; // size of the user data area
- unsigned char *mem; // beginning of our allocation (pts to header)
- TAllocation *prevAlloc; // prior allocation in the chain
-
- // Support MSVC++ 6.0
- const static unsigned char guardBlockBeginVal;
- const static unsigned char guardBlockEndVal;
- const static unsigned char userDataFill;
-
- const static size_t guardBlockSize;
-#ifdef GUARD_BLOCKS
- inline static size_t headerSize() { return sizeof(TAllocation); }
-#else
- inline static size_t headerSize() { return 0; }
-#endif
-};
-
-//
-// There are several stacks. One is to track the pushing and popping
-// of the user, and not yet implemented. The others are simply a
-// repositories of free pages or used pages.
-//
-// Page stacks are linked together with a simple header at the beginning
-// of each allocation obtained from the underlying OS. Multi-page allocations
-// are returned to the OS. Individual page allocations are kept for future
-// re-use.
-//
-// The "page size" used is not, nor must it match, the underlying OS
-// page size. But, having it be about that size or equal to a set of
-// pages is likely most optimal.
-//
-class TPoolAllocator
-{
- public:
- TPoolAllocator(int growthIncrement = 8 * 1024, int allocationAlignment = 16);
-
- //
- // Don't call the destructor just to free up the memory, call pop()
- //
- ~TPoolAllocator();
-
- //
- // Call push() to establish a new place to pop memory too. Does not
- // have to be called to get things started.
- //
- void push();
-
- //
- // Call pop() to free all memory allocated since the last call to push(),
- // or if no last call to push, frees all memory since first allocation.
- //
- void pop();
-
- //
- // Call popAll() to free all memory allocated.
- //
- void popAll();
-
- //
- // Call allocate() to actually acquire memory. Returns 0 if no memory
- // available, otherwise a properly aligned pointer to 'numBytes' of memory.
- //
- void *allocate(size_t numBytes);
-
- //
- // There is no deallocate. The point of this class is that
- // deallocation can be skipped by the user of it, as the model
- // of use is to simultaneously deallocate everything at once
- // by calling pop(), and to not have to solve memory leak problems.
- //
-
- // Catch unwanted allocations.
- // TODO(jmadill): Remove this when we remove the global allocator.
- void lock();
- void unlock();
-
- private:
- size_t alignment; // all returned allocations will be aligned at
- // this granularity, which will be a power of 2
- size_t alignmentMask;
-
-#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
- friend struct tHeader;
-
- struct tHeader
- {
- tHeader(tHeader *nextPage, size_t pageCount)
- : nextPage(nextPage),
- pageCount(pageCount)
-#ifdef GUARD_BLOCKS
- ,
- lastAllocation(0)
-#endif
- {
- }
-
- ~tHeader()
- {
-#ifdef GUARD_BLOCKS
- if (lastAllocation)
- lastAllocation->checkAllocList();
-#endif
- }
-
- tHeader *nextPage;
- size_t pageCount;
-#ifdef GUARD_BLOCKS
- TAllocation *lastAllocation;
-#endif
- };
-
- struct tAllocState
- {
- size_t offset;
- tHeader *page;
- };
- typedef std::vector<tAllocState> tAllocStack;
-
- // Track allocations if and only if we're using guard blocks
- void *initializeAllocation(tHeader *block, unsigned char *memory, size_t numBytes)
- {
-#ifdef GUARD_BLOCKS
- new (memory) TAllocation(numBytes, memory, block->lastAllocation);
- block->lastAllocation = reinterpret_cast<TAllocation *>(memory);
-#endif
- // This is optimized entirely away if GUARD_BLOCKS is not defined.
- return TAllocation::offsetAllocation(memory);
- }
-
- size_t pageSize; // granularity of allocation from the OS
- size_t headerSkip; // amount of memory to skip to make room for the
- // header (basically, size of header, rounded
- // up to make it aligned
- size_t currentPageOffset; // next offset in top of inUseList to allocate from
- tHeader *freeList; // list of popped memory
- tHeader *inUseList; // list of all memory currently being used
- tAllocStack mStack; // stack of where to allocate from, to partition pool
-
- int numCalls; // just an interesting statistic
- size_t totalBytes; // just an interesting statistic
-
-#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
- std::vector<std::vector<void *>> mStack;
-#endif
-
- TPoolAllocator &operator=(const TPoolAllocator &); // dont allow assignment operator
- TPoolAllocator(const TPoolAllocator &); // dont allow default copy constructor
- bool mLocked;
-};
-
-//
-// 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 TPoolAllocator *GetGlobalPoolAllocator();
-extern void SetGlobalPoolAllocator(TPoolAllocator *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 T>
-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 <class Other>
- struct rebind
- {
- typedef pool_allocator<Other> other;
- };
- pointer address(reference x) const { return &x; }
- const_pointer address(const_reference x) const { return &x; }
-
- pool_allocator() {}
-
- template <class Other>
- pool_allocator(const pool_allocator<Other> &p)
- {
- }
-
- template <class Other>
- pool_allocator<T> &operator=(const pool_allocator<Other> &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 reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
- }
- pointer allocate(size_type n, const void *)
- {
- return reinterpret_cast<pointer>(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<size_type>(-1) / sizeof(T); }
- size_type max_size(int size) const { return static_cast<size_type>(-1) / size; }
-
- TPoolAllocator &getAllocator() const { return *GetGlobalPoolAllocator(); }
-};
-
-#endif // COMPILER_TRANSLATOR_POOLALLOC_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Pragma.h b/src/3rdparty/angle/src/compiler/translator/Pragma.h
deleted file mode 100644
index 8c419fc17e..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Pragma.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright (c) 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.
- // Precision emulation is turned on by default, but has no effect unless
- // the extension is enabled.
- TPragma() : optimize(true), debug(false), debugShaderPrecision(true) {}
- TPragma(bool o, bool d) : optimize(o), debug(d), debugShaderPrecision(true) {}
-
- bool optimize;
- bool debug;
- bool debugShaderPrecision;
- STDGL stdgl;
-};
-
-#endif // COMPILER_TRANSLATOR_PRAGMA_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp b/src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp
deleted file mode 100644
index 6c9a02cd1c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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.
-
-#include "compiler/translator/PruneNoOps.h"
-
-#include "compiler/translator/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:
- static void apply(TIntermBlock *root);
-
- private:
- PruneNoOpsTraverser();
- bool visitDeclaration(Visit, TIntermDeclaration *node) override;
- bool visitBlock(Visit visit, TIntermBlock *node) override;
- bool visitLoop(Visit visit, TIntermLoop *loop) override;
-};
-
-void PruneNoOpsTraverser::apply(TIntermBlock *root)
-{
- PruneNoOpsTraverser prune;
- root->traverse(&prune);
- prune.updateTree();
-}
-
-PruneNoOpsTraverser::PruneNoOpsTraverser() : TIntermTraverser(true, false, false)
-{
-}
-
-bool PruneNoOpsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
-{
- TIntermSequence *sequence = node->getSequence();
- if (sequence->size() >= 1)
- {
- TIntermSymbol *sym = sequence->front()->getAsSymbolNode();
- // Prune declarations without a variable name, unless it's an interface block declaration.
- if (sym != nullptr && sym->getSymbol() == "" && !sym->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.push_back(
- NodeReplaceWithMultipleEntry(node, sym, emptyReplacement));
- }
- else if (sym->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 (sym->getType().getQualifier() != EvqGlobal &&
- sym->getType().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."
-
- if (mInGlobalScope)
- {
- sym->getTypePointer()->setQualifier(EvqGlobal);
- }
- else
- {
- sym->getTypePointer()->setQualifier(EvqTemporary);
- }
- }
- }
- }
- return false;
-}
-
-bool PruneNoOpsTraverser::visitBlock(Visit visit, TIntermBlock *node)
-{
- TIntermSequence *statements = node->getSequence();
-
- for (TIntermNode *statement : *statements)
- {
- if (IsNoOp(statement))
- {
- TIntermSequence emptyReplacement;
- mMultiReplacements.push_back(
- NodeReplaceWithMultipleEntry(node, statement, emptyReplacement));
- }
- }
-
- return true;
-}
-
-bool PruneNoOpsTraverser::visitLoop(Visit visit, TIntermLoop *loop)
-{
- 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;
-}
-
-} // namespace
-
-void PruneNoOps(TIntermBlock *root)
-{
- PruneNoOpsTraverser::apply(root);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/PruneNoOps.h b/src/3rdparty/angle/src/compiler/translator/PruneNoOps.h
deleted file mode 100644
index c421cecca4..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/PruneNoOps.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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.
-
-#ifndef COMPILER_TRANSLATOR_PRUNENOOPS_H_
-#define COMPILER_TRANSLATOR_PRUNENOOPS_H_
-
-namespace sh
-{
-class TIntermBlock;
-
-void PruneNoOps(TIntermBlock *root);
-}
-
-#endif // COMPILER_TRANSLATOR_PRUNENOOPS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp b/src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp
deleted file mode 100644
index f748175957..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp
+++ /dev/null
@@ -1,784 +0,0 @@
-//
-// Copyright (c) 2002-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/QualifierTypes.h"
-
-#include "compiler/translator/Diagnostics.h"
-
-#include <algorithm>
-
-namespace sh
-{
-
-namespace
-{
-
-// 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<const TStorageQualifierWrapper *>(qualifier);
- TQualifier q = storageQualifier->getQualifier();
- return IsScopeQualifier(q);
-}
-
-// Returns true if the invariant 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]);
-}
-
-// 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,
- std::string *errorMessage)
-{
- bool invariantFound = 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 = "The invariant qualifier specified multiple times.";
- return true;
- }
- invariantFound = true;
- break;
- }
- case QtPrecision:
- {
- if (precisionFound)
- {
- *errorMessage = "The precision qualifier specified multiple times.";
- return true;
- }
- precisionFound = true;
- break;
- }
- case QtLayout:
- {
- if (layoutFound && !areQualifierChecksRelaxed)
- {
- *errorMessage = "The layout qualifier specified multiple times.";
- 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 =
- "The layout qualifier and invariant qualifier cannot coexist in the same "
- "declaration according to the grammar.";
- return true;
- }
- layoutFound = true;
- const TLayoutQualifier &currentQualifier =
- static_cast<const TLayoutQualifierWrapper *>(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 = "The interpolation qualifier specified multiple times.";
- 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<const TStorageQualifierWrapper *>(qualifiers[i])->getQualifier();
- if (currentQualifier == EvqVertexOut || currentQualifier == EvqFragmentOut)
- {
- isOut = true;
- }
- for (size_t j = 1; j < i; ++j)
- {
- if (qualifiers[j]->getType() == QtStorage)
- {
- const TStorageQualifierWrapper *previousQualifierWrapper =
- static_cast<const TStorageQualifierWrapper *>(qualifiers[j]);
- TQualifier previousQualifier = previousQualifierWrapper->getQualifier();
- if (currentQualifier == previousQualifier)
- {
- *errorMessage = previousQualifierWrapper->getQualifierString().c_str();
- *errorMessage += " specified multiple times";
- 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<const TMemoryQualifierWrapper *>(qualifiers[i])->getQualifier();
- for (size_t j = 1; j < i; ++j)
- {
- if (qualifiers[j]->getType() == QtMemory)
- {
- const TMemoryQualifierWrapper *previousQualifierWrapper =
- static_cast<const TMemoryQualifierWrapper *>(qualifiers[j]);
- TQualifier previousQualifier = previousQualifierWrapper->getQualifier();
- if (currentQualifier == previousQualifier)
- {
- *errorMessage = previousQualifierWrapper->getQualifierString().c_str();
- *errorMessage += " specified multiple times";
- 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 = "Output layout location specified multiple times.";
- 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.
-bool AreQualifiersInOrder(const TTypeQualifierBuilder::QualifierSequence &qualifiers,
- std::string *errorMessage)
-{
- 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 = "The invariant qualifier has to be first in the expression.";
- return false;
- }
- break;
- case QtInterpolation:
- if (foundStorage)
- {
- *errorMessage = "Storage qualifiers have to be after interpolation qualifiers.";
- return false;
- }
- else if (foundPrecision)
- {
- *errorMessage =
- "Precision qualifiers have to be after interpolation qualifiers.";
- return false;
- }
- foundInterpolation = true;
- break;
- case QtLayout:
- if (foundStorage)
- {
- *errorMessage = "Storage qualifiers have to be after layout qualifiers.";
- return false;
- }
- else if (foundPrecision)
- {
- *errorMessage = "Precision qualifiers have to be after layout qualifiers.";
- return false;
- }
- break;
- case QtStorage:
- if (foundPrecision)
- {
- *errorMessage = "Precision qualifiers have to be after storage qualifiers.";
- return false;
- }
- foundStorage = true;
- break;
- case QtMemory:
- if (foundPrecision)
- {
- *errorMessage = "Precision qualifiers have to be after memory qualifiers.";
- return false;
- }
- break;
- case QtPrecision:
- foundPrecision = true;
- 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:
- *joinedQualifier = EvqSmoothOut;
- break;
- case EvqFragmentIn:
- case EvqGeometryIn:
- *joinedQualifier = EvqSmoothIn;
- break;
- default:
- return false;
- }
- break;
- }
- case EvqFlat:
- {
- switch (storageQualifier)
- {
- case EvqCentroid:
- *joinedQualifier = EvqFlat;
- break;
- case EvqVertexOut:
- case EvqGeometryOut:
- *joinedQualifier = EvqFlatOut;
- break;
- case EvqFragmentIn:
- case EvqGeometryIn:
- *joinedQualifier = EvqFlatIn;
- break;
- default:
- return false;
- }
- break;
- }
- case EvqCentroid:
- {
- switch (storageQualifier)
- {
- case EvqVertexOut:
- case EvqGeometryOut:
- *joinedQualifier = EvqCentroidOut;
- break;
- case EvqFragmentIn:
- case EvqGeometryIn:
- *joinedQualifier = EvqCentroidIn;
- 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 EvqIn:
- *joinedQualifier = EvqConstReadOnly;
- 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<const TStorageQualifierWrapper *>(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 QtInterpolation:
- {
- switch (typeQualifier.qualifier)
- {
- case EvqGlobal:
- isQualifierValid = true;
- typeQualifier.qualifier =
- static_cast<const TInterpolationQualifierWrapper *>(qualifier)
- ->getQualifier();
- break;
- default:
- isQualifierValid = false;
- }
- break;
- }
- case QtLayout:
- {
- const TLayoutQualifierWrapper *layoutQualifierWrapper =
- static_cast<const TLayoutQualifierWrapper *>(qualifier);
- isQualifierValid = true;
- typeQualifier.layoutQualifier = sh::JoinLayoutQualifiers(
- typeQualifier.layoutQualifier, layoutQualifierWrapper->getQualifier(),
- layoutQualifierWrapper->getLine(), diagnostics);
- break;
- }
- case QtStorage:
- isQualifierValid = JoinVariableStorageQualifier(
- &typeQualifier.qualifier,
- static_cast<const TStorageQualifierWrapper *>(qualifier)->getQualifier());
- break;
- case QtPrecision:
- isQualifierValid = true;
- typeQualifier.precision =
- static_cast<const TPrecisionQualifierWrapper *>(qualifier)->getQualifier();
- ASSERT(typeQualifier.precision != EbpUndefined);
- break;
- case QtMemory:
- isQualifierValid = JoinMemoryQualifier(
- &typeQualifier.memoryQualifier,
- static_cast<const TMemoryQualifierWrapper *>(qualifier)->getQualifier());
- break;
- default:
- UNREACHABLE();
- }
- if (!isQualifierValid)
- {
- const TString &qualifierString = qualifier->getQualifierString();
- diagnostics->error(qualifier->getLine(), "invalid qualifier combination",
- qualifierString.c_str());
- break;
- }
- }
- return typeQualifier;
-}
-
-TTypeQualifier GetParameterTypeQualifierFromSortedSequence(
- 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<const TMemoryQualifierWrapper *>(qualifier)->getQualifier());
- break;
- case QtStorage:
- isQualifierValid = JoinParameterStorageQualifier(
- &typeQualifier.qualifier,
- static_cast<const TStorageQualifierWrapper *>(qualifier)->getQualifier());
- break;
- case QtPrecision:
- isQualifierValid = true;
- typeQualifier.precision =
- static_cast<const TPrecisionQualifierWrapper *>(qualifier)->getQualifier();
- ASSERT(typeQualifier.precision != EbpUndefined);
- break;
- default:
- UNREACHABLE();
- }
- if (!isQualifierValid)
- {
- const TString &qualifierString = qualifier->getQualifierString();
- diagnostics->error(qualifier->getLine(), "invalid parameter qualifier",
- qualifierString.c_str());
- break;
- }
- }
-
- switch (typeQualifier.qualifier)
- {
- case EvqIn:
- case EvqConstReadOnly: // const in
- case EvqOut:
- case EvqInOut:
- break;
- case EvqConst:
- typeQualifier.qualifier = EvqConstReadOnly;
- break;
- case EvqTemporary:
- // no qualifier has been specified, set it to EvqIn which is the default
- typeQualifier.qualifier = EvqIn;
- 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.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;
- }
-
- 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;
- }
-
- return joinedQualifier;
-}
-
-unsigned int TInvariantQualifierWrapper::getRank() const
-{
- return 0u;
-}
-
-unsigned int TInterpolationQualifierWrapper::getRank() const
-{
- return 1u;
-}
-
-unsigned int TLayoutQualifierWrapper::getRank() const
-{
- return 2u;
-}
-
-unsigned int TStorageQualifierWrapper::getRank() const
-{
- // Force the 'centroid' auxilary storage qualifier to be always first among all storage
- // qualifiers.
- if (mStorageQualifier == EvqCentroid)
- {
- return 3u;
- }
- else
- {
- return 4u;
- }
-}
-
-unsigned int TMemoryQualifierWrapper::getRank() const
-{
- return 4u;
-}
-
-unsigned int TPrecisionQualifierWrapper::getRank() const
-{
- return 5u;
-}
-
-TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc)
- : layoutQualifier(TLayoutQualifier::Create()),
- memoryQualifier(TMemoryQualifier::Create()),
- precision(EbpUndefined),
- qualifier(scope),
- invariant(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);
- std::string errorMessage;
- if (HasRepeatingQualifiers(mQualifiers, areQualifierChecksRelaxed, &errorMessage))
- {
- diagnostics->error(mQualifiers[0]->getLine(), errorMessage.c_str(), "qualifier sequence");
- return false;
- }
-
- if (!areQualifierChecksRelaxed && !AreQualifiersInOrder(mQualifiers, &errorMessage))
- {
- diagnostics->error(mQualifiers[0]->getLine(), errorMessage.c_str(), "qualifier sequence");
- return false;
- }
-
- return true;
-}
-
-TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier(TDiagnostics *diagnostics) const
-{
- ASSERT(IsInvariantCorrect(mQualifiers));
- ASSERT(static_cast<const TStorageQualifierWrapper *>(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(sortedQualifierSequence, diagnostics);
- }
- return GetParameterTypeQualifierFromSortedSequence(mQualifiers, diagnostics);
-}
-
-TTypeQualifier TTypeQualifierBuilder::getVariableTypeQualifier(TDiagnostics *diagnostics) const
-{
- ASSERT(IsInvariantCorrect(mQualifiers));
-
- if (!checkSequenceIsValid(diagnostics))
- {
- return TTypeQualifier(
- static_cast<const TStorageQualifierWrapper *>(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/src/3rdparty/angle/src/compiler/translator/QualifierTypes.h b/src/3rdparty/angle/src/compiler/translator/QualifierTypes.h
deleted file mode 100644
index 10bdeed89d..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/QualifierTypes.h
+++ /dev/null
@@ -1,191 +0,0 @@
-//
-// Copyright (c) 2002-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_QUALIFIER_TYPES_H_
-#define COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_
-
-#include "common/angleutils.h"
-#include "compiler/translator/BaseTypes.h"
-#include "compiler/translator/Types.h"
-
-namespace sh
-{
-class TDiagnostics;
-
-TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
- TLayoutQualifier rightQualifier,
- const TSourceLoc &rightQualifierLocation,
- TDiagnostics *diagnostics);
-
-enum TQualifierType
-{
- QtInvariant,
- 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 TString 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() {}
-
- TQualifierType getType() const { return QtInvariant; }
- TString getQualifierString() const { return "invariant"; }
- unsigned int getRank() const;
-};
-
-class TInterpolationQualifierWrapper final : public TQualifierWrapperBase
-{
- public:
- TInterpolationQualifierWrapper(TQualifier interpolationQualifier, const TSourceLoc &line)
- : TQualifierWrapperBase(line), mInterpolationQualifier(interpolationQualifier)
- {
- }
- ~TInterpolationQualifierWrapper() {}
-
- TQualifierType getType() const { return QtInterpolation; }
- TString getQualifierString() const { return sh::getQualifierString(mInterpolationQualifier); }
- TQualifier getQualifier() const { return mInterpolationQualifier; }
- unsigned int getRank() const;
-
- private:
- TQualifier mInterpolationQualifier;
-};
-
-class TLayoutQualifierWrapper final : public TQualifierWrapperBase
-{
- public:
- TLayoutQualifierWrapper(TLayoutQualifier layoutQualifier, const TSourceLoc &line)
- : TQualifierWrapperBase(line), mLayoutQualifier(layoutQualifier)
- {
- }
- ~TLayoutQualifierWrapper() {}
-
- TQualifierType getType() const { return QtLayout; }
- TString getQualifierString() const { return "layout"; }
- const TLayoutQualifier &getQualifier() const { return mLayoutQualifier; }
- unsigned int getRank() const;
-
- private:
- TLayoutQualifier mLayoutQualifier;
-};
-
-class TStorageQualifierWrapper final : public TQualifierWrapperBase
-{
- public:
- TStorageQualifierWrapper(TQualifier storageQualifier, const TSourceLoc &line)
- : TQualifierWrapperBase(line), mStorageQualifier(storageQualifier)
- {
- }
- ~TStorageQualifierWrapper() {}
-
- TQualifierType getType() const { return QtStorage; }
- TString getQualifierString() const { return sh::getQualifierString(mStorageQualifier); }
- TQualifier getQualifier() const { return mStorageQualifier; }
- unsigned int getRank() const;
-
- private:
- TQualifier mStorageQualifier;
-};
-
-class TPrecisionQualifierWrapper final : public TQualifierWrapperBase
-{
- public:
- TPrecisionQualifierWrapper(TPrecision precisionQualifier, const TSourceLoc &line)
- : TQualifierWrapperBase(line), mPrecisionQualifier(precisionQualifier)
- {
- }
- ~TPrecisionQualifierWrapper() {}
-
- TQualifierType getType() const { return QtPrecision; }
- TString getQualifierString() const { return sh::getPrecisionString(mPrecisionQualifier); }
- TPrecision getQualifier() const { return mPrecisionQualifier; }
- unsigned int getRank() const;
-
- private:
- TPrecision mPrecisionQualifier;
-};
-
-class TMemoryQualifierWrapper final : public TQualifierWrapperBase
-{
- public:
- TMemoryQualifierWrapper(TQualifier memoryQualifier, const TSourceLoc &line)
- : TQualifierWrapperBase(line), mMemoryQualifier(memoryQualifier)
- {
- }
- ~TMemoryQualifierWrapper() {}
-
- TQualifierType getType() const { return QtMemory; }
- TString getQualifierString() const { return sh::getQualifierString(mMemoryQualifier); }
- TQualifier getQualifier() const { return mMemoryQualifier; }
- unsigned int getRank() const;
-
- 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;
- 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<const TQualifierWrapperBase *>;
-
- 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(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/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp b/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp
deleted file mode 100644
index 5233a29f19..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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/RecordConstantPrecision.h"
-
-#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class RecordConstantPrecisionTraverser : public TIntermTraverser
-{
- public:
- RecordConstantPrecisionTraverser(TSymbolTable *symbolTable);
-
- void visitConstantUnion(TIntermConstantUnion *node) override;
-
- void nextIteration();
-
- bool foundHigherPrecisionConstant() const { return mFoundHigherPrecisionConstant; }
- protected:
- bool operandAffectsParentOperationPrecision(TIntermTyped *operand);
-
- bool mFoundHigherPrecisionConstant;
-};
-
-RecordConstantPrecisionTraverser::RecordConstantPrecisionTraverser(TSymbolTable *symbolTable)
- : TIntermTraverser(true, false, true, symbolTable), mFoundHigherPrecisionConstant(false)
-{
-}
-
-bool RecordConstantPrecisionTraverser::operandAffectsParentOperationPrecision(TIntermTyped *operand)
-{
- if (getParentNode()->getAsCaseNode() || getParentNode()->getAsBlock())
- {
- 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:
- break;
- }
-
- TIntermTyped *otherOperand = parentAsBinary->getRight();
- if (otherOperand == operand)
- {
- otherOperand = parentAsBinary->getLeft();
- }
- // If the precision of the other child is at least as high as the precision of the constant,
- // the precision of the constant has no effect.
- if (otherOperand->getAsConstantUnion() == nullptr &&
- otherOperand->getPrecision() >= operand->getPrecision())
- {
- return false;
- }
- }
-
- TIntermAggregate *parentAsAggregate = getParentNode()->getAsAggregate();
- if (parentAsAggregate != nullptr)
- {
- if (!parentAsAggregate->gotPrecisionFromChildren())
- {
- // This can be either:
- // * a call to an user-defined function
- // * a call to a texture function
- // * some other kind of aggregate
- // In any of these cases the constant precision has no effect.
- return false;
- }
- if (parentAsAggregate->isConstructor() && parentAsAggregate->getBasicType() == EbtBool)
- {
- return false;
- }
- // If the precision of operands does affect the result, but the precision of any of the
- // other children has a precision that's at least as high as the precision of the constant,
- // the precision of the constant has no effect.
- TIntermSequence *parameters = parentAsAggregate->getSequence();
- for (TIntermNode *parameter : *parameters)
- {
- const TIntermTyped *typedParameter = parameter->getAsTyped();
- if (parameter != operand && typedParameter != nullptr &&
- parameter->getAsConstantUnion() == nullptr &&
- typedParameter->getPrecision() >= operand->getPrecision())
- {
- return false;
- }
- }
- }
- return true;
-}
-
-void RecordConstantPrecisionTraverser::visitConstantUnion(TIntermConstantUnion *node)
-{
- if (mFoundHigherPrecisionConstant)
- return;
-
- // 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.
- TIntermSequence insertions;
- insertions.push_back(createTempInitDeclaration(node, EvqConst));
- insertStatementsInParentBlock(insertions);
- queueReplacement(createTempSymbol(node->getType()), OriginalNode::IS_DROPPED);
- mFoundHigherPrecisionConstant = true;
-}
-
-void RecordConstantPrecisionTraverser::nextIteration()
-{
- nextTemporaryId();
- mFoundHigherPrecisionConstant = false;
-}
-
-} // namespace
-
-void RecordConstantPrecision(TIntermNode *root, TSymbolTable *symbolTable)
-{
- RecordConstantPrecisionTraverser traverser(symbolTable);
- // Iterate as necessary, and reset the traverser between iterations.
- do
- {
- traverser.nextIteration();
- root->traverse(&traverser);
- if (traverser.foundHigherPrecisionConstant())
- traverser.updateTree();
- } while (traverser.foundHigherPrecisionConstant());
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h b/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h
deleted file mode 100644
index f86c2a8693..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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_RECORDCONSTANTPRECISION_H_
-#define COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_
-
-namespace sh
-{
-class TIntermNode;
-class TSymbolTable;
-
-void RecordConstantPrecision(TIntermNode *root, TSymbolTable *symbolTable);
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp
deleted file mode 100644
index 55fb124a42..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// Copyright (c) 2002-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 "common/debug.h"
-#include "compiler/translator/RegenerateStructNames.h"
-
-namespace sh
-{
-
-void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol)
-{
- ASSERT(symbol);
- TType *type = symbol->getTypePointer();
- ASSERT(type);
- TStructure *userType = type->getStruct();
- if (!userType)
- return;
-
- if (mSymbolTable->findBuiltIn(userType->name(), mShaderVersion))
- {
- // Built-in struct, do not touch it.
- return;
- }
-
- int uniqueId = userType->uniqueId();
-
- 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}.
- const char kPrefix[] = "_webgl_struct_";
- if (userType->name().find(kPrefix) == 0)
- {
- // The name has already been regenerated.
- return;
- }
- std::string id = Str(uniqueId);
- TString tmp = kPrefix + TString(id.c_str());
- tmp += "_" + userType->name();
- userType->setName(tmp);
-}
-
-bool RegenerateStructNames::visitBlock(Visit, TIntermBlock *block)
-{
- ++mScopeDepth;
- TIntermSequence &sequence = *(block->getSequence());
- for (TIntermNode *node : sequence)
- {
- node->traverse(this);
- }
- --mScopeDepth;
- return false;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h
deleted file mode 100644
index 293720b6a4..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// Copyright (c) 2002-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_REGENERATESTRUCTNAMES_H_
-#define COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_
-
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.h"
-
-#include <set>
-
-namespace sh
-{
-
-class RegenerateStructNames : public TIntermTraverser
-{
- public:
- RegenerateStructNames(TSymbolTable *symbolTable, int shaderVersion)
- : TIntermTraverser(true, false, false, symbolTable),
- mShaderVersion(shaderVersion),
- mScopeDepth(0)
- {
- }
-
- protected:
- void visitSymbol(TIntermSymbol *) override;
- bool visitBlock(Visit, TIntermBlock *block) override;
-
- private:
- int mShaderVersion;
-
- // Indicating the depth of the current scope.
- // The global scope is 1.
- int mScopeDepth;
-
- // If a struct's declared globally, push its ID in this set.
- std::set<int> mDeclaredGlobalStructs;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp
deleted file mode 100644
index e9e6a17013..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-//
-// Copyright (c) 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 = <constant array length>;
-// func();
-// int j = <constant array length>;
-//
-// 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/RemoveArrayLengthMethod.h"
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/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:
- 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;
- if (!node->getOperand()->hasSideEffects())
- {
- queueReplacement(node->fold(nullptr), OriginalNode::IS_DROPPED);
- return false;
- }
- insertStatementInParentBlock(node->getOperand()->deepCopy());
- TConstantUnion *constArray = new TConstantUnion[1];
- constArray->setIConst(node->getOperand()->getOutermostArraySize());
- queueReplacement(new TIntermConstantUnion(constArray, node->getType()),
- OriginalNode::IS_DROPPED);
- return false;
- }
- return true;
-}
-
-} // anonymous namespace
-
-void RemoveArrayLengthMethod(TIntermBlock *root)
-{
- RemoveArrayLengthTraverser traverser;
- do
- {
- traverser.nextIteration();
- root->traverse(&traverser);
- if (traverser.foundArrayLength())
- traverser.updateTree();
- } while (traverser.foundArrayLength());
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h b/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h
deleted file mode 100644
index 3b2c6df824..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Copyright (c) 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 = <constant array length>;
-// func();
-// int j = <constant array length>;
-//
-// 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.
-
-namespace sh
-{
-
-class TIntermBlock;
-
-void RemoveArrayLengthMethod(TIntermBlock *root);
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp
deleted file mode 100644
index 7766c1abc6..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp
+++ /dev/null
@@ -1,550 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// RemoveDynamicIndexing is an AST traverser to remove dynamic indexing of vectors and matrices,
-// replacing them with calls to functions that choose which component to return or write.
-//
-
-#include "compiler/translator/RemoveDynamicIndexing.h"
-
-#include "compiler/translator/Diagnostics.h"
-#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermNodePatternMatcher.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-namespace
-{
-
-std::string GetIndexFunctionName(const TType &type, bool write)
-{
- TInfoSinkBase nameSink;
- nameSink << "dyn_index_";
- if (write)
- {
- nameSink << "write_";
- }
- if (type.isMatrix())
- {
- nameSink << "mat" << type.getCols() << "x" << 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 << type.getNominalSize();
- }
- return nameSink.str();
-}
-
-TIntermSymbol *CreateBaseSymbol(const TType &type, TQualifier qualifier, TSymbolTable *symbolTable)
-{
- TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), "base", type);
- symbol->setInternal(true);
- symbol->getTypePointer()->setQualifier(qualifier);
- return symbol;
-}
-
-TIntermSymbol *CreateIndexSymbol(TSymbolTable *symbolTable)
-{
- TIntermSymbol *symbol =
- new TIntermSymbol(symbolTable->nextUniqueId(), "index", TType(EbtInt, EbpHigh));
- symbol->setInternal(true);
- symbol->getTypePointer()->setQualifier(EvqIn);
- return symbol;
-}
-
-TIntermSymbol *CreateValueSymbol(const TType &type, TSymbolTable *symbolTable)
-{
- TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), "value", type);
- symbol->setInternal(true);
- symbol->getTypePointer()->setQualifier(EvqIn);
- return symbol;
-}
-
-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 = new TIntermSequence();
- arguments->push_back(node);
- return TIntermAggregate::CreateConstructor(TType(EbtInt), arguments);
-}
-
-TType GetFieldType(const TType &indexedType)
-{
- if (indexedType.isMatrix())
- {
- TType fieldType = TType(indexedType.getBasicType(), indexedType.getPrecision());
- fieldType.setPrimarySize(static_cast<unsigned char>(indexedType.getRows()));
- return fieldType;
- }
- else
- {
- return TType(indexedType.getBasicType(), indexedType.getPrecision());
- }
-}
-
-// 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(TType type,
- bool write,
- const TSymbolUniqueId &functionId,
- TSymbolTable *symbolTable)
-{
- ASSERT(!type.isArray());
- // 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.
- type.setPrecision(EbpHigh);
-
- TType fieldType = GetFieldType(type);
- int numCases = 0;
- if (type.isMatrix())
- {
- numCases = type.getCols();
- }
- else
- {
- numCases = type.getNominalSize();
- }
-
- TType returnType(EbtVoid);
- if (!write)
- {
- returnType = fieldType;
- }
-
- std::string functionName = GetIndexFunctionName(type, write);
- TIntermFunctionPrototype *prototypeNode =
- CreateInternalFunctionPrototypeNode(returnType, functionName.c_str(), functionId);
-
- TQualifier baseQualifier = EvqInOut;
- if (!write)
- baseQualifier = EvqIn;
- TIntermSymbol *baseParam = CreateBaseSymbol(type, baseQualifier, symbolTable);
- prototypeNode->getSequence()->push_back(baseParam);
- TIntermSymbol *indexParam = CreateIndexSymbol(symbolTable);
- prototypeNode->getSequence()->push_back(indexParam);
- TIntermSymbol *valueParam = nullptr;
- if (write)
- {
- valueParam = CreateValueSymbol(fieldType, symbolTable);
- prototypeNode->getSequence()->push_back(valueParam);
- }
-
- TIntermBlock *statementList = new TIntermBlock();
- for (int 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));
- cond->setType(TType(EbtBool, EbpUndefined));
-
- // 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(TSymbolTable *symbolTable,
- int shaderVersion,
- 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<TType, TSymbolUniqueId *> mIndexedVecAndMatrixTypes;
- std::map<TType, TSymbolUniqueId *> 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;
-
- PerformanceDiagnostics *mPerfDiagnostics;
-};
-
-RemoveDynamicIndexingTraverser::RemoveDynamicIndexingTraverser(
- TSymbolTable *symbolTable,
- int shaderVersion,
- PerformanceDiagnostics *perfDiagnostics)
- : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion),
- mUsedTreeInsertion(false),
- mRemoveIndexSideEffectsInSubtree(false),
- 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,
- const TSymbolUniqueId &functionId)
-{
- ASSERT(node->getOp() == EOpIndexIndirect);
- TIntermSequence *arguments = new TIntermSequence();
- arguments->push_back(node->getLeft());
- arguments->push_back(index);
-
- TType fieldType = GetFieldType(node->getLeft()->getType());
- std::string functionName = GetIndexFunctionName(node->getLeft()->getType(), false);
- TIntermAggregate *indexingCall =
- CreateInternalFunctionCallNode(fieldType, functionName.c_str(), functionId, arguments);
- indexingCall->setLine(node->getLine());
- indexingCall->getFunctionSymbolInfo()->setKnownToNotHaveSideEffects(true);
- return indexingCall;
-}
-
-TIntermAggregate *CreateIndexedWriteFunctionCall(TIntermBinary *node,
- TIntermTyped *index,
- TIntermTyped *writtenValue,
- const TSymbolUniqueId &functionId)
-{
- ASSERT(node->getOp() == EOpIndexIndirect);
- TIntermSequence *arguments = new TIntermSequence();
- // 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(index->deepCopy());
- arguments->push_back(writtenValue);
-
- std::string functionName = GetIndexFunctionName(node->getLeft()->getType(), true);
- TIntermAggregate *indexedWriteCall =
- CreateInternalFunctionCallNode(TType(EbtVoid), functionName.c_str(), functionId, 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.
-
- // Init the temp variable holding the index
- TIntermDeclaration *initIndex = createTempInitDeclaration(node->getRight());
- insertStatementInParentBlock(initIndex);
- mUsedTreeInsertion = true;
-
- // Replace the index with the temp variable
- TIntermSymbol *tempIndex = createTempSymbol(node->getRight()->getType());
- queueReplacementWithParent(node, node->getRight(), tempIndex, OriginalNode::IS_DROPPED);
- }
- else if (IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(node))
- {
- 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();
- TSymbolUniqueId *indexingFunctionId = new TSymbolUniqueId(mSymbolTable);
- if (mIndexedVecAndMatrixTypes.find(type) == mIndexedVecAndMatrixTypes.end())
- {
- mIndexedVecAndMatrixTypes[type] = indexingFunctionId;
- }
- else
- {
- indexingFunctionId = 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 &&
- IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(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
-
- TSymbolUniqueId *indexedWriteFunctionId = new TSymbolUniqueId(mSymbolTable);
- if (mWrittenVecAndMatrixTypes.find(type) == mWrittenVecAndMatrixTypes.end())
- {
- mWrittenVecAndMatrixTypes[type] = indexedWriteFunctionId;
- }
- else
- {
- indexedWriteFunctionId = mWrittenVecAndMatrixTypes[type];
- }
- TType fieldType = GetFieldType(type);
-
- TIntermSequence insertionsBefore;
- TIntermSequence insertionsAfter;
-
- // Store the index in a temporary signed int variable.
- TIntermTyped *indexInitializer = EnsureSignedInt(node->getRight());
- TIntermDeclaration *initIndex = createTempInitDeclaration(indexInitializer);
- initIndex->setLine(node->getLine());
- insertionsBefore.push_back(initIndex);
-
- // Create a node for referring to the index after the nextTemporaryId() call
- // below.
- TIntermSymbol *tempIndex = createTempSymbol(indexInitializer->getType());
-
- TIntermAggregate *indexingCall =
- CreateIndexFunctionCall(node, tempIndex, *indexingFunctionId);
-
- nextTemporaryId(); // From now on, creating temporary symbols that refer to the
- // field value.
- insertionsBefore.push_back(createTempInitDeclaration(indexingCall));
-
- TIntermAggregate *indexedWriteCall = CreateIndexedWriteFunctionCall(
- node, tempIndex, createTempSymbol(fieldType), *indexedWriteFunctionId);
- insertionsAfter.push_back(indexedWriteCall);
- insertStatementsInParentBlock(insertionsBefore, insertionsAfter);
- queueReplacement(createTempSymbol(fieldType), 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()), *indexingFunctionId);
- queueReplacement(indexingCall, OriginalNode::IS_DROPPED);
- }
- }
- }
- return !mUsedTreeInsertion;
-}
-
-void RemoveDynamicIndexingTraverser::nextIteration()
-{
- mUsedTreeInsertion = false;
- mRemoveIndexSideEffectsInSubtree = false;
- nextTemporaryId();
-}
-
-} // namespace
-
-void RemoveDynamicIndexing(TIntermNode *root,
- TSymbolTable *symbolTable,
- int shaderVersion,
- PerformanceDiagnostics *perfDiagnostics)
-{
- RemoveDynamicIndexingTraverser traverser(symbolTable, shaderVersion, perfDiagnostics);
- do
- {
- traverser.nextIteration();
- root->traverse(&traverser);
- traverser.updateTree();
- } 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);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h b/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h
deleted file mode 100644
index 543cf569a6..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// RemoveDynamicIndexing is an AST traverser to remove dynamic indexing of vectors and matrices,
-// replacing them with calls to functions that choose which component to return or write.
-//
-
-#ifndef COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_
-#define COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_
-
-namespace sh
-{
-
-class TIntermNode;
-class TSymbolTable;
-class PerformanceDiagnostics;
-
-void RemoveDynamicIndexing(TIntermNode *root,
- TSymbolTable *symbolTable,
- int shaderVersion,
- PerformanceDiagnostics *perfDiagnostics);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp
deleted file mode 100644
index b39c912e9c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (c) 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.
-//
-// RemoveEmptySwitchStatements.cpp: Remove switch statements that have an empty statement list.
-
-#include "compiler/translator/RemoveEmptySwitchStatements.h"
-
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class RemoveEmptySwitchStatementsTraverser : public TIntermTraverser
-{
- public:
- RemoveEmptySwitchStatementsTraverser() : TIntermTraverser(true, false, false) {}
-
- bool visitSwitch(Visit visit, TIntermSwitch *node);
-};
-
-bool RemoveEmptySwitchStatementsTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
-{
- if (node->getStatementList()->getSequence()->empty())
- {
- // Just output the init statement.
- if (node->getInit()->hasSideEffects())
- {
- queueReplacement(node->getInit(), OriginalNode::IS_DROPPED);
- }
- else
- {
- TIntermSequence emptyReplacement;
- ASSERT(getParentNode()->getAsBlock());
- mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(),
- node, emptyReplacement));
- }
- return false; // Nothing inside the child nodes to traverse.
- }
- return true;
-}
-
-} // anonymous namespace
-
-void RemoveEmptySwitchStatements(TIntermBlock *root)
-{
- RemoveEmptySwitchStatementsTraverser traverser;
- root->traverse(&traverser);
- traverser.updateTree();
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h b/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h
deleted file mode 100644
index 1018a50d82..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// Copyright (c) 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.
-//
-// RemoveEmptySwitchStatements.h: Remove switch statements that have an empty statement list.
-
-#ifndef COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_
-#define COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_
-
-namespace sh
-{
-class TIntermBlock;
-
-void RemoveEmptySwitchStatements(TIntermBlock *root);
-}
-
-#endif // COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp
deleted file mode 100644
index 4b533dc7b5..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (c) 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/RemoveInvariantDeclaration.h"
-
-#include "compiler/translator/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 visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override
- {
- TIntermSequence emptyReplacement;
- mMultiReplacements.push_back(
- NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, emptyReplacement));
- return false;
- }
-};
-
-} // anonymous namespace
-
-void RemoveInvariantDeclaration(TIntermNode *root)
-{
- RemoveInvariantDeclarationTraverser traverser;
- root->traverse(&traverser);
- traverser.updateTree();
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h b/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h
deleted file mode 100644
index cf9d4aa4c2..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// Copyright (c) 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_REMOVEINVARIANTDECLARATION_H_
-#define COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_
-
-class TIntermNode;
-namespace sh
-{
-
-void RemoveInvariantDeclaration(TIntermNode *root);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp
deleted file mode 100644
index b86d64d7a3..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-//
-// Copyright (c) 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.
-//
-// RemoveNoOpCasesFromEndOfSwitchStatements.cpp: Clean up cases from the end of a switch statement
-// that only contain no-ops.
-
-#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h"
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-namespace
-{
-
-bool AreEmptyBlocks(TIntermSequence *statements, size_t i);
-
-bool IsEmptyBlock(TIntermNode *node)
-{
- TIntermBlock *asBlock = node->getAsBlock();
- if (asBlock)
- {
- if (asBlock->getSequence()->empty())
- {
- return true;
- }
- return AreEmptyBlocks(asBlock->getSequence(), 0u);
- }
- // 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" starting from index i consist only of empty blocks
-// and no-op statements. Returns true also if there are no statements.
-bool AreEmptyBlocks(TIntermSequence *statements, size_t i)
-{
- for (; i < statements->size(); ++i)
- {
- if (!IsEmptyBlock(statements->at(i)))
- {
- return false;
- }
- }
- return true;
-}
-
-void RemoveNoOpCasesFromEndOfStatementList(TIntermBlock *statementList, TSymbolTable *symbolTable)
-{
- TIntermSequence *statements = statementList->getSequence();
-
- bool foundDeadCase = false;
- do
- {
- if (statements->empty())
- {
- return;
- }
-
- // Find the last case label.
- size_t i = statements->size();
- while (i > 0u && !(*statements)[i - 1]->getAsCaseNode())
- {
- --i;
- }
- // Now i is the index of the first statement following the last label inside the switch
- // statement.
- ASSERT(i > 0u);
-
- foundDeadCase = AreEmptyBlocks(statements, i);
- if (foundDeadCase)
- {
- statements->erase(statements->begin() + (i - 1u), statements->end());
- }
- } while (foundDeadCase);
-}
-
-class RemoveNoOpCasesFromEndOfSwitchTraverser : public TIntermTraverser
-{
- public:
- RemoveNoOpCasesFromEndOfSwitchTraverser(TSymbolTable *symbolTable)
- : TIntermTraverser(true, false, false, symbolTable)
- {
- }
-
- bool visitSwitch(Visit visit, TIntermSwitch *node) override;
-};
-
-bool RemoveNoOpCasesFromEndOfSwitchTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
-{
- // Here we may mutate the statement list, but it's safe since traversal has not yet reached
- // there.
- RemoveNoOpCasesFromEndOfStatementList(node->getStatementList(), mSymbolTable);
- // Handle also nested switch statements.
- return true;
-}
-
-} // anonymous namespace
-
-void RemoveNoOpCasesFromEndOfSwitchStatements(TIntermBlock *root, TSymbolTable *symbolTable)
-{
- RemoveNoOpCasesFromEndOfSwitchTraverser traverser(symbolTable);
- root->traverse(&traverser);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h b/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h
deleted file mode 100644
index ebd75eb774..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// Copyright (c) 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.
-//
-// RemoveNoOpCasesFromEndOfSwitchStatements.h: Clean up cases from the end of a switch statement
-// that only contain no-ops.
-
-#ifndef COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_
-#define COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_
-
-namespace sh
-{
-class TIntermBlock;
-class TSymbolTable;
-
-void RemoveNoOpCasesFromEndOfSwitchStatements(TIntermBlock *root, TSymbolTable *symbolTable);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RemovePow.cpp b/src/3rdparty/angle/src/compiler/translator/RemovePow.cpp
deleted file mode 100644
index b2cdac55f0..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemovePow.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// RemovePow is an AST traverser to convert pow(x, y) built-in calls where y is a
-// constant to exp2(y * log2(x)). This works around an issue in NVIDIA 311 series
-// OpenGL drivers.
-//
-
-#include "compiler/translator/RemovePow.h"
-
-#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-bool IsProblematicPow(TIntermTyped *node)
-{
- TIntermAggregate *agg = node->getAsAggregate();
- if (agg != nullptr && agg->getOp() == EOpPow)
- {
- ASSERT(agg->getSequence()->size() == 2);
- return agg->getSequence()->at(1)->getAsConstantUnion() != nullptr;
- }
- return false;
-}
-
-// Traverser that converts all pow operations simultaneously.
-class RemovePowTraverser : public TIntermTraverser
-{
- public:
- RemovePowTraverser();
-
- bool visitAggregate(Visit visit, TIntermAggregate *node) override;
-
- void nextIteration() { mNeedAnotherIteration = false; }
- bool needAnotherIteration() const { return mNeedAnotherIteration; }
-
- protected:
- bool mNeedAnotherIteration;
-};
-
-RemovePowTraverser::RemovePowTraverser()
- : TIntermTraverser(true, false, false), mNeedAnotherIteration(false)
-{
-}
-
-bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- if (IsProblematicPow(node))
- {
- TIntermTyped *x = node->getSequence()->at(0)->getAsTyped();
- TIntermTyped *y = node->getSequence()->at(1)->getAsTyped();
-
- TIntermUnary *log = new TIntermUnary(EOpLog2, x);
- log->setLine(node->getLine());
-
- TOperator op = TIntermBinary::GetMulOpBasedOnOperands(y->getType(), log->getType());
- TIntermBinary *mul = new TIntermBinary(op, y, log);
- mul->setLine(node->getLine());
-
- TIntermUnary *exp = new TIntermUnary(EOpExp2, mul);
- exp->setLine(node->getLine());
-
- queueReplacement(exp, OriginalNode::IS_DROPPED);
-
- // If the x parameter also needs to be replaced, we need to do that in another traversal,
- // since it's parent node will change in a way that's not handled correctly by updateTree().
- if (IsProblematicPow(x))
- {
- mNeedAnotherIteration = true;
- return false;
- }
- }
- return true;
-}
-
-} // namespace
-
-void RemovePow(TIntermNode *root)
-{
- RemovePowTraverser traverser;
- // Iterate as necessary, and reset the traverser between iterations.
- do
- {
- traverser.nextIteration();
- root->traverse(&traverser);
- traverser.updateTree();
- } while (traverser.needAnotherIteration());
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemovePow.h b/src/3rdparty/angle/src/compiler/translator/RemovePow.h
deleted file mode 100644
index 3cd84988a9..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemovePow.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// RemovePow is an AST traverser to convert pow(x, y) built-in calls where y is a
-// constant to exp2(y * log2(x)). This works around an issue in NVIDIA 311 series
-// OpenGL drivers.
-//
-
-#ifndef COMPILER_TRANSLATOR_REMOVEPOW_H_
-#define COMPILER_TRANSLATOR_REMOVEPOW_H_
-
-namespace sh
-{
-class TIntermNode;
-
-void RemovePow(TIntermNode *root);
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_REMOVEPOW_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp
deleted file mode 100644
index dea949f448..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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/RemoveSwitchFallThrough.h"
-
-#include "compiler/translator/Diagnostics.h"
-#include "compiler/translator/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<TIntermBlock *> 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/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h
deleted file mode 100644
index 7a3b1963f2..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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_REMOVESWITCHFALLTHROUGH_H_
-#define COMPILER_TRANSLATOR_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_REMOVESWITCHFALLTHROUGH_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp
deleted file mode 100644
index 74b5e73f71..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp
+++ /dev/null
@@ -1,358 +0,0 @@
-//
-// Copyright (c) 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/RemoveUnreferencedVariables.h"
-
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class CollectVariableRefCountsTraverser : public TIntermTraverser
-{
- public:
- CollectVariableRefCountsTraverser();
-
- using RefCountMap = std::unordered_map<int, unsigned int>;
- RefCountMap &getSymbolIdRefCounts() { return mSymbolIdRefCounts; }
- RefCountMap &getStructIdRefCounts() { return mStructIdRefCounts; }
-
- void visitSymbol(TIntermSymbol *node) override;
- bool visitAggregate(Visit visit, TIntermAggregate *node) override;
- bool visitFunctionPrototype(Visit visit, 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());
- if (structIter == mStructIdRefCounts.end())
- {
- mStructIdRefCounts[structure->uniqueId()] = 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->getId());
- if (iter == mSymbolIdRefCounts.end())
- {
- mSymbolIdRefCounts[node->getId()] = 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;
-}
-
-bool CollectVariableRefCountsTraverser::visitFunctionPrototype(Visit visit,
- TIntermFunctionPrototype *node)
-{
- incrementStructTypeRefCount(node->getType());
- return true;
-}
-
-// 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()) != mStructIdRefCounts->end());
- unsigned int structRefCount = --(*mStructIdRefCounts)[structure->uniqueId()];
-
- 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();
- if ((*mStructIdRefCounts)[structId] > 1u)
- {
- // 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()->getSymbol().empty())
- {
- // Already an empty declaration - nothing to do.
- return;
- }
- queueReplacementWithParent(node, declarator,
- new TIntermSymbol(mSymbolTable->getEmptySymbolId(),
- TString(""), declarator->getType()),
- OriginalNode::IS_DROPPED);
- return;
- }
- }
-
- if (getParentNode()->getAsBlock())
- {
- TIntermSequence emptyReplacement;
- mMultiReplacements.push_back(
- NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, 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)
- {
- return true;
- }
-
- bool canRemoveVariable = false;
- TIntermSymbol *symbolNode = declarator->getAsSymbolNode();
- if (symbolNode != nullptr)
- {
- canRemoveVariable =
- (*mSymbolIdRefCounts)[symbolNode->getId()] == 1u || symbolNode->getSymbol().empty();
- }
- TIntermBinary *initNode = declarator->getAsBinaryNode();
- if (initNode != nullptr)
- {
- ASSERT(initNode->getLeft()->getAsSymbolNode());
- int symbolId = initNode->getLeft()->getAsSymbolNode()->getId();
- 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->getId()) != mSymbolIdRefCounts->end());
- --(*mSymbolIdRefCounts)[node->getId()];
-
- decrementStructTypeRefCount(node->getType());
- }
-}
-
-bool RemoveUnreferencedVariablesTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- if (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
-
-void RemoveUnreferencedVariables(TIntermBlock *root, TSymbolTable *symbolTable)
-{
- CollectVariableRefCountsTraverser collector;
- root->traverse(&collector);
- RemoveUnreferencedVariablesTraverser traverser(&collector.getSymbolIdRefCounts(),
- &collector.getStructIdRefCounts(), symbolTable);
- root->traverse(&traverser);
- traverser.updateTree();
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h b/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h
deleted file mode 100644
index 39c8327776..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// Copyright (c) 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_REMOVEUNREFERENCEDVARIABLES_H_
-#define COMPILER_TRANSLATOR_REMOVEUNREFERENCEDVARIABLES_H_
-
-namespace sh
-{
-
-class TIntermBlock;
-class TSymbolTable;
-
-void RemoveUnreferencedVariables(TIntermBlock *root, TSymbolTable *symbolTable);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_REMOVEUNREFERENCEDVARIABLES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp
deleted file mode 100644
index dc3fb7a74e..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-//
-// Copyright (c) 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/RewriteDoWhile.h"
-
-#include "compiler/translator/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.
- nextTemporaryId();
-
- TType boolType = TType(EbtBool);
-
- // bool temp = false;
- TIntermDeclaration *tempDeclaration = nullptr;
- {
- TConstantUnion *falseConstant = new TConstantUnion();
- falseConstant->setBConst(false);
- TIntermTyped *falseValue = new TIntermConstantUnion(falseConstant, boolType);
-
- tempDeclaration = createTempInitDeclaration(falseValue);
- }
-
- // temp = true;
- TIntermBinary *assignTrue = nullptr;
- {
- TConstantUnion *trueConstant = new TConstantUnion();
- trueConstant->setBConst(true);
- TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, boolType);
-
- assignTrue = createTempAssignment(trueValue);
- }
-
- // 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());
-
- TIntermIfElse *innerIf = new TIntermIfElse(negatedCondition, breakBlock, nullptr);
-
- TIntermBlock *innerIfBlock = new TIntermBlock();
- innerIfBlock->getSequence()->push_back(innerIf);
-
- breakIf = new TIntermIfElse(createTempSymbol(boolType), innerIfBlock, nullptr);
- }
-
- // Assemble the replacement loops, reusing the do-while loop's body and inserting our
- // statements at the front.
- TIntermLoop *newLoop = nullptr;
- {
- TConstantUnion *trueConstant = new TConstantUnion();
- trueConstant->setBConst(true);
- TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, boolType);
-
- 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, trueValue, nullptr, body);
- }
-
- TIntermSequence replacement;
- replacement.push_back(tempDeclaration);
- replacement.push_back(newLoop);
-
- node->replaceChildNodeWithMultiple(loop, replacement);
- }
- return true;
- }
-};
-
-} // anonymous namespace
-
-void RewriteDoWhile(TIntermNode *root, TSymbolTable *symbolTable)
-{
- DoWhileRewriter rewriter(symbolTable);
-
- root->traverse(&rewriter);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h b/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h
deleted file mode 100644
index e83bfc4b56..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright (c) 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_REWRITEDOWHILE_H_
-#define COMPILER_TRANSLATOR_REWRITEDOWHILE_H_
-
-namespace sh
-{
-
-class TIntermNode;
-class TSymbolTable;
-
-void RewriteDoWhile(TIntermNode *root, TSymbolTable *symbolTable);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_REWRITEDOWHILE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp
deleted file mode 100644
index ed1bfad8a8..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-//
-// Copyright (c) 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/RewriteElseBlocks.h"
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/NodeSearch.h"
-#include "compiler/translator/SymbolTable.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);
-
- nextTemporaryId();
-
- TIntermDeclaration *storeCondition = createTempInitDeclaration(ifElse->getCondition());
-
- 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 dummy
- // 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 = createTempSymbol(boolType);
- TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse);
- TIntermIfElse *falseIfElse =
- new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
- falseBlock = EnsureBlock(falseIfElse);
- }
-
- TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType);
- 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
-
-void RewriteElseBlocks(TIntermNode *node, TSymbolTable *symbolTable)
-{
- ElseBlockRewriter rewriter(symbolTable);
- node->traverse(&rewriter);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h
deleted file mode 100644
index 2586b5405c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 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_REWRITEELSEBLOCKS_H_
-#define COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_
-
-namespace sh
-{
-
-class TIntermNode;
-class TSymbolTable;
-
-void RewriteElseBlocks(TIntermNode *node, TSymbolTable *symbolTable);
-}
-
-#endif // COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp
deleted file mode 100644
index b602e0c923..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-//
-// Copyright (c) 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/RewriteTexelFetchOffset.h"
-
-#include "common/angleutils.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class Traverser : public TIntermTraverser
-{
- public:
- static void Apply(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
-void Traverser::Apply(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion)
-{
- Traverser traverser(symbolTable, shaderVersion);
- do
- {
- traverser.nextIteration();
- root->traverse(&traverser);
- if (traverser.mFound)
- {
- traverser.updateTree();
- }
- } while (traverser.mFound);
-}
-
-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 (node->getOp() != EOpCallBuiltInFunction)
- {
- return true;
- }
-
- if (node->getFunctionSymbolInfo()->getName() != "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 = new TIntermSequence();
-
- // 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 = new TIntermSequence();
- 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
-
-void RewriteTexelFetchOffset(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion)
-{
- // texelFetchOffset is only valid in GLSL 3.0 and later.
- if (shaderVersion < 300)
- return;
-
- Traverser::Apply(root, symbolTable, shaderVersion);
-}
-
-} // namespace sh \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h b/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h
deleted file mode 100644
index 694d709f8e..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Copyright (c) 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_REWRITE_TEXELFETCHOFFSET_H_
-#define COMPILER_TRANSLATOR_REWRITE_TEXELFETCHOFFSET_H_
-
-class TIntermNode;
-class TSymbolTable;
-
-namespace sh
-{
-
-void RewriteTexelFetchOffset(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_REWRITE_TEXELFETCHOFFSET_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp
deleted file mode 100644
index 696a49536c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-//
-// Copyright (c) 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/RewriteUnaryMinusOperatorFloat.h"
-
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class Traverser : public TIntermTraverser
-{
- public:
- static void Apply(TIntermNode *root);
-
- private:
- Traverser();
- bool visitUnary(Visit visit, TIntermUnary *node) override;
- void nextIteration();
-
- bool mFound = false;
-};
-
-// static
-void Traverser::Apply(TIntermNode *root)
-{
- Traverser traverser;
- do
- {
- traverser.nextIteration();
- root->traverse(&traverser);
- if (traverser.mFound)
- {
- traverser.updateTree();
- }
- } while (traverser.mFound);
-}
-
-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
-
-void RewriteUnaryMinusOperatorFloat(TIntermNode *root)
-{
- Traverser::Apply(root);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h
deleted file mode 100644
index ccbfbcbd9e..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 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_REWRITEUNARYMINUSOPERATORFLOAT_H_
-#define COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORFLOAT_H_
-
-class TIntermNode;
-namespace sh
-{
-
-void RewriteUnaryMinusOperatorFloat(TIntermNode *root);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORFLOAT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp
deleted file mode 100644
index fe2ef948b4..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-//
-// Copyright (c) 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/RewriteUnaryMinusOperatorInt.h"
-
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class Traverser : public TIntermTraverser
-{
- public:
- static void Apply(TIntermNode *root);
-
- private:
- Traverser();
- bool visitUnary(Visit visit, TIntermUnary *node) override;
- void nextIteration();
-
- bool mFound = false;
-};
-
-// static
-void Traverser::Apply(TIntermNode *root)
-{
- Traverser traverser;
- do
- {
- traverser.nextIteration();
- root->traverse(&traverser);
- if (traverser.mFound)
- {
- traverser.updateTree();
- }
- } while (traverser.mFound);
-}
-
-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);
- bitwiseNot->setLine(opr->getLine());
-
- // Constant 1 (or 1u)
- TConstantUnion *one = new TConstantUnion();
- if (opr->getType().getBasicType() == EbtInt)
- {
- one->setIConst(1);
- }
- else
- {
- one->setUConst(1u);
- }
- TIntermConstantUnion *oneNode = new TIntermConstantUnion(one, opr->getType());
- oneNode->getTypePointer()->setQualifier(EvqConst);
- 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
-
-void RewriteUnaryMinusOperatorInt(TIntermNode *root)
-{
- Traverser::Apply(root);
-}
-
-} // namespace sh \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h
deleted file mode 100644
index 50f0c442a7..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 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_REWRITEUNARYMINUSOPERATORINT_H_
-#define COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_
-
-class TIntermNode;
-namespace sh
-{
-
-void RewriteUnaryMinusOperatorInt(TIntermNode *root);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp b/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp
deleted file mode 100644
index 3c4209c539..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-//
-// Copyright (c) 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.
-//
-
-#include "compiler/translator/RunAtTheEndOfShader.h"
-
-#include "compiler/translator/FindMain.h"
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class ContainsReturnTraverser : public TIntermTraverser
-{
- public:
- ContainsReturnTraverser() : TIntermTraverser(true, false, false), mContainsReturn(false) {}
-
- bool visitBranch(Visit visit, TIntermBranch *node) override
- {
- if (node->getFlowOp() == EOpReturn)
- {
- mContainsReturn = true;
- }
- return false;
- }
-
- bool containsReturn() { return mContainsReturn; }
-
- private:
- bool mContainsReturn;
-};
-
-bool ContainsReturn(TIntermNode *node)
-{
- ContainsReturnTraverser traverser;
- node->traverse(&traverser);
- return traverser.containsReturn();
-}
-
-void WrapMainAndAppend(TIntermBlock *root,
- TIntermFunctionDefinition *main,
- TIntermNode *codeToRun,
- TSymbolTable *symbolTable)
-{
- // Replace main() with main0() with the same body.
- TSymbolUniqueId oldMainId(symbolTable);
- std::stringstream oldMainName;
- oldMainName << "main" << oldMainId.get();
- TIntermFunctionDefinition *oldMain = CreateInternalFunctionDefinitionNode(
- TType(EbtVoid), oldMainName.str().c_str(), main->getBody(), oldMainId);
-
- bool replaced = root->replaceChildNode(main, oldMain);
- ASSERT(replaced);
-
- // void main()
- TIntermFunctionPrototype *newMainProto = new TIntermFunctionPrototype(
- TType(EbtVoid), main->getFunctionPrototype()->getFunctionSymbolInfo()->getId());
- newMainProto->getFunctionSymbolInfo()->setName("main");
-
- // {
- // main0();
- // codeToRun
- // }
- TIntermBlock *newMainBody = new TIntermBlock();
- TIntermAggregate *oldMainCall = CreateInternalFunctionCallNode(
- TType(EbtVoid), oldMainName.str().c_str(), oldMainId, new TIntermSequence());
- newMainBody->appendStatement(oldMainCall);
- newMainBody->appendStatement(codeToRun);
-
- // Add the new main() to the root node.
- TIntermFunctionDefinition *newMain = new TIntermFunctionDefinition(newMainProto, newMainBody);
- root->appendStatement(newMain);
-}
-
-} // anonymous namespace
-
-void RunAtTheEndOfShader(TIntermBlock *root, TIntermNode *codeToRun, TSymbolTable *symbolTable)
-{
- TIntermFunctionDefinition *main = FindMain(root);
- if (!ContainsReturn(main))
- {
- main->getBody()->appendStatement(codeToRun);
- return;
- }
-
- WrapMainAndAppend(root, main, codeToRun, symbolTable);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h b/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h
deleted file mode 100644
index ed94c28dae..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright (c) 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_RUNATTHEENDOFSHADER_H_
-#define COMPILER_TRANSLATOR_RUNATTHEENDOFSHADER_H_
-
-namespace sh
-{
-
-class TIntermBlock;
-class TIntermNode;
-class TSymbolTable;
-
-void RunAtTheEndOfShader(TIntermBlock *root, TIntermNode *codeToRun, TSymbolTable *symbolTable);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_RUNATTHEENDOFSHADER_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
deleted file mode 100644
index 746c16e2e6..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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 "common/debug.h"
-#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
-
-#include <algorithm>
-
-#include "angle_gl.h"
-#include "common/angleutils.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.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;
-}
-
-TIntermBinary *ConstructVectorIndexBinaryNode(TIntermSymbol *symbolNode, int index)
-{
- return new TIntermBinary(EOpIndexDirect, symbolNode, CreateIndexNode(index));
-}
-
-TIntermBinary *ConstructMatrixIndexBinaryNode(TIntermSymbol *symbolNode, int colIndex, int rowIndex)
-{
- TIntermBinary *colVectorNode = ConstructVectorIndexBinaryNode(symbolNode, colIndex);
-
- return new TIntermBinary(EOpIndexDirect, colVectorNode, CreateIndexNode(rowIndex));
-}
-
-class ScalarizeArgsTraverser : public TIntermTraverser
-{
- public:
- ScalarizeArgsTraverser(sh::GLenum shaderType,
- bool fragmentPrecisionHigh,
- TSymbolTable *symbolTable)
- : TIntermTraverser(true, false, false, symbolTable),
- mShaderType(shaderType),
- mFragmentPrecisionHigh(fragmentPrecisionHigh)
- {
- }
-
- 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.
- void createTempVariable(TIntermTyped *original);
-
- std::vector<TIntermSequence> mBlockStack;
-
- sh::GLenum mShaderType;
- bool mFragmentPrecisionHigh;
-};
-
-bool ScalarizeArgsTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- if (visit == PreVisit && node->getOp() == EOpConstruct)
- {
- if (node->getType().isVector() && ContainsMatrixNode(*(node->getSequence())))
- scalarizeArgs(node, false, true);
- else if (node->getType().isMatrix() && ContainsVectorNode(*(node->getSequence())))
- 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<int>(aggregate->getType().getObjectSize());
- TIntermSequence *sequence = aggregate->getSequence();
- TIntermSequence original(*sequence);
- sequence->clear();
- for (size_t ii = 0; ii < original.size(); ++ii)
- {
- ASSERT(size > 0);
- TIntermTyped *node = original[ii]->getAsTyped();
- ASSERT(node);
- createTempVariable(node);
- if (node->isScalar())
- {
- sequence->push_back(createTempSymbol(node->getType()));
- size--;
- }
- else if (node->isVector())
- {
- if (scalarizeVector)
- {
- int repeat = std::min(size, node->getNominalSize());
- size -= repeat;
- for (int index = 0; index < repeat; ++index)
- {
- TIntermSymbol *symbolNode = createTempSymbol(node->getType());
- TIntermBinary *newNode = ConstructVectorIndexBinaryNode(symbolNode, index);
- sequence->push_back(newNode);
- }
- }
- else
- {
- TIntermSymbol *symbolNode = createTempSymbol(node->getType());
- sequence->push_back(symbolNode);
- size -= node->getNominalSize();
- }
- }
- else
- {
- ASSERT(node->isMatrix());
- if (scalarizeMatrix)
- {
- int colIndex = 0, rowIndex = 0;
- int repeat = std::min(size, node->getCols() * node->getRows());
- size -= repeat;
- while (repeat > 0)
- {
- TIntermSymbol *symbolNode = createTempSymbol(node->getType());
- TIntermBinary *newNode =
- ConstructMatrixIndexBinaryNode(symbolNode, colIndex, rowIndex);
- sequence->push_back(newNode);
- rowIndex++;
- if (rowIndex >= node->getRows())
- {
- rowIndex = 0;
- colIndex++;
- }
- repeat--;
- }
- }
- else
- {
- TIntermSymbol *symbolNode = createTempSymbol(node->getType());
- sequence->push_back(symbolNode);
- size -= node->getCols() * node->getRows();
- }
- }
- }
-}
-
-void ScalarizeArgsTraverser::createTempVariable(TIntermTyped *original)
-{
- ASSERT(original);
- nextTemporaryId();
- TIntermDeclaration *decl = createTempInitDeclaration(original);
-
- TType type = original->getType();
- if (mShaderType == GL_FRAGMENT_SHADER && type.getBasicType() == EbtFloat &&
- type.getPrecision() == EbpUndefined)
- {
- // We use the highest available precision for the temporary variable
- // to avoid computing the actual precision using the rules defined
- // in GLSL ES 1.0 Section 4.5.2.
- TIntermBinary *init = decl->getSequence()->at(0)->getAsBinaryNode();
- init->getTypePointer()->setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium);
- init->getLeft()->getTypePointer()->setPrecision(mFragmentPrecisionHigh ? EbpHigh
- : EbpMedium);
- }
-
- ASSERT(mBlockStack.size() > 0);
- TIntermSequence &sequence = mBlockStack.back();
- sequence.push_back(decl);
-}
-
-} // namespace anonymous
-
-void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root,
- sh::GLenum shaderType,
- bool fragmentPrecisionHigh,
- TSymbolTable *symbolTable)
-{
- ScalarizeArgsTraverser scalarizer(shaderType, fragmentPrecisionHigh, symbolTable);
- root->traverse(&scalarizer);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
deleted file mode 100644
index b8f782d1ec..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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_SCALARIZEVECANDMATCONSTRUCTORARGS_H_
-#define COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_
-
-#include "GLSLANG/ShaderLang.h"
-
-namespace sh
-{
-class TIntermBlock;
-class TSymbolTable;
-
-void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root,
- sh::GLenum shaderType,
- bool fragmentPrecisionHigh,
- TSymbolTable *symbolTable);
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp
deleted file mode 100644
index 34c644d028..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// SearchSymbol is an AST traverser to detect the use of a given symbol name
-//
-
-#include "compiler/translator/SearchSymbol.h"
-
-#include "compiler/translator/InfoSink.h"
-
-namespace sh
-{
-SearchSymbol::SearchSymbol(const TString &symbol)
- : TIntermTraverser(true, false, false), mSymbol(symbol)
-{
- match = false;
-}
-
-void SearchSymbol::traverse(TIntermNode *node)
-{
- node->traverse(this);
-}
-
-void SearchSymbol::visitSymbol(TIntermSymbol *symbolNode)
-{
- if (symbolNode->getSymbol() == mSymbol)
- {
- match = true;
- }
-}
-
-bool SearchSymbol::foundMatch() const
-{
- return match;
-}
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h
deleted file mode 100644
index b8379e041f..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// SearchSymbol is an AST traverser to detect the use of a given symbol name
-//
-
-#ifndef COMPILER_TRANSLATOR_SEARCHSYMBOL_H_
-#define COMPILER_TRANSLATOR_SEARCHSYMBOL_H_
-
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/ParseContext.h"
-
-namespace sh
-{
-class SearchSymbol : public TIntermTraverser
-{
- public:
- SearchSymbol(const TString &symbol);
-
- void traverse(TIntermNode *node);
- void visitSymbol(TIntermSymbol *symbolNode) override;
-
- bool foundMatch() const;
-
- protected:
- const TString &mSymbol;
- bool match;
-};
-}
-
-#endif // COMPILER_TRANSLATOR_SEARCHSYMBOL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp b/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp
deleted file mode 100644
index fe25823e38..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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/SeparateArrayInitialization.h"
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/OutputHLSL.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class SeparateArrayInitTraverser : private TIntermTraverser
-{
- public:
- static void apply(TIntermNode *root);
-
- private:
- SeparateArrayInitTraverser();
- bool visitDeclaration(Visit, TIntermDeclaration *node) override;
-};
-
-void SeparateArrayInitTraverser::apply(TIntermNode *root)
-{
- SeparateArrayInitTraverser separateInit;
- root->traverse(&separateInit);
- separateInit.updateTree();
-}
-
-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() && !sh::OutputHLSL::canWriteAsHLSLLiteral(initializer))
- {
- // 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.push_back(
- NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
- }
- }
- return false;
-}
-
-} // namespace
-
-void SeparateArrayInitialization(TIntermNode *root)
-{
- SeparateArrayInitTraverser::apply(root);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h b/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h
deleted file mode 100644
index 3a9bb55dd1..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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_SEPARATEARRAYINITIALIZATION_H_
-#define COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_
-
-namespace sh
-{
-class TIntermNode;
-
-void SeparateArrayInitialization(TIntermNode *root);
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp b/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp
deleted file mode 100644
index 9a066075c0..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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/SeparateDeclarations.h"
-
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class SeparateDeclarationsTraverser : private TIntermTraverser
-{
- public:
- static void apply(TIntermNode *root);
-
- private:
- SeparateDeclarationsTraverser();
- bool visitDeclaration(Visit, TIntermDeclaration *node) override;
-};
-
-void SeparateDeclarationsTraverser::apply(TIntermNode *root)
-{
- SeparateDeclarationsTraverser separateDecl;
- root->traverse(&separateDecl);
- separateDecl.updateTree();
-}
-
-SeparateDeclarationsTraverser::SeparateDeclarationsTraverser()
- : TIntermTraverser(true, false, false)
-{
-}
-
-bool SeparateDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
-{
- TIntermSequence *sequence = node->getSequence();
- if (sequence->size() > 1)
- {
- TIntermBlock *parentBlock = getParentNode()->getAsBlock();
- ASSERT(parentBlock != nullptr);
-
- TIntermSequence replacementDeclarations;
- for (size_t ii = 0; ii < sequence->size(); ++ii)
- {
- TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
-
- replacementDeclaration->appendDeclarator(sequence->at(ii)->getAsTyped());
- replacementDeclaration->setLine(sequence->at(ii)->getLine());
- replacementDeclarations.push_back(replacementDeclaration);
- }
-
- mMultiReplacements.push_back(
- NodeReplaceWithMultipleEntry(parentBlock, node, replacementDeclarations));
- }
- return false;
-}
-
-} // namespace
-
-void SeparateDeclarations(TIntermNode *root)
-{
- SeparateDeclarationsTraverser::apply(root);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h b/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h
deleted file mode 100644
index 8142faea1c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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_SEPARATEDECLARATIONS_H_
-#define COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_
-
-namespace sh
-{
-class TIntermNode;
-
-void SeparateDeclarations(TIntermNode *root);
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp b/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
deleted file mode 100644
index 01d627937c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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/SeparateExpressionsReturningArrays.h"
-
-#include "compiler/translator/IntermNodePatternMatcher.h"
-#include "compiler/translator/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.
- insertions.push_back(createTempInitDeclaration(node->getLeft()));
- insertStatementsInParentBlock(insertions);
-
- queueReplacement(createTempSymbol(node->getType()), 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;
-
- TIntermSequence insertions;
- insertions.push_back(createTempInitDeclaration(node->shallowCopy()));
- insertStatementsInParentBlock(insertions);
-
- queueReplacement(createTempSymbol(node->getType()), OriginalNode::IS_DROPPED);
-
- return false;
-}
-
-void SeparateExpressionsTraverser::nextIteration()
-{
- mFoundArrayExpression = false;
- nextTemporaryId();
-}
-
-} // namespace
-
-void SeparateExpressionsReturningArrays(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())
- traverser.updateTree();
- } while (traverser.foundArrayExpression());
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h b/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h
deleted file mode 100644
index f8eb438748..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_
-#define COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_
-
-namespace sh
-{
-class TIntermNode;
-class TSymbolTable;
-
-void SeparateExpressionsReturningArrays(TIntermNode *root, TSymbolTable *symbolTable);
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Severity.h b/src/3rdparty/angle/src/compiler/translator/Severity.h
deleted file mode 100644
index 47808a16a7..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Severity.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 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/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp
deleted file mode 100644
index eeb13f2ec0..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp
+++ /dev/null
@@ -1,578 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-//
-// 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/length_limits.h"
-#ifdef ANGLE_ENABLE_HLSL
-#include "compiler/translator/TranslatorHLSL.h"
-#endif // ANGLE_ENABLE_HLSL
-#include "compiler/translator/VariablePacker.h"
-#include "angle_gl.h"
-
-namespace sh
-{
-
-namespace
-{
-
-bool isInitialized = false;
-
-//
-// This is the platform independent interface between an OGL driver
-// and the shading language compiler.
-//
-
-template <typename VarT>
-const std::vector<VarT> *GetVariableList(const TCompiler *compiler);
-
-template <>
-const std::vector<Uniform> *GetVariableList(const TCompiler *compiler)
-{
- return &compiler->getUniforms();
-}
-
-template <>
-const std::vector<Varying> *GetVariableList(const TCompiler *compiler)
-{
- 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;
- }
-}
-
-template <>
-const std::vector<Attribute> *GetVariableList(const TCompiler *compiler)
-{
- return &compiler->getAttributes();
-}
-
-template <>
-const std::vector<OutputVariable> *GetVariableList(const TCompiler *compiler)
-{
- return &compiler->getOutputVariables();
-}
-
-template <>
-const std::vector<InterfaceBlock> *GetVariableList(const TCompiler *compiler)
-{
- return &compiler->getInterfaceBlocks();
-}
-
-TCompiler *GetCompilerFromHandle(ShHandle handle)
-{
- if (!handle)
- {
- return nullptr;
- }
-
- TShHandleBase *base = static_cast<TShHandleBase *>(handle);
- return base->getAsCompiler();
-}
-
-template <typename VarT>
-const std::vector<VarT> *GetShaderVariables(const ShHandle handle)
-{
- TCompiler *compiler = GetCompilerFromHandle(handle);
- if (!compiler)
- {
- return nullptr;
- }
-
- return GetVariableList<VarT>(compiler);
-}
-
-#ifdef ANGLE_ENABLE_HLSL
-TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle)
-{
- if (!handle)
- return nullptr;
- TShHandleBase *base = static_cast<TShHandleBase *>(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:
- return GL_INVALID_VALUE;
-
- 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->WEBGL_debug_shader_precision = 0;
- resources->EXT_shader_framebuffer_fetch = 0;
- resources->NV_shader_framebuffer_fetch = 0;
- resources->ARM_shader_framebuffer_fetch = 0;
- resources->OVR_multiview = 0;
- resources->EXT_YUV_target = 0;
- resources->OES_geometry_shader = 0;
-
- resources->NV_draw_buffers = 0;
-
- // 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->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC;
-
- 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;
-}
-
-//
-// 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<TShHandleBase *>(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 reinterpret_cast<void *>(base);
-}
-
-void Destruct(ShHandle handle)
-{
- if (handle == 0)
- return;
-
- TShHandleBase *base = static_cast<TShHandleBase *>(handle);
-
- if (base->getAsCompiler())
- DeleteCompiler(base->getAsCompiler());
-}
-
-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,
- 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();
-}
-
-const std::map<std::string, std::string> *GetNameHashingMap(const ShHandle handle)
-{
- TCompiler *compiler = GetCompilerFromHandle(handle);
- ASSERT(compiler);
- return &(compiler->getNameMap());
-}
-
-const std::vector<Uniform> *GetUniforms(const ShHandle handle)
-{
- return GetShaderVariables<Uniform>(handle);
-}
-
-const std::vector<Varying> *GetInputVaryings(const ShHandle handle)
-{
- TCompiler *compiler = GetCompilerFromHandle(handle);
- if (compiler == nullptr)
- {
- return nullptr;
- }
- return &compiler->getInputVaryings();
-}
-
-const std::vector<Varying> *GetOutputVaryings(const ShHandle handle)
-{
- TCompiler *compiler = GetCompilerFromHandle(handle);
- if (compiler == nullptr)
- {
- return nullptr;
- }
- return &compiler->getOutputVaryings();
-}
-
-const std::vector<Varying> *GetVaryings(const ShHandle handle)
-{
- return GetShaderVariables<Varying>(handle);
-}
-
-const std::vector<Attribute> *GetAttributes(const ShHandle handle)
-{
- return GetShaderVariables<Attribute>(handle);
-}
-
-const std::vector<OutputVariable> *GetOutputVariables(const ShHandle handle)
-{
- return GetShaderVariables<OutputVariable>(handle);
-}
-
-const std::vector<InterfaceBlock> *GetInterfaceBlocks(const ShHandle handle)
-{
- return GetShaderVariables<InterfaceBlock>(handle);
-}
-
-const std::vector<InterfaceBlock> *GetUniformBlocks(const ShHandle handle)
-{
- ASSERT(handle);
- TShHandleBase *base = static_cast<TShHandleBase *>(handle);
- TCompiler *compiler = base->getAsCompiler();
- ASSERT(compiler);
-
- return &compiler->getUniformBlocks();
-}
-
-const std::vector<InterfaceBlock> *GetShaderStorageBlocks(const ShHandle handle)
-{
- ASSERT(handle);
- TShHandleBase *base = static_cast<TShHandleBase *>(handle);
- TCompiler *compiler = base->getAsCompiler();
- ASSERT(compiler);
-
- return &compiler->getShaderStorageBlocks();
-}
-
-WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle)
-{
- ASSERT(handle);
-
- TShHandleBase *base = static_cast<TShHandleBase *>(handle);
- TCompiler *compiler = base->getAsCompiler();
- ASSERT(compiler);
-
- return compiler->getComputeShaderLocalSize();
-}
-
-int GetVertexShaderNumViews(const ShHandle handle)
-{
- ASSERT(handle);
- TShHandleBase *base = static_cast<TShHandleBase *>(handle);
- TCompiler *compiler = base->getAsCompiler();
- ASSERT(compiler);
-
- return compiler->getNumViews();
-}
-
-bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector<ShaderVariable> &variables)
-{
- return CheckVariablesInPackingLimits(maxVectors, variables);
-}
-
-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
-}
-
-const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle)
-{
-#ifdef ANGLE_ENABLE_HLSL
- TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
- ASSERT(translator);
-
- return translator->getUniformRegisterMap();
-#else
- return nullptr;
-#endif // ANGLE_ENABLE_HLSL
-}
-
-GLenum GetGeometryShaderInputPrimitiveType(const ShHandle handle)
-{
- ASSERT(handle);
-
- TShHandleBase *base = static_cast<TShHandleBase *>(handle);
- TCompiler *compiler = base->getAsCompiler();
- ASSERT(compiler);
-
- return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderInputPrimitiveType());
-}
-
-GLenum GetGeometryShaderOutputPrimitiveType(const ShHandle handle)
-{
- ASSERT(handle);
-
- TShHandleBase *base = static_cast<TShHandleBase *>(handle);
- TCompiler *compiler = base->getAsCompiler();
- ASSERT(compiler);
-
- return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderOutputPrimitiveType());
-}
-
-int GetGeometryShaderInvocations(const ShHandle handle)
-{
- ASSERT(handle);
-
- TShHandleBase *base = static_cast<TShHandleBase *>(handle);
- TCompiler *compiler = base->getAsCompiler();
- ASSERT(compiler);
-
- return compiler->getGeometryShaderInvocations();
-}
-
-int GetGeometryShaderMaxVertices(const ShHandle handle)
-{
- ASSERT(handle);
-
- TShHandleBase *base = static_cast<TShHandleBase *>(handle);
- TCompiler *compiler = base->getAsCompiler();
- ASSERT(compiler);
-
- return compiler->getGeometryShaderMaxVertices();
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp
deleted file mode 100644
index 4ab574e935..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp
+++ /dev/null
@@ -1,586 +0,0 @@
-//
-// Copyright (c) 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 <GLSLANG/ShaderLang.h>
-
-#include "common/debug.h"
-#include "common/utilities.h"
-
-namespace sh
-{
-
-namespace
-{
-
-InterpolationType GetNonAuxiliaryInterpolationType(InterpolationType interpolation)
-{
- return (interpolation == INTERPOLATION_CENTROID ? INTERPOLATION_SMOOTH : interpolation);
-}
-}
-// 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()
- : type(0), precision(0), flattenedOffsetInParentArrays(0), staticUse(false)
-{
-}
-
-ShaderVariable::ShaderVariable(GLenum typeIn)
- : type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false)
-{
-}
-
-ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn)
- : type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false)
-{
- 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),
- flattenedOffsetInParentArrays(other.flattenedOffsetInParentArrays),
- staticUse(other.staticUse),
- fields(other.fields),
- structName(other.structName)
-{
-}
-
-ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
-{
- type = other.type;
- precision = other.precision;
- name = other.name;
- mappedName = other.mappedName;
- arraySizes = other.arraySizes;
- staticUse = other.staticUse;
- flattenedOffsetInParentArrays = other.flattenedOffsetInParentArrays;
- fields = other.fields;
- structName = other.structName;
- 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 || fields.size() != other.fields.size() ||
- structName != other.structName)
- {
- 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::getArraySizeProduct() const
-{
- return gl::ArraySizeProduct(arraySizes);
-}
-
-void ShaderVariable::indexIntoArray(unsigned int arrayIndex)
-{
- ASSERT(isArray());
- flattenedOffsetInParentArrays =
- arrayIndex + getOutermostArraySize() * flattenedOffsetInParentArrays;
- arraySizes.pop_back();
-}
-
-unsigned int ShaderVariable::getNestedArraySize(unsigned int arrayNestingIndex) const
-{
- ASSERT(arraySizes.size() > arrayNestingIndex);
- return arraySizes[arraySizes.size() - 1u - arrayNestingIndex];
-}
-
-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;
-}
-
-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;
- }
-}
-
-bool ShaderVariable::isBuiltIn() const
-{
- return (name.size() >= 4 && name[0] == 'g' && name[1] == 'l' && name[2] == '_');
-}
-
-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 (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 (structName != other.structName)
- return false;
- return true;
-}
-
-Uniform::Uniform() : binding(-1), offset(-1)
-{
-}
-
-Uniform::~Uniform()
-{
-}
-
-Uniform::Uniform(const Uniform &other)
- : VariableWithLocation(other), binding(other.binding), offset(other.offset)
-{
-}
-
-Uniform &Uniform::operator=(const Uniform &other)
-{
- VariableWithLocation::operator=(other);
- binding = other.binding;
- offset = other.offset;
- return *this;
-}
-
-bool Uniform::operator==(const Uniform &other) const
-{
- return VariableWithLocation::operator==(other) && binding == other.binding &&
- offset == other.offset;
-}
-
-bool Uniform::isSameUniformAtLinkTime(const Uniform &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 (location != -1 && other.location != -1 && location != other.location)
- {
- return false;
- }
- if (offset != other.offset)
- {
- return false;
- }
- return VariableWithLocation::isSameVariableAtLinkTime(other, true, true);
-}
-
-VariableWithLocation::VariableWithLocation() : location(-1)
-{
-}
-
-VariableWithLocation::~VariableWithLocation()
-{
-}
-
-VariableWithLocation::VariableWithLocation(const VariableWithLocation &other)
- : ShaderVariable(other), location(other.location)
-{
-}
-
-VariableWithLocation &VariableWithLocation::operator=(const VariableWithLocation &other)
-{
- ShaderVariable::operator=(other);
- location = other.location;
- return *this;
-}
-
-bool VariableWithLocation::operator==(const VariableWithLocation &other) const
-{
- return (ShaderVariable::operator==(other) && location == other.location);
-}
-
-Attribute::Attribute()
-{
-}
-
-Attribute::~Attribute()
-{
-}
-
-Attribute::Attribute(const Attribute &other) : VariableWithLocation(other)
-{
-}
-
-Attribute &Attribute::operator=(const Attribute &other)
-{
- VariableWithLocation::operator=(other);
- return *this;
-}
-
-bool Attribute::operator==(const Attribute &other) const
-{
- return VariableWithLocation::operator==(other);
-}
-
-OutputVariable::OutputVariable()
-{
-}
-
-OutputVariable::~OutputVariable()
-{
-}
-
-OutputVariable::OutputVariable(const OutputVariable &other) : VariableWithLocation(other)
-{
-}
-
-OutputVariable &OutputVariable::operator=(const OutputVariable &other)
-{
- VariableWithLocation::operator=(other);
- return *this;
-}
-
-bool OutputVariable::operator==(const OutputVariable &other) const
-{
- return VariableWithLocation::operator==(other);
-}
-
-InterfaceBlockField::InterfaceBlockField() : isRowMajorLayout(false)
-{
-}
-
-InterfaceBlockField::~InterfaceBlockField()
-{
-}
-
-InterfaceBlockField::InterfaceBlockField(const InterfaceBlockField &other)
- : ShaderVariable(other), isRowMajorLayout(other.isRowMajorLayout)
-{
-}
-
-InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &other)
-{
- ShaderVariable::operator=(other);
- isRowMajorLayout = other.isRowMajorLayout;
- return *this;
-}
-
-bool InterfaceBlockField::operator==(const InterfaceBlockField &other) const
-{
- return (ShaderVariable::operator==(other) && isRowMajorLayout == other.isRowMajorLayout);
-}
-
-bool InterfaceBlockField::isSameInterfaceBlockFieldAtLinkTime(
- const InterfaceBlockField &other) const
-{
- return (ShaderVariable::isSameVariableAtLinkTime(other, true, true) &&
- isRowMajorLayout == other.isRowMajorLayout);
-}
-
-Varying::Varying() : interpolation(INTERPOLATION_SMOOTH), isInvariant(false)
-{
-}
-
-Varying::~Varying()
-{
-}
-
-Varying::Varying(const Varying &other)
- : VariableWithLocation(other),
- interpolation(other.interpolation),
- isInvariant(other.isInvariant)
-{
-}
-
-Varying &Varying::operator=(const Varying &other)
-{
- VariableWithLocation::operator=(other);
- interpolation = other.interpolation;
- isInvariant = other.isInvariant;
- return *this;
-}
-
-bool Varying::operator==(const Varying &other) const
-{
- return (VariableWithLocation::operator==(other) && interpolation == other.interpolation &&
- isInvariant == other.isInvariant);
-}
-
-bool Varying::isSameVaryingAtLinkTime(const Varying &other) const
-{
- return isSameVaryingAtLinkTime(other, 100);
-}
-
-bool Varying::isSameVaryingAtLinkTime(const Varying &other, int shaderVersion) const
-{
- return (ShaderVariable::isSameVariableAtLinkTime(other, false, false) &&
- InterpolationTypesMatch(interpolation, other.interpolation) &&
- (shaderVersion >= 300 || isInvariant == other.isInvariant) &&
- (location == other.location) &&
- (name == other.name || (shaderVersion >= 310 && location >= 0)));
-}
-
-InterfaceBlock::InterfaceBlock()
- : arraySize(0),
- layout(BLOCKLAYOUT_PACKED),
- isRowMajorLayout(false),
- binding(-1),
- staticUse(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),
- 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;
- 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 (name.size() >= 4 && name[0] == 'g' && name[1] == 'l' && name[2] == '_');
-}
-
-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/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp b/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp
deleted file mode 100644
index 9704046839..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-//
-// Copyright (c) 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/SimplifyLoopConditions.h"
-
-#include "compiler/translator/IntermNodePatternMatcher.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class SimplifyLoopConditionsTraverser : public TLValueTrackingTraverser
-{
- public:
- SimplifyLoopConditionsTraverser(unsigned int conditionsToSimplifyMask,
- TSymbolTable *symbolTable,
- int shaderVersion);
-
- 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 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;
- IntermNodePatternMatcher mConditionsToSimplify;
-};
-
-SimplifyLoopConditionsTraverser::SimplifyLoopConditionsTraverser(
- unsigned int conditionsToSimplifyMask,
- TSymbolTable *symbolTable,
- int shaderVersion)
- : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion),
- mFoundLoopToChange(false),
- mInsideLoopInitConditionOrExpression(false),
- mConditionsToSimplify(conditionsToSimplifyMask)
-{
-}
-
-// 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.
-
- 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.
-
- 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.
-
- 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.
-
- 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.
-
- mFoundLoopToChange = mConditionsToSimplify.match(node);
- return !mFoundLoopToChange;
-}
-
-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 = false;
-
- 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;
-
- if (mFoundLoopToChange)
- {
- nextTemporaryId();
-
- // Replace the loop condition with a boolean variable that's updated on each iteration.
- TLoopType loopType = node->getType();
- if (loopType == ELoopWhile)
- {
- // Transform:
- // while (expr) { body; }
- // into
- // bool s0 = expr;
- // while (s0) { { body; } s0 = expr; }
- TIntermSequence tempInitSeq;
- tempInitSeq.push_back(createTempInitDeclaration(node->getCondition()->deepCopy()));
- insertStatementsInParentBlock(tempInitSeq);
-
- TIntermBlock *newBody = new TIntermBlock();
- if (node->getBody())
- {
- newBody->getSequence()->push_back(node->getBody());
- }
- newBody->getSequence()->push_back(
- createTempAssignment(node->getCondition()->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(createTempSymbol(node->getCondition()->getType()));
- }
- else if (loopType == ELoopDoWhile)
- {
- // Transform:
- // do {
- // body;
- // } while (expr);
- // into
- // bool s0 = true;
- // do {
- // { body; }
- // s0 = expr;
- // } while (s0);
- TIntermSequence tempInitSeq;
- tempInitSeq.push_back(createTempInitDeclaration(CreateBoolNode(true)));
- insertStatementsInParentBlock(tempInitSeq);
-
- TIntermBlock *newBody = new TIntermBlock();
- if (node->getBody())
- {
- newBody->getSequence()->push_back(node->getBody());
- }
- newBody->getSequence()->push_back(
- createTempAssignment(node->getCondition()->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(createTempSymbol(node->getCondition()->getType()));
- }
- else if (loopType == ELoopFor)
- {
- // Move the loop condition inside the loop.
- // Transform:
- // for (init; expr; exprB) { body; }
- // into
- // {
- // init;
- // bool s0 = expr;
- // while (s0) {
- // { body; }
- // exprB;
- // s0 = expr;
- // }
- // }
- TIntermBlock *loopScope = new TIntermBlock();
- TIntermSequence *loopScopeSequence = loopScope->getSequence();
-
- // Insert "init;"
- if (node->getInit())
- {
- loopScopeSequence->push_back(node->getInit());
- }
-
- // Insert "bool s0 = expr;" if applicable, "bool s0 = true;" otherwise
- TIntermTyped *conditionInitializer = nullptr;
- if (node->getCondition())
- {
- conditionInitializer = node->getCondition()->deepCopy();
- }
- else
- {
- conditionInitializer = CreateBoolNode(true);
- }
- loopScopeSequence->push_back(createTempInitDeclaration(conditionInitializer));
-
- // Insert "{ body; }" in the while loop
- TIntermBlock *whileLoopBody = new TIntermBlock();
- if (node->getBody())
- {
- whileLoopBody->getSequence()->push_back(node->getBody());
- }
- // Insert "exprB;" in the while loop
- if (node->getExpression())
- {
- whileLoopBody->getSequence()->push_back(node->getExpression());
- }
- // Insert "s0 = expr;" in the while loop
- if (node->getCondition())
- {
- whileLoopBody->getSequence()->push_back(
- createTempAssignment(node->getCondition()->deepCopy()));
- }
-
- // Create "while(s0) { whileLoopBody }"
- TIntermLoop *whileLoop = new TIntermLoop(
- ELoopWhile, nullptr, createTempSymbol(conditionInitializer->getType()), 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);
-}
-
-} // namespace
-
-void SimplifyLoopConditions(TIntermNode *root,
- unsigned int conditionsToSimplifyMask,
- TSymbolTable *symbolTable,
- int shaderVersion)
-{
- SimplifyLoopConditionsTraverser traverser(conditionsToSimplifyMask, symbolTable, shaderVersion);
- root->traverse(&traverser);
- traverser.updateTree();
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h b/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h
deleted file mode 100644
index d8f95cd2c8..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// Copyright (c) 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_SIMPLIFYLOOPCONDITIONS_H_
-#define COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_
-
-namespace sh
-{
-class TIntermNode;
-class TSymbolTable;
-
-void SimplifyLoopConditions(TIntermNode *root,
- unsigned int conditionsToSimplify,
- TSymbolTable *symbolTable,
- int shaderVersion);
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp b/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp
deleted file mode 100644
index 5df3154560..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-//
-// Copyright (c) 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/SplitSequenceOperator.h"
-
-#include "compiler/translator/IntermNodePatternMatcher.h"
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser
-{
- public:
- SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask,
- TSymbolTable *symbolTable,
- int shaderVersion);
-
- 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,
- int shaderVersion)
- : TLValueTrackingTraverser(true, false, true, symbolTable, shaderVersion),
- mFoundExpressionToSplit(false),
- mInsideSequenceOperator(0),
- mPatternToSplitMatcher(patternsToSplitMask)
-{
-}
-
-void SplitSequenceOperatorTraverser::nextIteration()
-{
- mFoundExpressionToSplit = false;
- mInsideSequenceOperator = 0;
- nextTemporaryId();
-}
-
-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
-
-void SplitSequenceOperator(TIntermNode *root,
- int patternsToSplitMask,
- TSymbolTable *symbolTable,
- int shaderVersion)
-{
- SplitSequenceOperatorTraverser traverser(patternsToSplitMask, symbolTable, shaderVersion);
- // Separate one expression at a time, and reset the traverser between iterations.
- do
- {
- traverser.nextIteration();
- root->traverse(&traverser);
- if (traverser.foundExpressionToSplit())
- traverser.updateTree();
- } while (traverser.foundExpressionToSplit());
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h b/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h
deleted file mode 100644
index 8f1a766775..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Copyright (c) 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_SPLITSEQUENCEOPERATOR_H_
-#define COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_
-
-namespace sh
-{
-
-class TIntermNode;
-class TSymbolTable;
-
-void SplitSequenceOperator(TIntermNode *root,
- int patternsToSplitMask,
- TSymbolTable *symbolTable,
- int shaderVersion);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp
deleted file mode 100644
index 61a9431ceb..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp
+++ /dev/null
@@ -1,594 +0,0 @@
-//
-// Copyright (c) 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/util.h"
-#include "compiler/translator/UtilsHLSL.h"
-
-namespace sh
-{
-
-namespace
-{
-
-TString Define(const TStructure &structure,
- bool useHLSLRowMajorPacking,
- bool useStd140Packing,
- Std140PaddingHelper *padHelper)
-{
- const TFieldList &fields = structure.fields();
- const bool isNameless = (structure.name() == "");
- const TString &structName =
- QualifiedStructNameString(structure, useHLSLRowMajorPacking, useStd140Packing);
- const TString declareString = (isNameless ? "struct" : "struct " + structName);
-
- TString string;
- string += declareString +
- "\n"
- "{\n";
-
- for (const TField *field : fields)
- {
- const TType &fieldType = *field->type();
- if (!IsSampler(fieldType.getBasicType()))
- {
- const TStructure *fieldStruct = fieldType.getStruct();
- const TString &fieldTypeString =
- fieldStruct ? QualifiedStructNameString(*fieldStruct, useHLSLRowMajorPacking,
- useStd140Packing)
- : TypeString(fieldType);
-
- if (padHelper)
- {
- string += padHelper->prePaddingString(fieldType);
- }
-
- string += " " + fieldTypeString + " " + DecorateField(field->name(), structure) +
- ArrayString(fieldType) + ";\n";
-
- if (padHelper)
- {
- string += padHelper->postPaddingString(fieldType, useHLSLRowMajorPacking);
- }
- }
- }
-
- // 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<TType> &parameters)
-{
- TString parameterList;
- for (size_t parameter = 0u; parameter < parameters.size(); parameter++)
- {
- const TType &paramType = parameters[parameter];
-
- parameterList += TypeString(paramType) + " x" + str(parameter) + ArrayString(paramType);
-
- if (parameter < parameters.size() - 1u)
- {
- parameterList += ", ";
- }
- }
- return parameterList;
-}
-
-} // anonymous namespace
-
-Std140PaddingHelper::Std140PaddingHelper(const std::map<TString, int> &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)
-{
- if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray())
- {
- // 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)
- {
- // no padding needed, HLSL will align the field to a new register
- mElementIndex = 0;
- return 0;
- }
-
- if (mElementIndex + numComponents > 4)
- {
- // 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 paddingOffset = (mElementIndex % alignment);
- const int paddingCount = (paddingOffset != 0 ? (alignment - paddingOffset) : 0);
-
- mElementIndex += paddingCount;
- mElementIndex += numComponents;
- mElementIndex %= 4;
-
- return paddingCount;
-}
-
-TString Std140PaddingHelper::prePaddingString(const TType &type)
-{
- int paddingCount = prePadding(type);
-
- TString padding;
-
- for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++)
- {
- padding += " float pad_" + next() + ";\n";
- }
-
- return padding;
-}
-
-TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRowMajorPacking)
-{
- if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct)
- {
- 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);
- 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)
-{
- if (useStd140Packing)
- {
- Std140PaddingHelper padHelper = getPaddingHelper();
- return Define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper);
- }
- else
- {
- return Define(structure, useHLSLRowMajorPacking, useStd140Packing, nullptr);
- }
-}
-
-TString StructureHLSL::defineNameless(const TStructure &structure)
-{
- return Define(structure, 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);
-
- 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) +
- "#pragma pack_matrix(column_major)\n";
-
- TString std140String = defineQualified(structure, false, true);
- TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" +
- defineQualified(structure, true, true) +
- "#pragma pack_matrix(column_major)\n";
-
- mStructDeclarations.push_back(structString);
- mStructDeclarations.push_back(rowMajorString);
- mStructDeclarations.push_back(std140String);
- mStructDeclarations.push_back(std140RowMajorString);
- 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<TType> 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<TType> ctorParameters;
- for (auto parameter : *parameters)
- {
- const TType &paramType = 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)
- {
- int rows = ctorType.getRows();
- int cols = ctorType.getCols();
- const TType &parameter = ctorParameters[0];
-
- if (parameter.isScalar())
- {
- for (int col = 0; col < cols; col++)
- {
- for (int 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 (int col = 0; col < cols; col++)
- {
- for (int 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 &parameter = 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<size_t>(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())
- {
- int column = 0;
- while (remainingComponents > 0 && column < parameter.getCols())
- {
- constructor += "[" + str(column) + "]";
-
- if (remainingComponents < static_cast<size_t>(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());
- }
-
- // Add remaining element index to the global map, for use with nested structs in standard
- // layouts
- const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking, true);
- mStd140StructElementIndexes[structName] = padHelper.elementIndex();
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h
deleted file mode 100644
index daced8f8d1..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h
+++ /dev/null
@@ -1,98 +0,0 @@
-//
-// Copyright (c) 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 <set>
-
-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<TString, int> &structElementIndexes,
- unsigned int *uniqueCounter);
- Std140PaddingHelper(const Std140PaddingHelper &other);
- Std140PaddingHelper &operator=(const Std140PaddingHelper &other);
-
- int elementIndex() const { return mElementIndex; }
- int prePadding(const TType &type);
- TString prePaddingString(const TType &type);
- TString postPaddingString(const TType &type, bool useHLSLRowMajorPacking);
-
- private:
- TString next();
-
- unsigned *mPaddingCounter;
- int mElementIndex;
- const std::map<TString, int> *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<TString, int> 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<TString, TStructProperties *> 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<TString> StructDeclarations;
- StructDeclarations mStructDeclarations;
-
- typedef std::set<TString> BuiltInConstructors;
- BuiltInConstructors mBuiltInConstructors;
-
- void storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking);
- TString defineQualified(const TStructure &structure,
- bool useHLSLRowMajorPacking,
- bool useStd140Packing);
- DefinedStructs::iterator defineVariants(const TStructure &structure, const TString &name);
-};
-}
-
-#endif // COMPILER_TRANSLATOR_STRUCTUREHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp
deleted file mode 100644
index 6c38461469..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp
+++ /dev/null
@@ -1,622 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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 "compiler/translator/Cache.h"
-#include "compiler/translator/IntermNode.h"
-
-#include <stdio.h>
-#include <algorithm>
-
-namespace sh
-{
-
-namespace
-{
-
-static const char kFunctionMangledNameSeparator = '(';
-
-} // anonymous namespace
-
-TSymbol::TSymbol(TSymbolTable *symbolTable, const TString *n)
- : uniqueId(symbolTable->nextUniqueId()), name(n), extension(TExtension::UNDEFINED)
-{
-}
-
-//
-// Functions have buried pointers to delete.
-//
-TFunction::~TFunction()
-{
- clearParameters();
-}
-
-void TFunction::clearParameters()
-{
- for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
- delete (*i).type;
- parameters.clear();
- mangledName = nullptr;
-}
-
-void TFunction::swapParameters(const TFunction &parametersSource)
-{
- clearParameters();
- for (auto parameter : parametersSource.parameters)
- {
- addParameter(parameter);
- }
-}
-
-const TString *TFunction::buildMangledName() const
-{
- std::string newName = getName().c_str();
- newName += kFunctionMangledNameSeparator;
-
- for (const auto &p : parameters)
- {
- newName += p.type->getMangledName();
- }
- return NewPoolTString(newName.c_str());
-}
-
-const TString &TFunction::GetMangledNameFromCall(const TString &functionName,
- const TIntermSequence &arguments)
-{
- std::string newName = functionName.c_str();
- newName += kFunctionMangledNameSeparator;
-
- for (TIntermNode *argument : arguments)
- {
- newName += argument->getAsTyped()->getType().getMangledName();
- }
- return *NewPoolTString(newName.c_str());
-}
-
-//
-// Symbol table levels are a map of pointers to symbols that have to be deleted.
-//
-TSymbolTableLevel::~TSymbolTableLevel()
-{
- for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
- delete (*it).second;
-}
-
-bool TSymbolTableLevel::insert(TSymbol *symbol)
-{
- // returning true means symbol was added to the table
- tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
-
- return result.second;
-}
-
-bool TSymbolTableLevel::insertUnmangled(TFunction *function)
-{
- // returning true means symbol was added to the table
- tInsertResult result = level.insert(tLevelPair(function->getName(), function));
-
- return result.second;
-}
-
-TSymbol *TSymbolTableLevel::find(const TString &name) const
-{
- tLevel::const_iterator it = level.find(name);
- if (it == level.end())
- return 0;
- else
- return (*it).second;
-}
-
-TSymbol *TSymbolTable::find(const TString &name,
- int shaderVersion,
- bool *builtIn,
- bool *sameScope) const
-{
- int level = currentLevel();
- TSymbol *symbol;
-
- do
- {
- if (level == GLSL_BUILTINS)
- level--;
- if (level == ESSL3_1_BUILTINS && shaderVersion != 310)
- level--;
- if (level == ESSL3_BUILTINS && shaderVersion < 300)
- level--;
- if (level == ESSL1_BUILTINS && shaderVersion != 100)
- level--;
-
- symbol = table[level]->find(name);
- } while (symbol == 0 && --level >= 0);
-
- if (builtIn)
- *builtIn = (level <= LAST_BUILTIN_LEVEL);
- if (sameScope)
- *sameScope = (level == currentLevel());
-
- return symbol;
-}
-
-TSymbol *TSymbolTable::findGlobal(const TString &name) const
-{
- ASSERT(table.size() > GLOBAL_LEVEL);
- return table[GLOBAL_LEVEL]->find(name);
-}
-
-TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) const
-{
- return findBuiltIn(name, shaderVersion, false);
-}
-
-TSymbol *TSymbolTable::findBuiltIn(const TString &name,
- int shaderVersion,
- bool includeGLSLBuiltins) const
-{
- for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--)
- {
- if (level == GLSL_BUILTINS && !includeGLSLBuiltins)
- level--;
- if (level == ESSL3_1_BUILTINS && shaderVersion != 310)
- level--;
- if (level == ESSL3_BUILTINS && shaderVersion < 300)
- level--;
- if (level == ESSL1_BUILTINS && shaderVersion != 100)
- level--;
-
- TSymbol *symbol = table[level]->find(name);
-
- if (symbol)
- return symbol;
- }
-
- return nullptr;
-}
-
-TSymbolTable::~TSymbolTable()
-{
- while (table.size() > 0)
- pop();
-}
-
-bool IsGenType(const TType *type)
-{
- if (type)
- {
- TBasicType basicType = type->getBasicType();
- return basicType == EbtGenType || basicType == EbtGenIType || basicType == EbtGenUType ||
- basicType == EbtGenBType;
- }
-
- return false;
-}
-
-bool IsVecType(const TType *type)
-{
- if (type)
- {
- TBasicType basicType = type->getBasicType();
- return basicType == EbtVec || basicType == EbtIVec || basicType == EbtUVec ||
- basicType == EbtBVec;
- }
-
- return false;
-}
-
-const TType *SpecificType(const TType *type, int size)
-{
- ASSERT(size >= 1 && size <= 4);
-
- if (!type)
- {
- return nullptr;
- }
-
- ASSERT(!IsVecType(type));
-
- switch (type->getBasicType())
- {
- case EbtGenType:
- return TCache::getType(EbtFloat, type->getQualifier(),
- static_cast<unsigned char>(size));
- case EbtGenIType:
- return TCache::getType(EbtInt, type->getQualifier(), static_cast<unsigned char>(size));
- case EbtGenUType:
- return TCache::getType(EbtUInt, type->getQualifier(), static_cast<unsigned char>(size));
- case EbtGenBType:
- return TCache::getType(EbtBool, type->getQualifier(), static_cast<unsigned char>(size));
- default:
- return type;
- }
-}
-
-const TType *VectorType(const TType *type, int size)
-{
- ASSERT(size >= 2 && size <= 4);
-
- if (!type)
- {
- return nullptr;
- }
-
- ASSERT(!IsGenType(type));
-
- switch (type->getBasicType())
- {
- case EbtVec:
- return TCache::getType(EbtFloat, static_cast<unsigned char>(size));
- case EbtIVec:
- return TCache::getType(EbtInt, static_cast<unsigned char>(size));
- case EbtUVec:
- return TCache::getType(EbtUInt, static_cast<unsigned char>(size));
- case EbtBVec:
- return TCache::getType(EbtBool, static_cast<unsigned char>(size));
- default:
- return type;
- }
-}
-
-TVariable *TSymbolTable::declareVariable(const TString *name, const TType &type)
-{
- return insertVariable(currentLevel(), name, type);
-}
-
-TVariable *TSymbolTable::declareStructType(TStructure *str)
-{
- return insertStructType(currentLevel(), str);
-}
-
-TInterfaceBlockName *TSymbolTable::declareInterfaceBlockName(const TString *name)
-{
- TInterfaceBlockName *blockNameSymbol = new TInterfaceBlockName(this, name);
- if (insert(currentLevel(), blockNameSymbol))
- {
- return blockNameSymbol;
- }
- return nullptr;
-}
-
-TInterfaceBlockName *TSymbolTable::insertInterfaceBlockNameExt(ESymbolLevel level,
- TExtension ext,
- const TString *name)
-{
- TInterfaceBlockName *blockNameSymbol = new TInterfaceBlockName(this, name);
- if (insert(level, ext, blockNameSymbol))
- {
- return blockNameSymbol;
- }
- return nullptr;
-}
-
-TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const char *name, const TType &type)
-{
- return insertVariable(level, NewPoolTString(name), type);
-}
-
-TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const TString *name, const TType &type)
-{
- TVariable *var = new TVariable(this, name, type);
- if (insert(level, var))
- {
- // Do lazy initialization for struct types, so we allocate to the current scope.
- if (var->getType().getBasicType() == EbtStruct)
- {
- var->getType().realize();
- }
- return var;
- }
- return nullptr;
-}
-
-TVariable *TSymbolTable::insertVariableExt(ESymbolLevel level,
- TExtension ext,
- const char *name,
- const TType &type)
-{
- TVariable *var = new TVariable(this, NewPoolTString(name), type);
- if (insert(level, ext, var))
- {
- if (var->getType().getBasicType() == EbtStruct)
- {
- var->getType().realize();
- }
- return var;
- }
- return nullptr;
-}
-
-TVariable *TSymbolTable::insertStructType(ESymbolLevel level, TStructure *str)
-{
- TVariable *var = new TVariable(this, &str->name(), TType(str), true);
- if (insert(level, var))
- {
- var->getType().realize();
- return var;
- }
- return nullptr;
-}
-
-void TSymbolTable::insertBuiltIn(ESymbolLevel level,
- TOperator op,
- TExtension ext,
- const TType *rvalue,
- const char *name,
- const TType *ptype1,
- const TType *ptype2,
- const TType *ptype3,
- const TType *ptype4,
- const TType *ptype5)
-{
- if (ptype1->getBasicType() == EbtGSampler2D)
- {
- insertUnmangledBuiltInName(name, level);
- bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
- TCache::getType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
- TCache::getType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
- TCache::getType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5);
- }
- else if (ptype1->getBasicType() == EbtGSampler3D)
- {
- insertUnmangledBuiltInName(name, level);
- bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
- TCache::getType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
- TCache::getType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
- TCache::getType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5);
- }
- else if (ptype1->getBasicType() == EbtGSamplerCube)
- {
- insertUnmangledBuiltInName(name, level);
- bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
- TCache::getType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
- TCache::getType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
- TCache::getType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5);
- }
- else if (ptype1->getBasicType() == EbtGSampler2DArray)
- {
- insertUnmangledBuiltInName(name, level);
- bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
- TCache::getType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
- TCache::getType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
- TCache::getType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5);
- }
- else if (ptype1->getBasicType() == EbtGSampler2DMS)
- {
- insertUnmangledBuiltInName(name, level);
- bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
- TCache::getType(EbtSampler2DMS), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
- TCache::getType(EbtISampler2DMS), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
- TCache::getType(EbtUSampler2DMS), ptype2, ptype3, ptype4, ptype5);
- }
- else if (IsGImage(ptype1->getBasicType()))
- {
- insertUnmangledBuiltInName(name, level);
-
- const TType *floatType = TCache::getType(EbtFloat, 4);
- const TType *intType = TCache::getType(EbtInt, 4);
- const TType *unsignedType = TCache::getType(EbtUInt, 4);
-
- const TType *floatImage =
- TCache::getType(convertGImageToFloatImage(ptype1->getBasicType()));
- const TType *intImage = TCache::getType(convertGImageToIntImage(ptype1->getBasicType()));
- const TType *unsignedImage =
- TCache::getType(convertGImageToUnsignedImage(ptype1->getBasicType()));
-
- // GLSL ES 3.10, Revision 4, 8.12 Image Functions
- if (rvalue->getBasicType() == EbtGVec4)
- {
- // imageLoad
- insertBuiltIn(level, floatType, name, floatImage, ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, intType, name, intImage, ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, unsignedType, name, unsignedImage, ptype2, ptype3, ptype4, ptype5);
- }
- else if (rvalue->getBasicType() == EbtVoid)
- {
- // imageStore
- insertBuiltIn(level, rvalue, name, floatImage, ptype2, floatType, ptype4, ptype5);
- insertBuiltIn(level, rvalue, name, intImage, ptype2, intType, ptype4, ptype5);
- insertBuiltIn(level, rvalue, name, unsignedImage, ptype2, unsignedType, ptype4, ptype5);
- }
- else
- {
- // imageSize
- insertBuiltIn(level, rvalue, name, floatImage, ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, rvalue, name, intImage, ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, rvalue, name, unsignedImage, ptype2, ptype3, ptype4, ptype5);
- }
- }
- else if (IsGenType(rvalue) || IsGenType(ptype1) || IsGenType(ptype2) || IsGenType(ptype3) ||
- IsGenType(ptype4))
- {
- ASSERT(!ptype5);
- insertUnmangledBuiltInName(name, level);
- insertBuiltIn(level, op, ext, SpecificType(rvalue, 1), name, SpecificType(ptype1, 1),
- SpecificType(ptype2, 1), SpecificType(ptype3, 1), SpecificType(ptype4, 1));
- insertBuiltIn(level, op, ext, SpecificType(rvalue, 2), name, SpecificType(ptype1, 2),
- SpecificType(ptype2, 2), SpecificType(ptype3, 2), SpecificType(ptype4, 2));
- insertBuiltIn(level, op, ext, SpecificType(rvalue, 3), name, SpecificType(ptype1, 3),
- SpecificType(ptype2, 3), SpecificType(ptype3, 3), SpecificType(ptype4, 3));
- insertBuiltIn(level, op, ext, SpecificType(rvalue, 4), name, SpecificType(ptype1, 4),
- SpecificType(ptype2, 4), SpecificType(ptype3, 4), SpecificType(ptype4, 4));
- }
- else if (IsVecType(rvalue) || IsVecType(ptype1) || IsVecType(ptype2) || IsVecType(ptype3))
- {
- ASSERT(!ptype4 && !ptype5);
- insertUnmangledBuiltInName(name, level);
- insertBuiltIn(level, op, ext, VectorType(rvalue, 2), name, VectorType(ptype1, 2),
- VectorType(ptype2, 2), VectorType(ptype3, 2));
- insertBuiltIn(level, op, ext, VectorType(rvalue, 3), name, VectorType(ptype1, 3),
- VectorType(ptype2, 3), VectorType(ptype3, 3));
- insertBuiltIn(level, op, ext, VectorType(rvalue, 4), name, VectorType(ptype1, 4),
- VectorType(ptype2, 4), VectorType(ptype3, 4));
- }
- else
- {
- TFunction *function = new TFunction(this, NewPoolTString(name), rvalue, op, ext);
-
- function->addParameter(TConstParameter(ptype1));
-
- if (ptype2)
- {
- function->addParameter(TConstParameter(ptype2));
- }
-
- if (ptype3)
- {
- function->addParameter(TConstParameter(ptype3));
- }
-
- if (ptype4)
- {
- function->addParameter(TConstParameter(ptype4));
- }
-
- if (ptype5)
- {
- function->addParameter(TConstParameter(ptype5));
- }
-
- ASSERT(hasUnmangledBuiltInAtLevel(name, level));
- insert(level, function);
- }
-}
-
-void TSymbolTable::insertBuiltInOp(ESymbolLevel level,
- TOperator op,
- const TType *rvalue,
- const TType *ptype1,
- const TType *ptype2,
- const TType *ptype3,
- const TType *ptype4,
- const TType *ptype5)
-{
- const char *name = GetOperatorString(op);
- ASSERT(strlen(name) > 0);
- insertUnmangledBuiltInName(name, level);
- insertBuiltIn(level, op, TExtension::UNDEFINED, rvalue, name, ptype1, ptype2, ptype3, ptype4,
- ptype5);
-}
-
-void TSymbolTable::insertBuiltInOp(ESymbolLevel level,
- TOperator op,
- TExtension ext,
- const TType *rvalue,
- const TType *ptype1,
- const TType *ptype2,
- const TType *ptype3,
- const TType *ptype4,
- const TType *ptype5)
-{
- const char *name = GetOperatorString(op);
- insertUnmangledBuiltInName(name, level);
- insertBuiltIn(level, op, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
-}
-
-void TSymbolTable::insertBuiltInFunctionNoParameters(ESymbolLevel level,
- TOperator op,
- const TType *rvalue,
- const char *name)
-{
- insertUnmangledBuiltInName(name, level);
- insert(level, new TFunction(this, NewPoolTString(name), rvalue, op));
-}
-
-void TSymbolTable::insertBuiltInFunctionNoParametersExt(ESymbolLevel level,
- TExtension ext,
- TOperator op,
- const TType *rvalue,
- const char *name)
-{
- insertUnmangledBuiltInName(name, level);
- insert(level, new TFunction(this, NewPoolTString(name), rvalue, op, ext));
-}
-
-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<int>(precisionStack.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 = precisionStack[level]->find(baseType);
- if (it != precisionStack[level]->end())
- {
- prec = (*it).second;
- break;
- }
- level--;
- }
- return prec;
-}
-
-void TSymbolTable::insertUnmangledBuiltInName(const char *name, ESymbolLevel level)
-{
- ASSERT(level >= 0 && level < static_cast<ESymbolLevel>(table.size()));
- table[level]->insertUnmangledBuiltInName(std::string(name));
-}
-
-bool TSymbolTable::hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level)
-{
- ASSERT(level >= 0 && level < static_cast<ESymbolLevel>(table.size()));
- return table[level]->hasUnmangledBuiltIn(std::string(name));
-}
-
-bool TSymbolTable::hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion)
-{
- ASSERT(static_cast<ESymbolLevel>(table.size()) > LAST_BUILTIN_LEVEL);
-
- for (int level = LAST_BUILTIN_LEVEL; level >= 0; --level)
- {
- if (level == ESSL3_1_BUILTINS && shaderVersion != 310)
- {
- --level;
- }
- if (level == ESSL3_BUILTINS && shaderVersion < 300)
- {
- --level;
- }
- if (level == ESSL1_BUILTINS && shaderVersion != 100)
- {
- --level;
- }
-
- if (table[level]->hasUnmangledBuiltIn(name))
- {
- return true;
- }
- }
- return false;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
deleted file mode 100644
index 5d792ec188..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
+++ /dev/null
@@ -1,545 +0,0 @@
-//
-// Copyright (c) 2002-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_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 <array>
-#include <assert.h>
-#include <set>
-
-#include "common/angleutils.h"
-#include "compiler/translator/ExtensionBehavior.h"
-#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/SymbolUniqueId.h"
-
-namespace sh
-{
-
-// Symbol base class. (Can build functions or variables out of these...)
-class TSymbol : angle::NonCopyable
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- TSymbol(TSymbolTable *symbolTable, const TString *n);
-
- virtual ~TSymbol()
- {
- // don't delete name, it's from the pool
- }
-
- const TString &getName() const { return *name; }
- virtual const TString &getMangledName() const { return getName(); }
- virtual bool isFunction() const { return false; }
- virtual bool isVariable() const { return false; }
- const TSymbolUniqueId &getUniqueId() const { return uniqueId; }
- void relateToExtension(TExtension ext) { extension = ext; }
- TExtension getExtension() const { return extension; }
-
- private:
- const TSymbolUniqueId uniqueId;
- const TString *name;
- TExtension extension;
-};
-
-// Variable, meaning a symbol that's not a function.
-//
-// May store the value of a constant variable of any type (float, int, bool or struct).
-class TVariable : public TSymbol
-{
- public:
- ~TVariable() override {}
- bool isVariable() const override { return true; }
- TType &getType() { return type; }
- const TType &getType() const { return type; }
- bool isUserType() const { return userType; }
- void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); }
-
- const TConstantUnion *getConstPointer() const { return unionArray; }
-
- void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; }
-
- private:
- friend class TSymbolTable;
-
- TVariable(TSymbolTable *symbolTable,
- const TString *name,
- const TType &t,
- bool isUserTypeDefinition = false)
- : TSymbol(symbolTable, name), type(t), userType(isUserTypeDefinition), unionArray(0)
- {
- }
-
- TType type;
-
- // Set to true if this represents a struct type, as opposed to a variable.
- bool userType;
-
- // we are assuming that Pool Allocator will free the memory
- // allocated to unionArray when this object is destroyed.
- const TConstantUnion *unionArray;
-};
-
-// Immutable version of TParameter.
-struct TConstParameter
-{
- TConstParameter() : name(nullptr), type(nullptr) {}
- explicit TConstParameter(const TString *n) : name(n), type(nullptr) {}
- explicit TConstParameter(const TType *t) : name(nullptr), type(t) {}
- TConstParameter(const TString *n, const TType *t) : name(n), type(t) {}
-
- // Both constructor arguments must be const.
- TConstParameter(TString *n, TType *t) = delete;
- TConstParameter(const TString *n, TType *t) = delete;
- TConstParameter(TString *n, const TType *t) = delete;
-
- const TString *const name;
- const TType *const type;
-};
-
-// The function sub-class of symbols and the parser will need to
-// share this definition of a function parameter.
-struct TParameter
-{
- // Destructively converts to TConstParameter.
- // This method resets name and type to nullptrs to make sure
- // their content cannot be modified after the call.
- TConstParameter turnToConst()
- {
- const TString *constName = name;
- const TType *constType = type;
- name = nullptr;
- type = nullptr;
- return TConstParameter(constName, constType);
- }
-
- const TString *name;
- TType *type;
-};
-
-// The function sub-class of a symbol.
-class TFunction : public TSymbol
-{
- public:
- TFunction(TSymbolTable *symbolTable,
- const TString *name,
- const TType *retType,
- TOperator tOp = EOpNull,
- TExtension ext = TExtension::UNDEFINED)
- : TSymbol(symbolTable, name),
- returnType(retType),
- mangledName(nullptr),
- op(tOp),
- defined(false),
- mHasPrototypeDeclaration(false)
- {
- relateToExtension(ext);
- }
- ~TFunction() override;
- bool isFunction() const override { return true; }
-
- void addParameter(const TConstParameter &p)
- {
- parameters.push_back(p);
- mangledName = nullptr;
- }
-
- void swapParameters(const TFunction &parametersSource);
-
- const TString &getMangledName() const override
- {
- if (mangledName == nullptr)
- {
- mangledName = buildMangledName();
- }
- return *mangledName;
- }
-
- static const TString &GetMangledNameFromCall(const TString &functionName,
- const TIntermSequence &arguments);
-
- const TType &getReturnType() const { return *returnType; }
-
- TOperator getBuiltInOp() const { return op; }
-
- void setDefined() { defined = true; }
- bool isDefined() { return defined; }
- void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; }
- bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; }
-
- size_t getParamCount() const { return parameters.size(); }
- const TConstParameter &getParam(size_t i) const { return parameters[i]; }
-
- private:
- void clearParameters();
-
- const TString *buildMangledName() const;
-
- typedef TVector<TConstParameter> TParamList;
- TParamList parameters;
- const TType *returnType;
- mutable const TString *mangledName;
- TOperator op;
- bool defined;
- bool mHasPrototypeDeclaration;
-};
-
-// Interface block name sub-symbol
-class TInterfaceBlockName : public TSymbol
-{
- public:
- virtual ~TInterfaceBlockName() {}
-
- private:
- friend class TSymbolTable;
- TInterfaceBlockName(TSymbolTable *symbolTable, const TString *name) : TSymbol(symbolTable, name)
- {
- }
-};
-
-class TSymbolTableLevel
-{
- public:
- typedef TUnorderedMap<TString, TSymbol *> tLevel;
- typedef tLevel::const_iterator const_iterator;
- typedef const tLevel::value_type tLevelPair;
- typedef std::pair<tLevel::iterator, bool> tInsertResult;
-
- TSymbolTableLevel() : mGlobalInvariant(false) {}
- ~TSymbolTableLevel();
-
- bool insert(TSymbol *symbol);
-
- // Insert a function using its unmangled name as the key.
- bool insertUnmangled(TFunction *function);
-
- TSymbol *find(const TString &name) const;
-
- void addInvariantVarying(const std::string &name) { mInvariantVaryings.insert(name); }
-
- bool isVaryingInvariant(const std::string &name)
- {
- return (mGlobalInvariant || mInvariantVaryings.count(name) > 0);
- }
-
- void setGlobalInvariant(bool invariant) { mGlobalInvariant = invariant; }
-
- void insertUnmangledBuiltInName(const std::string &name)
- {
- mUnmangledBuiltInNames.insert(name);
- }
-
- bool hasUnmangledBuiltIn(const std::string &name)
- {
- return mUnmangledBuiltInNames.count(name) > 0;
- }
-
- protected:
- tLevel level;
- std::set<std::string> mInvariantVaryings;
- bool mGlobalInvariant;
-
- private:
- std::set<std::string> mUnmangledBuiltInNames;
-};
-
-// Define ESymbolLevel as int rather than an enum since level can go
-// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the
-// compiler optimizes the >= of the last element to ==.
-typedef int ESymbolLevel;
-const int COMMON_BUILTINS = 0;
-const int ESSL1_BUILTINS = 1;
-const int ESSL3_BUILTINS = 2;
-const int ESSL3_1_BUILTINS = 3;
-// GLSL_BUILTINS are desktop GLSL builtins that don't exist in ESSL but are used to implement
-// features in ANGLE's GLSL backend. They're not visible to the parser.
-const int GLSL_BUILTINS = 4;
-const int LAST_BUILTIN_LEVEL = GLSL_BUILTINS;
-const int GLOBAL_LEVEL = 5;
-
-class TSymbolTable : angle::NonCopyable
-{
- public:
- TSymbolTable() : mUniqueIdCounter(0), mEmptySymbolId(this)
- {
- // The symbol table cannot be used until push() is called, but
- // the lack of an initial call to push() can be used to detect
- // that the symbol table has not been preloaded with built-ins.
- }
-
- ~TSymbolTable();
-
- // When the symbol table is initialized with the built-ins, there should
- // 'push' calls, so that built-ins are at level 0 and the shader
- // globals are at level 1.
- bool isEmpty() const { return table.empty(); }
- bool atBuiltInLevel() const { return currentLevel() <= LAST_BUILTIN_LEVEL; }
- bool atGlobalLevel() const { return currentLevel() == GLOBAL_LEVEL; }
- void push()
- {
- table.push_back(new TSymbolTableLevel);
- precisionStack.push_back(new PrecisionStackLevel);
- }
-
- void pop()
- {
- delete table.back();
- table.pop_back();
-
- delete precisionStack.back();
- precisionStack.pop_back();
- }
-
- // The declare* entry points are used when parsing and declare symbols at the current scope.
- // They return the created symbol in case the declaration was successful, and nullptr if the
- // declaration failed due to redefinition.
- TVariable *declareVariable(const TString *name, const TType &type);
- TVariable *declareStructType(TStructure *str);
- TInterfaceBlockName *declareInterfaceBlockName(const TString *name);
-
- // The insert* entry points are used when initializing the symbol table with built-ins.
- // They return the created symbol in case the declaration was successful, and nullptr if the
- // declaration failed due to redefinition.
- TVariable *insertVariable(ESymbolLevel level, const char *name, const TType &type);
- TVariable *insertVariableExt(ESymbolLevel level,
- TExtension ext,
- const char *name,
- const TType &type);
- TVariable *insertStructType(ESymbolLevel level, TStructure *str);
- TInterfaceBlockName *insertInterfaceBlockNameExt(ESymbolLevel level,
- TExtension ext,
- const TString *name);
-
- bool insertConstInt(ESymbolLevel level, const char *name, int value, TPrecision precision)
- {
- TVariable *constant =
- new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 1));
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray[0].setIConst(value);
- constant->shareConstPointer(unionArray);
- return insert(level, constant);
- }
-
- bool insertConstIntExt(ESymbolLevel level,
- TExtension ext,
- const char *name,
- int value,
- TPrecision precision)
- {
- TVariable *constant =
- new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 1));
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray[0].setIConst(value);
- constant->shareConstPointer(unionArray);
- return insert(level, ext, constant);
- }
-
- bool insertConstIvec3(ESymbolLevel level,
- const char *name,
- const std::array<int, 3> &values,
- TPrecision precision)
- {
- TVariable *constantIvec3 =
- new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 3));
-
- TConstantUnion *unionArray = new TConstantUnion[3];
- for (size_t index = 0u; index < 3u; ++index)
- {
- unionArray[index].setIConst(values[index]);
- }
- constantIvec3->shareConstPointer(unionArray);
-
- return insert(level, constantIvec3);
- }
-
- void insertBuiltIn(ESymbolLevel level,
- TOperator op,
- TExtension ext,
- const TType *rvalue,
- const char *name,
- const TType *ptype1,
- const TType *ptype2 = 0,
- const TType *ptype3 = 0,
- const TType *ptype4 = 0,
- const TType *ptype5 = 0);
-
- void insertBuiltIn(ESymbolLevel level,
- const TType *rvalue,
- const char *name,
- const TType *ptype1,
- const TType *ptype2 = 0,
- const TType *ptype3 = 0,
- const TType *ptype4 = 0,
- const TType *ptype5 = 0)
- {
- insertUnmangledBuiltInName(name, level);
- insertBuiltIn(level, EOpNull, TExtension::UNDEFINED, rvalue, name, ptype1, ptype2, ptype3,
- ptype4, ptype5);
- }
-
- void insertBuiltIn(ESymbolLevel level,
- TExtension ext,
- const TType *rvalue,
- const char *name,
- const TType *ptype1,
- const TType *ptype2 = 0,
- const TType *ptype3 = 0,
- const TType *ptype4 = 0,
- const TType *ptype5 = 0)
- {
- insertUnmangledBuiltInName(name, level);
- insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
- }
-
- void insertBuiltInOp(ESymbolLevel level,
- TOperator op,
- const TType *rvalue,
- const TType *ptype1,
- const TType *ptype2 = 0,
- const TType *ptype3 = 0,
- const TType *ptype4 = 0,
- const TType *ptype5 = 0);
-
- void insertBuiltInOp(ESymbolLevel level,
- TOperator op,
- TExtension ext,
- const TType *rvalue,
- const TType *ptype1,
- const TType *ptype2 = 0,
- const TType *ptype3 = 0,
- const TType *ptype4 = 0,
- const TType *ptype5 = 0);
-
- void insertBuiltInFunctionNoParameters(ESymbolLevel level,
- TOperator op,
- const TType *rvalue,
- const char *name);
-
- void insertBuiltInFunctionNoParametersExt(ESymbolLevel level,
- TExtension ext,
- TOperator op,
- const TType *rvalue,
- const char *name);
-
- TSymbol *find(const TString &name,
- int shaderVersion,
- bool *builtIn = nullptr,
- bool *sameScope = nullptr) const;
-
- TSymbol *findGlobal(const TString &name) const;
-
- TSymbol *findBuiltIn(const TString &name, int shaderVersion) const;
-
- TSymbol *findBuiltIn(const TString &name, int shaderVersion, bool includeGLSLBuiltins) const;
-
- TSymbolTableLevel *getOuterLevel()
- {
- assert(currentLevel() >= 1);
- return table[currentLevel() - 1];
- }
-
- void setDefaultPrecision(TBasicType type, TPrecision prec)
- {
- int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
- // Uses map operator [], overwrites the current value
- (*precisionStack[indexOfLastElement])[type] = 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 std::string &originalName)
- {
- ASSERT(atGlobalLevel());
- table[currentLevel()]->addInvariantVarying(originalName);
- }
- // 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 std::string &originalName) const
- {
- ASSERT(atGlobalLevel());
- return table[currentLevel()]->isVaryingInvariant(originalName);
- }
-
- void setGlobalInvariant(bool invariant)
- {
- ASSERT(atGlobalLevel());
- table[currentLevel()]->setGlobalInvariant(invariant);
- }
-
- const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); }
-
- // The empty symbol id is shared between all empty string ("") symbols. They are used in the
- // AST for unused function parameters and struct type declarations that don't declare a
- // variable, for example.
- const TSymbolUniqueId &getEmptySymbolId() { return mEmptySymbolId; }
-
- // Checks whether there is a built-in accessible by a shader with the specified version.
- bool hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion);
-
- private:
- friend class TSymbolUniqueId;
- int nextUniqueIdValue() { return ++mUniqueIdCounter; }
-
- ESymbolLevel currentLevel() const { return static_cast<ESymbolLevel>(table.size() - 1); }
-
- TVariable *insertVariable(ESymbolLevel level, const TString *name, const TType &type);
-
- bool insert(ESymbolLevel level, TSymbol *symbol) { return table[level]->insert(symbol); }
-
- bool insert(ESymbolLevel level, TExtension ext, TSymbol *symbol)
- {
- symbol->relateToExtension(ext);
- return table[level]->insert(symbol);
- }
-
- // Used to insert unmangled functions to check redeclaration of built-ins in ESSL 3.00 and
- // above.
- void insertUnmangledBuiltInName(const char *name, ESymbolLevel level);
-
- bool hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level);
-
- std::vector<TSymbolTableLevel *> table;
- typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
- std::vector<PrecisionStackLevel *> precisionStack;
-
- int mUniqueIdCounter;
-
- const TSymbolUniqueId mEmptySymbolId;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp
deleted file mode 100644
index 2a68ae3e70..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Copyright (c) 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.getUniqueId().get())
-{
-}
-
-int TSymbolUniqueId::get() const
-{
- return mId;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h b/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h
deleted file mode 100644
index 4bd5604246..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Copyright (c) 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(TSymbolTable *symbolTable);
- explicit TSymbolUniqueId(const TSymbol &symbol);
- TSymbolUniqueId(const TSymbolUniqueId &) = default;
- TSymbolUniqueId &operator=(const TSymbolUniqueId &) = default;
-
- int get() const;
-
- private:
- int mId;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp
deleted file mode 100644
index d2b65a6c56..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp
+++ /dev/null
@@ -1,1322 +0,0 @@
-//
-// Copyright (c) 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/UtilsHLSL.h"
-
-namespace sh
-{
-
-namespace
-{
-
-void OutputIntTexCoordWrap(TInfoSinkBase &out,
- const char *wrapMode,
- const char *size,
- const TString &texCoord,
- const TString &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";
-
- // CLAMP_TO_EDGE
- out << "if (" << wrapMode << " == 1)\n";
- out << "{\n";
- out << " " << texCoordOutName << " = clamp(int(floor(" << size << " * " << texCoordOutName
- << "Offset)), 0, int(" << size << ") - 1);\n";
- out << "}\n";
-
- // MIRRORED_REPEAT
- out << "else if (" << wrapMode << " == 3)\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,
- TString *texCoordX,
- TString *texCoordY,
- TString *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 = "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 = "tiy";
-
- if (IsSamplerArray(textureFunction.sampler))
- {
- *texCoordZ = "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 = "tiz";
- }
-}
-
-void OutputHLSL4SampleFunctionPrefix(TInfoSinkBase &out,
- const TextureFunctionHLSL::TextureFunction &textureFunction,
- const TString &textureReference,
- const TString &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)
-{
- if (IsIntegerSampler(textureFunction.sampler) ||
- textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH)
- {
- switch (hlslCoords)
- {
- case 2:
- if (textureFunction.sampler == EbtSampler2DMS ||
- textureFunction.sampler == EbtISampler2DMS ||
- textureFunction.sampler == EbtUSampler2DMS)
- return "int2";
- else
- return "int3";
- case 3:
- return "int4";
- default:
- UNREACHABLE();
- }
- }
- else
- {
- switch (hlslCoords)
- {
- 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 EbtSampler2D:
- case EbtSamplerExternalOES:
- case EbtSampler2DMS:
- 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
- {
- switch (textureFunction.sampler)
- {
- case EbtSampler2D:
- return 2;
- case EbtSampler2DMS:
- return 2;
- case EbtSampler3D:
- return 3;
- case EbtSamplerCube:
- return 3;
- case EbtSampler2DArray:
- return 3;
- case EbtSamplerExternalOES:
- return 2;
- case EbtISampler2D:
- return 2;
- case EbtISampler2DMS:
- return 2;
- case EbtISampler3D:
- return 3;
- case EbtISamplerCube:
- return 3;
- case EbtISampler2DArray:
- return 3;
- case EbtUSampler2D:
- return 2;
- case EbtUSampler2DMS:
- return 2;
- case EbtUSampler3D:
- return 3;
- case EbtUSamplerCube:
- return 3;
- case EbtUSampler2DArray:
- return 3;
- case EbtSampler2DShadow:
- return 2;
- case EbtSamplerCubeShadow:
- return 3;
- case EbtSampler2DArrayShadow:
- return 3;
- default:
- UNREACHABLE();
- }
- }
- 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 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 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:
- 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 (textureFunction.sampler == EbtSampler2DMS ||
- textureFunction.sampler == EbtISampler2DMS ||
- textureFunction.sampler == EbtUSampler2DMS)
- out << ", int index";
- else
- out << ", int mip";
- break;
- case TextureFunctionHLSL::TextureFunction::GRAD:
- break;
- default:
- UNREACHABLE();
- }
-
- 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 EbtSampler2DMS:
- case EbtISampler2DMS:
- case EbtUSampler2DMS:
- case EbtSamplerExternalOES:
- out << ", int2 offset";
- break;
- default:
- UNREACHABLE();
- }
- }
-
- if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS ||
- textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
- {
- out << ", float bias";
- }
-}
-
-void GetTextureReference(TInfoSinkBase &out,
- const TextureFunctionHLSL::TextureFunction &textureFunction,
- const ShShaderOutput outputType,
- TString *textureReference,
- TString *samplerReference)
-{
- if (outputType == SH_HLSL_4_1_OUTPUT)
- {
- TString suffix = TextureGroupSuffix(textureFunction.sampler);
- if (TextureGroup(textureFunction.sampler) == HLSL_TEXTURE_2D)
- {
- *textureReference = TString("textures") + suffix + "[samplerIndex]";
- *samplerReference = TString("samplers") + suffix + "[samplerIndex]";
- }
- else
- {
- out << " const uint textureIndex = samplerIndex - textureIndexOffset" << suffix
- << ";\n";
- *textureReference = TString("textures") + suffix + "[textureIndex]";
- out << " const uint samplerArrayIndex = samplerIndex - samplerIndexOffset" << suffix
- << ";\n";
- *samplerReference = TString("samplers") + suffix + "[samplerArrayIndex]";
- }
- }
- else
- {
- *textureReference = "x";
- *samplerReference = "s";
- }
-}
-
-void OutputTextureSizeFunctionBody(TInfoSinkBase &out,
- const TextureFunctionHLSL::TextureFunction &textureFunction,
- const TString &textureReference,
- bool getDimensionsIgnoresBaseLevel)
-{
- if (IsSampler2DMS(textureFunction.sampler))
- {
- out << " uint width; uint height; uint samples;\n"
- << " " << textureReference << ".GetDimensions(width, height, samples);\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();
- }
-
- if (strcmp(textureFunction.getReturnType(), "int3") == 0)
- {
- out << " return int3(width, height, depth);\n";
- }
- else
- {
- out << " return int2(width, height);\n";
- }
-}
-
-void ProjectTextureCoordinates(const TextureFunctionHLSL::TextureFunction &textureFunction,
- TString *texCoordX,
- TString *texCoordY,
- TString *texCoordZ)
-{
- if (textureFunction.proj)
- {
- TString proj("");
- switch (textureFunction.coords)
- {
- case 3:
- proj = " / t.z";
- break;
- case 4:
- proj = " / t.w";
- break;
- default:
- UNREACHABLE();
- }
- *texCoordX = "(" + *texCoordX + proj + ")";
- *texCoordY = "(" + *texCoordY + proj + ")";
- *texCoordZ = "(" + *texCoordZ + proj + ")";
- }
-}
-
-void OutputIntegerTextureSampleFunctionComputations(
- TInfoSinkBase &out,
- const TextureFunctionHLSL::TextureFunction &textureFunction,
- const ShShaderOutput outputType,
- const TString &textureReference,
- TString *texCoordX,
- TString *texCoordY,
- TString *texCoordZ)
-{
- if (!IsIntegerSampler(textureFunction.sampler))
- {
- return;
- }
- if (IsSamplerCube(textureFunction.sampler))
- {
- out << " float width; float height; float layers; float levels;\n";
-
- out << " uint mip = 0;\n";
-
- out << " " << textureReference
- << ".GetDimensions(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 << " 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)
- {
- out << " float2 tSized = float2(t.x * width, t.y * height);\n"
- " float2 dx = ddx(tSized);\n"
- " float2 dy = ddy(tSized);\n"
- " float lod = 0.5f * log2(max(dot(dx, dx), dot(dy, dy)));\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(mip, width, height, layers, levels);\n";
- }
-
- // Convert from normalized floating-point to integer
- *texCoordX = "int(floor(width * frac(" + *texCoordX + ")))";
- *texCoordY = "int(floor(height * frac(" + *texCoordY + ")))";
- *texCoordZ = "face";
- }
- else if (textureFunction.method != TextureFunctionHLSL::TextureFunction::FETCH)
- {
- if (IsSampler2D(textureFunction.sampler))
- {
- 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(0, 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(mip, width, height, layers, levels);\n";
- }
- else
- {
- 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(0, 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(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(0, 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(mip, width, height, depth, levels);\n";
- }
- else
- UNREACHABLE();
-
- OutputIntTexCoordWraps(out, textureFunction, texCoordX, texCoordY, texCoordZ);
- }
-}
-
-void OutputTextureSampleFunctionReturnStatement(
- TInfoSinkBase &out,
- const TextureFunctionHLSL::TextureFunction &textureFunction,
- const ShShaderOutput outputType,
- const TString &textureReference,
- const TString &samplerReference,
- const TString &texCoordX,
- const TString &texCoordY,
- const TString &texCoordZ)
-{
- out << " return ";
-
- // HLSL intrinsic
- if (outputType == SH_HLSL_3_0_OUTPUT)
- {
- switch (textureFunction.sampler)
- {
- case EbtSampler2D:
- 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) << "(" << texCoordX << ", "
- << texCoordY;
-
- 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 (textureFunction.sampler == EbtSampler2DMS ||
- textureFunction.sampler == EbtISampler2DMS ||
- textureFunction.sampler == EbtUSampler2DMS)
- out << "), index";
- 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
-
-TString TextureFunctionHLSL::TextureFunction::name() const
-{
- TString name = "gl_texture";
-
- // 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 += TextureTypeSuffix(this->sampler);
-
- 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;
- 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:
- return "int2";
- case EbtSampler3D:
- case EbtISampler3D:
- case EbtUSampler3D:
- case EbtSampler2DArray:
- case EbtISampler2DArray:
- case EbtUSampler2DArray:
- case EbtSampler2DArrayShadow:
- return "int3";
- default:
- UNREACHABLE();
- }
- }
- else // Sampling function
- {
- switch (sampler)
- {
- case EbtSampler2D:
- case EbtSampler2DMS:
- case EbtSampler3D:
- case EbtSamplerCube:
- case EbtSampler2DArray:
- case EbtSamplerExternalOES:
- return "float4";
- case EbtISampler2D:
- case EbtISampler2DMS:
- case EbtISampler3D:
- case EbtISamplerCube:
- case EbtISampler2DArray:
- return "int4";
- case EbtUSampler2D:
- case EbtUSampler2DMS:
- case EbtUSampler3D:
- case EbtUSamplerCube:
- case EbtUSampler2DArray:
- return "uint4";
- case EbtSampler2DShadow:
- case EbtSamplerCubeShadow:
- case EbtSampler2DArrayShadow:
- 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);
-}
-
-TString TextureFunctionHLSL::useTextureFunction(const TString &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
- 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)
- {
- 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.
- TString textureReference;
- TString samplerReference;
- GetTextureReference(out, textureFunction, outputType, &textureReference, &samplerReference);
-
- if (textureFunction.method == TextureFunction::SIZE)
- {
- OutputTextureSizeFunctionBody(out, textureFunction, textureReference,
- getDimensionsIgnoresBaseLevel);
- }
- else
- {
- TString texCoordX("t.x");
- TString texCoordY("t.y");
- TString texCoordZ("t.z");
- ProjectTextureCoordinates(textureFunction, &texCoordX, &texCoordY, &texCoordZ);
- OutputIntegerTextureSampleFunctionComputations(out, textureFunction, outputType,
- textureReference, &texCoordX, &texCoordY,
- &texCoordZ);
- OutputTextureSampleFunctionReturnStatement(out, textureFunction, outputType,
- textureReference, samplerReference,
- texCoordX, texCoordY, texCoordZ);
- }
-
- out << "}\n"
- "\n";
- }
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h b/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h
deleted file mode 100644
index 68bf8c0898..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// Copyright (c) 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 <set>
-
-#include "compiler/translator/BaseTypes.h"
-#include "compiler/translator/Common.h"
-#include "compiler/translator/InfoSink.h"
-#include "GLSLANG/ShaderLang.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
- };
-
- TString 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.
- TString useTextureFunction(const TString &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<TextureFunction> TextureFunctionSet;
- TextureFunctionSet mUsesTexture;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp
deleted file mode 100644
index 23c967f944..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#include "compiler/translator/TranslatorESSL.h"
-
-#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
-#include "compiler/translator/EmulatePrecision.h"
-#include "compiler/translator/RecordConstantPrecision.h"
-#include "compiler/translator/OutputESSL.h"
-#include "angle_gl.h"
-
-namespace sh
-{
-
-TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec)
- : TCompiler(type, spec, SH_ESSL_OUTPUT)
-{
-}
-
-void TranslatorESSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
- ShCompileOptions compileOptions)
-{
- if (compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION)
- {
- InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu);
- }
-}
-
-void TranslatorESSL::translate(TIntermBlock *root,
- ShCompileOptions compileOptions,
- PerformanceDiagnostics * /*perfDiagnostics*/)
-{
- TInfoSinkBase &sink = getInfoSink().obj;
-
- int shaderVer = getShaderVersion();
- 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(compileOptions);
-
- bool precisionEmulation =
- getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
-
- if (precisionEmulation)
- {
- EmulatePrecision emulatePrecision(&getSymbolTable(), shaderVer);
- root->traverse(&emulatePrecision);
- emulatePrecision.updateTree();
- emulatePrecision.writeEmulationHelpers(sink, shaderVer, SH_ESSL_OUTPUT);
- }
-
- RecordConstantPrecision(root, &getSymbolTable());
-
- // 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";
- }
-
- // Write array bounds clamping emulation if needed.
- getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
-
- if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared())
- {
- const sh::WorkGroupSize &localSize = getComputeShaderLocalSize();
- sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1]
- << ", local_size_z=" << localSize[2] << ") in;\n";
- }
-
- if (getShaderType() == GL_GEOMETRY_SHADER_OES)
- {
- WriteGeometryShaderLayoutQualifiers(
- sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(),
- getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices());
- }
-
- // Write translated shader.
- TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(),
- &getSymbolTable(), getShaderType(), shaderVer, precisionEmulation,
- compileOptions);
-
- if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM)
- {
- TName uniformName(TString("ViewID_OVR"));
- uniformName.setInternal(true);
- sink << "highp uniform int " << outputESSL.hashName(uniformName) << ";\n";
- }
-
- root->traverse(&outputESSL);
-}
-
-bool TranslatorESSL::shouldFlattenPragmaStdglInvariantAll()
-{
- // Not necessary when translating to ESSL.
- return false;
-}
-
-void TranslatorESSL::writeExtensionBehavior(ShCompileOptions compileOptions)
-{
- TInfoSinkBase &sink = getInfoSink().obj;
- const TExtensionBehavior &extBehavior = getExtensionBehavior();
- const bool isMultiviewExtEmulated =
- (compileOptions &
- (SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM | SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
- SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER)) != 0u;
- for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); iter != extBehavior.end();
- ++iter)
- {
- if (iter->second != EBhUndefined)
- {
- const bool isMultiview = (iter->first == TExtension::OVR_multiview);
- 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 && isMultiviewExtEmulated)
- {
- if (getShaderType() == GL_VERTEX_SHADER &&
- (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u)
- {
- // Emit the NV_viewport_array2 extension 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.
- sink << "#extension GL_NV_viewport_array2 : require\n";
- }
- }
- else if (iter->first == TExtension::OES_geometry_shader)
- {
- sink << "#ifdef GL_OES_geometry_shader\n"
- << "#extension GL_OES_geometry_shader : " << GetBehaviorString(iter->second)
- << "\n"
- << "#elif defined GL_EXT_geometry_shader\n"
- << "#extension GL_EXT_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
- {
- sink << "#extension " << GetExtensionNameString(iter->first) << " : "
- << GetBehaviorString(iter->second) << "\n";
- }
- }
- }
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h
deleted file mode 100644
index 24dc738513..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Copyright (c) 2002-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_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,
- ShCompileOptions compileOptions) override;
-
- void translate(TIntermBlock *root,
- ShCompileOptions compileOptions,
- PerformanceDiagnostics *perfDiagnostics) override;
- bool shouldFlattenPragmaStdglInvariantAll() override;
-
- private:
- void writeExtensionBehavior(ShCompileOptions compileOptions);
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_TRANSLATORESSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
deleted file mode 100644
index a14e69e5d5..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
+++ /dev/null
@@ -1,339 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#include "compiler/translator/TranslatorGLSL.h"
-
-#include "angle_gl.h"
-#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
-#include "compiler/translator/EmulatePrecision.h"
-#include "compiler/translator/ExtensionGLSL.h"
-#include "compiler/translator/OutputGLSL.h"
-#include "compiler/translator/RewriteTexelFetchOffset.h"
-#include "compiler/translator/RewriteUnaryMinusOperatorFloat.h"
-#include "compiler/translator/VersionGLSL.h"
-
-namespace sh
-{
-
-TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
- : TCompiler(type, spec, output)
-{
-}
-
-void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
- ShCompileOptions compileOptions)
-{
- if (compileOptions & SH_EMULATE_ABS_INT_FUNCTION)
- {
- InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(emu, getShaderType());
- }
-
- if (compileOptions & SH_EMULATE_ISNAN_FLOAT_FUNCTION)
- {
- InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(emu, getShaderVersion());
- }
-
- if (compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION)
- {
- InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu);
- }
-
- int targetGLSLVersion = ShaderOutputTypeToGLSLVersion(getOutputType());
- InitBuiltInFunctionEmulatorForGLSLMissingFunctions(emu, getShaderType(), targetGLSLVersion);
-}
-
-void TranslatorGLSL::translate(TIntermBlock *root,
- 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(compileOptions);
-
- // 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 & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) != 0 &&
- 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 & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0)
- {
- sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion());
- }
-
- if ((compileOptions & SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR) != 0)
- {
- sh::RewriteUnaryMinusOperatorFloat(root);
- }
-
- bool precisionEmulation =
- getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
-
- if (precisionEmulation)
- {
- EmulatePrecision emulatePrecision(&getSymbolTable(), getShaderVersion());
- root->traverse(&emulatePrecision);
- emulatePrecision.updateTree();
- emulatePrecision.writeEmulationHelpers(sink, getShaderVersion(), getOutputType());
- }
-
- // 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";
- }
-
- // Write array bounds clamping emulation if needed.
- getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
-
- // 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 : outputVariables)
- {
- 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 angle_SecondaryFragColor;\n";
- }
- if (hasGLSecondaryFragData)
- {
- sink << "out vec4 angle_SecondaryFragData[" << getResources().MaxDualSourceDrawBuffers
- << "];\n";
- }
- }
-
- if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared())
- {
- const sh::WorkGroupSize &localSize = getComputeShaderLocalSize();
- sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1]
- << ", local_size_z=" << localSize[2] << ") in;\n";
- }
-
- if (getShaderType() == GL_GEOMETRY_SHADER_OES)
- {
- WriteGeometryShaderLayoutQualifiers(
- sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(),
- getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices());
- }
-
- // Write translated shader.
- TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(),
- &getSymbolTable(), getShaderType(), getShaderVersion(), getOutputType(),
- compileOptions);
-
- if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM)
- {
- TName uniformName(TString("ViewID_OVR"));
- uniformName.setInternal(true);
- sink << "uniform int " << outputGLSL.hashName(uniformName) << ";\n";
- }
-
- root->traverse(&outputGLSL);
-}
-
-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(ShCompileOptions compileOptions)
-{
- return (compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) ||
- 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, ShCompileOptions compileOptions)
-{
- 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::OES_geometry_shader)
- {
- sink << "#extension GL_ARB_geometry_shader4 : " << GetBehaviorString(iter.second)
- << "\n";
- }
- }
-
- const bool isMultiview = (iter.first == TExtension::OVR_multiview);
- if (isMultiview && getShaderType() == GL_VERTEX_SHADER &&
- (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u)
- {
- // Emit the NV_viewport_array2 extension 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.
- sink << "#extension GL_NV_viewport_array2 : require\n";
- }
- }
-
- // 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";
- }
-
- 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/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h
deleted file mode 100644
index 982d0e5ddc..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Copyright (c) 2002-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_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,
- ShCompileOptions compileOptions) override;
-
- void translate(TIntermBlock *root,
- ShCompileOptions compileOptions,
- PerformanceDiagnostics *perfDiagnostics) override;
- bool shouldFlattenPragmaStdglInvariantAll() override;
- bool shouldCollectVariables(ShCompileOptions compileOptions) override;
-
- private:
- void writeVersion(TIntermNode *root);
- void writeExtensionBehavior(TIntermNode *root, ShCompileOptions compileOptions);
- void conditionallyOutputInvariantDeclaration(const char *builtinVaryingName);
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_TRANSLATORGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp
deleted file mode 100644
index 091a649cfc..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#include "compiler/translator/TranslatorHLSL.h"
-
-#include "compiler/translator/AddDefaultReturnStatements.h"
-#include "compiler/translator/ArrayReturnValueToOutParameter.h"
-#include "compiler/translator/BreakVariableAliasingInInnerLoops.h"
-#include "compiler/translator/EmulatePrecision.h"
-#include "compiler/translator/ExpandIntegerPowExpressions.h"
-#include "compiler/translator/IntermNodePatternMatcher.h"
-#include "compiler/translator/OutputHLSL.h"
-#include "compiler/translator/RemoveDynamicIndexing.h"
-#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h"
-#include "compiler/translator/RewriteElseBlocks.h"
-#include "compiler/translator/RewriteTexelFetchOffset.h"
-#include "compiler/translator/RewriteUnaryMinusOperatorInt.h"
-#include "compiler/translator/SeparateArrayInitialization.h"
-#include "compiler/translator/SeparateDeclarations.h"
-#include "compiler/translator/SeparateExpressionsReturningArrays.h"
-#include "compiler/translator/SimplifyLoopConditions.h"
-#include "compiler/translator/SplitSequenceOperator.h"
-#include "compiler/translator/UnfoldShortCircuitToIf.h"
-#include "compiler/translator/WrapSwitchStatementsInBlocks.h"
-
-namespace sh
-{
-
-TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
- : TCompiler(type, spec, output)
-{
-}
-
-void TranslatorHLSL::translate(TIntermBlock *root,
- ShCompileOptions compileOptions,
- PerformanceDiagnostics *perfDiagnostics)
-{
- const ShBuiltInResources &resources = getResources();
- int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
-
- sh::AddDefaultReturnStatements(root);
-
- // 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().
- SimplifyLoopConditions(root,
- IntermNodePatternMatcher::kExpressionReturningArray |
- IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
- IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue,
- &getSymbolTable(), getShaderVersion());
-
- SplitSequenceOperator(root,
- IntermNodePatternMatcher::kExpressionReturningArray |
- IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
- IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue,
- &getSymbolTable(), getShaderVersion());
-
- // Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf.
- UnfoldShortCircuitToIf(root, &getSymbolTable());
-
- SeparateExpressionsReturningArrays(root, &getSymbolTable());
-
- // Note that SeparateDeclarations needs to be run before SeparateArrayInitialization.
- SeparateArrayInitialization(root);
-
- // 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.
- ArrayReturnValueToOutParameter(root, &getSymbolTable());
-
- if (!shouldRunLoopAndIndexingValidation(compileOptions))
- {
- // HLSL doesn't support dynamic indexing of vectors and matrices.
- RemoveDynamicIndexing(root, &getSymbolTable(), getShaderVersion(), perfDiagnostics);
- }
-
- // 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)
- {
- sh::RewriteElseBlocks(root, &getSymbolTable());
- }
-
- // 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.
- sh::BreakVariableAliasingInInnerLoops(root);
-
- // WrapSwitchStatementsInBlocks should be called after any AST transformations that might
- // introduce variable declarations inside the main scope of any switch statement.
- if (WrapSwitchStatementsInBlocks(root))
- {
- // The WrapSwitchStatementsInBlocks step might introduce new no-op cases to the end of
- // switch statements, so make sure to clean up the AST.
- RemoveNoOpCasesFromEndOfSwitchStatements(root, &getSymbolTable());
- }
-
- bool precisionEmulation =
- getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
-
- if (precisionEmulation)
- {
- EmulatePrecision emulatePrecision(&getSymbolTable(), getShaderVersion());
- root->traverse(&emulatePrecision);
- emulatePrecision.updateTree();
- emulatePrecision.writeEmulationHelpers(getInfoSink().obj, getShaderVersion(),
- getOutputType());
- }
-
- if ((compileOptions & SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS) != 0)
- {
- sh::ExpandIntegerPowExpressions(root, &getSymbolTable());
- }
-
- if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0)
- {
- sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion());
- }
-
- if (((compileOptions & SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR) != 0) &&
- getShaderType() == GL_VERTEX_SHADER)
- {
- sh::RewriteUnaryMinusOperatorInt(root);
- }
-
- sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
- getSourcePath(), getOutputType(), numRenderTargets, getUniforms(),
- compileOptions, &getSymbolTable(), perfDiagnostics);
-
- outputHLSL.output(root, getInfoSink().obj);
-
- mUniformBlockRegisterMap = outputHLSL.getUniformBlockRegisterMap();
- mUniformRegisterMap = outputHLSL.getUniformRegisterMap();
-}
-
-bool TranslatorHLSL::shouldFlattenPragmaStdglInvariantAll()
-{
- // Not necessary when translating to HLSL.
- return false;
-}
-
-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<std::string, unsigned int> *TranslatorHLSL::getUniformRegisterMap() const
-{
- return &mUniformRegisterMap;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h
deleted file mode 100644
index d7005a603c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#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 hasUniformBlock(const std::string &interfaceBlockName) const;
- unsigned int getUniformBlockRegister(const std::string &interfaceBlockName) const;
-
- const std::map<std::string, unsigned int> *getUniformRegisterMap() const;
-
- protected:
- void translate(TIntermBlock *root,
- ShCompileOptions compileOptions,
- PerformanceDiagnostics *perfDiagnostics) override;
- bool shouldFlattenPragmaStdglInvariantAll() override;
-
- // collectVariables needs to be run always so registers can be assigned.
- bool shouldCollectVariables(ShCompileOptions compileOptions) override { return true; }
-
- std::map<std::string, unsigned int> mUniformBlockRegisterMap;
- std::map<std::string, unsigned int> mUniformRegisterMap;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_TRANSLATORHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp
deleted file mode 100644
index 0fe2a21f90..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-//
-// Copyright (c) 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.
-// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side).
-// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt
-//
-
-#include "compiler/translator/TranslatorVulkan.h"
-
-#include "angle_gl.h"
-#include "common/utilities.h"
-#include "compiler/translator/OutputVulkanGLSL.h"
-#include "compiler/translator/util.h"
-
-namespace sh
-{
-
-class DeclareDefaultUniformsTraverser : public TIntermTraverser
-{
- public:
- DeclareDefaultUniformsTraverser(TInfoSinkBase *sink,
- ShHashFunction64 hashFunction,
- NameMap *nameMap)
- : TIntermTraverser(true, true, true),
- mSink(sink),
- mHashFunction(hashFunction),
- mNameMap(nameMap),
- mInDefaultUniform(false)
- {
- }
-
- bool visitDeclaration(Visit visit, TIntermDeclaration *node) override
- {
- const TIntermSequence &sequence = *(node->getSequence());
-
- // TODO(jmadill): Compound declarations.
- ASSERT(sequence.size() == 1);
-
- TIntermTyped *variable = sequence.front()->getAsTyped();
- const TType &type = variable->getType();
- bool isUniform = (type.getQualifier() == EvqUniform) && !IsOpaqueType(type.getBasicType());
-
- if (visit == PreVisit)
- {
- if (isUniform)
- {
- (*mSink) << " " << GetTypeName(type, mHashFunction, mNameMap) << " ";
- mInDefaultUniform = true;
- }
- }
- else if (visit == InVisit)
- {
- mInDefaultUniform = isUniform;
- }
- else if (visit == PostVisit)
- {
- if (isUniform)
- {
- (*mSink) << ";\n";
-
- // Remove the uniform declaration from the tree so it isn't parsed again.
- TIntermSequence emptyReplacement;
- mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(
- getParentNode()->getAsBlock(), node, emptyReplacement));
- }
-
- mInDefaultUniform = false;
- }
- return true;
- }
-
- void visitSymbol(TIntermSymbol *symbol) override
- {
- if (mInDefaultUniform)
- {
- const TName &name = symbol->getName();
- ASSERT(name.getString().substr(0, 3) != "gl_");
- (*mSink) << HashName(name, mHashFunction, mNameMap);
- }
- }
-
- private:
- TInfoSinkBase *mSink;
- ShHashFunction64 mHashFunction;
- NameMap *mNameMap;
- bool mInDefaultUniform;
-};
-
-TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec)
- : TCompiler(type, spec, SH_GLSL_450_CORE_OUTPUT)
-{
-}
-
-void TranslatorVulkan::translate(TIntermBlock *root,
- ShCompileOptions compileOptions,
- PerformanceDiagnostics * /*perfDiagnostics*/)
-{
- TInfoSinkBase &sink = getInfoSink().obj;
-
- sink << "#version 450 core\n";
-
- // Write out default uniforms into a uniform block assigned to a specific set/binding.
- int defaultUniformCount = 0;
- for (const auto &uniform : getUniforms())
- {
- if (!uniform.isBuiltIn() && uniform.staticUse && !gl::IsOpaqueType(uniform.type))
- {
- ++defaultUniformCount;
- }
- }
-
- if (defaultUniformCount > 0)
- {
- sink << "\nlayout(@@ DEFAULT-UNIFORMS-SET-BINDING @@) uniform defaultUniforms\n{\n";
-
- DeclareDefaultUniformsTraverser defaultTraverser(&sink, getHashFunction(), &getNameMap());
- root->traverse(&defaultTraverser);
- defaultTraverser.updateTree();
-
- sink << "};\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)
- {
- bool hasGLFragColor = false;
- bool hasGLFragData = false;
-
- for (const auto &outputVar : outputVariables)
- {
- if (outputVar.name == "gl_FragColor")
- {
- ASSERT(!hasGLFragColor);
- hasGLFragColor = true;
- continue;
- }
- else if (outputVar.name == "gl_FragData")
- {
- ASSERT(!hasGLFragData);
- hasGLFragData = true;
- continue;
- }
- }
- ASSERT(!(hasGLFragColor && hasGLFragData));
- if (hasGLFragColor)
- {
- sink << "layout(location = 0) out vec4 webgl_FragColor;\n";
- }
- if (hasGLFragData)
- {
- sink << "layout(location = 0) out vec4 webgl_FragData[gl_MaxDrawBuffers];\n";
- }
- }
-
- // Write translated shader.
- TOutputVulkanGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(),
- getNameMap(), &getSymbolTable(), getShaderType(),
- getShaderVersion(), getOutputType(), compileOptions);
- root->traverse(&outputGLSL);
-}
-
-bool TranslatorVulkan::shouldFlattenPragmaStdglInvariantAll()
-{
- // Not necessary.
- return false;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h b/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h
deleted file mode 100644
index ef67b15ae1..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Copyright (c) 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.
-// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side).
-// 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 TranslatorVulkan : public TCompiler
-{
- public:
- TranslatorVulkan(sh::GLenum type, ShShaderSpec spec);
-
- protected:
- void translate(TIntermBlock *root,
- ShCompileOptions compileOptions,
- PerformanceDiagnostics *perfDiagnostics) override;
- bool shouldFlattenPragmaStdglInvariantAll() override;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Types.cpp b/src/3rdparty/angle/src/compiler/translator/Types.cpp
deleted file mode 100644
index 530ffe3aeb..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Types.cpp
+++ /dev/null
@@ -1,1072 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#if defined(_MSC_VER)
-#pragma warning(disable : 4718)
-#endif
-
-#include "compiler/translator/Types.h"
-#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/SymbolTable.h"
-
-#include <algorithm>
-#include <climits>
-
-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 EbtISampler2D:
- return "isampler2D";
- case EbtISampler3D:
- return "isampler3D";
- case EbtISamplerCube:
- return "isamplerCube";
- case EbtISampler2DArray:
- return "isampler2DArray";
- case EbtISampler2DMS:
- return "isampler2DMS";
- case EbtUSampler2D:
- return "usampler2D";
- case EbtUSampler3D:
- return "usampler3D";
- case EbtUSamplerCube:
- return "usamplerCube";
- case EbtUSampler2DArray:
- return "usampler2DArray";
- case EbtUSampler2DMS:
- return "usampler2DMS";
- case EbtSampler2DShadow:
- return "sampler2DShadow";
- case EbtSamplerCubeShadow:
- return "samplerCubeShadow";
- case EbtSampler2DArrayShadow:
- return "sampler2DArrayShadow";
- 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 EbtAtomicCounter:
- return "atomic_uint";
- default:
- UNREACHABLE();
- return "unknown type";
- }
-}
-
-// TType implementation.
-TType::TType()
- : type(EbtVoid),
- precision(EbpUndefined),
- qualifier(EvqGlobal),
- invariant(false),
- memoryQualifier(TMemoryQualifier::Create()),
- layoutQualifier(TLayoutQualifier::Create()),
- primarySize(0),
- secondarySize(0),
- mArraySizes(nullptr),
- mInterfaceBlock(nullptr),
- mStructure(nullptr),
- mIsStructSpecifier(false),
- mMangledName(nullptr)
-{
-}
-
-TType::TType(TBasicType t, unsigned char ps, unsigned char ss)
- : type(t),
- precision(EbpUndefined),
- qualifier(EvqGlobal),
- invariant(false),
- memoryQualifier(TMemoryQualifier::Create()),
- layoutQualifier(TLayoutQualifier::Create()),
- primarySize(ps),
- secondarySize(ss),
- mArraySizes(nullptr),
- mInterfaceBlock(nullptr),
- mStructure(nullptr),
- mIsStructSpecifier(false),
- mMangledName(nullptr)
-{
-}
-
-TType::TType(TBasicType t, TPrecision p, TQualifier q, unsigned char ps, unsigned char ss)
- : type(t),
- precision(p),
- qualifier(q),
- invariant(false),
- memoryQualifier(TMemoryQualifier::Create()),
- layoutQualifier(TLayoutQualifier::Create()),
- primarySize(ps),
- secondarySize(ss),
- mArraySizes(nullptr),
- mInterfaceBlock(nullptr),
- mStructure(nullptr),
- mIsStructSpecifier(false),
- mMangledName(nullptr)
-{
-}
-
-TType::TType(const TPublicType &p)
- : type(p.getBasicType()),
- precision(p.precision),
- qualifier(p.qualifier),
- invariant(p.invariant),
- memoryQualifier(p.memoryQualifier),
- layoutQualifier(p.layoutQualifier),
- primarySize(p.getPrimarySize()),
- secondarySize(p.getSecondarySize()),
- mArraySizes(nullptr),
- mInterfaceBlock(nullptr),
- mStructure(nullptr),
- mIsStructSpecifier(false),
- mMangledName(nullptr)
-{
- ASSERT(primarySize <= 4);
- ASSERT(secondarySize <= 4);
- if (p.isArray())
- {
- mArraySizes = new TVector<unsigned int>(*p.arraySizes);
- }
- if (p.getUserDef())
- {
- mStructure = p.getUserDef();
- mIsStructSpecifier = p.isStructSpecifier();
- }
-}
-
-TType::TType(TStructure *userDef)
- : type(EbtStruct),
- precision(EbpUndefined),
- qualifier(EvqTemporary),
- invariant(false),
- memoryQualifier(TMemoryQualifier::Create()),
- layoutQualifier(TLayoutQualifier::Create()),
- primarySize(1),
- secondarySize(1),
- mArraySizes(nullptr),
- mInterfaceBlock(nullptr),
- mStructure(userDef),
- mIsStructSpecifier(false),
- mMangledName(nullptr)
-{
-}
-
-TType::TType(TInterfaceBlock *interfaceBlockIn,
- TQualifier qualifierIn,
- TLayoutQualifier layoutQualifierIn)
- : type(EbtInterfaceBlock),
- precision(EbpUndefined),
- qualifier(qualifierIn),
- invariant(false),
- memoryQualifier(TMemoryQualifier::Create()),
- layoutQualifier(layoutQualifierIn),
- primarySize(1),
- secondarySize(1),
- mArraySizes(nullptr),
- mInterfaceBlock(interfaceBlockIn),
- mStructure(0),
- mIsStructSpecifier(false),
- mMangledName(nullptr)
-{
-}
-
-TType::TType(const TType &t)
- : type(t.type),
- precision(t.precision),
- qualifier(t.qualifier),
- invariant(t.invariant),
- memoryQualifier(t.memoryQualifier),
- layoutQualifier(t.layoutQualifier),
- primarySize(t.primarySize),
- secondarySize(t.secondarySize),
- mArraySizes(t.mArraySizes ? new TVector<unsigned int>(*t.mArraySizes) : nullptr),
- mInterfaceBlock(t.mInterfaceBlock),
- mStructure(t.mStructure),
- mIsStructSpecifier(t.mIsStructSpecifier),
- mMangledName(t.mMangledName)
-{
-}
-
-TType &TType::operator=(const TType &t)
-{
- type = t.type;
- precision = t.precision;
- qualifier = t.qualifier;
- invariant = t.invariant;
- memoryQualifier = t.memoryQualifier;
- layoutQualifier = t.layoutQualifier;
- primarySize = t.primarySize;
- secondarySize = t.secondarySize;
- mArraySizes = t.mArraySizes ? new TVector<unsigned int>(*t.mArraySizes) : nullptr;
- mInterfaceBlock = t.mInterfaceBlock;
- mStructure = t.mStructure;
- mIsStructSpecifier = t.mIsStructSpecifier;
- mMangledName = t.mMangledName;
- 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();
-}
-
-TString TType::getCompleteString() const
-{
- TStringStream stream;
-
- if (invariant)
- stream << "invariant ";
- if (qualifier != EvqTemporary && qualifier != EvqGlobal)
- stream << getQualifierString() << " ";
- if (precision != EbpUndefined)
- stream << getPrecisionString() << " ";
- if (mArraySizes)
- {
- for (auto arraySizeIter = mArraySizes->rbegin(); arraySizeIter != mArraySizes->rend();
- ++arraySizeIter)
- {
- stream << "array[" << (*arraySizeIter) << "] of ";
- }
- }
- if (isMatrix())
- stream << getCols() << "X" << getRows() << " matrix of ";
- else if (isVector())
- stream << getNominalSize() << "-component vector of ";
-
- stream << getBasicString();
- return stream.str();
-}
-
-//
-// Recursively generate mangled names.
-//
-const char *TType::buildMangledName() const
-{
- TString mangledName;
- if (isMatrix())
- mangledName += 'm';
- else if (isVector())
- mangledName += 'v';
-
- switch (type)
- {
- case EbtFloat:
- mangledName += 'f';
- break;
- case EbtInt:
- mangledName += 'i';
- break;
- case EbtUInt:
- mangledName += 'u';
- break;
- case EbtBool:
- mangledName += 'b';
- break;
- case EbtYuvCscStandardEXT:
- mangledName += "ycs";
- break;
- case EbtSampler2D:
- mangledName += "s2";
- break;
- case EbtSampler3D:
- mangledName += "s3";
- break;
- case EbtSamplerCube:
- mangledName += "sC";
- break;
- case EbtSampler2DArray:
- mangledName += "s2a";
- break;
- case EbtSamplerExternalOES:
- mangledName += "sext";
- break;
- case EbtSamplerExternal2DY2YEXT:
- mangledName += "sext2y2y";
- break;
- case EbtSampler2DRect:
- mangledName += "s2r";
- break;
- case EbtSampler2DMS:
- mangledName += "s2ms";
- break;
- case EbtISampler2D:
- mangledName += "is2";
- break;
- case EbtISampler3D:
- mangledName += "is3";
- break;
- case EbtISamplerCube:
- mangledName += "isC";
- break;
- case EbtISampler2DArray:
- mangledName += "is2a";
- break;
- case EbtISampler2DMS:
- mangledName += "is2ms";
- break;
- case EbtUSampler2D:
- mangledName += "us2";
- break;
- case EbtUSampler3D:
- mangledName += "us3";
- break;
- case EbtUSamplerCube:
- mangledName += "usC";
- break;
- case EbtUSampler2DArray:
- mangledName += "us2a";
- break;
- case EbtUSampler2DMS:
- mangledName += "us2ms";
- break;
- case EbtSampler2DShadow:
- mangledName += "s2s";
- break;
- case EbtSamplerCubeShadow:
- mangledName += "sCs";
- break;
- case EbtSampler2DArrayShadow:
- mangledName += "s2as";
- break;
- case EbtImage2D:
- mangledName += "im2";
- break;
- case EbtIImage2D:
- mangledName += "iim2";
- break;
- case EbtUImage2D:
- mangledName += "uim2";
- break;
- case EbtImage3D:
- mangledName += "im3";
- break;
- case EbtIImage3D:
- mangledName += "iim3";
- break;
- case EbtUImage3D:
- mangledName += "uim3";
- break;
- case EbtImage2DArray:
- mangledName += "im2a";
- break;
- case EbtIImage2DArray:
- mangledName += "iim2a";
- break;
- case EbtUImage2DArray:
- mangledName += "uim2a";
- break;
- case EbtImageCube:
- mangledName += "imc";
- break;
- case EbtIImageCube:
- mangledName += "iimc";
- break;
- case EbtUImageCube:
- mangledName += "uimc";
- break;
- case EbtAtomicCounter:
- mangledName += "ac";
- break;
- case EbtStruct:
- mangledName += mStructure->mangledName();
- break;
- case EbtInterfaceBlock:
- mangledName += mInterfaceBlock->mangledName();
- break;
- default:
- // EbtVoid, EbtAddress and non types
- break;
- }
-
- if (isMatrix())
- {
- mangledName += static_cast<char>('0' + getCols());
- mangledName += static_cast<char>('x');
- mangledName += static_cast<char>('0' + getRows());
- }
- else
- {
- mangledName += static_cast<char>('0' + getNominalSize());
- }
-
- if (mArraySizes)
- {
- for (unsigned int arraySize : *mArraySizes)
- {
- char buf[20];
- snprintf(buf, sizeof(buf), "%d", arraySize);
- mangledName += '[';
- mangledName += buf;
- mangledName += ']';
- }
- }
-
- mangledName += ';';
-
- // Copy string contents into a pool-allocated buffer, so we never need to call delete.
- size_t requiredSize = mangledName.size() + 1;
- char *buffer = reinterpret_cast<char *>(GetGlobalPoolAllocator()->allocate(requiredSize));
- memcpy(buffer, mangledName.c_str(), requiredSize);
- return buffer;
-}
-
-size_t TType::getObjectSize() const
-{
- size_t totalSize;
-
- if (getBasicType() == EbtStruct)
- totalSize = mStructure->objectSize();
- else
- totalSize = primarySize * secondarySize;
-
- if (totalSize == 0)
- return 0;
-
- if (mArraySizes)
- {
- 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;
- }
-
- if (mArraySizes)
- {
- for (unsigned int arraySize : *mArraySizes)
- {
- if (arraySize > static_cast<unsigned int>(std::numeric_limits<int>::max() / count))
- {
- count = std::numeric_limits<int>::max();
- }
- else
- {
- count *= static_cast<int>(arraySize);
- }
- }
- }
-
- return count;
-}
-
-unsigned int TType::getArraySizeProduct() const
-{
- if (!mArraySizes)
- return 1u;
-
- unsigned int product = 1u;
-
- for (unsigned int arraySize : *mArraySizes)
- {
- product *= arraySize;
- }
- return product;
-}
-
-bool TType::isUnsizedArray() const
-{
- if (!mArraySizes)
- return false;
-
- 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;
- }
- if (isArray())
- {
- for (size_t i = 0; i < mArraySizes->size(); ++i)
- {
- if ((*mArraySizes)[i] != (*arrayType.mArraySizes)[i])
- {
- return false;
- }
- }
- }
- return true;
-}
-
-void TType::sizeUnsizedArrays(const TVector<unsigned int> *newArraySizes)
-{
- size_t newArraySizesSize = newArraySizes ? newArraySizes->size() : 0;
- for (size_t i = 0u; i < getNumArraySizes(); ++i)
- {
- if ((*mArraySizes)[i] == 0)
- {
- if (i < newArraySizesSize)
- {
- ASSERT(newArraySizes != nullptr);
- (*mArraySizes)[i] = (*newArraySizes)[i];
- }
- else
- {
- (*mArraySizes)[i] = 1u;
- }
- }
- }
- invalidateMangledName();
-}
-
-void TType::sizeOutermostUnsizedArray(unsigned int arraySize)
-{
- ASSERT(isArray());
- ASSERT(mArraySizes->back() == 0u);
- mArraySizes->back() = arraySize;
-}
-
-void TType::setBasicType(TBasicType t)
-{
- if (type != t)
- {
- type = t;
- invalidateMangledName();
- }
-}
-
-void TType::setPrimarySize(unsigned char ps)
-{
- if (primarySize != ps)
- {
- ASSERT(ps <= 4);
- primarySize = ps;
- invalidateMangledName();
- }
-}
-
-void TType::setSecondarySize(unsigned char ss)
-{
- if (secondarySize != ss)
- {
- ASSERT(ss <= 4);
- secondarySize = ss;
- invalidateMangledName();
- }
-}
-
-void TType::makeArray(unsigned int s)
-{
- if (!mArraySizes)
- mArraySizes = new TVector<unsigned int>();
-
- mArraySizes->push_back(s);
- invalidateMangledName();
-}
-
-void TType::makeArrays(const TVector<unsigned int> &sizes)
-{
- if (!mArraySizes)
- mArraySizes = new TVector<unsigned int>();
-
- mArraySizes->insert(mArraySizes->end(), sizes.begin(), sizes.end());
- invalidateMangledName();
-}
-
-void TType::setArraySize(size_t arrayDimension, unsigned int s)
-{
- ASSERT(mArraySizes != nullptr);
- ASSERT(arrayDimension < mArraySizes->size());
- if (mArraySizes->at(arrayDimension) != s)
- {
- (*mArraySizes)[arrayDimension] = s;
- invalidateMangledName();
- }
-}
-
-void TType::toArrayElementType()
-{
- ASSERT(mArraySizes != nullptr);
- if (mArraySizes->size() > 0)
- {
- mArraySizes->pop_back();
- invalidateMangledName();
- }
-}
-
-void TType::setInterfaceBlock(TInterfaceBlock *interfaceBlockIn)
-{
- if (mInterfaceBlock != interfaceBlockIn)
- {
- mInterfaceBlock = interfaceBlockIn;
- invalidateMangledName();
- }
-}
-
-void TType::setStruct(TStructure *s)
-{
- if (mStructure != s)
- {
- mStructure = s;
- invalidateMangledName();
- }
-}
-
-const char *TType::getMangledName() const
-{
- if (mMangledName == nullptr)
- {
- mMangledName = buildMangledName();
- }
-
- return mMangledName;
-}
-
-void TType::realize()
-{
- getMangledName();
-}
-
-void TType::invalidateMangledName()
-{
- mMangledName = nullptr;
-}
-
-// TStructure implementation.
-TStructure::TStructure(TSymbolTable *symbolTable, const TString *name, TFieldList *fields)
- : TFieldListCollection(name, fields),
- mDeepestNesting(0),
- mUniqueId(symbolTable->nextUniqueId()),
- mAtGlobalScope(false)
-{
-}
-
-bool TStructure::equals(const TStructure &other) const
-{
- return (uniqueId() == other.uniqueId());
-}
-
-bool TStructure::containsArrays() const
-{
- for (size_t i = 0; i < mFields->size(); ++i)
- {
- const TType *fieldType = (*mFields)[i]->type();
- if (fieldType->isArray() || fieldType->isStructureContainingArrays())
- return true;
- }
- return false;
-}
-
-bool TStructure::containsType(TBasicType type) const
-{
- for (size_t i = 0; i < mFields->size(); ++i)
- {
- const TType *fieldType = (*mFields)[i]->type();
- if (fieldType->getBasicType() == type || fieldType->isStructureContainingType(type))
- return true;
- }
- return false;
-}
-
-bool TStructure::containsSamplers() const
-{
- for (size_t i = 0; i < mFields->size(); ++i)
- {
- const TType *fieldType = (*mFields)[i]->type();
- if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
- return true;
- }
- return false;
-}
-
-void TType::createSamplerSymbols(const TString &namePrefix,
- const TString &apiNamePrefix,
- TVector<TIntermSymbol *> *outputSymbols,
- TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
- TSymbolTable *symbolTable) const
-{
- if (isStructureContainingSamplers())
- {
- if (isArray())
- {
- TType elementType(*this);
- elementType.toArrayElementType();
- for (unsigned int arrayIndex = 0u; arrayIndex < getOutermostArraySize(); ++arrayIndex)
- {
- TStringStream elementName;
- elementName << namePrefix << "_" << arrayIndex;
- TStringStream elementApiName;
- elementApiName << apiNamePrefix << "[" << arrayIndex << "]";
- elementType.createSamplerSymbols(elementName.str(), elementApiName.str(),
- outputSymbols, outputSymbolsToAPINames,
- symbolTable);
- }
- }
- else
- {
- mStructure->createSamplerSymbols(namePrefix, apiNamePrefix, outputSymbols,
- outputSymbolsToAPINames, symbolTable);
- }
- return;
- }
-
- ASSERT(IsSampler(type));
- TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), namePrefix, *this);
- outputSymbols->push_back(symbol);
- if (outputSymbolsToAPINames)
- {
- (*outputSymbolsToAPINames)[symbol] = apiNamePrefix;
- }
-}
-
-void TStructure::createSamplerSymbols(const TString &namePrefix,
- const TString &apiNamePrefix,
- TVector<TIntermSymbol *> *outputSymbols,
- TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
- TSymbolTable *symbolTable) const
-{
- ASSERT(containsSamplers());
- for (auto &field : *mFields)
- {
- const TType *fieldType = field->type();
- if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
- {
- TString fieldName = namePrefix + "_" + field->name();
- TString fieldApiName = apiNamePrefix + "." + field->name();
- fieldType->createSamplerSymbols(fieldName, fieldApiName, outputSymbols,
- outputSymbolsToAPINames, symbolTable);
- }
- }
-}
-
-TString TFieldListCollection::buildMangledName(const TString &mangledNamePrefix) const
-{
- TString mangledName(mangledNamePrefix);
- mangledName += *mName;
- for (size_t i = 0; i < mFields->size(); ++i)
- {
- mangledName += '-';
- mangledName += (*mFields)[i]->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;
-}
-
-int TFieldListCollection::getLocationCount() const
-{
- int count = 0;
- for (const TField *field : *mFields)
- {
- int fieldCount = field->type()->getLocationCount();
- if (fieldCount > std::numeric_limits<int>::max() - count)
- {
- count = std::numeric_limits<int>::max();
- }
- else
- {
- count += fieldCount;
- }
- }
- return count;
-}
-
-int TStructure::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;
- 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;
- 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<unsigned int> *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/src/3rdparty/angle/src/compiler/translator/Types.h b/src/3rdparty/angle/src/compiler/translator/Types.h
deleted file mode 100644
index 7dc84c5b1c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Types.h
+++ /dev/null
@@ -1,509 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#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/SymbolUniqueId.h"
-
-namespace sh
-{
-
-struct TPublicType;
-class TType;
-class TSymbol;
-class TIntermSymbol;
-class TSymbolTable;
-
-class TField : angle::NonCopyable
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- TField(TType *type, TString *name, const TSourceLoc &line)
- : mType(type), mName(name), mLine(line)
- {
- }
-
- // TODO(alokp): We should only return const type.
- // Fix it by tweaking grammar.
- TType *type() { return mType; }
- const TType *type() const { return mType; }
-
- const TString &name() const { return *mName; }
- const TSourceLoc &line() const { return mLine; }
-
- private:
- TType *mType;
- TString *mName;
- TSourceLoc mLine;
-};
-
-typedef TVector<TField *> TFieldList;
-inline TFieldList *NewPoolTFieldList()
-{
- void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
- return new (memory) TFieldList;
-}
-
-class TFieldListCollection : angle::NonCopyable
-{
- public:
- const TString &name() const { return *mName; }
- const TFieldList &fields() const { return *mFields; }
-
- size_t objectSize() const
- {
- if (mObjectSize == 0)
- mObjectSize = calculateObjectSize();
- return mObjectSize;
- }
-
- // How many locations the field list consumes as a uniform.
- int getLocationCount() const;
-
- protected:
- TFieldListCollection(const TString *name, TFieldList *fields)
- : mName(name), mFields(fields), mObjectSize(0)
- {
- }
- TString buildMangledName(const TString &mangledNamePrefix) const;
- size_t calculateObjectSize() const;
-
- const TString *mName;
- TFieldList *mFields;
-
- mutable TString mMangledName;
- mutable size_t mObjectSize;
-};
-
-// May also represent interface blocks
-class TStructure : public TFieldListCollection
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- TStructure(TSymbolTable *symbolTable, const TString *name, TFieldList *fields);
-
- int deepestNesting() const
- {
- if (mDeepestNesting == 0)
- mDeepestNesting = calculateDeepestNesting();
- return mDeepestNesting;
- }
- bool containsArrays() const;
- bool containsType(TBasicType t) const;
- bool containsSamplers() const;
-
- void createSamplerSymbols(const TString &namePrefix,
- const TString &apiNamePrefix,
- TVector<TIntermSymbol *> *outputSymbols,
- TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
- TSymbolTable *symbolTable) const;
-
- bool equals(const TStructure &other) const;
-
- int uniqueId() const { return mUniqueId.get(); }
-
- void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; }
-
- bool atGlobalScope() const { return mAtGlobalScope; }
-
- const TString &mangledName() const
- {
- if (mMangledName.empty())
- mMangledName = buildMangledName("struct-");
- return mMangledName;
- }
-
- private:
- // 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 RegenerateStructNames;
- void setName(const TString &name)
- {
- TString *mutableName = const_cast<TString *>(mName);
- *mutableName = name;
- }
-
- int calculateDeepestNesting() const;
-
- mutable int mDeepestNesting;
- const TSymbolUniqueId mUniqueId;
- bool mAtGlobalScope;
-};
-
-class TInterfaceBlock : public TFieldListCollection
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- TInterfaceBlock(const TString *name,
- TFieldList *fields,
- const TString *instanceName,
- const TLayoutQualifier &layoutQualifier)
- : TFieldListCollection(name, fields),
- mInstanceName(instanceName),
- mBlockStorage(layoutQualifier.blockStorage),
- mMatrixPacking(layoutQualifier.matrixPacking),
- mBinding(layoutQualifier.binding)
- {
- }
-
- const TString &instanceName() const { return *mInstanceName; }
- bool hasInstanceName() const { return mInstanceName != nullptr; }
- TLayoutBlockStorage blockStorage() const { return mBlockStorage; }
- TLayoutMatrixPacking matrixPacking() const { return mMatrixPacking; }
- int blockBinding() const { return mBinding; }
- const TString &mangledName() const
- {
- if (mMangledName.empty())
- mMangledName = buildMangledName("iblock-");
- return mMangledName;
- }
-
- private:
- const TString *mInstanceName; // for interface block instance names
- TLayoutBlockStorage mBlockStorage;
- TLayoutMatrixPacking mMatrixPacking;
- int mBinding;
-};
-
-//
-// Base class for things that have a type.
-//
-class TType
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- TType();
- explicit TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1);
- TType(TBasicType t,
- TPrecision p,
- TQualifier q = EvqTemporary,
- unsigned char ps = 1,
- unsigned char ss = 1);
- explicit TType(const TPublicType &p);
- explicit TType(TStructure *userDef);
- TType(TInterfaceBlock *interfaceBlockIn,
- TQualifier qualifierIn,
- TLayoutQualifier layoutQualifierIn);
- TType(const TType &t);
- TType &operator=(const TType &t);
-
- TBasicType getBasicType() const { return type; }
- void setBasicType(TBasicType t);
-
- TPrecision getPrecision() const { return precision; }
- void setPrecision(TPrecision p) { precision = p; }
-
- TQualifier getQualifier() const { return qualifier; }
- void setQualifier(TQualifier q) { qualifier = q; }
-
- bool isInvariant() const { return invariant; }
-
- void setInvariant(bool i) { invariant = i; }
-
- TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; }
- void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; }
-
- TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; }
- void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; }
-
- int getNominalSize() const { return primarySize; }
- int getSecondarySize() const { return secondarySize; }
- int getCols() const
- {
- ASSERT(isMatrix());
- return primarySize;
- }
- int getRows() const
- {
- ASSERT(isMatrix());
- return secondarySize;
- }
- void setPrimarySize(unsigned char ps);
- void setSecondarySize(unsigned char 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 != nullptr && !mArraySizes->empty(); }
- bool isArrayOfArrays() const { return isArray() && mArraySizes->size() > 1u; }
- size_t getNumArraySizes() const { return isArray() ? mArraySizes->size() : 0; }
- const TVector<unsigned int> *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 TVector<unsigned int> &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 TVector<unsigned int> *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();
-
- TInterfaceBlock *getInterfaceBlock() const { return mInterfaceBlock; }
- void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn);
- bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
-
- bool isVector() const { return primarySize > 1 && secondarySize == 1; }
- bool isScalar() 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;
-
- TStructure *getStruct() { return mStructure; }
- const TStructure *getStruct() const { return mStructure; }
- void setStruct(TStructure *s);
-
- 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;
-
- TString getCompleteString() 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 { return mStructure ? mStructure->deepestNesting() : 0; }
-
- bool isNamelessStruct() const { return mStructure && mStructure->name() == ""; }
-
- bool isStructureContainingArrays() const
- {
- return mStructure ? mStructure->containsArrays() : false;
- }
-
- bool isStructureContainingType(TBasicType t) const
- {
- return mStructure ? mStructure->containsType(t) : false;
- }
-
- bool isStructureContainingSamplers() const
- {
- return mStructure ? mStructure->containsSamplers() : false;
- }
-
- bool isStructSpecifier() const { return mIsStructSpecifier; }
-
- void createSamplerSymbols(const TString &namePrefix,
- const TString &apiNamePrefix,
- TVector<TIntermSymbol *> *outputSymbols,
- TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
- TSymbolTable *symbolTable) const;
-
- // Initializes all lazily-initialized members.
- void realize();
-
- private:
- void invalidateMangledName();
- const char *buildMangledName() const;
-
- TBasicType type;
- TPrecision precision;
- TQualifier qualifier;
- bool invariant;
- TMemoryQualifier memoryQualifier;
- TLayoutQualifier layoutQualifier;
- unsigned char primarySize; // size of vector or cols matrix
- unsigned char 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.
- TVector<unsigned int> *mArraySizes;
-
- // 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.
- TInterfaceBlock *mInterfaceBlock;
-
- // 0 unless this is a struct
- TStructure *mStructure;
- bool mIsStructSpecifier;
-
- mutable const char *mMangledName;
-};
-
-// TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the
-// grammar
-struct TTypeSpecifierNonArray
-{
- TBasicType type;
- unsigned char primarySize; // size of vector or cols of matrix
- unsigned char secondarySize; // rows of matrix
- 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(TStructure *aUserDef, bool aIsStructSpecifier, const TSourceLoc &aLine)
- {
- type = EbtStruct;
- primarySize = 1;
- secondarySize = 1;
- userDef = aUserDef;
- line = aLine;
- isStructSpecifier = aIsStructSpecifier;
- }
-
- void setAggregate(unsigned char size) { primarySize = size; }
-
- void setMatrix(unsigned char columns, unsigned char 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; }
-
- unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; }
- unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; }
-
- 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<unsigned int> *sizes);
- bool isArray() const;
- void clearArrayness();
- bool isAggregate() const;
-
- TTypeSpecifierNonArray typeSpecifierNonArray;
- TLayoutQualifier layoutQualifier;
- TMemoryQualifier memoryQualifier;
- TQualifier qualifier;
- bool invariant;
- 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<unsigned int> *arraySizes;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_TYPES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp
deleted file mode 100644
index 4e4653bbe5..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#include "compiler/translator/UnfoldShortCircuitAST.h"
-
-namespace sh
-{
-
-namespace
-{
-
-// "x || y" is equivalent to "x ? true : y".
-TIntermTernary *UnfoldOR(TIntermTyped *x, TIntermTyped *y)
-{
- TConstantUnion *u = new TConstantUnion;
- u->setBConst(true);
- TIntermConstantUnion *trueNode =
- new TIntermConstantUnion(u, TType(EbtBool, EbpUndefined, EvqConst, 1));
- return new TIntermTernary(x, trueNode, y);
-}
-
-// "x && y" is equivalent to "x ? y : false".
-TIntermTernary *UnfoldAND(TIntermTyped *x, TIntermTyped *y)
-{
- TConstantUnion *u = new TConstantUnion;
- u->setBConst(false);
- TIntermConstantUnion *falseNode =
- new TIntermConstantUnion(u, TType(EbtBool, EbpUndefined, EvqConst, 1));
- return new TIntermTernary(x, y, falseNode);
-}
-
-} // namespace anonymous
-
-bool UnfoldShortCircuitAST::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;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h
deleted file mode 100644
index 7f377e6f15..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// UnfoldShortCircuitAST is an AST traverser to replace short-circuiting
-// operations with ternary operations.
-//
-
-#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_
-#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_
-
-#include "common/angleutils.h"
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-// 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 UnfoldShortCircuitAST : public TIntermTraverser
-{
- public:
- UnfoldShortCircuitAST() : TIntermTraverser(true, false, false) {}
-
- bool visitBinary(Visit visit, TIntermBinary *) override;
-};
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp
deleted file mode 100644
index 774f1fc704..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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/UnfoldShortCircuitToIf.h"
-
-#include "compiler/translator/IntermNodePatternMatcher.h"
-#include "compiler/translator/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;
- TType boolType(EbtBool, EbpUndefined, EvqTemporary);
-
- ASSERT(node->getLeft()->getType() == boolType);
- insertions.push_back(createTempInitDeclaration(node->getLeft()));
-
- TIntermBlock *assignRightBlock = new TIntermBlock();
- ASSERT(node->getRight()->getType() == boolType);
- assignRightBlock->getSequence()->push_back(createTempAssignment(node->getRight()));
-
- TIntermUnary *notTempSymbol =
- new TIntermUnary(EOpLogicalNot, createTempSymbol(boolType));
- TIntermIfElse *ifNode = new TIntermIfElse(notTempSymbol, assignRightBlock, nullptr);
- insertions.push_back(ifNode);
-
- insertStatementsInParentBlock(insertions);
-
- queueReplacement(createTempSymbol(boolType), 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;
- TType boolType(EbtBool, EbpUndefined, EvqTemporary);
-
- ASSERT(node->getLeft()->getType() == boolType);
- insertions.push_back(createTempInitDeclaration(node->getLeft()));
-
- TIntermBlock *assignRightBlock = new TIntermBlock();
- ASSERT(node->getRight()->getType() == boolType);
- assignRightBlock->getSequence()->push_back(createTempAssignment(node->getRight()));
-
- TIntermIfElse *ifNode =
- new TIntermIfElse(createTempSymbol(boolType), assignRightBlock, nullptr);
- insertions.push_back(ifNode);
-
- insertStatementsInParentBlock(insertions);
-
- queueReplacement(createTempSymbol(boolType), 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 = createTempDeclaration(node->getType());
- insertions.push_back(tempDeclaration);
-
- TIntermBlock *trueBlock = new TIntermBlock();
- TIntermBinary *trueAssignment = createTempAssignment(node->getTrueExpression());
- trueBlock->getSequence()->push_back(trueAssignment);
-
- TIntermBlock *falseBlock = new TIntermBlock();
- TIntermBinary *falseAssignment = createTempAssignment(node->getFalseExpression());
- falseBlock->getSequence()->push_back(falseAssignment);
-
- TIntermIfElse *ifNode =
- new TIntermIfElse(node->getCondition()->getAsTyped(), trueBlock, falseBlock);
- insertions.push_back(ifNode);
-
- insertStatementsInParentBlock(insertions);
-
- TIntermSymbol *ternaryResult = createTempSymbol(node->getType());
- queueReplacement(ternaryResult, OriginalNode::IS_DROPPED);
-
- return false;
-}
-
-void UnfoldShortCircuitTraverser::nextIteration()
-{
- mFoundShortCircuit = false;
- nextTemporaryId();
-}
-
-} // namespace
-
-void UnfoldShortCircuitToIf(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())
- traverser.updateTree();
- } while (traverser.foundShortCircuit());
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h
deleted file mode 100644
index 37dd83a8cf..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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_UNFOLDSHORTCIRCUIT_H_
-#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
-
-namespace sh
-{
-
-class TIntermNode;
-class TSymbolTable;
-
-void UnfoldShortCircuitToIf(TIntermNode *root, TSymbolTable *symbolTable);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp
deleted file mode 100644
index 9f18509438..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp
+++ /dev/null
@@ -1,600 +0,0 @@
-//
-// Copyright (c) 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.
-//
-// UniformHLSL.cpp:
-// Methods for GLSL to HLSL translation for uniforms and uniform blocks.
-//
-
-#include "compiler/translator/UniformHLSL.h"
-
-#include "common/utilities.h"
-#include "compiler/translator/StructureHLSL.h"
-#include "compiler/translator/UtilsHLSL.h"
-#include "compiler/translator/blocklayoutHLSL.h"
-#include "compiler/translator/util.h"
-
-namespace sh
-{
-
-namespace
-{
-
-static const char *UniformRegisterPrefix(const TType &type)
-{
- if (IsSampler(type.getBasicType()))
- {
- return "s";
- }
- else
- {
- return "c";
- }
-}
-
-static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage)
-{
- 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)
- {
- // Use HLSL row-major packing for GLSL column-major matrices
- return QualifiedStructNameString(*structure, matrixPacking == EmpColumnMajor,
- blockStorage == EbsStd140);
- }
- else
- {
- return TypeString(fieldType);
- }
-}
-
-static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock)
-{
- return DecoratePrivate(interfaceBlock.name()) + "_type";
-}
-
-void OutputSamplerIndexArrayInitializer(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())
- {
- OutputSamplerIndexArrayInitializer(out, elementType,
- startIndex + i * elementType.getArraySizeProduct());
- }
- else
- {
- out << (startIndex + i);
- }
- }
- out << "}";
-}
-
-} // anonymous namespace
-
-UniformHLSL::UniformHLSL(sh::GLenum shaderType,
- StructureHLSL *structureHLSL,
- ShShaderOutput outputType,
- const std::vector<Uniform> &uniforms)
- : mUniformRegister(0),
- mUniformBlockRegister(0),
- mTextureRegister(0),
- mRWTextureRegister(0),
- mSamplerCount(0),
- mShaderType(shaderType),
- mStructureHLSL(structureHLSL),
- mOutputType(outputType),
- mUniforms(uniforms)
-{
-}
-
-void UniformHLSL::reserveUniformRegisters(unsigned int registerCount)
-{
- mUniformRegister = registerCount;
-}
-
-void UniformHLSL::reserveUniformBlockRegisters(unsigned int registerCount)
-{
- mUniformBlockRegister = registerCount;
-}
-
-const Uniform *UniformHLSL::findUniformByName(const TString &name) const
-{
- for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
- {
- if (mUniforms[uniformIndex].name == name.c_str())
- {
- return &mUniforms[uniformIndex];
- }
- }
-
- return nullptr;
-}
-
-unsigned int UniformHLSL::assignUniformRegister(const TType &type,
- const TString &name,
- unsigned int *outRegisterCount)
-{
- unsigned int registerIndex;
- const Uniform *uniform = findUniformByName(name);
- ASSERT(uniform);
-
- if (IsSampler(type.getBasicType()) ||
- (IsImage(type.getBasicType()) && type.getMemoryQualifier().readonly))
- {
- registerIndex = mTextureRegister;
- }
- else if (IsImage(type.getBasicType()))
- {
- registerIndex = mRWTextureRegister;
- }
- else
- {
- registerIndex = mUniformRegister;
- }
-
- mUniformRegisterMap[uniform->name] = registerIndex;
-
- unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);
-
- if (IsSampler(type.getBasicType()) ||
- (IsImage(type.getBasicType()) && type.getMemoryQualifier().readonly))
- {
- mTextureRegister += registerCount;
- }
- else if (IsImage(type.getBasicType()))
- {
- mRWTextureRegister += registerCount;
- }
- else
- {
- mUniformRegister += registerCount;
- }
- if (outRegisterCount)
- {
- *outRegisterCount = registerCount;
- }
- return registerIndex;
-}
-
-unsigned int UniformHLSL::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 = mTextureRegister;
- mUniformRegisterMap[std::string(name.c_str())] = registerIndex;
- unsigned int registerCount = type.isArray() ? type.getArraySizeProduct() : 1u;
- mTextureRegister += registerCount;
- if (outRegisterCount)
- {
- *outRegisterCount = registerCount;
- }
- return registerIndex;
-}
-
-void UniformHLSL::outputHLSLSamplerUniformGroup(
- TInfoSinkBase &out,
- const HLSLTextureGroup textureGroup,
- const TVector<const TIntermSymbol *> &group,
- const TMap<const TIntermSymbol *, TString> &samplerInStructSymbolsToAPINames,
- unsigned int *groupTextureRegisterIndex)
-{
- if (group.empty())
- {
- return;
- }
- unsigned int groupRegisterCount = 0;
- for (const TIntermSymbol *uniform : group)
- {
- const TType &type = uniform->getType();
- const TString &name = uniform->getSymbol();
- unsigned int registerCount;
-
- // The uniform might be just a regular sampler or one extracted from a struct.
- unsigned int samplerArrayIndex = 0u;
- const Uniform *uniformByName = findUniformByName(name);
- if (uniformByName)
- {
- samplerArrayIndex = assignUniformRegister(type, name, &registerCount);
- }
- else
- {
- ASSERT(samplerInStructSymbolsToAPINames.find(uniform) !=
- samplerInStructSymbolsToAPINames.end());
- samplerArrayIndex = assignSamplerInStructUniformRegister(
- type, samplerInStructSymbolsToAPINames.at(uniform), &registerCount);
- }
- groupRegisterCount += registerCount;
-
- if (type.isArray())
- {
- out << "static const uint " << DecorateVariableIfNeeded(uniform->getName())
- << ArrayString(type) << " = ";
- OutputSamplerIndexArrayInitializer(out, type, samplerArrayIndex);
- out << ";\n";
- }
- else
- {
- out << "static const uint " << DecorateVariableIfNeeded(uniform->getName()) << " = "
- << 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 UniformHLSL::outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out,
- const TType &type,
- const TName &name,
- const unsigned int registerIndex)
-{
- out << "uniform " << SamplerString(type.getBasicType()) << " sampler_"
- << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(s"
- << str(registerIndex) << ");\n";
- out << "uniform " << TextureString(type.getBasicType()) << " texture_"
- << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(t"
- << str(registerIndex) << ");\n";
-}
-
-void UniformHLSL::outputHLSL4_1_FL11Texture(TInfoSinkBase &out,
- const TType &type,
- const TName &name,
- const unsigned int registerIndex)
-{
- // TODO(xinghua.cao@intel.com): if image2D variable is bound on one layer of Texture3D or
- // Texture2DArray. Translate this variable to HLSL Texture3D object or HLSL Texture2DArray
- // object, or create a temporary Texture2D to save content of the layer and bind the
- // temporary Texture2D to image2D variable.
- out << "uniform "
- << TextureString(type.getBasicType(), type.getLayoutQualifier().imageInternalFormat) << " "
- << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(t"
- << str(registerIndex) << ");\n";
- return;
-}
-
-void UniformHLSL::outputHLSL4_1_FL11RWTexture(TInfoSinkBase &out,
- const TType &type,
- const TName &name,
- const unsigned int registerIndex)
-{
- // TODO(xinghua.cao@intel.com): if image2D variable is bound on one layer of Texture3D or
- // Texture2DArray. Translate this variable to HLSL RWTexture3D object or HLSL RWTexture2DArray
- // object, or create a temporary Texture2D to save content of the layer and bind the
- // temporary Texture2D to image2D variable.
- if (mShaderType == GL_COMPUTE_SHADER)
- {
- out << "uniform "
- << RWTextureString(type.getBasicType(), type.getLayoutQualifier().imageInternalFormat)
- << " " << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(u"
- << str(registerIndex) << ");\n";
- }
- else
- {
- // TODO(xinghua.cao@intel.com): Support images in vertex shader and fragment shader,
- // which are needed to sync binding value when linking program.
- }
- return;
-}
-
-void UniformHLSL::outputUniform(TInfoSinkBase &out,
- const TType &type,
- const TName &name,
- 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->name().empty())
- ? QualifiedStructNameString(*structure, false, false)
- : TypeString(type));
-
- const TString &registerString =
- TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")";
-
- out << "uniform " << typeName << " ";
-
- out << DecorateVariableIfNeeded(name);
-
- out << ArrayString(type) << " : " << registerString << ";\n";
-}
-
-void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
- ShShaderOutput outputType,
- const ReferencedSymbols &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<TVector<const TIntermSymbol *>> groupedSamplerUniforms(HLSL_TEXTURE_MAX + 1);
- TMap<const TIntermSymbol *, TString> samplerInStructSymbolsToAPINames;
- TVector<const TIntermSymbol *> imageUniformsHLSL41Output;
- for (auto &uniformIt : referencedUniforms)
- {
- // Output regular uniforms. Group sampler uniforms by type.
- const TIntermSymbol &uniform = *uniformIt.second;
- const TType &type = uniform.getType();
- const TName &name = uniform.getName();
-
- if (outputType == SH_HLSL_4_1_OUTPUT && IsSampler(type.getBasicType()))
- {
- HLSLTextureGroup group = TextureGroup(type.getBasicType());
- groupedSamplerUniforms[group].push_back(&uniform);
- }
- else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(type.getBasicType()))
- {
- unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
- outputHLSL4_0_FL9_3Sampler(out, type, name, registerIndex);
- }
- else if (outputType == SH_HLSL_4_1_OUTPUT && IsImage(type.getBasicType()))
- {
- imageUniformsHLSL41Output.push_back(&uniform);
- }
- else
- {
- if (type.isStructureContainingSamplers())
- {
- TVector<TIntermSymbol *> samplerSymbols;
- TMap<TIntermSymbol *, TString> symbolsToAPINames;
- type.createSamplerSymbols("angle_" + name.getString(), name.getString(),
- &samplerSymbols, &symbolsToAPINames, symbolTable);
- for (TIntermSymbol *sampler : samplerSymbols)
- {
- const TType &samplerType = sampler->getType();
-
- // Will use angle_ prefix instead of regular prefix.
- sampler->setInternal(true);
- const TName &samplerName = sampler->getName();
-
- 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, samplerName, registerIndex);
- }
- else
- {
- ASSERT(outputType == SH_HLSL_3_0_OUTPUT);
- unsigned int registerIndex = assignSamplerInStructUniformRegister(
- samplerType, symbolsToAPINames[sampler], nullptr);
- outputUniform(out, samplerType, samplerName, registerIndex);
- }
- }
- }
- unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
- outputUniform(out, type, name, registerIndex);
- }
- }
-
- if (outputType == SH_HLSL_4_1_OUTPUT)
- {
- unsigned int groupTextureRegisterIndex = 0;
- // 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;
-
- for (const TIntermSymbol *image : imageUniformsHLSL41Output)
- {
- const TType &type = image->getType();
- const TName &name = image->getName();
- unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
- if (type.getMemoryQualifier().readonly)
- {
- outputHLSL4_1_FL11Texture(out, type, name, registerIndex);
- }
- else
- {
- outputHLSL4_1_FL11RWTexture(out, type, name, registerIndex);
- }
- }
- }
-}
-
-void UniformHLSL::samplerMetadataUniforms(TInfoSinkBase &out, const char *reg)
-{
- // 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"
- " };\n"
- " SamplerMetadata samplerMetadata["
- << mSamplerCount << "] : packoffset(" << reg << ");\n";
- }
-}
-
-TString UniformHLSL::uniformBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks)
-{
- TString interfaceBlocks;
-
- for (ReferencedSymbols::const_iterator interfaceBlockIt = referencedInterfaceBlocks.begin();
- interfaceBlockIt != referencedInterfaceBlocks.end(); interfaceBlockIt++)
- {
- const TType &nodeType = interfaceBlockIt->second->getType();
- const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock();
-
- // nodeType.isInterfaceBlock() == false means the node is a field of a uniform block which
- // doesn't have instance name, so this block cannot be an array.
- unsigned int interfaceBlockArraySize = 0u;
- if (nodeType.isInterfaceBlock() && nodeType.isArray())
- {
- interfaceBlockArraySize = nodeType.getOutermostArraySize();
- }
- unsigned int activeRegister = mUniformBlockRegister;
-
- mUniformBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister;
- mUniformBlockRegister += std::max(1u, interfaceBlockArraySize);
-
- // FIXME: interface block field names
-
- if (interfaceBlock.hasInstanceName())
- {
- interfaceBlocks += uniformBlockStructString(interfaceBlock);
- }
-
- if (interfaceBlockArraySize > 0)
- {
- for (unsigned int arrayIndex = 0; arrayIndex < interfaceBlockArraySize; arrayIndex++)
- {
- interfaceBlocks +=
- uniformBlockString(interfaceBlock, activeRegister + arrayIndex, arrayIndex);
- }
- }
- else
- {
- interfaceBlocks += uniformBlockString(interfaceBlock, activeRegister, GL_INVALID_INDEX);
- }
- }
-
- return (interfaceBlocks.empty() ? "" : ("// Uniform Blocks\n\n" + interfaceBlocks));
-}
-
-TString UniformHLSL::uniformBlockString(const TInterfaceBlock &interfaceBlock,
- unsigned int registerIndex,
- unsigned int arrayIndex)
-{
- const TString &arrayIndexString =
- (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : "");
- const TString &blockName = interfaceBlock.name() + arrayIndexString;
- TString hlsl;
-
- hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) +
- ")\n"
- "{\n";
-
- if (interfaceBlock.hasInstanceName())
- {
- hlsl += " " + InterfaceBlockStructName(interfaceBlock) + " " +
- uniformBlockInstanceString(interfaceBlock, arrayIndex) + ";\n";
- }
- else
- {
- const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
- hlsl += uniformBlockMembersString(interfaceBlock, blockStorage);
- }
-
- hlsl += "};\n\n";
-
- return hlsl;
-}
-
-TString UniformHLSL::uniformBlockInstanceString(const TInterfaceBlock &interfaceBlock,
- unsigned int arrayIndex)
-{
- if (!interfaceBlock.hasInstanceName())
- {
- return "";
- }
- else if (arrayIndex != GL_INVALID_INDEX)
- {
- return DecoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex);
- }
- else
- {
- return Decorate(interfaceBlock.instanceName());
- }
-}
-
-TString UniformHLSL::uniformBlockMembersString(const TInterfaceBlock &interfaceBlock,
- TLayoutBlockStorage blockStorage)
-{
- TString hlsl;
-
- Std140PaddingHelper padHelper = mStructureHLSL->getPaddingHelper();
-
- for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); 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);
- }
-
- hlsl += " " + InterfaceBlockFieldTypeString(field, blockStorage) + " " +
- Decorate(field.name()) + ArrayString(fieldType) + ";\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);
- }
- }
-
- return hlsl;
-}
-
-TString UniformHLSL::uniformBlockStructString(const TInterfaceBlock &interfaceBlock)
-{
- const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
-
- return "struct " + InterfaceBlockStructName(interfaceBlock) +
- "\n"
- "{\n" +
- uniformBlockMembersString(interfaceBlock, blockStorage) + "};\n\n";
-}
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h
deleted file mode 100644
index 8784e50533..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h
+++ /dev/null
@@ -1,110 +0,0 @@
-//
-// Copyright (c) 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.
-//
-// UniformHLSL.h:
-// Methods for GLSL to HLSL translation for uniforms and uniform blocks.
-//
-
-#ifndef COMPILER_TRANSLATOR_UNIFORMHLSL_H_
-#define COMPILER_TRANSLATOR_UNIFORMHLSL_H_
-
-#include "compiler/translator/OutputHLSL.h"
-#include "compiler/translator/UtilsHLSL.h"
-
-namespace sh
-{
-class StructureHLSL;
-class TSymbolTable;
-
-class UniformHLSL : angle::NonCopyable
-{
- public:
- UniformHLSL(sh::GLenum shaderType,
- StructureHLSL *structureHLSL,
- ShShaderOutput outputType,
- const std::vector<Uniform> &uniforms);
-
- void reserveUniformRegisters(unsigned int registerCount);
- void reserveUniformBlockRegisters(unsigned int registerCount);
- void uniformsHeader(TInfoSinkBase &out,
- ShShaderOutput outputType,
- const ReferencedSymbols &referencedUniforms,
- TSymbolTable *symbolTable);
-
- // Must be called after uniformsHeader
- void samplerMetadataUniforms(TInfoSinkBase &out, const char *reg);
-
- TString uniformBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks);
-
- // Used for direct index references
- static TString uniformBlockInstanceString(const TInterfaceBlock &interfaceBlock,
- unsigned int arrayIndex);
-
- const std::map<std::string, unsigned int> &getUniformBlockRegisterMap() const
- {
- return mUniformBlockRegisterMap;
- }
- const std::map<std::string, unsigned int> &getUniformRegisterMap() const
- {
- return mUniformRegisterMap;
- }
-
- private:
- TString uniformBlockString(const TInterfaceBlock &interfaceBlock,
- unsigned int registerIndex,
- unsigned int arrayIndex);
- TString uniformBlockMembersString(const TInterfaceBlock &interfaceBlock,
- TLayoutBlockStorage blockStorage);
- TString uniformBlockStructString(const TInterfaceBlock &interfaceBlock);
- const Uniform *findUniformByName(const TString &name) const;
-
- void outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out,
- const TType &type,
- const TName &name,
- const unsigned int registerIndex);
- void outputHLSL4_1_FL11Texture(TInfoSinkBase &out,
- const TType &type,
- const TName &name,
- const unsigned int registerIndex);
- void outputHLSL4_1_FL11RWTexture(TInfoSinkBase &out,
- const TType &type,
- const TName &name,
- const unsigned int registerIndex);
- void outputUniform(TInfoSinkBase &out,
- const TType &type,
- const TName &name,
- const unsigned int registerIndex);
-
- // Returns the uniform's register index
- unsigned int assignUniformRegister(const TType &type,
- const TString &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<const TIntermSymbol *> &group,
- const TMap<const TIntermSymbol *, TString> &samplerInStructSymbolsToAPINames,
- unsigned int *groupTextureRegisterIndex);
-
- unsigned int mUniformRegister;
- unsigned int mUniformBlockRegister;
- unsigned int mTextureRegister;
- unsigned int mRWTextureRegister;
- unsigned int mSamplerCount;
- sh::GLenum mShaderType;
- StructureHLSL *mStructureHLSL;
- ShShaderOutput mOutputType;
-
- const std::vector<Uniform> &mUniforms;
- std::map<std::string, unsigned int> mUniformBlockRegisterMap;
- std::map<std::string, unsigned int> mUniformRegisterMap;
-};
-}
-
-#endif // COMPILER_TRANSLATOR_UNIFORMHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp b/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp
deleted file mode 100644
index 40bd42afad..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-//
-// 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/UseInterfaceBlockFields.h"
-
-#include "compiler/translator/FindMain.h"
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/SymbolTable.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)
-{
- TString name = TString(var.name.c_str());
- ASSERT(name.find_last_of('[') == TString::npos);
- TIntermSymbol *symbol = ReferenceGlobalVariable(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)
- {
- TString name(block.instanceName.c_str());
- TIntermSymbol *arraySymbol = ReferenceGlobalVariable(name, symbolTable);
- for (unsigned int i = 0u; i < block.arraySize; ++i)
- {
- TIntermBinary *elementSymbol =
- new TIntermBinary(EOpIndexDirect, arraySymbol->deepCopy(), CreateIndexNode(i));
- InsertUseCode(block, elementSymbol, sequence);
- }
- }
- else
- {
- TString name(block.instanceName.c_str());
- TIntermSymbol *blockSymbol = ReferenceGlobalVariable(name, symbolTable);
- InsertUseCode(block, blockSymbol, sequence);
- }
- }
-}
-
-} // namespace anonymous
-
-void UseInterfaceBlockFields(TIntermBlock *root,
- const InterfaceBlockList &blocks,
- const TSymbolTable &symbolTable)
-{
- TIntermBlock *mainBody = FindMainBody(root);
- InsertUseCode(mainBody->getSequence(), blocks, symbolTable);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h b/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h
deleted file mode 100644
index 3e2a4815d4..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// 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_USEINTERFACEBLOCKFIELDS_H_
-#define COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_
-
-#include <GLSLANG/ShaderLang.h>
-
-namespace sh
-{
-
-class TIntermBlock;
-class TSymbolTable;
-
-using InterfaceBlockList = std::vector<sh::InterfaceBlock>;
-
-void UseInterfaceBlockFields(TIntermBlock *root,
- const InterfaceBlockList &blocks,
- const TSymbolTable &symbolTable);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp
deleted file mode 100644
index 8a77f0049a..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp
+++ /dev/null
@@ -1,970 +0,0 @@
-//
-// Copyright (c) 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 "compiler/translator/IntermNode.h"
-#include "compiler/translator/StructureHLSL.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-TString SamplerString(const TBasicType type)
-{
- if (IsShadowSampler(type))
- {
- return "SamplerComparisonState";
- }
- else
- {
- return "SamplerState";
- }
-}
-
-TString 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:
- 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 EbtISampler2D:
- return HLSL_TEXTURE_2D_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 EbtUSampler2D:
- return HLSL_TEXTURE_2D_UINT4;
- case EbtUSampler3D:
- return HLSL_TEXTURE_3D_UINT4;
- case EbtUSamplerCube:
- return HLSL_TEXTURE_2D_ARRAY_UINT4;
- case EbtUSampler2DArray:
- return HLSL_TEXTURE_2D_ARRAY_UINT4;
- case EbtUSampler2DMS:
- return HLSL_TEXTURE_2D_MS_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();
- }
- }
- case EbtIImage2D:
- {
- switch (imageInternalFormat)
- {
- case EiifRGBA32I:
- case EiifRGBA16I:
- case EiifRGBA8I:
- case EiifR32I:
- return HLSL_TEXTURE_2D_INT4;
- default:
- UNREACHABLE();
- }
- }
- case EbtUImage2D:
- {
- switch (imageInternalFormat)
- {
-
- case EiifRGBA32UI:
- case EiifRGBA16UI:
- case EiifRGBA8UI:
- case EiifR32UI:
- return HLSL_TEXTURE_2D_UINT4;
- default:
- UNREACHABLE();
- }
- }
- 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();
- }
- }
- case EbtIImage3D:
- {
- switch (imageInternalFormat)
- {
- case EiifRGBA32I:
- case EiifRGBA16I:
- case EiifRGBA8I:
- case EiifR32I:
- return HLSL_TEXTURE_3D_INT4;
- default:
- UNREACHABLE();
- }
- }
- case EbtUImage3D:
- {
- switch (imageInternalFormat)
- {
- case EiifRGBA32UI:
- case EiifRGBA16UI:
- case EiifRGBA8UI:
- case EiifR32UI:
- return HLSL_TEXTURE_3D_UINT4;
- default:
- UNREACHABLE();
- }
- }
- 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();
- }
- }
- case EbtIImage2DArray:
- case EbtIImageCube:
- {
- switch (imageInternalFormat)
- {
- case EiifRGBA32I:
- case EiifRGBA16I:
- case EiifRGBA8I:
- case EiifR32I:
- return HLSL_TEXTURE_2D_ARRAY_INT4;
- default:
- UNREACHABLE();
- }
- }
- case EbtUImage2DArray:
- case EbtUImageCube:
- {
- switch (imageInternalFormat)
- {
- case EiifRGBA32UI:
- case EiifRGBA16UI:
- case EiifRGBA8UI:
- case EiifR32UI:
- return HLSL_TEXTURE_2D_ARRAY_UINT4;
- default:
- UNREACHABLE();
- }
- }
- default:
- UNREACHABLE();
- }
- return HLSL_TEXTURE_UNKNOWN;
-}
-
-TString TextureString(const HLSLTextureGroup textureGroup)
-{
- switch (textureGroup)
- {
- case HLSL_TEXTURE_2D:
- return "Texture2D<float4>";
- case HLSL_TEXTURE_CUBE:
- return "TextureCube<float4>";
- case HLSL_TEXTURE_2D_ARRAY:
- return "Texture2DArray<float4>";
- case HLSL_TEXTURE_3D:
- return "Texture3D<float4>";
- case HLSL_TEXTURE_2D_UNORM:
- return "Texture2D<unorm float4>";
- case HLSL_TEXTURE_CUBE_UNORM:
- return "TextureCube<unorm float4>";
- case HLSL_TEXTURE_2D_ARRAY_UNORN:
- return "Texture2DArray<unorm float4>";
- case HLSL_TEXTURE_3D_UNORM:
- return "Texture3D<unorm float4>";
- case HLSL_TEXTURE_2D_SNORM:
- return "Texture2D<snorm float4>";
- case HLSL_TEXTURE_CUBE_SNORM:
- return "TextureCube<snorm float4>";
- case HLSL_TEXTURE_2D_ARRAY_SNORM:
- return "Texture2DArray<snorm float4>";
- case HLSL_TEXTURE_3D_SNORM:
- return "Texture3D<snorm float4>";
- case HLSL_TEXTURE_2D_MS:
- return "Texture2DMS<float4>";
- case HLSL_TEXTURE_2D_INT4:
- return "Texture2D<int4>";
- case HLSL_TEXTURE_3D_INT4:
- return "Texture3D<int4>";
- case HLSL_TEXTURE_2D_ARRAY_INT4:
- return "Texture2DArray<int4>";
- case HLSL_TEXTURE_2D_MS_INT4:
- return "Texture2DMS<int4>";
- case HLSL_TEXTURE_2D_UINT4:
- return "Texture2D<uint4>";
- case HLSL_TEXTURE_3D_UINT4:
- return "Texture3D<uint4>";
- case HLSL_TEXTURE_2D_ARRAY_UINT4:
- return "Texture2DArray<uint4>";
- case HLSL_TEXTURE_2D_MS_UINT4:
- return "Texture2DMS<uint4>";
- case HLSL_TEXTURE_2D_COMPARISON:
- return "Texture2D";
- case HLSL_TEXTURE_CUBE_COMPARISON:
- return "TextureCube";
- case HLSL_TEXTURE_2D_ARRAY_COMPARISON:
- return "Texture2DArray";
- default:
- UNREACHABLE();
- }
-
- return "<unknown read texture type>";
-}
-
-TString TextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
-{
- return TextureString(TextureGroup(type, imageInternalFormat));
-}
-
-TString 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_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_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_COMPARISON:
- return "2D_comparison";
- case HLSL_TEXTURE_CUBE_COMPARISON:
- return "Cube_comparison";
- case HLSL_TEXTURE_2D_ARRAY_COMPARISON:
- return "2DArray_comparison";
- default:
- UNREACHABLE();
- }
-
- return "<unknown texture type>";
-}
-
-TString TextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
-{
- return TextureGroupSuffix(TextureGroup(type, imageInternalFormat));
-}
-
-TString 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();
- }
- }
- case EbtIImageCube:
- {
- switch (imageInternalFormat)
- {
- case EiifRGBA32I:
- case EiifRGBA16I:
- case EiifRGBA8I:
- case EiifR32I:
- return "Cube_int4_";
- default:
- UNREACHABLE();
- }
- }
- case EbtUImageCube:
- {
- switch (imageInternalFormat)
- {
- case EiifRGBA32UI:
- case EiifRGBA16UI:
- case EiifRGBA8UI:
- case EiifR32UI:
- return "Cube_uint4_";
- default:
- UNREACHABLE();
- }
- }
- default:
- // All other types are identified by their group suffix
- return TextureGroupSuffix(type, imageInternalFormat);
- }
-}
-
-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();
- }
- }
- case EbtIImage2D:
- {
- switch (imageInternalFormat)
- {
- case EiifRGBA32I:
- case EiifRGBA16I:
- case EiifRGBA8I:
- case EiifR32I:
- return HLSL_RWTEXTURE_2D_INT4;
- default:
- UNREACHABLE();
- }
- }
- case EbtUImage2D:
- {
- switch (imageInternalFormat)
- {
-
- case EiifRGBA32UI:
- case EiifRGBA16UI:
- case EiifRGBA8UI:
- case EiifR32UI:
- return HLSL_RWTEXTURE_2D_UINT4;
- default:
- UNREACHABLE();
- }
- }
- 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();
- }
- }
- case EbtIImage3D:
- {
- switch (imageInternalFormat)
- {
- case EiifRGBA32I:
- case EiifRGBA16I:
- case EiifRGBA8I:
- case EiifR32I:
- return HLSL_RWTEXTURE_3D_INT4;
- default:
- UNREACHABLE();
- }
- }
- case EbtUImage3D:
- {
- switch (imageInternalFormat)
- {
- case EiifRGBA32UI:
- case EiifRGBA16UI:
- case EiifRGBA8UI:
- case EiifR32UI:
- return HLSL_RWTEXTURE_3D_UINT4;
- default:
- UNREACHABLE();
- }
- }
- 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();
- }
- }
- case EbtIImage2DArray:
- case EbtIImageCube:
- {
- switch (imageInternalFormat)
- {
- case EiifRGBA32I:
- case EiifRGBA16I:
- case EiifRGBA8I:
- case EiifR32I:
- return HLSL_RWTEXTURE_2D_ARRAY_INT4;
- default:
- UNREACHABLE();
- }
- }
- case EbtUImage2DArray:
- case EbtUImageCube:
- {
- switch (imageInternalFormat)
- {
- case EiifRGBA32UI:
- case EiifRGBA16UI:
- case EiifRGBA8UI:
- case EiifR32UI:
- return HLSL_RWTEXTURE_2D_ARRAY_UINT4;
- default:
- UNREACHABLE();
- }
- }
- default:
- UNREACHABLE();
- }
- return HLSL_RWTEXTURE_UNKNOWN;
-}
-
-TString RWTextureString(const HLSLRWTextureGroup RWTextureGroup)
-{
- switch (RWTextureGroup)
- {
- case HLSL_RWTEXTURE_2D_FLOAT4:
- return "RWTexture2D<float4>";
- case HLSL_RWTEXTURE_2D_ARRAY_FLOAT4:
- return "RWTexture2DArray<float4>";
- case HLSL_RWTEXTURE_3D_FLOAT4:
- return "RWTexture3D<float4>";
- case HLSL_RWTEXTURE_2D_UNORM:
- return "RWTexture2D<unorm float4>";
- case HLSL_RWTEXTURE_2D_ARRAY_UNORN:
- return "RWTexture2DArray<unorm float4>";
- case HLSL_RWTEXTURE_3D_UNORM:
- return "RWTexture3D<unorm float4>";
- case HLSL_RWTEXTURE_2D_SNORM:
- return "RWTexture2D<snorm float4>";
- case HLSL_RWTEXTURE_2D_ARRAY_SNORM:
- return "RWTexture2DArray<snorm float4>";
- case HLSL_RWTEXTURE_3D_SNORM:
- return "RWTexture3D<snorm float4>";
- case HLSL_RWTEXTURE_2D_UINT4:
- return "RWTexture2D<uint4>";
- case HLSL_RWTEXTURE_2D_ARRAY_UINT4:
- return "RWTexture2DArray<uint4>";
- case HLSL_RWTEXTURE_3D_UINT4:
- return "RWTexture3D<uint4>";
- case HLSL_RWTEXTURE_2D_INT4:
- return "RWTexture2D<int4>";
- case HLSL_RWTEXTURE_2D_ARRAY_INT4:
- return "RWTexture2DArray<int4>";
- case HLSL_RWTEXTURE_3D_INT4:
- return "RWTexture3D<int4>";
- default:
- UNREACHABLE();
- }
-
- return "<unknown read and write texture type>";
-}
-
-TString RWTextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
-{
- return RWTextureString(RWTextureGroup(type, imageInternalFormat));
-}
-
-TString 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_";
- default:
- UNREACHABLE();
- }
-
- return "<unknown read and write resource>";
-}
-
-TString RWTextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
-{
- return RWTextureGroupSuffix(RWTextureGroup(type, imageInternalFormat));
-}
-
-TString 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();
- }
- }
- case EbtIImageCube:
- {
- switch (imageInternalFormat)
- {
- case EiifRGBA32I:
- case EiifRGBA16I:
- case EiifRGBA8I:
- case EiifR32I:
- return "RWCube_int4_";
- default:
- UNREACHABLE();
- }
- }
- case EbtUImageCube:
- {
- switch (imageInternalFormat)
- {
- case EiifRGBA32UI:
- case EiifRGBA16UI:
- case EiifRGBA8UI:
- case EiifR32UI:
- return "RWCube_uint4_";
- default:
- UNREACHABLE();
- }
- }
- default:
- // All other types are identified by their group suffix
- return TextureGroupSuffix(type, imageInternalFormat);
- }
-}
-
-TString DecorateField(const TString &string, const TStructure &structure)
-{
- if (structure.name().compare(0, 3, "gl_") != 0)
- {
- return Decorate(string);
- }
-
- return string;
-}
-
-TString DecoratePrivate(const TString &privateText)
-{
- return "dx_" + privateText;
-}
-
-TString Decorate(const TString &string)
-{
- if (string.compare(0, 3, "gl_") != 0)
- {
- return "_" + string;
- }
-
- return string;
-}
-
-TString DecorateVariableIfNeeded(const TName &name)
-{
- if (name.isInternal())
- {
- // The name should not have a prefix reserved for user-defined variables or functions.
- ASSERT(name.getString().compare(0, 2, "f_") != 0);
- ASSERT(name.getString().compare(0, 1, "_") != 0);
- return name.getString();
- }
- else
- {
- return Decorate(name.getString());
- }
-}
-
-TString DecorateFunctionIfNeeded(const TName &name)
-{
- if (name.isInternal())
- {
- // The name should not have a prefix reserved for user-defined variables or functions.
- ASSERT(name.getString().compare(0, 2, "f_") != 0);
- ASSERT(name.getString().compare(0, 1, "_") != 0);
- return name.getString();
- }
- ASSERT(name.getString().compare(0, 3, "gl_") != 0);
- // 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_" + name.getString();
-}
-
-TString TypeString(const TType &type)
-{
- const TStructure *structure = type.getStruct();
- if (structure)
- {
- const TString &typeName = structure->name();
- if (typeName != "")
- {
- return StructNameString(*structure);
- }
- else // Nameless structure, define in place
- {
- return StructureHLSL::defineNameless(*structure);
- }
- }
- else if (type.isMatrix())
- {
- int cols = type.getCols();
- int 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 EbtAtomicCounter:
- return "atomic_uint";
- default:
- break;
- }
- }
-
- UNREACHABLE();
- return "<unknown type>";
-}
-
-TString StructNameString(const TStructure &structure)
-{
- if (structure.name().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()) + "_" + structure.name();
-}
-
-TString QualifiedStructNameString(const TStructure &structure,
- bool useHLSLRowMajorPacking,
- bool useStd140Packing)
-{
- if (structure.name() == "")
- {
- 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_";
- }
-
- return prefix + StructNameString(structure);
-}
-
-TString 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";
- default:
- UNREACHABLE();
- }
-
- return "";
-}
-
-TString QualifierString(TQualifier qualifier)
-{
- switch (qualifier)
- {
- case EvqIn:
- return "in";
- case EvqOut:
- return "inout"; // 'out' results in an HLSL error if not all fields are written, for
- // GLSL it's undefined
- case EvqInOut:
- return "inout";
- case EvqConstReadOnly:
- return "const";
- default:
- UNREACHABLE();
- }
-
- return "";
-}
-
-TString DisambiguateFunctionName(const TIntermSequence *parameters)
-{
- TString disambiguatingString;
- for (auto parameter : *parameters)
- {
- const TType &paramType = parameter->getAsTyped()->getType();
- // 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.
- 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.
- disambiguatingString += "_" + TypeString(paramType);
- }
- else 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()->name() != "");
- disambiguatingString += "_" + TypeString(paramType);
- }
- }
- return disambiguatingString;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h
deleted file mode 100644
index daeec8de41..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h
+++ /dev/null
@@ -1,129 +0,0 @@
-//
-// Copyright (c) 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 <vector>
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/Types.h"
-
-#include "angle_gl.h"
-
-class TName;
-
-namespace sh
-{
-
-// 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_INT4,
- HLSL_TEXTURE_3D_INT4,
- HLSL_TEXTURE_2D_ARRAY_INT4,
- HLSL_TEXTURE_2D_MS_INT4,
- HLSL_TEXTURE_2D_UINT4,
- HLSL_TEXTURE_3D_UINT4,
- HLSL_TEXTURE_2D_ARRAY_UINT4,
- HLSL_TEXTURE_2D_MS_UINT4,
-
- // 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_UNKNOWN,
- HLSL_RWTEXTURE_MAX = HLSL_RWTEXTURE_UNKNOWN
-};
-
-HLSLTextureGroup TextureGroup(const TBasicType type,
- TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
-TString TextureString(const HLSLTextureGroup textureGroup);
-TString TextureString(const TBasicType type,
- TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
-TString TextureGroupSuffix(const HLSLTextureGroup type);
-TString TextureGroupSuffix(const TBasicType type,
- TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
-TString TextureTypeSuffix(const TBasicType type,
- TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
-HLSLRWTextureGroup RWTextureGroup(const TBasicType type,
- TLayoutImageInternalFormat imageInternalFormat);
-TString RWTextureString(const HLSLRWTextureGroup textureGroup);
-TString RWTextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat);
-TString RWTextureGroupSuffix(const HLSLRWTextureGroup type);
-TString RWTextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat);
-TString RWTextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat);
-
-TString SamplerString(const TBasicType type);
-TString SamplerString(HLSLTextureGroup type);
-
-// Adds a prefix to user-defined names to avoid naming clashes.
-TString Decorate(const TString &string);
-TString DecorateVariableIfNeeded(const TName &name);
-TString DecorateFunctionIfNeeded(const TName &name);
-TString DecorateField(const TString &string, const TStructure &structure);
-TString DecoratePrivate(const TString &privateText);
-TString TypeString(const TType &type);
-TString StructNameString(const TStructure &structure);
-TString QualifiedStructNameString(const TStructure &structure,
- bool useHLSLRowMajorPacking,
- bool useStd140Packing);
-TString InterpolationString(TQualifier qualifier);
-TString QualifierString(TQualifier qualifier);
-// Parameters may need to be included in function names to disambiguate between overloaded
-// functions.
-TString DisambiguateFunctionName(const TIntermSequence *parameters);
-}
-
-#endif // COMPILER_TRANSLATOR_UTILSHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp
deleted file mode 100644
index 492972b60d..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#include "compiler/translator/ValidateGlobalInitializer.h"
-
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/ParseContext.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class ValidateGlobalInitializerTraverser : public TIntermTraverser
-{
- public:
- ValidateGlobalInitializerTraverser(const TParseContext *context);
-
- void visitSymbol(TIntermSymbol *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; }
- bool issueWarning() const { return mIssueWarning; }
-
- private:
- const TParseContext *mContext;
- bool mIsValid;
- bool mIssueWarning;
-};
-
-void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node)
-{
- const TSymbol *sym =
- mContext->symbolTable.find(node->getSymbol(), mContext->getShaderVersion());
- if (sym->isVariable())
- {
- // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3):
- // Global initializers must be constant expressions.
- const TVariable *var = static_cast<const TVariable *>(sym);
- switch (var->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.
- if (mContext->getShaderVersion() >= 300)
- {
- mIsValid = false;
- }
- else
- {
- mIssueWarning = true;
- }
- break;
- default:
- mIsValid = false;
- }
- }
-}
-
-bool ValidateGlobalInitializerTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- // Disallow calls to user-defined functions and texture lookup functions in global variable
- // initializers.
- // This is done simply by disabling all function calls - built-in math functions don't use
- // the function call ops.
- if (node->isFunctionCall())
- {
- mIsValid = false;
- }
- return true;
-}
-
-bool ValidateGlobalInitializerTraverser::visitBinary(Visit visit, TIntermBinary *node)
-{
- if (node->isAssignment())
- {
- mIsValid = false;
- }
- return true;
-}
-
-bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *node)
-{
- if (node->isAssignment())
- {
- mIsValid = false;
- }
- return true;
-}
-
-ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(const TParseContext *context)
- : TIntermTraverser(true, false, false), mContext(context), mIsValid(true), mIssueWarning(false)
-{
-}
-
-} // namespace
-
-bool ValidateGlobalInitializer(TIntermTyped *initializer,
- const TParseContext *context,
- bool *warning)
-{
- ValidateGlobalInitializerTraverser validate(context);
- initializer->traverse(&validate);
- ASSERT(warning != nullptr);
- *warning = validate.issueWarning();
- return validate.isValid();
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h b/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h
deleted file mode 100644
index 2e7570667a..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#ifndef COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_
-#define COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_
-
-namespace sh
-{
-
-class TIntermTyped;
-class TParseContext;
-
-// Returns true if the initializer is valid.
-bool ValidateGlobalInitializer(TIntermTyped *initializer,
- const TParseContext *context,
- bool *warning);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp
deleted file mode 100644
index 941f79ae51..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp
+++ /dev/null
@@ -1,444 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#include "compiler/translator/ValidateLimitations.h"
-
-#include "angle_gl.h"
-#include "compiler/translator/Diagnostics.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/ParseContext.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->getId();
-}
-
-// 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<int> &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->getId()) != mLoopSymbolIds.end();
- mValid = (symbol->getQualifier() == EvqConst) || isLoopSymbol;
- }
- }
-
- private:
- bool mValid;
- const std::vector<int> 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,
- int shaderVersion,
- 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);
-
- bool withinLoopBody() const;
- 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<int> mLoopSymbolIds;
-};
-
-ValidateLimitationsTraverser::ValidateLimitationsTraverser(sh::GLenum shaderType,
- TSymbolTable *symbolTable,
- int shaderVersion,
- TDiagnostics *diagnostics)
- : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion),
- 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->getSymbol().c_str());
- }
-}
-
-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);
-}
-
-bool ValidateLimitationsTraverser::withinLoopBody() const
-{
- return !mLoopSymbolIds.empty();
-}
-
-bool ValidateLimitationsTraverser::isLoopIndex(TIntermSymbol *symbol)
-{
- return std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(), symbol->getId()) !=
- 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->getSymbol().c_str());
- return -1;
- }
-
- return symbol->getId();
-}
-
-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->getId() != indexSymbolId)
- {
- error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str());
- 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->getSymbol().c_str());
- 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;
- TIntermSymbol *symbol = nullptr;
- if (unOp != nullptr)
- {
- op = unOp->getOp();
- 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->getId() != indexSymbolId)
- {
- error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str());
- 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:
- 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->getSymbol().c_str());
- 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 anonymous
-
-bool ValidateLimitations(TIntermNode *root,
- GLenum shaderType,
- TSymbolTable *symbolTable,
- int shaderVersion,
- TDiagnostics *diagnostics)
-{
- ValidateLimitationsTraverser validate(shaderType, symbolTable, shaderVersion, diagnostics);
- root->traverse(&validate);
- return diagnostics->numErrors() == 0;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h
deleted file mode 100644
index 9149b8c216..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// Copyright (c) 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,
- int shaderVersion,
- TDiagnostics *diagnostics);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp
deleted file mode 100644
index 9dccbf413f..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Copyright (c) 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"
-
-namespace sh
-{
-
-bool ValidateMaxParameters(TIntermBlock *root, unsigned int maxParameters)
-{
- for (TIntermNode *node : *root->getSequence())
- {
- TIntermFunctionDefinition *definition = node->getAsFunctionDefinition();
- if (definition != nullptr &&
- definition->getFunctionPrototype()->getSequence()->size() > maxParameters)
- {
- return false;
- }
- }
- return true;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h b/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h
deleted file mode 100644
index dec7597da4..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// Copyright (c) 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/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp
deleted file mode 100644
index 26f0e81ba7..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-//
-// Copyright (c) 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 <set>
-
-#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/ParseContext.h"
-
-namespace sh
-{
-
-namespace
-{
-void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics)
-{
- diagnostics->error(symbol.getLine(), reason, symbol.getSymbol().c_str());
-}
-
-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<TIntermSymbol *> OutputVector;
- OutputVector mOutputs;
- OutputVector mUnspecifiedLocationOutputs;
- OutputVector mYuvOutputs;
- std::set<std::string> mVisitedSymbols;
-};
-
-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)
-{
- TString name = symbol->getSymbol();
- TQualifier qualifier = symbol->getQualifier();
-
- if (mVisitedSymbols.count(name.c_str()) == 1)
- return;
-
- mVisitedSymbols.insert(name.c_str());
-
- 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 || qualifier == EvqFragDepthEXT)
- {
- mUsesFragDepth = true;
- }
-}
-
-void ValidateOutputsTraverser::validate(TDiagnostics *diagnostics) const
-{
- ASSERT(diagnostics);
- OutputVector validOutputs(mMaxDrawBuffers);
-
- 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<size_t>(type.isArray() ? type.getOutermostArraySize() : 1u);
- const size_t location = static_cast<size_t>(type.getLayoutQualifier().location);
-
- ASSERT(type.getLayoutQualifier().location != -1);
-
- if (location + elementCount <= validOutputs.size())
- {
- for (size_t elementIndex = 0; elementIndex < elementCount; elementIndex++)
- {
- const size_t offsetLocation = location + elementIndex;
- if (validOutputs[offsetLocation])
- {
- std::stringstream strstr;
- strstr << "conflicting output locations with previously defined output '"
- << validOutputs[offsetLocation]->getSymbol() << "'";
- error(*symbol, strstr.str().c_str(), diagnostics);
- }
- else
- {
- validOutputs[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/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h
deleted file mode 100644
index e41ccd990c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// Copyright (c) 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/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp
deleted file mode 100644
index 9f7a264e58..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp
+++ /dev/null
@@ -1,319 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#include "compiler/translator/ValidateSwitch.h"
-
-#include "compiler/translator/Diagnostics.h"
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class ValidateSwitch : public TIntermTraverser
-{
- public:
- static bool validate(TBasicType switchType,
- int shaderVersion,
- TDiagnostics *diagnostics,
- TIntermBlock *statementList,
- const TSourceLoc &loc);
-
- void visitSymbol(TIntermSymbol *) override;
- void visitConstantUnion(TIntermConstantUnion *) override;
- bool visitDeclaration(Visit, TIntermDeclaration *) override;
- bool visitBlock(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, int shaderVersion, TDiagnostics *context);
-
- bool validateInternal(const TSourceLoc &loc);
-
- TBasicType mSwitchType;
- int mShaderVersion;
- TDiagnostics *mDiagnostics;
- bool mCaseTypeMismatch;
- bool mFirstCaseFound;
- bool mStatementBeforeCase;
- bool mLastStatementWasCase;
- int mControlFlowDepth;
- bool mCaseInsideControlFlow;
- int mDefaultCount;
- std::set<int> mCasesSigned;
- std::set<unsigned int> mCasesUnsigned;
- bool mDuplicateCases;
-};
-
-bool ValidateSwitch::validate(TBasicType switchType,
- int shaderVersion,
- TDiagnostics *diagnostics,
- TIntermBlock *statementList,
- const TSourceLoc &loc)
-{
- ValidateSwitch validate(switchType, shaderVersion, diagnostics);
- ASSERT(statementList);
- statementList->traverse(&validate);
- return validate.validateInternal(loc);
-}
-
-ValidateSwitch::ValidateSwitch(TBasicType switchType, int shaderVersion, TDiagnostics *diagnostics)
- : TIntermTraverser(true, false, true),
- mSwitchType(switchType),
- mShaderVersion(shaderVersion),
- mDiagnostics(diagnostics),
- mCaseTypeMismatch(false),
- mFirstCaseFound(false),
- mStatementBeforeCase(false),
- mLastStatementWasCase(false),
- mControlFlowDepth(0),
- mCaseInsideControlFlow(false),
- mDefaultCount(0),
- mDuplicateCases(false)
-{
-}
-
-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, TIntermBlock *)
-{
- if (getParentNode() != nullptr)
- {
- if (!mFirstCaseFound)
- mStatementBeforeCase = true;
- mLastStatementWasCase = false;
- }
- 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");
- }
- bool lastStatementWasCaseError = false;
- if (mLastStatementWasCase)
- {
- if (mShaderVersion == 300)
- {
- lastStatementWasCaseError = true;
- // This error has been proposed to be made optional in GLSL ES 3.00, but dEQP tests
- // still require it.
- mDiagnostics->error(
- loc, "no statement between the last label and the end of the switch statement",
- "switch");
- }
- else
- {
- // The error has been removed from GLSL ES 3.10.
- mDiagnostics->warning(
- loc, "no statement between the last label and the end of the switch statement",
- "switch");
- }
- }
- return !mStatementBeforeCase && !lastStatementWasCaseError && !mCaseInsideControlFlow &&
- !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases;
-}
-
-} // anonymous namespace
-
-bool ValidateSwitchStatementList(TBasicType switchType,
- int shaderVersion,
- TDiagnostics *diagnostics,
- TIntermBlock *statementList,
- const TSourceLoc &loc)
-{
- return ValidateSwitch::validate(switchType, shaderVersion, diagnostics, statementList, loc);
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h
deleted file mode 100644
index 2d2dd70f78..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#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,
- int shaderVersion,
- TDiagnostics *diagnostics,
- TIntermBlock *statementList,
- const TSourceLoc &loc);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_VALIDATESWITCH_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp
deleted file mode 100644
index 9c36fcea78..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// The ValidateVaryingLocations function checks if there exists location conflicts on shader
-// varyings.
-//
-
-#include "ValidateVaryingLocations.h"
-
-#include "compiler/translator/Diagnostics.h"
-#include "compiler/translator/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.getSymbol().c_str());
-}
-
-int GetLocationCount(const TIntermSymbol *varying, bool ignoreVaryingArraySize)
-{
- const auto &varyingType = varying->getType();
- if (varyingType.getStruct() != nullptr)
- {
- ASSERT(!varyingType.isArray());
- int totalLocation = 0;
- for (const auto *field : varyingType.getStruct()->fields())
- {
- const auto *fieldType = field->type();
- ASSERT(fieldType->getStruct() == nullptr && !fieldType->isArray());
-
- totalLocation += fieldType->getSecondarySize();
- }
- return totalLocation;
- }
- // [GL_OES_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.
- else if (ignoreVaryingArraySize)
- {
- // Array-of-arrays cannot be inputs or outputs of a geometry shader.
- // (GL_OES_geometry_shader SPEC issues(5))
- ASSERT(!varyingType.isArrayOfArrays());
- return varyingType.getSecondarySize();
- }
- else
- {
- return varyingType.getSecondarySize() * static_cast<int>(varyingType.getArraySizeProduct());
- }
-}
-
-using VaryingVector = std::vector<const TIntermSymbol *>;
-
-void ValidateShaderInterface(TDiagnostics *diagnostics,
- VaryingVector &varyingVector,
- bool ignoreVaryingArraySize)
-{
- // Location conflicts can only happen when there are two or more varyings in varyingVector.
- if (varyingVector.size() <= 1)
- {
- return;
- }
-
- std::map<int, const TIntermSymbol *> locationMap;
- for (const TIntermSymbol *varying : varyingVector)
- {
- const int location = varying->getType().getLayoutQualifier().location;
- ASSERT(location >= 0);
-
- const int elementCount = GetLocationCount(varying, ignoreVaryingArraySize);
- for (int elementIndex = 0; elementIndex < elementCount; ++elementIndex)
- {
- const int offsetLocation = location + elementIndex;
- if (locationMap.find(offsetLocation) != locationMap.end())
- {
- std::stringstream strstr;
- strstr << "'" << varying->getSymbol()
- << "' conflicting location with previously defined '"
- << locationMap[offsetLocation]->getSymbol() << "'";
- error(*varying, strstr.str().c_str(), diagnostics);
- }
- else
- {
- locationMap[offsetLocation] = varying;
- }
- }
- }
-}
-
-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;
- }
-
- // 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);
-
- ValidateShaderInterface(diagnostics, mInputVaryingsWithLocation,
- mShaderType == GL_GEOMETRY_SHADER_OES);
- ValidateShaderInterface(diagnostics, mOutputVaryingsWithLocation, false);
-}
-
-} // anonymous namespace
-
-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 \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h b/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h
deleted file mode 100644
index 1e53977c68..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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 TDiagnostics;
-
-bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType);
-
-} // namespace sh
-
-#endif \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp
deleted file mode 100644
index 6dd396ff02..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp
+++ /dev/null
@@ -1,413 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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 <algorithm>
-
-#include "angle_gl.h"
-
-#include "compiler/translator/VariablePacker.h"
-#include "common/utilities.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<ShaderVariable> *expanded);
-
-void ExpandStructVariable(const ShaderVariable &variable,
- const std::string &name,
- std::vector<ShaderVariable> *expanded)
-{
- ASSERT(variable.isStruct());
-
- const std::vector<ShaderVariable> &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<ShaderVariable> *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<ShaderVariable> *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<sh::ShaderVariable> *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<unsigned> 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<sh::ShaderVariable> *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;
- }
-}
-
-template <typename T>
-bool CheckVariablesInPackingLimits(unsigned int maxVectors, const std::vector<T> &variables)
-{
- VariablePacker packer;
- std::vector<sh::ShaderVariable> expandedVariables;
- for (const ShaderVariable &variable : variables)
- {
- ExpandVariable(variable, variable.name, &expandedVariables);
- }
- return packer.checkExpandedVariablesWithinPackingLimits(maxVectors, &expandedVariables);
-}
-
-template bool CheckVariablesInPackingLimits<ShaderVariable>(
- unsigned int maxVectors,
- const std::vector<ShaderVariable> &variables);
-template bool CheckVariablesInPackingLimits<Uniform>(unsigned int maxVectors,
- const std::vector<Uniform> &variables);
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h
deleted file mode 100644
index 36b2104cd0..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-// 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 <vector>
-
-#include <GLSLANG/ShaderLang.h>
-
-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.
-template <typename T>
-bool CheckVariablesInPackingLimits(unsigned int maxVectors, const std::vector<T> &variables);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_VARIABLEPACKER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp b/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp
deleted file mode 100644
index 1e79a60991..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright (c) 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.
-//
-// VectorizeVectorScalarArithmetic.cpp: Turn some arithmetic operations that operate on a float
-// vector-scalar pair into vector-vector operations. This is done recursively. Some scalar binary
-// operations inside vector constructors are also turned into vector operations.
-//
-// This is targeted to work around a bug in NVIDIA OpenGL drivers that was reproducible on NVIDIA
-// driver version 387.92. It works around the most common occurrences of the bug.
-
-#include "compiler/translator/VectorizeVectorScalarArithmetic.h"
-
-#include <set>
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class VectorizeVectorScalarArithmeticTraverser : public TIntermTraverser
-{
- public:
- VectorizeVectorScalarArithmeticTraverser(TSymbolTable *symbolTable)
- : TIntermTraverser(true, false, false, symbolTable), mReplaced(false)
- {
- }
-
- bool didReplaceScalarsWithVectors() { return mReplaced; }
- void nextIteration()
- {
- mReplaced = false;
- mModifiedBlocks.clear();
- }
-
- protected:
- bool visitBinary(Visit visit, TIntermBinary *node) override;
- bool visitAggregate(Visit visit, TIntermAggregate *node) override;
-
- private:
- // These helpers should only be called from visitAggregate when visiting a constructor.
- // argBinary is the only argument of the constructor.
- void replaceMathInsideConstructor(TIntermAggregate *node, TIntermBinary *argBinary);
- void replaceAssignInsideConstructor(const TIntermAggregate *node,
- const TIntermBinary *argBinary);
-
- static TIntermTyped *Vectorize(TIntermTyped *node,
- TType vectorType,
- TIntermTraverser::OriginalNode *originalNodeFate);
-
- bool mReplaced;
- std::set<const TIntermBlock *> mModifiedBlocks;
-};
-
-TIntermTyped *VectorizeVectorScalarArithmeticTraverser::Vectorize(
- TIntermTyped *node,
- TType vectorType,
- TIntermTraverser::OriginalNode *originalNodeFate)
-{
- ASSERT(node->isScalar());
- vectorType.setQualifier(EvqTemporary);
- TIntermSequence vectorConstructorArgs;
- vectorConstructorArgs.push_back(node);
- TIntermAggregate *vectorized =
- TIntermAggregate::CreateConstructor(vectorType, &vectorConstructorArgs);
- TIntermTyped *vectorizedFolded = vectorized->fold(nullptr);
- if (originalNodeFate != nullptr)
- {
- if (vectorizedFolded != vectorized)
- {
- *originalNodeFate = OriginalNode::IS_DROPPED;
- }
- else
- {
- *originalNodeFate = OriginalNode::BECOMES_CHILD;
- }
- }
- return vectorizedFolded;
-}
-
-bool VectorizeVectorScalarArithmeticTraverser::visitBinary(Visit /*visit*/, TIntermBinary *node)
-{
- TIntermTyped *left = node->getLeft();
- TIntermTyped *right = node->getRight();
- ASSERT(left);
- ASSERT(right);
- switch (node->getOp())
- {
- case EOpAdd:
- case EOpAddAssign:
- // Only these specific ops are necessary to turn into vector ops.
- break;
- default:
- return true;
- }
- if (node->getBasicType() != EbtFloat)
- {
- // Only float ops have reproduced the bug.
- return true;
- }
- if (left->isScalar() && right->isVector())
- {
- ASSERT(!node->isAssignment());
- ASSERT(!right->isArray());
- OriginalNode originalNodeFate;
- TIntermTyped *leftVectorized = Vectorize(left, right->getType(), &originalNodeFate);
- queueReplacementWithParent(node, left, leftVectorized, originalNodeFate);
- mReplaced = true;
- // Don't replace more nodes in the same subtree on this traversal. However, nodes elsewhere
- // in the tree may still be replaced.
- return false;
- }
- else if (left->isVector() && right->isScalar())
- {
- OriginalNode originalNodeFate;
- TIntermTyped *rightVectorized = Vectorize(right, left->getType(), &originalNodeFate);
- queueReplacementWithParent(node, right, rightVectorized, originalNodeFate);
- mReplaced = true;
- // Don't replace more nodes in the same subtree on this traversal. However, nodes elsewhere
- // in the tree may still be replaced.
- return false;
- }
- return true;
-}
-
-void VectorizeVectorScalarArithmeticTraverser::replaceMathInsideConstructor(
- TIntermAggregate *node,
- TIntermBinary *argBinary)
-{
- // Turn:
- // a * b
- // into:
- // gvec(a) * gvec(b)
-
- TIntermTyped *left = argBinary->getLeft();
- TIntermTyped *right = argBinary->getRight();
- ASSERT(left->isScalar() && right->isScalar());
-
- TType leftVectorizedType = left->getType();
- leftVectorizedType.setPrimarySize(static_cast<unsigned char>(node->getType().getNominalSize()));
- TIntermTyped *leftVectorized = Vectorize(left, leftVectorizedType, nullptr);
- TType rightVectorizedType = right->getType();
- rightVectorizedType.setPrimarySize(
- static_cast<unsigned char>(node->getType().getNominalSize()));
- TIntermTyped *rightVectorized = Vectorize(right, rightVectorizedType, nullptr);
-
- TIntermBinary *newArg = new TIntermBinary(argBinary->getOp(), leftVectorized, rightVectorized);
- queueReplacementWithParent(node, argBinary, newArg, OriginalNode::IS_DROPPED);
-}
-
-void VectorizeVectorScalarArithmeticTraverser::replaceAssignInsideConstructor(
- const TIntermAggregate *node,
- const TIntermBinary *argBinary)
-{
- // Turn:
- // gvec(a *= b);
- // into:
- // // This is inserted into the parent block:
- // gvec s0 = gvec(a);
- //
- // // This goes where the gvec constructor used to be:
- // ((s0 *= b, a = s0.x), s0);
-
- TIntermTyped *left = argBinary->getLeft();
- TIntermTyped *right = argBinary->getRight();
- ASSERT(left->isScalar() && right->isScalar());
- ASSERT(!left->hasSideEffects());
-
- TType vecType = node->getType();
- vecType.setQualifier(EvqTemporary);
-
- nextTemporaryId();
- // gvec s0 = gvec(a);
- // s0 is called "tempAssignmentTarget" below.
- TIntermTyped *tempAssignmentTargetInitializer = Vectorize(left->deepCopy(), vecType, nullptr);
- TIntermDeclaration *tempAssignmentTargetDeclaration =
- createTempInitDeclaration(tempAssignmentTargetInitializer);
-
- // s0 *= b
- TOperator compoundAssignmentOp = argBinary->getOp();
- if (compoundAssignmentOp == EOpMulAssign)
- {
- compoundAssignmentOp = EOpVectorTimesScalarAssign;
- }
- TIntermBinary *replacementCompoundAssignment =
- new TIntermBinary(compoundAssignmentOp, createTempSymbol(vecType), right->deepCopy());
-
- // s0.x
- TVector<int> swizzleXOffset;
- swizzleXOffset.push_back(0);
- TIntermSwizzle *tempAssignmentTargetX =
- new TIntermSwizzle(createTempSymbol(vecType), swizzleXOffset);
- // a = s0.x
- TIntermBinary *replacementAssignBackToTarget =
- new TIntermBinary(EOpAssign, left->deepCopy(), tempAssignmentTargetX);
-
- // s0 *= b, a = s0.x
- TIntermBinary *replacementSequenceLeft =
- new TIntermBinary(EOpComma, replacementCompoundAssignment, replacementAssignBackToTarget);
- // (s0 *= b, a = s0.x), s0
- TIntermBinary *replacementSequence =
- new TIntermBinary(EOpComma, replacementSequenceLeft, createTempSymbol(vecType));
-
- insertStatementInParentBlock(tempAssignmentTargetDeclaration);
- queueReplacement(replacementSequence, OriginalNode::IS_DROPPED);
-}
-
-bool VectorizeVectorScalarArithmeticTraverser::visitAggregate(Visit /*visit*/,
- TIntermAggregate *node)
-{
- // Transform scalar binary expressions inside vector constructors.
- if (!node->isConstructor() || !node->isVector() || node->getSequence()->size() != 1)
- {
- return true;
- }
- TIntermTyped *argument = node->getSequence()->back()->getAsTyped();
- ASSERT(argument);
- if (!argument->isScalar() || argument->getBasicType() != EbtFloat)
- {
- return true;
- }
- TIntermBinary *argBinary = argument->getAsBinaryNode();
- if (!argBinary)
- {
- return true;
- }
-
- // Only specific ops are necessary to change.
- switch (argBinary->getOp())
- {
- case EOpMul:
- case EOpDiv:
- {
- replaceMathInsideConstructor(node, argBinary);
- mReplaced = true;
- // Don't replace more nodes in the same subtree on this traversal. However, nodes
- // elsewhere in the tree may still be replaced.
- return false;
- }
- case EOpMulAssign:
- case EOpDivAssign:
- {
- // The case where the left side has side effects is too complicated to deal with, so we
- // leave that be.
- if (!argBinary->getLeft()->hasSideEffects())
- {
- const TIntermBlock *parentBlock = getParentBlock();
- // We can't do more than one insertion to the same block on the same traversal.
- if (mModifiedBlocks.find(parentBlock) == mModifiedBlocks.end())
- {
- replaceAssignInsideConstructor(node, argBinary);
- mModifiedBlocks.insert(parentBlock);
- mReplaced = true;
- // Don't replace more nodes in the same subtree on this traversal.
- // However, nodes elsewhere in the tree may still be replaced.
- return false;
- }
- }
- break;
- }
- default:
- return true;
- }
- return true;
-}
-
-} // anonymous namespace
-
-void VectorizeVectorScalarArithmetic(TIntermBlock *root, TSymbolTable *symbolTable)
-{
- VectorizeVectorScalarArithmeticTraverser traverser(symbolTable);
- do
- {
- traverser.nextIteration();
- root->traverse(&traverser);
- traverser.updateTree();
- } while (traverser.didReplaceScalarsWithVectors());
-}
-
-} // namespace sh \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h b/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h
deleted file mode 100644
index 69f092e039..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 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.
-//
-// VectorizeVectorScalarArithmetic.h: Turn some arithmetic operations that operate on a float
-// vector-scalar pair into vector-vector operations. This is done recursively. Some scalar binary
-// operations inside vector constructors are also turned into vector operations.
-//
-// This is targeted to work around a bug in NVIDIA OpenGL drivers that was reproducible on NVIDIA
-// driver version 387.92. It works around the most common occurrences of the bug.
-
-#ifndef COMPILER_TRANSLATOR_VECTORIZEVECTORSCALARARITHMETIC_H_
-#define COMPILER_TRANSLATOR_VECTORIZEVECTORSCALARARITHMETIC_H_
-
-namespace sh
-{
-
-class TIntermBlock;
-class TSymbolTable;
-
-void VectorizeVectorScalarArithmetic(TIntermBlock *root, TSymbolTable *symbolTable);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_VECTORIZEVECTORSCALARARITHMETIC_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp
deleted file mode 100644
index 81688765b8..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-//
-// Copyright (c) 2002-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/VersionGLSL.h"
-
-#include "angle_gl.h"
-
-namespace sh
-{
-
-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->getSymbol() == "gl_PointCoord")
- {
- 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::visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node)
-{
- ensureVersionIsAtLeast(GLSL_VERSION_120);
- return true;
-}
-
-bool TVersionGLSL::visitFunctionPrototype(Visit, TIntermFunctionPrototype *node)
-{
- const TIntermSequence &params = *(node->getSequence());
- for (TIntermSequence::const_iterator iter = params.begin(); iter != params.end(); ++iter)
- {
- const TIntermTyped *param = (*iter)->getAsTyped();
- if (param->isArray())
- {
- TQualifier qualifier = param->getQualifier();
- if ((qualifier == EvqOut) || (qualifier == EvqInOut))
- {
- ensureVersionIsAtLeast(GLSL_VERSION_120);
- break;
- }
- }
- }
- // Fully processed. No need to visit children.
- return false;
-}
-
-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/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h
deleted file mode 100644
index 8b82eb9615..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// Copyright (c) 2002-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.
-//
-
-#ifndef COMPILER_TRANSLATOR_VERSIONGLSL_H_
-#define COMPILER_TRANSLATOR_VERSIONGLSL_H_
-
-#include "compiler/translator/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 visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node) override;
- bool visitFunctionPrototype(Visit, 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/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp b/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp
deleted file mode 100644
index 85a11c998d..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-//
-// Copyright (c) 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/WrapSwitchStatementsInBlocks.h"
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class WrapSwitchStatementsInBlocksTraverser : public TIntermTraverser
-{
- public:
- WrapSwitchStatementsInBlocksTraverser() : TIntermTraverser(true, false, false), mDidWrap(false)
- {
- }
-
- bool visitSwitch(Visit visit, TIntermSwitch *node) override;
-
- bool didWrap() const { return mDidWrap; }
-
- private:
- bool mDidWrap;
-};
-
-bool WrapSwitchStatementsInBlocksTraverser::visitSwitch(Visit, TIntermSwitch *node)
-{
- std::vector<TIntermDeclaration *> 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.push_back(NodeReplaceWithMultipleEntry(
- node->getStatementList(), declaration, emptyReplacement));
-
- declarationInBlock->appendDeclarator(declaratorAsSymbol->deepCopy());
- }
- 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);
- mDidWrap = true;
-
- // 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(TIntermBlock *root)
-{
- WrapSwitchStatementsInBlocksTraverser traverser;
- root->traverse(&traverser);
- traverser.updateTree();
- return traverser.didWrap();
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h b/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h
deleted file mode 100644
index bc0179926d..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 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_WRAPSWITCHSTATEMENTSINBLOCKS_H_
-#define COMPILER_TRANSLATOR_WRAPSWITCHSTATEMENTSINBLOCKS_H_
-
-namespace sh
-{
-
-class TIntermBlock;
-
-// Wrap switch statements in the AST into blocks when needed. Returns true if the AST was changed.
-bool WrapSwitchStatementsInBlocks(TIntermBlock *root);
-
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_WRAPSWITCHSTATEMENTSINBLOCKS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp b/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp
deleted file mode 100644
index fd8c450c20..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-//
-// Copyright (c) 2013-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.
-//
-// blocklayout.cpp:
-// Implementation for block layout classes and methods.
-//
-
-#include "compiler/translator/blocklayout.h"
-
-#include "common/mathutil.h"
-#include "common/utilities.h"
-
-namespace sh
-{
-
-namespace
-{
-bool IsRowMajorLayout(const InterfaceBlockField &var)
-{
- return var.isRowMajorLayout;
-}
-
-bool IsRowMajorLayout(const ShaderVariable &var)
-{
- return false;
-}
-
-template <typename VarT>
-void GetUniformBlockStructMemberInfo(const std::vector<VarT> &fields,
- const std::string &fieldName,
- sh::BlockLayoutEncoder *encoder,
- bool inRowMajorLayout,
- BlockLayoutMap *blockInfoOut)
-{
- encoder->enterAggregateType();
- GetUniformBlockInfo(fields, fieldName, encoder, inRowMajorLayout, blockInfoOut);
- encoder->exitAggregateType();
-}
-
-template <typename VarT>
-void GetUniformBlockStructArrayMemberInfo(const VarT &field,
- unsigned int arrayNestingIndex,
- const std::string &arrayName,
- sh::BlockLayoutEncoder *encoder,
- bool inRowMajorLayout,
- BlockLayoutMap *blockInfoOut)
-{
- // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
- // innermost.
- const unsigned int currentArraySize = field.getNestedArraySize(arrayNestingIndex);
- for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
- {
- const std::string elementName = arrayName + ArrayString(arrayElement);
- if (arrayNestingIndex + 1u < field.arraySizes.size())
- {
- GetUniformBlockStructArrayMemberInfo(field, arrayNestingIndex + 1u, elementName,
- encoder, inRowMajorLayout, blockInfoOut);
- }
- else
- {
- GetUniformBlockStructMemberInfo(field.fields, elementName, encoder, inRowMajorLayout,
- blockInfoOut);
- }
- }
-}
-
-template <typename VarT>
-void GetUniformBlockArrayOfArraysMemberInfo(const VarT &field,
- unsigned int arrayNestingIndex,
- const std::string &arrayName,
- sh::BlockLayoutEncoder *encoder,
- bool inRowMajorLayout,
- BlockLayoutMap *blockInfoOut)
-{
- const unsigned int currentArraySize = field.getNestedArraySize(arrayNestingIndex);
- for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
- {
- const std::string elementName = arrayName + ArrayString(arrayElement);
- if (arrayNestingIndex + 2u < field.arraySizes.size())
- {
- GetUniformBlockArrayOfArraysMemberInfo(field, arrayNestingIndex + 1u, elementName,
- encoder, inRowMajorLayout, blockInfoOut);
- }
- else
- {
- std::vector<unsigned int> innermostArraySize(
- 1u, field.getNestedArraySize(arrayNestingIndex + 1u));
- (*blockInfoOut)[elementName] =
- encoder->encodeType(field.type, innermostArraySize, inRowMajorLayout);
- }
- }
-}
-
-} // anonymous namespace
-
-BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0)
-{
-}
-
-BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type,
- const std::vector<unsigned int> &arraySizes,
- bool isRowMajorMatrix)
-{
- int arrayStride;
- int matrixStride;
-
- getBlockLayoutInfo(type, arraySizes, isRowMajorMatrix, &arrayStride, &matrixStride);
-
- const BlockMemberInfo memberInfo(static_cast<int>(mCurrentOffset * BytesPerComponent),
- static_cast<int>(arrayStride * BytesPerComponent),
- static_cast<int>(matrixStride * BytesPerComponent),
- isRowMajorMatrix);
-
- advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride, matrixStride);
-
- return memberInfo;
-}
-
-// static
-size_t BlockLayoutEncoder::getBlockRegister(const BlockMemberInfo &info)
-{
- return (info.offset / BytesPerComponent) / ComponentsPerRegister;
-}
-
-// static
-size_t BlockLayoutEncoder::getBlockRegisterElement(const BlockMemberInfo &info)
-{
- return (info.offset / BytesPerComponent) % ComponentsPerRegister;
-}
-
-void BlockLayoutEncoder::nextRegister()
-{
- mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, ComponentsPerRegister);
-}
-
-Std140BlockEncoder::Std140BlockEncoder()
-{
-}
-
-void Std140BlockEncoder::enterAggregateType()
-{
- nextRegister();
-}
-
-void Std140BlockEncoder::exitAggregateType()
-{
- nextRegister();
-}
-
-void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
- const std::vector<unsigned int> &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)) == BytesPerComponent);
-
- size_t baseAlignment = 0;
- int matrixStride = 0;
- int arrayStride = 0;
-
- if (gl::IsMatrixType(type))
- {
- baseAlignment = ComponentsPerRegister;
- matrixStride = ComponentsPerRegister;
-
- if (!arraySizes.empty())
- {
- const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
- arrayStride = ComponentsPerRegister * numRegisters;
- }
- }
- else if (!arraySizes.empty())
- {
- baseAlignment = ComponentsPerRegister;
- arrayStride = ComponentsPerRegister;
- }
- else
- {
- const int numComponents = gl::VariableComponentCount(type);
- baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents));
- }
-
- mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
-
- *matrixStrideOut = matrixStride;
- *arrayStrideOut = arrayStride;
-}
-
-void Std140BlockEncoder::advanceOffset(GLenum type,
- const std::vector<unsigned int> &arraySizes,
- bool isRowMajorMatrix,
- int arrayStride,
- int matrixStride)
-{
- if (!arraySizes.empty())
- {
- mCurrentOffset += arrayStride * gl::ArraySizeProduct(arraySizes);
- }
- else if (gl::IsMatrixType(type))
- {
- ASSERT(matrixStride == ComponentsPerRegister);
- const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
- mCurrentOffset += ComponentsPerRegister * numRegisters;
- }
- else
- {
- mCurrentOffset += gl::VariableComponentCount(type);
- }
-}
-
-template <typename VarT>
-void GetUniformBlockInfo(const std::vector<VarT> &fields,
- const std::string &prefix,
- sh::BlockLayoutEncoder *encoder,
- bool inRowMajorLayout,
- BlockLayoutMap *blockInfoOut)
-{
- for (const VarT &field : fields)
- {
- // Skip samplers. On Vulkan we use this for the default uniform block, so samplers may be
- // included.
- if (gl::IsSamplerType(field.type))
- {
- continue;
- }
-
- const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
-
- if (field.isStruct())
- {
- bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
-
- if (field.isArray())
- {
- GetUniformBlockStructArrayMemberInfo(field, 0u, fieldName, encoder, rowMajorLayout,
- blockInfoOut);
- }
- else
- {
- GetUniformBlockStructMemberInfo(field.fields, fieldName, encoder, rowMajorLayout,
- blockInfoOut);
- }
- }
- else if (field.isArrayOfArrays())
- {
- bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
- GetUniformBlockArrayOfArraysMemberInfo(field, 0u, fieldName, encoder, isRowMajorMatrix,
- blockInfoOut);
- }
- else
- {
- bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
- (*blockInfoOut)[fieldName] =
- encoder->encodeType(field.type, field.arraySizes, isRowMajorMatrix);
- }
- }
-}
-
-template void GetUniformBlockInfo(const std::vector<InterfaceBlockField> &,
- const std::string &,
- sh::BlockLayoutEncoder *,
- bool,
- BlockLayoutMap *);
-
-template void GetUniformBlockInfo(const std::vector<Uniform> &,
- const std::string &,
- sh::BlockLayoutEncoder *,
- bool,
- BlockLayoutMap *);
-
-template void GetUniformBlockInfo(const std::vector<ShaderVariable> &,
- const std::string &,
- sh::BlockLayoutEncoder *,
- bool,
- BlockLayoutMap *);
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayout.h b/src/3rdparty/angle/src/compiler/translator/blocklayout.h
deleted file mode 100644
index 2b7acf4e60..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/blocklayout.h
+++ /dev/null
@@ -1,144 +0,0 @@
-//
-// Copyright (c) 2013-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.
-//
-// blocklayout.h:
-// Methods and classes related to uniform layout and packing in GLSL and HLSL.
-//
-
-#ifndef COMMON_BLOCKLAYOUT_H_
-#define COMMON_BLOCKLAYOUT_H_
-
-#include <cstddef>
-#include <map>
-#include <vector>
-
-#include "angle_gl.h"
-#include <GLSLANG/ShaderLang.h>
-
-namespace sh
-{
-struct ShaderVariable;
-struct InterfaceBlockField;
-struct Uniform;
-struct Varying;
-struct InterfaceBlock;
-
-struct BlockMemberInfo
-{
- BlockMemberInfo()
- : offset(-1),
- arrayStride(-1),
- matrixStride(-1),
- isRowMajorMatrix(false),
- topLevelArrayStride(-1)
- {
- }
-
- BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
- : offset(offset),
- arrayStride(arrayStride),
- matrixStride(matrixStride),
- isRowMajorMatrix(isRowMajorMatrix),
- topLevelArrayStride(-1)
- {
- }
-
- BlockMemberInfo(int offset,
- int arrayStride,
- int matrixStride,
- bool isRowMajorMatrix,
- int topLevelArrayStride)
- : offset(offset),
- arrayStride(arrayStride),
- matrixStride(matrixStride),
- isRowMajorMatrix(isRowMajorMatrix),
- topLevelArrayStride(topLevelArrayStride)
- {
- }
-
- static BlockMemberInfo getDefaultBlockInfo() { return BlockMemberInfo(-1, -1, -1, false, -1); }
-
- int offset;
- int arrayStride;
- int matrixStride;
- bool isRowMajorMatrix;
- int topLevelArrayStride; // Only used for shader storage block members.
-};
-
-class BlockLayoutEncoder
-{
- public:
- BlockLayoutEncoder();
- virtual ~BlockLayoutEncoder() {}
-
- BlockMemberInfo encodeType(GLenum type,
- const std::vector<unsigned int> &arraySizes,
- bool isRowMajorMatrix);
-
- size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
-
- virtual void enterAggregateType() = 0;
- virtual void exitAggregateType() = 0;
-
- static const size_t BytesPerComponent = 4u;
- static const unsigned int ComponentsPerRegister = 4u;
-
- static size_t getBlockRegister(const BlockMemberInfo &info);
- static size_t getBlockRegisterElement(const BlockMemberInfo &info);
-
- protected:
- size_t mCurrentOffset;
-
- void nextRegister();
-
- virtual void getBlockLayoutInfo(GLenum type,
- const std::vector<unsigned int> &arraySizes,
- bool isRowMajorMatrix,
- int *arrayStrideOut,
- int *matrixStrideOut) = 0;
- virtual void advanceOffset(GLenum type,
- const std::vector<unsigned int> &arraySizes,
- bool isRowMajorMatrix,
- int arrayStride,
- int matrixStride) = 0;
-};
-
-// 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() override;
- void exitAggregateType() override;
-
- protected:
- void getBlockLayoutInfo(GLenum type,
- const std::vector<unsigned int> &arraySizes,
- bool isRowMajorMatrix,
- int *arrayStrideOut,
- int *matrixStrideOut) override;
- void advanceOffset(GLenum type,
- const std::vector<unsigned int> &arraySizes,
- bool isRowMajorMatrix,
- int arrayStride,
- int matrixStride) override;
-};
-
-using BlockLayoutMap = std::map<std::string, BlockMemberInfo>;
-
-// Only valid to call with ShaderVariable, InterfaceBlockField and Uniform.
-template <typename VarT>
-void GetUniformBlockInfo(const std::vector<VarT> &fields,
- const std::string &prefix,
- sh::BlockLayoutEncoder *encoder,
- bool inRowMajorLayout,
- BlockLayoutMap *blockLayoutMap);
-
-} // namespace sh
-
-#endif // COMMON_BLOCKLAYOUT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp
deleted file mode 100644
index 867821f1ea..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-//
-// Copyright (c) 2013-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.
-//
-// 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()
-{
- nextRegister();
-}
-
-void HLSLBlockEncoder::exitAggregateType()
-{
-}
-
-void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
- const std::vector<unsigned int> &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)) == BytesPerComponent);
-
- 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())
- {
- nextRegister();
- }
-
- if (gl::IsMatrixType(type))
- {
- matrixStride = ComponentsPerRegister;
-
- if (!arraySizes.empty())
- {
- const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
- arrayStride = ComponentsPerRegister * numRegisters;
- }
- }
- else if (!arraySizes.empty())
- {
- arrayStride = ComponentsPerRegister;
- }
- else if (isPacked())
- {
- int numComponents = gl::VariableComponentCount(type);
- if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister)
- {
- nextRegister();
- }
- }
-
- *matrixStrideOut = matrixStride;
- *arrayStrideOut = arrayStride;
-}
-
-void HLSLBlockEncoder::advanceOffset(GLenum typeIn,
- const std::vector<unsigned int> &arraySizes,
- bool isRowMajorMatrix,
- int arrayStride,
- int matrixStride)
-{
- GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn);
-
- if (!arraySizes.empty())
- {
- mCurrentOffset += arrayStride * (gl::ArraySizeProduct(arraySizes) - 1);
- }
-
- if (gl::IsMatrixType(type))
- {
- ASSERT(matrixStride == ComponentsPerRegister);
- const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
- const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix);
- mCurrentOffset += ComponentsPerRegister * (numRegisters - 1);
- mCurrentOffset += numComponents;
- }
- else if (isPacked())
- {
- mCurrentOffset += gl::VariableComponentCount(type);
- }
- else
- {
- mCurrentOffset += ComponentsPerRegister;
- }
-}
-
-void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
-{
- mCurrentOffset += (numRegisters * ComponentsPerRegister);
-}
-
-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 <class ShaderVarType>
-void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
-{
- if (variable.isStruct())
- {
- for (size_t arrayElement = 0; arrayElement < variable.getArraySizeProduct(); arrayElement++)
- {
- encoder->enterAggregateType();
-
- for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++)
- {
- HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder);
- }
-
- encoder->exitAggregateType();
- }
- }
- 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 Uniform &variable, ShShaderOutput outputType)
-{
- HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType), true);
- HLSLVariableRegisterCount(variable, &encoder);
-
- const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
- return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) /
- registerBytes);
-}
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h
deleted file mode 100644
index 8f4a51a906..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h
+++ /dev/null
@@ -1,68 +0,0 @@
-//
-// Copyright (c) 2013-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.
-//
-// blocklayout.h:
-// Methods and classes related to uniform layout and packing in GLSL and HLSL.
-//
-
-#ifndef COMMON_BLOCKLAYOUTHLSL_H_
-#define COMMON_BLOCKLAYOUTHLSL_H_
-
-#include <cstddef>
-#include <vector>
-
-#include "angle_gl.h"
-#include "blocklayout.h"
-#include <GLSLANG/ShaderLang.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() override;
- void exitAggregateType() 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<unsigned int> &arraySizes,
- bool isRowMajorMatrix,
- int *arrayStrideOut,
- int *matrixStrideOut) override;
- void advanceOffset(GLenum type,
- const std::vector<unsigned int> &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 Uniform &variable, ShShaderOutput outputType);
-}
-
-#endif // COMMON_BLOCKLAYOUTHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json b/src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json
deleted file mode 100644
index 32e500fe67..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json
+++ /dev/null
@@ -1,1382 +0,0 @@
-[
- {
- "op":"mod",
- "return_type":"float",
- "args":[
- "float x",
- "float y"
- ],
- "body":[
- "return x - y * floor(x / y);"
- ]
- },
- {
- "op":"mod",
- "return_type":"float2",
- "args":[
- "float2 x",
- "float2 y"
- ],
- "body":[
- "return x - y * floor(x / y);"
- ]
- },
- {
- "op":"mod",
- "return_type":"float2",
- "args":[
- "float2 x",
- "float y"
- ],
- "body":[
- "return x - y * floor(x / y);"
- ]
- },
- {
- "op":"mod",
- "return_type":"float3",
- "args":[
- "float3 x",
- "float3 y"
- ],
- "body":[
- "return x - y * floor(x / y);"
- ]
- },
- {
- "op":"mod",
- "return_type":"float3",
- "args":[
- "float3 x",
- "float y"
- ],
- "body":[
- "return x - y * floor(x / y);"
- ]
- },
- {
- "op":"mod",
- "return_type":"float4",
- "args":[
- "float4 x",
- "float4 y"
- ],
- "body":[
- "return x - y * floor(x / y);"
- ]
- },
- {
- "op":"mod",
- "return_type":"float4",
- "args":[
- "float4 x",
- "float y"
- ],
- "body":[
- "return x - y * floor(x / y);"
- ]
- },
- {
- "op":"frexp",
- "return_type":"float",
- "args":[
- "float x",
- "out int exp"
- ],
- "body":[
- "float fexp;",
- "float mantissa = frexp(abs(x), fexp) * sign(x);",
- "exp = int(fexp);",
- "return mantissa;"
- ]
- },
- {
- "op":"frexp",
- "return_type":"float2",
- "args":[
- "float2 x",
- "out int2 exp"
- ],
- "body":[
- "float2 fexp;",
- "float2 mantissa = frexp(abs(x), fexp) * sign(x);",
- "exp = int2(fexp);",
- "return mantissa;"
- ]
- },
- {
- "op":"frexp",
- "return_type":"float3",
- "args":[
- "float3 x",
- "out int3 exp"
- ],
- "body":[
- "float3 fexp;",
- "float3 mantissa = frexp(abs(x), fexp) * sign(x);",
- "exp = int3(fexp);",
- "return mantissa;"
- ]
- },
- {
- "op":"frexp",
- "return_type":"float4",
- "args":[
- "float4 x",
- "out int4 exp"
- ],
- "body":[
- "float4 fexp;",
- "float4 mantissa = frexp(abs(x), fexp) * sign(x);",
- "exp = int4(fexp);",
- "return mantissa;"
- ]
- },
- {
- "op":"ldexp",
- "return_type":"float",
- "args":[
- "float x",
- "int exp"
- ],
- "body":[
- "return ldexp(x, float(exp));"
- ]
- },
- {
- "op":"ldexp",
- "return_type":"float2",
- "args":[
- "float2 x",
- "int2 exp"
- ],
- "body":[
- "return ldexp(x, float2(exp));"
- ]
- },
- {
- "op":"ldexp",
- "return_type":"float3",
- "args":[
- "float3 x",
- "int3 exp"
- ],
- "body":[
- "return ldexp(x, float3(exp));"
- ]
- },
- {
- "op":"ldexp",
- "return_type":"float4",
- "args":[
- "float4 x",
- "int4 exp"
- ],
- "body":[
- "return ldexp(x, float4(exp));"
- ]
- },
- {
- "op":"faceforward",
- "return_type":"float",
- "args":[
- "float N",
- "float I",
- "float Nref"
- ],
- "body":[
- "if(dot(Nref, I) >= 0)",
- "{",
- " return -N;",
- "}",
- "else",
- "{",
- " return N;",
- "}"
- ]
- },
- {
- "op":"faceforward",
- "return_type":"float2",
- "args":[
- "float2 N",
- "float2 I",
- "float2 Nref"
- ],
- "body":[
- "if(dot(Nref, I) >= 0)",
- "{",
- " return -N;",
- "}",
- "else",
- "{",
- " return N;",
- "}"
- ]
- },
- {
- "op":"faceforward",
- "return_type":"float3",
- "args":[
- "float3 N",
- "float3 I",
- "float3 Nref"
- ],
- "body":[
- "if(dot(Nref, I) >= 0)",
- "{",
- " return -N;",
- "}",
- "else",
- "{",
- " return N;",
- "}"
- ]
- },
- {
- "op":"faceforward",
- "return_type":"float4",
- "args":[
- "float4 N",
- "float4 I",
- "float4 Nref"
- ],
- "body":[
- "if(dot(Nref, I) >= 0)",
- "{",
- " return -N;",
- "}",
- "else",
- "{",
- " return N;",
- "}"
- ]
- },
- {
- "op":"atan",
- "return_type":"float",
- "args":[
- "float y",
- "float x"
- ],
- "body":[
- "if(x == 0 && y == 0) x = 1;",
- "return atan2(y, x);"
- ]
- },
- {
- "op":"atan",
- "return_type":"float2",
- "args":[
- "float2 y",
- "float2 x"
- ],
- "body":[
- "if(x[0] == 0 && y[0] == 0) x[0] = 1;",
- "if(x[1] == 0 && y[1] == 0) x[1] = 1;",
- "return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));"
- ]
- },
- {
- "op":"atan",
- "return_type":"float3",
- "args":[
- "float3 y",
- "float3 x"
- ],
- "body":[
- "if(x[0] == 0 && y[0] == 0) x[0] = 1;",
- "if(x[1] == 0 && y[1] == 0) x[1] = 1;",
- "if(x[2] == 0 && y[2] == 0) x[2] = 1;",
- "return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));"
- ]
- },
- {
- "op":"atan",
- "return_type":"float4",
- "args":[
- "float4 y",
- "float4 x"
- ],
- "body":[
- "if(x[0] == 0 && y[0] == 0) x[0] = 1;",
- "if(x[1] == 0 && y[1] == 0) x[1] = 1;",
- "if(x[2] == 0 && y[2] == 0) x[2] = 1;",
- "if(x[3] == 0 && y[3] == 0) x[3] = 1;",
- "return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], ",
- "x[2]), atan2(y[3], x[3]));"
- ]
- },
- {
- "op":"asinh",
- "return_type":"float",
- "args":[
- "in float x"
- ],
- "body":[
- "return log(x + sqrt(pow(x, 2.0) + 1.0));"
- ]
- },
- {
- "op":"asinh",
- "return_type":"float2",
- "args":[
- "in float2 x"
- ],
- "body":[
- "return log(x + sqrt(pow(x, 2.0) + 1.0));"
- ]
- },
- {
- "op":"asinh",
- "return_type":"float3",
- "args":[
- "in float3 x"
- ],
- "body":[
- "return log(x + sqrt(pow(x, 2.0) + 1.0));"
- ]
- },
- {
- "op":"asinh",
- "return_type":"float4",
- "args":[
- "in float4 x"
- ],
- "body":[
- "return log(x + sqrt(pow(x, 2.0) + 1.0));"
- ]
- },
- {
- "op":"acosh",
- "return_type":"float",
- "args":[
- "in float x"
- ],
- "body":[
- "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));"
- ]
- },
- {
- "op":"acosh",
- "return_type":"float2",
- "args":[
- "in float2 x"
- ],
- "body":[
- "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));"
- ]
- },
- {
- "op":"acosh",
- "return_type":"float3",
- "args":[
- "in float3 x"
- ],
- "body":[
- "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));"
- ]
- },
- {
- "op":"acosh",
- "return_type":"float4",
- "args":[
- "in float4 x"
- ],
- "body":[
- "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));"
- ]
- },
- {
- "op":"atanh",
- "return_type":"float",
- "args":[
- "in float x"
- ],
- "body":[
- "return 0.5 * log((1.0 + x) / (1.0 - x));"
- ]
- },
- {
- "op":"atanh",
- "return_type":"float2",
- "args":[
- "in float2 x"
- ],
- "body":[
- "return 0.5 * log((1.0 + x) / (1.0 - x));"
- ]
- },
- {
- "op":"atanh",
- "return_type":"float3",
- "args":[
- "in float3 x"
- ],
- "body":[
- "return 0.5 * log((1.0 + x) / (1.0 - x));"
- ]
- },
- {
- "op":"atanh",
- "return_type":"float4",
- "args":[
- "in float4 x"
- ],
- "body":[
- "return 0.5 * log((1.0 + x) / (1.0 - x));"
- ]
- },
- {
- "op":"roundEven",
- "return_type":"float",
- "args":[
- "in float x"
- ],
- "body":[
- "return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);"
- ]
- },
- {
- "op":"roundEven",
- "return_type":"float2",
- "args":[
- "in float2 x"
- ],
- "body":[
- "float2 v;",
- "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);",
- "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);",
- "return v;"
- ]
- },
- {
- "op":"roundEven",
- "return_type":"float3",
- "args":[
- "in float3 x"
- ],
- "body":[
- "float3 v;",
- "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);",
- "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);",
- "v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);",
- "return v;"
- ]
- },
- {
- "op":"roundEven",
- "return_type":"float4",
- "args":[
- "in float4 x"
- ],
- "body":[
- "float4 v;",
- "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);",
- "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);",
- "v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);",
- "v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);",
- "return v;"
- ]
- },
- {
- "op":"packSnorm2x16",
- "return_type":"uint",
- "args":[
- "in float2 v"
- ],
- "helper":[
- "int webgl_toSnorm16(in float x) {",
- " return int(round(clamp(x, -1.0, 1.0) * 32767.0));",
- "}"
- ],
- "body":[
- "int x = webgl_toSnorm16(v.x);",
- "int y = webgl_toSnorm16(v.y);",
- "return (asuint(y) << 16) | (asuint(x) & 0xffffu);"
- ]
- },
- {
- "op":"packUnorm2x16",
- "return_type":"uint",
- "args":[
- "in float2 v"
- ],
- "helper":[
- "uint webgl_toUnorm16(in float x) {",
- " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));",
- "}"
- ],
- "body":[
- "uint x = webgl_toUnorm16(v.x);",
- "uint y = webgl_toUnorm16(v.y);",
- "return (y << 16) | x;"
- ]
- },
- {
- "op":"packHalf2x16",
- "return_type":"uint",
- "args":[
- "in float2 v"
- ],
- "body":[
- "uint x = f32tof16(v.x);",
- "uint y = f32tof16(v.y);",
- "return (y << 16) | x;"
- ]
- },
- {
- "op":"unpackSnorm2x16",
- "return_type":"float2",
- "args":[
- "in uint u"
- ],
- "helper":[
- "float webgl_fromSnorm16(in uint x) {",
- " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);",
- " return clamp(float(xi) / 32767.0, -1.0, 1.0);",
- "}"
- ],
- "body":[
- "uint y = (u >> 16);",
- "uint x = u;",
- "return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));"
- ]
- },
- {
- "op":"unpackUnorm2x16",
- "return_type":"float2",
- "args":[
- "in uint u"
- ],
- "helper":[
- "float webgl_fromUnorm16(in uint x) {",
- " return float(x) / 65535.0;",
- "}"
- ],
- "body":[
- "uint y = (u >> 16);",
- "uint x = u & 0xffffu;",
- "return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));"
- ]
- },
- {
- "op":"unpackHalf2x16",
- "return_type":"float2",
- "args":[
- "in uint u"
- ],
- "body":[
- "uint y = (u >> 16);",
- "uint x = u & 0xffffu;",
- "return float2(f16tof32(x), f16tof32(y));"
- ]
- },
- {
- "op":"packSnorm4x8",
- "return_type":"uint",
- "args":[
- "in float4 v"
- ],
- "helper":[
- "int webgl_toSnorm8(in float x) {",
- " return int(round(clamp(x, -1.0, 1.0) * 127.0));",
- "}"
- ],
- "body":[
- "int x = webgl_toSnorm8(v.x);",
- "int y = webgl_toSnorm8(v.y);",
- "int z = webgl_toSnorm8(v.z);",
- "int w = webgl_toSnorm8(v.w);",
- "return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) ",
- "| ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);"
- ]
- },
- {
- "op":"packUnorm4x8",
- "return_type":"uint",
- "args":[
- "in float4 v"
- ],
- "helper":[
- "uint webgl_toUnorm8(in float x) {",
- " return uint(round(clamp(x, 0.0, 1.0) * 255.0));",
- "}"
- ],
- "body":[
- "uint x = webgl_toUnorm8(v.x);",
- "uint y = webgl_toUnorm8(v.y);",
- "uint z = webgl_toUnorm8(v.z);",
- "uint w = webgl_toUnorm8(v.w);",
- "return (w << 24) | (z << 16) | (y << 8) | x;"
- ]
- },
- {
- "op":"unpackSnorm4x8",
- "return_type":"float4",
- "args":[
- "in uint u"
- ],
- "helper":[
- "float webgl_fromSnorm8(in uint x) {",
- " int xi = asint(x & 0x7fu) - asint(x & 0x80u);",
- " return clamp(float(xi) / 127.0, -1.0, 1.0);",
- "}"
- ],
- "body":[
- "uint w = (u >> 24);",
- "uint z = (u >> 16);",
- "uint y = (u >> 8);",
- "uint x = u;",
- "return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), ",
- "webgl_fromSnorm8(z), webgl_fromSnorm8(w));"
- ]
- },
- {
- "op":"unpackUnorm4x8",
- "return_type":"float4",
- "args":[
- "in uint u"
- ],
- "helper":[
- "float webgl_fromUnorm8(in uint x) {",
- " return float(x) / 255.0;",
- "}"
- ],
- "body":[
- "uint w = (u >> 24) & 0xffu;",
- "uint z = (u >> 16) & 0xffu;",
- "uint y = (u >> 8) & 0xffu;",
- "uint x = u & 0xffu;",
- "return float4(webgl_fromUnorm8(x), webgl_fromUnorm8(y), ",
- "webgl_fromUnorm8(z), webgl_fromUnorm8(w));"
- ]
- },
- {
- "comment":[
- "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."
- ],
- "op":"outerProduct",
- "return_type":"float2x2",
- "args":[
- "in float2 c",
- "in float2 r"
- ],
- "body":[
- "return mul(float2x1(r), float1x2(c));"
- ]
- },
- {
- "op":"outerProduct",
- "return_type":"float3x3",
- "args":[
- "in float3 c",
- "in float3 r"
- ],
- "body":[
- "return mul(float3x1(r), float1x3(c));"
- ]
- },
- {
- "op":"outerProduct",
- "return_type":"float4x4",
- "args":[
- "in float4 c",
- "in float4 r"
- ],
- "body":[
- "return mul(float4x1(r), float1x4(c));"
- ]
- },
- {
- "op":"outerProduct",
- "return_type":"float2x3",
- "args":[
- "in float3 c",
- "in float2 r"
- ],
- "body":[
- "return mul(float2x1(r), float1x3(c));"
- ]
- },
- {
- "op":"outerProduct",
- "return_type":"float3x2",
- "args":[
- "in float2 c",
- "in float3 r"
- ],
- "body":[
- "return mul(float3x1(r), float1x2(c));"
- ]
- },
- {
- "op":"outerProduct",
- "return_type":"float2x4",
- "args":[
- "in float4 c",
- "in float2 r"
- ],
- "body":[
- "return mul(float2x1(r), float1x4(c));"
- ]
- },
- {
- "op":"outerProduct",
- "return_type":"float4x2",
- "args":[
- "in float2 c",
- "in float4 r"
- ],
- "body":[
- "return mul(float4x1(r), float1x2(c));"
- ]
- },
- {
- "op":"outerProduct",
- "return_type":"float3x4",
- "args":[
- "in float4 c",
- "in float3 r"
- ],
- "body":[
- "return mul(float3x1(r), float1x4(c));"
- ]
- },
- {
- "op":"outerProduct",
- "return_type":"float4x3",
- "args":[
- "in float3 c",
- "in float4 r"
- ],
- "body":[
- "return mul(float4x1(r), float1x3(c));"
- ]
- },
- {
- "comment":[
- "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."
- ],
- "op":"inverse",
- "return_type":"float2x2",
- "args":[
- "in float2x2 m"
- ],
- "body":[
- "float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };",
- "return cof / determinant(transpose(m));"
- ]
- },
- {
- "comment":[
- "cofAB is the cofactor for column A and row B."
- ],
- "op":"inverse",
- "return_type":"float3x3",
- "args":[
- "in float3x3 m"
- ],
- "body":[
- "float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];",
- "float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);",
- "float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];",
- "float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);",
- "float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];",
- "float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);",
- "float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];",
- "float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);",
- "float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];",
- "float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };",
- "return cof / determinant(transpose(m));"
- ]
- },
- {
- "op":"inverse",
- "return_type":"float4x4",
- "args":[
- "in float4x4 m"
- ],
- "body":[
- "float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * ",
- "m[1][2] * m[2][3]",
- " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * ",
- "m[1][3];",
- "float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * ",
- "m[1][2] * m[2][3]",
- " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * ",
- "m[1][3]);",
- "float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * ",
- "m[1][1] * m[2][3]",
- " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * ",
- "m[1][3];",
- "float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * ",
- "m[1][1] * m[2][2]",
- " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * ",
- "m[1][2]);",
- "float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * ",
- "m[0][2] * m[2][3]",
- " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * ",
- "m[0][3]);",
- "float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * ",
- "m[0][2] * m[2][3]",
- " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * ",
- "m[0][3];",
- "float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * ",
- "m[0][1] * m[2][3]",
- " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * ",
- "m[0][3]);",
- "float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * ",
- "m[0][1] * m[2][2]",
- " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * ",
- "m[0][2];",
- "float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * ",
- "m[0][2] * m[1][3]",
- " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * ",
- "m[0][3];",
- "float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * ",
- "m[0][2] * m[1][3]",
- " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * ",
- "m[0][3]);",
- "float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * ",
- "m[0][1] * m[1][3]",
- " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * ",
- "m[0][3];",
- "float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * ",
- "m[0][1] * m[1][2]",
- " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * ",
- "m[0][2]);",
- "float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * ",
- "m[0][2] * m[1][3]",
- " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * ",
- "m[0][3]);",
- "float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * ",
- "m[0][2] * m[1][3]",
- " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * ",
- "m[0][3];",
- "float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * ",
- "m[0][1] * m[1][3]",
- " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * ",
- "m[0][3]);",
- "float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * ",
- "m[0][1] * m[1][2]",
- " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * ",
- "m[0][2];",
- "float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,",
- " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };",
- "return cof / determinant(transpose(m));"
- ]
- },
- {
- "comment":[
- "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."
- ],
- "op":"mix",
- "return_type":"float",
- "args":[
- "float x",
- "float y",
- "bool a"
- ],
- "body":[
- "return a ? y : x;"
- ]
- },
- {
- "op":"mix",
- "return_type":"float2",
- "args":[
- "float2 x",
- "float2 y",
- "bool2 a"
- ],
- "body":[
- "return a ? y : x;"
- ]
- },
- {
- "op":"mix",
- "return_type":"float3",
- "args":[
- "float3 x",
- "float3 y",
- "bool3 a"
- ],
- "body":[
- "return a ? y : x;"
- ]
- },
- {
- "op":"mix",
- "return_type":"float4",
- "args":[
- "float4 x",
- "float4 y",
- "bool4 a"
- ],
- "body":[
- "return a ? y : x;"
- ]
- },
- {
- "op":"bitfieldExtract",
- "return_type":"uint",
- "args":[
- "uint value",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return 0u;",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
- "return (value & mask) >> offset;"
- ]
- },
- {
- "op":"bitfieldExtract",
- "return_type":"uint2",
- "args":[
- "uint2 value",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return uint2(0u, 0u);",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
- "return (value & mask) >> offset;"
- ]
- },
- {
- "op":"bitfieldExtract",
- "return_type":"uint3",
- "args":[
- "uint3 value",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return uint3(0u, 0u, 0u);",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
- "return (value & mask) >> offset;"
- ]
- },
- {
- "op":"bitfieldExtract",
- "return_type":"uint4",
- "args":[
- "uint4 value",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return uint4(0u, 0u, 0u, 0u);",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
- "return (value & mask) >> offset;"
- ]
- },
- {
- "op":"bitfieldExtract",
- "return_type":"int",
- "args":[
- "int value",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return 0;",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
- "uint resultUnsigned = (asuint(value) & mask) >> offset;",
- "if (bits != 32 && (resultUnsigned & maskMsb) != 0)",
- "{",
- " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;",
- " resultUnsigned |= higherBitsMask;",
- "}",
- "return asint(resultUnsigned);"
- ]
- },
- {
- "op":"bitfieldExtract",
- "return_type":"int2",
- "args":[
- "int2 value",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return int2(0, 0);",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
- "uint2 resultUnsigned = (asuint(value) & mask) >> offset;",
- "if (bits != 32)",
- "{",
- " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;",
- " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;",
- "}",
- "return asint(resultUnsigned);"
- ]
- },
- {
- "op":"bitfieldExtract",
- "return_type":"int3",
- "args":[
- "int3 value",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return int3(0, 0, 0);",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
- "uint3 resultUnsigned = (asuint(value) & mask) >> offset;",
- "if (bits != 32)",
- "{",
- " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;",
- " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;",
- "}",
- "return asint(resultUnsigned);"
- ]
- },
- {
- "op":"bitfieldExtract",
- "return_type":"int4",
- "args":[
- "int4 value",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return int4(0, 0, 0, 0);",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
- "uint4 resultUnsigned = (asuint(value) & mask) >> offset;",
- "if (bits != 32)",
- "{",
- " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;",
- " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;",
- "}",
- "return asint(resultUnsigned);"
- ]
- },
- {
- "op":"bitfieldInsert",
- "return_type":"uint",
- "args":[
- "uint base",
- "uint insert",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return base;",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
- "uint baseMask = ~insertMask;",
- "return (base & baseMask) | ((insert << offset) & insertMask);"
- ]
- },
- {
- "op":"bitfieldInsert",
- "return_type":"uint2",
- "args":[
- "uint2 base",
- "uint2 insert",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return base;",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
- "uint baseMask = ~insertMask;",
- "return (base & baseMask) | ((insert << offset) & insertMask);"
- ]
- },
- {
- "op":"bitfieldInsert",
- "return_type":"uint3",
- "args":[
- "uint3 base",
- "uint3 insert",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return base;",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
- "uint baseMask = ~insertMask;",
- "return (base & baseMask) | ((insert << offset) & insertMask);"
- ]
- },
- {
- "op":"bitfieldInsert",
- "return_type":"uint4",
- "args":[
- "uint4 base",
- "uint4 insert",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return base;",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
- "uint baseMask = ~insertMask;",
- "return (base & baseMask) | ((insert << offset) & insertMask);"
- ]
- },
- {
- "op":"bitfieldInsert",
- "return_type":"int",
- "args":[
- "int base",
- "int insert",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return base;",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
- "uint baseMask = ~insertMask;",
- "uint resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ",
- " insertMask);",
- "return asint(resultUnsigned);"
- ]
- },
- {
- "op":"bitfieldInsert",
- "return_type":"int2",
- "args":[
- "int2 base",
- "int2 insert",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return base;",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
- "uint baseMask = ~insertMask;",
- "uint2 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ",
- " insertMask);",
- "return asint(resultUnsigned);"
- ]
- },
- {
- "op":"bitfieldInsert",
- "return_type":"int3",
- "args":[
- "int3 base",
- "int3 insert",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return base;",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
- "uint baseMask = ~insertMask;",
- "uint3 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ",
- " insertMask);",
- "return asint(resultUnsigned);"
- ]
- },
- {
- "op":"bitfieldInsert",
- "return_type":"int4",
- "args":[
- "int4 base",
- "int4 insert",
- "int offset",
- "int bits"
- ],
- "body":[
- "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
- "{",
- " return base;",
- "}",
- "uint maskMsb = (1u << (bits - 1));",
- "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
- "uint baseMask = ~insertMask;",
- "uint4 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ",
- "insertMask);",
- "return asint(resultUnsigned);"
- ]
- },
- {
- "op":"uaddCarry",
- "return_type":"uint",
- "args":[
- "uint x",
- "uint y",
- "out uint carry"
- ],
- "body":[
- "carry = uint(x > (0xffffffffu - y));",
- "return x + y;"
- ]
- },
- {
- "op":"uaddCarry",
- "return_type":"uint2",
- "args":[
- "uint2 x",
- "uint2 y",
- "out uint2 carry"
- ],
- "body":[
- "carry = uint2(x > (0xffffffffu - y));",
- "return x + y;"
- ]
- },
- {
- "op":"uaddCarry",
- "return_type":"uint3",
- "args":[
- "uint3 x",
- "uint3 y",
- "out uint3 carry"
- ],
- "body":[
- "carry = uint3(x > (0xffffffffu - y));",
- "return x + y;"
- ]
- },
- {
- "op":"uaddCarry",
- "return_type":"uint4",
- "args":[
- "uint4 x",
- "uint4 y",
- "out uint4 carry"
- ],
- "body":[
- "carry = uint4(x > (0xffffffffu - y));",
- "return x + y;"
- ]
- },
- {
- "op":"usubBorrow",
- "return_type":"uint",
- "args":[
- "uint x",
- "uint y",
- "out uint borrow"
- ],
- "body":[
- "borrow = uint(x < y);",
- "return x - y;"
- ]
- },
- {
- "op":"usubBorrow",
- "return_type":"uint2",
- "args":[
- "uint2 x",
- "uint2 y",
- "out uint2 borrow"
- ],
- "body":[
- "borrow = uint2(x < y);",
- "return x - y;"
- ]
- },
- {
- "op":"usubBorrow",
- "return_type":"uint3",
- "args":[
- "uint3 x",
- "uint3 y",
- "out uint3 borrow"
- ],
- "body":[
- "borrow = uint3(x < y);",
- "return x - y;"
- ]
- },
- {
- "op":"usubBorrow",
- "return_type":"uint4",
- "args":[
- "uint4 x",
- "uint4 y",
- "out uint4 borrow"
- ],
- "body":[
- "borrow = uint4(x < y);",
- "return x - y;"
- ]
- }
-]
diff --git a/src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp b/src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp
deleted file mode 100644
index 288da5e0f5..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp
+++ /dev/null
@@ -1,859 +0,0 @@
-// 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"
-
-namespace sh
-{
-
-namespace
-{
-
-struct FunctionPair
-{
- constexpr FunctionPair(const MiniFunctionId &idIn, const char *bodyIn) : id(idIn), body(bodyIn)
- {
- }
-
- MiniFunctionId id;
- const char *body;
-};
-
-constexpr FunctionPair g_hlslFunctions[] = {
- {{EOpMod, ParamType::Float1, ParamType::Float1},
- "float mod_emu(float x, float y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"},
- {{EOpMod, ParamType::Float2, ParamType::Float2},
- "float2 mod_emu(float2 x, float2 y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"},
- {{EOpMod, ParamType::Float2, ParamType::Float1},
- "float2 mod_emu(float2 x, float y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"},
- {{EOpMod, ParamType::Float3, ParamType::Float3},
- "float3 mod_emu(float3 x, float3 y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"},
- {{EOpMod, ParamType::Float3, ParamType::Float1},
- "float3 mod_emu(float3 x, float y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"},
- {{EOpMod, ParamType::Float4, ParamType::Float4},
- "float4 mod_emu(float4 x, float4 y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"},
- {{EOpMod, ParamType::Float4, ParamType::Float1},
- "float4 mod_emu(float4 x, float y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"},
- {{EOpFrexp, ParamType::Float1, ParamType::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"},
- {{EOpFrexp, ParamType::Float2, ParamType::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"},
- {{EOpFrexp, ParamType::Float3, ParamType::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"},
- {{EOpFrexp, ParamType::Float4, ParamType::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"},
- {{EOpLdexp, ParamType::Float1, ParamType::Int1},
- "float ldexp_emu(float x, int exp)\n"
- "{\n"
- " return ldexp(x, float(exp));\n"
- "}\n"},
- {{EOpLdexp, ParamType::Float2, ParamType::Int2},
- "float2 ldexp_emu(float2 x, int2 exp)\n"
- "{\n"
- " return ldexp(x, float2(exp));\n"
- "}\n"},
- {{EOpLdexp, ParamType::Float3, ParamType::Int3},
- "float3 ldexp_emu(float3 x, int3 exp)\n"
- "{\n"
- " return ldexp(x, float3(exp));\n"
- "}\n"},
- {{EOpLdexp, ParamType::Float4, ParamType::Int4},
- "float4 ldexp_emu(float4 x, int4 exp)\n"
- "{\n"
- " return ldexp(x, float4(exp));\n"
- "}\n"},
- {{EOpFaceforward, ParamType::Float1, ParamType::Float1, ParamType::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"},
- {{EOpFaceforward, ParamType::Float2, ParamType::Float2, ParamType::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"},
- {{EOpFaceforward, ParamType::Float3, ParamType::Float3, ParamType::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"},
- {{EOpFaceforward, ParamType::Float4, ParamType::Float4, ParamType::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"},
- {{EOpAtan, ParamType::Float1, ParamType::Float1},
- "float atan_emu(float y, float x)\n"
- "{\n"
- " if(x == 0 && y == 0) x = 1;\n"
- " return atan2(y, x);\n"
- "}\n"},
- {{EOpAtan, ParamType::Float2, ParamType::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"},
- {{EOpAtan, ParamType::Float3, ParamType::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"},
- {{EOpAtan, ParamType::Float4, ParamType::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"},
- {{EOpAsinh, ParamType::Float1},
- "float asinh_emu(in float x)\n"
- "{\n"
- " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
- "}\n"},
- {{EOpAsinh, ParamType::Float2},
- "float2 asinh_emu(in float2 x)\n"
- "{\n"
- " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
- "}\n"},
- {{EOpAsinh, ParamType::Float3},
- "float3 asinh_emu(in float3 x)\n"
- "{\n"
- " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
- "}\n"},
- {{EOpAsinh, ParamType::Float4},
- "float4 asinh_emu(in float4 x)\n"
- "{\n"
- " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
- "}\n"},
- {{EOpAcosh, ParamType::Float1},
- "float acosh_emu(in float x)\n"
- "{\n"
- " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
- "}\n"},
- {{EOpAcosh, ParamType::Float2},
- "float2 acosh_emu(in float2 x)\n"
- "{\n"
- " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
- "}\n"},
- {{EOpAcosh, ParamType::Float3},
- "float3 acosh_emu(in float3 x)\n"
- "{\n"
- " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
- "}\n"},
- {{EOpAcosh, ParamType::Float4},
- "float4 acosh_emu(in float4 x)\n"
- "{\n"
- " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
- "}\n"},
- {{EOpAtanh, ParamType::Float1},
- "float atanh_emu(in float x)\n"
- "{\n"
- " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
- "}\n"},
- {{EOpAtanh, ParamType::Float2},
- "float2 atanh_emu(in float2 x)\n"
- "{\n"
- " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
- "}\n"},
- {{EOpAtanh, ParamType::Float3},
- "float3 atanh_emu(in float3 x)\n"
- "{\n"
- " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
- "}\n"},
- {{EOpAtanh, ParamType::Float4},
- "float4 atanh_emu(in float4 x)\n"
- "{\n"
- " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
- "}\n"},
- {{EOpRoundEven, ParamType::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"},
- {{EOpRoundEven, ParamType::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"},
- {{EOpRoundEven, ParamType::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"},
- {{EOpRoundEven, ParamType::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"},
- {{EOpPackSnorm2x16, ParamType::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"},
- {{EOpPackUnorm2x16, ParamType::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"},
- {{EOpPackHalf2x16, ParamType::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"},
- {{EOpUnpackSnorm2x16, ParamType::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"},
- {{EOpUnpackUnorm2x16, ParamType::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"},
- {{EOpUnpackHalf2x16, ParamType::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"},
- {{EOpPackSnorm4x8, ParamType::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"},
- {{EOpPackUnorm4x8, ParamType::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"},
- {{EOpUnpackSnorm4x8, ParamType::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"},
- {{EOpUnpackUnorm4x8, ParamType::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.
- {{EOpOuterProduct, ParamType::Float2, ParamType::Float2},
- "float2x2 outerProduct_emu(in float2 c, in float2 r)\n"
- "{\n"
- " return mul(float2x1(r), float1x2(c));\n"
- "}\n"},
- {{EOpOuterProduct, ParamType::Float3, ParamType::Float3},
- "float3x3 outerProduct_emu(in float3 c, in float3 r)\n"
- "{\n"
- " return mul(float3x1(r), float1x3(c));\n"
- "}\n"},
- {{EOpOuterProduct, ParamType::Float4, ParamType::Float4},
- "float4x4 outerProduct_emu(in float4 c, in float4 r)\n"
- "{\n"
- " return mul(float4x1(r), float1x4(c));\n"
- "}\n"},
- {{EOpOuterProduct, ParamType::Float3, ParamType::Float2},
- "float2x3 outerProduct_emu(in float3 c, in float2 r)\n"
- "{\n"
- " return mul(float2x1(r), float1x3(c));\n"
- "}\n"},
- {{EOpOuterProduct, ParamType::Float2, ParamType::Float3},
- "float3x2 outerProduct_emu(in float2 c, in float3 r)\n"
- "{\n"
- " return mul(float3x1(r), float1x2(c));\n"
- "}\n"},
- {{EOpOuterProduct, ParamType::Float4, ParamType::Float2},
- "float2x4 outerProduct_emu(in float4 c, in float2 r)\n"
- "{\n"
- " return mul(float2x1(r), float1x4(c));\n"
- "}\n"},
- {{EOpOuterProduct, ParamType::Float2, ParamType::Float4},
- "float4x2 outerProduct_emu(in float2 c, in float4 r)\n"
- "{\n"
- " return mul(float4x1(r), float1x2(c));\n"
- "}\n"},
- {{EOpOuterProduct, ParamType::Float4, ParamType::Float3},
- "float3x4 outerProduct_emu(in float4 c, in float3 r)\n"
- "{\n"
- " return mul(float3x1(r), float1x4(c));\n"
- "}\n"},
- {{EOpOuterProduct, ParamType::Float3, ParamType::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.
- {{EOpInverse, ParamType::Mat2},
- "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.
- {{EOpInverse, ParamType::Mat3},
- "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"},
- {{EOpInverse, ParamType::Mat4},
- "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.
- {{EOpMix, ParamType::Float1, ParamType::Float1, ParamType::Bool1},
- "float mix_emu(float x, float y, bool a)\n"
- "{\n"
- " return a ? y : x;\n"
- "}\n"},
- {{EOpMix, ParamType::Float2, ParamType::Float2, ParamType::Bool2},
- "float2 mix_emu(float2 x, float2 y, bool2 a)\n"
- "{\n"
- " return a ? y : x;\n"
- "}\n"},
- {{EOpMix, ParamType::Float3, ParamType::Float3, ParamType::Bool3},
- "float3 mix_emu(float3 x, float3 y, bool3 a)\n"
- "{\n"
- " return a ? y : x;\n"
- "}\n"},
- {{EOpMix, ParamType::Float4, ParamType::Float4, ParamType::Bool4},
- "float4 mix_emu(float4 x, float4 y, bool4 a)\n"
- "{\n"
- " return a ? y : x;\n"
- "}\n"},
- {{EOpBitfieldExtract, ParamType::Uint1, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldExtract, ParamType::Uint2, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldExtract, ParamType::Uint3, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldExtract, ParamType::Uint4, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldExtract, ParamType::Int1, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldExtract, ParamType::Int2, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldExtract, ParamType::Int3, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldExtract, ParamType::Int4, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldInsert, ParamType::Uint1, ParamType::Uint1, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldInsert, ParamType::Uint2, ParamType::Uint2, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldInsert, ParamType::Uint3, ParamType::Uint3, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldInsert, ParamType::Uint4, ParamType::Uint4, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldInsert, ParamType::Int1, ParamType::Int1, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldInsert, ParamType::Int2, ParamType::Int2, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldInsert, ParamType::Int3, ParamType::Int3, ParamType::Int1, ParamType::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"},
- {{EOpBitfieldInsert, ParamType::Int4, ParamType::Int4, ParamType::Int1, ParamType::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"},
- {{EOpUaddCarry, ParamType::Uint1, ParamType::Uint1, ParamType::Uint1},
- "uint uaddCarry_emu(uint x, uint y, out uint carry)\n"
- "{\n"
- " carry = uint(x > (0xffffffffu - y));\n"
- " return x + y;\n"
- "}\n"},
- {{EOpUaddCarry, ParamType::Uint2, ParamType::Uint2, ParamType::Uint2},
- "uint2 uaddCarry_emu(uint2 x, uint2 y, out uint2 carry)\n"
- "{\n"
- " carry = uint2(x > (0xffffffffu - y));\n"
- " return x + y;\n"
- "}\n"},
- {{EOpUaddCarry, ParamType::Uint3, ParamType::Uint3, ParamType::Uint3},
- "uint3 uaddCarry_emu(uint3 x, uint3 y, out uint3 carry)\n"
- "{\n"
- " carry = uint3(x > (0xffffffffu - y));\n"
- " return x + y;\n"
- "}\n"},
- {{EOpUaddCarry, ParamType::Uint4, ParamType::Uint4, ParamType::Uint4},
- "uint4 uaddCarry_emu(uint4 x, uint4 y, out uint4 carry)\n"
- "{\n"
- " carry = uint4(x > (0xffffffffu - y));\n"
- " return x + y;\n"
- "}\n"},
- {{EOpUsubBorrow, ParamType::Uint1, ParamType::Uint1, ParamType::Uint1},
- "uint usubBorrow_emu(uint x, uint y, out uint borrow)\n"
- "{\n"
- " borrow = uint(x < y);\n"
- " return x - y;\n"
- "}\n"},
- {{EOpUsubBorrow, ParamType::Uint2, ParamType::Uint2, ParamType::Uint2},
- "uint2 usubBorrow_emu(uint2 x, uint2 y, out uint2 borrow)\n"
- "{\n"
- " borrow = uint2(x < y);\n"
- " return x - y;\n"
- "}\n"},
- {{EOpUsubBorrow, ParamType::Uint3, ParamType::Uint3, ParamType::Uint3},
- "uint3 usubBorrow_emu(uint3 x, uint3 y, out uint3 borrow)\n"
- "{\n"
- " borrow = uint3(x < y);\n"
- " return x - y;\n"
- "}\n"},
- {{EOpUsubBorrow, ParamType::Uint4, ParamType::Uint4, ParamType::Uint4},
- "uint4 usubBorrow_emu(uint4 x, uint4 y, out uint4 borrow)\n"
- "{\n"
- " borrow = uint4(x < y);\n"
- " return x - y;\n"
- "}\n"},
-};
-} // anonymous namespace
-
-const char *FindHLSLFunction(const FunctionId &functionID)
-{
- for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index)
- {
- const auto &function = g_hlslFunctions[index];
- if (function.id == functionID)
- {
- return function.body;
- }
- }
-
- return nullptr;
-}
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.h b/src/3rdparty/angle/src/compiler/translator/glslang.h
deleted file mode 100644
index e54c31ba3e..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/glslang.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// Copyright (c) 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/src/3rdparty/angle/src/compiler/translator/glslang.l b/src/3rdparty/angle/src/compiler/translator/glslang.l
deleted file mode 100644
index 858ffd96bb..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/glslang.l
+++ /dev/null
@@ -1,697 +0,0 @@
-/*
-//
-// Copyright (c) 2002-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.
-//
-
-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 generate_parser.sh,
-WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
-*/
-
-%top{
-//
-// Copyright (c) 2012-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.
-//
-
-// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
-
-/* clang-format off */
-
-// 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: 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
-}
-
-%{
-#include "compiler/translator/glslang.h"
-#include "compiler/translator/ParseContext.h"
-#include "compiler/preprocessor/Token.h"
-#include "compiler/translator/util.h"
-#include "compiler/translator/length_limits.h"
-
-using namespace sh;
-
-#include "glslang_tab.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_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);
-static int ES2_reserved_ES3_keyword(TParseContext *context, int token);
-static int ES2_keyword_ES3_reserved(TParseContext *context, int token);
-static int ES2_ident_ES3_keyword(TParseContext *context, int token);
-static int ES2_ident_ES3_keyword_multiview_keyword(TParseContext *context, int token);
-static int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
-static int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
-static int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token);
-static int ES3_extension_keyword_else_ident(TParseContext *context, TExtension extension, 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);
-%}
-
-%option noyywrap nounput never-interactive
-%option yylineno reentrant bison-bridge bison-locations
-%option extra-type="TParseContext*"
-%x FIELDS
-
-D [0-9]
-L [a-zA-Z_]
-H [a-fA-F0-9]
-E [Ee][+-]?{D}+
-O [0-7]
-
-%%
-
-%{
- TParseContext* context = yyextra;
-%}
-
-"invariant" { return INVARIANT; }
-"highp" { return HIGH_PRECISION; }
-"mediump" { return MEDIUM_PRECISION; }
-"lowp" { return LOW_PRECISION; }
-"precision" { return PRECISION; }
-
-"attribute" { return ES2_keyword_ES3_reserved(context, ATTRIBUTE); }
-"const" { return CONST_QUAL; }
-"uniform" { return UNIFORM; }
-"buffer" { return ES2_and_ES3_ident_ES3_1_keyword(context, BUFFER); }
-"varying" { return ES2_keyword_ES3_reserved(context, VARYING); }
-
-"break" { return BREAK; }
-"continue" { return CONTINUE; }
-"do" { return DO; }
-"for" { return FOR; }
-"while" { return WHILE; }
-
-"if" { return IF; }
-"else" { return ELSE; }
-"switch" { return ES2_reserved_ES3_keyword(context, SWITCH); }
-"case" { return ES2_ident_ES3_keyword(context, CASE); }
-"default" { return ES2_reserved_ES3_keyword(context, DEFAULT); }
-
-"centroid" { return ES2_ident_ES3_keyword(context, CENTROID); }
-"flat" { return ES2_reserved_ES3_keyword(context, FLAT); }
-"smooth" { return ES2_ident_ES3_keyword(context, SMOOTH); }
-
-"in" { return IN_QUAL; }
-"out" { return OUT_QUAL; }
-"inout" { return INOUT_QUAL; }
-"shared" { return ES2_and_ES3_ident_ES3_1_keyword(context, SHARED); }
-
-"float" { return FLOAT_TYPE; }
-"int" { return INT_TYPE; }
-"uint" { return ES2_ident_ES3_keyword(context, UINT_TYPE); }
-"void" { return VOID_TYPE; }
-"bool" { return BOOL_TYPE; }
-"true" { yylval->lex.b = true; return BOOLCONSTANT; }
-"false" { yylval->lex.b = false; return BOOLCONSTANT; }
-
-"discard" { return DISCARD; }
-"return" { return RETURN; }
-
-"mat2" { return MATRIX2; }
-"mat3" { return MATRIX3; }
-"mat4" { return MATRIX4; }
-
-"mat2x2" { return ES2_ident_ES3_keyword(context, MATRIX2); }
-"mat3x3" { return ES2_ident_ES3_keyword(context, MATRIX3); }
-"mat4x4" { return ES2_ident_ES3_keyword(context, MATRIX4); }
-
-"mat2x3" { return ES2_ident_ES3_keyword(context, MATRIX2x3); }
-"mat3x2" { return ES2_ident_ES3_keyword(context, MATRIX3x2); }
-"mat2x4" { return ES2_ident_ES3_keyword(context, MATRIX2x4); }
-"mat4x2" { return ES2_ident_ES3_keyword(context, MATRIX4x2); }
-"mat3x4" { return ES2_ident_ES3_keyword(context, MATRIX3x4); }
-"mat4x3" { return ES2_ident_ES3_keyword(context, MATRIX4x3); }
-
-"vec2" { return VEC2; }
-"vec3" { return VEC3; }
-"vec4" { return VEC4; }
-"ivec2" { return IVEC2; }
-"ivec3" { return IVEC3; }
-"ivec4" { return IVEC4; }
-"bvec2" { return BVEC2; }
-"bvec3" { return BVEC3; }
-"bvec4" { return BVEC4; }
-"uvec2" { return ES2_ident_ES3_keyword(context, UVEC2); }
-"uvec3" { return ES2_ident_ES3_keyword(context, UVEC3); }
-"uvec4" { return ES2_ident_ES3_keyword(context, UVEC4); }
-
-"sampler2D" { return SAMPLER2D; }
-"samplerCube" { return SAMPLERCUBE; }
-"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; }
-"sampler3D" { return ES2_reserved_ES3_keyword(context, SAMPLER3D); }
-"sampler3DRect" { return ES2_reserved_ES3_keyword(context, SAMPLER3DRECT); }
-"sampler2DRect" { return SAMPLER2DRECT; }
-"sampler2DArray" { return ES2_ident_ES3_keyword(context, SAMPLER2DARRAY); }
-"sampler2DMS" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, SAMPLER2DMS); }
-"isampler2D" { return ES2_ident_ES3_keyword(context, ISAMPLER2D); }
-"isampler3D" { return ES2_ident_ES3_keyword(context, ISAMPLER3D); }
-"isamplerCube" { return ES2_ident_ES3_keyword(context, ISAMPLERCUBE); }
-"isampler2DArray" { return ES2_ident_ES3_keyword(context, ISAMPLER2DARRAY); }
-"isampler2DMS" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, ISAMPLER2DMS); }
-"usampler2D" { return ES2_ident_ES3_keyword(context, USAMPLER2D); }
-"usampler3D" { return ES2_ident_ES3_keyword(context, USAMPLER3D); }
-"usamplerCube" { return ES2_ident_ES3_keyword(context, USAMPLERCUBE); }
-"usampler2DArray" { return ES2_ident_ES3_keyword(context, USAMPLER2DARRAY); }
-"usampler2DMS" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, USAMPLER2DMS); }
-"sampler2DShadow" { return ES2_reserved_ES3_keyword(context, SAMPLER2DSHADOW); }
-"samplerCubeShadow" { return ES2_ident_ES3_keyword(context, SAMPLERCUBESHADOW); }
-"sampler2DArrayShadow" { return ES2_ident_ES3_keyword(context, SAMPLER2DARRAYSHADOW); }
-"__samplerExternal2DY2YEXT" { return ES3_extension_keyword_else_ident(context, TExtension::EXT_YUV_target, SAMPLEREXTERNAL2DY2YEXT); }
-
-"struct" { return STRUCT; }
-
-"layout" { return ES2_ident_ES3_keyword_multiview_keyword(context, LAYOUT); }
-
-"yuvCscStandardEXT" { return ES3_extension_keyword_else_ident(context, TExtension::EXT_YUV_target, YUVCSCSTANDARDEXT); }
-"itu_601" { return yuvcscstandardext_constant(context); }
-"itu_601_full_range" { return yuvcscstandardext_constant(context); }
-"itu_709" { return yuvcscstandardext_constant(context); }
-
-"image2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2D); }
-"iimage2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2D); }
-"uimage2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2D); }
-"image2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2DARRAY); }
-"iimage2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2DARRAY); }
-"uimage2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2DARRAY); }
-"image3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE3D); }
-"uimage3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE3D); }
-"iimage3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE3D); }
-"iimageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGECUBE); }
-"uimageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGECUBE); }
-"imageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGECUBE); }
-"readonly" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, READONLY); }
-"writeonly" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, WRITEONLY); }
-"coherent" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, COHERENT); }
-"restrict" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, RESTRICT); }
-"volatile" { return ES2_and_ES3_reserved_ES3_1_keyword(context, VOLATILE); }
-"atomic_uint" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, ATOMICUINT); }
-
- /* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */
-"resource" |
-"noperspective" |
-"patch" |
-"sample" |
-"subroutine" |
-"common" |
-"partition" |
-"active" |
-
-"filter" |
-"image1D" |
-"iimage1D" |
-"uimage1D" |
-"image1DArray" |
-"iimage1DArray" |
-"uimage1DArray" |
-"image1DShadow" |
-"image2DShadow" |
-"image1DArrayShadow" |
-"image2DArrayShadow" |
-"imageBuffer" |
-"iimageBuffer" |
-"uimageBuffer" |
-
-"sampler1DArray" |
-"sampler1DArrayShadow" |
-"isampler1D" |
-"isampler1DArray" |
-"usampler1D" |
-"usampler1DArray" |
-"isampler2DRect" |
-"usampler2DRect" |
-"samplerBuffer" |
-"isamplerBuffer" |
-"usamplerBuffer" |
-"sampler2DMSArray" |
-"isampler2DMSArray" |
-"usampler2DMSArray" {
- if (context->getShaderVersion() < 300) {
- yylval->lex.string = NewPoolTString(yytext);
- return check_type(yyscanner);
- }
- return reserved_word(yyscanner);
-}
-
- /* Reserved keywords in GLSL ES 1.00 that are not reserved in GLSL ES 3.00 */
-"packed" {
- if (context->getShaderVersion() >= 300)
- {
- yylval->lex.string = NewPoolTString(yytext);
- return check_type(yyscanner);
- }
-
- return reserved_word(yyscanner);
-}
-
- /* Reserved keywords */
-"asm" |
-
-"class" |
-"union" |
-"enum" |
-"typedef" |
-"template" |
-"this" |
-
-"goto" |
-
-"inline" |
-"noinline" |
-"public" |
-"static" |
-"extern" |
-"external" |
-"interface" |
-
-"long" |
-"short" |
-"double" |
-"half" |
-"fixed" |
-"unsigned" |
-"superp" |
-
-"input" |
-"output" |
-
-"hvec2" |
-"hvec3" |
-"hvec4" |
-"dvec2" |
-"dvec3" |
-"dvec4" |
-"fvec2" |
-"fvec3" |
-"fvec4" |
-
-"sampler1D" |
-"sampler1DShadow" |
-"sampler2DRectShadow" |
-
-"sizeof" |
-"cast" |
-
-"namespace" |
-"using" { return reserved_word(yyscanner); }
-
-{L}({L}|{D})* {
- yylval->lex.string = NewPoolTString(yytext);
- return check_type(yyscanner);
-}
-
-0[xX]{H}+ { return int_constant(context); }
-0{O}+ { return int_constant(context); }
-{D}+ { return int_constant(context); }
-
-0[xX]{H}+[uU] { return uint_constant(context); }
-0{O}+[uU] { return uint_constant(context); }
-{D}+[uU] { return uint_constant(context); }
-
-{D}+{E} { return float_constant(yyscanner); }
-{D}+"."{D}*({E})? { return float_constant(yyscanner); }
-"."{D}+({E})? { return float_constant(yyscanner); }
-
-{D}+{E}[fF] { return floatsuffix_check(context); }
-{D}+"."{D}*({E})?[fF] { return floatsuffix_check(context); }
-"."{D}+({E})?[fF] { return floatsuffix_check(context); }
-
-"+=" { return ADD_ASSIGN; }
-"-=" { return SUB_ASSIGN; }
-"*=" { return MUL_ASSIGN; }
-"/=" { return DIV_ASSIGN; }
-"%=" { return MOD_ASSIGN; }
-"<<=" { return LEFT_ASSIGN; }
-">>=" { return RIGHT_ASSIGN; }
-"&=" { return AND_ASSIGN; }
-"^=" { return XOR_ASSIGN; }
-"|=" { return OR_ASSIGN; }
-
-"++" { return INC_OP; }
-"--" { return DEC_OP; }
-"&&" { return AND_OP; }
-"||" { return OR_OP; }
-"^^" { return XOR_OP; }
-"<=" { return LE_OP; }
-">=" { return GE_OP; }
-"==" { return EQ_OP; }
-"!=" { return NE_OP; }
-"<<" { return LEFT_OP; }
-">>" { return RIGHT_OP; }
-";" { return SEMICOLON; }
-("{"|"<%") { return LEFT_BRACE; }
-("}"|"%>") { return RIGHT_BRACE; }
-"," { return COMMA; }
-":" { return COLON; }
-"=" { return EQUAL; }
-"(" { return LEFT_PAREN; }
-")" { return RIGHT_PAREN; }
-("["|"<:") { return LEFT_BRACKET; }
-("]"|":>") { return RIGHT_BRACKET; }
-"." { BEGIN(FIELDS); return DOT; }
-"!" { return BANG; }
-"-" { return DASH; }
-"~" { return TILDE; }
-"+" { return PLUS; }
-"*" { return STAR; }
-"/" { return SLASH; }
-"%" { return PERCENT; }
-"<" { return LEFT_ANGLE; }
-">" { return RIGHT_ANGLE; }
-"|" { return VERTICAL_BAR; }
-"^" { return CARET; }
-"&" { return AMPERSAND; }
-"?" { return QUESTION; }
-
-<FIELDS>{L}({L}|{D})* {
- BEGIN(INITIAL);
- yylval->lex.string = NewPoolTString(yytext);
- return FIELD_SELECTION;
-}
-<FIELDS>[ \t\v\f\r] {}
-<FIELDS>. {
- yyextra->error(*yylloc, "Illegal character at fieldname start", yytext);
- return 0;
-}
-
-[ \t\v\n\f\r] { }
-<*><<EOF>> { yyterminate(); }
-<*>. { assert(false); return 0; }
-
-%%
-
-yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) {
- pp::Token token;
- yyget_extra(yyscanner)->getPreprocessor().lex(&token);
- yy_size_t len = token.type == 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;
- TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->getShaderVersion());
- if (symbol && symbol->isVariable()) {
- TVariable* variable = static_cast<TVariable*>(symbol);
- if (variable->isUserType()) {
- 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;
-}
-
-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 ES2_ident_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 = NewPoolTString(yytext);
- return check_type(yyscanner);
- }
- else if (context->getShaderVersion() == 300)
- {
- return reserved_word(yyscanner);
- }
-
- return token;
-}
-
-int ES2_ident_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 = NewPoolTString(yytext);
- return check_type(yyscanner);
- }
-
- return token;
-}
-
-int ES2_ident_ES3_keyword_multiview_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
- // except when multiview extension is enabled
- if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview))
- {
- yylval->lex.string = NewPoolTString(yytext);
- return check_type(yyscanner);
- }
-
- return token;
-}
-
-int ES2_and_ES3_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 ES2_and_ES3_ident_ES3_1_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 and GLSL ES 3.00, so could be used as an identifier/type name
- if (context->getShaderVersion() < 310)
- {
- yylval->lex.string = NewPoolTString(yytext);
- return check_type(yyscanner);
- }
-
- return token;
-}
-
-int ES3_extension_keyword_else_ident(TParseContext *context, TExtension extension, int token)
-{
- 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(extension))
- {
- return token;
- }
-
- yylval->lex.string = NewPoolTString(yytext);
- 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<int>(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 = NewPoolTString(yytext);
- return YUVCSCSTANDARDEXTCONSTANT;
- }
-
- yylval->lex.string = NewPoolTString(yytext);
- 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.
- 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) {
- 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/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y
deleted file mode 100644
index 3e506caac8..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/glslang.y
+++ /dev/null
@@ -1,1468 +0,0 @@
-/*
-//
-// Copyright (c) 2002-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.
-//
-
-This file contains the Yacc grammar for GLSL ES.
-Based on ANSI C Yacc grammar:
-http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
-
-IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
-WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
-*/
-
-%{
-//
-// Copyright (c) 2002-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.
-//
-
-// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
-
-// clang-format off
-
-// 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
-
-#include "angle_gl.h"
-#include "compiler/translator/Cache.h"
-#include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/ParseContext.h"
-#include "GLSLANG/ShaderLang.h"
-
-#define YYENABLE_NLS 0
-
-using namespace sh;
-
-%}
-%expect 1 /* One shift reduce conflict because of if | else */
-%parse-param {TParseContext* context}
-%param {void *scanner}
-%define api.pure full
-%locations
-
-%code requires {
-#define YYLTYPE TSourceLoc
-#define YYLTYPE_IS_DECLARED 1
-}
-
-%union {
- struct {
- union {
- TString *string;
- float f;
- int i;
- unsigned int u;
- bool b;
- };
- TSymbol* symbol;
- } lex;
- struct {
- TOperator op;
- union {
- TIntermNode *intermNode;
- TIntermNodePair nodePair;
- TIntermFunctionCallOrMethod callOrMethodPair;
- TIntermTyped *intermTypedNode;
- TIntermAggregate *intermAggregate;
- TIntermBlock *intermBlock;
- TIntermDeclaration *intermDeclaration;
- TIntermFunctionPrototype *intermFunctionPrototype;
- TIntermSwitch *intermSwitch;
- TIntermCase *intermCase;
- };
- union {
- TVector<unsigned int> *arraySizes;
- TTypeSpecifierNonArray typeSpecifierNonArray;
- TPublicType type;
- TPrecision precision;
- TLayoutQualifier layoutQualifier;
- TQualifier qualifier;
- TFunction *function;
- TParameter param;
- TField *field;
- TFieldList *fieldList;
- TQualifierWrapperBase *qualifierWrapper;
- TTypeQualifierBuilder *typeQualifierBuilder;
- };
- } interm;
-}
-
-%{
-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) { \
- if (context->getShaderType() != GL_VERTEX_SHADER) { \
- context->error(L, " supported in vertex shaders only", S); \
- } \
-}
-
-#define COMPUTE_ONLY(S, L) { \
- if (context->getShaderType() != GL_COMPUTE_SHADER) { \
- context->error(L, " supported in compute shaders only", S); \
- } \
-}
-
-#define ES2_ONLY(S, L) { \
- if (context->getShaderVersion() != 100) { \
- context->error(L, " supported in GLSL ES 1.00 only", S); \
- } \
-}
-
-#define ES3_OR_NEWER(TOKEN, LINE, REASON) { \
- if (context->getShaderVersion() < 300) { \
- context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN); \
- } \
-}
-
-#define ES3_OR_NEWER_OR_MULTIVIEW(TOKEN, LINE, REASON) { \
- if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview)) { \
- context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN); \
- } \
-}
-
-#define ES3_1_ONLY(TOKEN, LINE, REASON) { \
- if (context->getShaderVersion() != 310) { \
- context->error(LINE, REASON " supported in GLSL ES 3.10 only", TOKEN); \
- } \
-}
-%}
-
-%token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
-%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE UINT_TYPE
-%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
-%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 UVEC2 UVEC3 UVEC4
-%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM BUFFER VARYING
-%token <lex> MATRIX2x3 MATRIX3x2 MATRIX2x4 MATRIX4x2 MATRIX3x4 MATRIX4x3
-%token <lex> CENTROID FLAT SMOOTH
-%token <lex> READONLY WRITEONLY COHERENT RESTRICT VOLATILE SHARED
-%token <lex> STRUCT VOID_TYPE WHILE
-%token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT SAMPLER2DARRAY
-%token <lex> ISAMPLER2D ISAMPLER3D ISAMPLERCUBE ISAMPLER2DARRAY
-%token <lex> USAMPLER2D USAMPLER3D USAMPLERCUBE USAMPLER2DARRAY
-%token <lex> SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS
-%token <lex> SAMPLER3D SAMPLER3DRECT SAMPLER2DSHADOW SAMPLERCUBESHADOW SAMPLER2DARRAYSHADOW
-%token <lex> SAMPLEREXTERNAL2DY2YEXT
-%token <lex> IMAGE2D IIMAGE2D UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY
-%token <lex> IMAGECUBE IIMAGECUBE UIMAGECUBE
-%token <lex> ATOMICUINT
-%token <lex> LAYOUT
-%token <lex> YUVCSCSTANDARDEXT YUVCSCSTANDARDEXTCONSTANT
-
-%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT
-%token <lex> FIELD_SELECTION
-%token <lex> LEFT_OP RIGHT_OP
-%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
-%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
-%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
-%token <lex> SUB_ASSIGN
-
-%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
-%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
-%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
-
-%type <lex> identifier
-%type <interm.op> assignment_operator unary_operator
-%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
-%type <interm.intermTypedNode> expression integer_expression assignment_expression
-%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
-%type <interm.intermTypedNode> relational_expression equality_expression
-%type <interm.intermTypedNode> conditional_expression constant_expression
-%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
-%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
-%type <interm.intermTypedNode> function_call initializer
-
-%type <interm.intermNode> condition conditionopt
-%type <interm.intermBlock> translation_unit
-%type <interm.intermNode> function_definition statement simple_statement
-%type <interm.intermBlock> statement_list compound_statement_with_scope compound_statement_no_new_scope
-%type <interm.intermNode> declaration_statement selection_statement expression_statement
-%type <interm.intermNode> declaration external_declaration
-%type <interm.intermNode> for_init_statement
-%type <interm.nodePair> selection_rest_statement for_rest_statement
-%type <interm.intermSwitch> switch_statement
-%type <interm.intermCase> case_label
-%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
-%type <interm> single_declaration init_declarator_list
-
-%type <interm.param> parameter_declaration parameter_declarator parameter_type_specifier
-%type <interm.layoutQualifier> layout_qualifier_id_list layout_qualifier_id
-
-// Note: array_specifier guaranteed to be non-null.
-%type <interm.arraySizes> array_specifier
-
-%type <interm.type> fully_specified_type type_specifier
-
-%type <interm.precision> precision_qualifier
-%type <interm.layoutQualifier> layout_qualifier
-%type <interm.qualifier> interpolation_qualifier
-%type <interm.qualifierWrapper> storage_qualifier single_type_qualifier invariant_qualifier
-%type <interm.typeQualifierBuilder> type_qualifier
-
-%type <interm.typeSpecifierNonArray> type_specifier_nonarray struct_specifier
-%type <interm.type> type_specifier_no_prec
-%type <interm.field> struct_declarator
-%type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list
-%type <interm.function> function_header function_declarator function_identifier
-%type <interm.function> function_header_with_parameters function_call_header
-%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
-%type <interm> function_call_or_method
-
-%type <lex> enter_struct
-
-%start translation_unit
-%%
-
-identifier
- : IDENTIFIER
- | TYPE_NAME
-
-variable_identifier
- : IDENTIFIER {
- // The symbol table search was done in the lexical phase
- $$ = context->parseVariableIdentifier(@1, $1.string, $1.symbol);
-
- // don't delete $1.string, it's used by error recovery, and the pool
- // pop will reclaim the memory
- }
- ;
-
-primary_expression
- : variable_identifier {
- $$ = $1;
- }
- | INTCONSTANT {
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray->setIConst($1.i);
- $$ = context->addScalarLiteral(unionArray, @1);
- }
- | UINTCONSTANT {
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray->setUConst($1.u);
- $$ = context->addScalarLiteral(unionArray, @1);
- }
- | FLOATCONSTANT {
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray->setFConst($1.f);
- $$ = context->addScalarLiteral(unionArray, @1);
- }
- | BOOLCONSTANT {
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray->setBConst($1.b);
- $$ = context->addScalarLiteral(unionArray, @1);
- }
- | YUVCSCSTANDARDEXTCONSTANT {
- if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target))
- {
- context->error(@1, "unsupported value", $1.string->c_str());
- }
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray->setYuvCscStandardEXTConst(getYuvCscStandardEXT($1.string->c_str()));
- $$ = context->addScalarLiteral(unionArray, @1);
- }
- | LEFT_PAREN expression RIGHT_PAREN {
- $$ = $2;
- }
- ;
-
-postfix_expression
- : primary_expression {
- $$ = $1;
- }
- | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
- $$ = context->addIndexExpression($1, @2, $3);
- }
- | function_call {
- $$ = $1;
- }
- | postfix_expression DOT FIELD_SELECTION {
- $$ = context->addFieldSelectionExpression($1, @2, *$3.string, @3);
- }
- | postfix_expression INC_OP {
- $$ = context->addUnaryMathLValue(EOpPostIncrement, $1, @2);
- }
- | postfix_expression DEC_OP {
- $$ = context->addUnaryMathLValue(EOpPostDecrement, $1, @2);
- }
- ;
-
-integer_expression
- : expression {
- context->checkIsScalarInteger($1, "[]");
- $$ = $1;
- }
- ;
-
-function_call
- : function_call_or_method {
- $$ = context->addFunctionCallOrMethod($1.function, $1.callOrMethodPair.arguments, $1.callOrMethodPair.thisNode, @1);
- }
- ;
-
-function_call_or_method
- : function_call_generic {
- $$ = $1;
- $$.callOrMethodPair.thisNode = nullptr;
- }
- | postfix_expression DOT function_call_generic {
- ES3_OR_NEWER("", @3, "methods");
- $$ = $3;
- $$.callOrMethodPair.thisNode = $1;
- }
- ;
-
-function_call_generic
- : function_call_header_with_parameters RIGHT_PAREN {
- $$ = $1;
- }
- | function_call_header_no_parameters RIGHT_PAREN {
- $$ = $1;
- }
- ;
-
-function_call_header_no_parameters
- : function_call_header VOID_TYPE {
- $$.function = $1;
- $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
- }
- | function_call_header {
- $$.function = $1;
- $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
- }
- ;
-
-function_call_header_with_parameters
- : function_call_header assignment_expression {
- $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
- $$.function = $1;
- $$.callOrMethodPair.arguments->push_back($2);
- }
- | function_call_header_with_parameters COMMA assignment_expression {
- $$.function = $1.function;
- $$.callOrMethodPair.arguments->push_back($3);
- }
- ;
-
-function_call_header
- : function_identifier LEFT_PAREN {
- $$ = $1;
- }
- ;
-
-// Grammar Note: Constructors look like functions, but are recognized as types.
-
-function_identifier
- : type_specifier_no_prec {
- $$ = context->addConstructorFunc($1);
- }
- | IDENTIFIER {
- $$ = context->addNonConstructorFunc($1.string, @1);
- }
- | FIELD_SELECTION {
- $$ = context->addNonConstructorFunc($1.string, @1);
- }
- ;
-
-unary_expression
- : postfix_expression {
- $$ = $1;
- }
- | INC_OP unary_expression {
- $$ = context->addUnaryMathLValue(EOpPreIncrement, $2, @1);
- }
- | DEC_OP unary_expression {
- $$ = context->addUnaryMathLValue(EOpPreDecrement, $2, @1);
- }
- | unary_operator unary_expression {
- $$ = context->addUnaryMath($1, $2, @1);
- }
- ;
-// Grammar Note: No traditional style type casts.
-
-unary_operator
- : PLUS { $$ = EOpPositive; }
- | DASH { $$ = EOpNegative; }
- | BANG { $$ = EOpLogicalNot; }
- | TILDE {
- ES3_OR_NEWER("~", @$, "bit-wise operator");
- $$ = EOpBitwiseNot;
- }
- ;
-// Grammar Note: No '*' or '&' unary ops. Pointers are not supported.
-
-multiplicative_expression
- : unary_expression { $$ = $1; }
- | multiplicative_expression STAR unary_expression {
- $$ = context->addBinaryMath(EOpMul, $1, $3, @2);
- }
- | multiplicative_expression SLASH unary_expression {
- $$ = context->addBinaryMath(EOpDiv, $1, $3, @2);
- }
- | multiplicative_expression PERCENT unary_expression {
- ES3_OR_NEWER("%", @2, "integer modulus operator");
- $$ = context->addBinaryMath(EOpIMod, $1, $3, @2);
- }
- ;
-
-additive_expression
- : multiplicative_expression { $$ = $1; }
- | additive_expression PLUS multiplicative_expression {
- $$ = context->addBinaryMath(EOpAdd, $1, $3, @2);
- }
- | additive_expression DASH multiplicative_expression {
- $$ = context->addBinaryMath(EOpSub, $1, $3, @2);
- }
- ;
-
-shift_expression
- : additive_expression { $$ = $1; }
- | shift_expression LEFT_OP additive_expression {
- ES3_OR_NEWER("<<", @2, "bit-wise operator");
- $$ = context->addBinaryMath(EOpBitShiftLeft, $1, $3, @2);
- }
- | shift_expression RIGHT_OP additive_expression {
- ES3_OR_NEWER(">>", @2, "bit-wise operator");
- $$ = context->addBinaryMath(EOpBitShiftRight, $1, $3, @2);
- }
- ;
-
-relational_expression
- : shift_expression { $$ = $1; }
- | relational_expression LEFT_ANGLE shift_expression {
- $$ = context->addBinaryMathBooleanResult(EOpLessThan, $1, $3, @2);
- }
- | relational_expression RIGHT_ANGLE shift_expression {
- $$ = context->addBinaryMathBooleanResult(EOpGreaterThan, $1, $3, @2);
- }
- | relational_expression LE_OP shift_expression {
- $$ = context->addBinaryMathBooleanResult(EOpLessThanEqual, $1, $3, @2);
- }
- | relational_expression GE_OP shift_expression {
- $$ = context->addBinaryMathBooleanResult(EOpGreaterThanEqual, $1, $3, @2);
- }
- ;
-
-equality_expression
- : relational_expression { $$ = $1; }
- | equality_expression EQ_OP relational_expression {
- $$ = context->addBinaryMathBooleanResult(EOpEqual, $1, $3, @2);
- }
- | equality_expression NE_OP relational_expression {
- $$ = context->addBinaryMathBooleanResult(EOpNotEqual, $1, $3, @2);
- }
- ;
-
-and_expression
- : equality_expression { $$ = $1; }
- | and_expression AMPERSAND equality_expression {
- ES3_OR_NEWER("&", @2, "bit-wise operator");
- $$ = context->addBinaryMath(EOpBitwiseAnd, $1, $3, @2);
- }
- ;
-
-exclusive_or_expression
- : and_expression { $$ = $1; }
- | exclusive_or_expression CARET and_expression {
- ES3_OR_NEWER("^", @2, "bit-wise operator");
- $$ = context->addBinaryMath(EOpBitwiseXor, $1, $3, @2);
- }
- ;
-
-inclusive_or_expression
- : exclusive_or_expression { $$ = $1; }
- | inclusive_or_expression VERTICAL_BAR exclusive_or_expression {
- ES3_OR_NEWER("|", @2, "bit-wise operator");
- $$ = context->addBinaryMath(EOpBitwiseOr, $1, $3, @2);
- }
- ;
-
-logical_and_expression
- : inclusive_or_expression { $$ = $1; }
- | logical_and_expression AND_OP inclusive_or_expression {
- $$ = context->addBinaryMathBooleanResult(EOpLogicalAnd, $1, $3, @2);
- }
- ;
-
-logical_xor_expression
- : logical_and_expression { $$ = $1; }
- | logical_xor_expression XOR_OP logical_and_expression {
- $$ = context->addBinaryMathBooleanResult(EOpLogicalXor, $1, $3, @2);
- }
- ;
-
-logical_or_expression
- : logical_xor_expression { $$ = $1; }
- | logical_or_expression OR_OP logical_xor_expression {
- $$ = context->addBinaryMathBooleanResult(EOpLogicalOr, $1, $3, @2);
- }
- ;
-
-conditional_expression
- : logical_or_expression { $$ = $1; }
- | logical_or_expression QUESTION expression COLON assignment_expression {
- $$ = context->addTernarySelection($1, $3, $5, @2);
- }
- ;
-
-assignment_expression
- : conditional_expression { $$ = $1; }
- | unary_expression assignment_operator assignment_expression {
- $$ = context->addAssign($2, $1, $3, @2);
- }
- ;
-
-assignment_operator
- : EQUAL { $$ = EOpAssign; }
- | MUL_ASSIGN { $$ = EOpMulAssign; }
- | DIV_ASSIGN { $$ = EOpDivAssign; }
- | MOD_ASSIGN {
- ES3_OR_NEWER("%=", @$, "integer modulus operator");
- $$ = EOpIModAssign;
- }
- | ADD_ASSIGN { $$ = EOpAddAssign; }
- | SUB_ASSIGN { $$ = EOpSubAssign; }
- | LEFT_ASSIGN {
- ES3_OR_NEWER("<<=", @$, "bit-wise operator");
- $$ = EOpBitShiftLeftAssign;
- }
- | RIGHT_ASSIGN {
- ES3_OR_NEWER(">>=", @$, "bit-wise operator");
- $$ = EOpBitShiftRightAssign;
- }
- | AND_ASSIGN {
- ES3_OR_NEWER("&=", @$, "bit-wise operator");
- $$ = EOpBitwiseAndAssign;
- }
- | XOR_ASSIGN {
- ES3_OR_NEWER("^=", @$, "bit-wise operator");
- $$ = EOpBitwiseXorAssign;
- }
- | OR_ASSIGN {
- ES3_OR_NEWER("|=", @$, "bit-wise operator");
- $$ = EOpBitwiseOrAssign;
- }
- ;
-
-expression
- : assignment_expression {
- $$ = $1;
- }
- | expression COMMA assignment_expression {
- $$ = context->addComma($1, $3, @2);
- }
- ;
-
-constant_expression
- : conditional_expression {
- context->checkIsConst($1);
- $$ = $1;
- }
- ;
-
-enter_struct
- : IDENTIFIER LEFT_BRACE {
- context->enterStructDeclaration(@1, *$1.string);
- $$ = $1;
- }
- ;
-
-declaration
- : function_prototype SEMICOLON {
- $$ = context->addFunctionPrototypeDeclaration(*($1.function), @1);
- }
- | init_declarator_list SEMICOLON {
- $$ = $1.intermDeclaration;
- }
- | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
- context->parseDefaultPrecisionQualifier($2, $3, @1);
- $$ = nullptr;
- }
- | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE SEMICOLON {
- ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks");
- $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, NULL, @$, NULL, @$);
- }
- | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON {
- ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks");
- $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, $5.string, @5, NULL, @$);
- }
- | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET SEMICOLON {
- ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks");
- $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, $5.string, @5, $7, @6);
- }
- | type_qualifier SEMICOLON {
- context->parseGlobalLayoutQualifier(*$1);
- $$ = nullptr;
- }
- | type_qualifier IDENTIFIER SEMICOLON // e.g. to qualify an existing variable as invariant
- {
- $$ = context->parseInvariantDeclaration(*$1, @2, $2.string, $2.symbol);
- }
- ;
-
-function_prototype
- : function_declarator RIGHT_PAREN {
- $$.function = context->parseFunctionDeclarator(@2, $1);
- context->exitFunctionDeclaration();
- }
- ;
-
-function_declarator
- : function_header {
- $$ = $1;
- }
- | function_header_with_parameters {
- $$ = $1;
- }
- ;
-
-
-function_header_with_parameters
- : function_header parameter_declaration {
- // Add the parameter
- $$ = $1;
- if ($2.type->getBasicType() != EbtVoid)
- {
- $1->addParameter($2.turnToConst());
- }
- }
- | function_header_with_parameters COMMA parameter_declaration {
- $$ = $1;
- // Only first parameter of one-parameter functions can be void
- // The check for named parameters not being void is done in parameter_declarator
- if ($3.type->getBasicType() == EbtVoid)
- {
- // This parameter > first is void
- context->error(@2, "cannot be a parameter type except for '(void)'", "void");
- }
- else
- {
- $1->addParameter($3.turnToConst());
- }
- }
- ;
-
-function_header
- : fully_specified_type IDENTIFIER LEFT_PAREN {
- $$ = context->parseFunctionHeader($1, $2.string, @2);
-
- context->symbolTable.push();
- context->enterFunctionDeclaration();
- }
- ;
-
-parameter_declarator
- // Type + name
- : type_specifier identifier {
- $$ = context->parseParameterDeclarator($1, $2.string, @2);
- }
- | type_specifier identifier array_specifier {
- $$ = context->parseParameterArrayDeclarator($2.string, @2, *($3), @3, &$1);
- }
- ;
-
-parameter_declaration
- : type_qualifier parameter_declarator {
- $$ = $2;
- context->checkIsParameterQualifierValid(@2, *$1, $2.type);
- }
- | parameter_declarator {
- $$ = $1;
- $$.type->setQualifier(EvqIn);
- }
- | type_qualifier parameter_type_specifier {
- $$ = $2;
- context->checkIsParameterQualifierValid(@2, *$1, $2.type);
- }
- | parameter_type_specifier {
- $$ = $1;
- $$.type->setQualifier(EvqIn);
- }
- ;
-
-parameter_type_specifier
- : type_specifier {
- TParameter param = { 0, new TType($1) };
- $$ = param;
- }
- ;
-
-init_declarator_list
- : single_declaration {
- $$ = $1;
- }
- | init_declarator_list COMMA identifier {
- $$ = $1;
- context->parseDeclarator($$.type, @3, *$3.string, $$.intermDeclaration);
- }
- | init_declarator_list COMMA identifier array_specifier {
- $$ = $1;
- context->parseArrayDeclarator($$.type, @3, *$3.string, @4, *($4), $$.intermDeclaration);
- }
- | init_declarator_list COMMA identifier array_specifier EQUAL initializer {
- ES3_OR_NEWER("=", @5, "first-class arrays (array initializer)");
- $$ = $1;
- context->parseArrayInitDeclarator($$.type, @3, *$3.string, @4, *($4), @5, $6, $$.intermDeclaration);
- }
- | init_declarator_list COMMA identifier EQUAL initializer {
- $$ = $1;
- context->parseInitDeclarator($$.type, @3, *$3.string, @4, $5, $$.intermDeclaration);
- }
- ;
-
-single_declaration
- : fully_specified_type {
- $$.type = $1;
- $$.intermDeclaration = context->parseSingleDeclaration($$.type, @1, "");
- }
- | fully_specified_type identifier {
- $$.type = $1;
- $$.intermDeclaration = context->parseSingleDeclaration($$.type, @2, *$2.string);
- }
- | fully_specified_type identifier array_specifier {
- $$.type = $1;
- $$.intermDeclaration = context->parseSingleArrayDeclaration($$.type, @2, *$2.string, @3, *($3));
- }
- | fully_specified_type identifier array_specifier EQUAL initializer {
- ES3_OR_NEWER("[]", @3, "first-class arrays (array initializer)");
- $$.type = $1;
- $$.intermDeclaration = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, *($3), @4, $5);
- }
- | fully_specified_type identifier EQUAL initializer {
- $$.type = $1;
- $$.intermDeclaration = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4);
- }
- ;
-
-fully_specified_type
- : type_specifier {
- context->addFullySpecifiedType(&$1);
- $$ = $1;
- }
- | type_qualifier type_specifier {
- $$ = context->addFullySpecifiedType(*$1, $2);
- }
- ;
-
-interpolation_qualifier
- : SMOOTH {
- $$ = EvqSmooth;
- }
- | FLAT {
- $$ = EvqFlat;
- }
- ;
-
-type_qualifier
- : single_type_qualifier {
- $$ = context->createTypeQualifierBuilder(@1);
- $$->appendQualifier($1);
- }
- | type_qualifier single_type_qualifier {
- $$ = $1;
- $$->appendQualifier($2);
- }
- ;
-
-invariant_qualifier
- : INVARIANT {
- // empty
- }
- ;
-
-single_type_qualifier
- : storage_qualifier {
- context->checkLocalVariableConstStorageQualifier(*$1);
- $$ = $1;
- }
- | layout_qualifier {
- context->checkIsAtGlobalLevel(@1, "layout");
- $$ = new TLayoutQualifierWrapper($1, @1);
- }
- | precision_qualifier {
- $$ = new TPrecisionQualifierWrapper($1, @1);
- }
- | interpolation_qualifier {
- $$ = new TInterpolationQualifierWrapper($1, @1);
- }
- | invariant_qualifier {
- context->checkIsAtGlobalLevel(@1, "invariant");
- $$ = new TInvariantQualifierWrapper(@1);
- }
- ;
-
-
-storage_qualifier
- :
- ATTRIBUTE {
- VERTEX_ONLY("attribute", @1);
- ES2_ONLY("attribute", @1);
- $$ = context->parseGlobalStorageQualifier(EvqAttribute, @1);
- }
- | VARYING {
- ES2_ONLY("varying", @1);
- $$ = context->parseVaryingQualifier(@1);
- }
- | CONST_QUAL {
- $$ = new TStorageQualifierWrapper(EvqConst, @1);
- }
- | IN_QUAL {
- $$ = context->parseInQualifier(@1);
- }
- | OUT_QUAL {
- $$ = context->parseOutQualifier(@1);
- }
- | INOUT_QUAL {
- $$ = context->parseInOutQualifier(@1);
- }
- | CENTROID {
- ES3_OR_NEWER("centroid", @1, "storage qualifier");
- $$ = new TStorageQualifierWrapper(EvqCentroid, @1);
- }
- | UNIFORM {
- $$ = context->parseGlobalStorageQualifier(EvqUniform, @1);
- }
- | BUFFER {
- ES3_1_ONLY("buffer", @1, "storage qualifier");
- $$ = context->parseGlobalStorageQualifier(EvqBuffer, @1);
- }
- | READONLY {
- $$ = new TMemoryQualifierWrapper(EvqReadOnly, @1);
- }
- | WRITEONLY {
- $$ = new TMemoryQualifierWrapper(EvqWriteOnly, @1);
- }
- | COHERENT {
- $$ = new TMemoryQualifierWrapper(EvqCoherent, @1);
- }
- | RESTRICT {
- $$ = new TMemoryQualifierWrapper(EvqRestrict, @1);
- }
- | VOLATILE {
- $$ = new TMemoryQualifierWrapper(EvqVolatile, @1);
- }
- | SHARED {
- COMPUTE_ONLY("shared", @1);
- $$ = context->parseGlobalStorageQualifier(EvqShared, @1);
- }
- ;
-
-type_specifier
- : type_specifier_no_prec {
- $$ = $1;
- $$.precision = context->symbolTable.getDefaultPrecision($1.getBasicType());
- }
- ;
-
-precision_qualifier
- : HIGH_PRECISION {
- $$ = EbpHigh;
- }
- | MEDIUM_PRECISION {
- $$ = EbpMedium;
- }
- | LOW_PRECISION {
- $$ = EbpLow;
- }
- ;
-
-layout_qualifier
- : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN {
- ES3_OR_NEWER_OR_MULTIVIEW("layout", @1, "qualifier");
- $$ = $3;
- }
- ;
-
-layout_qualifier_id_list
- : layout_qualifier_id {
- $$ = $1;
- }
- | layout_qualifier_id_list COMMA layout_qualifier_id {
- $$ = context->joinLayoutQualifiers($1, $3, @3);
- }
- ;
-
-layout_qualifier_id
- : IDENTIFIER {
- $$ = context->parseLayoutQualifier(*$1.string, @1);
- }
- | IDENTIFIER EQUAL INTCONSTANT {
- $$ = context->parseLayoutQualifier(*$1.string, @1, $3.i, @3);
- }
- | IDENTIFIER EQUAL UINTCONSTANT {
- $$ = context->parseLayoutQualifier(*$1.string, @1, $3.i, @3);
- }
- | SHARED {
- $$ = context->parseLayoutQualifier("shared", @1);
- }
- ;
-
-type_specifier_no_prec
- : type_specifier_nonarray {
- $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
- }
- | type_specifier_nonarray array_specifier {
- $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
- $$.setArraySizes($2);
- }
- ;
-
-array_specifier
- : LEFT_BRACKET RIGHT_BRACKET {
- ES3_OR_NEWER("[]", @1, "implicitly sized array");
- $$ = new TVector<unsigned int>();
- $$->push_back(0u);
- }
- | LEFT_BRACKET constant_expression RIGHT_BRACKET {
- $$ = new TVector<unsigned int>();
- unsigned int size = context->checkIsValidArraySize(@1, $2);
- // Make the type an array even if size check failed.
- // This ensures useless error messages regarding a variable's non-arrayness won't follow.
- $$->push_back(size);
- }
- | array_specifier LEFT_BRACKET RIGHT_BRACKET {
- ES3_1_ONLY("[]", @2, "arrays of arrays");
- $$ = $1;
- $$->insert($$->begin(), 0u);
- }
- | array_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
- ES3_1_ONLY("[]", @2, "arrays of arrays");
- $$ = $1;
- unsigned int size = context->checkIsValidArraySize(@2, $3);
- // Make the type an array even if size check failed.
- // This ensures useless error messages regarding a variable's non-arrayness won't follow.
- $$->insert($$->begin(), size);
- }
- ;
-
-type_specifier_nonarray
- : VOID_TYPE {
- $$.initialize(EbtVoid, @1);
- }
- | FLOAT_TYPE {
- $$.initialize(EbtFloat, @1);
- }
- | INT_TYPE {
- $$.initialize(EbtInt, @1);
- }
- | UINT_TYPE {
- $$.initialize(EbtUInt, @1);
- }
- | BOOL_TYPE {
- $$.initialize(EbtBool, @1);
- }
- | VEC2 {
- $$.initialize(EbtFloat, @1);
- $$.setAggregate(2);
- }
- | VEC3 {
- $$.initialize(EbtFloat, @1);
- $$.setAggregate(3);
- }
- | VEC4 {
- $$.initialize(EbtFloat, @1);
- $$.setAggregate(4);
- }
- | BVEC2 {
- $$.initialize(EbtBool, @1);
- $$.setAggregate(2);
- }
- | BVEC3 {
- $$.initialize(EbtBool, @1);
- $$.setAggregate(3);
- }
- | BVEC4 {
- $$.initialize(EbtBool, @1);
- $$.setAggregate(4);
- }
- | IVEC2 {
- $$.initialize(EbtInt, @1);
- $$.setAggregate(2);
- }
- | IVEC3 {
- $$.initialize(EbtInt, @1);
- $$.setAggregate(3);
- }
- | IVEC4 {
- $$.initialize(EbtInt, @1);
- $$.setAggregate(4);
- }
- | UVEC2 {
- $$.initialize(EbtUInt, @1);
- $$.setAggregate(2);
- }
- | UVEC3 {
- $$.initialize(EbtUInt, @1);
- $$.setAggregate(3);
- }
- | UVEC4 {
- $$.initialize(EbtUInt, @1);
- $$.setAggregate(4);
- }
- | MATRIX2 {
- $$.initialize(EbtFloat, @1);
- $$.setMatrix(2, 2);
- }
- | MATRIX3 {
- $$.initialize(EbtFloat, @1);
- $$.setMatrix(3, 3);
- }
- | MATRIX4 {
- $$.initialize(EbtFloat, @1);
- $$.setMatrix(4, 4);
- }
- | MATRIX2x3 {
- $$.initialize(EbtFloat, @1);
- $$.setMatrix(2, 3);
- }
- | MATRIX3x2 {
- $$.initialize(EbtFloat, @1);
- $$.setMatrix(3, 2);
- }
- | MATRIX2x4 {
- $$.initialize(EbtFloat, @1);
- $$.setMatrix(2, 4);
- }
- | MATRIX4x2 {
- $$.initialize(EbtFloat, @1);
- $$.setMatrix(4, 2);
- }
- | MATRIX3x4 {
- $$.initialize(EbtFloat, @1);
- $$.setMatrix(3, 4);
- }
- | MATRIX4x3 {
- $$.initialize(EbtFloat, @1);
- $$.setMatrix(4, 3);
- }
- | YUVCSCSTANDARDEXT {
- if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target))
- {
- context->error(@1, "unsupported type", "yuvCscStandardEXT");
- }
- $$.initialize(EbtYuvCscStandardEXT, @1);
- }
- | SAMPLER2D {
- $$.initialize(EbtSampler2D, @1);
- }
- | SAMPLER3D {
- $$.initialize(EbtSampler3D, @1);
- }
- | SAMPLERCUBE {
- $$.initialize(EbtSamplerCube, @1);
- }
- | SAMPLER2DARRAY {
- $$.initialize(EbtSampler2DArray, @1);
- }
- | SAMPLER2DMS {
- $$.initialize(EbtSampler2DMS, @1);
- }
- | ISAMPLER2D {
- $$.initialize(EbtISampler2D, @1);
- }
- | ISAMPLER3D {
- $$.initialize(EbtISampler3D, @1);
- }
- | ISAMPLERCUBE {
- $$.initialize(EbtISamplerCube, @1);
- }
- | ISAMPLER2DARRAY {
- $$.initialize(EbtISampler2DArray, @1);
- }
- | ISAMPLER2DMS {
- $$.initialize(EbtISampler2DMS, @1);
- }
- | USAMPLER2D {
- $$.initialize(EbtUSampler2D, @1);
- }
- | USAMPLER3D {
- $$.initialize(EbtUSampler3D, @1);
- }
- | USAMPLERCUBE {
- $$.initialize(EbtUSamplerCube, @1);
- }
- | USAMPLER2DARRAY {
- $$.initialize(EbtUSampler2DArray, @1);
- }
- | USAMPLER2DMS {
- $$.initialize(EbtUSampler2DMS, @1);
- }
- | SAMPLER2DSHADOW {
- $$.initialize(EbtSampler2DShadow, @1);
- }
- | SAMPLERCUBESHADOW {
- $$.initialize(EbtSamplerCubeShadow, @1);
- }
- | SAMPLER2DARRAYSHADOW {
- $$.initialize(EbtSampler2DArrayShadow, @1);
- }
- | SAMPLER_EXTERNAL_OES {
- constexpr std::array<TExtension, 3u> extensions{ { TExtension::NV_EGL_stream_consumer_external,
- TExtension::OES_EGL_image_external_essl3,
- TExtension::OES_EGL_image_external } };
- if (!context->checkCanUseOneOfExtensions(@1, extensions))
- {
- context->error(@1, "unsupported type", "samplerExternalOES");
- }
- $$.initialize(EbtSamplerExternalOES, @1);
- }
- | SAMPLEREXTERNAL2DY2YEXT {
- if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target))
- {
- context->error(@1, "unsupported type", "__samplerExternal2DY2YEXT");
- }
- $$.initialize(EbtSamplerExternal2DY2YEXT, @1);
- }
- | SAMPLER2DRECT {
- if (!context->checkCanUseExtension(@1, TExtension::ARB_texture_rectangle))
- {
- context->error(@1, "unsupported type", "sampler2DRect");
- }
- $$.initialize(EbtSampler2DRect, @1);
- }
- | struct_specifier {
- $$ = $1;
- }
- | IMAGE2D {
- $$.initialize(EbtImage2D, @1);
- }
- | IIMAGE2D {
- $$.initialize(EbtIImage2D, @1);
- }
- | UIMAGE2D {
- $$.initialize(EbtUImage2D, @1);
- }
- | IMAGE3D {
- $$.initialize(EbtImage3D, @1);
- }
- | IIMAGE3D {
- $$.initialize(EbtIImage3D, @1);
- }
- | UIMAGE3D {
- $$.initialize(EbtUImage3D, @1);
- }
- | IMAGE2DARRAY {
- $$.initialize(EbtImage2DArray, @1);
- }
- | IIMAGE2DARRAY {
- $$.initialize(EbtIImage2DArray, @1);
- }
- | UIMAGE2DARRAY {
- $$.initialize(EbtUImage2DArray, @1);
- }
- | IMAGECUBE {
- $$.initialize(EbtImageCube, @1);
- }
- | IIMAGECUBE {
- $$.initialize(EbtIImageCube, @1);
- }
- | UIMAGECUBE {
- $$.initialize(EbtUImageCube, @1);
- }
- | ATOMICUINT {
- $$.initialize(EbtAtomicCounter, @1);
- }
- | TYPE_NAME {
- // This is for user defined type names. The lexical phase looked up the type.
- TType& structure = static_cast<TVariable*>($1.symbol)->getType();
- $$.initializeStruct(structure.getStruct(), false, @1);
- }
- ;
-
-struct_specifier
- : STRUCT identifier LEFT_BRACE { context->enterStructDeclaration(@2, *$2.string); } struct_declaration_list RIGHT_BRACE {
- $$ = context->addStructure(@1, @2, $2.string, $5);
- }
- | STRUCT LEFT_BRACE { context->enterStructDeclaration(@2, *$2.string); } struct_declaration_list RIGHT_BRACE {
- $$ = context->addStructure(@1, @$, NewPoolTString(""), $4);
- }
- ;
-
-struct_declaration_list
- : struct_declaration {
- $$ = context->addStructFieldList($1, @1);
- }
- | struct_declaration_list struct_declaration {
- $$ = context->combineStructFieldLists($1, $2, @2);
- }
- ;
-
-struct_declaration
- : type_specifier struct_declarator_list SEMICOLON {
- $$ = context->addStructDeclaratorList($1, $2);
- }
- | type_qualifier type_specifier struct_declarator_list SEMICOLON {
- // ES3 Only, but errors should be handled elsewhere
- $$ = context->addStructDeclaratorListWithQualifiers(*$1, &$2, $3);
- }
- ;
-
-struct_declarator_list
- : struct_declarator {
- $$ = NewPoolTFieldList();
- $$->push_back($1);
- }
- | struct_declarator_list COMMA struct_declarator {
- $$->push_back($3);
- }
- ;
-
-struct_declarator
- : identifier {
- $$ = context->parseStructDeclarator($1.string, @1);
- }
- | identifier array_specifier {
- $$ = context->parseStructArrayDeclarator($1.string, @1, *($2), @2);
- }
- ;
-
-initializer
- : assignment_expression { $$ = $1; }
- ;
-
-declaration_statement
- : declaration { $$ = $1; }
- ;
-
-statement
- : compound_statement_with_scope { $$ = $1; }
- | simple_statement { $$ = $1; }
- ;
-
-// Grammar Note: Labeled statements for SWITCH only; 'goto' is not supported.
-
-simple_statement
- : declaration_statement { $$ = $1; }
- | expression_statement { $$ = $1; }
- | selection_statement { $$ = $1; }
- | switch_statement { $$ = $1; }
- | case_label { $$ = $1; }
- | iteration_statement { $$ = $1; }
- | jump_statement { $$ = $1; }
- ;
-
-compound_statement_with_scope
- : LEFT_BRACE RIGHT_BRACE {
- $$ = new TIntermBlock();
- $$->setLine(@$);
- }
- | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE {
- $3->setLine(@$);
- $$ = $3;
- }
- ;
-
-statement_no_new_scope
- : compound_statement_no_new_scope { $$ = $1; }
- | simple_statement { $$ = $1; }
- ;
-
-statement_with_scope
- : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; }
- | { context->symbolTable.push(); } simple_statement { context->symbolTable.pop(); $$ = $2; }
- ;
-
-compound_statement_no_new_scope
- // Statement that doesn't create a new scope for iteration_statement, function definition (scope is created for parameters)
- : LEFT_BRACE RIGHT_BRACE {
- $$ = new TIntermBlock();
- $$->setLine(@$);
- }
- | LEFT_BRACE statement_list RIGHT_BRACE {
- $2->setLine(@$);
- $$ = $2;
- }
- ;
-
-statement_list
- : statement {
- $$ = new TIntermBlock();
- $$->appendStatement($1);
- }
- | statement_list statement {
- $$ = $1;
- $$->appendStatement($2);
- }
- ;
-
-expression_statement
- : SEMICOLON { $$ = context->addEmptyStatement(@$); }
- | expression SEMICOLON { $$ = $1; }
- ;
-
-selection_statement
- : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
- $$ = context->addIfElse($3, $5, @1);
- }
- ;
-
-selection_rest_statement
- : statement_with_scope ELSE statement_with_scope {
- $$.node1 = $1;
- $$.node2 = $3;
- }
- | statement_with_scope {
- $$.node1 = $1;
- $$.node2 = nullptr;
- }
- ;
-
-// Note that we've diverged from the spec grammar here a bit for the sake of simplicity.
-// We're reusing compound_statement_with_scope instead of having separate rules for switch.
-switch_statement
- : SWITCH LEFT_PAREN expression RIGHT_PAREN { context->incrSwitchNestingLevel(); } compound_statement_with_scope {
- $$ = context->addSwitch($3, $6, @1);
- context->decrSwitchNestingLevel();
- }
- ;
-
-case_label
- : CASE constant_expression COLON {
- $$ = context->addCase($2, @1);
- }
- | DEFAULT COLON {
- $$ = context->addDefault(@1);
- }
- ;
-
-condition
- : expression {
- $$ = $1;
- context->checkIsScalarBool($1->getLine(), $1);
- }
- | fully_specified_type identifier EQUAL initializer {
- $$ = context->addConditionInitializer($1, *$2.string, $4, @2);
- }
- ;
-
-iteration_statement
- : WHILE LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(); } condition RIGHT_PAREN statement_no_new_scope {
- context->symbolTable.pop();
- $$ = context->addLoop(ELoopWhile, 0, $4, 0, $6, @1);
- context->decrLoopNestingLevel();
- }
- | DO { context->incrLoopNestingLevel(); } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
- $$ = context->addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
- context->decrLoopNestingLevel();
- }
- | FOR LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(); } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
- context->symbolTable.pop();
- $$ = context->addLoop(ELoopFor, $4, $5.node1, reinterpret_cast<TIntermTyped*>($5.node2), $7, @1);
- context->decrLoopNestingLevel();
- }
- ;
-
-for_init_statement
- : expression_statement {
- $$ = $1;
- }
- | declaration_statement {
- $$ = $1;
- }
- ;
-
-conditionopt
- : condition {
- $$ = $1;
- }
- | /* May be null */ {
- $$ = nullptr;
- }
- ;
-
-for_rest_statement
- : conditionopt SEMICOLON {
- $$.node1 = $1;
- $$.node2 = 0;
- }
- | conditionopt SEMICOLON expression {
- $$.node1 = $1;
- $$.node2 = $3;
- }
- ;
-
-jump_statement
- : CONTINUE SEMICOLON {
- $$ = context->addBranch(EOpContinue, @1);
- }
- | BREAK SEMICOLON {
- $$ = context->addBranch(EOpBreak, @1);
- }
- | RETURN SEMICOLON {
- $$ = context->addBranch(EOpReturn, @1);
- }
- | RETURN expression SEMICOLON {
- $$ = context->addBranch(EOpReturn, $2, @1);
- }
- | DISCARD SEMICOLON {
- $$ = context->addBranch(EOpKill, @1);
- }
- ;
-
-// Grammar Note: No 'goto'. Gotos are not supported.
-
-translation_unit
- : external_declaration {
- $$ = new TIntermBlock();
- $$->setLine(@$);
- $$->appendStatement($1);
- context->setTreeRoot($$);
- }
- | translation_unit external_declaration {
- $$->appendStatement($2);
- }
- ;
-
-external_declaration
- : function_definition {
- $$ = $1;
- }
- | declaration {
- $$ = $1;
- }
- ;
-
-function_definition
- : function_prototype {
- context->parseFunctionDefinitionHeader(@1, &($1.function), &($1.intermFunctionPrototype));
- }
- compound_statement_no_new_scope {
- $$ = context->addFunctionDefinition($1.intermFunctionPrototype, $3, @1);
- }
- ;
-
-%%
-
-int glslang_parse(TParseContext* context) {
- return yyparse(context, context->getScanner());
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/length_limits.h b/src/3rdparty/angle/src/compiler/translator/length_limits.h
deleted file mode 100644
index fcda639d71..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/length_limits.h
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// Copyright (c) 2011-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.
-//
-
-//
-// 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/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp
deleted file mode 100644
index 9738370c47..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/util.cpp
+++ /dev/null
@@ -1,714 +0,0 @@
-//
-// Copyright (c) 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 <limits>
-
-#include "common/utilities.h"
-#include "compiler/preprocessor/numeric_lex.h"
-#include "compiler/translator/SymbolTable.h"
-
-bool atoi_clamp(const char *str, unsigned int *value)
-{
- bool success = pp::numeric_lex_int(str, value);
- if (!success)
- *value = std::numeric_limits<unsigned int>::max();
- return success;
-}
-
-namespace sh
-{
-
-namespace
-{
-
-bool IsInterpolationIn(TQualifier qualifier)
-{
- switch (qualifier)
- {
- case EvqSmoothIn:
- case EvqFlatIn:
- case EvqCentroidIn:
- 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;
- 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<unsigned int>(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<unsigned int>::max() - 9u) / 10u)
- {
- decimalMantissa = decimalMantissa * 10u + digit;
- }
- 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<unsigned int>(c - '0');
- ASSERT(digit < 10u);
- if (exponent <= (std::numeric_limits<int>::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<float>::infinity();
- }
- }
- }
- // Do the calculation in 64-bit to avoid overflow.
- long long exponentLong =
- static_cast<long long>(exponent) + static_cast<long long>(exponentOffset);
- if (exponentLong > std::numeric_limits<float>::max_exponent10)
- {
- return std::numeric_limits<float>::infinity();
- }
- else if (exponentLong < std::numeric_limits<float>::min_exponent10)
- {
- return 0.0f;
- }
- // The exponent is in range, so we need to actually evaluate the float.
- exponent = static_cast<int>(exponentLong);
- double value = decimalMantissa;
-
- // Calculate the exponent offset to normalize the mantissa.
- int normalizationExponentOffset = 0;
- while (decimalMantissa >= 10u)
- {
- --normalizationExponentOffset;
- decimalMantissa /= 10u;
- }
- // Apply the exponent.
- value *= std::pow(10.0, static_cast<double>(exponent + normalizationExponentOffset));
- if (value > static_cast<double>(std::numeric_limits<float>::max()))
- {
- return std::numeric_limits<float>::infinity();
- }
- if (value < static_cast<double>(std::numeric_limits<float>::min()))
- {
- return 0.0f;
- }
- return static_cast<float>(value);
-}
-
-bool strtof_clamp(const std::string &str, float *value)
-{
- // Try the standard float parsing path first.
- bool success = pp::numeric_lex_float(str, value);
-
- // If the standard path doesn't succeed, take the path 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.
- if (!success)
- *value = NumericLexFloat32OutOfRangeToInfinity(str);
- return !gl::isInf(*value);
-}
-
-GLenum GLVariableType(const TType &type)
-{
- if (type.getBasicType() == EbtFloat)
- {
- if (type.isVector())
- {
- switch (type.getNominalSize())
- {
- case 2:
- return GL_FLOAT_VEC2;
- case 3:
- return GL_FLOAT_VEC3;
- case 4:
- return GL_FLOAT_VEC4;
- default:
- UNREACHABLE();
- }
- }
- else if (type.isMatrix())
- {
- switch (type.getCols())
- {
- case 2:
- switch (type.getRows())
- {
- case 2:
- return GL_FLOAT_MAT2;
- case 3:
- return GL_FLOAT_MAT2x3;
- case 4:
- return GL_FLOAT_MAT2x4;
- default:
- UNREACHABLE();
- }
-
- case 3:
- switch (type.getRows())
- {
- case 2:
- return GL_FLOAT_MAT3x2;
- case 3:
- return GL_FLOAT_MAT3;
- case 4:
- return GL_FLOAT_MAT3x4;
- default:
- UNREACHABLE();
- }
-
- case 4:
- switch (type.getRows())
- {
- case 2:
- return GL_FLOAT_MAT4x2;
- case 3:
- return GL_FLOAT_MAT4x3;
- case 4:
- return GL_FLOAT_MAT4;
- default:
- UNREACHABLE();
- }
-
- default:
- UNREACHABLE();
- }
- }
- else
- {
- return GL_FLOAT;
- }
- }
- else if (type.getBasicType() == EbtInt)
- {
- if (type.isVector())
- {
- switch (type.getNominalSize())
- {
- case 2:
- return GL_INT_VEC2;
- case 3:
- return GL_INT_VEC3;
- case 4:
- return GL_INT_VEC4;
- default:
- UNREACHABLE();
- }
- }
- else
- {
- ASSERT(!type.isMatrix());
- return GL_INT;
- }
- }
- else if (type.getBasicType() == EbtUInt)
- {
- if (type.isVector())
- {
- switch (type.getNominalSize())
- {
- case 2:
- return GL_UNSIGNED_INT_VEC2;
- case 3:
- return GL_UNSIGNED_INT_VEC3;
- case 4:
- return GL_UNSIGNED_INT_VEC4;
- default:
- UNREACHABLE();
- }
- }
- else
- {
- ASSERT(!type.isMatrix());
- return GL_UNSIGNED_INT;
- }
- }
- else if (type.getBasicType() == EbtBool)
- {
- if (type.isVector())
- {
- switch (type.getNominalSize())
- {
- case 2:
- return GL_BOOL_VEC2;
- case 3:
- return GL_BOOL_VEC3;
- case 4:
- return GL_BOOL_VEC4;
- default:
- UNREACHABLE();
- }
- }
- else
- {
- ASSERT(!type.isMatrix());
- return GL_BOOL;
- }
- }
-
- switch (type.getBasicType())
- {
- 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 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 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 EbtSampler2DShadow:
- return GL_SAMPLER_2D_SHADOW;
- case EbtSamplerCubeShadow:
- return GL_SAMPLER_CUBE_SHADOW;
- case EbtSampler2DArrayShadow:
- return GL_SAMPLER_2D_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 EbtAtomicCounter:
- return GL_UNSIGNED_INT_ATOMIC_COUNTER;
- 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:
- // Should be defined as the default precision by the parser
- 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:
- // Should be defined as the default precision by the parser
- default:
- UNREACHABLE();
- }
- }
-
- // Other types (boolean, sampler) don't have a precision
- return GL_NONE;
-}
-
-TString ArrayString(const TType &type)
-{
- TStringStream arrayString;
- if (!type.isArray())
- return arrayString.str();
-
- const TVector<unsigned int> &arraySizes = *type.getArraySizes();
- for (auto arraySizeIter = arraySizes.rbegin(); arraySizeIter != arraySizes.rend();
- ++arraySizeIter)
- {
- arrayString << "[";
- if (*arraySizeIter > 0)
- {
- arrayString << (*arraySizeIter);
- }
- arrayString << "]";
- }
- return arrayString.str();
-}
-
-TString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap)
-{
- if (type.getBasicType() == EbtStruct)
- return HashName(TName(type.getStruct()->name()), hashFunction, nameMap);
- else
- return type.getBuiltInTypeNameString();
-}
-
-bool IsVaryingOut(TQualifier qualifier)
-{
- switch (qualifier)
- {
- case EvqVaryingOut:
- case EvqSmoothOut:
- case EvqFlatOut:
- case EvqCentroidOut:
- case EvqVertexOut:
- case EvqGeometryOut:
- return true;
-
- default:
- break;
- }
-
- return false;
-}
-
-bool IsVaryingIn(TQualifier qualifier)
-{
- switch (qualifier)
- {
- case EvqVaryingIn:
- case EvqSmoothIn:
- case EvqFlatIn:
- case EvqCentroidIn:
- case EvqFragmentIn:
- case EvqGeometryIn:
- return true;
-
- default:
- break;
- }
-
- return false;
-}
-
-bool IsVarying(TQualifier qualifier)
-{
- return IsVaryingIn(qualifier) || IsVaryingOut(qualifier);
-}
-
-bool IsGeometryShaderInput(GLenum shaderType, TQualifier qualifier)
-{
- return (qualifier == EvqGeometryIn) ||
- ((shaderType == GL_GEOMETRY_SHADER_OES) && IsInterpolationIn(qualifier));
-}
-
-InterpolationType GetInterpolationType(TQualifier qualifier)
-{
- switch (qualifier)
- {
- case EvqFlatIn:
- case EvqFlatOut:
- return INTERPOLATION_FLAT;
-
- case EvqSmoothIn:
- case EvqSmoothOut:
- case EvqVertexOut:
- case EvqFragmentIn:
- case EvqVaryingIn:
- case EvqVaryingOut:
- case EvqGeometryIn:
- case EvqGeometryOut:
- return INTERPOLATION_SMOOTH;
-
- case EvqCentroidIn:
- case EvqCentroidOut:
- return INTERPOLATION_CENTROID;
-
- default:
- UNREACHABLE();
- return INTERPOLATION_SMOOTH;
- }
-}
-
-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();
- }
-}
-
-// 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);
-}
-
-bool IsBuiltinOutputVariable(TQualifier qualifier)
-{
- switch (qualifier)
- {
- case EvqPosition:
- case EvqPointSize:
- case EvqFragDepth:
- case EvqFragDepthEXT:
- case EvqFragColor:
- case EvqSecondaryFragColorEXT:
- case EvqFragData:
- case EvqSecondaryFragDataEXT:
- return true;
- default:
- break;
- }
- return false;
-}
-
-bool IsBuiltinFragmentInputVariable(TQualifier qualifier)
-{
- switch (qualifier)
- {
- case EvqFragCoord:
- case EvqPointCoord:
- case EvqFrontFacing:
- return true;
- default:
- break;
- }
- 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_GLSL_VULKAN_OUTPUT;
-}
-
-} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h
deleted file mode 100644
index 6d6dc95b3b..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/util.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// Copyright (c) 2002-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_UTIL_H_
-#define COMPILER_TRANSLATOR_UTIL_H_
-
-#include <stack>
-
-#include "angle_gl.h"
-#include <GLSLANG/ShaderLang.h>
-
-#include "compiler/translator/HashNames.h"
-#include "compiler/translator/Operator.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
-{
-class TSymbolTable;
-
-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 IsGeometryShaderInput(GLenum shaderType, TQualifier qualifier);
-InterpolationType GetInterpolationType(TQualifier qualifier);
-
-// Returns array brackets including size with outermost array size first, as specified in GLSL ES
-// 3.10 section 4.1.9.
-TString ArrayString(const TType &type);
-
-TString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap);
-
-TType GetShaderVariableBasicType(const sh::ShaderVariable &var);
-
-bool IsBuiltinOutputVariable(TQualifier qualifier);
-bool IsBuiltinFragmentInputVariable(TQualifier qualifier);
-bool CanBeInvariantESSL1(TQualifier qualifier);
-bool CanBeInvariantESSL3OrGreater(TQualifier qualifier);
-bool IsOutputESSL(ShShaderOutput output);
-bool IsOutputGLSL(ShShaderOutput output);
-bool IsOutputHLSL(ShShaderOutput output);
-bool IsOutputVulkan(ShShaderOutput output);
-} // namespace sh
-
-#endif // COMPILER_TRANSLATOR_UTIL_H_