From 311157c3c6849e8efccd88f7594bb34c570a6780 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Thu, 25 Sep 2014 13:22:55 +0300 Subject: ANGLE: Upgrade to 2.1~abce76206141 Upgrade to address issues discovered since the last upgrade. Patch notes: 0000-General-fixes-for-ANGLE-2.1.patch added removal of the unused third-party tracing functions 0003-Fix-compilation-with-MinGW-gcc-64-bit.patch removed as it is no longer needed 0011-ANGLE-Fix-compilation-error-on-MinGW-caused-by-trace.patch removed as it is no longer needed 0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch now supports MinGW 64-bit [ChangeLog][Third-party libraries] ANGLE updated to 2.1~f8602ad91e4f Task-number: QTBUG-40649 Task-number: QTBUG-40658 Task-number: QTBUG-41031 Task-number: QTBUG-41081 Task-number: QTBUG-41308 Task-number: QTBUG-41563 Change-Id: I9f776c8d5cb94ddb12d608a8d5630bfc54437bea Reviewed-by: Friedemann Kleint Reviewed-by: Oliver Wolff Reviewed-by: Kai Koehne --- .../angle/src/compiler/translator/BaseTypes.h | 33 +- .../compiler/translator/BuiltInFunctionEmulator.h | 2 +- .../angle/src/compiler/translator/Compiler.cpp | 26 +- .../angle/src/compiler/translator/Compiler.h | 13 +- .../src/compiler/translator/DetectCallDepth.h | 2 +- .../src/compiler/translator/DetectDiscontinuity.h | 2 +- .../src/compiler/translator/FlagStd140Structs.h | 2 +- .../angle/src/compiler/translator/HashNames.h | 2 +- .../angle/src/compiler/translator/Initialize.cpp | 2 +- .../src/compiler/translator/InitializeVariables.h | 2 +- .../angle/src/compiler/translator/IntermNode.cpp | 1107 ++++++++++++++++++++ .../angle/src/compiler/translator/IntermNode.h | 772 ++++++++++++++ .../src/compiler/translator/IntermTraverse.cpp | 2 +- .../angle/src/compiler/translator/Intermediate.cpp | 1093 +------------------ .../angle/src/compiler/translator/LoopInfo.h | 2 +- .../angle/src/compiler/translator/NodeSearch.h | 2 +- .../src/compiler/translator/OutputGLSLBase.cpp | 14 +- .../angle/src/compiler/translator/OutputGLSLBase.h | 2 +- .../angle/src/compiler/translator/OutputHLSL.cpp | 74 +- .../angle/src/compiler/translator/OutputHLSL.h | 16 +- .../angle/src/compiler/translator/ParseContext.cpp | 75 +- .../angle/src/compiler/translator/ParseContext.h | 7 +- .../src/compiler/translator/QualifierAlive.cpp | 2 +- .../compiler/translator/RegenerateStructNames.cpp | 82 ++ .../compiler/translator/RegenerateStructNames.h | 40 + .../angle/src/compiler/translator/RemoveTree.cpp | 2 +- .../angle/src/compiler/translator/RenameFunction.h | 2 +- .../src/compiler/translator/RewriteElseBlocks.h | 2 +- .../ScalarizeVecAndMatConstructorArgs.cpp | 11 + .../translator/ScalarizeVecAndMatConstructorArgs.h | 12 +- .../angle/src/compiler/translator/SearchSymbol.h | 2 +- .../angle/src/compiler/translator/ShaderLang.cpp | 124 ++- .../angle/src/compiler/translator/ShaderVars.cpp | 166 +++ .../src/compiler/translator/StructureHLSL.cpp | 35 +- .../angle/src/compiler/translator/StructureHLSL.h | 13 +- .../angle/src/compiler/translator/SymbolTable.cpp | 8 +- .../angle/src/compiler/translator/SymbolTable.h | 14 +- .../src/compiler/translator/TranslatorHLSL.cpp | 8 +- .../angle/src/compiler/translator/TranslatorHLSL.h | 1 - .../angle/src/compiler/translator/Types.cpp | 32 + src/3rdparty/angle/src/compiler/translator/Types.h | 11 + .../src/compiler/translator/UnfoldShortCircuit.h | 2 +- .../compiler/translator/UnfoldShortCircuitAST.h | 2 +- .../angle/src/compiler/translator/UniformHLSL.cpp | 76 +- .../angle/src/compiler/translator/UniformHLSL.h | 9 +- .../src/compiler/translator/ValidateLimitations.h | 2 +- .../src/compiler/translator/ValidateOutputs.h | 2 +- .../angle/src/compiler/translator/VariableInfo.cpp | 197 ++-- .../angle/src/compiler/translator/VariableInfo.h | 37 +- .../src/compiler/translator/VariablePacker.cpp | 8 +- .../angle/src/compiler/translator/VersionGLSL.cpp | 3 + .../angle/src/compiler/translator/VersionGLSL.h | 2 +- .../compiler/translator/depgraph/DependencyGraph.h | 2 +- .../angle/src/compiler/translator/glslang.y | 58 +- .../angle/src/compiler/translator/intermOut.cpp | 3 +- .../angle/src/compiler/translator/intermediate.h | 806 +------------- .../src/compiler/translator/localintermediate.h | 67 -- .../timing/RestrictFragmentShaderTiming.h | 2 +- .../translator/timing/RestrictVertexShaderTiming.h | 2 +- .../angle/src/compiler/translator/util.cpp | 53 +- src/3rdparty/angle/src/compiler/translator/util.h | 28 +- 61 files changed, 2794 insertions(+), 2386 deletions(-) create mode 100644 src/3rdparty/angle/src/compiler/translator/IntermNode.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/IntermNode.h create mode 100644 src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h create mode 100644 src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/localintermediate.h (limited to 'src/3rdparty/angle/src/compiler') diff --git a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h index ba9ef5e609..324b0669f4 100644 --- a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h +++ b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h @@ -69,40 +69,9 @@ enum TBasicType EbtStruct, EbtInterfaceBlock, EbtAddress, // should be deprecated?? - EbtInvariant // used as a type when qualifying a previously declared variable as being invariant }; -inline const char* getBasicString(TBasicType t) -{ - switch (t) - { - case EbtVoid: return "void"; break; - case EbtFloat: return "float"; break; - case EbtInt: return "int"; break; - case EbtUInt: return "uint"; break; - case EbtBool: return "bool"; break; - case EbtSampler2D: return "sampler2D"; break; - case EbtSampler3D: return "sampler3D"; break; - case EbtSamplerCube: return "samplerCube"; break; - case EbtSamplerExternalOES: return "samplerExternalOES"; break; - case EbtSampler2DRect: return "sampler2DRect"; break; - case EbtSampler2DArray: return "sampler2DArray"; break; - case EbtISampler2D: return "isampler2D"; break; - case EbtISampler3D: return "isampler3D"; break; - case EbtISamplerCube: return "isamplerCube"; break; - case EbtISampler2DArray: return "isampler2DArray"; break; - case EbtUSampler2D: return "usampler2D"; break; - case EbtUSampler3D: return "usampler3D"; break; - case EbtUSamplerCube: return "usamplerCube"; break; - case EbtUSampler2DArray: return "usampler2DArray"; break; - case EbtSampler2DShadow: return "sampler2DShadow"; break; - case EbtSamplerCubeShadow: return "samplerCubeShadow"; break; - case EbtSampler2DArrayShadow: return "sampler2DArrayShadow"; break; - case EbtStruct: return "structure"; break; - case EbtInterfaceBlock: return "interface block"; break; - default: return "unknown type"; - } -} +const char* getBasicString(TBasicType t); inline bool IsSampler(TBasicType type) { diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h index 926b6bed69..c6bf77c386 100644 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h @@ -8,7 +8,7 @@ #define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ #include "compiler/translator/InfoSink.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // // This class decides which built-in functions need to be replaced with the diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp index 0606c72e39..368cd2ae4a 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp @@ -12,6 +12,7 @@ #include "compiler/translator/InitializeParseContext.h" #include "compiler/translator/InitializeVariables.h" #include "compiler/translator/ParseContext.h" +#include "compiler/translator/RegenerateStructNames.h" #include "compiler/translator/RenameFunction.h" #include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h" #include "compiler/translator/UnfoldShortCircuitAST.h" @@ -257,10 +258,17 @@ bool TCompiler::compile(const char* const shaderStrings[], if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)) { - ScalarizeVecAndMatConstructorArgs scalarizer; + ScalarizeVecAndMatConstructorArgs scalarizer( + shaderType, fragmentPrecisionHigh); root->traverse(&scalarizer); } + if (success && (compileOptions & SH_REGENERATE_STRUCT_NAMES)) + { + RegenerateStructNames gen(symbolTable, shaderVersion); + root->traverse(&gen); + } + if (success && (compileOptions & SH_INTERMEDIATE_TREE)) intermediate.outputTree(root); @@ -494,18 +502,18 @@ bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root) void TCompiler::collectVariables(TIntermNode* root) { - CollectVariables collect(&attributes, - &outputVariables, - &uniforms, - &varyings, - &interfaceBlocks, - hashFunction); + sh::CollectVariables collect(&attributes, + &outputVariables, + &uniforms, + &varyings, + &interfaceBlocks, + hashFunction); root->traverse(&collect); // For backwards compatiblity with ShGetVariableInfo, expand struct // uniforms and varyings into separate variables for each field. - ExpandVariables(uniforms, &expandedUniforms); - ExpandVariables(varyings, &expandedVaryings); + sh::ExpandVariables(uniforms, &expandedUniforms); + sh::ExpandVariables(varyings, &expandedVaryings); } bool TCompiler::enforcePackingRestrictions() diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.h b/src/3rdparty/angle/src/compiler/translator/Compiler.h index 5eac2d89d1..ca0c157884 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.h +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.h @@ -71,9 +71,9 @@ class TCompiler : public TShHandleBase const std::vector &getAttributes() const { return attributes; } const std::vector &getOutputVariables() const { return outputVariables; } const std::vector &getUniforms() const { return uniforms; } - const std::vector &getExpandedUniforms() const { return expandedUniforms; } + const std::vector &getExpandedUniforms() const { return expandedUniforms; } const std::vector &getVaryings() const { return varyings; } - const std::vector &getExpandedVaryings() const { return expandedVaryings; } + const std::vector &getExpandedVaryings() const { return expandedVaryings; } const std::vector &getInterfaceBlocks() const { return interfaceBlocks; } ShHashFunction64 getHashFunction() const { return hashFunction; } @@ -83,6 +83,9 @@ class TCompiler : public TShHandleBase ShShaderOutput getOutputType() const { return outputType; } std::string getBuiltInResourcesString() const { return builtInResourcesString; } + // Get the resources set by InitBuiltInSymbolTable + const ShBuiltInResources& getResources() const; + protected: sh::GLenum getShaderType() const { return shaderType; } // Initialize symbol-table with built-in symbols. @@ -128,8 +131,6 @@ class TCompiler : public TShHandleBase bool limitExpressionComplexity(TIntermNode* root); // Get built-in extensions with default behavior. const TExtensionBehavior& getExtensionBehavior() const; - // Get the resources set by InitBuiltInSymbolTable - const ShBuiltInResources& getResources() const; const ArrayBoundsClamper& getArrayBoundsClamper() const; ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; @@ -138,9 +139,9 @@ class TCompiler : public TShHandleBase std::vector attributes; std::vector outputVariables; std::vector uniforms; - std::vector expandedUniforms; + std::vector expandedUniforms; std::vector varyings; - std::vector expandedVaryings; + std::vector expandedVaryings; std::vector interfaceBlocks; private: diff --git a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h index cb76f1de02..86810650dc 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h @@ -8,7 +8,7 @@ #define COMPILER_DETECT_RECURSION_H_ #include -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/VariableInfo.h" class TInfoSink; diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h index 1dd8be9233..35d66cbc2e 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h @@ -11,7 +11,7 @@ #ifndef COMPILER_DETECTDISCONTINUITY_H_ #define COMPILER_DETECTDISCONTINUITY_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h index 610205eb92..c93a6f808e 100644 --- a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h +++ b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h @@ -7,7 +7,7 @@ #ifndef COMPILER_FLAGSTD140STRUCTS_H_ #define COMPILER_FLAGSTD140STRUCTS_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.h b/src/3rdparty/angle/src/compiler/translator/HashNames.h index 85161428b2..26546a3e7b 100644 --- a/src/3rdparty/angle/src/compiler/translator/HashNames.h +++ b/src/3rdparty/angle/src/compiler/translator/HashNames.h @@ -9,7 +9,7 @@ #include -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #define HASHED_NAME_PREFIX "webgl_" diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp index e91d64f43b..10b21e6d28 100644 --- a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp @@ -12,7 +12,7 @@ #include "compiler/translator/Initialize.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "angle_gl.h" void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h index 81ab9fe90f..59c3ea0a39 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h +++ b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h @@ -7,7 +7,7 @@ #ifndef COMPILER_INITIALIZE_VARIABLES_H_ #define COMPILER_INITIALIZE_VARIABLES_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class InitializeVariables : public TIntermTraverser { diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp new file mode 100644 index 0000000000..b155545ad2 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp @@ -0,0 +1,1107 @@ +// +// 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 +#include +#include + +#include "compiler/translator/HashNames.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/SymbolTable.h" + +namespace +{ + +TPrecision GetHigherPrecision(TPrecision left, TPrecision right) +{ + return left > right ? left : right; +} + +bool ValidateMultiplication(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: + case EOpVectorTimesScalarAssign: + return true; + case EOpVectorTimesMatrix: + return left.getNominalSize() == right.getRows(); + case EOpVectorTimesMatrixAssign: + return left.getNominalSize() == right.getRows() && + left.getNominalSize() == right.getCols(); + case EOpMatrixTimesVector: + return left.getCols() == right.getNominalSize(); + case EOpMatrixTimesScalar: + case EOpMatrixTimesScalarAssign: + return true; + case EOpMatrixTimesMatrix: + return left.getCols() == right.getRows(); + case EOpMatrixTimesMatrixAssign: + return left.getCols() == right.getCols() && + left.getRows() == right.getRows(); + + default: + UNREACHABLE(); + return false; + } +} + +bool CompareStructure(const TType& leftNodeType, + ConstantUnion *rightUnionArray, + ConstantUnion *leftUnionArray); + +bool CompareStruct(const TType &leftNodeType, + ConstantUnion *rightUnionArray, + ConstantUnion *leftUnionArray) +{ + const TFieldList &fields = leftNodeType.getStruct()->fields(); + + size_t structSize = fields.size(); + size_t index = 0; + + for (size_t j = 0; j < structSize; j++) + { + size_t size = fields[j]->type()->getObjectSize(); + for (size_t i = 0; i < size; i++) + { + if (fields[j]->type()->getBasicType() == EbtStruct) + { + if (!CompareStructure(*fields[j]->type(), + &rightUnionArray[index], + &leftUnionArray[index])) + { + return false; + } + } + else + { + if (leftUnionArray[index] != rightUnionArray[index]) + return false; + index++; + } + } + } + return true; +} + +bool CompareStructure(const TType &leftNodeType, + ConstantUnion *rightUnionArray, + ConstantUnion *leftUnionArray) +{ + if (leftNodeType.isArray()) + { + TType typeWithoutArrayness = leftNodeType; + typeWithoutArrayness.clearArrayness(); + + size_t arraySize = leftNodeType.getArraySize(); + + for (size_t i = 0; i < arraySize; ++i) + { + size_t offset = typeWithoutArrayness.getObjectSize() * i; + if (!CompareStruct(typeWithoutArrayness, + &rightUnionArray[offset], + &leftUnionArray[offset])) + { + return false; + } + } + } + else + { + return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); + } + return true; +} + +} // namespace anonymous + + +//////////////////////////////////////////////////////////////// +// +// Member functions of the nodes used for building the tree. +// +//////////////////////////////////////////////////////////////// + +#define REPLACE_IF_IS(node, type, original, replacement) \ + if (node == original) { \ + node = static_cast(replacement); \ + return true; \ + } + +bool TIntermLoop::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + 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, TIntermNode, original, replacement); + return false; +} + +void TIntermLoop::enqueueChildren(std::queue *nodeQueue) const +{ + if (mInit) + { + nodeQueue->push(mInit); + } + if (mCond) + { + nodeQueue->push(mCond); + } + if (mExpr) + { + nodeQueue->push(mExpr); + } + if (mBody) + { + nodeQueue->push(mBody); + } +} + +bool TIntermBranch::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement); + return false; +} + +void TIntermBranch::enqueueChildren(std::queue *nodeQueue) const +{ + if (mExpression) + { + nodeQueue->push(mExpression); + } +} + +bool TIntermBinary::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement); + REPLACE_IF_IS(mRight, TIntermTyped, original, replacement); + return false; +} + +void TIntermBinary::enqueueChildren(std::queue *nodeQueue) const +{ + if (mLeft) + { + nodeQueue->push(mLeft); + } + if (mRight) + { + nodeQueue->push(mRight); + } +} + +bool TIntermUnary::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); + return false; +} + +void TIntermUnary::enqueueChildren(std::queue *nodeQueue) const +{ + if (mOperand) + { + nodeQueue->push(mOperand); + } +} + +bool TIntermAggregate::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + for (size_t ii = 0; ii < mSequence.size(); ++ii) + { + REPLACE_IF_IS(mSequence[ii], TIntermNode, original, replacement); + } + return false; +} + +void TIntermAggregate::enqueueChildren(std::queue *nodeQueue) const +{ + for (size_t childIndex = 0; childIndex < mSequence.size(); childIndex++) + { + nodeQueue->push(mSequence[childIndex]); + } +} + +bool TIntermSelection::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); + REPLACE_IF_IS(mTrueBlock, TIntermNode, original, replacement); + REPLACE_IF_IS(mFalseBlock, TIntermNode, original, replacement); + return false; +} + +void TIntermSelection::enqueueChildren(std::queue *nodeQueue) const +{ + if (mCondition) + { + nodeQueue->push(mCondition); + } + if (mTrueBlock) + { + nodeQueue->push(mTrueBlock); + } + if (mFalseBlock) + { + nodeQueue->push(mFalseBlock); + } +} + +// +// Say whether or not an operation node changes the value of a variable. +// +bool TIntermOperator::isAssignment() const +{ + switch (mOp) + { + 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: + return true; + default: + return false; + } +} + +// +// returns true if the operator is for one of the constructors +// +bool TIntermOperator::isConstructor() const +{ + switch (mOp) + { + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + case EOpConstructFloat: + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + case EOpConstructInt: + case EOpConstructUVec2: + case EOpConstructUVec3: + case EOpConstructUVec4: + case EOpConstructUInt: + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructBool: + case EOpConstructStruct: + return true; + default: + return false; + } +} + +// +// Make sure the type of a unary operator is appropriate for its +// combination of operation and operand type. +// +// Returns false in nothing makes sense. +// +bool TIntermUnary::promote(TInfoSink &) +{ + switch (mOp) + { + case EOpLogicalNot: + if (mOperand->getBasicType() != EbtBool) + return false; + break; + case EOpNegative: + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + if (mOperand->getBasicType() == EbtBool) + return false; + break; + + // operators for built-ins are already type checked against their prototype + case EOpAny: + case EOpAll: + case EOpVectorLogicalNot: + return true; + + default: + if (mOperand->getBasicType() != EbtFloat) + return false; + } + + setType(mOperand->getType()); + mType.setQualifier(EvqTemporary); + + return true; +} + +// +// Establishes the type of the resultant operation, as well as +// makes the operator the correct one for the operands. +// +// Returns false if operator can't work on operands. +// +bool TIntermBinary::promote(TInfoSink &infoSink) +{ + // This function only handles scalars, vectors, and matrices. + if (mLeft->isArray() || mRight->isArray()) + { + infoSink.info.message(EPrefixInternalError, getLine(), + "Invalid operation for arrays"); + return false; + } + + // GLSL ES 2.0 does not support implicit type casting. + // So the basic type should always match. + if (mLeft->getBasicType() != mRight->getBasicType()) + { + return false; + } + + // + // Base assumption: just make the type the same as the left + // operand. Then only deviations from this need be coded. + // + setType(mLeft->getType()); + + // The result gets promoted to the highest precision. + TPrecision higherPrecision = GetHigherPrecision( + mLeft->getPrecision(), mRight->getPrecision()); + getTypePointer()->setPrecision(higherPrecision); + + // Binary operations results in temporary variables unless both + // operands are const. + if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst) + { + getTypePointer()->setQualifier(EvqTemporary); + } + + 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)); + break; + + // + // And and Or operate on conditionals + // + case EOpLogicalAnd: + case EOpLogicalOr: + // Both operands must be of type bool. + if (mLeft->getBasicType() != EbtBool || mRight->getBasicType() != EbtBool) + { + return false; + } + setType(TType(EbtBool, EbpUndefined)); + break; + + default: + break; + } + return true; + } + + // If we reach here, at least one of the operands is vector or matrix. + // The other operand could be a scalar, vector, or matrix. + // Can these two operands be combined? + // + TBasicType basicType = mLeft->getBasicType(); + switch (mOp) + { + case EOpMul: + if (!mLeft->isMatrix() && mRight->isMatrix()) + { + if (mLeft->isVector()) + { + mOp = EOpVectorTimesMatrix; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), 1)); + } + else + { + mOp = EOpMatrixTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), mRight->getRows())); + } + } + else if (mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mRight->isVector()) + { + mOp = EOpMatrixTimesVector; + setType(TType(basicType, higherPrecision, EvqTemporary, + mLeft->getRows(), 1)); + } + else + { + mOp = EOpMatrixTimesScalar; + } + } + else if (mLeft->isMatrix() && mRight->isMatrix()) + { + mOp = EOpMatrixTimesMatrix; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), mLeft->getRows())); + } + else if (!mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mLeft->isVector() && mRight->isVector()) + { + // leave as component product + } + else if (mLeft->isVector() || mRight->isVector()) + { + mOp = EOpVectorTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, + nominalSize, 1)); + } + } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), + "Missing elses"); + return false; + } + + if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType())) + { + return false; + } + break; + + case EOpMulAssign: + if (!mLeft->isMatrix() && mRight->isMatrix()) + { + if (mLeft->isVector()) + { + mOp = EOpVectorTimesMatrixAssign; + } + else + { + return false; + } + } + else if (mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mRight->isVector()) + { + return false; + } + else + { + mOp = EOpMatrixTimesScalarAssign; + } + } + else if (mLeft->isMatrix() && mRight->isMatrix()) + { + mOp = EOpMatrixTimesMatrixAssign; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), mLeft->getRows())); + } + else if (!mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mLeft->isVector() && mRight->isVector()) + { + // leave as component product + } + else if (mLeft->isVector() || mRight->isVector()) + { + if (!mLeft->isVector()) + return false; + mOp = EOpVectorTimesScalarAssign; + setType(TType(basicType, higherPrecision, EvqTemporary, + mLeft->getNominalSize(), 1)); + } + } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), + "Missing elses"); + return false; + } + + if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType())) + { + return false; + } + break; + + case EOpAssign: + case EOpInitialize: + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpAddAssign: + case EOpSubAssign: + case EOpDivAssign: + if ((mLeft->isMatrix() && mRight->isVector()) || + (mLeft->isVector() && mRight->isMatrix())) + { + return false; + } + + // Are the sizes compatible? + if (mLeft->getNominalSize() != mRight->getNominalSize() || + mLeft->getSecondarySize() != mRight->getSecondarySize()) + { + // If the nominal size of operands do not match: + // One of them must be scalar. + if (!mLeft->isScalar() && !mRight->isScalar()) + return false; + + // Operator cannot be of type pure assignment. + if (mOp == EOpAssign || mOp == EOpInitialize) + return false; + } + + { + const int secondarySize = std::max( + mLeft->getSecondarySize(), mRight->getSecondarySize()); + setType(TType(basicType, higherPrecision, EvqTemporary, + nominalSize, secondarySize)); + } + break; + + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if ((mLeft->getNominalSize() != mRight->getNominalSize()) || + (mLeft->getSecondarySize() != mRight->getSecondarySize())) + { + return false; + } + setType(TType(EbtBool, EbpUndefined)); + break; + + default: + return false; + } + return true; +} + +// +// The fold functions see if an operation on a constant can be done in place, +// without generating run-time code. +// +// Returns the node to keep using, which may or may not be the node passed in. +// +TIntermTyped *TIntermConstantUnion::fold( + TOperator op, TIntermTyped *constantNode, TInfoSink &infoSink) +{ + ConstantUnion *unionArray = getUnionArrayPointer(); + + if (!unionArray) + return NULL; + + size_t objectSize = getType().getObjectSize(); + + if (constantNode) + { + // binary operations + TIntermConstantUnion *node = constantNode->getAsConstantUnion(); + ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); + TType returnType = getType(); + + if (!rightUnionArray) + return NULL; + + // for a case like float f = 1.2 + vec4(2,3,4,5); + if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) + { + rightUnionArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; ++i) + { + rightUnionArray[i] = *node->getUnionArrayPointer(); + } + returnType = getType(); + } + else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) + { + // for a case like float f = vec4(2,3,4,5) + 1.2; + unionArray = new ConstantUnion[constantNode->getType().getObjectSize()]; + for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) + { + unionArray[i] = *getUnionArrayPointer(); + } + returnType = node->getType(); + objectSize = constantNode->getType().getObjectSize(); + } + + ConstantUnion *tempConstArray = NULL; + TIntermConstantUnion *tempNode; + + bool boolNodeFlag = false; + switch(op) + { + case EOpAdd: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] + rightUnionArray[i]; + break; + case EOpSub: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] - rightUnionArray[i]; + break; + + case EOpMul: + case EOpVectorTimesScalar: + case EOpMatrixTimesScalar: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] * rightUnionArray[i]; + break; + + case EOpMatrixTimesMatrix: + { + if (getType().getBasicType() != EbtFloat || + node->getBasicType() != EbtFloat) + { + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant Folding cannot be done for matrix multiply"); + return NULL; + } + + const int leftCols = getCols(); + const int leftRows = getRows(); + const int rightCols = constantNode->getType().getCols(); + const int rightRows = constantNode->getType().getRows(); + const int resultCols = rightCols; + const int resultRows = leftRows; + + tempConstArray = new ConstantUnion[resultCols*resultRows]; + for (int row = 0; row < resultRows; row++) + { + for (int column = 0; column < resultCols; column++) + { + tempConstArray[resultRows * column + row].setFConst(0.0f); + for (int i = 0; i < leftCols; i++) + { + tempConstArray[resultRows * column + row].setFConst( + tempConstArray[resultRows * column + row].getFConst() + + unionArray[i * leftRows + row].getFConst() * + rightUnionArray[column * rightRows + i].getFConst()); + } + } + } + + // update return type for matrix product + returnType.setPrimarySize(resultCols); + returnType.setSecondarySize(resultRows); + } + break; + + case EOpDiv: + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + switch (getType().getBasicType()) + { + case EbtFloat: + if (rightUnionArray[i] == 0.0f) + { + infoSink.info.message( + EPrefixWarning, getLine(), + "Divide by zero error during constant folding"); + tempConstArray[i].setFConst( + unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX); + } + else + { + tempConstArray[i].setFConst( + unionArray[i].getFConst() / + rightUnionArray[i].getFConst()); + } + break; + + case EbtInt: + if (rightUnionArray[i] == 0) + { + infoSink.info.message( + EPrefixWarning, getLine(), + "Divide by zero error during constant folding"); + tempConstArray[i].setIConst(INT_MAX); + } + else + { + tempConstArray[i].setIConst( + unionArray[i].getIConst() / + rightUnionArray[i].getIConst()); + } + break; + + case EbtUInt: + if (rightUnionArray[i] == 0) + { + infoSink.info.message( + EPrefixWarning, getLine(), + "Divide by zero error during constant folding"); + tempConstArray[i].setUConst(UINT_MAX); + } + else + { + tempConstArray[i].setUConst( + unionArray[i].getUConst() / + rightUnionArray[i].getUConst()); + } + break; + + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant folding cannot be done for \"/\""); + return NULL; + } + } + } + break; + + case EOpMatrixTimesVector: + { + if (node->getBasicType() != EbtFloat) + { + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant Folding cannot be done for matrix times vector"); + return NULL; + } + + const int matrixCols = getCols(); + const int matrixRows = getRows(); + + tempConstArray = new ConstantUnion[matrixRows]; + + for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) + { + tempConstArray[matrixRow].setFConst(0.0f); + for (int col = 0; col < matrixCols; col++) + { + tempConstArray[matrixRow].setFConst( + tempConstArray[matrixRow].getFConst() + + unionArray[col * matrixRows + matrixRow].getFConst() * + rightUnionArray[col].getFConst()); + } + } + + returnType = node->getType(); + returnType.setPrimarySize(matrixRows); + + tempNode = new TIntermConstantUnion(tempConstArray, returnType); + tempNode->setLine(getLine()); + + return tempNode; + } + + case EOpVectorTimesMatrix: + { + if (getType().getBasicType() != EbtFloat) + { + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant Folding cannot be done for vector times matrix"); + return NULL; + } + + const int matrixCols = constantNode->getType().getCols(); + const int matrixRows = constantNode->getType().getRows(); + + tempConstArray = new ConstantUnion[matrixCols]; + + for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++) + { + tempConstArray[matrixCol].setFConst(0.0f); + for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) + { + tempConstArray[matrixCol].setFConst( + tempConstArray[matrixCol].getFConst() + + unionArray[matrixRow].getFConst() * + rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst()); + } + } + + returnType.setPrimarySize(matrixCols); + } + break; + + case EOpLogicalAnd: + // this code is written for possible future use, + // will not get executed currently + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + tempConstArray[i] = unionArray[i] && rightUnionArray[i]; + } + } + break; + + case EOpLogicalOr: + // this code is written for possible future use, + // will not get executed currently + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + tempConstArray[i] = unionArray[i] || rightUnionArray[i]; + } + } + break; + + case EOpLogicalXor: + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + switch (getType().getBasicType()) + { + case EbtBool: + tempConstArray[i].setBConst( + unionArray[i] == rightUnionArray[i] ? false : true); + break; + default: + UNREACHABLE(); + break; + } + } + } + break; + + case EOpLessThan: + ASSERT(objectSize == 1); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(*unionArray < *rightUnionArray); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + + case EOpGreaterThan: + ASSERT(objectSize == 1); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(*unionArray > *rightUnionArray); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + + case EOpLessThanEqual: + { + ASSERT(objectSize == 1); + ConstantUnion constant; + constant.setBConst(*unionArray > *rightUnionArray); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(!constant.getBConst()); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + } + + case EOpGreaterThanEqual: + { + ASSERT(objectSize == 1); + ConstantUnion constant; + constant.setBConst(*unionArray < *rightUnionArray); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(!constant.getBConst()); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + } + + case EOpEqual: + if (getType().getBasicType() == EbtStruct) + { + if (!CompareStructure(node->getType(), + node->getUnionArrayPointer(), + unionArray)) + { + boolNodeFlag = true; + } + } + else + { + for (size_t i = 0; i < objectSize; i++) + { + if (unionArray[i] != rightUnionArray[i]) + { + boolNodeFlag = true; + break; // break out of for loop + } + } + } + + tempConstArray = new ConstantUnion[1]; + if (!boolNodeFlag) + { + tempConstArray->setBConst(true); + } + else + { + tempConstArray->setBConst(false); + } + + tempNode = new TIntermConstantUnion( + tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); + tempNode->setLine(getLine()); + + return tempNode; + + case EOpNotEqual: + if (getType().getBasicType() == EbtStruct) + { + if (CompareStructure(node->getType(), + node->getUnionArrayPointer(), + unionArray)) + { + boolNodeFlag = true; + } + } + else + { + for (size_t i = 0; i < objectSize; i++) + { + if (unionArray[i] == rightUnionArray[i]) + { + boolNodeFlag = true; + break; // break out of for loop + } + } + } + + tempConstArray = new ConstantUnion[1]; + if (!boolNodeFlag) + { + tempConstArray->setBConst(true); + } + else + { + tempConstArray->setBConst(false); + } + + tempNode = new TIntermConstantUnion( + tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); + tempNode->setLine(getLine()); + + return tempNode; + + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Invalid operator for constant folding"); + return NULL; + } + tempNode = new TIntermConstantUnion(tempConstArray, returnType); + tempNode->setLine(getLine()); + + return tempNode; + } + else + { + // + // Do unary operations + // + TIntermConstantUnion *newNode = 0; + ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + switch(op) + { + case EOpNegative: + switch (getType().getBasicType()) + { + case EbtFloat: + tempConstArray[i].setFConst(-unionArray[i].getFConst()); + break; + case EbtInt: + tempConstArray[i].setIConst(-unionArray[i].getIConst()); + break; + case EbtUInt: + tempConstArray[i].setUConst(static_cast( + -static_cast(unionArray[i].getUConst()))); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return NULL; + } + break; + + case EOpLogicalNot: + // this code is written for possible future use, + // will not get executed currently + switch (getType().getBasicType()) + { + case EbtBool: + tempConstArray[i].setBConst(!unionArray[i].getBConst()); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return NULL; + } + break; + + default: + return NULL; + } + } + newNode = new TIntermConstantUnion(tempConstArray, getType()); + newNode->setLine(getLine()); + return newNode; + } +} + +// static +TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction) +{ + if (hashFunction == NULL || name.empty()) + return name; + khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); + TStringStream stream; + stream << HASHED_NAME_PREFIX << std::hex << number; + TString hashedName = stream.str(); + return hashedName; +} diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.h b/src/3rdparty/angle/src/compiler/translator/IntermNode.h new file mode 100644 index 0000000000..ec440da010 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.h @@ -0,0 +1,772 @@ +// +// 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_INTERMEDIATE_H_ +#define COMPILER_TRANSLATOR_INTERMEDIATE_H_ + +#include "GLSLANG/ShaderLang.h" + +#include +#include + +#include "compiler/translator/Common.h" +#include "compiler/translator/Types.h" +#include "compiler/translator/ConstantUnion.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 + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpFunctionCall, + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function + + EOpDeclaration, + EOpInvariantDeclaration, // Specialized declarations for attributing invariance + EOpPrototype, + + // + // Unary operators + // + + EOpNegative, + EOpLogicalNot, + EOpVectorLogicalNot, + + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, + + // + // binary operations + // + + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpEqual, + EOpNotEqual, + EOpVectorEqual, + EOpVectorNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + EOpComma, + + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, + + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, + + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + EOpIndexDirectInterfaceBlock, + + EOpVectorSwizzle, + + // + // Built-in functions potentially mapped to operators + // + + EOpRadians, + EOpDegrees, + EOpSin, + EOpCos, + EOpTan, + EOpAsin, + EOpAcos, + EOpAtan, + + EOpPow, + EOpExp, + EOpLog, + EOpExp2, + EOpLog2, + EOpSqrt, + EOpInverseSqrt, + + EOpAbs, + EOpSign, + EOpFloor, + EOpCeil, + EOpFract, + EOpMod, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothStep, + + 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 + + EOpMatrixTimesMatrix, + + EOpAny, + EOpAll, + + // + // Branch + // + + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, + + // + // Constructors + // + + EOpConstructInt, + EOpConstructUInt, + EOpConstructBool, + EOpConstructFloat, + EOpConstructVec2, + EOpConstructVec3, + EOpConstructVec4, + EOpConstructBVec2, + EOpConstructBVec3, + EOpConstructBVec4, + EOpConstructIVec2, + EOpConstructIVec3, + EOpConstructIVec4, + EOpConstructUVec2, + EOpConstructUVec3, + EOpConstructUVec4, + EOpConstructMat2, + EOpConstructMat3, + EOpConstructMat4, + EOpConstructStruct, + + // + // moves + // + + EOpAssign, + EOpInitialize, + EOpAddAssign, + EOpSubAssign, + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + EOpDivAssign +}; + +class TIntermTraverser; +class TIntermAggregate; +class TIntermBinary; +class TIntermUnary; +class TIntermConstantUnion; +class TIntermSelection; +class TIntermTyped; +class TIntermSymbol; +class TIntermLoop; +class TInfoSink; +class TIntermRaw; + +// +// Base class for the tree nodes +// +class TIntermNode +{ + 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 TIntermAggregate *getAsAggregate() { return 0; } + virtual TIntermBinary *getAsBinaryNode() { return 0; } + virtual TIntermUnary *getAsUnaryNode() { return 0; } + virtual TIntermSelection *getAsSelectionNode() { return 0; } + virtual TIntermSymbol *getAsSymbolNode() { return 0; } + virtual TIntermLoop *getAsLoopNode() { return 0; } + virtual TIntermRaw *getAsRawNode() { 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; + + // For traversing a tree in no particular order, but using + // heap memory. + virtual void enqueueChildren(std::queue *nodeQueue) const = 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 *getAsTyped() { return this; } + + virtual bool hasSideEffects() const = 0; + + void setType(const TType &t) { mType = 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(); } + 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(); } + const char *getQualifierString() const { return mType.getQualifierString(); } + TString getCompleteString() const { return mType.getCompleteString(); } + + int getArraySize() const { return mType.getArraySize(); } + + protected: + TType mType; +}; + +// +// 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, + TIntermNode *body) + : mType(type), + mInit(init), + mCond(cond), + mExpr(expr), + mBody(body), + mUnrollFlag(false) { } + + virtual TIntermLoop *getAsLoopNode() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + TLoopType getType() const { return mType; } + TIntermNode *getInit() { return mInit; } + TIntermTyped *getCondition() { return mCond; } + TIntermTyped *getExpression() { return mExpr; } + TIntermNode *getBody() { return mBody; } + + void setUnrollFlag(bool flag) { mUnrollFlag = flag; } + bool getUnrollFlag() const { return mUnrollFlag; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + + protected: + TLoopType mType; + TIntermNode *mInit; // for-loop initialization + TIntermTyped *mCond; // loop exit condition + TIntermTyped *mExpr; // for-loop expression + TIntermNode *mBody; // loop body + + bool mUnrollFlag; // Whether the loop should be unrolled or not. +}; + +// +// Handle break, continue, return, and kill. +// +class TIntermBranch : public TIntermNode +{ + public: + TIntermBranch(TOperator op, TIntermTyped *e) + : mFlowOp(op), + mExpression(e) { } + + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + TOperator getFlowOp() { return mFlowOp; } + TIntermTyped* getExpression() { return mExpression; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + +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(int id, const TString &symbol, const TType &type) + : TIntermTyped(type), + mId(id) + { + mSymbol = symbol; + } + + virtual bool hasSideEffects() const { return false; } + + int getId() const { return mId; } + const TString &getSymbol() const { return mSymbol; } + + void setId(int newId) { mId = newId; } + + virtual void traverse(TIntermTraverser *); + virtual TIntermSymbol *getAsSymbolNode() { return this; } + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } + + virtual void enqueueChildren(std::queue *nodeQueue) const {} + + protected: + int mId; + TString mSymbol; +}; + +// 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) { } + + virtual bool hasSideEffects() const { return false; } + + TString getRawText() const { return mRawText; } + + virtual void traverse(TIntermTraverser *); + + virtual TIntermRaw *getAsRawNode() { return this; } + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } + virtual void enqueueChildren(std::queue *nodeQueue) const {} + + protected: + TString mRawText; +}; + +class TIntermConstantUnion : public TIntermTyped +{ + public: + TIntermConstantUnion(ConstantUnion *unionPointer, const TType &type) + : TIntermTyped(type), + mUnionArrayPointer(unionPointer) { } + + virtual bool hasSideEffects() const { return false; } + + ConstantUnion *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; + } + + virtual TIntermConstantUnion *getAsConstantUnion() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } + + TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &); + + virtual void enqueueChildren(std::queue *nodeQueue) const {} + + protected: + ConstantUnion *mUnionArrayPointer; +}; + +// +// Intermediate class for node types that hold operators. +// +class TIntermOperator : public TIntermTyped +{ + public: + TOperator getOp() const { return mOp; } + void setOp(TOperator op) { mOp = op; } + + bool isAssignment() const; + bool isConstructor() const; + + virtual bool hasSideEffects() const { return isAssignment(); } + + protected: + TIntermOperator(TOperator op) + : TIntermTyped(TType(EbtFloat, EbpUndefined)), + mOp(op) {} + TIntermOperator(TOperator op, const TType &type) + : TIntermTyped(type), + mOp(op) {} + + TOperator mOp; +}; + +// +// Nodes for all the basic binary math operators. +// +class TIntermBinary : public TIntermOperator +{ + public: + TIntermBinary(TOperator op) + : TIntermOperator(op), + mAddIndexClamp(false) {} + + virtual TIntermBinary *getAsBinaryNode() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + virtual bool hasSideEffects() const + { + return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects(); + } + + void setLeft(TIntermTyped *node) { mLeft = node; } + void setRight(TIntermTyped *node) { mRight = node; } + TIntermTyped *getLeft() const { return mLeft; } + TIntermTyped *getRight() const { return mRight; } + bool promote(TInfoSink &); + + void setAddIndexClamp() { mAddIndexClamp = true; } + bool getAddIndexClamp() { return mAddIndexClamp; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + + protected: + TIntermTyped* mLeft; + TIntermTyped* mRight; + + // If set to true, wrap any EOpIndexIndirect with a clamp to bounds. + bool mAddIndexClamp; +}; + +// +// Nodes for unary math operators. +// +class TIntermUnary : public TIntermOperator +{ + public: + TIntermUnary(TOperator op, const TType &type) + : TIntermOperator(op, type), + mOperand(NULL), + mUseEmulatedFunction(false) {} + TIntermUnary(TOperator op) + : TIntermOperator(op), + mOperand(NULL), + mUseEmulatedFunction(false) {} + + virtual void traverse(TIntermTraverser *); + virtual TIntermUnary *getAsUnaryNode() { return this; } + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + virtual bool hasSideEffects() const + { + return isAssignment() || mOperand->hasSideEffects(); + } + + void setOperand(TIntermTyped *operand) { mOperand = operand; } + TIntermTyped *getOperand() { return mOperand; } + bool promote(TInfoSink &); + + void setUseEmulatedFunction() { mUseEmulatedFunction = true; } + bool getUseEmulatedFunction() { return mUseEmulatedFunction; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + + protected: + TIntermTyped *mOperand; + + // If set to true, replace the built-in function call with an emulated one + // to work around driver bugs. + bool mUseEmulatedFunction; +}; + +typedef TVector TIntermSequence; +typedef TVector TQualifierList; + +// +// Nodes that operate on an arbitrary sized set of children. +// +class TIntermAggregate : public TIntermOperator +{ + public: + TIntermAggregate() + : TIntermOperator(EOpNull), + mUserDefined(false), + mUseEmulatedFunction(false) { } + TIntermAggregate(TOperator op) + : TIntermOperator(op), + mUseEmulatedFunction(false) { } + ~TIntermAggregate() { } + + virtual TIntermAggregate *getAsAggregate() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + // Conservatively assume function calls and other aggregate operators have side-effects + virtual bool hasSideEffects() const { return true; } + + TIntermSequence *getSequence() { return &mSequence; } + + void setName(const TString &name) { mName = name; } + const TString &getName() const { return mName; } + + void setUserDefined() { mUserDefined = true; } + bool isUserDefined() const { return mUserDefined; } + + void setOptimize(bool optimize) { mOptimize = optimize; } + bool getOptimize() const { return mOptimize; } + void setDebug(bool debug) { mDebug = debug; } + bool getDebug() const { return mDebug; } + + void setUseEmulatedFunction() { mUseEmulatedFunction = true; } + bool getUseEmulatedFunction() { return mUseEmulatedFunction; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + + protected: + TIntermAggregate(const TIntermAggregate &); // disallow copy constructor + TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator + TIntermSequence mSequence; + TString mName; + bool mUserDefined; // used for user defined function names + + bool mOptimize; + bool mDebug; + + // If set to true, replace the built-in function call with an emulated one + // to work around driver bugs. + bool mUseEmulatedFunction; +}; + +// +// For if tests. Simplified since there is no switch statement. +// +class TIntermSelection : public TIntermTyped +{ + public: + TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB) + : TIntermTyped(TType(EbtVoid, EbpUndefined)), + mCondition(cond), + mTrueBlock(trueB), + mFalseBlock(falseB) {} + TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB, + const TType &type) + : TIntermTyped(type), + mCondition(cond), + mTrueBlock(trueB), + mFalseBlock(falseB) {} + + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + // Conservatively assume selections have side-effects + virtual bool hasSideEffects() const { return true; } + + bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } + TIntermNode *getCondition() const { return mCondition; } + TIntermNode *getTrueBlock() const { return mTrueBlock; } + TIntermNode *getFalseBlock() const { return mFalseBlock; } + TIntermSelection *getAsSelectionNode() { return this; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + +protected: + TIntermTyped *mCondition; + TIntermNode *mTrueBlock; + TIntermNode *mFalseBlock; +}; + +enum Visit +{ + PreVisit, + InVisit, + PostVisit +}; + +// +// For traversing the tree. User should derive from this, +// put their traversal specific data in it, and then pass +// it to a Traverse method. +// +// 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 +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + // TODO(zmo): remove default values. + TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, + bool rightToLeft = false) + : preVisit(preVisit), + inVisit(inVisit), + postVisit(postVisit), + rightToLeft(rightToLeft), + mDepth(0), + mMaxDepth(0) {} + virtual ~TIntermTraverser() {} + + virtual void visitSymbol(TIntermSymbol *) {} + virtual void visitRaw(TIntermRaw *) {} + virtual void visitConstantUnion(TIntermConstantUnion *) {} + virtual bool visitBinary(Visit, TIntermBinary *) { return true; } + virtual bool visitUnary(Visit, TIntermUnary *) { return true; } + virtual bool visitSelection(Visit, TIntermSelection *) { return true; } + virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; } + virtual bool visitLoop(Visit, TIntermLoop *) { return true; } + virtual bool visitBranch(Visit, TIntermBranch *) { return true; } + + int getMaxDepth() const { return mMaxDepth; } + + void incrementDepth(TIntermNode *current) + { + mDepth++; + mMaxDepth = std::max(mMaxDepth, mDepth); + mPath.push_back(current); + } + + void decrementDepth() + { + mDepth--; + mPath.pop_back(); + } + + TIntermNode *getParentNode() + { + return mPath.size() == 0 ? NULL : mPath.back(); + } + + // Return the original name if hash function pointer is NULL; + // otherwise return the hashed name. + static TString hash(const TString& name, ShHashFunction64 hashFunction); + + const bool preVisit; + const bool inVisit; + const bool postVisit; + const bool rightToLeft; + + protected: + int mDepth; + int mMaxDepth; + + // All the nodes from root to the current node's parent during traversing. + TVector mPath; +}; + +// +// For traversing the tree, and computing max depth. +// Takes a maximum depth limit to prevent stack overflow. +// +class TMaxDepthTraverser : public TIntermTraverser +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + TMaxDepthTraverser(int depthLimit) + : TIntermTraverser(true, true, false, false), + mDepthLimit(depthLimit) { } + + virtual bool visitBinary(Visit, TIntermBinary *) { return depthCheck(); } + virtual bool visitUnary(Visit, TIntermUnary *) { return depthCheck(); } + virtual bool visitSelection(Visit, TIntermSelection *) { return depthCheck(); } + virtual bool visitAggregate(Visit, TIntermAggregate *) { return depthCheck(); } + virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); } + virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); } + +protected: + bool depthCheck() const { return mMaxDepth < mDepthLimit; } + + int mDepthLimit; +}; + +#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp index 48d2013cc5..72b2033fb3 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp +++ b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // // Traverse the intermediate representation tree, and diff --git a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp index fa0c9f7748..ef4f83307c 100644 --- a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp @@ -12,122 +12,10 @@ #include #include -#include "compiler/translator/HashNames.h" -#include "compiler/translator/localintermediate.h" -#include "compiler/translator/QualifierAlive.h" +#include "compiler/translator/Intermediate.h" #include "compiler/translator/RemoveTree.h" #include "compiler/translator/SymbolTable.h" -namespace -{ - -TPrecision GetHigherPrecision(TPrecision left, TPrecision right) -{ - return left > right ? left : right; -} - -bool ValidateMultiplication(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: - case EOpVectorTimesScalarAssign: - return true; - case EOpVectorTimesMatrix: - return left.getNominalSize() == right.getRows(); - case EOpVectorTimesMatrixAssign: - return left.getNominalSize() == right.getRows() && - left.getNominalSize() == right.getCols(); - case EOpMatrixTimesVector: - return left.getCols() == right.getNominalSize(); - case EOpMatrixTimesScalar: - case EOpMatrixTimesScalarAssign: - return true; - case EOpMatrixTimesMatrix: - return left.getCols() == right.getRows(); - case EOpMatrixTimesMatrixAssign: - return left.getCols() == right.getCols() && - left.getRows() == right.getRows(); - - default: - UNREACHABLE(); - return false; - } -} - -bool CompareStructure(const TType& leftNodeType, - ConstantUnion *rightUnionArray, - ConstantUnion *leftUnionArray); - -bool CompareStruct(const TType &leftNodeType, - ConstantUnion *rightUnionArray, - ConstantUnion *leftUnionArray) -{ - const TFieldList &fields = leftNodeType.getStruct()->fields(); - - size_t structSize = fields.size(); - size_t index = 0; - - for (size_t j = 0; j < structSize; j++) - { - size_t size = fields[j]->type()->getObjectSize(); - for (size_t i = 0; i < size; i++) - { - if (fields[j]->type()->getBasicType() == EbtStruct) - { - if (!CompareStructure(*fields[j]->type(), - &rightUnionArray[index], - &leftUnionArray[index])) - { - return false; - } - } - else - { - if (leftUnionArray[index] != rightUnionArray[index]) - return false; - index++; - } - } - } - return true; -} - -bool CompareStructure(const TType &leftNodeType, - ConstantUnion *rightUnionArray, - ConstantUnion *leftUnionArray) -{ - if (leftNodeType.isArray()) - { - TType typeWithoutArrayness = leftNodeType; - typeWithoutArrayness.clearArrayness(); - - size_t arraySize = leftNodeType.getArraySize(); - - for (size_t i = 0; i < arraySize; ++i) - { - size_t offset = typeWithoutArrayness.getObjectSize() * i; - if (!CompareStruct(typeWithoutArrayness, - &rightUnionArray[offset], - &leftUnionArray[offset])) - { - return false; - } - } - } - else - { - return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); - } - return true; -} - -} // namespace anonymous - //////////////////////////////////////////////////////////////////////////// // // First set of functions are to help build the intermediate representation. @@ -630,982 +518,3 @@ void TIntermediate::remove(TIntermNode *root) if (root) RemoveAllTreeNodes(root); } - -//////////////////////////////////////////////////////////////// -// -// Member functions of the nodes used for building the tree. -// -//////////////////////////////////////////////////////////////// - -#define REPLACE_IF_IS(node, type, original, replacement) \ - if (node == original) { \ - node = static_cast(replacement); \ - return true; \ - } - -bool TIntermLoop::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - 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, TIntermNode, original, replacement); - return false; -} - -void TIntermLoop::enqueueChildren(std::queue *nodeQueue) const -{ - if (mInit) - { - nodeQueue->push(mInit); - } - if (mCond) - { - nodeQueue->push(mCond); - } - if (mExpr) - { - nodeQueue->push(mExpr); - } - if (mBody) - { - nodeQueue->push(mBody); - } -} - -bool TIntermBranch::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement); - return false; -} - -void TIntermBranch::enqueueChildren(std::queue *nodeQueue) const -{ - if (mExpression) - { - nodeQueue->push(mExpression); - } -} - -bool TIntermBinary::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement); - REPLACE_IF_IS(mRight, TIntermTyped, original, replacement); - return false; -} - -void TIntermBinary::enqueueChildren(std::queue *nodeQueue) const -{ - if (mLeft) - { - nodeQueue->push(mLeft); - } - if (mRight) - { - nodeQueue->push(mRight); - } -} - -bool TIntermUnary::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); - return false; -} - -void TIntermUnary::enqueueChildren(std::queue *nodeQueue) const -{ - if (mOperand) - { - nodeQueue->push(mOperand); - } -} - -bool TIntermAggregate::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - for (size_t ii = 0; ii < mSequence.size(); ++ii) - { - REPLACE_IF_IS(mSequence[ii], TIntermNode, original, replacement); - } - return false; -} - -void TIntermAggregate::enqueueChildren(std::queue *nodeQueue) const -{ - for (size_t childIndex = 0; childIndex < mSequence.size(); childIndex++) - { - nodeQueue->push(mSequence[childIndex]); - } -} - -bool TIntermSelection::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); - REPLACE_IF_IS(mTrueBlock, TIntermNode, original, replacement); - REPLACE_IF_IS(mFalseBlock, TIntermNode, original, replacement); - return false; -} - -void TIntermSelection::enqueueChildren(std::queue *nodeQueue) const -{ - if (mCondition) - { - nodeQueue->push(mCondition); - } - if (mTrueBlock) - { - nodeQueue->push(mTrueBlock); - } - if (mFalseBlock) - { - nodeQueue->push(mFalseBlock); - } -} - -// -// Say whether or not an operation node changes the value of a variable. -// -bool TIntermOperator::isAssignment() const -{ - switch (mOp) - { - 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: - return true; - default: - return false; - } -} - -// -// returns true if the operator is for one of the constructors -// -bool TIntermOperator::isConstructor() const -{ - switch (mOp) - { - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructMat2: - case EOpConstructMat3: - case EOpConstructMat4: - case EOpConstructFloat: - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructInt: - case EOpConstructUVec2: - case EOpConstructUVec3: - case EOpConstructUVec4: - case EOpConstructUInt: - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructBool: - case EOpConstructStruct: - return true; - default: - return false; - } -} - -// -// Make sure the type of a unary operator is appropriate for its -// combination of operation and operand type. -// -// Returns false in nothing makes sense. -// -bool TIntermUnary::promote(TInfoSink &) -{ - switch (mOp) - { - case EOpLogicalNot: - if (mOperand->getBasicType() != EbtBool) - return false; - break; - case EOpNegative: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - if (mOperand->getBasicType() == EbtBool) - return false; - break; - - // operators for built-ins are already type checked against their prototype - case EOpAny: - case EOpAll: - case EOpVectorLogicalNot: - return true; - - default: - if (mOperand->getBasicType() != EbtFloat) - return false; - } - - setType(mOperand->getType()); - mType.setQualifier(EvqTemporary); - - return true; -} - -// -// Establishes the type of the resultant operation, as well as -// makes the operator the correct one for the operands. -// -// Returns false if operator can't work on operands. -// -bool TIntermBinary::promote(TInfoSink &infoSink) -{ - // This function only handles scalars, vectors, and matrices. - if (mLeft->isArray() || mRight->isArray()) - { - infoSink.info.message(EPrefixInternalError, getLine(), - "Invalid operation for arrays"); - return false; - } - - // GLSL ES 2.0 does not support implicit type casting. - // So the basic type should always match. - if (mLeft->getBasicType() != mRight->getBasicType()) - { - return false; - } - - // - // Base assumption: just make the type the same as the left - // operand. Then only deviations from this need be coded. - // - setType(mLeft->getType()); - - // The result gets promoted to the highest precision. - TPrecision higherPrecision = GetHigherPrecision( - mLeft->getPrecision(), mRight->getPrecision()); - getTypePointer()->setPrecision(higherPrecision); - - // Binary operations results in temporary variables unless both - // operands are const. - if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst) - { - getTypePointer()->setQualifier(EvqTemporary); - } - - 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)); - break; - - // - // And and Or operate on conditionals - // - case EOpLogicalAnd: - case EOpLogicalOr: - // Both operands must be of type bool. - if (mLeft->getBasicType() != EbtBool || mRight->getBasicType() != EbtBool) - { - return false; - } - setType(TType(EbtBool, EbpUndefined)); - break; - - default: - break; - } - return true; - } - - // If we reach here, at least one of the operands is vector or matrix. - // The other operand could be a scalar, vector, or matrix. - // Can these two operands be combined? - // - TBasicType basicType = mLeft->getBasicType(); - switch (mOp) - { - case EOpMul: - if (!mLeft->isMatrix() && mRight->isMatrix()) - { - if (mLeft->isVector()) - { - mOp = EOpVectorTimesMatrix; - setType(TType(basicType, higherPrecision, EvqTemporary, - mRight->getCols(), 1)); - } - else - { - mOp = EOpMatrixTimesScalar; - setType(TType(basicType, higherPrecision, EvqTemporary, - mRight->getCols(), mRight->getRows())); - } - } - else if (mLeft->isMatrix() && !mRight->isMatrix()) - { - if (mRight->isVector()) - { - mOp = EOpMatrixTimesVector; - setType(TType(basicType, higherPrecision, EvqTemporary, - mLeft->getRows(), 1)); - } - else - { - mOp = EOpMatrixTimesScalar; - } - } - else if (mLeft->isMatrix() && mRight->isMatrix()) - { - mOp = EOpMatrixTimesMatrix; - setType(TType(basicType, higherPrecision, EvqTemporary, - mRight->getCols(), mLeft->getRows())); - } - else if (!mLeft->isMatrix() && !mRight->isMatrix()) - { - if (mLeft->isVector() && mRight->isVector()) - { - // leave as component product - } - else if (mLeft->isVector() || mRight->isVector()) - { - mOp = EOpVectorTimesScalar; - setType(TType(basicType, higherPrecision, EvqTemporary, - nominalSize, 1)); - } - } - else - { - infoSink.info.message(EPrefixInternalError, getLine(), - "Missing elses"); - return false; - } - - if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType())) - { - return false; - } - break; - - case EOpMulAssign: - if (!mLeft->isMatrix() && mRight->isMatrix()) - { - if (mLeft->isVector()) - { - mOp = EOpVectorTimesMatrixAssign; - } - else - { - return false; - } - } - else if (mLeft->isMatrix() && !mRight->isMatrix()) - { - if (mRight->isVector()) - { - return false; - } - else - { - mOp = EOpMatrixTimesScalarAssign; - } - } - else if (mLeft->isMatrix() && mRight->isMatrix()) - { - mOp = EOpMatrixTimesMatrixAssign; - setType(TType(basicType, higherPrecision, EvqTemporary, - mRight->getCols(), mLeft->getRows())); - } - else if (!mLeft->isMatrix() && !mRight->isMatrix()) - { - if (mLeft->isVector() && mRight->isVector()) - { - // leave as component product - } - else if (mLeft->isVector() || mRight->isVector()) - { - if (!mLeft->isVector()) - return false; - mOp = EOpVectorTimesScalarAssign; - setType(TType(basicType, higherPrecision, EvqTemporary, - mLeft->getNominalSize(), 1)); - } - } - else - { - infoSink.info.message(EPrefixInternalError, getLine(), - "Missing elses"); - return false; - } - - if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType())) - { - return false; - } - break; - - case EOpAssign: - case EOpInitialize: - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - if ((mLeft->isMatrix() && mRight->isVector()) || - (mLeft->isVector() && mRight->isMatrix())) - { - return false; - } - - // Are the sizes compatible? - if (mLeft->getNominalSize() != mRight->getNominalSize() || - mLeft->getSecondarySize() != mRight->getSecondarySize()) - { - // If the nominal size of operands do not match: - // One of them must be scalar. - if (!mLeft->isScalar() && !mRight->isScalar()) - return false; - - // Operator cannot be of type pure assignment. - if (mOp == EOpAssign || mOp == EOpInitialize) - return false; - } - - { - const int secondarySize = std::max( - mLeft->getSecondarySize(), mRight->getSecondarySize()); - setType(TType(basicType, higherPrecision, EvqTemporary, - nominalSize, secondarySize)); - } - break; - - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if ((mLeft->getNominalSize() != mRight->getNominalSize()) || - (mLeft->getSecondarySize() != mRight->getSecondarySize())) - { - return false; - } - setType(TType(EbtBool, EbpUndefined)); - break; - - default: - return false; - } - return true; -} - -// -// The fold functions see if an operation on a constant can be done in place, -// without generating run-time code. -// -// Returns the node to keep using, which may or may not be the node passed in. -// -TIntermTyped *TIntermConstantUnion::fold( - TOperator op, TIntermTyped *constantNode, TInfoSink &infoSink) -{ - ConstantUnion *unionArray = getUnionArrayPointer(); - - if (!unionArray) - return NULL; - - size_t objectSize = getType().getObjectSize(); - - if (constantNode) - { - // binary operations - TIntermConstantUnion *node = constantNode->getAsConstantUnion(); - ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - TType returnType = getType(); - - if (!rightUnionArray) - return NULL; - - // for a case like float f = 1.2 + vec4(2,3,4,5); - if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) - { - rightUnionArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; ++i) - { - rightUnionArray[i] = *node->getUnionArrayPointer(); - } - returnType = getType(); - } - else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) - { - // for a case like float f = vec4(2,3,4,5) + 1.2; - unionArray = new ConstantUnion[constantNode->getType().getObjectSize()]; - for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) - { - unionArray[i] = *getUnionArrayPointer(); - } - returnType = node->getType(); - objectSize = constantNode->getType().getObjectSize(); - } - - ConstantUnion *tempConstArray = NULL; - TIntermConstantUnion *tempNode; - - bool boolNodeFlag = false; - switch(op) - { - case EOpAdd: - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] + rightUnionArray[i]; - break; - case EOpSub: - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] - rightUnionArray[i]; - break; - - case EOpMul: - case EOpVectorTimesScalar: - case EOpMatrixTimesScalar: - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] * rightUnionArray[i]; - break; - - case EOpMatrixTimesMatrix: - { - if (getType().getBasicType() != EbtFloat || - node->getBasicType() != EbtFloat) - { - infoSink.info.message( - EPrefixInternalError, getLine(), - "Constant Folding cannot be done for matrix multiply"); - return NULL; - } - - const int leftCols = getCols(); - const int leftRows = getRows(); - const int rightCols = constantNode->getType().getCols(); - const int rightRows = constantNode->getType().getRows(); - const int resultCols = rightCols; - const int resultRows = leftRows; - - tempConstArray = new ConstantUnion[resultCols*resultRows]; - for (int row = 0; row < resultRows; row++) - { - for (int column = 0; column < resultCols; column++) - { - tempConstArray[resultRows * column + row].setFConst(0.0f); - for (int i = 0; i < leftCols; i++) - { - tempConstArray[resultRows * column + row].setFConst( - tempConstArray[resultRows * column + row].getFConst() + - unionArray[i * leftRows + row].getFConst() * - rightUnionArray[column * rightRows + i].getFConst()); - } - } - } - - // update return type for matrix product - returnType.setPrimarySize(resultCols); - returnType.setSecondarySize(resultRows); - } - break; - - case EOpDiv: - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - switch (getType().getBasicType()) - { - case EbtFloat: - if (rightUnionArray[i] == 0.0f) - { - infoSink.info.message( - EPrefixWarning, getLine(), - "Divide by zero error during constant folding"); - tempConstArray[i].setFConst( - unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX); - } - else - { - tempConstArray[i].setFConst( - unionArray[i].getFConst() / - rightUnionArray[i].getFConst()); - } - break; - - case EbtInt: - if (rightUnionArray[i] == 0) - { - infoSink.info.message( - EPrefixWarning, getLine(), - "Divide by zero error during constant folding"); - tempConstArray[i].setIConst(INT_MAX); - } - else - { - tempConstArray[i].setIConst( - unionArray[i].getIConst() / - rightUnionArray[i].getIConst()); - } - break; - - case EbtUInt: - if (rightUnionArray[i] == 0) - { - infoSink.info.message( - EPrefixWarning, getLine(), - "Divide by zero error during constant folding"); - tempConstArray[i].setUConst(UINT_MAX); - } - else - { - tempConstArray[i].setUConst( - unionArray[i].getUConst() / - rightUnionArray[i].getUConst()); - } - break; - - default: - infoSink.info.message( - EPrefixInternalError, getLine(), - "Constant folding cannot be done for \"/\""); - return NULL; - } - } - } - break; - - case EOpMatrixTimesVector: - { - if (node->getBasicType() != EbtFloat) - { - infoSink.info.message( - EPrefixInternalError, getLine(), - "Constant Folding cannot be done for matrix times vector"); - return NULL; - } - - const int matrixCols = getCols(); - const int matrixRows = getRows(); - - tempConstArray = new ConstantUnion[matrixRows]; - - for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) - { - tempConstArray[matrixRow].setFConst(0.0f); - for (int col = 0; col < matrixCols; col++) - { - tempConstArray[matrixRow].setFConst( - tempConstArray[matrixRow].getFConst() + - unionArray[col * matrixRows + matrixRow].getFConst() * - rightUnionArray[col].getFConst()); - } - } - - returnType = node->getType(); - returnType.setPrimarySize(matrixRows); - - tempNode = new TIntermConstantUnion(tempConstArray, returnType); - tempNode->setLine(getLine()); - - return tempNode; - } - - case EOpVectorTimesMatrix: - { - if (getType().getBasicType() != EbtFloat) - { - infoSink.info.message( - EPrefixInternalError, getLine(), - "Constant Folding cannot be done for vector times matrix"); - return NULL; - } - - const int matrixCols = constantNode->getType().getCols(); - const int matrixRows = constantNode->getType().getRows(); - - tempConstArray = new ConstantUnion[matrixCols]; - - for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++) - { - tempConstArray[matrixCol].setFConst(0.0f); - for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) - { - tempConstArray[matrixCol].setFConst( - tempConstArray[matrixCol].getFConst() + - unionArray[matrixRow].getFConst() * - rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst()); - } - } - - returnType.setPrimarySize(matrixCols); - } - break; - - case EOpLogicalAnd: - // this code is written for possible future use, - // will not get executed currently - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - tempConstArray[i] = unionArray[i] && rightUnionArray[i]; - } - } - break; - - case EOpLogicalOr: - // this code is written for possible future use, - // will not get executed currently - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - tempConstArray[i] = unionArray[i] || rightUnionArray[i]; - } - } - break; - - case EOpLogicalXor: - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - switch (getType().getBasicType()) - { - case EbtBool: - tempConstArray[i].setBConst( - unionArray[i] == rightUnionArray[i] ? false : true); - break; - default: - UNREACHABLE(); - break; - } - } - } - break; - - case EOpLessThan: - ASSERT(objectSize == 1); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(*unionArray < *rightUnionArray); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - - case EOpGreaterThan: - ASSERT(objectSize == 1); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(*unionArray > *rightUnionArray); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - - case EOpLessThanEqual: - { - ASSERT(objectSize == 1); - ConstantUnion constant; - constant.setBConst(*unionArray > *rightUnionArray); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(!constant.getBConst()); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - } - - case EOpGreaterThanEqual: - { - ASSERT(objectSize == 1); - ConstantUnion constant; - constant.setBConst(*unionArray < *rightUnionArray); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(!constant.getBConst()); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - } - - case EOpEqual: - if (getType().getBasicType() == EbtStruct) - { - if (!CompareStructure(node->getType(), - node->getUnionArrayPointer(), - unionArray)) - { - boolNodeFlag = true; - } - } - else - { - for (size_t i = 0; i < objectSize; i++) - { - if (unionArray[i] != rightUnionArray[i]) - { - boolNodeFlag = true; - break; // break out of for loop - } - } - } - - tempConstArray = new ConstantUnion[1]; - if (!boolNodeFlag) - { - tempConstArray->setBConst(true); - } - else - { - tempConstArray->setBConst(false); - } - - tempNode = new TIntermConstantUnion( - tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); - tempNode->setLine(getLine()); - - return tempNode; - - case EOpNotEqual: - if (getType().getBasicType() == EbtStruct) - { - if (CompareStructure(node->getType(), - node->getUnionArrayPointer(), - unionArray)) - { - boolNodeFlag = true; - } - } - else - { - for (size_t i = 0; i < objectSize; i++) - { - if (unionArray[i] == rightUnionArray[i]) - { - boolNodeFlag = true; - break; // break out of for loop - } - } - } - - tempConstArray = new ConstantUnion[1]; - if (!boolNodeFlag) - { - tempConstArray->setBConst(true); - } - else - { - tempConstArray->setBConst(false); - } - - tempNode = new TIntermConstantUnion( - tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); - tempNode->setLine(getLine()); - - return tempNode; - - default: - infoSink.info.message( - EPrefixInternalError, getLine(), - "Invalid operator for constant folding"); - return NULL; - } - tempNode = new TIntermConstantUnion(tempConstArray, returnType); - tempNode->setLine(getLine()); - - return tempNode; - } - else - { - // - // Do unary operations - // - TIntermConstantUnion *newNode = 0; - ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - switch(op) - { - case EOpNegative: - switch (getType().getBasicType()) - { - case EbtFloat: - tempConstArray[i].setFConst(-unionArray[i].getFConst()); - break; - case EbtInt: - tempConstArray[i].setIConst(-unionArray[i].getIConst()); - break; - case EbtUInt: - tempConstArray[i].setUConst(static_cast( - -static_cast(unionArray[i].getUConst()))); - break; - default: - infoSink.info.message( - EPrefixInternalError, getLine(), - "Unary operation not folded into constant"); - return NULL; - } - break; - - case EOpLogicalNot: - // this code is written for possible future use, - // will not get executed currently - switch (getType().getBasicType()) - { - case EbtBool: - tempConstArray[i].setBConst(!unionArray[i].getBConst()); - break; - default: - infoSink.info.message( - EPrefixInternalError, getLine(), - "Unary operation not folded into constant"); - return NULL; - } - break; - - default: - return NULL; - } - } - newNode = new TIntermConstantUnion(tempConstArray, getType()); - newNode->setLine(getLine()); - return newNode; - } -} - -// static -TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction) -{ - if (hashFunction == NULL || name.empty()) - return name; - khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); - TStringStream stream; - stream << HASHED_NAME_PREFIX << std::hex << number; - TString hashedName = stream.str(); - return hashedName; -} diff --git a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h index 5a140c339e..5f72a6e944 100644 --- a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h +++ b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TRANSLATOR_LOOP_INFO_H_ #define COMPILER_TRANSLATOR_LOOP_INFO_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class TLoopIndexInfo { diff --git a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h index b58c7ec689..60070c9d33 100644 --- a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h +++ b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h @@ -9,7 +9,7 @@ #ifndef TRANSLATOR_NODESEARCH_H_ #define TRANSLATOR_NODESEARCH_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp index 7839c04852..6d07cccc04 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -81,9 +81,10 @@ void TOutputGLSLBase::writeVariableType(const TType &type) { TInfoSinkBase &out = objSink(); TQualifier qualifier = type.getQualifier(); - // TODO(alokp): Validate qualifier for variable declarations. if (qualifier != EvqTemporary && qualifier != EvqGlobal) + { out << type.getQualifierString() << " "; + } // Declare the struct if we have not done so already. if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct())) { @@ -648,6 +649,17 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) mDeclaringVariables = false; } break; + case EOpInvariantDeclaration: { + // Invariant declaration. + ASSERT(visit == PreVisit); + const TIntermSequence *sequence = node->getSequence(); + ASSERT(sequence && sequence->size() == 1); + const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode(); + ASSERT(symbol); + out << "invariant " << symbol->getSymbol() << ";"; + visitChildren = false; + break; + } case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break; diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h index 42364de6f5..e5174f5660 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h @@ -9,7 +9,7 @@ #include -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/LoopInfo.h" #include "compiler/translator/ParseContext.h" diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp index 1bf1181af0..a5ea71599d 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp @@ -21,6 +21,7 @@ #include "compiler/translator/util.h" #include "compiler/translator/UniformHLSL.h" #include "compiler/translator/StructureHLSL.h" +#include "compiler/translator/TranslatorHLSL.h" #include #include @@ -93,8 +94,10 @@ bool OutputHLSL::TextureFunction::operator<(const TextureFunction &rhs) const return false; } -OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType) - : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType) +OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator) + : TIntermTraverser(true, true, true), + mContext(context), + mOutputType(parentTranslator->getOutputType()) { mUnfoldShortCircuit = new UnfoldShortCircuit(context, this); mInsideFunction = false; @@ -126,6 +129,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc mUsesDiscardRewriting = false; mUsesNestedBreak = false; + const ShBuiltInResources &resources = parentTranslator->getResources(); mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; mUniqueIndex = 0; @@ -138,7 +142,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc mExcessiveLoopIndex = NULL; mStructureHLSL = new StructureHLSL; - mUniformHLSL = new UniformHLSL(mStructureHLSL, mOutputType); + mUniformHLSL = new UniformHLSL(mStructureHLSL, parentTranslator); if (mOutputType == SH_HLSL9_OUTPUT) { @@ -212,31 +216,6 @@ TInfoSinkBase &OutputHLSL::getBodyStream() return mBody; } -const std::vector &OutputHLSL::getUniforms() -{ - return mUniformHLSL->getUniforms(); -} - -const std::vector &OutputHLSL::getInterfaceBlocks() const -{ - return mUniformHLSL->getInterfaceBlocks(); -} - -const std::vector &OutputHLSL::getOutputVariables() const -{ - return mActiveOutputVariables; -} - -const std::vector &OutputHLSL::getAttributes() const -{ - return mActiveAttributes; -} - -const std::vector &OutputHLSL::getVaryings() const -{ - return mActiveVaryings; -} - const std::map &OutputHLSL::getInterfaceBlockRegisterMap() const { return mUniformHLSL->getInterfaceBlockRegisterMap(); @@ -324,8 +303,6 @@ void OutputHLSL::header() // Program linking depends on this exact format varyings += "static " + InterpolationString(type.getQualifier()) + " " + TypeString(type) + " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n"; - - declareVaryingToList(type, type.getQualifier(), name, mActiveVaryings); } for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++) @@ -334,10 +311,6 @@ void OutputHLSL::header() const TString &name = attribute->second->getSymbol(); attributes += "static " + TypeString(type) + " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n"; - - sh::Attribute attributeVar(GLVariableType(type), GLVariablePrecision(type), name.c_str(), - (unsigned int)type.getArraySize(), type.getLayoutQualifier().location); - mActiveAttributes.push_back(attributeVar); } out << mStructureHLSL->structsHeader(); @@ -370,14 +343,9 @@ void OutputHLSL::header() { const TString &variableName = outputVariableIt->first; const TType &variableType = outputVariableIt->second->getType(); - const TLayoutQualifier &layoutQualifier = variableType.getLayoutQualifier(); out << "static " + TypeString(variableType) + " out_" + variableName + ArrayString(variableType) + " = " + initializer(variableType) + ";\n"; - - sh::Attribute outputVar(GLVariableType(variableType), GLVariablePrecision(variableType), variableName.c_str(), - (unsigned int)variableType.getArraySize(), layoutQualifier.location); - mActiveOutputVariables.push_back(outputVar); } } else @@ -1951,6 +1919,9 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) out << ", "; } break; + case EOpInvariantDeclaration: + // Do not do any translation + return false; case EOpPrototype: if (visit == PreVisit) { @@ -2910,29 +2881,4 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con return constUnion; } -class DeclareVaryingTraverser : public GetVariableTraverser -{ - public: - DeclareVaryingTraverser(std::vector *output, - InterpolationType interpolation) - : GetVariableTraverser(output), - mInterpolation(interpolation) - {} - - private: - void visitVariable(Varying *varying) - { - varying->interpolation = mInterpolation; - } - - InterpolationType mInterpolation; -}; - -void OutputHLSL::declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, - const TString &name, std::vector &fieldsOut) -{ - DeclareVaryingTraverser traverser(&fieldsOut, GetInterpolationType(baseTypeQualifier)); - traverser.traverse(type, name); -} - } diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h index 78bb741a11..bec02479bb 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h @@ -12,9 +12,9 @@ #include #include "angle_gl.h" -#include "compiler/translator/intermediate.h" + +#include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" -#include "common/shadervars.h" namespace sh { @@ -27,17 +27,12 @@ typedef std::map ReferencedSymbols; class OutputHLSL : public TIntermTraverser { public: - OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType); + OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator); ~OutputHLSL(); void output(); TInfoSinkBase &getBodyStream(); - const std::vector &getUniforms(); - const std::vector &getInterfaceBlocks() const; - const std::vector &getOutputVariables() const; - const std::vector &getAttributes() const; - const std::vector &getVaryings() const; const std::map &getInterfaceBlockRegisterMap() const; const std::map &getUniformRegisterMap() const; @@ -155,13 +150,8 @@ class OutputHLSL : public TIntermTraverser TIntermSymbol *mExcessiveLoopIndex; - void declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, const TString &name, std::vector& fieldsOut); - TString structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName); - std::vector mActiveOutputVariables; - std::vector mActiveAttributes; - std::vector mActiveVaryings; std::map mFlaggedStructMappedNames; std::map mFlaggedStructOriginalNames; diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp index 605612ac37..ff0a49667c 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp @@ -1018,6 +1018,45 @@ void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* nam // ///////////////////////////////////////////////////////////////////////////////// +const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location, + const TString *name, + const TSymbol *symbol) +{ + const TVariable *variable = NULL; + + if (!symbol) + { + error(location, "undeclared identifier", name->c_str()); + recover(); + } + else if (!symbol->isVariable()) + { + error(location, "variable expected", name->c_str()); + recover(); + } + else + { + variable = static_cast(symbol); + + if (symbolTable.findBuiltIn(variable->getName(), shaderVersion) && + !variable->getExtension().empty() && + extensionErrorCheck(location, variable->getExtension())) + { + recover(); + } + } + + if (!variable) + { + TType type(EbtFloat, EbpUndefined); + TVariable *fakeVariable = new TVariable(name, type); + symbolTable.declare(fakeVariable); + variable = fakeVariable; + } + + return variable; +} + // // Look up a function name in the symbol table, and make sure it is a function. // @@ -1050,6 +1089,8 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* // Initializers show up in several places in the grammar. Have one set of // code to handle them here. // +// Returns true on error, false if no error +// bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) { @@ -1308,14 +1349,40 @@ TIntermAggregate* TParseContext::parseSingleInitDeclaration(TPublicType &publicT } } -TIntermAggregate* TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier) +TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc, + const TSourceLoc &identifierLoc, + const TString *identifier, + const TSymbol *symbol) { - if (publicType.type == EbtInvariant && !identifierSymbol) + // invariant declaration + if (globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying")) + { + recover(); + } + + if (!symbol) { - error(identifierLocation, "undeclared identifier declared as invariant", identifier.c_str()); + error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str()); recover(); + + return NULL; } + else + { + const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); + ASSERT(variable); + const TType &type = variable->getType(); + TIntermSymbol *intermSymbol = intermediate.addSymbol(variable->getUniqueId(), + *identifier, type, identifierLoc); + TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc); + aggregate->setOp(EOpInvariantDeclaration); + return aggregate; + } +} + +TIntermAggregate* TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier) +{ TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation); TIntermAggregate* intermAggregate = intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation); @@ -1548,7 +1615,7 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType for (size_t i = 0; i < fields.size(); i++) { - if ((*args)[i]->getAsTyped()->getType() != *fields[i]->type()) + if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type()) { error(line, "Structure constructor arguments do not match structure fields", "Error"); recover(); diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h index a402eec78e..1f4cbdeba9 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.h +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.h @@ -9,7 +9,7 @@ #include "compiler/translator/Compiler.h" #include "compiler/translator/Diagnostics.h" #include "compiler/translator/DirectiveHandler.h" -#include "compiler/translator/localintermediate.h" +#include "compiler/translator/Intermediate.h" #include "compiler/translator/SymbolTable.h" #include "compiler/preprocessor/Preprocessor.h" @@ -77,6 +77,9 @@ struct TParseContext { void trace(const char* str); void recover(); + // 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); + bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc& line); bool parseMatrixFields(const TString&, int matCols, int matRows, TMatrixFields&, const TSourceLoc& line); @@ -126,6 +129,8 @@ struct TParseContext { TIntermAggregate* parseSingleDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier); TIntermAggregate* parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& indexLocation, TIntermTyped *indexExpression); TIntermAggregate* parseSingleInitDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer); + TIntermAggregate* parseInvariantDeclaration(const TSourceLoc &invariantLoc, const TSourceLoc &identifierLoc, const TString *identifier, const TSymbol *symbol); + TIntermAggregate* parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier); TIntermAggregate* parseArrayDeclarator(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& arrayLocation, TIntermNode *declaratorList, TIntermTyped *indexExpression); TIntermAggregate* parseInitDeclarator(TPublicType &publicType, TIntermAggregate *declaratorList, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer); diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp index 1ba087e176..1f6fb75821 100644 --- a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp +++ b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class TAliveTraverser : public TIntermTraverser { public: diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp new file mode 100644 index 0000000000..767b18085c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp @@ -0,0 +1,82 @@ +// +// 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/RegenerateStructNames.h" +#include "compiler/translator/compilerdebug.h" + +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::visitAggregate(Visit, TIntermAggregate *aggregate) +{ + ASSERT(aggregate); + switch (aggregate->getOp()) + { + case EOpSequence: + ++mScopeDepth; + { + TIntermSequence &sequence = *(aggregate->getSequence()); + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + TIntermNode *node = sequence[ii]; + ASSERT(node != NULL); + node->traverse(this); + } + } + --mScopeDepth; + return false; + default: + return true; + } +} diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h new file mode 100644 index 0000000000..ac87600347 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h @@ -0,0 +1,40 @@ +// +// 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_REGENERATE_STRUCT_NAMES_H_ +#define COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ + +#include "compiler/translator/Intermediate.h" +#include "compiler/translator/SymbolTable.h" + +#include + +class RegenerateStructNames : public TIntermTraverser +{ + public: + RegenerateStructNames(const TSymbolTable &symbolTable, + int shaderVersion) + : mSymbolTable(symbolTable), + mShaderVersion(shaderVersion), + mScopeDepth(0) {} + + protected: + virtual void visitSymbol(TIntermSymbol *); + virtual bool visitAggregate(Visit, TIntermAggregate *); + + private: + const TSymbolTable &mSymbolTable; + 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 mDeclaredGlobalStructs; +}; + +#endif // COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp index e381c32690..0cf6910aa2 100644 --- a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp +++ b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/RemoveTree.h" // diff --git a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h index 1f7fb16c45..d43e6ef7be 100644 --- a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h +++ b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h @@ -7,7 +7,7 @@ #ifndef COMPILER_RENAME_FUNCTION #define COMPILER_RENAME_FUNCTION -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // // Renames a function, including its declaration and any calls to it. diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h index 39963d6a82..d87baea0fe 100644 --- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h +++ b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h @@ -10,7 +10,7 @@ #ifndef COMPILER_REWRITE_ELSE_BLOCKS_H_ #define COMPILER_REWRITE_ELSE_BLOCKS_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp index 3a179f7499..8857ad59bd 100644 --- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp @@ -9,6 +9,7 @@ #include +#include "angle_gl.h" #include "common/angleutils.h" namespace @@ -249,6 +250,16 @@ TString ScalarizeVecAndMatConstructorArgs::createTempVariable(TIntermTyped *orig TType type = original->getType(); type.setQualifier(EvqTemporary); + 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. + type.setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium); + } + TIntermBinary *init = new TIntermBinary(EOpInitialize); TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type); init->setLeft(symbolNode); diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h index 6aeb0c4f60..7c6d09c1bb 100644 --- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h +++ b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h @@ -7,13 +7,16 @@ #ifndef COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ #define COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class ScalarizeVecAndMatConstructorArgs : public TIntermTraverser { public: - ScalarizeVecAndMatConstructorArgs() - : mTempVarCount(0) {} + ScalarizeVecAndMatConstructorArgs(sh::GLenum shaderType, + bool fragmentPrecisionHigh) + : mTempVarCount(0), + mShaderType(shaderType), + mFragmentPrecisionHigh(fragmentPrecisionHigh) {} protected: virtual bool visitAggregate(Visit visit, TIntermAggregate *node); @@ -36,6 +39,9 @@ class ScalarizeVecAndMatConstructorArgs : public TIntermTraverser std::vector mSequenceStack; int mTempVarCount; + + sh::GLenum mShaderType; + bool mFragmentPrecisionHigh; }; #endif // COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h index 8ddd3cb1ac..029ac30b9a 100644 --- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h +++ b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h @@ -9,7 +9,7 @@ #ifndef COMPILER_SEARCHSYMBOL_H_ #define COMPILER_SEARCHSYMBOL_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp index 6a801eacfe..20ce71605c 100644 --- a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp @@ -18,14 +18,26 @@ #include "compiler/translator/VariablePacker.h" #include "angle_gl.h" -static bool isInitialized = false; +namespace +{ + +enum ShaderVariableType +{ + SHADERVAR_UNIFORM, + SHADERVAR_VARYING, + SHADERVAR_ATTRIBUTE, + SHADERVAR_OUTPUTVARIABLE, + SHADERVAR_INTERFACEBLOCK +}; + +bool isInitialized = false; // // This is the platform independent interface between an OGL driver // and the shading language compiler. // -static bool checkVariableMaxLengths(const ShHandle handle, +static bool CheckVariableMaxLengths(const ShHandle handle, size_t expectedValue) { size_t activeUniformLimit = 0; @@ -39,7 +51,7 @@ static bool checkVariableMaxLengths(const ShHandle handle, expectedValue == varyingLimit); } -static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue) +bool CheckMappedNameMaxLength(const ShHandle handle, size_t expectedValue) { size_t mappedNameMaxLength = 0; ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength); @@ -47,7 +59,7 @@ static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue } template -static const sh::ShaderVariable *ReturnVariable(const std::vector &infoList, int index) +const sh::ShaderVariable *ReturnVariable(const std::vector &infoList, int index) { if (index < 0 || static_cast(index) >= infoList.size()) { @@ -57,7 +69,7 @@ static const sh::ShaderVariable *ReturnVariable(const std::vector &infoLis return &infoList[index]; } -static const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index) +const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index) { switch (varType) { @@ -73,7 +85,7 @@ static const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShader } } -static ShPrecisionType ConvertPrecision(sh::GLenum precision) +ShPrecisionType ConvertPrecision(sh::GLenum precision) { switch (precision) { @@ -91,6 +103,55 @@ static ShPrecisionType ConvertPrecision(sh::GLenum precision) } } +template +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType); + +template <> +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType) +{ + return &compiler->getUniforms(); +} + +template <> +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType) +{ + return &compiler->getVaryings(); +} + +template <> +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType) +{ + return (variableType == SHADERVAR_ATTRIBUTE ? + &compiler->getAttributes() : + &compiler->getOutputVariables()); +} + +template <> +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType) +{ + return &compiler->getInterfaceBlocks(); +} + +template +const std::vector *GetShaderVariables(const ShHandle handle, ShaderVariableType variableType) +{ + if (!handle) + { + return NULL; + } + + TShHandleBase* base = static_cast(handle); + TCompiler* compiler = base->getAsCompiler(); + if (!compiler) + { + return NULL; + } + + return GetVariableList(compiler, variableType); +} + +} + // // Driver must call this first, once, before doing any other compiler operations. // Subsequent calls to this function are no-op. @@ -372,7 +433,7 @@ void ShGetVariableInfo(const ShHandle handle, // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH // in ShGetInfo, below. size_t variableLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - ASSERT(checkVariableMaxLengths(handle, variableLength)); + ASSERT(CheckVariableMaxLengths(handle, variableLength)); strncpy(name, varInfo->name.c_str(), variableLength); name[variableLength - 1] = 0; if (mappedName) @@ -380,7 +441,7 @@ void ShGetVariableInfo(const ShHandle handle, // This size must match that queried by // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. size_t maxMappedNameLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); + ASSERT(CheckMappedNameMaxLength(handle, maxMappedNameLength)); strncpy(mappedName, varInfo->mappedName.c_str(), maxMappedNameLength); mappedName[maxMappedNameLength - 1] = 0; } @@ -429,34 +490,29 @@ void ShGetNameHashingEntry(const ShHandle handle, hashedName[len - 1] = '\0'; } -void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params) +const std::vector *ShGetUniforms(const ShHandle handle) { - if (!handle || !params) - return; + return GetShaderVariables(handle, SHADERVAR_UNIFORM); +} - TShHandleBase* base = static_cast(handle); - TranslatorHLSL* translator = base->getAsTranslatorHLSL(); - if (!translator) return; +const std::vector *ShGetVaryings(const ShHandle handle) +{ + return GetShaderVariables(handle, SHADERVAR_VARYING); +} - switch(pname) - { - case SH_ACTIVE_UNIFORMS_ARRAY: - *params = (void*)&translator->getUniforms(); - break; - case SH_ACTIVE_INTERFACE_BLOCKS_ARRAY: - *params = (void*)&translator->getInterfaceBlocks(); - break; - case SH_ACTIVE_OUTPUT_VARIABLES_ARRAY: - *params = (void*)&translator->getOutputVariables(); - break; - case SH_ACTIVE_ATTRIBUTES_ARRAY: - *params = (void*)&translator->getAttributes(); - break; - case SH_ACTIVE_VARYINGS_ARRAY: - *params = (void*)&translator->getVaryings(); - break; - default: UNREACHABLE(); - } +const std::vector *ShGetAttributes(const ShHandle handle) +{ + return GetShaderVariables(handle, SHADERVAR_ATTRIBUTE); +} + +const std::vector *ShGetOutputVariables(const ShHandle handle) +{ + return GetShaderVariables(handle, SHADERVAR_OUTPUTVARIABLE); +} + +const std::vector *ShGetInterfaceBlocks(const ShHandle handle) +{ + return GetShaderVariables(handle, SHADERVAR_INTERFACEBLOCK); } int ShCheckVariablesWithinPackingLimits( @@ -468,7 +524,7 @@ int ShCheckVariablesWithinPackingLimits( std::vector variables; for (size_t ii = 0; ii < varInfoArraySize; ++ii) { - sh::ShaderVariable var(varInfoArray[ii].type, (sh::GLenum)0, "", varInfoArray[ii].size); + sh::ShaderVariable var(varInfoArray[ii].type, varInfoArray[ii].size); variables.push_back(var); } VariablePacker packer; diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp new file mode 100644 index 0000000000..822c558c9b --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp @@ -0,0 +1,166 @@ +// +// 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 + +namespace sh +{ + +ShaderVariable::ShaderVariable() + : type(0), + precision(0), + arraySize(0), + staticUse(false) +{} + +ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn) + : type(typeIn), + precision(0), + arraySize(arraySizeIn), + staticUse(false) +{} + +ShaderVariable::~ShaderVariable() +{} + +ShaderVariable::ShaderVariable(const ShaderVariable &other) + : type(other.type), + precision(other.precision), + name(other.name), + mappedName(other.mappedName), + arraySize(other.arraySize), + 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; + arraySize = other.arraySize; + staticUse = other.staticUse; + fields = other.fields; + structName = other.structName; + return *this; +} + +Uniform::Uniform() +{} + +Uniform::~Uniform() +{} + +Uniform::Uniform(const Uniform &other) + : ShaderVariable(other) +{} + +Uniform &Uniform::operator=(const Uniform &other) +{ + ShaderVariable::operator=(other); + return *this; +} + +Attribute::Attribute() + : location(-1) +{} + +Attribute::~Attribute() +{} + +Attribute::Attribute(const Attribute &other) + : ShaderVariable(other), + location(other.location) +{} + +Attribute &Attribute::operator=(const Attribute &other) +{ + ShaderVariable::operator=(other); + location = other.location; + return *this; +} + +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; +} + +Varying::Varying() + : interpolation(INTERPOLATION_SMOOTH), + isInvariant(false) +{} + +Varying::~Varying() +{} + +Varying::Varying(const Varying &other) + : ShaderVariable(other), + interpolation(other.interpolation), + isInvariant(other.isInvariant) +{} + +Varying &Varying::operator=(const Varying &other) +{ + ShaderVariable::operator=(other); + interpolation = other.interpolation; + isInvariant = other.isInvariant; + return *this; +} + +InterfaceBlock::InterfaceBlock() + : arraySize(0), + layout(BLOCKLAYOUT_PACKED), + isRowMajorLayout(false), + staticUse(false) +{} + +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), + staticUse(other.staticUse), + 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; + staticUse = other.staticUse; + fields = other.fields; + return *this; +} + +} diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp index 365985c852..48929affe6 100644 --- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp @@ -17,12 +17,19 @@ namespace sh { -Std140PaddingHelper::Std140PaddingHelper(const std::map &structElementIndexes) - : mPaddingCounter(0), +Std140PaddingHelper::Std140PaddingHelper(const std::map &structElementIndexes, + unsigned *uniqueCounter) + : mPaddingCounter(uniqueCounter), mElementIndex(0), mStructElementIndexes(structElementIndexes) {} +TString Std140PaddingHelper::next() +{ + unsigned value = (*mPaddingCounter)++; + return str(value); +} + int Std140PaddingHelper::prePadding(const TType &type) { if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray()) @@ -68,7 +75,7 @@ TString Std140PaddingHelper::prePaddingString(const TType &type) for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++) { - padding += " float pad_" + str(mPaddingCounter++) + ";\n"; + padding += " float pad_" + next() + ";\n"; } return padding; @@ -116,19 +123,25 @@ TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRo TString padding; for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++) { - padding += " float pad_" + str(mPaddingCounter++) + ";\n"; + 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(mStd140StructElementIndexes); + Std140PaddingHelper padHelper = getPaddingHelper(); return define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper); } else @@ -291,9 +304,9 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const if (parameter.isScalar()) { - for (int row = 0; row < rows; row++) + for (int col = 0; col < cols; col++) { - for (int col = 0; col < cols; col++) + for (int row = 0; row < rows; row++) { constructor += TString((row == col) ? "x0" : "0.0"); @@ -306,13 +319,13 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const } else if (parameter.isMatrix()) { - for (int row = 0; row < rows; row++) + for (int col = 0; col < cols; col++) { - 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(row) + "][" + str(col) + "]"; + constructor += TString("x0") + "[" + str(col) + "][" + str(row) + "]"; } else { @@ -461,7 +474,7 @@ std::string StructureHLSL::structsHeader() const void StructureHLSL::storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking) { - Std140PaddingHelper padHelper(mStd140StructElementIndexes); + Std140PaddingHelper padHelper = getPaddingHelper(); const TFieldList &fields = structure.fields(); for (unsigned int i = 0; i < fields.size(); i++) diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h index 63fbaaaf8e..ed002fef30 100644 --- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h @@ -11,7 +11,7 @@ #define TRANSLATOR_STRUCTUREHLSL_H_ #include "compiler/translator/Common.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include @@ -26,7 +26,8 @@ namespace sh class Std140PaddingHelper { public: - explicit Std140PaddingHelper(const std::map &structElementIndexes); + explicit Std140PaddingHelper(const std::map &structElementIndexes, + unsigned *uniqueCounter); int elementIndex() const { return mElementIndex; } int prePadding(const TType &type); @@ -34,7 +35,9 @@ class Std140PaddingHelper TString postPaddingString(const TType &type, bool useHLSLRowMajorPacking); private: - int mPaddingCounter; + TString next(); + + unsigned *mPaddingCounter; int mElementIndex; const std::map &mStructElementIndexes; }; @@ -50,9 +53,11 @@ class StructureHLSL TString defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing); static TString defineNameless(const TStructure &structure); - Std140PaddingHelper getPaddingHelper() const { return Std140PaddingHelper(mStd140StructElementIndexes); } + Std140PaddingHelper getPaddingHelper(); private: + unsigned mUniquePaddingCounter; + std::map mStd140StructElementIndexes; typedef std::set StructNames; diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp index ae4fcaa6c3..028da21151 100644 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp @@ -98,7 +98,8 @@ TSymbol::TSymbol(const TSymbol ©Of) uniqueId = copyOf.uniqueId; } -TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope) +TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, + bool *builtIn, bool *sameScope) const { int level = currentLevel(); TSymbol *symbol; @@ -122,7 +123,8 @@ TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtI return symbol; } -TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) +TSymbol *TSymbolTable::findBuiltIn( + const TString &name, int shaderVersion) const { for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--) { @@ -210,7 +212,7 @@ void TSymbolTable::insertBuiltIn( insert(level, function); } -TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) +TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const { if (!SupportsPrecision(type)) return EbpUndefined; diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h index d3ddf19e34..6b0e0c0a03 100644 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h @@ -34,7 +34,7 @@ #include "common/angleutils.h" #include "compiler/translator/InfoSink.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // Symbol base class. (Can build functions or variables out of these...) class TSymbol @@ -323,15 +323,15 @@ class 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() + bool isEmpty() const { return table.empty(); } - bool atBuiltInLevel() + bool atBuiltInLevel() const { return currentLevel() <= LAST_BUILTIN_LEVEL; } - bool atGlobalLevel() + bool atGlobalLevel() const { return currentLevel() <= GLOBAL_LEVEL; } @@ -373,8 +373,8 @@ class TSymbolTable TType *ptype4 = 0, TType *ptype5 = 0); TSymbol *find(const TString &name, int shaderVersion, - bool *builtIn = NULL, bool *sameScope = NULL); - TSymbol *findBuiltIn(const TString &name, int shaderVersion); + bool *builtIn = NULL, bool *sameScope = NULL) const; + TSymbol *findBuiltIn(const TString &name, int shaderVersion) const; TSymbolTableLevel *getOuterLevel() { @@ -406,7 +406,7 @@ class TSymbolTable // Searches down the precisionStack for a precision qualifier // for the specified TBasicType - TPrecision getDefaultPrecision(TBasicType type); + TPrecision getDefaultPrecision(TBasicType type) const; static int nextUniqueId() { diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp index 52588e4626..22bf60e86e 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp @@ -17,16 +17,10 @@ TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutpu void TranslatorHLSL::translate(TIntermNode *root) { TParseContext& parseContext = *GetGlobalParseContext(); - sh::OutputHLSL outputHLSL(parseContext, getResources(), getOutputType()); + sh::OutputHLSL outputHLSL(parseContext, this); outputHLSL.output(); - attributes = outputHLSL.getAttributes(); - outputVariables = outputHLSL.getOutputVariables(); - uniforms = outputHLSL.getUniforms(); - varyings = outputHLSL.getVaryings(); - interfaceBlocks = outputHLSL.getInterfaceBlocks(); - mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap(); mUniformRegisterMap = outputHLSL.getUniformRegisterMap(); } diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h index 598c8a7b30..11a042d83a 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h @@ -8,7 +8,6 @@ #define COMPILER_TRANSLATORHLSL_H_ #include "compiler/translator/Compiler.h" -#include "common/shadervars.h" class TranslatorHLSL : public TCompiler { diff --git a/src/3rdparty/angle/src/compiler/translator/Types.cpp b/src/3rdparty/angle/src/compiler/translator/Types.cpp index bafad0d64f..d36936fb23 100644 --- a/src/3rdparty/angle/src/compiler/translator/Types.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Types.cpp @@ -13,6 +13,38 @@ #include #include +const char* getBasicString(TBasicType t) +{ + switch (t) + { + case EbtVoid: return "void"; break; + case EbtFloat: return "float"; break; + case EbtInt: return "int"; break; + case EbtUInt: return "uint"; break; + case EbtBool: return "bool"; break; + case EbtSampler2D: return "sampler2D"; break; + case EbtSampler3D: return "sampler3D"; break; + case EbtSamplerCube: return "samplerCube"; break; + case EbtSamplerExternalOES: return "samplerExternalOES"; break; + case EbtSampler2DRect: return "sampler2DRect"; break; + case EbtSampler2DArray: return "sampler2DArray"; break; + case EbtISampler2D: return "isampler2D"; break; + case EbtISampler3D: return "isampler3D"; break; + case EbtISamplerCube: return "isamplerCube"; break; + case EbtISampler2DArray: return "isampler2DArray"; break; + case EbtUSampler2D: return "usampler2D"; break; + case EbtUSampler3D: return "usampler3D"; break; + case EbtUSamplerCube: return "usamplerCube"; break; + case EbtUSampler2DArray: return "usampler2DArray"; break; + case EbtSampler2DShadow: return "sampler2DShadow"; break; + case EbtSamplerCubeShadow: return "samplerCubeShadow"; break; + case EbtSampler2DArrayShadow: return "sampler2DArrayShadow"; break; + case EbtStruct: return "structure"; break; + case EbtInterfaceBlock: return "interface block"; break; + default: UNREACHABLE(); return "unknown type"; + } +} + TType::TType(const TPublicType &p) : type(p.type), precision(p.precision), qualifier(p.qualifier), layoutQualifier(p.layoutQualifier), primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize), diff --git a/src/3rdparty/angle/src/compiler/translator/Types.h b/src/3rdparty/angle/src/compiler/translator/Types.h index bc50a4dc64..075196daa3 100644 --- a/src/3rdparty/angle/src/compiler/translator/Types.h +++ b/src/3rdparty/angle/src/compiler/translator/Types.h @@ -140,6 +140,17 @@ class TStructure : public TFieldListCollection private: DISALLOW_COPY_AND_ASSIGN(TStructure); + + // 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(mName); + *mutableName = name; + } + virtual TString mangledNamePrefix() const { return "struct-"; diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h index 1e416bc04c..6fd3b457bd 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h @@ -9,7 +9,7 @@ #ifndef COMPILER_UNFOLDSHORTCIRCUIT_H_ #define COMPILER_UNFOLDSHORTCIRCUIT_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h index 24c14a60e3..3acaf7ee7c 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h @@ -11,7 +11,7 @@ #define COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ #include "common/angleutils.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // This traverser identifies all the short circuit binary nodes that need to // be replaced, and creates the corresponding replacement nodes. However, diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp index 41a7d2c10b..61b6ed7455 100644 --- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp @@ -14,6 +14,7 @@ #include "compiler/translator/StructureHLSL.h" #include "compiler/translator/util.h" #include "compiler/translator/UtilsHLSL.h" +#include "compiler/translator/TranslatorHLSL.h" namespace sh { @@ -30,18 +31,6 @@ static const char *UniformRegisterPrefix(const TType &type) } } -static TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field) -{ - if (interfaceBlock.hasInstanceName()) - { - return interfaceBlock.name() + "." + field.name(); - } - else - { - return field.name(); - } -} - static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage) { const TType &fieldType = *field.type(); @@ -72,12 +61,13 @@ static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock) return DecoratePrivate(interfaceBlock.name()) + "_type"; } -UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType) +UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator) : mUniformRegister(0), mInterfaceBlockRegister(0), mSamplerRegister(0), mStructureHLSL(structureHLSL), - mOutputType(outputType) + mOutputType(translator->getOutputType()), + mUniforms(translator->getUniforms()) {} void UniformHLSL::reserveUniformRegisters(unsigned int registerCount) @@ -90,18 +80,32 @@ void UniformHLSL::reserveInterfaceBlockRegisters(unsigned int registerCount) mInterfaceBlockRegister = 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]; + } + } + + UNREACHABLE(); + return NULL; +} + unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name) { unsigned int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister); - GetVariableTraverser traverser(&mActiveUniforms); - traverser.traverse(type, name); + const Uniform *uniform = findUniformByName(name); + ASSERT(uniform); - const sh::Uniform &activeUniform = mActiveUniforms.back(); - mUniformRegisterMap[activeUniform.name] = registerIndex; + mUniformRegisterMap[uniform->name] = registerIndex; - unsigned int registerCount = HLSLVariableRegisterCount(activeUniform, mOutputType); - if (IsSampler(type.getBasicType())) + unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType); + + if (gl::IsSampler(uniform->type)) { mSamplerRegister += registerCount; } @@ -137,7 +141,12 @@ TString UniformHLSL::uniformsHeader(ShShaderOutput outputType, const ReferencedS else { const TStructure *structure = type.getStruct(); - const TString &typeName = (structure ? QualifiedStructNameString(*structure, false, false) : TypeString(type)); + // 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 ®isterString = TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")"; @@ -157,33 +166,14 @@ TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedIn { const TType &nodeType = interfaceBlockIt->second->getType(); const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock(); - const TFieldList &fieldList = interfaceBlock.fields(); unsigned int arraySize = static_cast(interfaceBlock.arraySize()); unsigned int activeRegister = mInterfaceBlockRegister; - InterfaceBlock activeBlock(interfaceBlock.name().c_str(), arraySize); - for (unsigned int typeIndex = 0; typeIndex < fieldList.size(); typeIndex++) - { - const TField &field = *fieldList[typeIndex]; - const TString &fullFieldName = InterfaceBlockFieldName(interfaceBlock, field); - - bool isRowMajor = (field.type()->getLayoutQualifier().matrixPacking == EmpRowMajor); - GetInterfaceBlockFieldTraverser traverser(&activeBlock.fields, isRowMajor); - traverser.traverse(*field.type(), fullFieldName); - } - - mInterfaceBlockRegisterMap[activeBlock.name] = activeRegister; + mInterfaceBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister; mInterfaceBlockRegister += std::max(1u, arraySize); - activeBlock.layout = GetBlockLayoutType(interfaceBlock.blockStorage()); - - if (interfaceBlock.matrixPacking() == EmpRowMajor) - { - activeBlock.isRowMajorLayout = true; - } - - mActiveInterfaceBlocks.push_back(activeBlock); + // FIXME: interface block field names if (interfaceBlock.hasInstanceName()) { @@ -261,7 +251,7 @@ TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfac if (blockStorage == EbsStd140) { // 2 and 3 component vector types in some cases need pre-padding - hlsl += padHelper.prePadding(fieldType); + hlsl += padHelper.prePaddingString(fieldType); } hlsl += " " + InterfaceBlockFieldTypeString(field, blockStorage) + diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h index 835b1ef2c8..91fa51588b 100644 --- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h @@ -10,7 +10,6 @@ #ifndef TRANSLATOR_UNIFORMHLSL_H_ #define TRANSLATOR_UNIFORMHLSL_H_ -#include "common/shadervars.h" #include "compiler/translator/Types.h" namespace sh @@ -20,7 +19,7 @@ class StructureHLSL; class UniformHLSL { public: - UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType); + UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator); void reserveUniformRegisters(unsigned int registerCount); void reserveInterfaceBlockRegisters(unsigned int registerCount); @@ -30,8 +29,6 @@ class UniformHLSL // Used for direct index references static TString interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex); - const std::vector &getUniforms() const { return mActiveUniforms; } - const std::vector &getInterfaceBlocks() const { return mActiveInterfaceBlocks; } const std::map &getInterfaceBlockRegisterMap() const { return mInterfaceBlockRegisterMap; @@ -45,6 +42,7 @@ class UniformHLSL TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex); TString interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage); TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock); + const Uniform *findUniformByName(const TString &name) const; // Returns the uniform's register index unsigned int declareUniformAndAssignRegister(const TType &type, const TString &name); @@ -55,8 +53,7 @@ class UniformHLSL StructureHLSL *mStructureHLSL; ShShaderOutput mOutputType; - std::vector mActiveUniforms; - std::vector mActiveInterfaceBlocks; + const std::vector &mUniforms; std::map mInterfaceBlockRegisterMap; std::map mUniformRegisterMap; }; diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h index 8c9ebf53ed..e6e8a9619f 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/LoopInfo.h" class TInfoSinkBase; diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h index e391ad9486..0f808dbb97 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h +++ b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp index 153455c4f1..f26c1566ac 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp @@ -9,20 +9,46 @@ #include "compiler/translator/util.h" #include "common/utilities.h" -template -static void ExpandUserDefinedVariable(const VarT &variable, - const std::string &name, - const std::string &mappedName, - bool markStaticUse, - std::vector *expanded); +namespace sh +{ -// Returns info for an attribute, uniform, or varying. -template -static void ExpandVariable(const VarT &variable, - const std::string &name, - const std::string &mappedName, - bool markStaticUse, - std::vector *expanded) +namespace +{ + +TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field) +{ + if (interfaceBlock.hasInstanceName()) + { + return interfaceBlock.name() + "." + field.name(); + } + else + { + return field.name(); + } +} + +BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage) +{ + switch (blockStorage) + { + case EbsPacked: return BLOCKLAYOUT_PACKED; + case EbsShared: return BLOCKLAYOUT_SHARED; + case EbsStd140: return BLOCKLAYOUT_STANDARD; + default: UNREACHABLE(); return BLOCKLAYOUT_SHARED; + } +} + +void ExpandUserDefinedVariable(const ShaderVariable &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector *expanded); + +void ExpandVariable(const ShaderVariable &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector *expanded) { if (variable.isStruct()) { @@ -30,8 +56,8 @@ static void ExpandVariable(const VarT &variable, { for (size_t elementIndex = 0; elementIndex < variable.elementCount(); elementIndex++) { - std::string lname = name + ArrayString(elementIndex); - std::string lmappedName = mappedName + ArrayString(elementIndex); + std::string lname = name + ::ArrayString(elementIndex); + std::string lmappedName = mappedName + ::ArrayString(elementIndex); ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded); } } @@ -42,7 +68,7 @@ static void ExpandVariable(const VarT &variable, } else { - VarT expandedVar = variable; + ShaderVariable expandedVar = variable; expandedVar.name = name; expandedVar.mappedName = mappedName; @@ -63,20 +89,19 @@ static void ExpandVariable(const VarT &variable, } } -template -static void ExpandUserDefinedVariable(const VarT &variable, - const std::string &name, - const std::string &mappedName, - bool markStaticUse, - std::vector *expanded) +void ExpandUserDefinedVariable(const ShaderVariable &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector *expanded) { ASSERT(variable.isStruct()); - const std::vector &fields = variable.fields; + const std::vector &fields = variable.fields; for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) { - const VarT &field = fields[fieldIndex]; + const ShaderVariable &field = fields[fieldIndex]; ExpandVariable(field, name + "." + field.name, mappedName + "." + field.mappedName, @@ -86,8 +111,8 @@ static void ExpandUserDefinedVariable(const VarT &variable, } template -static VarT *FindVariable(const TString &name, - std::vector *infoList) +VarT *FindVariable(const TString &name, + std::vector *infoList) { // TODO(zmo): optimize this function. for (size_t ii = 0; ii < infoList->size(); ++ii) @@ -99,6 +124,8 @@ static VarT *FindVariable(const TString &name, return NULL; } +} + CollectVariables::CollectVariables(std::vector *attribs, std::vector *outputVariables, std::vector *uniforms, @@ -125,14 +152,18 @@ CollectVariables::CollectVariables(std::vector *attribs, void CollectVariables::visitSymbol(TIntermSymbol *symbol) { ASSERT(symbol != NULL); - sh::ShaderVariable *var = NULL; + ShaderVariable *var = NULL; const TString &symbolName = symbol->getSymbol(); - if (sh::IsVarying(symbol->getQualifier())) + if (IsVarying(symbol->getQualifier())) { var = FindVariable(symbolName, mVaryings); } - else if (symbol->getType() != EbtInterfaceBlock) + else if (symbol->getType().getBasicType() == EbtInterfaceBlock) + { + UNREACHABLE(); + } + else { switch (symbol->getQualifier()) { @@ -148,12 +179,13 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock(); if (interfaceBlock) { - sh::InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks); + InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks); ASSERT(namedBlock); var = FindVariable(symbolName, &namedBlock->fields); // Set static use on the parent interface block here namedBlock->staticUse = true; + } else { @@ -167,7 +199,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) case EvqFragCoord: if (!mFragCoordAdded) { - sh::Varying info; + Varying info; info.name = "gl_FragCoord"; info.mappedName = "gl_FragCoord"; info.type = GL_FLOAT_VEC4; @@ -181,7 +213,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) case EvqFrontFacing: if (!mFrontFacingAdded) { - sh::Varying info; + Varying info; info.name = "gl_FrontFacing"; info.mappedName = "gl_FrontFacing"; info.type = GL_BOOL; @@ -195,7 +227,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) case EvqPointCoord: if (!mPointCoordAdded) { - sh::Varying info; + Varying info; info.name = "gl_PointCoord"; info.mappedName = "gl_PointCoord"; info.type = GL_FLOAT_VEC2; @@ -216,17 +248,17 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) } } -template -class NameHashingTraverser : public sh::GetVariableTraverser +class NameHashingTraverser : public GetVariableTraverser { public: - NameHashingTraverser(std::vector *output, ShHashFunction64 hashFunction) - : sh::GetVariableTraverser(output), - mHashFunction(hashFunction) + NameHashingTraverser(ShHashFunction64 hashFunction) + : mHashFunction(hashFunction) {} private: - void visitVariable(VarT *variable) + DISALLOW_COPY_AND_ASSIGN(NameHashingTraverser); + + virtual void visitVariable(ShaderVariable *variable) { TString stringName = TString(variable->name.c_str()); variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str(); @@ -238,16 +270,16 @@ class NameHashingTraverser : public sh::GetVariableTraverser // Attributes, which cannot have struct fields, are a special case template <> void CollectVariables::visitVariable(const TIntermSymbol *variable, - std::vector *infoList) const + std::vector *infoList) const { ASSERT(variable); const TType &type = variable->getType(); ASSERT(!type.getStruct()); - sh::Attribute attribute; + Attribute attribute; - attribute.type = sh::GLVariableType(type); - attribute.precision = sh::GLVariablePrecision(type); + attribute.type = GLVariableType(type); + attribute.precision = GLVariablePrecision(type); attribute.name = variable->getSymbol().c_str(); attribute.arraySize = static_cast(type.getArraySize()); attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str(); @@ -258,29 +290,32 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable, template <> void CollectVariables::visitVariable(const TIntermSymbol *variable, - std::vector *infoList) const + std::vector *infoList) const { - sh::InterfaceBlock interfaceBlock; + InterfaceBlock interfaceBlock; const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock(); - - bool isRowMajor = (blockType->matrixPacking() == EmpRowMajor); + ASSERT(blockType); interfaceBlock.name = blockType->name().c_str(); interfaceBlock.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str(); + interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : ""); interfaceBlock.arraySize = variable->getArraySize(); - interfaceBlock.isRowMajorLayout = isRowMajor; - interfaceBlock.layout = sh::GetBlockLayoutType(blockType->blockStorage()); + interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor); + interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage()); - ASSERT(blockType); - const TFieldList &blockFields = blockType->fields(); + // Gather field information + const TFieldList &fieldList = blockType->fields(); - for (size_t fieldIndex = 0; fieldIndex < blockFields.size(); fieldIndex++) + for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex) { - const TField *field = blockFields[fieldIndex]; - ASSERT(field); + const TField &field = *fieldList[fieldIndex]; + const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field); + const TType &fieldType = *field.type(); - sh::GetInterfaceBlockFieldTraverser traverser(&interfaceBlock.fields, isRowMajor); - traverser.traverse(*field->type(), field->name()); + GetVariableTraverser traverser; + traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields); + + interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); } infoList->push_back(interfaceBlock); @@ -290,8 +325,8 @@ template void CollectVariables::visitVariable(const TIntermSymbol *variable, std::vector *infoList) const { - NameHashingTraverser traverser(infoList, mHashFunction); - traverser.traverse(variable->getType(), variable->getSymbol()); + NameHashingTraverser traverser(mHashFunction); + traverser.traverse(variable->getType(), variable->getSymbol(), infoList); } template @@ -320,16 +355,19 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) case EOpDeclaration: { const TIntermSequence &sequence = *(node->getSequence()); + ASSERT(!sequence.empty()); + const TIntermTyped &typedNode = *(sequence.front()->getAsTyped()); TQualifier qualifier = typedNode.getQualifier(); if (typedNode.getBasicType() == EbtInterfaceBlock) { visitInfoList(sequence, mInterfaceBlocks); + visitChildren = false; } else if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqFragmentOut || qualifier == EvqUniform || - sh::IsVarying(qualifier)) + IsVarying(qualifier)) { switch (qualifier) { @@ -348,10 +386,7 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) break; } - if (!sequence.empty()) - { - visitChildren = false; - } + visitChildren = false; } break; } @@ -361,15 +396,43 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) return visitChildren; } +bool CollectVariables::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); + + const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock(); + InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks); + ASSERT(namedBlock); + namedBlock->staticUse = true; + + unsigned int fieldIndex = constantUnion->getUConst(0); + ASSERT(fieldIndex < namedBlock->fields.size()); + namedBlock->fields[fieldIndex].staticUse = true; + return false; + } + + return true; +} + template -void ExpandVariables(const std::vector &compact, std::vector *expanded) +void ExpandVariables(const std::vector &compact, + std::vector *expanded) { for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++) { - const VarT &variable = compact[variableIndex]; + const ShaderVariable &variable = compact[variableIndex]; ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded); } } -template void ExpandVariables(const std::vector &, std::vector *); -template void ExpandVariables(const std::vector &, std::vector *); +template void ExpandVariables(const std::vector &, std::vector *); +template void ExpandVariables(const std::vector &, std::vector *); + +} diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h index 3771819c8b..5ac4c46baa 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h @@ -7,22 +7,27 @@ #ifndef COMPILER_VARIABLE_INFO_H_ #define COMPILER_VARIABLE_INFO_H_ -#include "compiler/translator/intermediate.h" -#include "common/shadervars.h" +#include + +#include "compiler/translator/IntermNode.h" + +namespace sh +{ // Traverses intermediate tree to collect all attributes, uniforms, varyings. class CollectVariables : public TIntermTraverser { public: - CollectVariables(std::vector *attribs, - std::vector *outputVariables, - std::vector *uniforms, - std::vector *varyings, - std::vector *interfaceBlocks, + CollectVariables(std::vector *attribs, + std::vector *outputVariables, + std::vector *uniforms, + std::vector *varyings, + std::vector *interfaceBlocks, ShHashFunction64 hashFunction); virtual void visitSymbol(TIntermSymbol *symbol); virtual bool visitAggregate(Visit, TIntermAggregate *node); + virtual bool visitBinary(Visit visit, TIntermBinary *binaryNode); private: template @@ -31,13 +36,13 @@ class CollectVariables : public TIntermTraverser template void visitInfoList(const TIntermSequence &sequence, std::vector *infoList) const; - std::vector *mAttribs; - std::vector *mOutputVariables; - std::vector *mUniforms; - std::vector *mVaryings; - std::vector *mInterfaceBlocks; + std::vector *mAttribs; + std::vector *mOutputVariables; + std::vector *mUniforms; + std::vector *mVaryings; + std::vector *mInterfaceBlocks; - std::map mInterfaceBlockFields; + std::map mInterfaceBlockFields; bool mPointCoordAdded; bool mFrontFacingAdded; @@ -47,8 +52,10 @@ class CollectVariables : public TIntermTraverser }; // Expand struct variables to flattened lists of split variables -// Implemented for sh::Varying and sh::Uniform. template -void ExpandVariables(const std::vector &compact, std::vector *expanded); +void ExpandVariables(const std::vector &compact, + std::vector *expanded); + +} #endif // COMPILER_VARIABLE_INFO_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp index faaf0115fc..e69052162a 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp @@ -3,12 +3,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -#include "compiler/translator/VariablePacker.h" -#include "angle_gl.h" -#include "common/utilities.h" #include +#include "angle_gl.h" + +#include "compiler/translator/VariablePacker.h" +#include "common/utilities.h" + int VariablePacker::GetNumComponentsPerRow(sh::GLenum type) { switch (type) diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp index 12dc9e0dad..8edbd009b0 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp @@ -67,6 +67,9 @@ bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node) } break; } + case EOpInvariantDeclaration: + updateVersion(GLSL_VERSION_120); + break; case EOpParameters: { const TIntermSequence ¶ms = *(node->getSequence()); diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h index de4141d38c..30f5a138a0 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TRANSLATOR_VERSIONGLSL_H_ #define COMPILER_TRANSLATOR_VERSIONGLSL_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // Traverses the intermediate tree to return the minimum GLSL version // required to legally access all built-in features used in the shader. diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h index 5ea1cbb837..bc25fe7cbc 100644 --- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h @@ -7,7 +7,7 @@ #ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H #define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include #include diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y index fb2d835368..5c945ad5ad 100644 --- a/src/3rdparty/angle/src/compiler/translator/glslang.y +++ b/src/3rdparty/angle/src/compiler/translator/glslang.y @@ -209,38 +209,7 @@ identifier variable_identifier : IDENTIFIER { // The symbol table search was done in the lexical phase - const TSymbol *symbol = $1.symbol; - const TVariable *variable = 0; - - if (!symbol) - { - context->error(@1, "undeclared identifier", $1.string->c_str()); - context->recover(); - } - else if (!symbol->isVariable()) - { - context->error(@1, "variable expected", $1.string->c_str()); - context->recover(); - } - else - { - variable = static_cast(symbol); - - if (context->symbolTable.findBuiltIn(variable->getName(), context->shaderVersion) && - !variable->getExtension().empty() && - context->extensionErrorCheck(@1, variable->getExtension())) - { - context->recover(); - } - } - - if (!variable) - { - TType type(EbtFloat, EbpUndefined); - TVariable *fakeVariable = new TVariable($1.string, type); - context->symbolTable.declare(fakeVariable); - variable = fakeVariable; - } + const TVariable *variable = context->getNamedVariable(@1, $1.string, $1.symbol); if (variable->getType().getQualifier() == EvqConst) { @@ -816,9 +785,10 @@ declaration context->symbolTable.pop(); } | init_declarator_list SEMICOLON { - if ($1.intermAggregate) - $1.intermAggregate->setOp(EOpDeclaration); - $$ = $1.intermAggregate; + TIntermAggregate *aggNode = $1.intermAggregate; + if (aggNode && aggNode->getOp() == EOpNull) + aggNode->setOp(EOpDeclaration); + $$ = aggNode; } | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { if (($2 == EbpHigh) && (context->shaderType == GL_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { @@ -1102,22 +1072,8 @@ single_declaration $$.intermAggregate = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4); } | INVARIANT IDENTIFIER { - VERTEX_ONLY("invariant declaration", @1); - if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) - context->recover(); - $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, @2); - if (!$2.symbol) - { - context->error(@2, "undeclared identifier declared as invariant", $2.string->c_str()); - context->recover(); - - $$.intermAggregate = 0; - } - else - { - TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), @2); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - } + // $$.type is not used in invariant declarations. + $$.intermAggregate = context->parseInvariantDeclaration(@1, @2, $2.string, $2.symbol); } ; diff --git a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp index a6e7ab41a6..56340c6f9e 100644 --- a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp +++ b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/localintermediate.h" +#include "compiler/translator/Intermediate.h" #include "compiler/translator/SymbolTable.h" namespace @@ -342,6 +342,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) case EOpMul: out << "component-wise multiply"; break; case EOpDeclaration: out << "Declaration: "; break; + case EOpInvariantDeclaration: out << "Invariant Declaration: "; break; default: out.prefix(EPrefixError); diff --git a/src/3rdparty/angle/src/compiler/translator/intermediate.h b/src/3rdparty/angle/src/compiler/translator/intermediate.h index 892f2849e0..3b7e7bd802 100644 --- a/src/3rdparty/angle/src/compiler/translator/intermediate.h +++ b/src/3rdparty/angle/src/compiler/translator/intermediate.h @@ -4,768 +4,64 @@ // 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_INTERMEDIATE_H_ -#define COMPILER_TRANSLATOR_INTERMEDIATE_H_ - -#include "GLSLANG/ShaderLang.h" - -#include -#include - -#include "compiler/translator/Common.h" -#include "compiler/translator/Types.h" -#include "compiler/translator/ConstantUnion.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 - EOpSequence, // denotes a list of statements, or parameters, etc. - EOpFunctionCall, - EOpFunction, // For function definition - EOpParameters, // an aggregate listing the parameters to a function - - EOpDeclaration, - EOpPrototype, - - // - // Unary operators - // - - EOpNegative, - EOpLogicalNot, - EOpVectorLogicalNot, - - EOpPostIncrement, - EOpPostDecrement, - EOpPreIncrement, - EOpPreDecrement, - - // - // binary operations - // - - EOpAdd, - EOpSub, - EOpMul, - EOpDiv, - EOpEqual, - EOpNotEqual, - EOpVectorEqual, - EOpVectorNotEqual, - EOpLessThan, - EOpGreaterThan, - EOpLessThanEqual, - EOpGreaterThanEqual, - EOpComma, - - EOpVectorTimesScalar, - EOpVectorTimesMatrix, - EOpMatrixTimesVector, - EOpMatrixTimesScalar, - - EOpLogicalOr, - EOpLogicalXor, - EOpLogicalAnd, - - EOpIndexDirect, - EOpIndexIndirect, - EOpIndexDirectStruct, - EOpIndexDirectInterfaceBlock, - - EOpVectorSwizzle, - - // - // Built-in functions potentially mapped to operators - // - - EOpRadians, - EOpDegrees, - EOpSin, - EOpCos, - EOpTan, - EOpAsin, - EOpAcos, - EOpAtan, - - EOpPow, - EOpExp, - EOpLog, - EOpExp2, - EOpLog2, - EOpSqrt, - EOpInverseSqrt, - - EOpAbs, - EOpSign, - EOpFloor, - EOpCeil, - EOpFract, - EOpMod, - EOpMin, - EOpMax, - EOpClamp, - EOpMix, - EOpStep, - EOpSmoothStep, - - 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 - - EOpMatrixTimesMatrix, - - EOpAny, - EOpAll, - - // - // Branch - // - - EOpKill, // Fragment only - EOpReturn, - EOpBreak, - EOpContinue, - - // - // Constructors - // - - EOpConstructInt, - EOpConstructUInt, - EOpConstructBool, - EOpConstructFloat, - EOpConstructVec2, - EOpConstructVec3, - EOpConstructVec4, - EOpConstructBVec2, - EOpConstructBVec3, - EOpConstructBVec4, - EOpConstructIVec2, - EOpConstructIVec3, - EOpConstructIVec4, - EOpConstructUVec2, - EOpConstructUVec3, - EOpConstructUVec4, - EOpConstructMat2, - EOpConstructMat3, - EOpConstructMat4, - EOpConstructStruct, - - // - // moves - // - - EOpAssign, - EOpInitialize, - EOpAddAssign, - EOpSubAssign, - EOpMulAssign, - EOpVectorTimesMatrixAssign, - EOpVectorTimesScalarAssign, - EOpMatrixTimesScalarAssign, - EOpMatrixTimesMatrixAssign, - EOpDivAssign -}; - -class TIntermTraverser; -class TIntermAggregate; -class TIntermBinary; -class TIntermUnary; -class TIntermConstantUnion; -class TIntermSelection; -class TIntermTyped; -class TIntermSymbol; -class TIntermLoop; -class TInfoSink; -class TIntermRaw; - -// -// Base class for the tree nodes -// -class TIntermNode -{ - 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 TIntermAggregate *getAsAggregate() { return 0; } - virtual TIntermBinary *getAsBinaryNode() { return 0; } - virtual TIntermUnary *getAsUnaryNode() { return 0; } - virtual TIntermSelection *getAsSelectionNode() { return 0; } - virtual TIntermSymbol *getAsSymbolNode() { return 0; } - virtual TIntermLoop *getAsLoopNode() { return 0; } - virtual TIntermRaw *getAsRawNode() { 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; - - // For traversing a tree in no particular order, but using - // heap memory. - virtual void enqueueChildren(std::queue *nodeQueue) const = 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 *getAsTyped() { return this; } +#ifndef COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ +#define COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ - virtual bool hasSideEffects() const = 0; +#include "compiler/translator/IntermNode.h" - void setType(const TType &t) { mType = 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(); } - 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(); } - const char *getQualifierString() const { return mType.getQualifierString(); } - TString getCompleteString() const { return mType.getCompleteString(); } - - int getArraySize() const { return mType.getArraySize(); } - - protected: - TType mType; -}; - -// -// Handle for, do-while, and while loops. -// -enum TLoopType +struct TVectorFields { - ELoopFor, - ELoopWhile, - ELoopDoWhile -}; - -class TIntermLoop : public TIntermNode -{ - public: - TIntermLoop(TLoopType type, - TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr, - TIntermNode *body) - : mType(type), - mInit(init), - mCond(cond), - mExpr(expr), - mBody(body), - mUnrollFlag(false) { } - - virtual TIntermLoop *getAsLoopNode() { return this; } - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - TLoopType getType() const { return mType; } - TIntermNode *getInit() { return mInit; } - TIntermTyped *getCondition() { return mCond; } - TIntermTyped *getExpression() { return mExpr; } - TIntermNode *getBody() { return mBody; } - - void setUnrollFlag(bool flag) { mUnrollFlag = flag; } - bool getUnrollFlag() const { return mUnrollFlag; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - - protected: - TLoopType mType; - TIntermNode *mInit; // for-loop initialization - TIntermTyped *mCond; // loop exit condition - TIntermTyped *mExpr; // for-loop expression - TIntermNode *mBody; // loop body - - bool mUnrollFlag; // Whether the loop should be unrolled or not. + int offsets[4]; + int num; }; // -// Handle break, continue, return, and kill. +// Set of helper functions to help parse and build the tree. // -class TIntermBranch : public TIntermNode -{ - public: - TIntermBranch(TOperator op, TIntermTyped *e) - : mFlowOp(op), - mExpression(e) { } - - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - TOperator getFlowOp() { return mFlowOp; } - TIntermTyped* getExpression() { return mExpression; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - -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(int id, const TString &symbol, const TType &type) - : TIntermTyped(type), - mId(id) - { - mSymbol = symbol; - } - - virtual bool hasSideEffects() const { return false; } - - int getId() const { return mId; } - const TString &getSymbol() const { return mSymbol; } - - void setId(int newId) { mId = newId; } - - virtual void traverse(TIntermTraverser *); - virtual TIntermSymbol *getAsSymbolNode() { return this; } - virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - - virtual void enqueueChildren(std::queue *nodeQueue) const {} - - protected: - int mId; - TString mSymbol; -}; - -// 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) { } - - virtual bool hasSideEffects() const { return false; } - - TString getRawText() const { return mRawText; } - - virtual void traverse(TIntermTraverser *); - - virtual TIntermRaw *getAsRawNode() { return this; } - virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - virtual void enqueueChildren(std::queue *nodeQueue) const {} - - protected: - TString mRawText; -}; - -class TIntermConstantUnion : public TIntermTyped -{ - public: - TIntermConstantUnion(ConstantUnion *unionPointer, const TType &type) - : TIntermTyped(type), - mUnionArrayPointer(unionPointer) { } - - virtual bool hasSideEffects() const { return false; } - - ConstantUnion *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; - } - - virtual TIntermConstantUnion *getAsConstantUnion() { return this; } - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - - TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &); - - virtual void enqueueChildren(std::queue *nodeQueue) const {} - - protected: - ConstantUnion *mUnionArrayPointer; -}; - -// -// Intermediate class for node types that hold operators. -// -class TIntermOperator : public TIntermTyped -{ - public: - TOperator getOp() const { return mOp; } - void setOp(TOperator op) { mOp = op; } - - bool isAssignment() const; - bool isConstructor() const; - - virtual bool hasSideEffects() const { return isAssignment(); } - - protected: - TIntermOperator(TOperator op) - : TIntermTyped(TType(EbtFloat, EbpUndefined)), - mOp(op) {} - TIntermOperator(TOperator op, const TType &type) - : TIntermTyped(type), - mOp(op) {} - - TOperator mOp; -}; - -// -// Nodes for all the basic binary math operators. -// -class TIntermBinary : public TIntermOperator -{ - public: - TIntermBinary(TOperator op) - : TIntermOperator(op), - mAddIndexClamp(false) {} - - virtual TIntermBinary *getAsBinaryNode() { return this; } - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - virtual bool hasSideEffects() const - { - return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects(); - } - - void setLeft(TIntermTyped *node) { mLeft = node; } - void setRight(TIntermTyped *node) { mRight = node; } - TIntermTyped *getLeft() const { return mLeft; } - TIntermTyped *getRight() const { return mRight; } - bool promote(TInfoSink &); - - void setAddIndexClamp() { mAddIndexClamp = true; } - bool getAddIndexClamp() { return mAddIndexClamp; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - - protected: - TIntermTyped* mLeft; - TIntermTyped* mRight; - - // If set to true, wrap any EOpIndexIndirect with a clamp to bounds. - bool mAddIndexClamp; -}; - -// -// Nodes for unary math operators. -// -class TIntermUnary : public TIntermOperator -{ - public: - TIntermUnary(TOperator op, const TType &type) - : TIntermOperator(op, type), - mOperand(NULL), - mUseEmulatedFunction(false) {} - TIntermUnary(TOperator op) - : TIntermOperator(op), - mOperand(NULL), - mUseEmulatedFunction(false) {} - - virtual void traverse(TIntermTraverser *); - virtual TIntermUnary *getAsUnaryNode() { return this; } - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - virtual bool hasSideEffects() const - { - return isAssignment() || mOperand->hasSideEffects(); - } - - void setOperand(TIntermTyped *operand) { mOperand = operand; } - TIntermTyped *getOperand() { return mOperand; } - bool promote(TInfoSink &); - - void setUseEmulatedFunction() { mUseEmulatedFunction = true; } - bool getUseEmulatedFunction() { return mUseEmulatedFunction; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - - protected: - TIntermTyped *mOperand; - - // If set to true, replace the built-in function call with an emulated one - // to work around driver bugs. - bool mUseEmulatedFunction; -}; - -typedef TVector TIntermSequence; -typedef TVector TQualifierList; - -// -// Nodes that operate on an arbitrary sized set of children. -// -class TIntermAggregate : public TIntermOperator -{ - public: - TIntermAggregate() - : TIntermOperator(EOpNull), - mUserDefined(false), - mUseEmulatedFunction(false) { } - TIntermAggregate(TOperator op) - : TIntermOperator(op), - mUseEmulatedFunction(false) { } - ~TIntermAggregate() { } - - virtual TIntermAggregate *getAsAggregate() { return this; } - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - // Conservatively assume function calls and other aggregate operators have side-effects - virtual bool hasSideEffects() const { return true; } - - TIntermSequence *getSequence() { return &mSequence; } - - void setName(const TString &name) { mName = name; } - const TString &getName() const { return mName; } - - void setUserDefined() { mUserDefined = true; } - bool isUserDefined() const { return mUserDefined; } - - void setOptimize(bool optimize) { mOptimize = optimize; } - bool getOptimize() const { return mOptimize; } - void setDebug(bool debug) { mDebug = debug; } - bool getDebug() const { return mDebug; } - - void setUseEmulatedFunction() { mUseEmulatedFunction = true; } - bool getUseEmulatedFunction() { return mUseEmulatedFunction; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - - protected: - TIntermAggregate(const TIntermAggregate &); // disallow copy constructor - TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator - TIntermSequence mSequence; - TString mName; - bool mUserDefined; // used for user defined function names - - bool mOptimize; - bool mDebug; - - // If set to true, replace the built-in function call with an emulated one - // to work around driver bugs. - bool mUseEmulatedFunction; -}; - -// -// For if tests. Simplified since there is no switch statement. -// -class TIntermSelection : public TIntermTyped -{ - public: - TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB) - : TIntermTyped(TType(EbtVoid, EbpUndefined)), - mCondition(cond), - mTrueBlock(trueB), - mFalseBlock(falseB) {} - TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB, - const TType &type) - : TIntermTyped(type), - mCondition(cond), - mTrueBlock(trueB), - mFalseBlock(falseB) {} - - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - // Conservatively assume selections have side-effects - virtual bool hasSideEffects() const { return true; } - - bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } - TIntermNode *getCondition() const { return mCondition; } - TIntermNode *getTrueBlock() const { return mTrueBlock; } - TIntermNode *getFalseBlock() const { return mFalseBlock; } - TIntermSelection *getAsSelectionNode() { return this; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - -protected: - TIntermTyped *mCondition; - TIntermNode *mTrueBlock; - TIntermNode *mFalseBlock; -}; - -enum Visit -{ - PreVisit, - InVisit, - PostVisit -}; - -// -// For traversing the tree. User should derive from this, -// put their traversal specific data in it, and then pass -// it to a Traverse method. -// -// 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 -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - // TODO(zmo): remove default values. - TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, - bool rightToLeft = false) - : preVisit(preVisit), - inVisit(inVisit), - postVisit(postVisit), - rightToLeft(rightToLeft), - mDepth(0), - mMaxDepth(0) {} - virtual ~TIntermTraverser() {} - - virtual void visitSymbol(TIntermSymbol *) {} - virtual void visitRaw(TIntermRaw *) {} - virtual void visitConstantUnion(TIntermConstantUnion *) {} - virtual bool visitBinary(Visit, TIntermBinary *) { return true; } - virtual bool visitUnary(Visit, TIntermUnary *) { return true; } - virtual bool visitSelection(Visit, TIntermSelection *) { return true; } - virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; } - virtual bool visitLoop(Visit, TIntermLoop *) { return true; } - virtual bool visitBranch(Visit, TIntermBranch *) { return true; } - - int getMaxDepth() const { return mMaxDepth; } - - void incrementDepth(TIntermNode *current) - { - mDepth++; - mMaxDepth = std::max(mMaxDepth, mDepth); - mPath.push_back(current); - } - - void decrementDepth() - { - mDepth--; - mPath.pop_back(); - } - - TIntermNode *getParentNode() - { - return mPath.size() == 0 ? NULL : mPath.back(); - } - - // Return the original name if hash function pointer is NULL; - // otherwise return the hashed name. - static TString hash(const TString& name, ShHashFunction64 hashFunction); - - const bool preVisit; - const bool inVisit; - const bool postVisit; - const bool rightToLeft; - - protected: - int mDepth; - int mMaxDepth; - - // All the nodes from root to the current node's parent during traversing. - TVector mPath; -}; - -// -// For traversing the tree, and computing max depth. -// Takes a maximum depth limit to prevent stack overflow. -// -class TMaxDepthTraverser : public TIntermTraverser +class TInfoSink; +class TIntermediate { public: POOL_ALLOCATOR_NEW_DELETE(); - TMaxDepthTraverser(int depthLimit) - : TIntermTraverser(true, true, false, false), - mDepthLimit(depthLimit) { } - - virtual bool visitBinary(Visit, TIntermBinary *) { return depthCheck(); } - virtual bool visitUnary(Visit, TIntermUnary *) { return depthCheck(); } - virtual bool visitSelection(Visit, TIntermSelection *) { return depthCheck(); } - virtual bool visitAggregate(Visit, TIntermAggregate *) { return depthCheck(); } - virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); } - virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); } - -protected: - bool depthCheck() const { return mMaxDepth < mDepthLimit; } - - int mDepthLimit; -}; - -#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_ + TIntermediate(TInfoSink &i) + : mInfoSink(i) { } + + TIntermSymbol *addSymbol( + int id, const TString &, const TType &, const TSourceLoc &); + TIntermTyped *addBinaryMath( + TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); + TIntermTyped *addAssign( + TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); + TIntermTyped *addIndex( + TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &); + TIntermTyped *addUnaryMath( + TOperator op, TIntermNode *child, const TSourceLoc &); + TIntermAggregate *growAggregate( + TIntermNode *left, TIntermNode *right, const TSourceLoc &); + TIntermAggregate *makeAggregate(TIntermNode *node, const TSourceLoc &); + TIntermAggregate *setAggregateOperator(TIntermNode *, TOperator, const TSourceLoc &); + TIntermNode *addSelection(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &); + TIntermTyped *addSelection( + TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &); + TIntermTyped *addComma( + TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); + TIntermConstantUnion *addConstantUnion(ConstantUnion *, const TType &, const TSourceLoc &); + // TODO(zmo): Get rid of default value. + bool parseConstTree(const TSourceLoc &, TIntermNode *, ConstantUnion *, + TOperator, TType, bool singleConstantParam = false); + TIntermNode *addLoop(TLoopType, TIntermNode *, TIntermTyped *, TIntermTyped *, + TIntermNode *, const TSourceLoc &); + TIntermBranch *addBranch(TOperator, const TSourceLoc &); + TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &); + TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &); + bool postProcess(TIntermNode *); + void remove(TIntermNode *); + void outputTree(TIntermNode *); + + private: + void operator=(TIntermediate &); // prevent assignments + + TInfoSink & mInfoSink; +}; + +#endif // COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/localintermediate.h b/src/3rdparty/angle/src/compiler/translator/localintermediate.h deleted file mode 100644 index 0809bbd362..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/localintermediate.h +++ /dev/null @@ -1,67 +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_LOCAL_INTERMEDIATE_H_ -#define COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ - -#include "compiler/translator/intermediate.h" - -struct TVectorFields -{ - int offsets[4]; - int num; -}; - -// -// Set of helper functions to help parse and build the tree. -// -class TInfoSink; -class TIntermediate -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TIntermediate(TInfoSink &i) - : mInfoSink(i) { } - - TIntermSymbol *addSymbol( - int id, const TString &, const TType &, const TSourceLoc &); - TIntermTyped *addBinaryMath( - TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); - TIntermTyped *addAssign( - TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); - TIntermTyped *addIndex( - TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &); - TIntermTyped *addUnaryMath( - TOperator op, TIntermNode *child, const TSourceLoc &); - TIntermAggregate *growAggregate( - TIntermNode *left, TIntermNode *right, const TSourceLoc &); - TIntermAggregate *makeAggregate(TIntermNode *node, const TSourceLoc &); - TIntermAggregate *setAggregateOperator(TIntermNode *, TOperator, const TSourceLoc &); - TIntermNode *addSelection(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &); - TIntermTyped *addSelection( - TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &); - TIntermTyped *addComma( - TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); - TIntermConstantUnion *addConstantUnion(ConstantUnion *, const TType &, const TSourceLoc &); - // TODO(zmo): Get rid of default value. - bool parseConstTree(const TSourceLoc &, TIntermNode *, ConstantUnion *, - TOperator, TType, bool singleConstantParam = false); - TIntermNode *addLoop(TLoopType, TIntermNode *, TIntermTyped *, TIntermTyped *, - TIntermNode *, const TSourceLoc &); - TIntermBranch *addBranch(TOperator, const TSourceLoc &); - TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &); - TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &); - bool postProcess(TIntermNode *); - void remove(TIntermNode *); - void outputTree(TIntermNode *); - - private: - void operator=(TIntermediate &); // prevent assignments - - TInfoSink & mInfoSink; -}; - -#endif // COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h index e77d8c21cb..80d5f7fa7f 100644 --- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ #define COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/depgraph/DependencyGraph.h" class TInfoSinkBase; diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h index d461fbdbfe..a6263567b4 100644 --- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ #define COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/InfoSink.h" class TInfoSinkBase; diff --git a/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp index 561d4e007c..f74c7d1173 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.cpp +++ b/src/3rdparty/angle/src/compiler/translator/util.cpp @@ -9,7 +9,6 @@ #include #include "compiler/preprocessor/numeric_lex.h" -#include "common/shadervars.h" #include "common/utilities.h" bool atof_clamp(const char *str, float *value) @@ -269,6 +268,8 @@ InterpolationType GetInterpolationType(TQualifier qualifier) case EvqFragmentIn: case EvqVaryingIn: case EvqVaryingOut: + case EvqInvariantVaryingIn: + case EvqInvariantVaryingOut: return INTERPOLATION_SMOOTH; case EvqCentroidIn: @@ -281,7 +282,7 @@ InterpolationType GetInterpolationType(TQualifier qualifier) } template -void GetVariableTraverser::traverse(const TType &type, const TString &name) +void GetVariableTraverser::traverse(const TType &type, const TString &name, std::vector *output) { const TStructure *structure = type.getStruct(); @@ -296,61 +297,27 @@ void GetVariableTraverser::traverse(const TType &type, const TString &name } else { + // Note: this enum value is not exposed outside ANGLE variable.type = GL_STRUCT_ANGLEX; - - mOutputStack.push(&variable.fields); + variable.structName = structure->name().c_str(); const TFieldList &fields = structure->fields(); for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) { TField *field = fields[fieldIndex]; - traverse(*field->type(), field->name()); + traverse(*field->type(), field->name(), &variable.fields); } - - mOutputStack.pop(); } visitVariable(&variable); - ASSERT(!mOutputStack.empty()); - mOutputStack.top()->push_back(variable); -} - -template -GetVariableTraverser::GetVariableTraverser(std::vector *output) -{ ASSERT(output); - mOutputStack.push(output); + output->push_back(variable); } -template class GetVariableTraverser; -template class GetVariableTraverser; -template class GetVariableTraverser; - -GetInterfaceBlockFieldTraverser::GetInterfaceBlockFieldTraverser(std::vector *output, bool isRowMajorMatrix) - : GetVariableTraverser(output), - mIsRowMajorMatrix(isRowMajorMatrix) -{ -} - -void GetInterfaceBlockFieldTraverser::visitVariable(InterfaceBlockField *newField) -{ - if (gl::IsMatrixType(newField->type)) - { - newField->isRowMajorMatrix = mIsRowMajorMatrix; - } -} - -BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage) -{ - switch (blockStorage) - { - case EbsPacked: return BLOCKLAYOUT_PACKED; - case EbsShared: return BLOCKLAYOUT_SHARED; - case EbsStd140: return BLOCKLAYOUT_STANDARD; - default: UNREACHABLE(); return BLOCKLAYOUT_SHARED; - } -} +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector *); +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector *); +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector *); } diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h index 5c214dd4fb..241e2cc1c2 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.h +++ b/src/3rdparty/angle/src/compiler/translator/util.h @@ -9,9 +9,10 @@ #include -#include "compiler/translator/Types.h" #include "angle_gl.h" -#include "common/shadervars.h" +#include + +#include "compiler/translator/Types.h" // atof_clamp is like atof but // 1. it forces C locale, i.e. forcing '.' as decimal point. @@ -32,33 +33,22 @@ bool IsVaryingIn(TQualifier qualifier); bool IsVaryingOut(TQualifier qualifier); bool IsVarying(TQualifier qualifier); InterpolationType GetInterpolationType(TQualifier qualifier); -BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage); TString ArrayString(const TType &type); -template class GetVariableTraverser { public: - GetVariableTraverser(std::vector *output); - void traverse(const TType &type, const TString &name); + GetVariableTraverser() {} + + template + void traverse(const TType &type, const TString &name, std::vector *output); protected: // May be overloaded - virtual void visitVariable(VarT *newVar) {} + virtual void visitVariable(ShaderVariable *newVar) {} private: - std::stack *> mOutputStack; -}; - -struct GetInterfaceBlockFieldTraverser : public GetVariableTraverser -{ - public: - GetInterfaceBlockFieldTraverser(std::vector *output, bool isRowMajorMatrix); - - private: - virtual void visitVariable(InterfaceBlockField *newField); - - bool mIsRowMajorMatrix; + DISALLOW_COPY_AND_ASSIGN(GetVariableTraverser); }; } -- cgit v1.2.3