diff options
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator')
212 files changed, 0 insertions, 55469 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp deleted file mode 100644 index b04fc28259..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp +++ /dev/null @@ -1,462 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Analysis of the AST needed for HLSL generation - -#include "compiler/translator/ASTMetadataHLSL.h" - -#include "compiler/translator/CallDAG.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -// Class used to traverse the AST of a function definition, checking if the -// function uses a gradient, and writing the set of control flow using gradients. -// It assumes that the analysis has already been made for the function's -// callees. -class PullGradient : public TIntermTraverser -{ - public: - PullGradient(MetadataList *metadataList, size_t index, const CallDAG &dag) - : TIntermTraverser(true, false, true), - mMetadataList(metadataList), - mMetadata(&(*metadataList)[index]), - mIndex(index), - mDag(dag) - { - ASSERT(index < metadataList->size()); - - // ESSL 100 builtin gradient functions - mGradientBuiltinFunctions.insert("texture2D"); - mGradientBuiltinFunctions.insert("texture2DProj"); - mGradientBuiltinFunctions.insert("textureCube"); - - // ESSL 300 builtin gradient functions - mGradientBuiltinFunctions.insert("texture"); - mGradientBuiltinFunctions.insert("textureProj"); - mGradientBuiltinFunctions.insert("textureOffset"); - mGradientBuiltinFunctions.insert("textureProjOffset"); - - // ESSL 310 doesn't add builtin gradient functions - } - - void traverse(TIntermFunctionDefinition *node) - { - node->traverse(this); - ASSERT(mParents.empty()); - } - - // Called when a gradient operation or a call to a function using a gradient is found. - void onGradient() - { - mMetadata->mUsesGradient = true; - // Mark the latest control flow as using a gradient. - if (!mParents.empty()) - { - mMetadata->mControlFlowsContainingGradient.insert(mParents.back()); - } - } - - void visitControlFlow(Visit visit, TIntermNode *node) - { - if (visit == PreVisit) - { - mParents.push_back(node); - } - else if (visit == PostVisit) - { - ASSERT(mParents.back() == node); - mParents.pop_back(); - // A control flow's using a gradient means its parents are too. - if (mMetadata->mControlFlowsContainingGradient.count(node) > 0 && !mParents.empty()) - { - mMetadata->mControlFlowsContainingGradient.insert(mParents.back()); - } - } - } - - bool visitLoop(Visit visit, TIntermLoop *loop) override - { - visitControlFlow(visit, loop); - return true; - } - - bool visitIfElse(Visit visit, TIntermIfElse *ifElse) override - { - visitControlFlow(visit, ifElse); - return true; - } - - bool visitUnary(Visit visit, TIntermUnary *node) override - { - if (visit == PreVisit) - { - switch (node->getOp()) - { - case EOpDFdx: - case EOpDFdy: - case EOpFwidth: - onGradient(); - default: - break; - } - } - - return true; - } - - bool visitAggregate(Visit visit, TIntermAggregate *node) override - { - if (visit == PreVisit) - { - if (node->getOp() == EOpCallFunctionInAST) - { - size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo()); - ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex); - - if ((*mMetadataList)[calleeIndex].mUsesGradient) - { - onGradient(); - } - } - else if (node->getOp() == EOpCallBuiltInFunction) - { - if (mGradientBuiltinFunctions.find(node->getFunctionSymbolInfo()->getName()) != - mGradientBuiltinFunctions.end()) - { - onGradient(); - } - } - } - - return true; - } - - private: - MetadataList *mMetadataList; - ASTMetadataHLSL *mMetadata; - size_t mIndex; - const CallDAG &mDag; - - // Contains a stack of the control flow nodes that are parents of the node being - // currently visited. It is used to mark control flows using a gradient. - std::vector<TIntermNode *> mParents; - - // A list of builtin functions that use gradients - std::set<TString> mGradientBuiltinFunctions; -}; - -// Traverses the AST of a function definition to compute the the discontinuous loops -// and the if statements containing gradient loops. It assumes that the gradient loops -// (loops that contain a gradient) have already been computed and that it has already -// traversed the current function's callees. -class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser -{ - public: - PullComputeDiscontinuousAndGradientLoops(MetadataList *metadataList, - size_t index, - const CallDAG &dag) - : TIntermTraverser(true, false, true), - mMetadataList(metadataList), - mMetadata(&(*metadataList)[index]), - mIndex(index), - mDag(dag) - { - } - - void traverse(TIntermFunctionDefinition *node) - { - node->traverse(this); - ASSERT(mLoopsAndSwitches.empty()); - ASSERT(mIfs.empty()); - } - - // Called when traversing a gradient loop or a call to a function with a - // gradient loop in its call graph. - void onGradientLoop() - { - mMetadata->mHasGradientLoopInCallGraph = true; - // Mark the latest if as using a discontinuous loop. - if (!mIfs.empty()) - { - mMetadata->mIfsContainingGradientLoop.insert(mIfs.back()); - } - } - - bool visitLoop(Visit visit, TIntermLoop *loop) override - { - if (visit == PreVisit) - { - mLoopsAndSwitches.push_back(loop); - - if (mMetadata->hasGradientInCallGraph(loop)) - { - onGradientLoop(); - } - } - else if (visit == PostVisit) - { - ASSERT(mLoopsAndSwitches.back() == loop); - mLoopsAndSwitches.pop_back(); - } - - return true; - } - - bool visitIfElse(Visit visit, TIntermIfElse *node) override - { - if (visit == PreVisit) - { - mIfs.push_back(node); - } - else if (visit == PostVisit) - { - ASSERT(mIfs.back() == node); - mIfs.pop_back(); - // An if using a discontinuous loop means its parents ifs are also discontinuous. - if (mMetadata->mIfsContainingGradientLoop.count(node) > 0 && !mIfs.empty()) - { - mMetadata->mIfsContainingGradientLoop.insert(mIfs.back()); - } - } - - return true; - } - - bool visitBranch(Visit visit, TIntermBranch *node) override - { - if (visit == PreVisit) - { - switch (node->getFlowOp()) - { - case EOpBreak: - { - ASSERT(!mLoopsAndSwitches.empty()); - TIntermLoop *loop = mLoopsAndSwitches.back()->getAsLoopNode(); - if (loop != nullptr) - { - mMetadata->mDiscontinuousLoops.insert(loop); - } - } - break; - case EOpContinue: - { - ASSERT(!mLoopsAndSwitches.empty()); - TIntermLoop *loop = nullptr; - size_t i = mLoopsAndSwitches.size(); - while (loop == nullptr && i > 0) - { - --i; - loop = mLoopsAndSwitches.at(i)->getAsLoopNode(); - } - ASSERT(loop != nullptr); - mMetadata->mDiscontinuousLoops.insert(loop); - } - break; - case EOpKill: - case EOpReturn: - // A return or discard jumps out of all the enclosing loops - if (!mLoopsAndSwitches.empty()) - { - for (TIntermNode *intermNode : mLoopsAndSwitches) - { - TIntermLoop *loop = intermNode->getAsLoopNode(); - if (loop) - { - mMetadata->mDiscontinuousLoops.insert(loop); - } - } - } - break; - default: - UNREACHABLE(); - } - } - - return true; - } - - bool visitAggregate(Visit visit, TIntermAggregate *node) override - { - if (visit == PreVisit && node->getOp() == EOpCallFunctionInAST) - { - size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo()); - ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex); - - if ((*mMetadataList)[calleeIndex].mHasGradientLoopInCallGraph) - { - onGradientLoop(); - } - } - - return true; - } - - bool visitSwitch(Visit visit, TIntermSwitch *node) override - { - if (visit == PreVisit) - { - mLoopsAndSwitches.push_back(node); - } - else if (visit == PostVisit) - { - ASSERT(mLoopsAndSwitches.back() == node); - mLoopsAndSwitches.pop_back(); - } - return true; - } - - private: - MetadataList *mMetadataList; - ASTMetadataHLSL *mMetadata; - size_t mIndex; - const CallDAG &mDag; - - std::vector<TIntermNode *> mLoopsAndSwitches; - std::vector<TIntermIfElse *> mIfs; -}; - -// Tags all the functions called in a discontinuous loop -class PushDiscontinuousLoops : public TIntermTraverser -{ - public: - PushDiscontinuousLoops(MetadataList *metadataList, size_t index, const CallDAG &dag) - : TIntermTraverser(true, true, true), - mMetadataList(metadataList), - mMetadata(&(*metadataList)[index]), - mIndex(index), - mDag(dag), - mNestedDiscont(mMetadata->mCalledInDiscontinuousLoop ? 1 : 0) - { - } - - void traverse(TIntermFunctionDefinition *node) - { - node->traverse(this); - ASSERT(mNestedDiscont == (mMetadata->mCalledInDiscontinuousLoop ? 1 : 0)); - } - - bool visitLoop(Visit visit, TIntermLoop *loop) override - { - bool isDiscontinuous = mMetadata->mDiscontinuousLoops.count(loop) > 0; - - if (visit == PreVisit && isDiscontinuous) - { - mNestedDiscont++; - } - else if (visit == PostVisit && isDiscontinuous) - { - mNestedDiscont--; - } - - return true; - } - - bool visitAggregate(Visit visit, TIntermAggregate *node) override - { - switch (node->getOp()) - { - case EOpCallFunctionInAST: - if (visit == PreVisit && mNestedDiscont > 0) - { - size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo()); - ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex); - - (*mMetadataList)[calleeIndex].mCalledInDiscontinuousLoop = true; - } - break; - default: - break; - } - return true; - } - - private: - MetadataList *mMetadataList; - ASTMetadataHLSL *mMetadata; - size_t mIndex; - const CallDAG &mDag; - - int mNestedDiscont; -}; -} - -bool ASTMetadataHLSL::hasGradientInCallGraph(TIntermLoop *node) -{ - return mControlFlowsContainingGradient.count(node) > 0; -} - -bool ASTMetadataHLSL::hasGradientLoop(TIntermIfElse *node) -{ - return mIfsContainingGradientLoop.count(node) > 0; -} - -MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag) -{ - MetadataList metadataList(callDag.size()); - - // Compute all the information related to when gradient operations are used. - // We want to know for each function and control flow operation if they have - // a gradient operation in their call graph (shortened to "using a gradient" - // in the rest of the file). - // - // This computation is logically split in three steps: - // 1 - For each function compute if it uses a gradient in its body, ignoring - // calls to other user-defined functions. - // 2 - For each function determine if it uses a gradient in its call graph, - // using the result of step 1 and the CallDAG to know its callees. - // 3 - For each control flow statement of each function, check if it uses a - // gradient in the function's body, or if it calls a user-defined function that - // uses a gradient. - // - // We take advantage of the call graph being a DAG and instead compute 1, 2 and 3 - // for leaves first, then going down the tree. This is correct because 1 doesn't - // depend on other functions, and 2 and 3 depend only on callees. - for (size_t i = 0; i < callDag.size(); i++) - { - PullGradient pull(&metadataList, i, callDag); - pull.traverse(callDag.getRecordFromIndex(i).node); - } - - // Compute which loops are discontinuous and which function are called in - // these loops. The same way computing gradient usage is a "pull" process, - // computing "bing used in a discont. loop" is a push process. However we also - // need to know what ifs have a discontinuous loop inside so we do the same type - // of callgraph analysis as for the gradient. - - // First compute which loops are discontinuous (no specific order) and pull - // the ifs and functions using a gradient loop. - for (size_t i = 0; i < callDag.size(); i++) - { - PullComputeDiscontinuousAndGradientLoops pull(&metadataList, i, callDag); - pull.traverse(callDag.getRecordFromIndex(i).node); - } - - // Then push the information to callees, either from the a local discontinuous - // loop or from the caller being called in a discontinuous loop already - for (size_t i = callDag.size(); i-- > 0;) - { - PushDiscontinuousLoops push(&metadataList, i, callDag); - push.traverse(callDag.getRecordFromIndex(i).node); - } - - // We create "Lod0" version of functions with the gradient operations replaced - // by non-gradient operations so that the D3D compiler is happier with discont - // loops. - for (auto &metadata : metadataList) - { - metadata.mNeedsLod0 = metadata.mCalledInDiscontinuousLoop && metadata.mUsesGradient; - } - - return metadataList; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h b/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h deleted file mode 100644 index 550a522b86..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Defines analyses of the AST needed for HLSL generation - -#ifndef COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_ -#define COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_ - -#include <set> -#include <vector> - -namespace sh -{ - -class CallDAG; -class TIntermNode; -class TIntermIfElse; -class TIntermLoop; - -struct ASTMetadataHLSL -{ - ASTMetadataHLSL() - : mUsesGradient(false), - mCalledInDiscontinuousLoop(false), - mHasGradientLoopInCallGraph(false), - mNeedsLod0(false) - { - } - - // Here "something uses a gradient" means here that it either contains a - // gradient operation, or a call to a function that uses a gradient. - bool hasGradientInCallGraph(TIntermLoop *node); - bool hasGradientLoop(TIntermIfElse *node); - - // Does the function use a gradient. - bool mUsesGradient; - - // Even if usesGradient is true, some control flow might not use a gradient - // so we store the set of all gradient-using control flows. - std::set<TIntermNode *> mControlFlowsContainingGradient; - - // Remember information about the discontinuous loops and which functions - // are called in such loops. - bool mCalledInDiscontinuousLoop; - bool mHasGradientLoopInCallGraph; - std::set<TIntermLoop *> mDiscontinuousLoops; - std::set<TIntermIfElse *> mIfsContainingGradientLoop; - - // Will we need to generate a Lod0 version of the function. - bool mNeedsLod0; -}; - -typedef std::vector<ASTMetadataHLSL> MetadataList; - -// Return the AST analysis result, in the order defined by the call DAG -MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp b/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp deleted file mode 100644 index 6a05104233..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/AddAndTrueToLoopCondition.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -// An AST traverser that rewrites for and while loops by replacing "condition" with -// "condition && true" to work around condition bug on Intel Mac. -class AddAndTrueToLoopConditionTraverser : public TIntermTraverser -{ - public: - AddAndTrueToLoopConditionTraverser() : TIntermTraverser(true, false, false) {} - - bool visitLoop(Visit, TIntermLoop *loop) override - { - // do-while loop doesn't have this bug. - if (loop->getType() != ELoopFor && loop->getType() != ELoopWhile) - { - return true; - } - - // For loop may not have a condition. - if (loop->getCondition() == nullptr) - { - return true; - } - - // Constant true. - TConstantUnion *trueConstant = new TConstantUnion(); - trueConstant->setBConst(true); - TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, TType(EbtBool)); - - // CONDITION && true. - TIntermBinary *andOp = new TIntermBinary(EOpLogicalAnd, loop->getCondition(), trueValue); - loop->setCondition(andOp); - - return true; - } -}; - -} // anonymous namespace - -void AddAndTrueToLoopCondition(TIntermNode *root) -{ - AddAndTrueToLoopConditionTraverser traverser; - root->traverse(&traverser); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h b/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h deleted file mode 100644 index 34debe0ed9..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Rewrite condition in for and while loops to work around driver bug on Intel Mac. - -#ifndef COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_ -#define COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_ - -class TIntermNode; -namespace sh -{ - -void AddAndTrueToLoopCondition(TIntermNode *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp b/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp deleted file mode 100644 index 4dfe60c0bc..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// AddDefaultReturnStatements.cpp: Add default return statements to functions that do not end in a -// return. -// - -#include "compiler/translator/AddDefaultReturnStatements.h" - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -bool NeedsReturnStatement(TIntermFunctionDefinition *node, TType *returnType) -{ - *returnType = node->getFunctionPrototype()->getType(); - if (returnType->getBasicType() == EbtVoid) - { - return false; - } - - TIntermBlock *bodyNode = node->getBody(); - TIntermBranch *returnNode = bodyNode->getSequence()->back()->getAsBranchNode(); - if (returnNode != nullptr && returnNode->getFlowOp() == EOpReturn) - { - return false; - } - - return true; -} - -} // anonymous namespace - -void AddDefaultReturnStatements(TIntermBlock *root) -{ - TType returnType; - for (TIntermNode *node : *root->getSequence()) - { - TIntermFunctionDefinition *definition = node->getAsFunctionDefinition(); - if (definition != nullptr && NeedsReturnStatement(definition, &returnType)) - { - TIntermBranch *branch = new TIntermBranch(EOpReturn, CreateZeroNode(returnType)); - - TIntermBlock *bodyNode = definition->getBody(); - bodyNode->getSequence()->push_back(branch); - } - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h b/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h deleted file mode 100644 index 40a70ad8c2..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// AddDefaultReturnStatements.h: Add default return statements to functions that do not end in a -// return. -// - -#ifndef COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_ -#define COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_ - -class TIntermBlock; - -namespace sh -{ - -void AddDefaultReturnStatements(TIntermBlock *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp b/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp deleted file mode 100644 index 17721fb0dc..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp +++ /dev/null @@ -1,213 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The ArrayReturnValueToOutParameter function changes return values of an array type to out -// parameters in function definitions, prototypes, and call sites. - -#include "compiler/translator/ArrayReturnValueToOutParameter.h" - -#include <map> - -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -void CopyAggregateChildren(TIntermAggregateBase *from, TIntermAggregateBase *to) -{ - const TIntermSequence *fromSequence = from->getSequence(); - for (size_t ii = 0; ii < fromSequence->size(); ++ii) - { - to->getSequence()->push_back(fromSequence->at(ii)); - } -} - -TIntermSymbol *CreateReturnValueSymbol(const TSymbolUniqueId &id, const TType &type) -{ - TIntermSymbol *node = new TIntermSymbol(id, "angle_return", type); - node->setInternal(true); - node->getTypePointer()->setQualifier(EvqOut); - return node; -} - -TIntermAggregate *CreateReplacementCall(TIntermAggregate *originalCall, - TIntermTyped *returnValueTarget) -{ - TIntermSequence *replacementArguments = new TIntermSequence(); - TIntermSequence *originalArguments = originalCall->getSequence(); - for (auto &arg : *originalArguments) - { - replacementArguments->push_back(arg); - } - replacementArguments->push_back(returnValueTarget); - TIntermAggregate *replacementCall = TIntermAggregate::CreateFunctionCall( - TType(EbtVoid), originalCall->getFunctionSymbolInfo()->getId(), - originalCall->getFunctionSymbolInfo()->getNameObj(), replacementArguments); - replacementCall->setLine(originalCall->getLine()); - return replacementCall; -} - -class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser -{ - public: - static void apply(TIntermNode *root, TSymbolTable *symbolTable); - - private: - ArrayReturnValueToOutParameterTraverser(TSymbolTable *symbolTable); - - bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitBranch(Visit visit, TIntermBranch *node) override; - bool visitBinary(Visit visit, TIntermBinary *node) override; - - // Set when traversal is inside a function with array return value. - TIntermFunctionDefinition *mFunctionWithArrayReturnValue; - - // Map from function symbol ids to array return value ids. - std::map<int, TSymbolUniqueId *> mReturnValueIds; -}; - -void ArrayReturnValueToOutParameterTraverser::apply(TIntermNode *root, TSymbolTable *symbolTable) -{ - ArrayReturnValueToOutParameterTraverser arrayReturnValueToOutParam(symbolTable); - root->traverse(&arrayReturnValueToOutParam); - arrayReturnValueToOutParam.updateTree(); -} - -ArrayReturnValueToOutParameterTraverser::ArrayReturnValueToOutParameterTraverser( - TSymbolTable *symbolTable) - : TIntermTraverser(true, false, true, symbolTable), mFunctionWithArrayReturnValue(nullptr) -{ -} - -bool ArrayReturnValueToOutParameterTraverser::visitFunctionDefinition( - Visit visit, - TIntermFunctionDefinition *node) -{ - if (node->getFunctionPrototype()->isArray() && visit == PreVisit) - { - // Replacing the function header is done on visitFunctionPrototype(). - mFunctionWithArrayReturnValue = node; - } - if (visit == PostVisit) - { - mFunctionWithArrayReturnValue = nullptr; - } - return true; -} - -bool ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(Visit visit, - TIntermFunctionPrototype *node) -{ - if (visit == PreVisit && node->isArray()) - { - // Replace the whole prototype node with another node that has the out parameter - // added. Also set the function to return void. - TIntermFunctionPrototype *replacement = - new TIntermFunctionPrototype(TType(EbtVoid), node->getFunctionSymbolInfo()->getId()); - CopyAggregateChildren(node, replacement); - const TSymbolUniqueId &functionId = node->getFunctionSymbolInfo()->getId(); - if (mReturnValueIds.find(functionId.get()) == mReturnValueIds.end()) - { - mReturnValueIds[functionId.get()] = new TSymbolUniqueId(mSymbolTable); - } - replacement->getSequence()->push_back( - CreateReturnValueSymbol(*mReturnValueIds[functionId.get()], node->getType())); - *replacement->getFunctionSymbolInfo() = *node->getFunctionSymbolInfo(); - replacement->setLine(node->getLine()); - - queueReplacement(replacement, OriginalNode::IS_DROPPED); - } - return false; -} - -bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - ASSERT(!node->isArray() || node->getOp() != EOpCallInternalRawFunction); - if (visit == PreVisit && node->isArray() && node->getOp() == EOpCallFunctionInAST) - { - // Handle call sites where the returned array is not assigned. - // Examples where f() is a function returning an array: - // 1. f(); - // 2. another_array == f(); - // 3. another_function(f()); - // 4. return f(); - // Cases 2 to 4 are already converted to simpler cases by - // SeparateExpressionsReturningArrays, so we only need to worry about the case where a - // function call returning an array forms an expression by itself. - TIntermBlock *parentBlock = getParentNode()->getAsBlock(); - if (parentBlock) - { - nextTemporaryId(); - TIntermSequence replacements; - replacements.push_back(createTempDeclaration(node->getType())); - TIntermSymbol *returnSymbol = createTempSymbol(node->getType()); - replacements.push_back(CreateReplacementCall(node, returnSymbol)); - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(parentBlock, node, replacements)); - } - return false; - } - return true; -} - -bool ArrayReturnValueToOutParameterTraverser::visitBranch(Visit visit, TIntermBranch *node) -{ - if (mFunctionWithArrayReturnValue && node->getFlowOp() == EOpReturn) - { - // Instead of returning a value, assign to the out parameter and then return. - TIntermSequence replacements; - - TIntermTyped *expression = node->getExpression(); - ASSERT(expression != nullptr); - const TSymbolUniqueId &functionId = - mFunctionWithArrayReturnValue->getFunctionSymbolInfo()->getId(); - ASSERT(mReturnValueIds.find(functionId.get()) != mReturnValueIds.end()); - const TSymbolUniqueId &returnValueId = *mReturnValueIds[functionId.get()]; - TIntermSymbol *returnValueSymbol = - CreateReturnValueSymbol(returnValueId, expression->getType()); - TIntermBinary *replacementAssignment = - new TIntermBinary(EOpAssign, returnValueSymbol, expression); - replacementAssignment->setLine(expression->getLine()); - replacements.push_back(replacementAssignment); - - TIntermBranch *replacementBranch = new TIntermBranch(EOpReturn, nullptr); - replacementBranch->setLine(node->getLine()); - replacements.push_back(replacementBranch); - - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, replacements)); - } - return false; -} - -bool ArrayReturnValueToOutParameterTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - if (node->getOp() == EOpAssign && node->getLeft()->isArray()) - { - TIntermAggregate *rightAgg = node->getRight()->getAsAggregate(); - ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpCallInternalRawFunction); - if (rightAgg != nullptr && rightAgg->getOp() == EOpCallFunctionInAST) - { - TIntermAggregate *replacementCall = CreateReplacementCall(rightAgg, node->getLeft()); - queueReplacement(replacementCall, OriginalNode::IS_DROPPED); - } - } - return false; -} - -} // namespace - -void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable) -{ - ArrayReturnValueToOutParameterTraverser::apply(root, symbolTable); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h b/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h deleted file mode 100644 index 469c7a3b14..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The ArrayReturnValueToOutParameter function changes return values of an array type to out -// parameters in function definitions, prototypes and call sites. - -#ifndef COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_ -#define COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_ - -namespace sh -{ - -class TIntermNode; -class TSymbolTable; - -void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h deleted file mode 100644 index b2070f3baf..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h +++ /dev/null @@ -1,1073 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_BASETYPES_H_ -#define COMPILER_TRANSLATOR_BASETYPES_H_ - -#include <algorithm> -#include <array> - -#include "common/debug.h" -#include "GLSLANG/ShaderLang.h" - -namespace sh -{ - -// -// Precision qualifiers -// -enum TPrecision -{ - // These need to be kept sorted - EbpUndefined, - EbpLow, - EbpMedium, - EbpHigh, - - // end of list - EbpLast -}; - -inline const char *getPrecisionString(TPrecision p) -{ - switch (p) - { - case EbpHigh: - return "highp"; - case EbpMedium: - return "mediump"; - case EbpLow: - return "lowp"; - default: - return "mediump"; // Safest fallback - } -} - -// -// Basic type. Arrays, vectors, etc., are orthogonal to this. -// -enum TBasicType -{ - EbtVoid, - EbtFloat, - EbtInt, - EbtUInt, - EbtBool, - EbtGVec4, // non type: represents vec4, ivec4, and uvec4 - EbtGenType, // non type: represents float, vec2, vec3, and vec4 - EbtGenIType, // non type: represents int, ivec2, ivec3, and ivec4 - EbtGenUType, // non type: represents uint, uvec2, uvec3, and uvec4 - EbtGenBType, // non type: represents bool, bvec2, bvec3, and bvec4 - EbtVec, // non type: represents vec2, vec3, and vec4 - EbtIVec, // non type: represents ivec2, ivec3, and ivec4 - EbtUVec, // non type: represents uvec2, uvec3, and uvec4 - EbtBVec, // non type: represents bvec2, bvec3, and bvec4 - EbtYuvCscStandardEXT, // Only valid if EXT_YUV_target exists. - EbtGuardSamplerBegin, // non type: see implementation of IsSampler() - EbtSampler2D, - EbtSampler3D, - EbtSamplerCube, - EbtSampler2DArray, - EbtSamplerExternalOES, // Only valid if OES_EGL_image_external exists. - EbtSamplerExternal2DY2YEXT, // Only valid if GL_EXT_YUV_target exists. - EbtSampler2DRect, // Only valid if GL_ARB_texture_rectangle exists. - EbtSampler2DMS, - EbtISampler2D, - EbtISampler3D, - EbtISamplerCube, - EbtISampler2DArray, - EbtISampler2DMS, - EbtUSampler2D, - EbtUSampler3D, - EbtUSamplerCube, - EbtUSampler2DArray, - EbtUSampler2DMS, - EbtSampler2DShadow, - EbtSamplerCubeShadow, - EbtSampler2DArrayShadow, - EbtGuardSamplerEnd, // non type: see implementation of IsSampler() - EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D - EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D - EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube - EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and - // usampler2DArray - EbtGSampler2DMS, // non type: represents sampler2DMS, isampler2DMS, and usampler2DMS - - // images - EbtGuardImageBegin, - EbtImage2D, - EbtIImage2D, - EbtUImage2D, - EbtImage3D, - EbtIImage3D, - EbtUImage3D, - EbtImage2DArray, - EbtIImage2DArray, - EbtUImage2DArray, - EbtImageCube, - EbtIImageCube, - EbtUImageCube, - EbtGuardImageEnd, - - EbtGuardGImageBegin, - EbtGImage2D, // non type: represents image2D, uimage2D, iimage2D - EbtGImage3D, // non type: represents image3D, uimage3D, iimage3D - EbtGImage2DArray, // non type: represents image2DArray, uimage2DArray, iimage2DArray - EbtGImageCube, // non type: represents imageCube, uimageCube, iimageCube - EbtGuardGImageEnd, - - EbtStruct, - EbtInterfaceBlock, - EbtAddress, // should be deprecated?? - - EbtAtomicCounter, - - // end of list - EbtLast -}; - -inline TBasicType convertGImageToFloatImage(TBasicType type) -{ - switch (type) - { - case EbtGImage2D: - return EbtImage2D; - case EbtGImage3D: - return EbtImage3D; - case EbtGImage2DArray: - return EbtImage2DArray; - case EbtGImageCube: - return EbtImageCube; - default: - UNREACHABLE(); - } - return EbtLast; -} - -inline TBasicType convertGImageToIntImage(TBasicType type) -{ - switch (type) - { - case EbtGImage2D: - return EbtIImage2D; - case EbtGImage3D: - return EbtIImage3D; - case EbtGImage2DArray: - return EbtIImage2DArray; - case EbtGImageCube: - return EbtIImageCube; - default: - UNREACHABLE(); - } - return EbtLast; -} - -inline TBasicType convertGImageToUnsignedImage(TBasicType type) -{ - switch (type) - { - case EbtGImage2D: - return EbtUImage2D; - case EbtGImage3D: - return EbtUImage3D; - case EbtGImage2DArray: - return EbtUImage2DArray; - case EbtGImageCube: - return EbtUImageCube; - default: - UNREACHABLE(); - } - return EbtLast; -} - -const char *getBasicString(TBasicType t); - -inline bool IsSampler(TBasicType type) -{ - return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd; -} - -inline bool IsImage(TBasicType type) -{ - return type > EbtGuardImageBegin && type < EbtGuardImageEnd; -} - -inline bool IsGImage(TBasicType type) -{ - return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd; -} - -inline bool IsAtomicCounter(TBasicType type) -{ - return type == EbtAtomicCounter; -} - -inline bool IsOpaqueType(TBasicType type) -{ - return IsSampler(type) || IsImage(type) || IsAtomicCounter(type); -} - -inline bool IsIntegerSampler(TBasicType type) -{ - switch (type) - { - case EbtISampler2D: - case EbtISampler3D: - case EbtISamplerCube: - case EbtISampler2DArray: - case EbtISampler2DMS: - case EbtUSampler2D: - case EbtUSampler3D: - case EbtUSamplerCube: - case EbtUSampler2DArray: - case EbtUSampler2DMS: - return true; - case EbtSampler2D: - case EbtSampler3D: - case EbtSamplerCube: - case EbtSamplerExternalOES: - case EbtSamplerExternal2DY2YEXT: - case EbtSampler2DRect: - case EbtSampler2DArray: - case EbtSampler2DShadow: - case EbtSamplerCubeShadow: - case EbtSampler2DArrayShadow: - case EbtSampler2DMS: - return false; - default: - assert(!IsSampler(type)); - } - - return false; -} - -inline bool IsSampler2DMS(TBasicType type) -{ - switch (type) - { - case EbtSampler2DMS: - case EbtISampler2DMS: - case EbtUSampler2DMS: - return true; - default: - return false; - } -} - -inline bool IsFloatImage(TBasicType type) -{ - switch (type) - { - case EbtImage2D: - case EbtImage3D: - case EbtImage2DArray: - case EbtImageCube: - return true; - default: - break; - } - - return false; -} - -inline bool IsIntegerImage(TBasicType type) -{ - - switch (type) - { - case EbtIImage2D: - case EbtIImage3D: - case EbtIImage2DArray: - case EbtIImageCube: - return true; - default: - break; - } - - return false; -} - -inline bool IsUnsignedImage(TBasicType type) -{ - - switch (type) - { - case EbtUImage2D: - case EbtUImage3D: - case EbtUImage2DArray: - case EbtUImageCube: - return true; - default: - break; - } - - return false; -} - -inline bool IsSampler2D(TBasicType type) -{ - switch (type) - { - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - case EbtSampler2DRect: - case EbtSamplerExternalOES: - case EbtSamplerExternal2DY2YEXT: - case EbtSampler2DShadow: - case EbtSampler2DArrayShadow: - case EbtSampler2DMS: - case EbtISampler2DMS: - case EbtUSampler2DMS: - return true; - case EbtSampler3D: - case EbtISampler3D: - case EbtUSampler3D: - case EbtISamplerCube: - case EbtUSamplerCube: - case EbtSamplerCube: - case EbtSamplerCubeShadow: - return false; - default: - assert(!IsSampler(type)); - } - - return false; -} - -inline bool IsSamplerCube(TBasicType type) -{ - switch (type) - { - case EbtSamplerCube: - case EbtISamplerCube: - case EbtUSamplerCube: - case EbtSamplerCubeShadow: - return true; - case EbtSampler2D: - case EbtSampler3D: - case EbtSamplerExternalOES: - case EbtSamplerExternal2DY2YEXT: - case EbtSampler2DRect: - case EbtSampler2DArray: - case EbtSampler2DMS: - case EbtISampler2D: - case EbtISampler3D: - case EbtISampler2DArray: - case EbtISampler2DMS: - case EbtUSampler2D: - case EbtUSampler3D: - case EbtUSampler2DArray: - case EbtUSampler2DMS: - case EbtSampler2DShadow: - case EbtSampler2DArrayShadow: - return false; - default: - assert(!IsSampler(type)); - } - - return false; -} - -inline bool IsSampler3D(TBasicType type) -{ - switch (type) - { - case EbtSampler3D: - case EbtISampler3D: - case EbtUSampler3D: - return true; - case EbtSampler2D: - case EbtSamplerCube: - case EbtSamplerExternalOES: - case EbtSamplerExternal2DY2YEXT: - case EbtSampler2DRect: - case EbtSampler2DArray: - case EbtSampler2DMS: - case EbtISampler2D: - case EbtISamplerCube: - case EbtISampler2DArray: - case EbtISampler2DMS: - case EbtUSampler2D: - case EbtUSamplerCube: - case EbtUSampler2DArray: - case EbtUSampler2DMS: - case EbtSampler2DShadow: - case EbtSamplerCubeShadow: - case EbtSampler2DArrayShadow: - return false; - default: - assert(!IsSampler(type)); - } - - return false; -} - -inline bool IsSamplerArray(TBasicType type) -{ - switch (type) - { - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - case EbtSampler2DArrayShadow: - return true; - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DRect: - case EbtSamplerExternalOES: - case EbtSamplerExternal2DY2YEXT: - case EbtSampler3D: - case EbtISampler3D: - case EbtUSampler3D: - case EbtISamplerCube: - case EbtUSamplerCube: - case EbtSamplerCube: - case EbtSampler2DShadow: - case EbtSamplerCubeShadow: - case EbtSampler2DMS: - case EbtISampler2DMS: - case EbtUSampler2DMS: - return false; - default: - assert(!IsSampler(type)); - } - - return false; -} - -inline bool IsShadowSampler(TBasicType type) -{ - switch (type) - { - case EbtSampler2DShadow: - case EbtSamplerCubeShadow: - case EbtSampler2DArrayShadow: - return true; - case EbtISampler2D: - case EbtISampler3D: - case EbtISamplerCube: - case EbtISampler2DArray: - case EbtISampler2DMS: - case EbtUSampler2D: - case EbtUSampler3D: - case EbtUSamplerCube: - case EbtUSampler2DArray: - case EbtUSampler2DMS: - case EbtSampler2D: - case EbtSampler3D: - case EbtSamplerCube: - case EbtSamplerExternalOES: - case EbtSamplerExternal2DY2YEXT: - case EbtSampler2DRect: - case EbtSampler2DArray: - case EbtSampler2DMS: - return false; - default: - assert(!IsSampler(type)); - } - - return false; -} - -inline bool IsImage2D(TBasicType type) -{ - switch (type) - { - case EbtImage2D: - case EbtIImage2D: - case EbtUImage2D: - return true; - case EbtImage3D: - case EbtIImage3D: - case EbtUImage3D: - case EbtImage2DArray: - case EbtIImage2DArray: - case EbtUImage2DArray: - case EbtImageCube: - case EbtIImageCube: - case EbtUImageCube: - return false; - default: - assert(!IsImage(type)); - } - - return false; -} - -inline bool IsImage3D(TBasicType type) -{ - switch (type) - { - case EbtImage3D: - case EbtIImage3D: - case EbtUImage3D: - return true; - case EbtImage2D: - case EbtIImage2D: - case EbtUImage2D: - case EbtImage2DArray: - case EbtIImage2DArray: - case EbtUImage2DArray: - case EbtImageCube: - case EbtIImageCube: - case EbtUImageCube: - return false; - default: - assert(!IsImage(type)); - } - - return false; -} - -inline bool IsImage2DArray(TBasicType type) -{ - switch (type) - { - case EbtImage2DArray: - case EbtIImage2DArray: - case EbtUImage2DArray: - return true; - case EbtImage2D: - case EbtIImage2D: - case EbtUImage2D: - case EbtImage3D: - case EbtIImage3D: - case EbtUImage3D: - case EbtImageCube: - case EbtIImageCube: - case EbtUImageCube: - return false; - default: - assert(!IsImage(type)); - } - - return false; -} - -inline bool IsImageCube(TBasicType type) -{ - switch (type) - { - case EbtImageCube: - case EbtIImageCube: - case EbtUImageCube: - return true; - case EbtImage2D: - case EbtIImage2D: - case EbtUImage2D: - case EbtImage3D: - case EbtIImage3D: - case EbtUImage3D: - case EbtImage2DArray: - case EbtIImage2DArray: - case EbtUImage2DArray: - return false; - default: - assert(!IsImage(type)); - } - - return false; -} - -inline bool IsInteger(TBasicType type) -{ - return type == EbtInt || type == EbtUInt; -} - -inline bool SupportsPrecision(TBasicType type) -{ - return type == EbtFloat || type == EbtInt || type == EbtUInt || IsOpaqueType(type); -} - -// -// Qualifiers and built-ins. These are mainly used to see what can be read -// or written, and by the machine dependent translator to know which registers -// to allocate variables in. Since built-ins tend to go to different registers -// than varying or uniform, it makes sense they are peers, not sub-classes. -// -enum TQualifier -{ - EvqTemporary, // For temporaries (within a function), read/write - EvqGlobal, // For globals read/write - EvqConst, // User defined constants and non-output parameters in functions - EvqAttribute, // Readonly - EvqVaryingIn, // readonly, fragment shaders only - EvqVaryingOut, // vertex shaders only read/write - EvqUniform, // Readonly, vertex and fragment - EvqBuffer, // read/write, vertex, fragment and compute shader - - EvqVertexIn, // Vertex shader input - EvqFragmentOut, // Fragment shader output - EvqVertexOut, // Vertex shader output - EvqFragmentIn, // Fragment shader input - - // parameters - EvqIn, - EvqOut, - EvqInOut, - EvqConstReadOnly, - - // built-ins read by vertex shader - EvqInstanceID, - EvqVertexID, - - // built-ins written by vertex shader - EvqPosition, - EvqPointSize, - - // built-ins read by fragment shader - EvqFragCoord, - EvqFrontFacing, - EvqPointCoord, - - // built-ins written by fragment shader - EvqFragColor, - EvqFragData, - - EvqFragDepth, // gl_FragDepth for ESSL300. - EvqFragDepthEXT, // gl_FragDepthEXT for ESSL100, EXT_frag_depth. - - EvqSecondaryFragColorEXT, // EXT_blend_func_extended - EvqSecondaryFragDataEXT, // EXT_blend_func_extended - - EvqViewIDOVR, // OVR_multiview - EvqViewportIndex, // gl_ViewportIndex - - // built-ins written by the shader_framebuffer_fetch extension(s) - EvqLastFragColor, - EvqLastFragData, - - // GLSL ES 3.0 vertex output and fragment input - EvqSmooth, // Incomplete qualifier, smooth is the default - EvqFlat, // Incomplete qualifier - EvqCentroid, // Incomplete qualifier - EvqSmoothOut, - EvqFlatOut, - EvqCentroidOut, // Implies smooth - EvqSmoothIn, - EvqFlatIn, - EvqCentroidIn, // Implies smooth - - // GLSL ES 3.1 compute shader special variables - EvqShared, - EvqComputeIn, - EvqNumWorkGroups, - EvqWorkGroupSize, - EvqWorkGroupID, - EvqLocalInvocationID, - EvqGlobalInvocationID, - EvqLocalInvocationIndex, - - // GLSL ES 3.1 memory qualifiers - EvqReadOnly, - EvqWriteOnly, - EvqCoherent, - EvqRestrict, - EvqVolatile, - - // GLSL ES 3.1 extension OES_geometry_shader qualifiers - EvqGeometryIn, - EvqGeometryOut, - EvqPerVertexIn, // gl_in - EvqPrimitiveIDIn, // gl_PrimitiveIDIn - EvqInvocationID, // gl_InvocationID - EvqPrimitiveID, // gl_PrimitiveID - EvqLayer, // gl_Layer - - // end of list - EvqLast -}; - -inline bool IsQualifierUnspecified(TQualifier qualifier) -{ - return (qualifier == EvqTemporary || qualifier == EvqGlobal); -} - -enum TLayoutImageInternalFormat -{ - EiifUnspecified, - EiifRGBA32F, - EiifRGBA16F, - EiifR32F, - EiifRGBA32UI, - EiifRGBA16UI, - EiifRGBA8UI, - EiifR32UI, - EiifRGBA32I, - EiifRGBA16I, - EiifRGBA8I, - EiifR32I, - EiifRGBA8, - EiifRGBA8_SNORM -}; - -enum TLayoutMatrixPacking -{ - EmpUnspecified, - EmpRowMajor, - EmpColumnMajor -}; - -enum TLayoutBlockStorage -{ - EbsUnspecified, - EbsShared, - EbsPacked, - EbsStd140, - EbsStd430 -}; - -enum TYuvCscStandardEXT -{ - EycsUndefined, - EycsItu601, - EycsItu601FullRange, - EycsItu709 -}; - -enum TLayoutPrimitiveType -{ - EptUndefined, - EptPoints, - EptLines, - EptLinesAdjacency, - EptTriangles, - EptTrianglesAdjacency, - EptLineStrip, - EptTriangleStrip -}; - -struct TLayoutQualifier -{ - // Must have a trivial default constructor since it is used in YYSTYPE. - TLayoutQualifier() = default; - - constexpr static TLayoutQualifier Create() { return TLayoutQualifier(0); } - - bool isEmpty() const - { - return location == -1 && binding == -1 && offset == -1 && numViews == -1 && yuv == false && - matrixPacking == EmpUnspecified && blockStorage == EbsUnspecified && - !localSize.isAnyValueSet() && imageInternalFormat == EiifUnspecified && - primitiveType == EptUndefined && invocations == 0 && maxVertices == -1; - } - - bool isCombinationValid() const - { - bool workSizeSpecified = localSize.isAnyValueSet(); - bool numViewsSet = (numViews != -1); - bool geometryShaderSpecified = - (primitiveType != EptUndefined) || (invocations != 0) || (maxVertices != -1); - bool otherLayoutQualifiersSpecified = - (location != -1 || binding != -1 || matrixPacking != EmpUnspecified || - blockStorage != EbsUnspecified || imageInternalFormat != EiifUnspecified); - - // we can have either the work group size specified, or number of views, - // or yuv layout qualifier, or the other layout qualifiers. - return (workSizeSpecified ? 1 : 0) + (numViewsSet ? 1 : 0) + (yuv ? 1 : 0) + - (otherLayoutQualifiersSpecified ? 1 : 0) + (geometryShaderSpecified ? 1 : 0) <= - 1; - } - - bool isLocalSizeEqual(const sh::WorkGroupSize &localSizeIn) const - { - return localSize.isWorkGroupSizeMatching(localSizeIn); - } - - int location; - unsigned int locationsSpecified; - TLayoutMatrixPacking matrixPacking; - TLayoutBlockStorage blockStorage; - - // Compute shader layout qualifiers. - sh::WorkGroupSize localSize; - - int binding; - int offset; - - // Image format layout qualifier - TLayoutImageInternalFormat imageInternalFormat; - - // OVR_multiview num_views. - int numViews; - - // EXT_YUV_target yuv layout qualifier. - bool yuv; - - // OES_geometry_shader layout qualifiers. - TLayoutPrimitiveType primitiveType; - int invocations; - int maxVertices; - - private: - explicit constexpr TLayoutQualifier(int /*placeholder*/) - : location(-1), - locationsSpecified(0), - matrixPacking(EmpUnspecified), - blockStorage(EbsUnspecified), - localSize(-1), - binding(-1), - offset(-1), - imageInternalFormat(EiifUnspecified), - numViews(-1), - yuv(false), - primitiveType(EptUndefined), - invocations(0), - maxVertices(-1) - { - } -}; - -struct TMemoryQualifier -{ - // Must have a trivial default constructor since it is used in YYSTYPE. - TMemoryQualifier() = default; - - bool isEmpty() const - { - return !readonly && !writeonly && !coherent && !restrictQualifier && !volatileQualifier; - } - - constexpr static TMemoryQualifier Create() { return TMemoryQualifier(0); } - - // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers - // An image can be qualified as both readonly and writeonly. It still can be can be used with - // imageSize(). - bool readonly; - bool writeonly; - bool coherent; - - // restrict and volatile are reserved keywords in C/C++ - bool restrictQualifier; - bool volatileQualifier; - - private: - explicit constexpr TMemoryQualifier(int /*placeholder*/) - : readonly(false), - writeonly(false), - coherent(false), - restrictQualifier(false), - volatileQualifier(false) - { - } -}; - -inline const char *getWorkGroupSizeString(size_t dimension) -{ - switch (dimension) - { - case 0u: - return "local_size_x"; - case 1u: - return "local_size_y"; - case 2u: - return "local_size_z"; - default: - UNREACHABLE(); - return "dimension out of bounds"; - } -} - -// -// This is just for debug and error message print out, carried along with the definitions above. -// -inline const char *getQualifierString(TQualifier q) -{ - // clang-format off - switch(q) - { - case EvqTemporary: return "Temporary"; - case EvqGlobal: return "Global"; - case EvqConst: return "const"; - case EvqAttribute: return "attribute"; - case EvqVaryingIn: return "varying"; - case EvqVaryingOut: return "varying"; - case EvqUniform: return "uniform"; - case EvqBuffer: return "buffer"; - case EvqVertexIn: return "in"; - case EvqFragmentOut: return "out"; - case EvqVertexOut: return "out"; - case EvqFragmentIn: return "in"; - case EvqIn: return "in"; - case EvqOut: return "out"; - case EvqInOut: return "inout"; - case EvqConstReadOnly: return "const"; - case EvqInstanceID: return "InstanceID"; - case EvqVertexID: return "VertexID"; - case EvqPosition: return "Position"; - case EvqPointSize: return "PointSize"; - case EvqFragCoord: return "FragCoord"; - case EvqFrontFacing: return "FrontFacing"; - case EvqPointCoord: return "PointCoord"; - case EvqFragColor: return "FragColor"; - case EvqFragData: return "FragData"; - case EvqFragDepthEXT: return "FragDepth"; - case EvqFragDepth: return "FragDepth"; - case EvqSecondaryFragColorEXT: return "SecondaryFragColorEXT"; - case EvqSecondaryFragDataEXT: return "SecondaryFragDataEXT"; - case EvqViewIDOVR: return "ViewIDOVR"; - case EvqViewportIndex: return "ViewportIndex"; - case EvqLayer: return "Layer"; - case EvqLastFragColor: return "LastFragColor"; - case EvqLastFragData: return "LastFragData"; - case EvqSmoothOut: return "smooth out"; - case EvqCentroidOut: return "smooth centroid out"; - case EvqFlatOut: return "flat out"; - case EvqSmoothIn: return "smooth in"; - case EvqFlatIn: return "flat in"; - case EvqCentroidIn: return "smooth centroid in"; - case EvqCentroid: return "centroid"; - case EvqFlat: return "flat"; - case EvqSmooth: return "smooth"; - case EvqShared: return "shared"; - case EvqComputeIn: return "in"; - case EvqNumWorkGroups: return "NumWorkGroups"; - case EvqWorkGroupSize: return "WorkGroupSize"; - case EvqWorkGroupID: return "WorkGroupID"; - case EvqLocalInvocationID: return "LocalInvocationID"; - case EvqGlobalInvocationID: return "GlobalInvocationID"; - case EvqLocalInvocationIndex: return "LocalInvocationIndex"; - case EvqReadOnly: return "readonly"; - case EvqWriteOnly: return "writeonly"; - case EvqGeometryIn: return "in"; - case EvqGeometryOut: return "out"; - case EvqPerVertexIn: return "gl_in"; - default: UNREACHABLE(); return "unknown qualifier"; - } - // clang-format on -} - -inline const char *getMatrixPackingString(TLayoutMatrixPacking mpq) -{ - switch (mpq) - { - case EmpUnspecified: - return "mp_unspecified"; - case EmpRowMajor: - return "row_major"; - case EmpColumnMajor: - return "column_major"; - default: - UNREACHABLE(); - return "unknown matrix packing"; - } -} - -inline const char *getBlockStorageString(TLayoutBlockStorage bsq) -{ - switch (bsq) - { - case EbsUnspecified: - return "bs_unspecified"; - case EbsShared: - return "shared"; - case EbsPacked: - return "packed"; - case EbsStd140: - return "std140"; - case EbsStd430: - return "std430"; - default: - UNREACHABLE(); - return "unknown block storage"; - } -} - -inline const char *getImageInternalFormatString(TLayoutImageInternalFormat iifq) -{ - switch (iifq) - { - case EiifRGBA32F: - return "rgba32f"; - case EiifRGBA16F: - return "rgba16f"; - case EiifR32F: - return "r32f"; - case EiifRGBA32UI: - return "rgba32ui"; - case EiifRGBA16UI: - return "rgba16ui"; - case EiifRGBA8UI: - return "rgba8ui"; - case EiifR32UI: - return "r32ui"; - case EiifRGBA32I: - return "rgba32i"; - case EiifRGBA16I: - return "rgba16i"; - case EiifRGBA8I: - return "rgba8i"; - case EiifR32I: - return "r32i"; - case EiifRGBA8: - return "rgba8"; - case EiifRGBA8_SNORM: - return "rgba8_snorm"; - default: - UNREACHABLE(); - return "unknown internal image format"; - } -} - -inline TYuvCscStandardEXT getYuvCscStandardEXT(const std::string &str) -{ - if (str == "itu_601") - return EycsItu601; - else if (str == "itu_601_full_range") - return EycsItu601FullRange; - else if (str == "itu_709") - return EycsItu709; - return EycsUndefined; -} - -inline const char *getYuvCscStandardEXTString(TYuvCscStandardEXT ycsq) -{ - switch (ycsq) - { - case EycsItu601: - return "itu_601"; - case EycsItu601FullRange: - return "itu_601_full_range"; - case EycsItu709: - return "itu_709"; - default: - UNREACHABLE(); - return "unknown color space conversion standard"; - } -} - -inline const char *getGeometryShaderPrimitiveTypeString(TLayoutPrimitiveType primitiveType) -{ - switch (primitiveType) - { - case EptPoints: - return "points"; - case EptLines: - return "lines"; - case EptTriangles: - return "triangles"; - case EptLinesAdjacency: - return "lines_adjacency"; - case EptTrianglesAdjacency: - return "triangles_adjacency"; - case EptLineStrip: - return "line_strip"; - case EptTriangleStrip: - return "triangle_strip"; - default: - UNREACHABLE(); - return "unknown geometry shader primitive type"; - } -} - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_BASETYPES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp b/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp deleted file mode 100644 index d6a1e025de..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend -// may record a variable as aliasing another. Sometimes the alias information gets garbled -// so we work around this issue by breaking the aliasing chain in inner loops. - -#include "BreakVariableAliasingInInnerLoops.h" - -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" - -// A HLSL compiler developer gave us more details on the root cause and the workaround needed: -// The root problem is that if the HLSL compiler is applying aliasing information even on -// incomplete simulations (in this case, a single pass). The bug is triggered by an assignment -// that comes from a series of assignments, possibly with swizzled or ternary operators with -// known conditionals, where the source is before the loop. -// So, a workaround is to add a +0 term to variables the first time they are assigned to in -// an inner loop (if they are declared in an outside scope, otherwise there is no need). -// This will break the aliasing chain. - -// For simplicity here we add a +0 to any assignment that is in at least two nested loops. Because -// the bug only shows up with swizzles, and ternary assignment, whole array or whole structure -// assignment don't need a workaround. - -namespace sh -{ - -namespace -{ - -class AliasingBreaker : public TIntermTraverser -{ - public: - AliasingBreaker() : TIntermTraverser(true, false, true) {} - - protected: - bool visitBinary(Visit visit, TIntermBinary *binary) - { - if (visit != PreVisit) - { - return false; - } - - if (mLoopLevel < 2 || !binary->isAssignment()) - { - return true; - } - - TIntermTyped *B = binary->getRight(); - TType type = B->getType(); - - if (!type.isScalar() && !type.isVector() && !type.isMatrix()) - { - return true; - } - - if (type.isArray() || IsSampler(type.getBasicType())) - { - return true; - } - - // We have a scalar / vector / matrix assignment with loop depth 2. - // Transform it from - // A = B - // to - // A = (B + typeof<B>(0)); - - TIntermBinary *bPlusZero = new TIntermBinary(EOpAdd, B, CreateZeroNode(type)); - bPlusZero->setLine(B->getLine()); - - binary->replaceChildNode(B, bPlusZero); - - return true; - } - - bool visitLoop(Visit visit, TIntermLoop *loop) - { - if (visit == PreVisit) - { - mLoopLevel++; - } - else - { - ASSERT(mLoopLevel > 0); - mLoopLevel--; - } - - return true; - } - - private: - int mLoopLevel = 0; -}; - -} // anonymous namespace - -void BreakVariableAliasingInInnerLoops(TIntermNode *root) -{ - AliasingBreaker breaker; - root->traverse(&breaker); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h b/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h deleted file mode 100644 index b1d906f919..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend -// may record a variable as aliasing another. Sometimes the alias information gets garbled -// so we work around this issue by breaking the aliasing chain in inner loops. - -#ifndef COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_ -#define COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_ - -class TIntermNode; - -namespace sh -{ - -void BreakVariableAliasingInInnerLoops(TIntermNode *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp deleted file mode 100644 index 905e634fd1..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp +++ /dev/null @@ -1,355 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/BuiltInFunctionEmulator.h" -#include "angle_gl.h" -#include "compiler/translator/Cache.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser -{ - public: - BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator &emulator) - : TIntermTraverser(true, false, false), mEmulator(emulator) - { - } - - bool visitUnary(Visit visit, TIntermUnary *node) override - { - if (visit == PreVisit) - { - bool needToEmulate = - mEmulator.setFunctionCalled(node->getOp(), node->getOperand()->getType()); - if (needToEmulate) - node->setUseEmulatedFunction(); - } - return true; - } - - bool visitAggregate(Visit visit, TIntermAggregate *node) override - { - if (visit == PreVisit) - { - // Here we handle all the built-in functions mapped to ops, not just the ones that are - // currently identified as problematic. - if (node->isConstructor() || node->isFunctionCall()) - { - return true; - } - const TIntermSequence &sequence = *(node->getSequence()); - bool needToEmulate = false; - // Right now we only handle built-in functions with two to four parameters. - if (sequence.size() == 2) - { - TIntermTyped *param1 = sequence[0]->getAsTyped(); - TIntermTyped *param2 = sequence[1]->getAsTyped(); - if (!param1 || !param2) - return true; - needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(), - param2->getType()); - } - else if (sequence.size() == 3) - { - TIntermTyped *param1 = sequence[0]->getAsTyped(); - TIntermTyped *param2 = sequence[1]->getAsTyped(); - TIntermTyped *param3 = sequence[2]->getAsTyped(); - if (!param1 || !param2 || !param3) - return true; - needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(), - param2->getType(), param3->getType()); - } - else if (sequence.size() == 4) - { - TIntermTyped *param1 = sequence[0]->getAsTyped(); - TIntermTyped *param2 = sequence[1]->getAsTyped(); - TIntermTyped *param3 = sequence[2]->getAsTyped(); - TIntermTyped *param4 = sequence[3]->getAsTyped(); - if (!param1 || !param2 || !param3 || !param4) - return true; - needToEmulate = - mEmulator.setFunctionCalled(node->getOp(), param1->getType(), param2->getType(), - param3->getType(), param4->getType()); - } - else - { - return true; - } - - if (needToEmulate) - node->setUseEmulatedFunction(); - } - return true; - } - - private: - BuiltInFunctionEmulator &mEmulator; -}; - -BuiltInFunctionEmulator::BuiltInFunctionEmulator() -{ -} - -FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, - const TType *param, - const char *emulatedFunctionDefinition) -{ - FunctionId id(op, param); - mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition); - return id; -} - -FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, - const TType *param1, - const TType *param2, - const char *emulatedFunctionDefinition) -{ - FunctionId id(op, param1, param2); - mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition); - return id; -} - -FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency( - const FunctionId &dependency, - TOperator op, - const TType *param1, - const TType *param2, - const char *emulatedFunctionDefinition) -{ - FunctionId id(op, param1, param2); - mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition); - mFunctionDependencies[id] = dependency; - return id; -} - -FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const char *emulatedFunctionDefinition) -{ - FunctionId id(op, param1, param2, param3); - mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition); - return id; -} - -FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const TType *param4, - const char *emulatedFunctionDefinition) -{ - FunctionId id(op, param1, param2, param3, param4); - mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition); - return id; -} - -FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency( - const FunctionId &dependency, - TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const TType *param4, - const char *emulatedFunctionDefinition) -{ - FunctionId id(op, param1, param2, param3, param4); - mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition); - mFunctionDependencies[id] = dependency; - return id; -} - -bool BuiltInFunctionEmulator::isOutputEmpty() const -{ - return (mFunctions.size() == 0); -} - -void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const -{ - for (const auto &function : mFunctions) - { - const char *body = findEmulatedFunction(function); - ASSERT(body); - out << body; - out << "\n\n"; - } -} - -bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, const TType ¶m) -{ - return setFunctionCalled(FunctionId(op, ¶m)); -} - -bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, - const TType ¶m1, - const TType ¶m2) -{ - return setFunctionCalled(FunctionId(op, ¶m1, ¶m2)); -} - -bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, - const TType ¶m1, - const TType ¶m2, - const TType ¶m3) -{ - return setFunctionCalled(FunctionId(op, ¶m1, ¶m2, ¶m3)); -} - -bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, - const TType ¶m1, - const TType ¶m2, - const TType ¶m3, - const TType ¶m4) -{ - return setFunctionCalled(FunctionId(op, ¶m1, ¶m2, ¶m3, ¶m4)); -} - -const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &functionId) const -{ - for (const auto &queryFunction : mQueryFunctions) - { - const char *result = queryFunction(functionId); - if (result) - { - return result; - } - } - - const auto &result = mEmulatedFunctions.find(functionId); - if (result != mEmulatedFunctions.end()) - { - return result->second.c_str(); - } - - return nullptr; -} - -bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId) -{ - if (!findEmulatedFunction(functionId)) - { - return false; - } - - for (size_t i = 0; i < mFunctions.size(); ++i) - { - if (mFunctions[i] == functionId) - return true; - } - // If the function depends on another, mark the dependency as called. - auto dependency = mFunctionDependencies.find(functionId); - if (dependency != mFunctionDependencies.end()) - { - setFunctionCalled((*dependency).second); - } - // Copy the functionId if it needs to be stored, to make sure that the TType pointers inside - // remain valid and constant. - mFunctions.push_back(functionId.getCopy()); - return true; -} - -void BuiltInFunctionEmulator::markBuiltInFunctionsForEmulation(TIntermNode *root) -{ - ASSERT(root); - - if (mEmulatedFunctions.empty() && mQueryFunctions.empty()) - return; - - BuiltInFunctionEmulationMarker marker(*this); - root->traverse(&marker); -} - -void BuiltInFunctionEmulator::cleanup() -{ - mFunctions.clear(); - mFunctionDependencies.clear(); -} - -void BuiltInFunctionEmulator::addFunctionMap(BuiltinQueryFunc queryFunc) -{ - mQueryFunctions.push_back(queryFunc); -} - -// static -void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name) -{ - ASSERT(name[strlen(name) - 1] != '('); - out << name << "_emu"; -} - -FunctionId::FunctionId() - : mOp(EOpNull), - mParam1(TCache::getType(EbtVoid)), - mParam2(TCache::getType(EbtVoid)), - mParam3(TCache::getType(EbtVoid)), - mParam4(TCache::getType(EbtVoid)) -{ -} - -FunctionId::FunctionId(TOperator op, const TType *param) - : mOp(op), - mParam1(param), - mParam2(TCache::getType(EbtVoid)), - mParam3(TCache::getType(EbtVoid)), - mParam4(TCache::getType(EbtVoid)) -{ -} - -FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2) - : mOp(op), - mParam1(param1), - mParam2(param2), - mParam3(TCache::getType(EbtVoid)), - mParam4(TCache::getType(EbtVoid)) -{ -} - -FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3) - : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(TCache::getType(EbtVoid)) -{ -} - -FunctionId::FunctionId(TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const TType *param4) - : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(param4) -{ -} - -bool FunctionId::operator==(const FunctionId &other) const -{ - return (mOp == other.mOp && *mParam1 == *other.mParam1 && *mParam2 == *other.mParam2 && - *mParam3 == *other.mParam3 && *mParam4 == *other.mParam4); -} - -bool FunctionId::operator<(const FunctionId &other) const -{ - if (mOp != other.mOp) - return mOp < other.mOp; - if (*mParam1 != *other.mParam1) - return *mParam1 < *other.mParam1; - if (*mParam2 != *other.mParam2) - return *mParam2 < *other.mParam2; - if (*mParam3 != *other.mParam3) - return *mParam3 < *other.mParam3; - if (*mParam4 != *other.mParam4) - return *mParam4 < *other.mParam4; - return false; // all fields are equal -} - -FunctionId FunctionId::getCopy() const -{ - return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3), - new TType(*mParam4)); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h deleted file mode 100644 index 5f15f66224..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h +++ /dev/null @@ -1,183 +0,0 @@ -// -// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ -#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ - -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/ParamType.h" - -namespace sh -{ - -struct MiniFunctionId -{ - constexpr MiniFunctionId(TOperator op = EOpNull, - ParamType paramType1 = ParamType::Void, - ParamType paramType2 = ParamType::Void, - ParamType paramType3 = ParamType::Void, - ParamType paramType4 = ParamType::Void) - : op(op), - paramType1(paramType1), - paramType2(paramType2), - paramType3(paramType3), - paramType4(paramType4) - { - } - - TOperator op; - ParamType paramType1; - ParamType paramType2; - ParamType paramType3; - ParamType paramType4; -}; - -class FunctionId final -{ - public: - FunctionId(); - FunctionId(TOperator op, const TType *param); - FunctionId(TOperator op, const TType *param1, const TType *param2); - FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3); - FunctionId(TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const TType *param4); - - FunctionId(const FunctionId &) = default; - FunctionId &operator=(const FunctionId &) = default; - - bool operator==(const FunctionId &other) const; - bool operator<(const FunctionId &other) const; - - FunctionId getCopy() const; - - private: - friend bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId); - TOperator mOp; - - // The memory that these TType objects use is freed by PoolAllocator. The - // BuiltInFunctionEmulator's lifetime can extend until after the memory pool is freed, but - // that's not an issue since this class never destructs these objects. - const TType *mParam1; - const TType *mParam2; - const TType *mParam3; - const TType *mParam4; -}; - -inline bool operator==(ParamType paramType, const TType *type) -{ - return SameParamType(paramType, type->getBasicType(), type->getNominalSize(), - type->getSecondarySize()); -} - -inline bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId) -{ - return miniId.op == functionId.mOp && miniId.paramType1 == functionId.mParam1 && - miniId.paramType2 == functionId.mParam2 && miniId.paramType3 == functionId.mParam3 && - miniId.paramType4 == functionId.mParam4; -} - -using BuiltinQueryFunc = const char *(const FunctionId &); - -// -// This class decides which built-in functions need to be replaced with the emulated ones. It can be -// used to work around driver bugs or implement functions that are not natively implemented on a -// specific platform. -// -class BuiltInFunctionEmulator -{ - public: - BuiltInFunctionEmulator(); - - void markBuiltInFunctionsForEmulation(TIntermNode *root); - - void cleanup(); - - // "name" gets written as "name_emu". - static void WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name); - - bool isOutputEmpty() const; - - // Output function emulation definition. This should be before any other shader source. - void outputEmulatedFunctions(TInfoSinkBase &out) const; - - // Add functions that need to be emulated. - FunctionId addEmulatedFunction(TOperator op, - const TType *param, - const char *emulatedFunctionDefinition); - FunctionId addEmulatedFunction(TOperator op, - const TType *param1, - const TType *param2, - const char *emulatedFunctionDefinition); - FunctionId addEmulatedFunction(TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const char *emulatedFunctionDefinition); - FunctionId addEmulatedFunction(TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const TType *param4, - const char *emulatedFunctionDefinition); - - FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency, - TOperator op, - const TType *param1, - const TType *param2, - const char *emulatedFunctionDefinition); - FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency, - TOperator op, - const TType *param1, - const TType *param2, - const TType *param3, - const TType *param4, - const char *emulatedFunctionDefinition); - - void addFunctionMap(BuiltinQueryFunc queryFunc); - - private: - class BuiltInFunctionEmulationMarker; - - // Records that a function is called by the shader and might need to be emulated. If the - // function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function - // call needs to be replaced with an emulated one. - bool setFunctionCalled(TOperator op, const TType ¶m); - bool setFunctionCalled(TOperator op, const TType ¶m1, const TType ¶m2); - bool setFunctionCalled(TOperator op, - const TType ¶m1, - const TType ¶m2, - const TType ¶m3); - bool setFunctionCalled(TOperator op, - const TType ¶m1, - const TType ¶m2, - const TType ¶m3, - const TType ¶m4); - - bool setFunctionCalled(const FunctionId &functionId); - - const char *findEmulatedFunction(const FunctionId &functionId) const; - - // Map from function id to emulated function definition - std::map<FunctionId, std::string> mEmulatedFunctions; - - // Map from dependent functions to their dependencies. This structure allows each function to - // have at most one dependency. - std::map<FunctionId, FunctionId> mFunctionDependencies; - - // Called function ids - std::vector<FunctionId> mFunctions; - - // Constexpr function tables. - std::vector<BuiltinQueryFunc *> mQueryFunctions; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp deleted file mode 100644 index 27ee04da35..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp +++ /dev/null @@ -1,293 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "angle_gl.h" -#include "compiler/translator/BuiltInFunctionEmulator.h" -#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" -#include "compiler/translator/Cache.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/VersionGLSL.h" - -namespace sh -{ - -void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, - sh::GLenum shaderType) -{ - if (shaderType == GL_VERTEX_SHADER) - { - const TType *int1 = TCache::getType(EbtInt); - emu->addEmulatedFunction(EOpAbs, int1, "int abs_emu(int x) { return x * sign(x); }"); - } -} - -void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, - int targetGLSLVersion) -{ - // isnan() is supported since GLSL 1.3. - if (targetGLSLVersion < GLSL_VERSION_130) - return; - - const TType *float1 = TCache::getType(EbtFloat); - const TType *float2 = TCache::getType(EbtFloat, 2); - const TType *float3 = TCache::getType(EbtFloat, 3); - const TType *float4 = TCache::getType(EbtFloat, 4); - - // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false. - emu->addEmulatedFunction( - EOpIsNan, float1, - "bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }"); - emu->addEmulatedFunction( - EOpIsNan, float2, - "bvec2 isnan_emu(vec2 x)\n" - "{\n" - " bvec2 isnan;\n" - " for (int i = 0; i < 2; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); - emu->addEmulatedFunction( - EOpIsNan, float3, - "bvec3 isnan_emu(vec3 x)\n" - "{\n" - " bvec3 isnan;\n" - " for (int i = 0; i < 3; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); - emu->addEmulatedFunction( - EOpIsNan, float4, - "bvec4 isnan_emu(vec4 x)\n" - "{\n" - " bvec4 isnan;\n" - " for (int i = 0; i < 4; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); -} - -void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu) -{ - const TType *float1 = TCache::getType(EbtFloat); - auto floatFuncId = emu->addEmulatedFunction( - EOpAtan, float1, float1, - "emu_precision float atan_emu(emu_precision float y, emu_precision " - "float x)\n" - "{\n" - " if (x > 0.0) return atan(y / x);\n" - " else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n" - " else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n" - " else return 1.57079632 * sign(y);\n" - "}\n"); - for (int dim = 2; dim <= 4; ++dim) - { - const TType *floatVec = TCache::getType(EbtFloat, static_cast<unsigned char>(dim)); - std::stringstream ss; - ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim - << " y, emu_precision vec" << dim << " x)\n" - << "{\n" - " return vec" - << dim << "("; - for (int i = 0; i < dim; ++i) - { - ss << "atan_emu(y[" << i << "], x[" << i << "])"; - if (i < dim - 1) - { - ss << ", "; - } - } - ss << ");\n" - "}\n"; - emu->addEmulatedFunctionWithDependency(floatFuncId, EOpAtan, floatVec, floatVec, - ss.str().c_str()); - } -} - -// Emulate built-in functions missing from GLSL 1.30 and higher -void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu, - sh::GLenum shaderType, - int targetGLSLVersion) -{ - // Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10) - if (targetGLSLVersion < GLSL_VERSION_410) - { - const TType *float2 = TCache::getType(EbtFloat, 2); - const TType *uint1 = TCache::getType(EbtUInt); - - // clang-format off - emu->addEmulatedFunction(EOpPackUnorm2x16, float2, - "uint packUnorm2x16_emu(vec2 v)\n" - "{\n" - " int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n" - " int y = int(round(clamp(v.y, 0.0, 1.0) * 65535.0));\n" - " return uint((y << 16) | (x & 0xFFFF));\n" - "}\n"); - - emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1, - "vec2 unpackUnorm2x16_emu(uint u)\n" - "{\n" - " float x = float(u & 0xFFFFu) / 65535.0;\n" - " float y = float(u >> 16) / 65535.0;\n" - " return vec2(x, y);\n" - "}\n"); - // clang-format on - } - - // Emulate packSnorm2x16, packHalf2x16, unpackSnorm2x16, and unpackHalf2x16 (GLSL 4.20) - // by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30). - if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420) - { - const TType *float2 = TCache::getType(EbtFloat, 2); - const TType *uint1 = TCache::getType(EbtUInt); - - // clang-format off - emu->addEmulatedFunction(EOpPackSnorm2x16, float2, - "uint packSnorm2x16_emu(vec2 v)\n" - "{\n" - " #if defined(GL_ARB_shading_language_packing)\n" - " return packSnorm2x16(v);\n" - " #else\n" - " int x = int(round(clamp(v.x, -1.0, 1.0) * 32767.0));\n" - " int y = int(round(clamp(v.y, -1.0, 1.0) * 32767.0));\n" - " return uint((y << 16) | (x & 0xFFFF));\n" - " #endif\n" - "}\n"); - emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1, - "#if !defined(GL_ARB_shading_language_packing)\n" - " float fromSnorm(uint x)\n" - " {\n" - " int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n" - " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n" - " }\n" - "#endif\n" - "\n" - "vec2 unpackSnorm2x16_emu(uint u)\n" - "{\n" - " #if defined(GL_ARB_shading_language_packing)\n" - " return unpackSnorm2x16(u);\n" - " #else\n" - " uint y = (u >> 16);\n" - " uint x = u;\n" - " return vec2(fromSnorm(x), fromSnorm(y));\n" - " #endif\n" - "}\n"); - // Functions uint f32tof16(float val) and float f16tof32(uint val) are - // based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL". - emu->addEmulatedFunction(EOpPackHalf2x16, float2, - "#if !defined(GL_ARB_shading_language_packing)\n" - " uint f32tof16(float val)\n" - " {\n" - " uint f32 = floatBitsToUint(val);\n" - " uint f16 = 0u;\n" - " uint sign = (f32 >> 16) & 0x8000u;\n" - " int exponent = int((f32 >> 23) & 0xFFu) - 127;\n" - " uint mantissa = f32 & 0x007FFFFFu;\n" - " if (exponent == 128)\n" - " {\n" - " // Infinity or NaN\n" - " // NaN bits that are masked out by 0x3FF get discarded.\n" - " // This can turn some NaNs to infinity, but this is allowed by the spec.\n" - " f16 = sign | (0x1Fu << 10);\n" - " f16 |= (mantissa & 0x3FFu);\n" - " }\n" - " else if (exponent > 15)\n" - " {\n" - " // Overflow - flush to Infinity\n" - " f16 = sign | (0x1Fu << 10);\n" - " }\n" - " else if (exponent > -15)\n" - " {\n" - " // Representable value\n" - " exponent += 15;\n" - " mantissa >>= 13;\n" - " f16 = sign | uint(exponent << 10) | mantissa;\n" - " }\n" - " else\n" - " {\n" - " f16 = sign;\n" - " }\n" - " return f16;\n" - " }\n" - "#endif\n" - "\n" - "uint packHalf2x16_emu(vec2 v)\n" - "{\n" - " #if defined(GL_ARB_shading_language_packing)\n" - " return packHalf2x16(v);\n" - " #else\n" - " uint x = f32tof16(v.x);\n" - " uint y = f32tof16(v.y);\n" - " return (y << 16) | x;\n" - " #endif\n" - "}\n"); - emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1, - "#if !defined(GL_ARB_shading_language_packing)\n" - " float f16tof32(uint val)\n" - " {\n" - " uint sign = (val & 0x8000u) << 16;\n" - " int exponent = int((val & 0x7C00u) >> 10);\n" - " uint mantissa = val & 0x03FFu;\n" - " float f32 = 0.0;\n" - " if(exponent == 0)\n" - " {\n" - " if (mantissa != 0u)\n" - " {\n" - " const float scale = 1.0 / (1 << 24);\n" - " f32 = scale * mantissa;\n" - " }\n" - " }\n" - " else if (exponent == 31)\n" - " {\n" - " return uintBitsToFloat(sign | 0x7F800000u | mantissa);\n" - " }\n" - " else\n" - " {\n" - " exponent -= 15;\n" - " float scale;\n" - " if(exponent < 0)\n" - " {\n" - " // The negative unary operator is buggy on OSX.\n" - " // Work around this by using abs instead.\n" - " scale = 1.0 / (1 << abs(exponent));\n" - " }\n" - " else\n" - " {\n" - " scale = 1 << exponent;\n" - " }\n" - " float decimal = 1.0 + float(mantissa) / float(1 << 10);\n" - " f32 = scale * decimal;\n" - " }\n" - "\n" - " if (sign != 0u)\n" - " {\n" - " f32 = -f32;\n" - " }\n" - "\n" - " return f32;\n" - " }\n" - "#endif\n" - "\n" - "vec2 unpackHalf2x16_emu(uint u)\n" - "{\n" - " #if defined(GL_ARB_shading_language_packing)\n" - " return unpackHalf2x16(u);\n" - " #else\n" - " uint y = (u >> 16);\n" - " uint x = u & 0xFFFFu;\n" - " return vec2(f16tof32(x), f16tof32(y));\n" - " #endif\n" - "}\n"); - // clang-format on - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h deleted file mode 100644 index e1b4779bd5..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ -#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ - -#include "GLSLANG/ShaderLang.h" - -namespace sh -{ -class BuiltInFunctionEmulator; - -// -// This works around bug in Intel Mac drivers. -// -void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, - sh::GLenum shaderType); - -// -// This works around isnan() bug in Intel Mac drivers -// -void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, - int targetGLSLVersion); -// -// This works around atan(y, x) bug in NVIDIA drivers. -// -void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu); - -// -// This function is emulating built-in functions missing from GLSL 1.30 and higher. -// -void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu, - sh::GLenum shaderType, - int targetGLSLVersion); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp deleted file mode 100644 index e78d86d00a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp +++ /dev/null @@ -1,184 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "angle_gl.h" -#include "compiler/translator/BuiltInFunctionEmulator.h" -#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/VersionGLSL.h" - -namespace sh -{ - -// Defined in emulated_builtin_functions_hlsl_autogen.cpp. -const char *FindHLSLFunction(const FunctionId &functionID); - -void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu, - int targetGLSLVersion) -{ - if (targetGLSLVersion < GLSL_VERSION_130) - return; - - TType *float1 = new TType(EbtFloat); - TType *float2 = new TType(EbtFloat, 2); - TType *float3 = new TType(EbtFloat, 3); - TType *float4 = new TType(EbtFloat, 4); - - emu->addEmulatedFunction(EOpIsNan, float1, - "bool isnan_emu(float x)\n" - "{\n" - " return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n" - "}\n" - "\n"); - - emu->addEmulatedFunction( - EOpIsNan, float2, - "bool2 isnan_emu(float2 x)\n" - "{\n" - " bool2 isnan;\n" - " for (int i = 0; i < 2; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); - - emu->addEmulatedFunction( - EOpIsNan, float3, - "bool3 isnan_emu(float3 x)\n" - "{\n" - " bool3 isnan;\n" - " for (int i = 0; i < 3; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); - - emu->addEmulatedFunction( - EOpIsNan, float4, - "bool4 isnan_emu(float4 x)\n" - "{\n" - " bool4 isnan;\n" - " for (int i = 0; i < 4; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); -} - -void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu) -{ - TType *int1 = new TType(EbtInt); - TType *int2 = new TType(EbtInt, 2); - TType *int3 = new TType(EbtInt, 3); - TType *int4 = new TType(EbtInt, 4); - TType *uint1 = new TType(EbtUInt); - TType *uint2 = new TType(EbtUInt, 2); - TType *uint3 = new TType(EbtUInt, 3); - TType *uint4 = new TType(EbtUInt, 4); - - emu->addFunctionMap(FindHLSLFunction); - - // (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32 - // Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because: - // a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000 - FunctionId umulExtendedUint1 = emu->addEmulatedFunction( - EOpUmulExtended, uint1, uint1, uint1, uint1, - "void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n" - "{\n" - " lsb = x * y;\n" - " uint a = (x & 0xffffu);\n" - " uint b = (x >> 16);\n" - " uint c = (y & 0xffffu);\n" - " uint d = (y >> 16);\n" - " uint ad = a * d + ((a * c) >> 16);\n" - " uint bc = b * c;\n" - " uint carry = uint(ad > (0xffffffffu - bc));\n" - " msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n" - "}\n"); - emu->addEmulatedFunctionWithDependency( - umulExtendedUint1, EOpUmulExtended, uint2, uint2, uint2, uint2, - "void umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n" - "{\n" - " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" - " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" - "}\n"); - emu->addEmulatedFunctionWithDependency( - umulExtendedUint1, EOpUmulExtended, uint3, uint3, uint3, uint3, - "void umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n" - "{\n" - " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" - " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" - " umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" - "}\n"); - emu->addEmulatedFunctionWithDependency( - umulExtendedUint1, EOpUmulExtended, uint4, uint4, uint4, uint4, - "void umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n" - "{\n" - " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" - " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" - " umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" - " umulExtended_emu(x.w, y.w, msb.w, lsb.w);\n" - "}\n"); - - // The imul emulation does two's complement negation on the lsb and msb manually in case the - // result needs to be negative. - // TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is - // -2^31. abs(-2^31) is undefined. - FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency( - umulExtendedUint1, EOpImulExtended, int1, int1, int1, int1, - "void imulExtended_emu(int x, int y, out int msb, out int lsb)\n" - "{\n" - " uint unsignedMsb;\n" - " uint unsignedLsb;\n" - " bool negative = (x < 0) != (y < 0);\n" - " umulExtended_emu(uint(abs(x)), uint(abs(y)), unsignedMsb, unsignedLsb);\n" - " lsb = asint(unsignedLsb);\n" - " msb = asint(unsignedMsb);\n" - " if (negative)\n" - " {\n" - " lsb = ~lsb;\n" - " msb = ~msb;\n" - " if (lsb == 0xffffffff)\n" - " {\n" - " lsb = 0;\n" - " msb += 1;\n" - " }\n" - " else\n" - " {\n" - " lsb += 1;\n" - " }\n" - " }\n" - "}\n"); - emu->addEmulatedFunctionWithDependency( - imulExtendedInt1, EOpImulExtended, int2, int2, int2, int2, - "void imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n" - "{\n" - " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" - " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" - "}\n"); - emu->addEmulatedFunctionWithDependency( - imulExtendedInt1, EOpImulExtended, int3, int3, int3, int3, - "void imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n" - "{\n" - " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" - " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" - " imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" - "}\n"); - emu->addEmulatedFunctionWithDependency( - imulExtendedInt1, EOpImulExtended, int4, int4, int4, int4, - "void imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n" - "{\n" - " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" - " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" - " imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" - " imulExtended_emu(x.w, y.w, msb.w, lsb.w);\n" - "}\n"); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h deleted file mode 100644 index 48da73f58e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ -#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ - -#include "GLSLANG/ShaderLang.h" - -namespace sh -{ - -class BuiltInFunctionEmulator; - -void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu); - -// -// This works around isnan() bug on some Intel drivers. -// -void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu, - int targetGLSLVersion); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Cache.cpp b/src/3rdparty/angle/src/compiler/translator/Cache.cpp deleted file mode 100644 index 417e82403a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Cache.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Cache.cpp: Implements a cache for various commonly created objects. - -#include <limits> - -#include "common/angleutils.h" -#include "common/debug.h" -#include "compiler/translator/Cache.h" - -namespace sh -{ - -namespace -{ - -class TScopedAllocator : angle::NonCopyable -{ - public: - TScopedAllocator(TPoolAllocator *allocator) : mPreviousAllocator(GetGlobalPoolAllocator()) - { - SetGlobalPoolAllocator(allocator); - } - ~TScopedAllocator() { SetGlobalPoolAllocator(mPreviousAllocator); } - - private: - TPoolAllocator *mPreviousAllocator; -}; - -} // namespace - -TCache::TypeKey::TypeKey(TBasicType basicType, - TPrecision precision, - TQualifier qualifier, - unsigned char primarySize, - unsigned char secondarySize) -{ - static_assert(sizeof(components) <= sizeof(value), "TypeKey::value is too small"); - - const size_t MaxEnumValue = std::numeric_limits<EnumComponentType>::max(); - - // TODO: change to static_assert() once we deprecate MSVC 2013 support - ASSERT(MaxEnumValue >= EbtLast && MaxEnumValue >= EbpLast && MaxEnumValue >= EvqLast && - "TypeKey::EnumComponentType is too small"); - - value = 0; - components.basicType = static_cast<EnumComponentType>(basicType); - components.precision = static_cast<EnumComponentType>(precision); - components.qualifier = static_cast<EnumComponentType>(qualifier); - components.primarySize = primarySize; - components.secondarySize = secondarySize; -} - -TCache *TCache::sCache = nullptr; - -TCache::TCache() -{ -} - -void TCache::initialize() -{ - if (sCache == nullptr) - { - sCache = new TCache(); - } -} - -void TCache::destroy() -{ - SafeDelete(sCache); -} - -const TType *TCache::getType(TBasicType basicType, - TPrecision precision, - TQualifier qualifier, - unsigned char primarySize, - unsigned char secondarySize) -{ - TypeKey key(basicType, precision, qualifier, primarySize, secondarySize); - auto it = sCache->mTypes.find(key); - if (it != sCache->mTypes.end()) - { - return it->second; - } - - TScopedAllocator scopedAllocator(&sCache->mAllocator); - - TType *type = new TType(basicType, precision, qualifier, primarySize, secondarySize); - type->realize(); - sCache->mTypes.insert(std::make_pair(key, type)); - - return type; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/Cache.h b/src/3rdparty/angle/src/compiler/translator/Cache.h deleted file mode 100644 index a182b07f51..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Cache.h +++ /dev/null @@ -1,84 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Cache.h: Implements a cache for various commonly created objects. - -#ifndef COMPILER_TRANSLATOR_CACHE_H_ -#define COMPILER_TRANSLATOR_CACHE_H_ - -#include <stdint.h> -#include <string.h> -#include <map> - -#include "compiler/translator/Types.h" -#include "compiler/translator/PoolAlloc.h" - -namespace sh -{ - -class TCache -{ - public: - static void initialize(); - static void destroy(); - - static const TType *getType(TBasicType basicType, TPrecision precision) - { - return getType(basicType, precision, EvqTemporary, 1, 1); - } - static const TType *getType(TBasicType basicType, - unsigned char primarySize = 1, - unsigned char secondarySize = 1) - { - return getType(basicType, EbpUndefined, EvqGlobal, primarySize, secondarySize); - } - static const TType *getType(TBasicType basicType, - TQualifier qualifier, - unsigned char primarySize = 1, - unsigned char secondarySize = 1) - { - return getType(basicType, EbpUndefined, qualifier, primarySize, secondarySize); - } - static const TType *getType(TBasicType basicType, - TPrecision precision, - TQualifier qualifier, - unsigned char primarySize, - unsigned char secondarySize); - - private: - TCache(); - - union TypeKey { - TypeKey(TBasicType basicType, - TPrecision precision, - TQualifier qualifier, - unsigned char primarySize, - unsigned char secondarySize); - - typedef uint8_t EnumComponentType; - struct - { - EnumComponentType basicType; - EnumComponentType precision; - EnumComponentType qualifier; - unsigned char primarySize; - unsigned char secondarySize; - } components; - uint64_t value; - - bool operator<(const TypeKey &other) const { return value < other.value; } - }; - typedef std::map<TypeKey, const TType *> TypeMap; - - TypeMap mTypes; - TPoolAllocator mAllocator; - - static TCache *sCache; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_CACHE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/CallDAG.cpp b/src/3rdparty/angle/src/compiler/translator/CallDAG.cpp deleted file mode 100644 index 5f54e80898..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/CallDAG.cpp +++ /dev/null @@ -1,346 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// CallDAG.h: Implements a call graph DAG of functions to be re-used accross -// analyses, allows to efficiently traverse the functions in topological -// order. - -#include "compiler/translator/CallDAG.h" - -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -// The CallDAGCreator does all the processing required to create the CallDAG -// structure so that the latter contains only the necessary variables. -class CallDAG::CallDAGCreator : public TIntermTraverser -{ - public: - CallDAGCreator(TDiagnostics *diagnostics) - : TIntermTraverser(true, false, true), - mDiagnostics(diagnostics), - mCurrentFunction(nullptr), - mCurrentIndex(0) - { - } - - InitResult assignIndices() - { - int skipped = 0; - for (auto &it : mFunctions) - { - // Skip unimplemented functions - if (it.second.node) - { - InitResult result = assignIndicesInternal(&it.second); - if (result != INITDAG_SUCCESS) - { - return result; - } - } - else - { - skipped++; - } - } - - ASSERT(mFunctions.size() == mCurrentIndex + skipped); - return INITDAG_SUCCESS; - } - - void fillDataStructures(std::vector<Record> *records, std::map<int, int> *idToIndex) - { - ASSERT(records->empty()); - ASSERT(idToIndex->empty()); - - records->resize(mCurrentIndex); - - for (auto &it : mFunctions) - { - CreatorFunctionData &data = it.second; - // Skip unimplemented functions - if (!data.node) - { - continue; - } - ASSERT(data.index < records->size()); - Record &record = (*records)[data.index]; - - record.name = data.name.data(); - record.node = data.node; - - record.callees.reserve(data.callees.size()); - for (auto &callee : data.callees) - { - record.callees.push_back(static_cast<int>(callee->index)); - } - - (*idToIndex)[data.node->getFunctionSymbolInfo()->getId().get()] = - static_cast<int>(data.index); - } - } - - private: - struct CreatorFunctionData - { - CreatorFunctionData() : node(nullptr), index(0), indexAssigned(false), visiting(false) {} - - std::set<CreatorFunctionData *> callees; - TIntermFunctionDefinition *node; - TString name; - size_t index; - bool indexAssigned; - bool visiting; - }; - - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override - { - // Create the record if need be and remember the node. - if (visit == PreVisit) - { - auto it = mFunctions.find(node->getFunctionSymbolInfo()->getId().get()); - - if (it == mFunctions.end()) - { - mCurrentFunction = &mFunctions[node->getFunctionSymbolInfo()->getId().get()]; - mCurrentFunction->name = node->getFunctionSymbolInfo()->getName(); - } - else - { - mCurrentFunction = &it->second; - ASSERT(mCurrentFunction->name == node->getFunctionSymbolInfo()->getName()); - } - - mCurrentFunction->node = node; - } - else if (visit == PostVisit) - { - mCurrentFunction = nullptr; - } - return true; - } - - bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override - { - ASSERT(visit == PreVisit); - if (mCurrentFunction != nullptr) - { - return false; - } - - // Function declaration, create an empty record. - auto &record = mFunctions[node->getFunctionSymbolInfo()->getId().get()]; - record.name = node->getFunctionSymbolInfo()->getName(); - - // No need to traverse the parameters. - return false; - } - - // Aggregates the AST node for each function as well as the name of the functions called by it - bool visitAggregate(Visit visit, TIntermAggregate *node) override - { - if (visit == PreVisit && node->getOp() == EOpCallFunctionInAST) - { - // Function call, add the callees - auto it = mFunctions.find(node->getFunctionSymbolInfo()->getId().get()); - ASSERT(it != mFunctions.end()); - - // We might be traversing the initializer of a global variable. Even though function - // calls in global scope are forbidden by the parser, some subsequent AST - // transformations can add them to emulate particular features. - if (mCurrentFunction) - { - mCurrentFunction->callees.insert(&it->second); - } - } - return true; - } - - // Recursively assigns indices to a sub DAG - InitResult assignIndicesInternal(CreatorFunctionData *root) - { - // Iterative implementation of the index assignment algorithm. A recursive version - // would be prettier but since the CallDAG creation runs before the limiting of the - // call depth, we might get stack overflows (computation of the call depth uses the - // CallDAG). - - ASSERT(root); - - if (root->indexAssigned) - { - return INITDAG_SUCCESS; - } - - // If we didn't have to detect recursion, functionsToProcess could be a simple queue - // in which we add the function being processed's callees. However in order to detect - // recursion we need to know which functions we are currently visiting. For that reason - // functionsToProcess will look like a concatenation of segments of the form - // [F visiting = true, subset of F callees with visiting = false] and the following - // segment (if any) will be start with a callee of F. - // This way we can remember when we started visiting a function, to put visiting back - // to false. - TVector<CreatorFunctionData *> functionsToProcess; - functionsToProcess.push_back(root); - - InitResult result = INITDAG_SUCCESS; - - std::stringstream errorStream; - - while (!functionsToProcess.empty()) - { - CreatorFunctionData *function = functionsToProcess.back(); - - if (function->visiting) - { - function->visiting = false; - function->index = mCurrentIndex++; - function->indexAssigned = true; - - functionsToProcess.pop_back(); - continue; - } - - if (!function->node) - { - errorStream << "Undefined function '" << function->name - << ")' used in the following call chain:"; - result = INITDAG_UNDEFINED; - break; - } - - if (function->indexAssigned) - { - functionsToProcess.pop_back(); - continue; - } - - function->visiting = true; - - for (auto callee : function->callees) - { - functionsToProcess.push_back(callee); - - // Check if the callee is already being visited after pushing it so that it appears - // in the chain printed in the info log. - if (callee->visiting) - { - errorStream << "Recursive function call in the following call chain:"; - result = INITDAG_RECURSION; - break; - } - } - - if (result != INITDAG_SUCCESS) - { - break; - } - } - - // The call chain is made of the function we were visiting when the error was detected. - if (result != INITDAG_SUCCESS) - { - bool first = true; - for (auto function : functionsToProcess) - { - if (function->visiting) - { - if (!first) - { - errorStream << " -> "; - } - errorStream << function->name << ")"; - first = false; - } - } - if (mDiagnostics) - { - std::string errorStr = errorStream.str(); - mDiagnostics->globalError(errorStr.c_str()); - } - } - - return result; - } - - TDiagnostics *mDiagnostics; - - std::map<int, CreatorFunctionData> mFunctions; - CreatorFunctionData *mCurrentFunction; - size_t mCurrentIndex; -}; - -// CallDAG - -CallDAG::CallDAG() -{ -} - -CallDAG::~CallDAG() -{ -} - -const size_t CallDAG::InvalidIndex = std::numeric_limits<size_t>::max(); - -size_t CallDAG::findIndex(const TFunctionSymbolInfo *functionInfo) const -{ - auto it = mFunctionIdToIndex.find(functionInfo->getId().get()); - - if (it == mFunctionIdToIndex.end()) - { - return InvalidIndex; - } - else - { - return it->second; - } -} - -const CallDAG::Record &CallDAG::getRecordFromIndex(size_t index) const -{ - ASSERT(index != InvalidIndex && index < mRecords.size()); - return mRecords[index]; -} - -const CallDAG::Record &CallDAG::getRecord(const TIntermAggregate *function) const -{ - size_t index = findIndex(function->getFunctionSymbolInfo()); - ASSERT(index != InvalidIndex && index < mRecords.size()); - return mRecords[index]; -} - -size_t CallDAG::size() const -{ - return mRecords.size(); -} - -void CallDAG::clear() -{ - mRecords.clear(); - mFunctionIdToIndex.clear(); -} - -CallDAG::InitResult CallDAG::init(TIntermNode *root, TDiagnostics *diagnostics) -{ - CallDAGCreator creator(diagnostics); - - // Creates the mapping of functions to callees - root->traverse(&creator); - - // Does the topological sort and detects recursions - InitResult result = creator.assignIndices(); - if (result != INITDAG_SUCCESS) - { - return result; - } - - creator.fillDataStructures(&mRecords, &mFunctionIdToIndex); - return INITDAG_SUCCESS; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/CallDAG.h b/src/3rdparty/angle/src/compiler/translator/CallDAG.h deleted file mode 100644 index 155081c9a2..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/CallDAG.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// CallDAG.h: Defines a call graph DAG of functions to be re-used accross -// analyses, allows to efficiently traverse the functions in topological -// order. - -#ifndef COMPILER_TRANSLATOR_CALLDAG_H_ -#define COMPILER_TRANSLATOR_CALLDAG_H_ - -#include <map> - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -// The translator needs to analyze the the graph of the function calls -// to run checks and analyses; since in GLSL recursion is not allowed -// that graph is a DAG. -// This class is used to precompute that function call DAG so that it -// can be reused by multiple analyses. -// -// It stores a vector of function records, with one record per function. -// Records are accessed by index but a function symbol id can be converted -// to the index of the corresponding record. The records mostly contain the -// AST node of the function and the indices of the function's callees. -// -// In addition, records are in reverse topological order: a function F being -// called by a function G will have index index(F) < index(G), that way -// depth-first analysis becomes analysis in the order of indices. - -class CallDAG : angle::NonCopyable -{ - public: - CallDAG(); - ~CallDAG(); - - struct Record - { - std::string name; - TIntermFunctionDefinition *node; - std::vector<int> callees; - }; - - enum InitResult - { - INITDAG_SUCCESS, - INITDAG_RECURSION, - INITDAG_UNDEFINED, - }; - - // Returns INITDAG_SUCCESS if it was able to create the DAG, otherwise prints - // the initialization error in diagnostics, if present. - InitResult init(TIntermNode *root, TDiagnostics *diagnostics); - - // Returns InvalidIndex if the function wasn't found - size_t findIndex(const TFunctionSymbolInfo *functionInfo) const; - - const Record &getRecordFromIndex(size_t index) const; - const Record &getRecord(const TIntermAggregate *function) const; - size_t size() const; - void clear(); - - const static size_t InvalidIndex; - - private: - std::vector<Record> mRecords; - std::map<int, int> mFunctionIdToIndex; - - class CallDAGCreator; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_CALLDAG_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp b/src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp deleted file mode 100644 index 8598a137f5..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ClampPointSize.cpp: Limit the value that is written to gl_PointSize. -// - -#include "compiler/translator/ClampPointSize.h" - -#include "compiler/translator/FindSymbolNode.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/RunAtTheEndOfShader.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbolTable) -{ - // Only clamp gl_PointSize if it's used in the shader. - if (!FindSymbolNode(root, TString("gl_PointSize"), EbtFloat)) - { - return; - } - - TIntermSymbol *pointSizeNode = ReferenceBuiltInVariable("gl_PointSize", *symbolTable, 100); - - TConstantUnion *maxPointSizeConstant = new TConstantUnion(); - maxPointSizeConstant->setFConst(maxPointSize); - TIntermConstantUnion *maxPointSizeNode = - new TIntermConstantUnion(maxPointSizeConstant, TType(EbtFloat, EbpHigh, EvqConst)); - - // min(gl_PointSize, maxPointSize) - TIntermSequence *minArguments = new TIntermSequence(); - minArguments->push_back(pointSizeNode->deepCopy()); - minArguments->push_back(maxPointSizeNode); - TIntermTyped *clampedPointSize = - CreateBuiltInFunctionCallNode("min", minArguments, *symbolTable, 100); - - // gl_PointSize = min(gl_PointSize, maxPointSize) - TIntermBinary *assignPointSize = new TIntermBinary(EOpAssign, pointSizeNode, clampedPointSize); - - RunAtTheEndOfShader(root, assignPointSize, symbolTable); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ClampPointSize.h b/src/3rdparty/angle/src/compiler/translator/ClampPointSize.h deleted file mode 100644 index 0c71ae6b0d..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ClampPointSize.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ClampPointSize.h: Limit the value that is written to gl_PointSize. -// - -#ifndef COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_ -#define COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_ - -namespace sh -{ - -class TIntermBlock; -class TSymbolTable; - -void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp deleted file mode 100644 index 3e25cc2339..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifdef ANGLE_ENABLE_ESSL -#include "compiler/translator/TranslatorESSL.h" -#endif // ANGLE_ENABLE_ESSL - -#ifdef ANGLE_ENABLE_GLSL -#include "compiler/translator/TranslatorGLSL.h" -#endif // ANGLE_ENABLE_GLSL - -#ifdef ANGLE_ENABLE_HLSL -#include "compiler/translator/TranslatorHLSL.h" -#endif // ANGLE_ENABLE_HLSL - -#ifdef ANGLE_ENABLE_VULKAN -#include "compiler/translator/TranslatorVulkan.h" -#endif // ANGLE_ENABLE_VULKAN - -#include "compiler/translator/util.h" - -namespace sh -{ - -// -// This function must be provided to create the actual -// compile object used by higher level code. It returns -// a subclass of TCompiler. -// -TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) -{ -#ifdef ANGLE_ENABLE_ESSL - if (IsOutputESSL(output)) - { - return new TranslatorESSL(type, spec); - } -#endif // ANGLE_ENABLE_ESSL - -#ifdef ANGLE_ENABLE_GLSL - if (IsOutputGLSL(output)) - { - return new TranslatorGLSL(type, spec, output); - } -#endif // ANGLE_ENABLE_GLSL - -#ifdef ANGLE_ENABLE_HLSL - if (IsOutputHLSL(output)) - { - return new TranslatorHLSL(type, spec, output); - } -#endif // ANGLE_ENABLE_HLSL - -#ifdef ANGLE_ENABLE_VULKAN - if (IsOutputVulkan(output)) - { - return new TranslatorVulkan(type, spec); - } -#endif // ANGLE_ENABLE_VULKAN - - // Unsupported compiler or unknown format. Return nullptr per the sh::ConstructCompiler API. - return nullptr; -} - -// -// Delete the compiler made by ConstructCompiler -// -void DeleteCompiler(TCompiler *compiler) -{ - SafeDelete(compiler); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp b/src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp deleted file mode 100644 index bd8cbc971a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp +++ /dev/null @@ -1,869 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// CollectVariables.cpp: Collect lists of shader interface variables based on the AST. - -#include "compiler/translator/CollectVariables.h" - -#include "angle_gl.h" -#include "common/utilities.h" -#include "compiler/translator/HashNames.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage) -{ - switch (blockStorage) - { - case EbsPacked: - return BLOCKLAYOUT_PACKED; - case EbsShared: - return BLOCKLAYOUT_SHARED; - case EbsStd140: - return BLOCKLAYOUT_STD140; - case EbsStd430: - return BLOCKLAYOUT_STD430; - default: - UNREACHABLE(); - return BLOCKLAYOUT_SHARED; - } -} - -// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks. -BlockType GetBlockType(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqUniform: - return BlockType::BLOCK_UNIFORM; - case EvqBuffer: - return BlockType::BLOCK_BUFFER; - case EvqPerVertexIn: - return BlockType::BLOCK_IN; - default: - UNREACHABLE(); - return BlockType::BLOCK_UNIFORM; - } -} - -template <class VarT> -VarT *FindVariable(const TString &name, std::vector<VarT> *infoList) -{ - // TODO(zmo): optimize this function. - for (size_t ii = 0; ii < infoList->size(); ++ii) - { - if ((*infoList)[ii].name.c_str() == name) - return &((*infoList)[ii]); - } - - return nullptr; -} - -// Note that this shouldn't be called for interface blocks - static use information is collected for -// individual fields in case of interface blocks. -void MarkStaticallyUsed(ShaderVariable *variable) -{ - if (!variable->staticUse) - { - if (variable->isStruct()) - { - // Conservatively assume all fields are statically used as well. - for (auto &field : variable->fields) - { - MarkStaticallyUsed(&field); - } - } - variable->staticUse = true; - } -} - -ShaderVariable *FindVariableInInterfaceBlock(const TString &name, - const TInterfaceBlock *interfaceBlock, - std::vector<InterfaceBlock> *infoList) -{ - ASSERT(interfaceBlock); - InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList); - ASSERT(namedBlock); - - // Set static use on the parent interface block here - namedBlock->staticUse = true; - return FindVariable(name, &namedBlock->fields); -} - -// Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs, -// and interface blocks. -class CollectVariablesTraverser : public TIntermTraverser -{ - public: - CollectVariablesTraverser(std::vector<Attribute> *attribs, - std::vector<OutputVariable> *outputVariables, - std::vector<Uniform> *uniforms, - std::vector<Varying> *inputVaryings, - std::vector<Varying> *outputVaryings, - std::vector<InterfaceBlock> *uniformBlocks, - std::vector<InterfaceBlock> *shaderStorageBlocks, - std::vector<InterfaceBlock> *inBlocks, - ShHashFunction64 hashFunction, - TSymbolTable *symbolTable, - int shaderVersion, - GLenum shaderType, - const TExtensionBehavior &extensionBehavior); - - void visitSymbol(TIntermSymbol *symbol) override; - bool visitDeclaration(Visit, TIntermDeclaration *node) override; - bool visitBinary(Visit visit, TIntermBinary *binaryNode) override; - - private: - std::string getMappedName(const TName &name) const; - - void setCommonVariableProperties(const TType &type, - const TName &name, - ShaderVariable *variableOut) const; - - Attribute recordAttribute(const TIntermSymbol &variable) const; - OutputVariable recordOutputVariable(const TIntermSymbol &variable) const; - Varying recordVarying(const TIntermSymbol &variable) const; - void recordInterfaceBlock(const TType &interfaceBlockType, - InterfaceBlock *interfaceBlock) const; - Uniform recordUniform(const TIntermSymbol &variable) const; - - void setBuiltInInfoFromSymbolTable(const char *name, ShaderVariable *info); - - void recordBuiltInVaryingUsed(const char *name, - bool *addedFlag, - std::vector<Varying> *varyings); - void recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag); - void recordBuiltInAttributeUsed(const char *name, bool *addedFlag); - InterfaceBlock *recordGLInUsed(const TType &glInType); - InterfaceBlock *findNamedInterfaceBlock(const TString &name) const; - - std::vector<Attribute> *mAttribs; - std::vector<OutputVariable> *mOutputVariables; - std::vector<Uniform> *mUniforms; - std::vector<Varying> *mInputVaryings; - std::vector<Varying> *mOutputVaryings; - std::vector<InterfaceBlock> *mUniformBlocks; - std::vector<InterfaceBlock> *mShaderStorageBlocks; - std::vector<InterfaceBlock> *mInBlocks; - - std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields; - - // Shader uniforms - bool mDepthRangeAdded; - - // Vertex Shader builtins - bool mInstanceIDAdded; - bool mVertexIDAdded; - bool mPointSizeAdded; - - // Vertex Shader and Geometry Shader builtins - bool mPositionAdded; - - // Fragment Shader builtins - bool mPointCoordAdded; - bool mFrontFacingAdded; - bool mFragCoordAdded; - bool mLastFragDataAdded; - bool mFragColorAdded; - bool mFragDataAdded; - bool mFragDepthEXTAdded; - bool mFragDepthAdded; - bool mSecondaryFragColorEXTAdded; - bool mSecondaryFragDataEXTAdded; - - // Geometry Shader builtins - bool mPerVertexInAdded; - bool mPrimitiveIDInAdded; - bool mInvocationIDAdded; - - // Geometry Shader and Fragment Shader builtins - bool mPrimitiveIDAdded; - bool mLayerAdded; - - ShHashFunction64 mHashFunction; - - int mShaderVersion; - GLenum mShaderType; - const TExtensionBehavior &mExtensionBehavior; -}; - -CollectVariablesTraverser::CollectVariablesTraverser( - std::vector<sh::Attribute> *attribs, - std::vector<sh::OutputVariable> *outputVariables, - std::vector<sh::Uniform> *uniforms, - std::vector<sh::Varying> *inputVaryings, - std::vector<sh::Varying> *outputVaryings, - std::vector<sh::InterfaceBlock> *uniformBlocks, - std::vector<sh::InterfaceBlock> *shaderStorageBlocks, - std::vector<sh::InterfaceBlock> *inBlocks, - ShHashFunction64 hashFunction, - TSymbolTable *symbolTable, - int shaderVersion, - GLenum shaderType, - const TExtensionBehavior &extensionBehavior) - : TIntermTraverser(true, false, false, symbolTable), - mAttribs(attribs), - mOutputVariables(outputVariables), - mUniforms(uniforms), - mInputVaryings(inputVaryings), - mOutputVaryings(outputVaryings), - mUniformBlocks(uniformBlocks), - mShaderStorageBlocks(shaderStorageBlocks), - mInBlocks(inBlocks), - mDepthRangeAdded(false), - mInstanceIDAdded(false), - mVertexIDAdded(false), - mPointSizeAdded(false), - mPositionAdded(false), - mPointCoordAdded(false), - mFrontFacingAdded(false), - mFragCoordAdded(false), - mLastFragDataAdded(false), - mFragColorAdded(false), - mFragDataAdded(false), - mFragDepthEXTAdded(false), - mFragDepthAdded(false), - mSecondaryFragColorEXTAdded(false), - mSecondaryFragDataEXTAdded(false), - mPerVertexInAdded(false), - mPrimitiveIDInAdded(false), - mInvocationIDAdded(false), - mPrimitiveIDAdded(false), - mLayerAdded(false), - mHashFunction(hashFunction), - mShaderVersion(shaderVersion), - mShaderType(shaderType), - mExtensionBehavior(extensionBehavior) -{ -} - -std::string CollectVariablesTraverser::getMappedName(const TName &name) const -{ - return HashName(name, mHashFunction, nullptr).c_str(); -} - -void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const char *name, - ShaderVariable *info) -{ - TVariable *symbolTableVar = - reinterpret_cast<TVariable *>(mSymbolTable->findBuiltIn(name, mShaderVersion)); - ASSERT(symbolTableVar); - const TType &type = symbolTableVar->getType(); - - info->name = name; - info->mappedName = name; - info->type = GLVariableType(type); - info->precision = GLVariablePrecision(type); - if (auto *arraySizes = type.getArraySizes()) - { - info->arraySizes.assign(arraySizes->begin(), arraySizes->end()); - } -} - -void CollectVariablesTraverser::recordBuiltInVaryingUsed(const char *name, - bool *addedFlag, - std::vector<Varying> *varyings) -{ - ASSERT(varyings); - if (!(*addedFlag)) - { - Varying info; - setBuiltInInfoFromSymbolTable(name, &info); - info.staticUse = true; - info.isInvariant = mSymbolTable->isVaryingInvariant(name); - varyings->push_back(info); - (*addedFlag) = true; - } -} - -void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag) -{ - if (!(*addedFlag)) - { - OutputVariable info; - setBuiltInInfoFromSymbolTable(name, &info); - info.staticUse = true; - mOutputVariables->push_back(info); - (*addedFlag) = true; - } -} - -void CollectVariablesTraverser::recordBuiltInAttributeUsed(const char *name, bool *addedFlag) -{ - if (!(*addedFlag)) - { - Attribute info; - setBuiltInInfoFromSymbolTable(name, &info); - info.staticUse = true; - info.location = -1; - mAttribs->push_back(info); - (*addedFlag) = true; - } -} - -InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType) -{ - if (!mPerVertexInAdded) - { - ASSERT(glInType.getQualifier() == EvqPerVertexIn); - InterfaceBlock info; - recordInterfaceBlock(glInType, &info); - info.staticUse = true; - - mPerVertexInAdded = true; - mInBlocks->push_back(info); - return &mInBlocks->back(); - } - else - { - return FindVariable("gl_PerVertex", mInBlocks); - } -} - -// We want to check whether a uniform/varying is statically used -// because we only count the used ones in packing computing. -// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count -// toward varying counting if they are statically used in a fragment -// shader. -void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol) -{ - ASSERT(symbol != nullptr); - - if (symbol->getName().isInternal()) - { - // Internal variables are not collected. - return; - } - - ShaderVariable *var = nullptr; - const TString &symbolName = symbol->getName().getString(); - - if (IsVaryingIn(symbol->getQualifier())) - { - var = FindVariable(symbolName, mInputVaryings); - } - else if (IsVaryingOut(symbol->getQualifier())) - { - var = FindVariable(symbolName, mOutputVaryings); - } - else if (symbol->getType().getBasicType() == EbtInterfaceBlock) - { - UNREACHABLE(); - } - else if (symbolName == "gl_DepthRange") - { - ASSERT(symbol->getQualifier() == EvqUniform); - - if (!mDepthRangeAdded) - { - Uniform info; - const char kName[] = "gl_DepthRange"; - info.name = kName; - info.mappedName = kName; - info.type = GL_NONE; - info.precision = GL_NONE; - info.staticUse = true; - - ShaderVariable nearInfo(GL_FLOAT); - const char kNearName[] = "near"; - nearInfo.name = kNearName; - nearInfo.mappedName = kNearName; - nearInfo.precision = GL_HIGH_FLOAT; - nearInfo.staticUse = true; - - ShaderVariable farInfo(GL_FLOAT); - const char kFarName[] = "far"; - farInfo.name = kFarName; - farInfo.mappedName = kFarName; - farInfo.precision = GL_HIGH_FLOAT; - farInfo.staticUse = true; - - ShaderVariable diffInfo(GL_FLOAT); - const char kDiffName[] = "diff"; - diffInfo.name = kDiffName; - diffInfo.mappedName = kDiffName; - diffInfo.precision = GL_HIGH_FLOAT; - diffInfo.staticUse = true; - - info.fields.push_back(nearInfo); - info.fields.push_back(farInfo); - info.fields.push_back(diffInfo); - - mUniforms->push_back(info); - mDepthRangeAdded = true; - } - } - else - { - switch (symbol->getQualifier()) - { - case EvqAttribute: - case EvqVertexIn: - var = FindVariable(symbolName, mAttribs); - break; - case EvqFragmentOut: - var = FindVariable(symbolName, mOutputVariables); - break; - case EvqUniform: - { - const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock(); - if (interfaceBlock) - { - var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks); - } - else - { - var = FindVariable(symbolName, mUniforms); - } - - // It's an internal error to reference an undefined user uniform - ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var); - } - break; - case EvqBuffer: - { - const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock(); - var = - FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks); - } - break; - case EvqFragCoord: - recordBuiltInVaryingUsed("gl_FragCoord", &mFragCoordAdded, mInputVaryings); - return; - case EvqFrontFacing: - recordBuiltInVaryingUsed("gl_FrontFacing", &mFrontFacingAdded, mInputVaryings); - return; - case EvqPointCoord: - recordBuiltInVaryingUsed("gl_PointCoord", &mPointCoordAdded, mInputVaryings); - return; - case EvqInstanceID: - // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set, - // gl_InstanceID is added inside expressions to initialize ViewID_OVR and - // InstanceID. gl_InstanceID is not added to the symbol table for ESSL1 shaders - // which makes it necessary to populate the type information explicitly instead of - // extracting it from the symbol table. - if (!mInstanceIDAdded) - { - Attribute info; - const char kName[] = "gl_InstanceID"; - info.name = kName; - info.mappedName = kName; - info.type = GL_INT; - info.precision = GL_HIGH_INT; // Defined by spec. - info.staticUse = true; - info.location = -1; - mAttribs->push_back(info); - mInstanceIDAdded = true; - } - return; - case EvqVertexID: - recordBuiltInAttributeUsed("gl_VertexID", &mVertexIDAdded); - return; - case EvqPosition: - recordBuiltInVaryingUsed("gl_Position", &mPositionAdded, mOutputVaryings); - return; - case EvqPointSize: - recordBuiltInVaryingUsed("gl_PointSize", &mPointSizeAdded, mOutputVaryings); - return; - case EvqLastFragData: - recordBuiltInVaryingUsed("gl_LastFragData", &mLastFragDataAdded, mInputVaryings); - return; - case EvqFragColor: - recordBuiltInFragmentOutputUsed("gl_FragColor", &mFragColorAdded); - return; - case EvqFragData: - if (!mFragDataAdded) - { - OutputVariable info; - setBuiltInInfoFromSymbolTable("gl_FragData", &info); - if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers)) - { - ASSERT(info.arraySizes.size() == 1u); - info.arraySizes.back() = 1u; - } - info.staticUse = true; - mOutputVariables->push_back(info); - mFragDataAdded = true; - } - return; - case EvqFragDepthEXT: - recordBuiltInFragmentOutputUsed("gl_FragDepthEXT", &mFragDepthEXTAdded); - return; - case EvqFragDepth: - recordBuiltInFragmentOutputUsed("gl_FragDepth", &mFragDepthAdded); - return; - case EvqSecondaryFragColorEXT: - recordBuiltInFragmentOutputUsed("gl_SecondaryFragColorEXT", - &mSecondaryFragColorEXTAdded); - return; - case EvqSecondaryFragDataEXT: - recordBuiltInFragmentOutputUsed("gl_SecondaryFragDataEXT", - &mSecondaryFragDataEXTAdded); - return; - case EvqInvocationID: - recordBuiltInVaryingUsed("gl_InvocationID", &mInvocationIDAdded, mInputVaryings); - break; - case EvqPrimitiveIDIn: - recordBuiltInVaryingUsed("gl_PrimitiveIDIn", &mPrimitiveIDInAdded, mInputVaryings); - break; - case EvqPrimitiveID: - if (mShaderType == GL_GEOMETRY_SHADER_OES) - { - recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mOutputVaryings); - } - else - { - ASSERT(mShaderType == GL_FRAGMENT_SHADER); - recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mInputVaryings); - } - break; - case EvqLayer: - if (mShaderType == GL_GEOMETRY_SHADER_OES) - { - recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mOutputVaryings); - } - else if (mShaderType == GL_FRAGMENT_SHADER) - { - recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mInputVaryings); - } - else - { - ASSERT(mShaderType == GL_VERTEX_SHADER && - IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview)); - } - break; - default: - break; - } - } - if (var) - { - MarkStaticallyUsed(var); - } -} - -void CollectVariablesTraverser::setCommonVariableProperties(const TType &type, - const TName &name, - ShaderVariable *variableOut) const -{ - ASSERT(variableOut); - - const TStructure *structure = type.getStruct(); - - if (!structure) - { - variableOut->type = GLVariableType(type); - variableOut->precision = GLVariablePrecision(type); - } - else - { - // Structures use a NONE type that isn't exposed outside ANGLE. - variableOut->type = GL_NONE; - variableOut->structName = structure->name().c_str(); - - const TFieldList &fields = structure->fields(); - - for (TField *field : fields) - { - // Regardless of the variable type (uniform, in/out etc.) its fields are always plain - // ShaderVariable objects. - ShaderVariable fieldVariable; - setCommonVariableProperties(*field->type(), TName(field->name()), &fieldVariable); - variableOut->fields.push_back(fieldVariable); - } - } - variableOut->name = name.getString().c_str(); - variableOut->mappedName = getMappedName(name); - - if (auto *arraySizes = type.getArraySizes()) - { - variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end()); - } -} - -Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const -{ - const TType &type = variable.getType(); - ASSERT(!type.getStruct()); - - Attribute attribute; - setCommonVariableProperties(type, variable.getName(), &attribute); - - attribute.location = type.getLayoutQualifier().location; - return attribute; -} - -OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const -{ - const TType &type = variable.getType(); - ASSERT(!type.getStruct()); - - OutputVariable outputVariable; - setCommonVariableProperties(type, variable.getName(), &outputVariable); - - outputVariable.location = type.getLayoutQualifier().location; - return outputVariable; -} - -Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const -{ - const TType &type = variable.getType(); - - Varying varying; - setCommonVariableProperties(type, variable.getName(), &varying); - varying.location = type.getLayoutQualifier().location; - - switch (type.getQualifier()) - { - case EvqVaryingIn: - case EvqVaryingOut: - case EvqVertexOut: - case EvqSmoothOut: - case EvqFlatOut: - case EvqCentroidOut: - case EvqGeometryOut: - if (mSymbolTable->isVaryingInvariant(std::string(variable.getSymbol().c_str())) || - type.isInvariant()) - { - varying.isInvariant = true; - } - break; - default: - break; - } - - varying.interpolation = GetInterpolationType(type.getQualifier()); - return varying; -} - -// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks. -void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlockType, - InterfaceBlock *interfaceBlock) const -{ - ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock); - ASSERT(interfaceBlock); - - const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock(); - ASSERT(blockType); - - interfaceBlock->name = blockType->name().c_str(); - interfaceBlock->mappedName = getMappedName(TName(blockType->name())); - interfaceBlock->instanceName = - (blockType->hasInstanceName() ? blockType->instanceName().c_str() : ""); - ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9 - interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0; - - interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier()); - if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM || - interfaceBlock->blockType == BlockType::BLOCK_BUFFER) - { - interfaceBlock->isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor); - interfaceBlock->binding = blockType->blockBinding(); - interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage()); - } - - // Gather field information - for (const TField *field : blockType->fields()) - { - const TType &fieldType = *field->type(); - - InterfaceBlockField fieldVariable; - setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable); - fieldVariable.isRowMajorLayout = - (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); - interfaceBlock->fields.push_back(fieldVariable); - } -} - -Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const -{ - Uniform uniform; - setCommonVariableProperties(variable.getType(), variable.getName(), &uniform); - uniform.binding = variable.getType().getLayoutQualifier().binding; - uniform.location = variable.getType().getLayoutQualifier().location; - uniform.offset = variable.getType().getLayoutQualifier().offset; - return uniform; -} - -bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node) -{ - const TIntermSequence &sequence = *(node->getSequence()); - ASSERT(!sequence.empty()); - - const TIntermTyped &typedNode = *(sequence.front()->getAsTyped()); - TQualifier qualifier = typedNode.getQualifier(); - - bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn || - qualifier == EvqFragmentOut || qualifier == EvqUniform || - IsVarying(qualifier); - - if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable) - { - return true; - } - - for (TIntermNode *variableNode : sequence) - { - // The only case in which the sequence will not contain a TIntermSymbol node is - // initialization. It will contain a TInterBinary node in that case. Since attributes, - // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we - // must have only TIntermSymbol nodes in the sequence in the cases we are interested in. - const TIntermSymbol &variable = *variableNode->getAsSymbolNode(); - if (variable.getName().isInternal()) - { - // Internal variables are not collected. - continue; - } - - // TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks. - if (typedNode.getBasicType() == EbtInterfaceBlock) - { - InterfaceBlock interfaceBlock; - recordInterfaceBlock(variable.getType(), &interfaceBlock); - - switch (qualifier) - { - case EvqUniform: - mUniformBlocks->push_back(interfaceBlock); - break; - case EvqBuffer: - mShaderStorageBlocks->push_back(interfaceBlock); - break; - default: - UNREACHABLE(); - } - } - else - { - switch (qualifier) - { - case EvqAttribute: - case EvqVertexIn: - mAttribs->push_back(recordAttribute(variable)); - break; - case EvqFragmentOut: - mOutputVariables->push_back(recordOutputVariable(variable)); - break; - case EvqUniform: - mUniforms->push_back(recordUniform(variable)); - break; - default: - if (IsVaryingIn(qualifier)) - { - mInputVaryings->push_back(recordVarying(variable)); - } - else - { - ASSERT(IsVaryingOut(qualifier)); - mOutputVaryings->push_back(recordVarying(variable)); - } - break; - } - } - } - - // None of the recorded variables can have initializers, so we don't need to traverse the - // declarators. - return false; -} - -// TODO(jiawei.shao@intel.com): add search on mInBlocks and mOutBlocks when implementing -// GL_OES_shader_io_blocks. -InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock(const TString &blockName) const -{ - InterfaceBlock *namedBlock = FindVariable(blockName, mUniformBlocks); - if (!namedBlock) - { - namedBlock = FindVariable(blockName, mShaderStorageBlocks); - } - return namedBlock; -} - -bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode) -{ - if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock) - { - // NOTE: we do not determine static use for individual blocks of an array - TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped(); - ASSERT(blockNode); - - TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion(); - ASSERT(constantUnion); - - InterfaceBlock *namedBlock = nullptr; - - bool traverseIndexExpression = false; - TIntermBinary *interfaceIndexingNode = blockNode->getAsBinaryNode(); - if (interfaceIndexingNode) - { - TIntermTyped *interfaceNode = interfaceIndexingNode->getLeft()->getAsTyped(); - ASSERT(interfaceNode); - - const TType &interfaceType = interfaceNode->getType(); - if (interfaceType.getQualifier() == EvqPerVertexIn) - { - namedBlock = recordGLInUsed(interfaceType); - ASSERT(namedBlock); - - // We need to continue traversing to collect useful variables in the index - // expression of gl_in. - traverseIndexExpression = true; - } - } - - const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock(); - if (!namedBlock) - { - namedBlock = findNamedInterfaceBlock(interfaceBlock->name()); - } - ASSERT(namedBlock); - namedBlock->staticUse = true; - unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0)); - ASSERT(fieldIndex < namedBlock->fields.size()); - namedBlock->fields[fieldIndex].staticUse = true; - - if (traverseIndexExpression) - { - ASSERT(interfaceIndexingNode); - interfaceIndexingNode->getRight()->traverse(this); - } - return false; - } - - return true; -} - -} // anonymous namespace - -void CollectVariables(TIntermBlock *root, - std::vector<Attribute> *attributes, - std::vector<OutputVariable> *outputVariables, - std::vector<Uniform> *uniforms, - std::vector<Varying> *inputVaryings, - std::vector<Varying> *outputVaryings, - std::vector<InterfaceBlock> *uniformBlocks, - std::vector<InterfaceBlock> *shaderStorageBlocks, - std::vector<InterfaceBlock> *inBlocks, - ShHashFunction64 hashFunction, - TSymbolTable *symbolTable, - int shaderVersion, - GLenum shaderType, - const TExtensionBehavior &extensionBehavior) -{ - CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings, - outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks, - hashFunction, symbolTable, shaderVersion, shaderType, - extensionBehavior); - root->traverse(&collect); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/CollectVariables.h b/src/3rdparty/angle/src/compiler/translator/CollectVariables.h deleted file mode 100644 index 4d0d1192e0..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/CollectVariables.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// CollectVariables.h: Collect lists of shader interface variables based on the AST. - -#ifndef COMPILER_TRANSLATOR_COLLECTVARIABLES_H_ -#define COMPILER_TRANSLATOR_COLLECTVARIABLES_H_ - -#include <GLSLANG/ShaderLang.h> - -#include "compiler/translator/ExtensionBehavior.h" - -namespace sh -{ - -class TIntermBlock; -class TSymbolTable; - -void CollectVariables(TIntermBlock *root, - std::vector<Attribute> *attributes, - std::vector<OutputVariable> *outputVariables, - std::vector<Uniform> *uniforms, - std::vector<Varying> *inputVaryings, - std::vector<Varying> *outputVaryings, - std::vector<InterfaceBlock> *uniformBlocks, - std::vector<InterfaceBlock> *shaderStorageBlocks, - std::vector<InterfaceBlock> *inBlocks, - ShHashFunction64 hashFunction, - TSymbolTable *symbolTable, - int shaderVersion, - GLenum shaderType, - const TExtensionBehavior &extensionBehavior); -} - -#endif // COMPILER_TRANSLATOR_COLLECTVARIABLES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Common.h b/src/3rdparty/angle/src/compiler/translator/Common.h deleted file mode 100644 index cb3a680d85..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Common.h +++ /dev/null @@ -1,138 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_COMMON_H_ -#define COMPILER_TRANSLATOR_COMMON_H_ - -#include <map> -#include <sstream> -#include <string> -#include <unordered_map> -#include <vector> -#include <limits> -#include <stdio.h> - -#include "common/angleutils.h" -#include "common/debug.h" -#include "common/third_party/smhasher/src/PMurHash.h" -#include "compiler/translator/PoolAlloc.h" - -namespace sh -{ - -struct TSourceLoc -{ - int first_file; - int first_line; - int last_file; - int last_line; -}; - -// -// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. -// -#define POOL_ALLOCATOR_NEW_DELETE() \ - void *operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ - void *operator new(size_t, void *_Where) { return (_Where); } \ - void operator delete(void *) {} \ - void operator delete(void *, void *) {} \ - void *operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ - void *operator new[](size_t, void *_Where) { return (_Where); } \ - void operator delete[](void *) {} \ - void operator delete[](void *, void *) {} - -// -// Pool version of string. -// -typedef pool_allocator<char> TStringAllocator; -typedef std::basic_string<char, std::char_traits<char>, TStringAllocator> TString; -typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream; -inline TString *NewPoolTString(const char *s) -{ - void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TString)); - return new (memory) TString(s); -} - -// -// Persistent string memory. Should only be used for strings that survive -// across compiles. -// -#define TPersistString std::string -#define TPersistStringStream std::ostringstream - -// -// Pool allocator versions of vectors, lists, and maps -// -template <class T> -class TVector : public std::vector<T, pool_allocator<T>> -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - - typedef typename std::vector<T, pool_allocator<T>>::size_type size_type; - TVector() : std::vector<T, pool_allocator<T>>() {} - TVector(const pool_allocator<T> &a) : std::vector<T, pool_allocator<T>>(a) {} - TVector(size_type i) : std::vector<T, pool_allocator<T>>(i) {} -}; - -template <class K, class D, class H = std::hash<K>, class CMP = std::equal_to<K>> -class TUnorderedMap : public std::unordered_map<K, D, H, CMP, pool_allocator<std::pair<const K, D>>> -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - typedef pool_allocator<std::pair<const K, D>> tAllocator; - - TUnorderedMap() : std::unordered_map<K, D, H, CMP, tAllocator>() {} - // use correct two-stage name lookup supported in gcc 3.4 and above - TUnorderedMap(const tAllocator &a) - : std::unordered_map<K, D, H, CMP, tAllocator>( - std::unordered_map<K, D, H, CMP, tAllocator>::key_compare(), - a) - { - } -}; - -template <class K, class D, class CMP = std::less<K>> -class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D>>> -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - typedef pool_allocator<std::pair<const K, D>> tAllocator; - - TMap() : std::map<K, D, CMP, tAllocator>() {} - // use correct two-stage name lookup supported in gcc 3.4 and above - TMap(const tAllocator &a) - : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) - { - } -}; - -// Integer to TString conversion -template <typename T> -inline TString str(T i) -{ - ASSERT(std::numeric_limits<T>::is_integer); - char buffer[((8 * sizeof(T)) / 3) + 3]; - const char *formatStr = std::numeric_limits<T>::is_signed ? "%d" : "%u"; - snprintf(buffer, sizeof(buffer), formatStr, i); - return buffer; -} - -} // namespace sh - -namespace std -{ -template <> -struct hash<sh::TString> -{ - size_t operator()(const sh::TString &s) const - { - return angle::PMurHash32(0, s.data(), static_cast<int>(s.length())); - } -}; -} // namespace std - -#endif // COMPILER_TRANSLATOR_COMMON_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp deleted file mode 100644 index 2f411cb58c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp +++ /dev/null @@ -1,1169 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/Compiler.h" - -#include <sstream> - -#include "angle_gl.h" -#include "common/utilities.h" -#include "compiler/translator/AddAndTrueToLoopCondition.h" -#include "compiler/translator/Cache.h" -#include "compiler/translator/CallDAG.h" -#include "compiler/translator/ClampPointSize.h" -#include "compiler/translator/CollectVariables.h" -#include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h" -#include "compiler/translator/DeferGlobalInitializers.h" -#include "compiler/translator/EmulateGLFragColorBroadcast.h" -#include "compiler/translator/EmulatePrecision.h" -#include "compiler/translator/Initialize.h" -#include "compiler/translator/InitializeVariables.h" -#include "compiler/translator/IntermNodePatternMatcher.h" -#include "compiler/translator/IsASTDepthBelowLimit.h" -#include "compiler/translator/OutputTree.h" -#include "compiler/translator/ParseContext.h" -#include "compiler/translator/PruneNoOps.h" -#include "compiler/translator/RegenerateStructNames.h" -#include "compiler/translator/RemoveArrayLengthMethod.h" -#include "compiler/translator/RemoveEmptySwitchStatements.h" -#include "compiler/translator/RemoveInvariantDeclaration.h" -#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h" -#include "compiler/translator/RemovePow.h" -#include "compiler/translator/RemoveUnreferencedVariables.h" -#include "compiler/translator/RewriteDoWhile.h" -#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h" -#include "compiler/translator/SeparateDeclarations.h" -#include "compiler/translator/SimplifyLoopConditions.h" -#include "compiler/translator/SplitSequenceOperator.h" -#include "compiler/translator/UnfoldShortCircuitAST.h" -#include "compiler/translator/UseInterfaceBlockFields.h" -#include "compiler/translator/ValidateLimitations.h" -#include "compiler/translator/ValidateMaxParameters.h" -#include "compiler/translator/ValidateOutputs.h" -#include "compiler/translator/ValidateVaryingLocations.h" -#include "compiler/translator/VariablePacker.h" -#include "compiler/translator/VectorizeVectorScalarArithmetic.h" -#include "compiler/translator/util.h" -#include "third_party/compiler/ArrayBoundsClamper.h" - -namespace sh -{ - -namespace -{ - -#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT) -void DumpFuzzerCase(char const *const *shaderStrings, - size_t numStrings, - uint32_t type, - uint32_t spec, - uint32_t output, - uint64_t options) -{ - static int fileIndex = 0; - - std::ostringstream o; - o << "corpus/" << fileIndex++ << ".sample"; - std::string s = o.str(); - - // Must match the input format of the fuzzer - FILE *f = fopen(s.c_str(), "w"); - fwrite(&type, sizeof(type), 1, f); - fwrite(&spec, sizeof(spec), 1, f); - fwrite(&output, sizeof(output), 1, f); - fwrite(&options, sizeof(options), 1, f); - - char zero[128 - 20] = {0}; - fwrite(&zero, 128 - 20, 1, f); - - for (size_t i = 0; i < numStrings; i++) - { - fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f); - } - fwrite(&zero, 1, 1, f); - - fclose(f); -} -#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT) -} // anonymous namespace - -bool IsWebGLBasedSpec(ShShaderSpec spec) -{ - return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC); -} - -bool IsGLSL130OrNewer(ShShaderOutput output) -{ - return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT || - output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT || - output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT || - output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT || - output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT); -} - -bool IsGLSL420OrNewer(ShShaderOutput output) -{ - return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT || - output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT); -} - -bool IsGLSL410OrOlder(ShShaderOutput output) -{ - return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT || - output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT || - output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT); -} - -bool RemoveInvariant(sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput outputType, - ShCompileOptions compileOptions) -{ - if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 && - shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType)) - return true; - - if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 && - shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER) - return true; - - return false; -} - -size_t GetGlobalMaxTokenSize(ShShaderSpec spec) -{ - // WebGL defines a max token length of 256, while ES2 leaves max token - // size undefined. ES3 defines a max size of 1024 characters. - switch (spec) - { - case SH_WEBGL_SPEC: - return 256; - default: - return 1024; - } -} - -int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResources &resources) -{ - switch (shaderType) - { - case GL_VERTEX_SHADER: - return resources.MaxVertexUniformVectors; - case GL_FRAGMENT_SHADER: - return resources.MaxFragmentUniformVectors; - - // TODO (jiawei.shao@intel.com): check if we need finer-grained component counting - case GL_COMPUTE_SHADER: - return resources.MaxComputeUniformComponents / 4; - case GL_GEOMETRY_SHADER_OES: - return resources.MaxGeometryUniformComponents / 4; - default: - UNREACHABLE(); - return -1; - } -} - -namespace -{ - -class TScopedPoolAllocator -{ - public: - TScopedPoolAllocator(TPoolAllocator *allocator) : mAllocator(allocator) - { - mAllocator->push(); - SetGlobalPoolAllocator(mAllocator); - } - ~TScopedPoolAllocator() - { - SetGlobalPoolAllocator(nullptr); - mAllocator->pop(); - } - - private: - TPoolAllocator *mAllocator; -}; - -class TScopedSymbolTableLevel -{ - public: - TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table) - { - ASSERT(mTable->atBuiltInLevel()); - mTable->push(); - } - ~TScopedSymbolTableLevel() - { - while (!mTable->atBuiltInLevel()) - mTable->pop(); - } - - private: - TSymbolTable *mTable; -}; - -int MapSpecToShaderVersion(ShShaderSpec spec) -{ - switch (spec) - { - case SH_GLES2_SPEC: - case SH_WEBGL_SPEC: - return 100; - case SH_GLES3_SPEC: - case SH_WEBGL2_SPEC: - return 300; - case SH_GLES3_1_SPEC: - case SH_WEBGL3_SPEC: - return 310; - default: - UNREACHABLE(); - return 0; - } -} - -} // namespace - -TShHandleBase::TShHandleBase() -{ - allocator.push(); - SetGlobalPoolAllocator(&allocator); -} - -TShHandleBase::~TShHandleBase() -{ - SetGlobalPoolAllocator(nullptr); - allocator.popAll(); -} - -TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) - : variablesCollected(false), - mGLPositionInitialized(false), - shaderType(type), - shaderSpec(spec), - outputType(output), - maxUniformVectors(0), - maxExpressionComplexity(0), - maxCallStackDepth(0), - maxFunctionParameters(0), - fragmentPrecisionHigh(false), - clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), - builtInFunctionEmulator(), - mDiagnostics(infoSink.info), - mSourcePath(nullptr), - mComputeShaderLocalSizeDeclared(false), - mComputeShaderLocalSize(1), - mGeometryShaderMaxVertices(-1), - mGeometryShaderInvocations(0), - mGeometryShaderInputPrimitiveType(EptUndefined), - mGeometryShaderOutputPrimitiveType(EptUndefined) -{ -} - -TCompiler::~TCompiler() -{ -} - -bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const -{ - // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API, - // validate loop and indexing as well (to verify that the shader only uses minimal functionality - // of ESSL 1.00 as in Appendix A of the spec). - return (IsWebGLBasedSpec(shaderSpec) && shaderVersion == 100) || - (compileOptions & SH_VALIDATE_LOOP_INDEXING); -} - -bool TCompiler::Init(const ShBuiltInResources &resources) -{ - shaderVersion = 100; - - maxUniformVectors = GetMaxUniformVectorsForShaderType(shaderType, resources); - - maxExpressionComplexity = resources.MaxExpressionComplexity; - maxCallStackDepth = resources.MaxCallStackDepth; - maxFunctionParameters = resources.MaxFunctionParameters; - - SetGlobalPoolAllocator(&allocator); - - // Generate built-in symbol table. - if (!InitBuiltInSymbolTable(resources)) - return false; - InitExtensionBehavior(resources, extensionBehavior); - fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1; - - arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy); - clampingStrategy = resources.ArrayIndexClampingStrategy; - - hashFunction = resources.HashFunction; - - return true; -} - -TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptions) -{ - return compileTreeImpl(shaderStrings, numStrings, compileOptions); -} - -TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], - size_t numStrings, - const ShCompileOptions compileOptions) -{ - clearResults(); - - ASSERT(numStrings > 0); - ASSERT(GetGlobalPoolAllocator()); - - // Reset the extension behavior for each compilation unit. - ResetExtensionBehavior(extensionBehavior); - - // First string is path of source file if flag is set. The actual source follows. - size_t firstSource = 0; - if (compileOptions & SH_SOURCE_PATH) - { - mSourcePath = shaderStrings[0]; - ++firstSource; - } - - TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec, - compileOptions, true, &mDiagnostics, getResources()); - - parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh); - - // We preserve symbols at the built-in level from compile-to-compile. - // Start pushing the user-defined symbols at global level. - TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable); - - // Parse shader. - if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr, - &parseContext) != 0) - { - return nullptr; - } - - if (parseContext.getTreeRoot() == nullptr) - { - return nullptr; - } - - setASTMetadata(parseContext); - - if (MapSpecToShaderVersion(shaderSpec) < shaderVersion) - { - mDiagnostics.globalError("unsupported shader version"); - return nullptr; - } - - TIntermBlock *root = parseContext.getTreeRoot(); - if (!checkAndSimplifyAST(root, parseContext, compileOptions)) - { - return nullptr; - } - - return root; -} - -void TCompiler::setASTMetadata(const TParseContext &parseContext) -{ - shaderVersion = parseContext.getShaderVersion(); - - mPragma = parseContext.pragma(); - symbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll); - - mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared(); - mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize(); - - mNumViews = parseContext.getNumViews(); - - // Highp might have been auto-enabled based on shader version - fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh(); - - if (shaderType == GL_GEOMETRY_SHADER_OES) - { - mGeometryShaderInputPrimitiveType = parseContext.getGeometryShaderInputPrimitiveType(); - mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType(); - mGeometryShaderMaxVertices = parseContext.getGeometryShaderMaxVertices(); - mGeometryShaderInvocations = parseContext.getGeometryShaderInvocations(); - } -} - -bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, - const TParseContext &parseContext, - ShCompileOptions compileOptions) -{ - // Disallow expressions deemed too complex. - if ((compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY) && !limitExpressionComplexity(root)) - { - return false; - } - - // We prune no-ops to work around driver bugs and to keep AST processing and output simple. - // The following kinds of no-ops are pruned: - // 1. Empty declarations "int;". - // 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision - // for float, so float literal statements would end up with no precision which is - // invalid ESSL. - // After this empty declarations are not allowed in the AST. - PruneNoOps(root); - - // In case the last case inside a switch statement is a certain type of no-op, GLSL - // compilers in drivers may not accept it. In this case we clean up the dead code from the - // end of switch statements. This is also required because PruneNoOps may have left switch - // statements that only contained an empty declaration inside the final case in an invalid - // state. Relies on that PruneNoOps has already been run. - RemoveNoOpCasesFromEndOfSwitchStatements(root, &symbolTable); - - // Remove empty switch statements - this makes output simpler. - RemoveEmptySwitchStatements(root); - - // Create the function DAG and check there is no recursion - if (!initCallDag(root)) - { - return false; - } - - if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) && !checkCallDepth()) - { - return false; - } - - // Checks which functions are used and if "main" exists - functionMetadata.clear(); - functionMetadata.resize(mCallDag.size()); - if (!tagUsedFunctions()) - { - return false; - } - - if (!(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS)) - { - pruneUnusedFunctions(root); - } - - if (shaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, shaderType)) - { - return false; - } - - if (shaderVersion >= 300 && shaderType == GL_FRAGMENT_SHADER && - !ValidateOutputs(root, getExtensionBehavior(), compileResources.MaxDrawBuffers, - &mDiagnostics)) - { - return false; - } - - if (shouldRunLoopAndIndexingValidation(compileOptions) && - !ValidateLimitations(root, shaderType, &symbolTable, shaderVersion, &mDiagnostics)) - { - return false; - } - - // Fail compilation if precision emulation not supported. - if (getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision && - !EmulatePrecision::SupportedInLanguage(outputType)) - { - mDiagnostics.globalError("Precision emulation not supported for this output type."); - return false; - } - - // Clamping uniform array bounds needs to happen after validateLimitations pass. - if (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS) - { - arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root); - } - - if ((compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) && - parseContext.isExtensionEnabled(TExtension::OVR_multiview) && - getShaderType() != GL_COMPUTE_SHADER) - { - DeclareAndInitBuiltinsForInstancedMultiview(root, mNumViews, shaderType, compileOptions, - outputType, &symbolTable); - } - - // This pass might emit short circuits so keep it before the short circuit unfolding - if (compileOptions & SH_REWRITE_DO_WHILE_LOOPS) - RewriteDoWhile(root, &symbolTable); - - if (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION) - sh::AddAndTrueToLoopCondition(root); - - if (compileOptions & SH_UNFOLD_SHORT_CIRCUIT) - { - UnfoldShortCircuitAST unfoldShortCircuit; - root->traverse(&unfoldShortCircuit); - unfoldShortCircuit.updateTree(); - } - - if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT) - { - RemovePow(root); - } - - if (compileOptions & SH_REGENERATE_STRUCT_NAMES) - { - RegenerateStructNames gen(&symbolTable, shaderVersion); - root->traverse(&gen); - } - - if (shaderType == GL_FRAGMENT_SHADER && shaderVersion == 100 && - compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 && - IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers)) - { - EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables, - &symbolTable, shaderVersion); - } - - // Split multi declarations and remove calls to array length(). - // Note that SimplifyLoopConditions needs to be run before any other AST transformations - // that may need to generate new statements from loop conditions or loop expressions. - SimplifyLoopConditions( - root, - IntermNodePatternMatcher::kMultiDeclaration | IntermNodePatternMatcher::kArrayLengthMethod, - &getSymbolTable(), getShaderVersion()); - - // Note that separate declarations need to be run before other AST transformations that - // generate new statements from expressions. - SeparateDeclarations(root); - - SplitSequenceOperator(root, IntermNodePatternMatcher::kArrayLengthMethod, &getSymbolTable(), - getShaderVersion()); - - RemoveArrayLengthMethod(root); - - RemoveUnreferencedVariables(root, &symbolTable); - - // Built-in function emulation needs to happen after validateLimitations pass. - // TODO(jmadill): Remove global pool allocator. - GetGlobalPoolAllocator()->lock(); - initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions); - GetGlobalPoolAllocator()->unlock(); - builtInFunctionEmulator.markBuiltInFunctionsForEmulation(root); - - if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS) - { - ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh, &symbolTable); - } - - if (shouldCollectVariables(compileOptions)) - { - ASSERT(!variablesCollected); - CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings, - &outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks, - hashFunction, &symbolTable, shaderVersion, shaderType, extensionBehavior); - collectInterfaceBlocks(); - variablesCollected = true; - if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS) - { - useAllMembersInUnusedStandardAndSharedBlocks(root); - } - if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) - { - // Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec - // Appendix A, section 7, the shader does not use too many uniforms. - if (!CheckVariablesInPackingLimits(maxUniformVectors, uniforms)) - { - mDiagnostics.globalError("too many uniforms"); - return false; - } - } - if (compileOptions & SH_INIT_OUTPUT_VARIABLES) - { - initializeOutputVariables(root); - } - } - - // Removing invariant declarations must be done after collecting variables. - // Otherwise, built-in invariant declarations don't apply. - if (RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions)) - { - RemoveInvariantDeclaration(root); - } - - // gl_Position is always written in compatibility output mode. - // It may have been already initialized among other output variables, in that case we don't - // need to initialize it twice. - if (shaderType == GL_VERTEX_SHADER && !mGLPositionInitialized && - ((compileOptions & SH_INIT_GL_POSITION) || (outputType == SH_GLSL_COMPATIBILITY_OUTPUT))) - { - initializeGLPosition(root); - mGLPositionInitialized = true; - } - - // DeferGlobalInitializers needs to be run before other AST transformations that generate new - // statements from expressions. But it's fine to run DeferGlobalInitializers after the above - // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST - // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00. - bool initializeLocalsAndGlobals = - (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType()); - bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES); - DeferGlobalInitializers(root, initializeLocalsAndGlobals, canUseLoopsToInitialize, &symbolTable); - - if (initializeLocalsAndGlobals) - { - // Initialize uninitialized local variables. - // In some cases initializing can generate extra statements in the parent block, such as - // when initializing nameless structs or initializing arrays in ESSL 1.00. In that case - // we need to first simplify loop conditions. We've already separated declarations - // earlier, which is also required. If we don't follow the Appendix A limitations, loop - // init statements can declare arrays or nameless structs and have multiple - // declarations. - - if (!shouldRunLoopAndIndexingValidation(compileOptions)) - { - SimplifyLoopConditions(root, - IntermNodePatternMatcher::kArrayDeclaration | - IntermNodePatternMatcher::kNamelessStructDeclaration, - &getSymbolTable(), getShaderVersion()); - } - - InitializeUninitializedLocals(root, getShaderVersion(), canUseLoopsToInitialize, - &getSymbolTable()); - } - - if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE)) - { - ClampPointSize(root, compileResources.MaxPointSize, &getSymbolTable()); - } - - if (compileOptions & SH_REWRITE_VECTOR_SCALAR_ARITHMETIC) - { - VectorizeVectorScalarArithmetic(root, &getSymbolTable()); - } - - return true; -} - -bool TCompiler::compile(const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptionsIn) -{ -#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT) - DumpFuzzerCase(shaderStrings, numStrings, shaderType, shaderSpec, outputType, compileOptionsIn); -#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT) - - if (numStrings == 0) - return true; - - ShCompileOptions compileOptions = compileOptionsIn; - - // Apply key workarounds. - if (shouldFlattenPragmaStdglInvariantAll()) - { - // This should be harmless to do in all cases, but for the moment, do it only conditionally. - compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL; - } - - TScopedPoolAllocator scopedAlloc(&allocator); - TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions); - - if (root) - { - if (compileOptions & SH_INTERMEDIATE_TREE) - OutputTree(root, infoSink.info); - - if (compileOptions & SH_OBJECT_CODE) - { - PerformanceDiagnostics perfDiagnostics(&mDiagnostics); - translate(root, compileOptions, &perfDiagnostics); - } - - // The IntermNode tree doesn't need to be deleted here, since the - // memory will be freed in a big chunk by the PoolAllocator. - return true; - } - return false; -} - -bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) -{ - if (resources.MaxDrawBuffers < 1) - { - return false; - } - if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1) - { - return false; - } - - compileResources = resources; - setResourceString(); - - ASSERT(symbolTable.isEmpty()); - symbolTable.push(); // COMMON_BUILTINS - symbolTable.push(); // ESSL1_BUILTINS - symbolTable.push(); // ESSL3_BUILTINS - symbolTable.push(); // ESSL3_1_BUILTINS - symbolTable.push(); // GLSL_BUILTINS - - switch (shaderType) - { - case GL_FRAGMENT_SHADER: - symbolTable.setDefaultPrecision(EbtInt, EbpMedium); - break; - case GL_VERTEX_SHADER: - case GL_COMPUTE_SHADER: - case GL_GEOMETRY_SHADER_OES: - symbolTable.setDefaultPrecision(EbtInt, EbpHigh); - symbolTable.setDefaultPrecision(EbtFloat, EbpHigh); - break; - default: - UNREACHABLE(); - } - // Set defaults for sampler types that have default precision, even those that are - // only available if an extension exists. - // New sampler types in ESSL3 don't have default precision. ESSL1 types do. - initSamplerDefaultPrecision(EbtSampler2D); - initSamplerDefaultPrecision(EbtSamplerCube); - // SamplerExternalOES is specified in the extension to have default precision. - initSamplerDefaultPrecision(EbtSamplerExternalOES); - // SamplerExternal2DY2YEXT is specified in the extension to have default precision. - initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT); - // It isn't specified whether Sampler2DRect has default precision. - initSamplerDefaultPrecision(EbtSampler2DRect); - - symbolTable.setDefaultPrecision(EbtAtomicCounter, EbpHigh); - - InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable); - - IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable); - - return true; -} - -void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType) -{ - ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd); - symbolTable.setDefaultPrecision(samplerType, EbpLow); -} - -void TCompiler::setResourceString() -{ - std::ostringstream strstream; - - // clang-format off - strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs - << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors - << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors - << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits - << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits - << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits - << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors - << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers - << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives - << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external - << ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3 - << ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external - << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle - << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers - << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh - << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity - << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth - << ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters - << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended - << ":EXT_frag_depth:" << compileResources.EXT_frag_depth - << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod - << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch - << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch - << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch - << ":OVR_multiview:" << compileResources.OVR_multiview - << ":EXT_YUV_target:" << compileResources.EXT_YUV_target - << ":OES_geometry_shader:" << compileResources.OES_geometry_shader - << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors - << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors - << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset - << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset - << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers - << ":MaxViewsOVR:" << compileResources.MaxViewsOVR - << ":NV_draw_buffers:" << compileResources.NV_draw_buffers - << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision - << ":MinProgramTextureGatherOffset:" << compileResources.MinProgramTextureGatherOffset - << ":MaxProgramTextureGatherOffset:" << compileResources.MaxProgramTextureGatherOffset - << ":MaxImageUnits:" << compileResources.MaxImageUnits - << ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms - << ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms - << ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms - << ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms - << ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources - << ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0] - << ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1] - << ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2] - << ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0] - << ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1] - << ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2] - << ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents - << ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits - << ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters - << ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers - << ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters - << ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters - << ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters - << ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings - << ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers - << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers - << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers - << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize - << ":MaxGeometryUniformComponents:" << compileResources.MaxGeometryUniformComponents - << ":MaxGeometryUniformBlocks:" << compileResources.MaxGeometryUniformBlocks - << ":MaxGeometryInputComponents:" << compileResources.MaxGeometryInputComponents - << ":MaxGeometryOutputComponents:" << compileResources.MaxGeometryOutputComponents - << ":MaxGeometryOutputVertices:" << compileResources.MaxGeometryOutputVertices - << ":MaxGeometryTotalOutputComponents:" << compileResources.MaxGeometryTotalOutputComponents - << ":MaxGeometryTextureImageUnits:" << compileResources.MaxGeometryTextureImageUnits - << ":MaxGeometryAtomicCounterBuffers:" << compileResources.MaxGeometryAtomicCounterBuffers - << ":MaxGeometryAtomicCounters:" << compileResources.MaxGeometryAtomicCounters - << ":MaxGeometryShaderStorageBlocks:" << compileResources.MaxGeometryShaderStorageBlocks - << ":MaxGeometryShaderInvocations:" << compileResources.MaxGeometryShaderInvocations - << ":MaxGeometryImageUniforms:" << compileResources.MaxGeometryImageUniforms; - // clang-format on - - builtInResourcesString = strstream.str(); -} - -void TCompiler::collectInterfaceBlocks() -{ - ASSERT(interfaceBlocks.empty()); - interfaceBlocks.reserve(uniformBlocks.size() + shaderStorageBlocks.size() + inBlocks.size()); - interfaceBlocks.insert(interfaceBlocks.end(), uniformBlocks.begin(), uniformBlocks.end()); - interfaceBlocks.insert(interfaceBlocks.end(), shaderStorageBlocks.begin(), - shaderStorageBlocks.end()); - interfaceBlocks.insert(interfaceBlocks.end(), inBlocks.begin(), inBlocks.end()); -} - -void TCompiler::clearResults() -{ - arrayBoundsClamper.Cleanup(); - infoSink.info.erase(); - infoSink.obj.erase(); - infoSink.debug.erase(); - mDiagnostics.resetErrorCount(); - - attributes.clear(); - outputVariables.clear(); - uniforms.clear(); - inputVaryings.clear(); - outputVaryings.clear(); - interfaceBlocks.clear(); - uniformBlocks.clear(); - shaderStorageBlocks.clear(); - inBlocks.clear(); - variablesCollected = false; - mGLPositionInitialized = false; - - mNumViews = -1; - - mGeometryShaderInputPrimitiveType = EptUndefined; - mGeometryShaderOutputPrimitiveType = EptUndefined; - mGeometryShaderInvocations = 0; - mGeometryShaderMaxVertices = -1; - - builtInFunctionEmulator.cleanup(); - - nameMap.clear(); - - mSourcePath = nullptr; -} - -bool TCompiler::initCallDag(TIntermNode *root) -{ - mCallDag.clear(); - - switch (mCallDag.init(root, &mDiagnostics)) - { - case CallDAG::INITDAG_SUCCESS: - return true; - case CallDAG::INITDAG_RECURSION: - case CallDAG::INITDAG_UNDEFINED: - // Error message has already been written out. - ASSERT(mDiagnostics.numErrors() > 0); - return false; - } - - UNREACHABLE(); - return true; -} - -bool TCompiler::checkCallDepth() -{ - std::vector<int> depths(mCallDag.size()); - - for (size_t i = 0; i < mCallDag.size(); i++) - { - int depth = 0; - auto &record = mCallDag.getRecordFromIndex(i); - - for (auto &calleeIndex : record.callees) - { - depth = std::max(depth, depths[calleeIndex] + 1); - } - - depths[i] = depth; - - if (depth >= maxCallStackDepth) - { - // Trace back the function chain to have a meaningful info log. - std::stringstream errorStream; - errorStream << "Call stack too deep (larger than " << maxCallStackDepth - << ") with the following call chain: " << record.name; - - int currentFunction = static_cast<int>(i); - int currentDepth = depth; - - while (currentFunction != -1) - { - errorStream << " -> " << mCallDag.getRecordFromIndex(currentFunction).name; - - int nextFunction = -1; - for (auto &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees) - { - if (depths[calleeIndex] == currentDepth - 1) - { - currentDepth--; - nextFunction = calleeIndex; - } - } - - currentFunction = nextFunction; - } - - std::string errorStr = errorStream.str(); - mDiagnostics.globalError(errorStr.c_str()); - - return false; - } - } - - return true; -} - -bool TCompiler::tagUsedFunctions() -{ - // Search from main, starting from the end of the DAG as it usually is the root. - for (size_t i = mCallDag.size(); i-- > 0;) - { - if (mCallDag.getRecordFromIndex(i).name == "main") - { - internalTagUsedFunction(i); - return true; - } - } - - mDiagnostics.globalError("Missing main()"); - return false; -} - -void TCompiler::internalTagUsedFunction(size_t index) -{ - if (functionMetadata[index].used) - { - return; - } - - functionMetadata[index].used = true; - - for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees) - { - internalTagUsedFunction(calleeIndex); - } -} - -// A predicate for the stl that returns if a top-level node is unused -class TCompiler::UnusedPredicate -{ - public: - UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas) - : mCallDag(callDag), mMetadatas(metadatas) - { - } - - bool operator()(TIntermNode *node) - { - const TIntermFunctionPrototype *asFunctionPrototype = node->getAsFunctionPrototypeNode(); - const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition(); - - const TFunctionSymbolInfo *functionInfo = nullptr; - - if (asFunctionDefinition) - { - functionInfo = asFunctionDefinition->getFunctionSymbolInfo(); - } - else if (asFunctionPrototype) - { - functionInfo = asFunctionPrototype->getFunctionSymbolInfo(); - } - if (functionInfo == nullptr) - { - return false; - } - - size_t callDagIndex = mCallDag->findIndex(functionInfo); - if (callDagIndex == CallDAG::InvalidIndex) - { - // This happens only for unimplemented prototypes which are thus unused - ASSERT(asFunctionPrototype); - return true; - } - - ASSERT(callDagIndex < mMetadatas->size()); - return !(*mMetadatas)[callDagIndex].used; - } - - private: - const CallDAG *mCallDag; - const std::vector<FunctionMetadata> *mMetadatas; -}; - -void TCompiler::pruneUnusedFunctions(TIntermBlock *root) -{ - UnusedPredicate isUnused(&mCallDag, &functionMetadata); - TIntermSequence *sequence = root->getSequence(); - - if (!sequence->empty()) - { - sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused), - sequence->end()); - } -} - -bool TCompiler::limitExpressionComplexity(TIntermBlock *root) -{ - if (!IsASTDepthBelowLimit(root, maxExpressionComplexity)) - { - mDiagnostics.globalError("Expression too complex."); - return false; - } - - if (!ValidateMaxParameters(root, maxFunctionParameters)) - { - mDiagnostics.globalError("Function has too many parameters."); - return false; - } - - return true; -} - -bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions) -{ - return (compileOptions & SH_VARIABLES) != 0; -} - -bool TCompiler::wereVariablesCollected() const -{ - return variablesCollected; -} - -void TCompiler::initializeGLPosition(TIntermBlock *root) -{ - InitVariableList list; - sh::ShaderVariable var(GL_FLOAT_VEC4); - var.name = "gl_Position"; - list.push_back(var); - InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false); -} - -void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root) -{ - sh::InterfaceBlockList list; - - for (auto block : uniformBlocks) - { - if (!block.staticUse && - (block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED)) - { - list.push_back(block); - } - } - - sh::UseInterfaceBlockFields(root, list, symbolTable); -} - -void TCompiler::initializeOutputVariables(TIntermBlock *root) -{ - InitVariableList list; - if (shaderType == GL_VERTEX_SHADER || shaderType == GL_GEOMETRY_SHADER_OES) - { - for (auto var : outputVaryings) - { - list.push_back(var); - if (var.name == "gl_Position") - { - ASSERT(!mGLPositionInitialized); - mGLPositionInitialized = true; - } - } - } - else - { - ASSERT(shaderType == GL_FRAGMENT_SHADER); - for (auto var : outputVariables) - { - list.push_back(var); - } - } - InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false); -} - -const TExtensionBehavior &TCompiler::getExtensionBehavior() const -{ - return extensionBehavior; -} - -const char *TCompiler::getSourcePath() const -{ - return mSourcePath; -} - -const ShBuiltInResources &TCompiler::getResources() const -{ - return compileResources; -} - -const ArrayBoundsClamper &TCompiler::getArrayBoundsClamper() const -{ - return arrayBoundsClamper; -} - -ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const -{ - return clampingStrategy; -} - -const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const -{ - return builtInFunctionEmulator; -} - -void TCompiler::writePragma(ShCompileOptions compileOptions) -{ - if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL)) - { - TInfoSinkBase &sink = infoSink.obj; - if (mPragma.stdgl.invariantAll) - sink << "#pragma STDGL invariant(all)\n"; - } -} - -bool TCompiler::isVaryingDefined(const char *varyingName) -{ - ASSERT(variablesCollected); - for (size_t ii = 0; ii < inputVaryings.size(); ++ii) - { - if (inputVaryings[ii].name == varyingName) - { - return true; - } - } - for (size_t ii = 0; ii < outputVaryings.size(); ++ii) - { - if (outputVaryings[ii].name == varyingName) - { - return true; - } - } - - return false; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.h b/src/3rdparty/angle/src/compiler/translator/Compiler.h deleted file mode 100644 index 753cfb8e7b..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.h +++ /dev/null @@ -1,308 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_COMPILER_H_ -#define COMPILER_TRANSLATOR_COMPILER_H_ - -// -// Machine independent part of the compiler private objects -// sent as ShHandle to the driver. -// -// This should not be included by driver code. -// - -#include <GLSLANG/ShaderVars.h> - -#include "compiler/translator/BuiltInFunctionEmulator.h" -#include "compiler/translator/CallDAG.h" -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/ExtensionBehavior.h" -#include "compiler/translator/HashNames.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/Pragma.h" -#include "compiler/translator/SymbolTable.h" -#include "third_party/compiler/ArrayBoundsClamper.h" - -namespace sh -{ - -class TCompiler; -class TParseContext; -#ifdef ANGLE_ENABLE_HLSL -class TranslatorHLSL; -#endif // ANGLE_ENABLE_HLSL - -// -// Helper function to identify specs that are based on the WebGL spec. -// -bool IsWebGLBasedSpec(ShShaderSpec spec); - -// -// Helper function to check if the shader type is GLSL. -// -bool IsGLSL130OrNewer(ShShaderOutput output); -bool IsGLSL420OrNewer(ShShaderOutput output); -bool IsGLSL410OrOlder(ShShaderOutput output); - -// -// Helper function to check if the invariant qualifier can be removed. -// -bool RemoveInvariant(sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput outputType, - ShCompileOptions compileOptions); - -// -// The base class used to back handles returned to the driver. -// -class TShHandleBase -{ - public: - TShHandleBase(); - virtual ~TShHandleBase(); - virtual TCompiler *getAsCompiler() { return 0; } -#ifdef ANGLE_ENABLE_HLSL - virtual TranslatorHLSL *getAsTranslatorHLSL() { return 0; } -#endif // ANGLE_ENABLE_HLSL - - protected: - // Memory allocator. Allocates and tracks memory required by the compiler. - // Deallocates all memory when compiler is destructed. - TPoolAllocator allocator; -}; - -// -// The base class for the machine dependent compiler to derive from -// for managing object code from the compile. -// -class TCompiler : public TShHandleBase -{ - public: - TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); - ~TCompiler() override; - TCompiler *getAsCompiler() override { return this; } - - bool Init(const ShBuiltInResources &resources); - - // compileTreeForTesting should be used only when tests require access to - // the AST. Users of this function need to manually manage the global pool - // allocator. Returns nullptr whenever there are compilation errors. - TIntermBlock *compileTreeForTesting(const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptions); - - bool compile(const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptions); - - // Get results of the last compilation. - int getShaderVersion() const { return shaderVersion; } - TInfoSink &getInfoSink() { return infoSink; } - - bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; } - const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; } - int getNumViews() const { return mNumViews; } - - // Clears the results from the previous compilation. - void clearResults(); - - const std::vector<sh::Attribute> &getAttributes() const { return attributes; } - const std::vector<sh::OutputVariable> &getOutputVariables() const { return outputVariables; } - const std::vector<sh::Uniform> &getUniforms() const { return uniforms; } - const std::vector<sh::Varying> &getInputVaryings() const { return inputVaryings; } - const std::vector<sh::Varying> &getOutputVaryings() const { return outputVaryings; } - const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return interfaceBlocks; } - const std::vector<sh::InterfaceBlock> &getUniformBlocks() const { return uniformBlocks; } - const std::vector<sh::InterfaceBlock> &getShaderStorageBlocks() const - { - return shaderStorageBlocks; - } - const std::vector<sh::InterfaceBlock> &getInBlocks() const { return inBlocks; } - - ShHashFunction64 getHashFunction() const { return hashFunction; } - NameMap &getNameMap() { return nameMap; } - TSymbolTable &getSymbolTable() { return symbolTable; } - ShShaderSpec getShaderSpec() const { return shaderSpec; } - ShShaderOutput getOutputType() const { return outputType; } - const std::string &getBuiltInResourcesString() const { return builtInResourcesString; } - - bool shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const; - - // Get the resources set by InitBuiltInSymbolTable - const ShBuiltInResources &getResources() const; - - int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; } - int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; } - TLayoutPrimitiveType getGeometryShaderInputPrimitiveType() const - { - return mGeometryShaderInputPrimitiveType; - } - TLayoutPrimitiveType getGeometryShaderOutputPrimitiveType() const - { - return mGeometryShaderOutputPrimitiveType; - } - - sh::GLenum getShaderType() const { return shaderType; } - - protected: - // Initialize symbol-table with built-in symbols. - bool InitBuiltInSymbolTable(const ShBuiltInResources &resources); - // Compute the string representation of the built-in resources - void setResourceString(); - // Return false if the call depth is exceeded. - bool checkCallDepth(); - // Add emulated functions to the built-in function emulator. - virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, - ShCompileOptions compileOptions){}; - // Translate to object code. May generate performance warnings through the diagnostics. - virtual void translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics *perfDiagnostics) = 0; - // Insert statements to reference all members in unused uniform blocks with standard and shared - // layout. This is to work around a Mac driver that treats unused standard/shared - // uniform blocks as inactive. - void useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root); - // Insert statements to initialize output variables in the beginning of main(). - // This is to avoid undefined behaviors. - void initializeOutputVariables(TIntermBlock *root); - // Insert gl_Position = vec4(0,0,0,0) to the beginning of main(). - // It is to work around a Linux driver bug where missing this causes compile failure - // while spec says it is allowed. - // This function should only be applied to vertex shaders. - void initializeGLPosition(TIntermBlock *root); - // Return true if the maximum expression complexity is below the limit. - bool limitExpressionComplexity(TIntermBlock *root); - // Get built-in extensions with default behavior. - const TExtensionBehavior &getExtensionBehavior() const; - const char *getSourcePath() const; - const TPragma &getPragma() const { return mPragma; } - void writePragma(ShCompileOptions compileOptions); - // Relies on collectVariables having been called. - bool isVaryingDefined(const char *varyingName); - - const ArrayBoundsClamper &getArrayBoundsClamper() const; - ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; - const BuiltInFunctionEmulator &getBuiltInFunctionEmulator() const; - - virtual bool shouldFlattenPragmaStdglInvariantAll() = 0; - virtual bool shouldCollectVariables(ShCompileOptions compileOptions); - - bool wereVariablesCollected() const; - std::vector<sh::Attribute> attributes; - std::vector<sh::OutputVariable> outputVariables; - std::vector<sh::Uniform> uniforms; - std::vector<sh::Varying> inputVaryings; - std::vector<sh::Varying> outputVaryings; - std::vector<sh::InterfaceBlock> interfaceBlocks; - std::vector<sh::InterfaceBlock> uniformBlocks; - std::vector<sh::InterfaceBlock> shaderStorageBlocks; - std::vector<sh::InterfaceBlock> inBlocks; - - private: - // Creates the function call DAG for further analysis, returning false if there is a recursion - bool initCallDag(TIntermNode *root); - // Return false if "main" doesn't exist - bool tagUsedFunctions(); - void internalTagUsedFunction(size_t index); - - void initSamplerDefaultPrecision(TBasicType samplerType); - - void collectInterfaceBlocks(); - - bool variablesCollected; - - bool mGLPositionInitialized; - - // Removes unused function declarations and prototypes from the AST - class UnusedPredicate; - void pruneUnusedFunctions(TIntermBlock *root); - - TIntermBlock *compileTreeImpl(const char *const shaderStrings[], - size_t numStrings, - const ShCompileOptions compileOptions); - - // Fetches and stores shader metadata that is not stored within the AST itself, such as shader - // version. - void setASTMetadata(const TParseContext &parseContext); - - // Does checks that need to be run after parsing is complete and returns true if they pass. - bool checkAndSimplifyAST(TIntermBlock *root, - const TParseContext &parseContext, - ShCompileOptions compileOptions); - - sh::GLenum shaderType; - ShShaderSpec shaderSpec; - ShShaderOutput outputType; - - struct FunctionMetadata - { - FunctionMetadata() : used(false) {} - bool used; - }; - - CallDAG mCallDag; - std::vector<FunctionMetadata> functionMetadata; - - int maxUniformVectors; - int maxExpressionComplexity; - int maxCallStackDepth; - int maxFunctionParameters; - - ShBuiltInResources compileResources; - std::string builtInResourcesString; - - // Built-in symbol table for the given language, spec, and resources. - // It is preserved from compile-to-compile. - TSymbolTable symbolTable; - // Built-in extensions with default behavior. - TExtensionBehavior extensionBehavior; - bool fragmentPrecisionHigh; - - ArrayBoundsClamper arrayBoundsClamper; - ShArrayIndexClampingStrategy clampingStrategy; - BuiltInFunctionEmulator builtInFunctionEmulator; - - // Results of compilation. - int shaderVersion; - TInfoSink infoSink; // Output sink. - TDiagnostics mDiagnostics; - const char *mSourcePath; // Path of source file or NULL - - // compute shader local group size - bool mComputeShaderLocalSizeDeclared; - sh::WorkGroupSize mComputeShaderLocalSize; - - // GL_OVR_multiview num_views. - int mNumViews; - - // geometry shader parameters. - int mGeometryShaderMaxVertices; - int mGeometryShaderInvocations; - TLayoutPrimitiveType mGeometryShaderInputPrimitiveType; - TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType; - - // name hashing. - ShHashFunction64 hashFunction; - NameMap nameMap; - - TPragma mPragma; -}; - -// -// This is the interface between the machine independent code -// and the machine dependent code. -// -// The machine dependent code should derive from the classes -// above. Then Construct*() and Delete*() will create and -// destroy the machine dependent objects, which contain the -// above machine independent information. -// -TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); -void DeleteCompiler(TCompiler *); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_COMPILER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp deleted file mode 100644 index 7004aedee3..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp +++ /dev/null @@ -1,681 +0,0 @@ -// -// Copyright 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ConstantUnion: Constant folding helper class. - -#include "compiler/translator/ConstantUnion.h" - -#include "common/mathutil.h" -#include "compiler/translator/Diagnostics.h" - -namespace sh -{ - -namespace -{ - -float CheckedSum(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line) -{ - float result = lhs + rhs; - if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs)) - { - diag->warning(line, "Constant folded undefined addition generated NaN", "+"); - } - else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs)) - { - diag->warning(line, "Constant folded addition overflowed to infinity", "+"); - } - return result; -} - -float CheckedDiff(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line) -{ - float result = lhs - rhs; - if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs)) - { - diag->warning(line, "Constant folded undefined subtraction generated NaN", "-"); - } - else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs)) - { - diag->warning(line, "Constant folded subtraction overflowed to infinity", "-"); - } - return result; -} - -float CheckedMul(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line) -{ - float result = lhs * rhs; - if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs)) - { - diag->warning(line, "Constant folded undefined multiplication generated NaN", "*"); - } - else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs)) - { - diag->warning(line, "Constant folded multiplication overflowed to infinity", "*"); - } - return result; -} - -bool IsValidShiftOffset(const TConstantUnion &rhs) -{ - return (rhs.getType() == EbtInt && (rhs.getIConst() >= 0 && rhs.getIConst() <= 31)) || - (rhs.getType() == EbtUInt && rhs.getUConst() <= 31u); -} - -} // anonymous namespace - -TConstantUnion::TConstantUnion() -{ - iConst = 0; - type = EbtVoid; -} - -int TConstantUnion::getIConst() const -{ - ASSERT(type == EbtInt); - return iConst; -} - -unsigned int TConstantUnion::getUConst() const -{ - ASSERT(type == EbtUInt); - return uConst; -} - -float TConstantUnion::getFConst() const -{ - ASSERT(type == EbtFloat); - return fConst; -} - -bool TConstantUnion::getBConst() const -{ - ASSERT(type == EbtBool); - return bConst; -} - -TYuvCscStandardEXT TConstantUnion::getYuvCscStandardEXTConst() const -{ - ASSERT(type == EbtYuvCscStandardEXT); - return yuvCscStandardEXTConst; -} - -bool TConstantUnion::cast(TBasicType newType, const TConstantUnion &constant) -{ - switch (newType) - { - case EbtFloat: - switch (constant.type) - { - case EbtInt: - setFConst(static_cast<float>(constant.getIConst())); - break; - case EbtUInt: - setFConst(static_cast<float>(constant.getUConst())); - break; - case EbtBool: - setFConst(static_cast<float>(constant.getBConst())); - break; - case EbtFloat: - setFConst(static_cast<float>(constant.getFConst())); - break; - default: - return false; - } - break; - case EbtInt: - switch (constant.type) - { - case EbtInt: - setIConst(static_cast<int>(constant.getIConst())); - break; - case EbtUInt: - setIConst(static_cast<int>(constant.getUConst())); - break; - case EbtBool: - setIConst(static_cast<int>(constant.getBConst())); - break; - case EbtFloat: - setIConst(static_cast<int>(constant.getFConst())); - break; - default: - return false; - } - break; - case EbtUInt: - switch (constant.type) - { - case EbtInt: - setUConst(static_cast<unsigned int>(constant.getIConst())); - break; - case EbtUInt: - setUConst(static_cast<unsigned int>(constant.getUConst())); - break; - case EbtBool: - setUConst(static_cast<unsigned int>(constant.getBConst())); - break; - case EbtFloat: - setUConst(static_cast<unsigned int>(constant.getFConst())); - break; - default: - return false; - } - break; - case EbtBool: - switch (constant.type) - { - case EbtInt: - setBConst(constant.getIConst() != 0); - break; - case EbtUInt: - setBConst(constant.getUConst() != 0); - break; - case EbtBool: - setBConst(constant.getBConst()); - break; - case EbtFloat: - setBConst(constant.getFConst() != 0.0f); - break; - default: - return false; - } - break; - case EbtStruct: // Struct fields don't get cast - switch (constant.type) - { - case EbtInt: - setIConst(constant.getIConst()); - break; - case EbtUInt: - setUConst(constant.getUConst()); - break; - case EbtBool: - setBConst(constant.getBConst()); - break; - case EbtFloat: - setFConst(constant.getFConst()); - break; - default: - return false; - } - break; - default: - return false; - } - - return true; -} - -bool TConstantUnion::operator==(const int i) const -{ - return i == iConst; -} - -bool TConstantUnion::operator==(const unsigned int u) const -{ - return u == uConst; -} - -bool TConstantUnion::operator==(const float f) const -{ - return f == fConst; -} - -bool TConstantUnion::operator==(const bool b) const -{ - return b == bConst; -} - -bool TConstantUnion::operator==(const TYuvCscStandardEXT s) const -{ - return s == yuvCscStandardEXTConst; -} - -bool TConstantUnion::operator==(const TConstantUnion &constant) const -{ - if (constant.type != type) - return false; - - switch (type) - { - case EbtInt: - return constant.iConst == iConst; - case EbtUInt: - return constant.uConst == uConst; - case EbtFloat: - return constant.fConst == fConst; - case EbtBool: - return constant.bConst == bConst; - case EbtYuvCscStandardEXT: - return constant.yuvCscStandardEXTConst == yuvCscStandardEXTConst; - default: - return false; - } -} - -bool TConstantUnion::operator!=(const int i) const -{ - return !operator==(i); -} - -bool TConstantUnion::operator!=(const unsigned int u) const -{ - return !operator==(u); -} - -bool TConstantUnion::operator!=(const float f) const -{ - return !operator==(f); -} - -bool TConstantUnion::operator!=(const bool b) const -{ - return !operator==(b); -} - -bool TConstantUnion::operator!=(const TYuvCscStandardEXT s) const -{ - return !operator==(s); -} - -bool TConstantUnion::operator!=(const TConstantUnion &constant) const -{ - return !operator==(constant); -} - -bool TConstantUnion::operator>(const TConstantUnion &constant) const -{ - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - return iConst > constant.iConst; - case EbtUInt: - return uConst > constant.uConst; - case EbtFloat: - return fConst > constant.fConst; - default: - return false; // Invalid operation, handled at semantic analysis - } -} - -bool TConstantUnion::operator<(const TConstantUnion &constant) const -{ - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - return iConst < constant.iConst; - case EbtUInt: - return uConst < constant.uConst; - case EbtFloat: - return fConst < constant.fConst; - default: - return false; // Invalid operation, handled at semantic analysis - } -} - -// static -TConstantUnion TConstantUnion::add(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == rhs.type); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(gl::WrappingSum<int>(lhs.iConst, rhs.iConst)); - break; - case EbtUInt: - returnValue.setUConst(gl::WrappingSum<unsigned int>(lhs.uConst, rhs.uConst)); - break; - case EbtFloat: - returnValue.setFConst(CheckedSum(lhs.fConst, rhs.fConst, diag, line)); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -// static -TConstantUnion TConstantUnion::sub(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == rhs.type); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(gl::WrappingDiff<int>(lhs.iConst, rhs.iConst)); - break; - case EbtUInt: - returnValue.setUConst(gl::WrappingDiff<unsigned int>(lhs.uConst, rhs.uConst)); - break; - case EbtFloat: - returnValue.setFConst(CheckedDiff(lhs.fConst, rhs.fConst, diag, line)); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -// static -TConstantUnion TConstantUnion::mul(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == rhs.type); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(gl::WrappingMul(lhs.iConst, rhs.iConst)); - break; - case EbtUInt: - // Unsigned integer math in C++ is defined to be done in modulo 2^n, so we rely on that - // to implement wrapping multiplication. - returnValue.setUConst(lhs.uConst * rhs.uConst); - break; - case EbtFloat: - returnValue.setFConst(CheckedMul(lhs.fConst, rhs.fConst, diag, line)); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator%(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - returnValue.setIConst(iConst % constant.iConst); - break; - case EbtUInt: - returnValue.setUConst(uConst % constant.uConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -// static -TConstantUnion TConstantUnion::rshift(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt); - ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt); - if (!IsValidShiftOffset(rhs)) - { - diag->warning(line, "Undefined shift (operand out of range)", ">>"); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(0); - break; - case EbtUInt: - returnValue.setUConst(0u); - break; - default: - UNREACHABLE(); - } - return returnValue; - } - - switch (lhs.type) - { - case EbtInt: - { - unsigned int shiftOffset = 0; - switch (rhs.type) - { - case EbtInt: - shiftOffset = static_cast<unsigned int>(rhs.iConst); - break; - case EbtUInt: - shiftOffset = rhs.uConst; - break; - default: - UNREACHABLE(); - } - if (shiftOffset > 0) - { - // ESSL 3.00.6 section 5.9: "If E1 is a signed integer, the right-shift will extend - // the sign bit." In C++ shifting negative integers is undefined, so we implement - // extending the sign bit manually. - int lhsSafe = lhs.iConst; - if (lhsSafe == std::numeric_limits<int>::min()) - { - // The min integer needs special treatment because only bit it has set is the - // sign bit, which we clear later to implement safe right shift of negative - // numbers. - lhsSafe = -0x40000000; - --shiftOffset; - } - if (shiftOffset > 0) - { - bool extendSignBit = false; - if (lhsSafe < 0) - { - extendSignBit = true; - // Clear the sign bit so that bitshift right is defined in C++. - lhsSafe &= 0x7fffffff; - ASSERT(lhsSafe > 0); - } - returnValue.setIConst(lhsSafe >> shiftOffset); - - // Manually fill in the extended sign bit if necessary. - if (extendSignBit) - { - int extendedSignBit = static_cast<int>(0xffffffffu << (31 - shiftOffset)); - returnValue.setIConst(returnValue.getIConst() | extendedSignBit); - } - } - else - { - returnValue.setIConst(lhsSafe); - } - } - else - { - returnValue.setIConst(lhs.iConst); - } - break; - } - case EbtUInt: - switch (rhs.type) - { - case EbtInt: - returnValue.setUConst(lhs.uConst >> rhs.iConst); - break; - case EbtUInt: - returnValue.setUConst(lhs.uConst >> rhs.uConst); - break; - default: - UNREACHABLE(); - } - break; - - default: - UNREACHABLE(); - } - return returnValue; -} - -// static -TConstantUnion TConstantUnion::lshift(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt); - ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt); - if (!IsValidShiftOffset(rhs)) - { - diag->warning(line, "Undefined shift (operand out of range)", "<<"); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(0); - break; - case EbtUInt: - returnValue.setUConst(0u); - break; - default: - UNREACHABLE(); - } - return returnValue; - } - - switch (lhs.type) - { - case EbtInt: - switch (rhs.type) - { - // Cast to unsigned integer before shifting, since ESSL 3.00.6 section 5.9 says that - // lhs is "interpreted as a bit pattern". This also avoids the possibility of signed - // integer overflow or undefined shift of a negative integer. - case EbtInt: - returnValue.setIConst( - static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.iConst)); - break; - case EbtUInt: - returnValue.setIConst( - static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.uConst)); - break; - default: - UNREACHABLE(); - } - break; - - case EbtUInt: - switch (rhs.type) - { - case EbtInt: - returnValue.setUConst(lhs.uConst << rhs.iConst); - break; - case EbtUInt: - returnValue.setUConst(lhs.uConst << rhs.uConst); - break; - default: - UNREACHABLE(); - } - break; - - default: - UNREACHABLE(); - } - return returnValue; -} - -TConstantUnion TConstantUnion::operator&(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(constant.type == EbtInt || constant.type == EbtUInt); - switch (type) - { - case EbtInt: - returnValue.setIConst(iConst & constant.iConst); - break; - case EbtUInt: - returnValue.setUConst(uConst & constant.uConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator|(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - returnValue.setIConst(iConst | constant.iConst); - break; - case EbtUInt: - returnValue.setUConst(uConst | constant.uConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator^(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - returnValue.setIConst(iConst ^ constant.iConst); - break; - case EbtUInt: - returnValue.setUConst(uConst ^ constant.uConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator&&(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtBool: - returnValue.setBConst(bConst && constant.bConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator||(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtBool: - returnValue.setBConst(bConst || constant.bConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h deleted file mode 100644 index c1b3db9070..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h +++ /dev/null @@ -1,117 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_CONSTANTUNION_H_ -#define COMPILER_TRANSLATOR_CONSTANTUNION_H_ - -#include <assert.h> - -#include "compiler/translator/Common.h" -#include "compiler/translator/BaseTypes.h" - -namespace sh -{ - -class TDiagnostics; - -class TConstantUnion -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TConstantUnion(); - - bool cast(TBasicType newType, const TConstantUnion &constant); - - void setIConst(int i) - { - iConst = i; - type = EbtInt; - } - void setUConst(unsigned int u) - { - uConst = u; - type = EbtUInt; - } - void setFConst(float f) - { - fConst = f; - type = EbtFloat; - } - void setBConst(bool b) - { - bConst = b; - type = EbtBool; - } - - void setYuvCscStandardEXTConst(TYuvCscStandardEXT s) - { - yuvCscStandardEXTConst = s; - type = EbtYuvCscStandardEXT; - } - - int getIConst() const; - unsigned int getUConst() const; - float getFConst() const; - bool getBConst() const; - TYuvCscStandardEXT getYuvCscStandardEXTConst() const; - - bool operator==(const int i) const; - bool operator==(const unsigned int u) const; - bool operator==(const float f) const; - bool operator==(const bool b) const; - bool operator==(const TYuvCscStandardEXT s) const; - bool operator==(const TConstantUnion &constant) const; - bool operator!=(const int i) const; - bool operator!=(const unsigned int u) const; - bool operator!=(const float f) const; - bool operator!=(const bool b) const; - bool operator!=(const TYuvCscStandardEXT s) const; - bool operator!=(const TConstantUnion &constant) const; - bool operator>(const TConstantUnion &constant) const; - bool operator<(const TConstantUnion &constant) const; - static TConstantUnion add(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - static TConstantUnion sub(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - static TConstantUnion mul(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - TConstantUnion operator%(const TConstantUnion &constant) const; - static TConstantUnion rshift(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - static TConstantUnion lshift(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - TConstantUnion operator&(const TConstantUnion &constant) const; - TConstantUnion operator|(const TConstantUnion &constant) const; - TConstantUnion operator^(const TConstantUnion &constant) const; - TConstantUnion operator&&(const TConstantUnion &constant) const; - TConstantUnion operator||(const TConstantUnion &constant) const; - - TBasicType getType() const { return type; } - private: - union { - int iConst; // used for ivec, scalar ints - unsigned int uConst; // used for uvec, scalar uints - bool bConst; // used for bvec, scalar bools - float fConst; // used for vec, mat, scalar floats - TYuvCscStandardEXT yuvCscStandardEXTConst; - }; - - TBasicType type; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_CONSTANTUNION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp b/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp deleted file mode 100644 index ce9828f1f9..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp +++ /dev/null @@ -1,221 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Applies the necessary AST transformations to support multiview rendering through instancing. -// Check the header file For more information. -// - -#include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h" - -#include "compiler/translator/FindMain.h" -#include "compiler/translator/InitializeVariables.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -class ReplaceVariableTraverser : public TIntermTraverser -{ - public: - ReplaceVariableTraverser(const TString &symbolName, TIntermSymbol *newSymbol) - : TIntermTraverser(true, false, false), mSymbolName(symbolName), mNewSymbol(newSymbol) - { - } - - void visitSymbol(TIntermSymbol *node) override - { - TName &name = node->getName(); - if (name.getString() == mSymbolName) - { - queueReplacement(mNewSymbol->deepCopy(), OriginalNode::IS_DROPPED); - } - } - - private: - TString mSymbolName; - TIntermSymbol *mNewSymbol; -}; - -TIntermSymbol *CreateGLInstanceIDSymbol(const TSymbolTable &symbolTable) -{ - return ReferenceBuiltInVariable("gl_InstanceID", symbolTable, 300); -} - -// Adds the InstanceID and ViewID_OVR initializers to the end of the initializers' sequence. -void InitializeViewIDAndInstanceID(TIntermTyped *viewIDSymbol, - TIntermTyped *instanceIDSymbol, - unsigned numberOfViews, - const TSymbolTable &symbolTable, - TIntermSequence *initializers) -{ - // Create an unsigned numberOfViews node. - TConstantUnion *numberOfViewsUnsignedConstant = new TConstantUnion(); - numberOfViewsUnsignedConstant->setUConst(numberOfViews); - TIntermConstantUnion *numberOfViewsUint = - new TIntermConstantUnion(numberOfViewsUnsignedConstant, TType(EbtUInt, EbpHigh, EvqConst)); - - // Create a uint(gl_InstanceID) node. - TIntermSequence *glInstanceIDSymbolCastArguments = new TIntermSequence(); - glInstanceIDSymbolCastArguments->push_back(CreateGLInstanceIDSymbol(symbolTable)); - TIntermAggregate *glInstanceIDAsUint = TIntermAggregate::CreateConstructor( - TType(EbtUInt, EbpHigh, EvqTemporary), glInstanceIDSymbolCastArguments); - - // Create a uint(gl_InstanceID) / numberOfViews node. - TIntermBinary *normalizedInstanceID = - new TIntermBinary(EOpDiv, glInstanceIDAsUint, numberOfViewsUint); - - // Create an int(uint(gl_InstanceID) / numberOfViews) node. - TIntermSequence *normalizedInstanceIDCastArguments = new TIntermSequence(); - normalizedInstanceIDCastArguments->push_back(normalizedInstanceID); - TIntermAggregate *normalizedInstanceIDAsInt = TIntermAggregate::CreateConstructor( - TType(EbtInt, EbpHigh, EvqTemporary), normalizedInstanceIDCastArguments); - - // Create an InstanceID = int(uint(gl_InstanceID) / numberOfViews) node. - TIntermBinary *instanceIDInitializer = - new TIntermBinary(EOpAssign, instanceIDSymbol->deepCopy(), normalizedInstanceIDAsInt); - initializers->push_back(instanceIDInitializer); - - // Create a uint(gl_InstanceID) % numberOfViews node. - TIntermBinary *normalizedViewID = - new TIntermBinary(EOpIMod, glInstanceIDAsUint->deepCopy(), numberOfViewsUint->deepCopy()); - - // Create a ViewID_OVR = uint(gl_InstanceID) % numberOfViews node. - TIntermBinary *viewIDInitializer = - new TIntermBinary(EOpAssign, viewIDSymbol->deepCopy(), normalizedViewID); - initializers->push_back(viewIDInitializer); -} - -// Replaces every occurrence of a symbol with the name specified in symbolName with newSymbolNode. -void ReplaceSymbol(TIntermBlock *root, const TString &symbolName, TIntermSymbol *newSymbolNode) -{ - ReplaceVariableTraverser traverser(symbolName, newSymbolNode); - root->traverse(&traverser); - traverser.updateTree(); -} - -void DeclareGlobalVariable(TIntermBlock *root, TIntermTyped *typedNode) -{ - TIntermSequence *globalSequence = root->getSequence(); - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->appendDeclarator(typedNode->deepCopy()); - globalSequence->insert(globalSequence->begin(), declaration); -} - -// Adds a branch to write int(ViewID_OVR) to either gl_ViewportIndex or gl_Layer. The branch is -// added to the end of the initializers' sequence. -void SelectViewIndexInVertexShader(TIntermTyped *viewIDSymbol, - TIntermTyped *multiviewBaseViewLayerIndexSymbol, - TIntermSequence *initializers, - const TSymbolTable &symbolTable) -{ - // Create an int(ViewID_OVR) node. - TIntermSequence *viewIDSymbolCastArguments = new TIntermSequence(); - viewIDSymbolCastArguments->push_back(viewIDSymbol); - TIntermAggregate *viewIDAsInt = TIntermAggregate::CreateConstructor( - TType(EbtInt, EbpHigh, EvqTemporary), viewIDSymbolCastArguments); - - // Create a gl_ViewportIndex node. - TIntermSymbol *viewportIndexSymbol = - ReferenceBuiltInVariable("gl_ViewportIndex", symbolTable, 0); - - // Create a { gl_ViewportIndex = int(ViewID_OVR) } node. - TIntermBlock *viewportIndexInitializerInBlock = new TIntermBlock(); - viewportIndexInitializerInBlock->appendStatement( - new TIntermBinary(EOpAssign, viewportIndexSymbol, viewIDAsInt)); - - // Create a gl_Layer node. - TIntermSymbol *layerSymbol = ReferenceBuiltInVariable("gl_Layer", symbolTable, 0); - - // Create an int(ViewID_OVR) + multiviewBaseViewLayerIndex node - TIntermBinary *sumOfViewIDAndBaseViewIndex = - new TIntermBinary(EOpAdd, viewIDAsInt->deepCopy(), multiviewBaseViewLayerIndexSymbol); - - // Create a { gl_Layer = int(ViewID_OVR) + multiviewBaseViewLayerIndex } node. - TIntermBlock *layerInitializerInBlock = new TIntermBlock(); - layerInitializerInBlock->appendStatement( - new TIntermBinary(EOpAssign, layerSymbol, sumOfViewIDAndBaseViewIndex)); - - // Create a node to compare whether the base view index uniform is less than zero. - TIntermBinary *multiviewBaseViewLayerIndexZeroComparison = - new TIntermBinary(EOpLessThan, multiviewBaseViewLayerIndexSymbol->deepCopy(), - CreateZeroNode(TType(EbtInt, EbpHigh, EvqConst))); - - // Create an if-else statement to select the code path. - TIntermIfElse *multiviewBranch = - new TIntermIfElse(multiviewBaseViewLayerIndexZeroComparison, - viewportIndexInitializerInBlock, layerInitializerInBlock); - - initializers->push_back(multiviewBranch); -} - -} // namespace - -void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root, - unsigned numberOfViews, - GLenum shaderType, - ShCompileOptions compileOptions, - ShShaderOutput shaderOutput, - TSymbolTable *symbolTable) -{ - ASSERT(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER); - - TQualifier viewIDQualifier = (shaderType == GL_VERTEX_SHADER) ? EvqFlatOut : EvqFlatIn; - TIntermSymbol *viewIDSymbol = new TIntermSymbol(symbolTable->nextUniqueId(), "ViewID_OVR", - TType(EbtUInt, EbpHigh, viewIDQualifier)); - viewIDSymbol->setInternal(true); - - DeclareGlobalVariable(root, viewIDSymbol); - ReplaceSymbol(root, "gl_ViewID_OVR", viewIDSymbol); - if (shaderType == GL_VERTEX_SHADER) - { - // Replacing gl_InstanceID with InstanceID should happen before adding the initializers of - // InstanceID and ViewID. - TIntermSymbol *instanceIDSymbol = new TIntermSymbol( - symbolTable->nextUniqueId(), "InstanceID", TType(EbtInt, EbpHigh, EvqGlobal)); - instanceIDSymbol->setInternal(true); - DeclareGlobalVariable(root, instanceIDSymbol); - ReplaceSymbol(root, "gl_InstanceID", instanceIDSymbol); - - TIntermSequence *initializers = new TIntermSequence(); - InitializeViewIDAndInstanceID(viewIDSymbol, instanceIDSymbol, numberOfViews, *symbolTable, - initializers); - - // The AST transformation which adds the expression to select the viewport index should - // be done only for the GLSL and ESSL output. - const bool selectView = (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u; - // Assert that if the view is selected in the vertex shader, then the output is - // either GLSL or ESSL. - ASSERT(!selectView || IsOutputGLSL(shaderOutput) || IsOutputESSL(shaderOutput)); - if (selectView) - { - // Add a uniform to switch between side-by-side and layered rendering. - TIntermSymbol *multiviewBaseViewLayerIndexSymbol = - new TIntermSymbol(symbolTable->nextUniqueId(), "multiviewBaseViewLayerIndex", - TType(EbtInt, EbpHigh, EvqUniform)); - multiviewBaseViewLayerIndexSymbol->setInternal(true); - DeclareGlobalVariable(root, multiviewBaseViewLayerIndexSymbol); - - // Setting a value to gl_ViewportIndex or gl_Layer should happen after ViewID_OVR's - // initialization. - SelectViewIndexInVertexShader(viewIDSymbol->deepCopy(), - multiviewBaseViewLayerIndexSymbol->deepCopy(), - initializers, *symbolTable); - } - - // Insert initializers at the beginning of main(). - TIntermBlock *initializersBlock = new TIntermBlock(); - initializersBlock->getSequence()->swap(*initializers); - TIntermBlock *mainBody = FindMainBody(root); - mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initializersBlock); - } -} - -} // namespace sh
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h b/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h deleted file mode 100644 index b4ab05fd0e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Regardless of the shader type, the following AST transformations are applied: -// - Add declaration of View_ID_OVR. -// - Replace every occurrence of gl_ViewID_OVR with ViewID_OVR, mark ViewID_OVR as internal and -// declare it as a flat varying. -// -// If the shader type is a vertex shader, the following AST transformations are applied: -// - Replace every occurrence of gl_InstanceID with InstanceID, mark InstanceID as internal and set -// its qualifier to EvqTemporary. -// - Add initializers of ViewID_OVR and InstanceID to the beginning of the body of main. The pass -// should be executed before any variables get collected so that usage of gl_InstanceID is recorded. -// - If the output is ESSL or GLSL and the SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is -// enabled, the expression -// "if (multiviewBaseViewLayerIndex < 0) { -// gl_ViewportIndex = int(ViewID_OVR); -// } else { -// gl_Layer = int(ViewID_OVR) + multiviewBaseViewLayerIndex; -// }" -// is added after ViewID and InstanceID are initialized. Also, MultiviewRenderPath is added as a -// uniform. -// - -#ifndef COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_ -#define COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_ - -#include "GLSLANG/ShaderLang.h" -#include "angle_gl.h" - -namespace sh -{ - -class TIntermBlock; -class TSymbolTable; - -void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root, - unsigned numberOfViews, - GLenum shaderType, - ShCompileOptions compileOptions, - ShShaderOutput shaderOutput, - TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp b/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp deleted file mode 100644 index 67d51ea87b..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// DeferGlobalInitializers is an AST traverser that moves global initializers into a separate -// function that is called in the beginning of main(). This enables initialization of globals with -// uniforms or non-constant globals, as allowed by the WebGL spec. Some initializers referencing -// non-constants may need to be unfolded into if statements in HLSL - this kind of steps should be -// done after DeferGlobalInitializers is run. Note that it's important that the function definition -// is at the end of the shader, as some globals may be declared after main(). -// -// It can also initialize all uninitialized globals. -// - -#include "compiler/translator/DeferGlobalInitializers.h" - -#include "compiler/translator/FindMain.h" -#include "compiler/translator/InitializeVariables.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -void GetDeferredInitializers(TIntermDeclaration *declaration, - bool initializeUninitializedGlobals, - bool canUseLoopsToInitialize, - TIntermSequence *deferredInitializersOut, - TSymbolTable *symbolTable) -{ - // SeparateDeclarations should have already been run. - ASSERT(declaration->getSequence()->size() == 1); - - TIntermNode *declarator = declaration->getSequence()->back(); - TIntermBinary *init = declarator->getAsBinaryNode(); - if (init) - { - TIntermSymbol *symbolNode = init->getLeft()->getAsSymbolNode(); - ASSERT(symbolNode); - TIntermTyped *expression = init->getRight(); - - if ((expression->getQualifier() != EvqConst || - (expression->getAsConstantUnion() == nullptr && - !expression->isConstructorWithOnlyConstantUnionParameters()))) - { - // For variables which are not constant, defer their real initialization until - // after we initialize uniforms. - // Deferral is done also in any cases where the variable has not been constant - // folded, since otherwise there's a chance that HLSL output will generate extra - // statements from the initializer expression. - - // Change const global to a regular global if its initialization is deferred. - // This can happen if ANGLE has not been able to fold the constant expression used - // as an initializer. - ASSERT(symbolNode->getQualifier() == EvqConst || - symbolNode->getQualifier() == EvqGlobal); - if (symbolNode->getQualifier() == EvqConst) - { - symbolNode->getTypePointer()->setQualifier(EvqGlobal); - } - - TIntermBinary *deferredInit = - new TIntermBinary(EOpAssign, symbolNode->deepCopy(), init->getRight()); - deferredInitializersOut->push_back(deferredInit); - - // Remove the initializer from the global scope and just declare the global instead. - declaration->replaceChildNode(init, symbolNode); - } - } - else if (initializeUninitializedGlobals) - { - TIntermSymbol *symbolNode = declarator->getAsSymbolNode(); - ASSERT(symbolNode); - - // Ignore ANGLE internal variables. - if (symbolNode->getName().isInternal()) - return; - - if (symbolNode->getQualifier() == EvqGlobal && symbolNode->getSymbol() != "") - { - TIntermSequence *initCode = - CreateInitCode(symbolNode, canUseLoopsToInitialize, symbolTable); - deferredInitializersOut->insert(deferredInitializersOut->end(), initCode->begin(), - initCode->end()); - } - } -} - -void InsertInitCallToMain(TIntermBlock *root, - TIntermSequence *deferredInitializers, - TSymbolTable *symbolTable) -{ - TIntermBlock *initGlobalsBlock = new TIntermBlock(); - initGlobalsBlock->getSequence()->swap(*deferredInitializers); - - TSymbolUniqueId initGlobalsFunctionId(symbolTable); - - const char *kInitGlobalsFunctionName = "initGlobals"; - - TIntermFunctionPrototype *initGlobalsFunctionPrototype = - CreateInternalFunctionPrototypeNode(TType(), kInitGlobalsFunctionName, initGlobalsFunctionId); - root->getSequence()->insert(root->getSequence()->begin(), initGlobalsFunctionPrototype); - TIntermFunctionDefinition *initGlobalsFunctionDefinition = CreateInternalFunctionDefinitionNode( - TType(), kInitGlobalsFunctionName, initGlobalsBlock, initGlobalsFunctionId); - root->appendStatement(initGlobalsFunctionDefinition); - - TIntermAggregate *initGlobalsCall = CreateInternalFunctionCallNode( - TType(), kInitGlobalsFunctionName, initGlobalsFunctionId, new TIntermSequence()); - - TIntermBlock *mainBody = FindMainBody(root); - mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initGlobalsCall); -} - -} // namespace - -void DeferGlobalInitializers(TIntermBlock *root, - bool initializeUninitializedGlobals, - bool canUseLoopsToInitialize, - TSymbolTable *symbolTable) -{ - TIntermSequence *deferredInitializers = new TIntermSequence(); - - // Loop over all global statements and process the declarations. This is simpler than using a - // traverser. - for (TIntermNode *statement : *root->getSequence()) - { - TIntermDeclaration *declaration = statement->getAsDeclarationNode(); - if (declaration) - { - GetDeferredInitializers(declaration, initializeUninitializedGlobals, - canUseLoopsToInitialize, deferredInitializers, symbolTable); - } - } - - // Add the function with initialization and the call to that. - if (!deferredInitializers->empty()) - { - InsertInitCallToMain(root, deferredInitializers, symbolTable); - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h b/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h deleted file mode 100644 index 86930a585f..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// DeferGlobalInitializers is an AST traverser that moves global initializers into a separate -// function that is called in the beginning of main(). This enables initialization of globals with -// uniforms or non-constant globals, as allowed by the WebGL spec. Some initializers referencing -// non-constants may need to be unfolded into if statements in HLSL - this kind of steps should be -// done after DeferGlobalInitializers is run. Note that it's important that the function definition -// is at the end of the shader, as some globals may be declared after main(). -// -// It can also initialize all uninitialized globals. -// - -#ifndef COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_ -#define COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_ - -namespace sh -{ - -class TIntermBlock; -class TSymbolTable; - -void DeferGlobalInitializers(TIntermBlock *root, - bool initializeUninitializedGlobals, - bool canUseLoopsToInitialize, - TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp deleted file mode 100644 index 1744e5ab3e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/Diagnostics.h" - -#include "common/debug.h" -#include "compiler/preprocessor/SourceLocation.h" -#include "compiler/translator/Common.h" -#include "compiler/translator/InfoSink.h" - -namespace sh -{ - -TDiagnostics::TDiagnostics(TInfoSinkBase &infoSink) - : mInfoSink(infoSink), mNumErrors(0), mNumWarnings(0) -{ -} - -TDiagnostics::~TDiagnostics() -{ -} - -void TDiagnostics::writeInfo(Severity severity, - const pp::SourceLocation &loc, - const char *reason, - const char *token) -{ - switch (severity) - { - case SH_ERROR: - ++mNumErrors; - break; - case SH_WARNING: - ++mNumWarnings; - break; - default: - UNREACHABLE(); - break; - } - - /* VC++ format: file(linenum) : error #: 'token' : extrainfo */ - mInfoSink.prefix(severity); - mInfoSink.location(loc.file, loc.line); - mInfoSink << "'" << token << "' : " << reason << "\n"; -} - -void TDiagnostics::globalError(const char *message) -{ - ++mNumErrors; - mInfoSink.prefix(SH_ERROR); - mInfoSink << message << "\n"; -} - -void TDiagnostics::error(const pp::SourceLocation &loc, const char *reason, const char *token) -{ - writeInfo(SH_ERROR, loc, reason, token); -} - -void TDiagnostics::warning(const pp::SourceLocation &loc, const char *reason, const char *token) -{ - writeInfo(SH_WARNING, loc, reason, token); -} - -void TDiagnostics::error(const TSourceLoc &loc, const char *reason, const char *token) -{ - pp::SourceLocation srcLoc; - srcLoc.file = loc.first_file; - srcLoc.line = loc.first_line; - error(srcLoc, reason, token); -} - -void TDiagnostics::warning(const TSourceLoc &loc, const char *reason, const char *token) -{ - pp::SourceLocation srcLoc; - srcLoc.file = loc.first_file; - srcLoc.line = loc.first_line; - warning(srcLoc, reason, token); -} - -void TDiagnostics::print(ID id, const pp::SourceLocation &loc, const std::string &text) -{ - writeInfo(isError(id) ? SH_ERROR : SH_WARNING, loc, message(id), text.c_str()); -} - -void TDiagnostics::resetErrorCount() -{ - mNumErrors = 0; - mNumWarnings = 0; -} - -PerformanceDiagnostics::PerformanceDiagnostics(TDiagnostics *diagnostics) - : mDiagnostics(diagnostics) -{ - ASSERT(diagnostics); -} - -void PerformanceDiagnostics::warning(const TSourceLoc &loc, const char *reason, const char *token) -{ - mDiagnostics->warning(loc, reason, token); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h deleted file mode 100644 index 55b88991df..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_DIAGNOSTICS_H_ -#define COMPILER_TRANSLATOR_DIAGNOSTICS_H_ - -#include "common/angleutils.h" -#include "compiler/preprocessor/DiagnosticsBase.h" -#include "compiler/translator/Severity.h" - -namespace sh -{ - -class TInfoSinkBase; -struct TSourceLoc; - -class TDiagnostics : public pp::Diagnostics, angle::NonCopyable -{ - public: - TDiagnostics(TInfoSinkBase &infoSink); - ~TDiagnostics() override; - - int numErrors() const { return mNumErrors; } - int numWarnings() const { return mNumWarnings; } - - void error(const pp::SourceLocation &loc, const char *reason, const char *token); - void warning(const pp::SourceLocation &loc, const char *reason, const char *token); - - void error(const TSourceLoc &loc, const char *reason, const char *token); - void warning(const TSourceLoc &loc, const char *reason, const char *token); - - void globalError(const char *message); - - void resetErrorCount(); - - protected: - void writeInfo(Severity severity, - const pp::SourceLocation &loc, - const char *reason, - const char *token); - - void print(ID id, const pp::SourceLocation &loc, const std::string &text) override; - - private: - TInfoSinkBase &mInfoSink; - int mNumErrors; - int mNumWarnings; -}; - -// Diagnostics wrapper to use when the code is only allowed to generate warnings. -class PerformanceDiagnostics : public angle::NonCopyable -{ - public: - PerformanceDiagnostics(TDiagnostics *diagnostics); - - void warning(const TSourceLoc &loc, const char *reason, const char *token); - - private: - TDiagnostics *mDiagnostics; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_DIAGNOSTICS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp deleted file mode 100644 index 485e66670c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp +++ /dev/null @@ -1,203 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/DirectiveHandler.h" - -#include <sstream> - -#include "angle_gl.h" -#include "common/debug.h" -#include "compiler/translator/Diagnostics.h" - -namespace sh -{ - -static TBehavior getBehavior(const std::string &str) -{ - const char kRequire[] = "require"; - const char kEnable[] = "enable"; - const char kDisable[] = "disable"; - const char kWarn[] = "warn"; - - if (str == kRequire) - return EBhRequire; - else if (str == kEnable) - return EBhEnable; - else if (str == kDisable) - return EBhDisable; - else if (str == kWarn) - return EBhWarn; - return EBhUndefined; -} - -TDirectiveHandler::TDirectiveHandler(TExtensionBehavior &extBehavior, - TDiagnostics &diagnostics, - int &shaderVersion, - sh::GLenum shaderType, - bool debugShaderPrecisionSupported) - : mExtensionBehavior(extBehavior), - mDiagnostics(diagnostics), - mShaderVersion(shaderVersion), - mShaderType(shaderType), - mDebugShaderPrecisionSupported(debugShaderPrecisionSupported) -{ -} - -TDirectiveHandler::~TDirectiveHandler() -{ -} - -void TDirectiveHandler::handleError(const pp::SourceLocation &loc, const std::string &msg) -{ - mDiagnostics.error(loc, msg.c_str(), ""); -} - -void TDirectiveHandler::handlePragma(const pp::SourceLocation &loc, - const std::string &name, - const std::string &value, - bool stdgl) -{ - if (stdgl) - { - const char kInvariant[] = "invariant"; - const char kAll[] = "all"; - - if (name == kInvariant && value == kAll) - { - if (mShaderVersion == 300 && mShaderType == GL_FRAGMENT_SHADER) - { - // ESSL 3.00.4 section 4.6.1 - mDiagnostics.error( - loc, "#pragma STDGL invariant(all) can not be used in fragment shader", - name.c_str()); - } - mPragma.stdgl.invariantAll = true; - } - // The STDGL pragma is used to reserve pragmas for use by future - // revisions of GLSL. Do not generate an error on unexpected - // name and value. - return; - } - else - { - const char kOptimize[] = "optimize"; - const char kDebug[] = "debug"; - const char kDebugShaderPrecision[] = "webgl_debug_shader_precision"; - const char kOn[] = "on"; - const char kOff[] = "off"; - - bool invalidValue = false; - if (name == kOptimize) - { - if (value == kOn) - mPragma.optimize = true; - else if (value == kOff) - mPragma.optimize = false; - else - invalidValue = true; - } - else if (name == kDebug) - { - if (value == kOn) - mPragma.debug = true; - else if (value == kOff) - mPragma.debug = false; - else - invalidValue = true; - } - else if (name == kDebugShaderPrecision && mDebugShaderPrecisionSupported) - { - if (value == kOn) - mPragma.debugShaderPrecision = true; - else if (value == kOff) - mPragma.debugShaderPrecision = false; - else - invalidValue = true; - } - else - { - mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name); - return; - } - - if (invalidValue) - { - mDiagnostics.error(loc, "invalid pragma value - 'on' or 'off' expected", value.c_str()); - } - } -} - -void TDirectiveHandler::handleExtension(const pp::SourceLocation &loc, - const std::string &name, - const std::string &behavior) -{ - const char kExtAll[] = "all"; - - TBehavior behaviorVal = getBehavior(behavior); - if (behaviorVal == EBhUndefined) - { - mDiagnostics.error(loc, "behavior invalid", name.c_str()); - return; - } - - if (name == kExtAll) - { - if (behaviorVal == EBhRequire) - { - mDiagnostics.error(loc, "extension cannot have 'require' behavior", name.c_str()); - } - else if (behaviorVal == EBhEnable) - { - mDiagnostics.error(loc, "extension cannot have 'enable' behavior", name.c_str()); - } - else - { - for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin(); - iter != mExtensionBehavior.end(); ++iter) - iter->second = behaviorVal; - } - return; - } - - TExtensionBehavior::iterator iter = mExtensionBehavior.find(GetExtensionByName(name.c_str())); - if (iter != mExtensionBehavior.end()) - { - iter->second = behaviorVal; - return; - } - - switch (behaviorVal) - { - case EBhRequire: - mDiagnostics.error(loc, "extension is not supported", name.c_str()); - break; - case EBhEnable: - case EBhWarn: - case EBhDisable: - mDiagnostics.warning(loc, "extension is not supported", name.c_str()); - break; - default: - UNREACHABLE(); - break; - } -} - -void TDirectiveHandler::handleVersion(const pp::SourceLocation &loc, int version) -{ - if (version == 100 || version == 300 || version == 310) - { - mShaderVersion = version; - } - else - { - std::stringstream stream; - stream << version; - std::string str = stream.str(); - mDiagnostics.error(loc, "version number not supported", str.c_str()); - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h deleted file mode 100644 index 8e8cb9bbf6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ -#define COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ - -#include "common/angleutils.h" -#include "compiler/translator/ExtensionBehavior.h" -#include "compiler/translator/Pragma.h" -#include "compiler/preprocessor/DirectiveHandlerBase.h" -#include "GLSLANG/ShaderLang.h" - -namespace sh -{ -class TDiagnostics; - -class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable -{ - public: - TDirectiveHandler(TExtensionBehavior &extBehavior, - TDiagnostics &diagnostics, - int &shaderVersion, - sh::GLenum shaderType, - bool debugShaderPrecisionSupported); - ~TDirectiveHandler() override; - - const TPragma &pragma() const { return mPragma; } - const TExtensionBehavior &extensionBehavior() const { return mExtensionBehavior; } - - void handleError(const pp::SourceLocation &loc, const std::string &msg) override; - - void handlePragma(const pp::SourceLocation &loc, - const std::string &name, - const std::string &value, - bool stdgl) override; - - void handleExtension(const pp::SourceLocation &loc, - const std::string &name, - const std::string &behavior) override; - - void handleVersion(const pp::SourceLocation &loc, int version) override; - - private: - TPragma mPragma; - TExtensionBehavior &mExtensionBehavior; - TDiagnostics &mDiagnostics; - int &mShaderVersion; - sh::GLenum mShaderType; - bool mDebugShaderPrecisionSupported; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp b/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp deleted file mode 100644 index 189ea341eb..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp +++ /dev/null @@ -1,129 +0,0 @@ -// -// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// gl_FragColor needs to broadcast to all color buffers in ES2 if -// GL_EXT_draw_buffers is explicitly enabled in a fragment shader. -// -// We emulate this by replacing all gl_FragColor with gl_FragData[0], and in the end -// of main() function, assigning gl_FragData[1], ..., gl_FragData[maxDrawBuffers-1] -// with gl_FragData[0]. -// - -#include "compiler/translator/EmulateGLFragColorBroadcast.h" - -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/RunAtTheEndOfShader.h" - -namespace sh -{ - -namespace -{ - -class GLFragColorBroadcastTraverser : public TIntermTraverser -{ - public: - GLFragColorBroadcastTraverser(int maxDrawBuffers, TSymbolTable *symbolTable, int shaderVersion) - : TIntermTraverser(true, false, false, symbolTable), - mGLFragColorUsed(false), - mMaxDrawBuffers(maxDrawBuffers), - mShaderVersion(shaderVersion) - { - } - - void broadcastGLFragColor(TIntermBlock *root); - - bool isGLFragColorUsed() const { return mGLFragColorUsed; } - - protected: - void visitSymbol(TIntermSymbol *node) override; - - TIntermBinary *constructGLFragDataNode(int index) const; - TIntermBinary *constructGLFragDataAssignNode(int index) const; - - private: - bool mGLFragColorUsed; - int mMaxDrawBuffers; - const int mShaderVersion; -}; - -TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataNode(int index) const -{ - TIntermSymbol *symbol = - ReferenceBuiltInVariable(TString("gl_FragData"), *mSymbolTable, mShaderVersion); - TIntermTyped *indexNode = CreateIndexNode(index); - - TIntermBinary *binary = new TIntermBinary(EOpIndexDirect, symbol, indexNode); - return binary; -} - -TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataAssignNode(int index) const -{ - TIntermTyped *fragDataIndex = constructGLFragDataNode(index); - TIntermTyped *fragDataZero = constructGLFragDataNode(0); - - return new TIntermBinary(EOpAssign, fragDataIndex, fragDataZero); -} - -void GLFragColorBroadcastTraverser::visitSymbol(TIntermSymbol *node) -{ - if (node->getSymbol() == "gl_FragColor") - { - queueReplacement(constructGLFragDataNode(0), OriginalNode::IS_DROPPED); - mGLFragColorUsed = true; - } -} - -void GLFragColorBroadcastTraverser::broadcastGLFragColor(TIntermBlock *root) -{ - ASSERT(mMaxDrawBuffers > 1); - if (!mGLFragColorUsed) - { - return; - } - - TIntermBlock *broadcastBlock = new TIntermBlock(); - // Now insert statements - // gl_FragData[1] = gl_FragData[0]; - // ... - // gl_FragData[maxDrawBuffers - 1] = gl_FragData[0]; - for (int colorIndex = 1; colorIndex < mMaxDrawBuffers; ++colorIndex) - { - broadcastBlock->appendStatement(constructGLFragDataAssignNode(colorIndex)); - } - RunAtTheEndOfShader(root, broadcastBlock, mSymbolTable); -} - -} // namespace anonymous - -void EmulateGLFragColorBroadcast(TIntermBlock *root, - int maxDrawBuffers, - std::vector<sh::OutputVariable> *outputVariables, - TSymbolTable *symbolTable, - int shaderVersion) -{ - ASSERT(maxDrawBuffers > 1); - GLFragColorBroadcastTraverser traverser(maxDrawBuffers, symbolTable, shaderVersion); - root->traverse(&traverser); - if (traverser.isGLFragColorUsed()) - { - traverser.updateTree(); - traverser.broadcastGLFragColor(root); - for (auto &var : *outputVariables) - { - if (var.name == "gl_FragColor") - { - // TODO(zmo): Find a way to keep the original variable information. - var.name = "gl_FragData"; - var.mappedName = "gl_FragData"; - var.arraySizes.push_back(maxDrawBuffers); - ASSERT(var.arraySizes.size() == 1u); - } - } - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h b/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h deleted file mode 100644 index e652b7e07e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Emulate gl_FragColor broadcast behaviors in ES2 where -// GL_EXT_draw_buffers is explicitly enabled in a fragment shader. -// - -#ifndef COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_ -#define COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_ - -#include <vector> - -namespace sh -{ -struct OutputVariable; -class TIntermBlock; -class TSymbolTable; - -// Replace all gl_FragColor with gl_FragData[0], and in the end of main() function, -// assign gl_FragData[1] ... gl_FragData[maxDrawBuffers - 1] with gl_FragData[0]. -// If gl_FragColor is in outputVariables, it is replaced by gl_FragData. -void EmulateGLFragColorBroadcast(TIntermBlock *root, - int maxDrawBuffers, - std::vector<OutputVariable> *outputVariables, - TSymbolTable *symbolTable, - int shaderVersion); -} - -#endif // COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp deleted file mode 100644 index ba09fd77df..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp +++ /dev/null @@ -1,751 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/EmulatePrecision.h" - -#include <memory> - -namespace sh -{ - -namespace -{ - -class RoundingHelperWriter : angle::NonCopyable -{ - public: - static RoundingHelperWriter *createHelperWriter(const ShShaderOutput outputLanguage); - - void writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion); - void writeCompoundAssignmentHelper(TInfoSinkBase &sink, - const char *lType, - const char *rType, - const char *opStr, - const char *opNameStr); - - virtual ~RoundingHelperWriter() {} - - protected: - RoundingHelperWriter(const ShShaderOutput outputLanguage) : mOutputLanguage(outputLanguage) {} - RoundingHelperWriter() = delete; - - const ShShaderOutput mOutputLanguage; - - private: - virtual std::string getTypeString(const char *glslType) = 0; - virtual void writeFloatRoundingHelpers(TInfoSinkBase &sink) = 0; - virtual void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) = 0; - virtual void writeMatrixRoundingHelper(TInfoSinkBase &sink, - const unsigned int columns, - const unsigned int rows, - const char *functionName) = 0; -}; - -class RoundingHelperWriterGLSL : public RoundingHelperWriter -{ - public: - RoundingHelperWriterGLSL(const ShShaderOutput outputLanguage) - : RoundingHelperWriter(outputLanguage) - { - } - - private: - std::string getTypeString(const char *glslType) override; - void writeFloatRoundingHelpers(TInfoSinkBase &sink) override; - void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override; - void writeMatrixRoundingHelper(TInfoSinkBase &sink, - const unsigned int columns, - const unsigned int rows, - const char *functionName) override; -}; - -class RoundingHelperWriterESSL : public RoundingHelperWriterGLSL -{ - public: - RoundingHelperWriterESSL(const ShShaderOutput outputLanguage) - : RoundingHelperWriterGLSL(outputLanguage) - { - } - - private: - std::string getTypeString(const char *glslType) override; -}; - -class RoundingHelperWriterHLSL : public RoundingHelperWriter -{ - public: - RoundingHelperWriterHLSL(const ShShaderOutput outputLanguage) - : RoundingHelperWriter(outputLanguage) - { - } - - private: - std::string getTypeString(const char *glslType) override; - void writeFloatRoundingHelpers(TInfoSinkBase &sink) override; - void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override; - void writeMatrixRoundingHelper(TInfoSinkBase &sink, - const unsigned int columns, - const unsigned int rows, - const char *functionName) override; -}; - -RoundingHelperWriter *RoundingHelperWriter::createHelperWriter(const ShShaderOutput outputLanguage) -{ - ASSERT(EmulatePrecision::SupportedInLanguage(outputLanguage)); - switch (outputLanguage) - { - case SH_HLSL_4_1_OUTPUT: - return new RoundingHelperWriterHLSL(outputLanguage); - case SH_ESSL_OUTPUT: - return new RoundingHelperWriterESSL(outputLanguage); - default: - return new RoundingHelperWriterGLSL(outputLanguage); - } -} - -void RoundingHelperWriter::writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion) -{ - // Write the angle_frm functions that round floating point numbers to - // half precision, and angle_frl functions that round them to minimum lowp - // precision. - - writeFloatRoundingHelpers(sink); - writeVectorRoundingHelpers(sink, 2); - writeVectorRoundingHelpers(sink, 3); - writeVectorRoundingHelpers(sink, 4); - if (shaderVersion > 100) - { - for (unsigned int columns = 2; columns <= 4; ++columns) - { - for (unsigned int rows = 2; rows <= 4; ++rows) - { - writeMatrixRoundingHelper(sink, columns, rows, "angle_frm"); - writeMatrixRoundingHelper(sink, columns, rows, "angle_frl"); - } - } - } - else - { - for (unsigned int size = 2; size <= 4; ++size) - { - writeMatrixRoundingHelper(sink, size, size, "angle_frm"); - writeMatrixRoundingHelper(sink, size, size, "angle_frl"); - } - } -} - -void RoundingHelperWriter::writeCompoundAssignmentHelper(TInfoSinkBase &sink, - const char *lType, - const char *rType, - const char *opStr, - const char *opNameStr) -{ - std::string lTypeStr = getTypeString(lType); - std::string rTypeStr = getTypeString(rType); - - // Note that y should be passed through angle_frm at the function call site, - // but x can't be passed through angle_frm there since it is an inout parameter. - // So only pass x and the result through angle_frm here. - // clang-format off - sink << - lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n" - " x = angle_frm(angle_frm(x) " << opStr << " y);\n" - " return x;\n" - "}\n"; - sink << - lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n" - " x = angle_frl(angle_frl(x) " << opStr << " y);\n" - " return x;\n" - "}\n"; - // clang-format on -} - -std::string RoundingHelperWriterGLSL::getTypeString(const char *glslType) -{ - return glslType; -} - -std::string RoundingHelperWriterESSL::getTypeString(const char *glslType) -{ - std::stringstream typeStrStr; - typeStrStr << "highp " << glslType; - return typeStrStr.str(); -} - -void RoundingHelperWriterGLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink) -{ - // Unoptimized version of angle_frm for single floats: - // - // int webgl_maxNormalExponent(in int exponentBits) - // { - // int possibleExponents = int(exp2(float(exponentBits))); - // int exponentBias = possibleExponents / 2 - 1; - // int allExponentBitsOne = possibleExponents - 1; - // return (allExponentBitsOne - 1) - exponentBias; - // } - // - // float angle_frm(in float x) - // { - // int mantissaBits = 10; - // int exponentBits = 5; - // float possibleMantissas = exp2(float(mantissaBits)); - // float mantissaMax = 2.0 - 1.0 / possibleMantissas; - // int maxNE = webgl_maxNormalExponent(exponentBits); - // float max = exp2(float(maxNE)) * mantissaMax; - // if (x > max) - // { - // return max; - // } - // if (x < -max) - // { - // return -max; - // } - // float exponent = floor(log2(abs(x))); - // if (abs(x) == 0.0 || exponent < -float(maxNE)) - // { - // return 0.0 * sign(x) - // } - // x = x * exp2(-(exponent - float(mantissaBits))); - // x = sign(x) * floor(abs(x)); - // return x * exp2(exponent - float(mantissaBits)); - // } - - // All numbers with a magnitude less than 2^-15 are subnormal, and are - // flushed to zero. - - // Note the constant numbers below: - // a) 65504 is the maximum possible mantissa (1.1111111111 in binary) times - // 2^15, the maximum normal exponent. - // b) 10.0 is the number of mantissa bits. - // c) -25.0 is the minimum normal half-float exponent -15.0 minus the number - // of mantissa bits. - // d) + 1e-30 is to make sure the argument of log2() won't be zero. It can - // only affect the result of log2 on x where abs(x) < 1e-22. Since these - // numbers will be flushed to zero either way (2^-15 is the smallest - // normal positive number), this does not introduce any error. - - std::string floatType = getTypeString("float"); - - // clang-format off - sink << - floatType << " angle_frm(in " << floatType << " x) {\n" - " x = clamp(x, -65504.0, 65504.0);\n" - " " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n" - " bool isNonZero = (exponent >= -25.0);\n" - " x = x * exp2(-exponent);\n" - " x = sign(x) * floor(abs(x));\n" - " return x * exp2(exponent) * float(isNonZero);\n" - "}\n"; - - sink << - floatType << " angle_frl(in " << floatType << " x) {\n" - " x = clamp(x, -2.0, 2.0);\n" - " x = x * 256.0;\n" - " x = sign(x) * floor(abs(x));\n" - " return x * 0.00390625;\n" - "}\n"; - // clang-format on -} - -void RoundingHelperWriterGLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink, - const unsigned int size) -{ - std::stringstream vecTypeStrStr; - vecTypeStrStr << "vec" << size; - std::string vecType = getTypeString(vecTypeStrStr.str().c_str()); - - // clang-format off - sink << - vecType << " angle_frm(in " << vecType << " v) {\n" - " v = clamp(v, -65504.0, 65504.0);\n" - " " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n" - " bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n" - " v = v * exp2(-exponent);\n" - " v = sign(v) * floor(abs(v));\n" - " return v * exp2(exponent) * vec" << size << "(isNonZero);\n" - "}\n"; - - sink << - vecType << " angle_frl(in " << vecType << " v) {\n" - " v = clamp(v, -2.0, 2.0);\n" - " v = v * 256.0;\n" - " v = sign(v) * floor(abs(v));\n" - " return v * 0.00390625;\n" - "}\n"; - // clang-format on -} - -void RoundingHelperWriterGLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink, - const unsigned int columns, - const unsigned int rows, - const char *functionName) -{ - std::stringstream matTypeStrStr; - matTypeStrStr << "mat" << columns; - if (rows != columns) - { - matTypeStrStr << "x" << rows; - } - std::string matType = getTypeString(matTypeStrStr.str().c_str()); - - sink << matType << " " << functionName << "(in " << matType << " m) {\n" - << " " << matType << " rounded;\n"; - - for (unsigned int i = 0; i < columns; ++i) - { - sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n"; - } - - sink << " return rounded;\n" - "}\n"; -} - -static const char *GetHLSLTypeStr(const char *floatTypeStr) -{ - if (strcmp(floatTypeStr, "float") == 0) - { - return "float"; - } - if (strcmp(floatTypeStr, "vec2") == 0) - { - return "float2"; - } - if (strcmp(floatTypeStr, "vec3") == 0) - { - return "float3"; - } - if (strcmp(floatTypeStr, "vec4") == 0) - { - return "float4"; - } - if (strcmp(floatTypeStr, "mat2") == 0) - { - return "float2x2"; - } - if (strcmp(floatTypeStr, "mat3") == 0) - { - return "float3x3"; - } - if (strcmp(floatTypeStr, "mat4") == 0) - { - return "float4x4"; - } - if (strcmp(floatTypeStr, "mat2x3") == 0) - { - return "float2x3"; - } - if (strcmp(floatTypeStr, "mat2x4") == 0) - { - return "float2x4"; - } - if (strcmp(floatTypeStr, "mat3x2") == 0) - { - return "float3x2"; - } - if (strcmp(floatTypeStr, "mat3x4") == 0) - { - return "float3x4"; - } - if (strcmp(floatTypeStr, "mat4x2") == 0) - { - return "float4x2"; - } - if (strcmp(floatTypeStr, "mat4x3") == 0) - { - return "float4x3"; - } - UNREACHABLE(); - return nullptr; -} - -std::string RoundingHelperWriterHLSL::getTypeString(const char *glslType) -{ - return GetHLSLTypeStr(glslType); -} - -void RoundingHelperWriterHLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink) -{ - // In HLSL scalars are the same as 1-vectors. - writeVectorRoundingHelpers(sink, 1); -} - -void RoundingHelperWriterHLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink, - const unsigned int size) -{ - std::stringstream vecTypeStrStr; - vecTypeStrStr << "float" << size; - std::string vecType = vecTypeStrStr.str(); - - // clang-format off - sink << - vecType << " angle_frm(" << vecType << " v) {\n" - " v = clamp(v, -65504.0, 65504.0);\n" - " " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n" - " bool" << size << " isNonZero = exponent < -25.0;\n" - " v = v * exp2(-exponent);\n" - " v = sign(v) * floor(abs(v));\n" - " return v * exp2(exponent) * (float" << size << ")(isNonZero);\n" - "}\n"; - - sink << - vecType << " angle_frl(" << vecType << " v) {\n" - " v = clamp(v, -2.0, 2.0);\n" - " v = v * 256.0;\n" - " v = sign(v) * floor(abs(v));\n" - " return v * 0.00390625;\n" - "}\n"; - // clang-format on -} - -void RoundingHelperWriterHLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink, - const unsigned int columns, - const unsigned int rows, - const char *functionName) -{ - std::stringstream matTypeStrStr; - matTypeStrStr << "float" << columns << "x" << rows; - std::string matType = matTypeStrStr.str(); - - sink << matType << " " << functionName << "(" << matType << " m) {\n" - << " " << matType << " rounded;\n"; - - for (unsigned int i = 0; i < columns; ++i) - { - sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n"; - } - - sink << " return rounded;\n" - "}\n"; -} - -bool canRoundFloat(const TType &type) -{ - return type.getBasicType() == EbtFloat && !type.isArray() && - (type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium); -} - -TIntermAggregate *createInternalFunctionCallNode(const TType &type, - TString name, - TIntermSequence *arguments) -{ - TName nameObj(name); - nameObj.setInternal(true); - TIntermAggregate *callNode = - TIntermAggregate::Create(type, EOpCallInternalRawFunction, arguments); - callNode->getFunctionSymbolInfo()->setNameObj(nameObj); - return callNode; -} - -TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild) -{ - TString roundFunctionName; - if (roundedChild->getPrecision() == EbpMedium) - roundFunctionName = "angle_frm"; - else - roundFunctionName = "angle_frl"; - TIntermSequence *arguments = new TIntermSequence(); - arguments->push_back(roundedChild); - TIntermAggregate *callNode = - createInternalFunctionCallNode(roundedChild->getType(), roundFunctionName, arguments); - callNode->getFunctionSymbolInfo()->setKnownToNotHaveSideEffects(true); - return callNode; -} - -TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left, - TIntermTyped *right, - const char *opNameStr) -{ - std::stringstream strstr; - if (left->getPrecision() == EbpMedium) - strstr << "angle_compound_" << opNameStr << "_frm"; - else - strstr << "angle_compound_" << opNameStr << "_frl"; - TString functionName = strstr.str().c_str(); - TIntermSequence *arguments = new TIntermSequence(); - arguments->push_back(left); - arguments->push_back(right); - return createInternalFunctionCallNode(left->getType(), functionName, arguments); -} - -bool ParentUsesResult(TIntermNode *parent, TIntermTyped *node) -{ - if (!parent) - { - return false; - } - - TIntermBlock *blockParent = parent->getAsBlock(); - // If the parent is a block, the result is not assigned anywhere, - // so rounding it is not needed. In particular, this can avoid a lot of - // unnecessary rounding of unused return values of assignment. - if (blockParent) - { - return false; - } - TIntermBinary *binaryParent = parent->getAsBinaryNode(); - if (binaryParent && binaryParent->getOp() == EOpComma && (binaryParent->getRight() != node)) - { - return false; - } - return true; -} - -bool ParentConstructorTakesCareOfRounding(TIntermNode *parent, TIntermTyped *node) -{ - if (!parent) - { - return false; - } - TIntermAggregate *parentConstructor = parent->getAsAggregate(); - if (!parentConstructor || parentConstructor->getOp() != EOpConstruct) - { - return false; - } - if (parentConstructor->getPrecision() != node->getPrecision()) - { - return false; - } - return canRoundFloat(parentConstructor->getType()); -} - -} // namespace anonymous - -EmulatePrecision::EmulatePrecision(TSymbolTable *symbolTable, int shaderVersion) - : TLValueTrackingTraverser(true, true, true, symbolTable, shaderVersion), - mDeclaringVariables(false) -{ -} - -void EmulatePrecision::visitSymbol(TIntermSymbol *node) -{ - TIntermNode *parent = getParentNode(); - if (canRoundFloat(node->getType()) && ParentUsesResult(parent, node) && - !ParentConstructorTakesCareOfRounding(parent, node) && !mDeclaringVariables && - !isLValueRequiredHere()) - { - TIntermNode *replacement = createRoundingFunctionCallNode(node); - queueReplacement(replacement, OriginalNode::BECOMES_CHILD); - } -} - -bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node) -{ - bool visitChildren = true; - - TOperator op = node->getOp(); - - // RHS of initialize is not being declared. - if (op == EOpInitialize && visit == InVisit) - mDeclaringVariables = false; - - if ((op == EOpIndexDirectStruct) && visit == InVisit) - visitChildren = false; - - if (visit != PreVisit) - return visitChildren; - - const TType &type = node->getType(); - bool roundFloat = canRoundFloat(type); - - if (roundFloat) - { - switch (op) - { - // Math operators that can result in a float may need to apply rounding to the return - // value. Note that in the case of assignment, the rounding is applied to its return - // value here, not the value being assigned. - case EOpAssign: - case EOpAdd: - case EOpSub: - case EOpMul: - case EOpDiv: - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: - { - TIntermNode *parent = getParentNode(); - if (!ParentUsesResult(parent, node) || - ParentConstructorTakesCareOfRounding(parent, node)) - { - break; - } - TIntermNode *replacement = createRoundingFunctionCallNode(node); - queueReplacement(replacement, OriginalNode::BECOMES_CHILD); - break; - } - - // Compound assignment cases need to replace the operator with a function call. - case EOpAddAssign: - { - mEmulateCompoundAdd.insert( - TypePair(type.getBuiltInTypeNameString(), - node->getRight()->getType().getBuiltInTypeNameString())); - TIntermNode *replacement = createCompoundAssignmentFunctionCallNode( - node->getLeft(), node->getRight(), "add"); - queueReplacement(replacement, OriginalNode::IS_DROPPED); - break; - } - case EOpSubAssign: - { - mEmulateCompoundSub.insert( - TypePair(type.getBuiltInTypeNameString(), - node->getRight()->getType().getBuiltInTypeNameString())); - TIntermNode *replacement = createCompoundAssignmentFunctionCallNode( - node->getLeft(), node->getRight(), "sub"); - queueReplacement(replacement, OriginalNode::IS_DROPPED); - break; - } - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - { - mEmulateCompoundMul.insert( - TypePair(type.getBuiltInTypeNameString(), - node->getRight()->getType().getBuiltInTypeNameString())); - TIntermNode *replacement = createCompoundAssignmentFunctionCallNode( - node->getLeft(), node->getRight(), "mul"); - queueReplacement(replacement, OriginalNode::IS_DROPPED); - break; - } - case EOpDivAssign: - { - mEmulateCompoundDiv.insert( - TypePair(type.getBuiltInTypeNameString(), - node->getRight()->getType().getBuiltInTypeNameString())); - TIntermNode *replacement = createCompoundAssignmentFunctionCallNode( - node->getLeft(), node->getRight(), "div"); - queueReplacement(replacement, OriginalNode::IS_DROPPED); - break; - } - default: - // The rest of the binary operations should not need precision emulation. - break; - } - } - return visitChildren; -} - -bool EmulatePrecision::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - // Variable or interface block declaration. - if (visit == PreVisit) - { - mDeclaringVariables = true; - } - else if (visit == InVisit) - { - mDeclaringVariables = true; - } - else - { - mDeclaringVariables = false; - } - return true; -} - -bool EmulatePrecision::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) -{ - return false; -} - -bool EmulatePrecision::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) -{ - return false; -} - -bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (visit != PreVisit) - return true; - switch (node->getOp()) - { - case EOpCallInternalRawFunction: - case EOpCallFunctionInAST: - // User-defined function return values are not rounded. The calculations that produced - // the value inside the function definition should have been rounded. - break; - case EOpConstruct: - if (node->getBasicType() == EbtStruct) - { - break; - } - default: - TIntermNode *parent = getParentNode(); - if (canRoundFloat(node->getType()) && ParentUsesResult(parent, node) && - !ParentConstructorTakesCareOfRounding(parent, node)) - { - TIntermNode *replacement = createRoundingFunctionCallNode(node); - queueReplacement(replacement, OriginalNode::BECOMES_CHILD); - } - break; - } - return true; -} - -bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node) -{ - switch (node->getOp()) - { - case EOpNegative: - case EOpLogicalNot: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - case EOpLogicalNotComponentWise: - break; - default: - if (canRoundFloat(node->getType()) && visit == PreVisit) - { - TIntermNode *replacement = createRoundingFunctionCallNode(node); - queueReplacement(replacement, OriginalNode::BECOMES_CHILD); - } - break; - } - - return true; -} - -void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase &sink, - const int shaderVersion, - const ShShaderOutput outputLanguage) -{ - std::unique_ptr<RoundingHelperWriter> roundingHelperWriter( - RoundingHelperWriter::createHelperWriter(outputLanguage)); - - roundingHelperWriter->writeCommonRoundingHelpers(sink, shaderVersion); - - EmulationSet::const_iterator it; - for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++) - roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "+", "add"); - for (it = mEmulateCompoundSub.begin(); it != mEmulateCompoundSub.end(); it++) - roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "-", "sub"); - for (it = mEmulateCompoundDiv.begin(); it != mEmulateCompoundDiv.end(); it++) - roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "/", "div"); - for (it = mEmulateCompoundMul.begin(); it != mEmulateCompoundMul.end(); it++) - roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "*", "mul"); -} - -// static -bool EmulatePrecision::SupportedInLanguage(const ShShaderOutput outputLanguage) -{ - switch (outputLanguage) - { - case SH_HLSL_4_1_OUTPUT: - case SH_ESSL_OUTPUT: - return true; - default: - // Other languages not yet supported - return (outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT || - sh::IsGLSL130OrNewer(outputLanguage)); - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h deleted file mode 100644 index 8044465410..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h +++ /dev/null @@ -1,73 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ -#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ - -#include "GLSLANG/ShaderLang.h" -#include "common/angleutils.h" -#include "compiler/translator/Compiler.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermTraverse.h" - -// This class gathers all compound assignments from the AST and can then write -// the functions required for their precision emulation. This way there is no -// need to write a huge number of variations of the emulated compound assignment -// to every translated shader with emulation enabled. - -namespace sh -{ - -class EmulatePrecision : public TLValueTrackingTraverser -{ - public: - EmulatePrecision(TSymbolTable *symbolTable, int shaderVersion); - - void visitSymbol(TIntermSymbol *node) override; - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitUnary(Visit visit, TIntermUnary *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override; - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; - - void writeEmulationHelpers(TInfoSinkBase &sink, - const int shaderVersion, - const ShShaderOutput outputLanguage); - - static bool SupportedInLanguage(const ShShaderOutput outputLanguage); - - private: - struct TypePair - { - TypePair(const char *l, const char *r) : lType(l), rType(r) {} - - const char *lType; - const char *rType; - }; - - struct TypePairComparator - { - bool operator()(const TypePair &l, const TypePair &r) const - { - if (l.lType == r.lType) - return l.rType < r.rType; - return l.lType < r.lType; - } - }; - - typedef std::set<TypePair, TypePairComparator> EmulationSet; - EmulationSet mEmulateCompoundAdd; - EmulationSet mEmulateCompoundSub; - EmulationSet mEmulateCompoundMul; - EmulationSet mEmulateCompoundDiv; - - bool mDeclaringVariables; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp b/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp deleted file mode 100644 index f17dd73657..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Implementation of the integer pow expressions HLSL bug workaround. -// See header for more info. - -#include "compiler/translator/ExpandIntegerPowExpressions.h" - -#include <cmath> -#include <cstdlib> - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class Traverser : public TIntermTraverser -{ - public: - static void Apply(TIntermNode *root, TSymbolTable *symbolTable); - - private: - Traverser(TSymbolTable *symbolTable); - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - void nextIteration(); - - bool mFound = false; -}; - -// static -void Traverser::Apply(TIntermNode *root, TSymbolTable *symbolTable) -{ - Traverser traverser(symbolTable); - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.mFound) - { - traverser.updateTree(); - } - } while (traverser.mFound); -} - -Traverser::Traverser(TSymbolTable *symbolTable) : TIntermTraverser(true, false, false, symbolTable) -{ -} - -void Traverser::nextIteration() -{ - mFound = false; - nextTemporaryId(); -} - -bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (mFound) - { - return false; - } - - // Test 0: skip non-pow operators. - if (node->getOp() != EOpPow) - { - return true; - } - - const TIntermSequence *sequence = node->getSequence(); - ASSERT(sequence->size() == 2u); - const TIntermConstantUnion *constantNode = sequence->at(1)->getAsConstantUnion(); - - // Test 1: check for a single constant. - if (!constantNode || constantNode->getNominalSize() != 1) - { - return true; - } - - const TConstantUnion *constant = constantNode->getUnionArrayPointer(); - - TConstantUnion asFloat; - asFloat.cast(EbtFloat, *constant); - - float value = asFloat.getFConst(); - - // Test 2: value is in the problematic range. - if (value < -5.0f || value > 9.0f) - { - return true; - } - - // Test 3: value is integer or pretty close to an integer. - float absval = std::abs(value); - float frac = absval - std::round(absval); - if (frac > 0.0001f) - { - return true; - } - - // Test 4: skip -1, 0, and 1 - int exponent = static_cast<int>(value); - int n = std::abs(exponent); - if (n < 2) - { - return true; - } - - // Potential problem case detected, apply workaround. - nextTemporaryId(); - - TIntermTyped *lhs = sequence->at(0)->getAsTyped(); - ASSERT(lhs); - - TIntermDeclaration *init = createTempInitDeclaration(lhs); - TIntermTyped *current = createTempSymbol(lhs->getType()); - - insertStatementInParentBlock(init); - - // Create a chain of n-1 multiples. - for (int i = 1; i < n; ++i) - { - TIntermBinary *mul = new TIntermBinary(EOpMul, current, createTempSymbol(lhs->getType())); - mul->setLine(node->getLine()); - current = mul; - } - - // For negative pow, compute the reciprocal of the positive pow. - if (exponent < 0) - { - TConstantUnion *oneVal = new TConstantUnion(); - oneVal->setFConst(1.0f); - TIntermConstantUnion *oneNode = new TIntermConstantUnion(oneVal, node->getType()); - TIntermBinary *div = new TIntermBinary(EOpDiv, oneNode, current); - current = div; - } - - queueReplacement(current, OriginalNode::IS_DROPPED); - mFound = true; - return false; -} - -} // anonymous namespace - -void ExpandIntegerPowExpressions(TIntermNode *root, TSymbolTable *symbolTable) -{ - Traverser::Apply(root, symbolTable); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h b/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h deleted file mode 100644 index 0074e5d663..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This mutating tree traversal works around a bug in the HLSL compiler optimizer with "pow" that -// manifests under the following conditions: -// -// - If pow() has a literal exponent value -// - ... and this value is integer or within 10e-6 of an integer -// - ... and it is in {-4, -3, -2, 2, 3, 4, 5, 6, 7, 8} -// -// The workaround is to replace the pow with a series of multiplies. -// See http://anglebug.com/851 - -#ifndef COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_ -#define COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_ - -namespace sh -{ - -class TIntermNode; -class TSymbolTable; - -void ExpandIntegerPowExpressions(TIntermNode *root, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp deleted file mode 100644 index 3f910b9050..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ExtensionBehavior.cpp: Extension name enumeration and data structures for storing extension -// behavior. - -#include "compiler/translator/ExtensionBehavior.h" - -#include "common/debug.h" - -#include <string.h> - -#define LIST_EXTENSIONS(OP) \ - OP(ARB_texture_rectangle) \ - OP(ARM_shader_framebuffer_fetch) \ - OP(EXT_blend_func_extended) \ - OP(EXT_draw_buffers) \ - OP(EXT_frag_depth) \ - OP(EXT_geometry_shader) \ - OP(EXT_shader_framebuffer_fetch) \ - OP(EXT_shader_texture_lod) \ - OP(EXT_YUV_target) \ - OP(NV_EGL_stream_consumer_external) \ - OP(NV_shader_framebuffer_fetch) \ - OP(OES_EGL_image_external) \ - OP(OES_EGL_image_external_essl3) \ - OP(OES_geometry_shader) \ - OP(OES_standard_derivatives) \ - OP(OVR_multiview) - -namespace sh -{ - -#define RETURN_EXTENSION_NAME_CASE(ext) \ - case TExtension::ext: \ - return "GL_" #ext; - -const char *GetExtensionNameString(TExtension extension) -{ - switch (extension) - { - LIST_EXTENSIONS(RETURN_EXTENSION_NAME_CASE) - default: - UNREACHABLE(); - return ""; - } -} - -#define RETURN_EXTENSION_IF_NAME_MATCHES(ext) \ - if (strcmp(extWithoutGLPrefix, #ext) == 0) \ - { \ - return TExtension::ext; \ - } - -TExtension GetExtensionByName(const char *extension) -{ - // If first characters of the extension don't equal "GL_", early out. - if (strncmp(extension, "GL_", 3) != 0) - { - return TExtension::UNDEFINED; - } - const char *extWithoutGLPrefix = extension + 3; - - LIST_EXTENSIONS(RETURN_EXTENSION_IF_NAME_MATCHES) - - return TExtension::UNDEFINED; -} - -const char *GetBehaviorString(TBehavior b) -{ - switch (b) - { - case EBhRequire: - return "require"; - case EBhEnable: - return "enable"; - case EBhWarn: - return "warn"; - case EBhDisable: - return "disable"; - default: - return nullptr; - } -} - -bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, TExtension extension) -{ - ASSERT(extension != TExtension::UNDEFINED); - auto iter = extBehavior.find(extension); - return iter != extBehavior.end() && - (iter->second == EBhEnable || iter->second == EBhRequire || iter->second == EBhWarn); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h deleted file mode 100644 index 09cc03f10f..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ExtensionBehavior.h: Extension name enumeration and data structures for storing extension -// behavior. - -#ifndef COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ -#define COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ - -#include <map> - -namespace sh -{ - -enum class TExtension -{ - UNDEFINED, // Special value used to indicate no extension. - - ARB_texture_rectangle, - ARM_shader_framebuffer_fetch, - EXT_blend_func_extended, - EXT_draw_buffers, - EXT_frag_depth, - EXT_geometry_shader, - EXT_shader_framebuffer_fetch, - EXT_shader_texture_lod, - EXT_YUV_target, - NV_EGL_stream_consumer_external, - NV_shader_framebuffer_fetch, - OES_EGL_image_external, - OES_EGL_image_external_essl3, - OES_geometry_shader, - OES_standard_derivatives, - OVR_multiview -}; - -enum TBehavior -{ - EBhRequire, - EBhEnable, - EBhWarn, - EBhDisable, - EBhUndefined -}; - -const char *GetExtensionNameString(TExtension extension); -TExtension GetExtensionByName(const char *extension); - -const char *GetBehaviorString(TBehavior b); - -// Mapping between extension id and behavior. -typedef std::map<TExtension, TBehavior> TExtensionBehavior; - -bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, TExtension extension); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp deleted file mode 100644 index 5b5dc580e9..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ExtensionGLSL.cpp: Implements the TExtensionGLSL class that tracks GLSL extension requirements -// of shaders. - -#include "compiler/translator/ExtensionGLSL.h" - -#include "compiler/translator/VersionGLSL.h" - -namespace sh -{ - -TExtensionGLSL::TExtensionGLSL(ShShaderOutput output) - : TIntermTraverser(true, false, false), mTargetVersion(ShaderOutputTypeToGLSLVersion(output)) -{ -} - -const std::set<std::string> &TExtensionGLSL::getEnabledExtensions() const -{ - return mEnabledExtensions; -} - -const std::set<std::string> &TExtensionGLSL::getRequiredExtensions() const -{ - return mRequiredExtensions; -} - -bool TExtensionGLSL::visitUnary(Visit, TIntermUnary *node) -{ - checkOperator(node); - - return true; -} - -bool TExtensionGLSL::visitAggregate(Visit, TIntermAggregate *node) -{ - checkOperator(node); - - return true; -} - -void TExtensionGLSL::checkOperator(TIntermOperator *node) -{ - if (mTargetVersion < GLSL_VERSION_130) - { - return; - } - - switch (node->getOp()) - { - case EOpAbs: - break; - - case EOpSign: - break; - - case EOpMix: - break; - - case EOpFloatBitsToInt: - case EOpFloatBitsToUint: - case EOpIntBitsToFloat: - case EOpUintBitsToFloat: - if (mTargetVersion < GLSL_VERSION_330) - { - // Bit conversion functions cannot be emulated. - mRequiredExtensions.insert("GL_ARB_shader_bit_encoding"); - } - break; - - case EOpPackSnorm2x16: - case EOpPackHalf2x16: - case EOpUnpackSnorm2x16: - case EOpUnpackHalf2x16: - if (mTargetVersion < GLSL_VERSION_420) - { - mEnabledExtensions.insert("GL_ARB_shading_language_packing"); - - if (mTargetVersion < GLSL_VERSION_330) - { - // floatBitsToUint and uintBitsToFloat are needed to emulate - // packHalf2x16 and unpackHalf2x16 respectively and cannot be - // emulated themselves. - mRequiredExtensions.insert("GL_ARB_shader_bit_encoding"); - } - } - break; - - case EOpPackUnorm2x16: - case EOpUnpackUnorm2x16: - if (mTargetVersion < GLSL_VERSION_410) - { - mEnabledExtensions.insert("GL_ARB_shading_language_packing"); - } - break; - - default: - break; - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h b/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h deleted file mode 100644 index a1b9cb2225..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ExtensionGLSL.h: Defines the TExtensionGLSL class that tracks GLSL extension requirements of -// shaders. - -#ifndef COMPILER_TRANSLATOR_EXTENSIONGLSL_H_ -#define COMPILER_TRANSLATOR_EXTENSIONGLSL_H_ - -#include <set> -#include <string> - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -// Traverses the intermediate tree to determine which GLSL extensions are required -// to support the shader. -class TExtensionGLSL : public TIntermTraverser -{ - public: - TExtensionGLSL(ShShaderOutput output); - - const std::set<std::string> &getEnabledExtensions() const; - const std::set<std::string> &getRequiredExtensions() const; - - bool visitUnary(Visit visit, TIntermUnary *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - - private: - void checkOperator(TIntermOperator *node); - - int mTargetVersion; - - std::set<std::string> mEnabledExtensions; - std::set<std::string> mRequiredExtensions; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_EXTENSIONGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/FindMain.cpp b/src/3rdparty/angle/src/compiler/translator/FindMain.cpp deleted file mode 100644 index 7417fbac8a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/FindMain.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// FindMain.cpp: Find the main() function definition in a given AST. - -#include "compiler/translator/FindMain.h" - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -TIntermFunctionDefinition *FindMain(TIntermBlock *root) -{ - for (TIntermNode *node : *root->getSequence()) - { - TIntermFunctionDefinition *nodeFunction = node->getAsFunctionDefinition(); - if (nodeFunction != nullptr && nodeFunction->getFunctionSymbolInfo()->isMain()) - { - return nodeFunction; - } - } - return nullptr; -} - -TIntermBlock *FindMainBody(TIntermBlock *root) -{ - TIntermFunctionDefinition *main = FindMain(root); - ASSERT(main != nullptr); - TIntermBlock *mainBody = main->getBody(); - ASSERT(mainBody != nullptr); - return mainBody; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/FindMain.h b/src/3rdparty/angle/src/compiler/translator/FindMain.h deleted file mode 100644 index bf2c45d871..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/FindMain.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// FindMain.h: Adds functions to get the main function definition and its body. - -#ifndef COMPILER_TRANSLATOR_FINDMAIN_H_ -#define COMPILER_TRANSLATOR_FINDMAIN_H_ - -namespace sh -{ - -class TIntermBlock; -class TIntermFunctionDefinition; - -TIntermFunctionDefinition *FindMain(TIntermBlock *root); -TIntermBlock *FindMainBody(TIntermBlock *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_FINDMAIN_H_
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp b/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp deleted file mode 100644 index a2a10f128d..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// FindSymbol.cpp: -// Utility for finding a symbol node inside an AST tree. - -#include "compiler/translator/FindSymbolNode.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class SymbolFinder : public TIntermTraverser -{ - public: - SymbolFinder(const TString &symbolName, TBasicType basicType) - : TIntermTraverser(true, false, false), - mSymbolName(symbolName), - mNodeFound(nullptr), - mBasicType(basicType) - { - } - - void visitSymbol(TIntermSymbol *node) - { - if (node->getBasicType() == mBasicType && node->getSymbol() == mSymbolName) - { - mNodeFound = node; - } - } - - bool isFound() const { return mNodeFound != nullptr; } - const TIntermSymbol *getNode() const { return mNodeFound; } - - private: - TString mSymbolName; - TIntermSymbol *mNodeFound; - TBasicType mBasicType; -}; - -} // anonymous namespace - -const TIntermSymbol *FindSymbolNode(TIntermNode *root, - const TString &symbolName, - TBasicType basicType) -{ - SymbolFinder finder(symbolName, basicType); - root->traverse(&finder); - return finder.getNode(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h b/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h deleted file mode 100644 index 08dfb9a222..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// FindSymbolNode.h: -// Utility for finding a symbol node inside an AST tree. - -#ifndef COMPILER_TRANSLATOR_FIND_SYMBOL_H_ -#define COMPILER_TRANSLATOR_FIND_SYMBOL_H_ - -#include "compiler/translator/BaseTypes.h" -#include "compiler/translator/Common.h" - -namespace sh -{ - -class TIntermNode; -class TIntermSymbol; - -const TIntermSymbol *FindSymbolNode(TIntermNode *root, - const TString &symbolName, - TBasicType basicType); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_FIND_SYMBOL_H_
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp deleted file mode 100644 index fba837f55c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// FlagStd140Structs.cpp: Find structs in std140 blocks, where the padding added in the translator -// conflicts with the "natural" unpadded type. - -#include "compiler/translator/FlagStd140Structs.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class FlagStd140StructsTraverser : public TIntermTraverser -{ - public: - FlagStd140StructsTraverser() : TIntermTraverser(true, false, false) {} - - const std::vector<MappedStruct> getMappedStructs() const { return mMappedStructs; } - - protected: - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - - private: - void mapBlockStructMembers(TIntermSymbol *blockDeclarator, TInterfaceBlock *block); - - std::vector<MappedStruct> mMappedStructs; -}; - -void FlagStd140StructsTraverser::mapBlockStructMembers(TIntermSymbol *blockDeclarator, - TInterfaceBlock *block) -{ - for (auto *field : block->fields()) - { - if (field->type()->getBasicType() == EbtStruct) - { - MappedStruct mappedStruct; - mappedStruct.blockDeclarator = blockDeclarator; - mappedStruct.field = field; - mMappedStructs.push_back(mappedStruct); - } - } -} - -bool FlagStd140StructsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - TIntermTyped *declarator = node->getSequence()->back()->getAsTyped(); - if (declarator->getBasicType() == EbtInterfaceBlock) - { - TInterfaceBlock *block = declarator->getType().getInterfaceBlock(); - if (block->blockStorage() == EbsStd140) - { - mapBlockStructMembers(declarator->getAsSymbolNode(), block); - } - } - return false; -} - -} // anonymous namespace - -std::vector<MappedStruct> FlagStd140Structs(TIntermNode *node) -{ - FlagStd140StructsTraverser flaggingTraversal; - - node->traverse(&flaggingTraversal); - - return flaggingTraversal.getMappedStructs(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h deleted file mode 100644 index f548d8b6ed..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// FlagStd140Structs.h: Find structs in std140 blocks, where the padding added in the translator -// conflicts with the "natural" unpadded type. - -#ifndef COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ -#define COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ - -#include <vector> - -namespace sh -{ - -class TField; -class TIntermNode; -class TIntermSymbol; - -struct MappedStruct -{ - TIntermSymbol *blockDeclarator; - TField *field; -}; - -std::vector<MappedStruct> FlagStd140Structs(TIntermNode *node); -} - -#endif // COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.cpp b/src/3rdparty/angle/src/compiler/translator/HashNames.cpp deleted file mode 100644 index 6bc90faf94..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/HashNames.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/HashNames.h" - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -namespace -{ - -// GLSL ES 3.00.6 section 3.9: the maximum length of an identifier is 1024 characters. -static const unsigned int kESSLMaxIdentifierLength = 1024u; - -static const char *kHashedNamePrefix = "webgl_"; - -// Can't prefix with just _ because then we might introduce a double underscore, which is not safe -// in GLSL (ESSL 3.00.6 section 3.8: All identifiers containing a double underscore are reserved for -// use by the underlying implementation). u is short for user-defined. -static const char *kUnhashedNamePrefix = "_u"; -static const unsigned int kUnhashedNamePrefixLength = 2u; - -TString HashName(const TString &name, ShHashFunction64 hashFunction) -{ - ASSERT(!name.empty()); - ASSERT(hashFunction); - khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); - TStringStream stream; - stream << kHashedNamePrefix << std::hex << number; - TString hashedName = stream.str(); - return hashedName; -} - -} // anonymous namespace - -TString HashName(const TName &name, ShHashFunction64 hashFunction, NameMap *nameMap) -{ - if (name.getString().empty() || name.isInternal()) - { - return name.getString(); - } - if (hashFunction == nullptr) - { - if (name.getString().length() + kUnhashedNamePrefixLength > kESSLMaxIdentifierLength) - { - // If the identifier length is already close to the limit, we can't prefix it. This is - // not a problem since there are no builtins or ANGLE's internal variables that would - // have as long names and could conflict. - return name.getString(); - } - return kUnhashedNamePrefix + name.getString(); - } - if (nameMap) - { - NameMap::const_iterator it = nameMap->find(name.getString().c_str()); - if (it != nameMap->end()) - return it->second.c_str(); - } - TString hashedName = HashName(name.getString(), hashFunction); - if (nameMap) - { - (*nameMap)[name.getString().c_str()] = hashedName.c_str(); - } - return hashedName; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.h b/src/3rdparty/angle/src/compiler/translator/HashNames.h deleted file mode 100644 index 28e861b309..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/HashNames.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_HASHNAMES_H_ -#define COMPILER_TRANSLATOR_HASHNAMES_H_ - -#include <map> - -#include "GLSLANG/ShaderLang.h" -#include "compiler/translator/Common.h" - -namespace sh -{ - -typedef std::map<TPersistString, TPersistString> NameMap; - -class TName; - -// Hash user-defined name for GLSL output, with special handling for internal names. -// The nameMap parameter is optional and is used to cache hashed names if set. -TString HashName(const TName &name, ShHashFunction64 hashFunction, NameMap *nameMap); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_HASHNAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp deleted file mode 100644 index 40b5e1f1e2..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp +++ /dev/null @@ -1,304 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output. -// - -#include "compiler/translator/ImageFunctionHLSL.h" -#include "compiler/translator/UtilsHLSL.h" - -namespace sh -{ - -// static -void ImageFunctionHLSL::OutputImageFunctionArgumentList( - TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction) -{ - if (imageFunction.readonly) - { - out << TextureString(imageFunction.image, imageFunction.imageInternalFormat) << " tex"; - } - else - { - out << RWTextureString(imageFunction.image, imageFunction.imageInternalFormat) << " tex"; - } - - if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::LOAD || - imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE) - { - switch (imageFunction.image) - { - case EbtImage2D: - case EbtIImage2D: - case EbtUImage2D: - out << ", int2 p"; - break; - case EbtImage3D: - case EbtIImage3D: - case EbtUImage3D: - case EbtImageCube: - case EbtIImageCube: - case EbtUImageCube: - case EbtImage2DArray: - case EbtIImage2DArray: - case EbtUImage2DArray: - out << ", int3 p"; - break; - default: - UNREACHABLE(); - } - - if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE) - { - switch (imageFunction.image) - { - case EbtImage2D: - case EbtImage3D: - case EbtImageCube: - case EbtImage2DArray: - out << ", float4 data"; - break; - case EbtIImage2D: - case EbtIImage3D: - case EbtIImageCube: - case EbtIImage2DArray: - out << ", int4 data"; - break; - case EbtUImage2D: - case EbtUImage3D: - case EbtUImageCube: - case EbtUImage2DArray: - out << ", uint4 data"; - break; - default: - UNREACHABLE(); - } - } - } -} - -// static -void ImageFunctionHLSL::OutputImageSizeFunctionBody( - TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction, - const TString &imageReference) -{ - if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) || - IsImageCube(imageFunction.image)) - { - // "depth" stores either the number of layers in an array texture or 3D depth - out << " uint width; uint height; uint depth;\n" - << " " << imageReference << ".GetDimensions(width, height, depth);\n"; - } - else if (IsImage2D(imageFunction.image)) - { - out << " uint width; uint height;\n" - << " " << imageReference << ".GetDimensions(width, height);\n"; - } - else - UNREACHABLE(); - - if (strcmp(imageFunction.getReturnType(), "int3") == 0) - { - out << " return int3(width, height, depth);\n"; - } - else - { - out << " return int2(width, height);\n"; - } -} - -// static -void ImageFunctionHLSL::OutputImageLoadFunctionBody( - TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction, - const TString &imageReference) -{ - if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) || - IsImageCube(imageFunction.image)) - { - out << " return " << imageReference << "[uint3(p.x, p.y, p.z)];\n"; - } - else if (IsImage2D(imageFunction.image)) - { - out << " return " << imageReference << "[uint2(p.x, p.y)];\n"; - } - else - UNREACHABLE(); -} - -// static -void ImageFunctionHLSL::OutputImageStoreFunctionBody( - TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction, - const TString &imageReference) -{ - if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) || - IsImage2D(imageFunction.image) || IsImageCube(imageFunction.image)) - { - out << " " << imageReference << "[p] = data;\n"; - } - else - UNREACHABLE(); -} - -TString ImageFunctionHLSL::ImageFunction::name() const -{ - TString name = "gl_image"; - if (readonly) - { - name += TextureTypeSuffix(image, imageInternalFormat); - } - else - { - name += RWTextureTypeSuffix(image, imageInternalFormat); - } - - switch (method) - { - case Method::SIZE: - name += "Size"; - break; - case Method::LOAD: - name += "Load"; - break; - case Method::STORE: - name += "Store"; - break; - default: - UNREACHABLE(); - } - - return name; -} - -const char *ImageFunctionHLSL::ImageFunction::getReturnType() const -{ - if (method == ImageFunction::Method::SIZE) - { - switch (image) - { - case EbtImage2D: - case EbtIImage2D: - case EbtUImage2D: - case EbtImageCube: - case EbtIImageCube: - case EbtUImageCube: - return "int2"; - case EbtImage3D: - case EbtIImage3D: - case EbtUImage3D: - case EbtImage2DArray: - case EbtIImage2DArray: - case EbtUImage2DArray: - return "int3"; - default: - UNREACHABLE(); - } - } - else if (method == ImageFunction::Method::LOAD) - { - switch (image) - { - case EbtImage2D: - case EbtImage3D: - case EbtImageCube: - case EbtImage2DArray: - return "float4"; - case EbtIImage2D: - case EbtIImage3D: - case EbtIImageCube: - case EbtIImage2DArray: - return "int4"; - case EbtUImage2D: - case EbtUImage3D: - case EbtUImageCube: - case EbtUImage2DArray: - return "uint4"; - default: - UNREACHABLE(); - } - } - else if (method == ImageFunction::Method::STORE) - { - return "void"; - } - else - { - UNREACHABLE(); - } - return ""; -} - -bool ImageFunctionHLSL::ImageFunction::operator<(const ImageFunction &rhs) const -{ - return std::tie(image, imageInternalFormat, readonly, method) < - std::tie(rhs.image, rhs.imageInternalFormat, rhs.readonly, rhs.method); -} - -TString ImageFunctionHLSL::useImageFunction(const TString &name, - const TBasicType &type, - TLayoutImageInternalFormat imageInternalFormat, - bool readonly) -{ - ASSERT(IsImage(type)); - ImageFunction imageFunction; - imageFunction.image = type; - imageFunction.imageInternalFormat = imageInternalFormat; - imageFunction.readonly = readonly; - - if (name == "imageSize") - { - imageFunction.method = ImageFunction::Method::SIZE; - } - else if (name == "imageLoad") - { - imageFunction.method = ImageFunction::Method::LOAD; - } - else if (name == "imageStore") - { - imageFunction.method = ImageFunction::Method::STORE; - } - else - UNREACHABLE(); - - mUsesImage.insert(imageFunction); - return imageFunction.name(); -} - -void ImageFunctionHLSL::imageFunctionHeader(TInfoSinkBase &out) -{ - for (const ImageFunction &imageFunction : mUsesImage) - { - // Function header - out << imageFunction.getReturnType() << " " << imageFunction.name() << "("; - - OutputImageFunctionArgumentList(out, imageFunction); - - out << ")\n" - "{\n"; - - TString imageReference("tex"); - - if (imageFunction.method == ImageFunction::Method::SIZE) - { - OutputImageSizeFunctionBody(out, imageFunction, imageReference); - } - else if (imageFunction.method == ImageFunction::Method::LOAD) - { - OutputImageLoadFunctionBody(out, imageFunction, imageReference); - } - else - { - OutputImageStoreFunctionBody(out, imageFunction, imageReference); - } - - out << "}\n" - "\n"; - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h b/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h deleted file mode 100644 index 9db17a6bbf..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output. -// - -#ifndef COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_ -#define COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_ - -#include <set> - -#include "GLSLANG/ShaderLang.h" -#include "compiler/translator/BaseTypes.h" -#include "compiler/translator/Common.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/Types.h" - -namespace sh -{ - -class ImageFunctionHLSL final : angle::NonCopyable -{ - public: - // Returns the name of the image function implementation to caller. - // The name that's passed in is the name of the GLSL image function that it should implement. - TString useImageFunction(const TString &name, - const TBasicType &type, - TLayoutImageInternalFormat imageInternalFormat, - bool readonly); - - void imageFunctionHeader(TInfoSinkBase &out); - - private: - struct ImageFunction - { - // See ESSL 3.10.4 section 8.12 for reference about what the different methods below do. - enum class Method - { - SIZE, - LOAD, - STORE - }; - - TString name() const; - - bool operator<(const ImageFunction &rhs) const; - - const char *getReturnType() const; - - TBasicType image; - TLayoutImageInternalFormat imageInternalFormat; - bool readonly; - Method method; - }; - - static void OutputImageFunctionArgumentList( - TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction); - static void OutputImageSizeFunctionBody(TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction, - const TString &imageReference); - static void OutputImageLoadFunctionBody(TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction, - const TString &imageReference); - static void OutputImageStoreFunctionBody(TInfoSinkBase &out, - const ImageFunctionHLSL::ImageFunction &imageFunction, - const TString &imageReference); - using ImageFunctionSet = std::set<ImageFunction>; - ImageFunctionSet mUsesImage; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp b/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp deleted file mode 100644 index db26aa67e8..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/InfoSink.h" - -namespace sh -{ - -void TInfoSinkBase::prefix(Severity severity) -{ - switch (severity) - { - case SH_WARNING: - sink.append("WARNING: "); - break; - case SH_ERROR: - sink.append("ERROR: "); - break; - default: - sink.append("UNKOWN ERROR: "); - break; - } -} - -void TInfoSinkBase::location(int file, int line) -{ - TPersistStringStream stream; - if (line) - stream << file << ":" << line; - else - stream << file << ":? "; - stream << ": "; - - sink.append(stream.str()); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/InfoSink.h b/src/3rdparty/angle/src/compiler/translator/InfoSink.h deleted file mode 100644 index 2705f48d59..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/InfoSink.h +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_INFOSINK_H_ -#define COMPILER_TRANSLATOR_INFOSINK_H_ - -#include <math.h> -#include <stdlib.h> -#include "compiler/translator/Common.h" -#include "compiler/translator/Severity.h" - -namespace sh -{ - -// Returns the fractional part of the given floating-point number. -inline float fractionalPart(float f) -{ - float intPart = 0.0f; - return modff(f, &intPart); -} - -// -// Encapsulate info logs for all objects that have them. -// -// The methods are a general set of tools for getting a variety of -// messages and types inserted into the log. -// -class TInfoSinkBase -{ - public: - TInfoSinkBase() {} - - template <typename T> - TInfoSinkBase &operator<<(const T &t) - { - TPersistStringStream stream; - stream << t; - sink.append(stream.str()); - return *this; - } - // Override << operator for specific types. It is faster to append strings - // and characters directly to the sink. - TInfoSinkBase &operator<<(char c) - { - sink.append(1, c); - return *this; - } - TInfoSinkBase &operator<<(const char *str) - { - sink.append(str); - return *this; - } - TInfoSinkBase &operator<<(const TPersistString &str) - { - sink.append(str); - return *this; - } - TInfoSinkBase &operator<<(const TString &str) - { - sink.append(str.c_str()); - return *this; - } - // Make sure floats are written with correct precision. - TInfoSinkBase &operator<<(float f) - { - // Make sure that at least one decimal point is written. If a number - // does not have a fractional part, the default precision format does - // not write the decimal portion which gets interpreted as integer by - // the compiler. - TPersistStringStream stream; - if (fractionalPart(f) == 0.0f) - { - stream.precision(1); - stream << std::showpoint << std::fixed << f; - } - else - { - stream.unsetf(std::ios::fixed); - stream.unsetf(std::ios::scientific); - stream.precision(8); - stream << f; - } - sink.append(stream.str()); - return *this; - } - // Write boolean values as their names instead of integral value. - TInfoSinkBase &operator<<(bool b) - { - const char *str = b ? "true" : "false"; - sink.append(str); - return *this; - } - - void erase() { sink.clear(); } - int size() { return static_cast<int>(sink.size()); } - - const TPersistString &str() const { return sink; } - const char *c_str() const { return sink.c_str(); } - - void prefix(Severity severity); - void location(int file, int line); - - private: - TPersistString sink; -}; - -class TInfoSink -{ - public: - TInfoSinkBase info; - TInfoSinkBase debug; - TInfoSinkBase obj; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INFOSINK_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp deleted file mode 100644 index 6f8baee96b..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp +++ /dev/null @@ -1,1135 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// Create symbols that declare built-in definitions, add built-ins that -// cannot be expressed in the files, and establish mappings between -// built-in functions and operators. -// - -#include "compiler/translator/Initialize.h" -#include "compiler/translator/Cache.h" - -#include "compiler/translator/IntermNode.h" -#include "angle_gl.h" - -namespace sh -{ - -void InsertBuiltInFunctions(sh::GLenum type, - ShShaderSpec spec, - const ShBuiltInResources &resources, - TSymbolTable &symbolTable) -{ - const TType *voidType = TCache::getType(EbtVoid); - const TType *float1 = TCache::getType(EbtFloat); - const TType *float2 = TCache::getType(EbtFloat, 2); - const TType *float3 = TCache::getType(EbtFloat, 3); - const TType *float4 = TCache::getType(EbtFloat, 4); - const TType *int1 = TCache::getType(EbtInt); - const TType *int2 = TCache::getType(EbtInt, 2); - const TType *int3 = TCache::getType(EbtInt, 3); - const TType *uint1 = TCache::getType(EbtUInt); - const TType *bool1 = TCache::getType(EbtBool); - const TType *genType = TCache::getType(EbtGenType); - const TType *genIType = TCache::getType(EbtGenIType); - const TType *genUType = TCache::getType(EbtGenUType); - const TType *genBType = TCache::getType(EbtGenBType); - - // - // Angle and Trigonometric Functions. - // - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpRadians, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDegrees, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSin, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCos, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpTan, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAsin, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAcos, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAtan, genType, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAtan, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpSinh, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpCosh, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTanh, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAsinh, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAcosh, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAtanh, genType, genType); - - // - // Exponential Functions. - // - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpPow, genType, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpExp, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLog, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpExp2, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLog2, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSqrt, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpInverseSqrt, genType, genType); - - // - // Common Functions. - // - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAbs, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAbs, genIType, genIType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSign, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpSign, genIType, genIType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFloor, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTrunc, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpRound, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpRoundEven, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCeil, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFract, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMod, genType, genType, float1); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMod, genType, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMin, genType, genType, float1); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMin, genType, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genIType, genIType, genIType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genIType, genIType, int1); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genUType, genUType, genUType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genUType, genUType, uint1); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMax, genType, genType, float1); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMax, genType, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genIType, genIType, genIType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genIType, genIType, int1); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genUType, genUType, genUType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genUType, genUType, uint1); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpClamp, genType, genType, float1, float1); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpClamp, genType, genType, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genIType, genIType, int1, int1); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genIType, genIType, genIType, genIType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genUType, genUType, uint1, uint1); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genUType, genUType, genUType, genUType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMix, genType, genType, genType, float1); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMix, genType, genType, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMix, genType, genType, genType, genBType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpStep, genType, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpStep, genType, float1, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSmoothStep, genType, genType, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSmoothStep, genType, float1, float1, genType); - - const TType *outGenType = TCache::getType(EbtGenType, EvqOut); - const TType *outGenIType = TCache::getType(EbtGenIType, EvqOut); - - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpModf, genType, genType, outGenType); - - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIsNan, genBType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIsInf, genBType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFloatBitsToInt, genIType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFloatBitsToUint, genUType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIntBitsToFloat, genType, genIType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUintBitsToFloat, genType, genUType); - - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFrexp, genType, genType, outGenIType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpLdexp, genType, genType, genIType); - - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackSnorm2x16, uint1, float2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackUnorm2x16, uint1, float2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackHalf2x16, uint1, float2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackSnorm2x16, float2, uint1); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackUnorm2x16, float2, uint1); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackHalf2x16, float2, uint1); - - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpPackUnorm4x8, uint1, float4); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpPackSnorm4x8, uint1, float4); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUnpackUnorm4x8, float4, uint1); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUnpackSnorm4x8, float4, uint1); - - // - // Geometric Functions. - // - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLength, float1, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDistance, float1, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDot, float1, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCross, float3, float3, float3); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNormalize, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFaceforward, genType, genType, genType, - genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpReflect, genType, genType, genType); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpRefract, genType, genType, genType, float1); - - const TType *mat2 = TCache::getType(EbtFloat, 2, 2); - const TType *mat3 = TCache::getType(EbtFloat, 3, 3); - const TType *mat4 = TCache::getType(EbtFloat, 4, 4); - const TType *mat2x3 = TCache::getType(EbtFloat, 2, 3); - const TType *mat3x2 = TCache::getType(EbtFloat, 3, 2); - const TType *mat2x4 = TCache::getType(EbtFloat, 2, 4); - const TType *mat4x2 = TCache::getType(EbtFloat, 4, 2); - const TType *mat3x4 = TCache::getType(EbtFloat, 3, 4); - const TType *mat4x3 = TCache::getType(EbtFloat, 4, 3); - - // - // Matrix Functions. - // - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat2, mat2, mat2); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat3, mat3, mat3); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat4, mat4, mat4); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat2x3, mat2x3, mat2x3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat3x2, mat3x2, mat3x2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat2x4, mat2x4, mat2x4); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat4x2, mat4x2, mat4x2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat3x4, mat3x4, mat3x4); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat4x3, mat4x3, mat4x3); - - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2, float2, float2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3, float3, float3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4, float4, float4); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2x3, float3, float2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3x2, float2, float3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2x4, float4, float2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4x2, float2, float4); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3x4, float4, float3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4x3, float3, float4); - - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2, mat2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3, mat3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4, mat4); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2x3, mat3x2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3x2, mat2x3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2x4, mat4x2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4x2, mat2x4); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3x4, mat4x3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4x3, mat3x4); - - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat4); - - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat2, mat2); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat3, mat3); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat4, mat4); - - const TType *vec = TCache::getType(EbtVec); - const TType *ivec = TCache::getType(EbtIVec); - const TType *uvec = TCache::getType(EbtUVec); - const TType *bvec = TCache::getType(EbtBVec); - - // - // Vector relational functions. - // - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanComponentWise, bvec, vec, vec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanComponentWise, bvec, ivec, ivec); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpLessThanComponentWise, bvec, uvec, uvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanEqualComponentWise, bvec, vec, vec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanEqualComponentWise, bvec, ivec, ivec); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpLessThanEqualComponentWise, bvec, uvec, uvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanComponentWise, bvec, vec, vec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanComponentWise, bvec, ivec, ivec); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpGreaterThanComponentWise, bvec, uvec, uvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, vec, vec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, ivec, - ivec); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, uvec, uvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, vec, vec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, ivec, ivec); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpEqualComponentWise, bvec, uvec, uvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, bvec, bvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, vec, vec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, ivec, ivec); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpNotEqualComponentWise, bvec, uvec, uvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, bvec, bvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAny, bool1, bvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAll, bool1, bvec); - symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLogicalNotComponentWise, bvec, bvec); - - // - // Integer functions - // - const TType *outGenUType = TCache::getType(EbtGenUType, EvqOut); - - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldExtract, genIType, genIType, int1, - int1); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldExtract, genUType, genUType, int1, - int1); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldInsert, genIType, genIType, genIType, - int1, int1); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldInsert, genUType, genUType, genUType, - int1, int1); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldReverse, genIType, genIType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldReverse, genUType, genUType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitCount, genIType, genIType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitCount, genIType, genUType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindLSB, genIType, genIType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindLSB, genIType, genUType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindMSB, genIType, genIType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindMSB, genIType, genUType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUaddCarry, genUType, genUType, genUType, - outGenUType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUsubBorrow, genUType, genUType, genUType, - outGenUType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUmulExtended, voidType, genUType, genUType, - outGenUType, outGenUType); - symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpImulExtended, voidType, genIType, genIType, - outGenIType, outGenIType); - - const TType *sampler2D = TCache::getType(EbtSampler2D); - const TType *samplerCube = TCache::getType(EbtSamplerCube); - - // - // Texture Functions for GLSL ES 1.0 - // - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3); - - if (resources.OES_EGL_image_external || resources.NV_EGL_stream_consumer_external) - { - const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES); - - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", samplerExternalOES, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES, - float3); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES, - float4); - } - - if (resources.ARB_texture_rectangle) - { - const TType *sampler2DRect = TCache::getType(EbtSampler2DRect); - - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRect", sampler2DRect, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect, - float3); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect, - float4); - } - - if (resources.EXT_shader_texture_lod) - { - /* The *Grad* variants are new to both vertex and fragment shaders; the fragment - * shader specific pieces are added separately below. - */ - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "texture2DGradEXT", sampler2D, float2, float2, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "texture2DProjGradEXT", sampler2D, float3, float2, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "texture2DProjGradEXT", sampler2D, float4, float2, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "textureCubeGradEXT", samplerCube, float3, float3, float3); - } - - if (type == GL_FRAGMENT_SHADER) - { - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3, - float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4, - float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3, - float1); - - if (resources.OES_standard_derivatives) - { - symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpDFdx, - TExtension::OES_standard_derivatives, genType, genType); - symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpDFdy, - TExtension::OES_standard_derivatives, genType, genType); - symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpFwidth, - TExtension::OES_standard_derivatives, genType, genType); - } - - if (resources.EXT_shader_texture_lod) - { - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "texture2DLodEXT", sampler2D, float2, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "texture2DProjLodEXT", sampler2D, float3, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "texture2DProjLodEXT", sampler2D, float4, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4, - "textureCubeLodEXT", samplerCube, float3, float1); - } - } - - if (type == GL_VERTEX_SHADER) - { - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLod", sampler2D, float2, - float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float3, - float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float4, - float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeLod", samplerCube, float3, - float1); - } - - const TType *gvec4 = TCache::getType(EbtGVec4); - - const TType *gsampler2D = TCache::getType(EbtGSampler2D); - const TType *gsamplerCube = TCache::getType(EbtGSamplerCube); - const TType *gsampler3D = TCache::getType(EbtGSampler3D); - const TType *gsampler2DArray = TCache::getType(EbtGSampler2DArray); - const TType *gsampler2DMS = TCache::getType(EbtGSampler2DMS); - - // - // Texture Functions for GLSL ES 3.0 - // - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2D, float2, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler3D, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsamplerCube, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2DArray, float3, float1); - - if (resources.OES_EGL_image_external_essl3) - { - const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texture", samplerExternalOES, float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES, - float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES, - float4); - } - - if (resources.EXT_YUV_target) - { - const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texture", - samplerExternal2DY2YEXT, float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "textureProj", - samplerExternal2DY2YEXT, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "textureProj", - samplerExternal2DY2YEXT, float4); - - const TType *yuvCscStandardEXT = TCache::getType(EbtYuvCscStandardEXT); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float3, "rgb_2_yuv", - float3, yuvCscStandardEXT); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float3, "yuv_2_rgb", - float3, yuvCscStandardEXT); - } - - if (type == GL_FRAGMENT_SHADER) - { - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3, - float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4, float1); - - if (resources.OES_EGL_image_external_essl3) - { - const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texture", samplerExternalOES, float2, - float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES, - float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES, - float4, float1); - } - - if (resources.EXT_YUV_target) - { - const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texture", - samplerExternal2DY2YEXT, float2, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, - "textureProj", samplerExternal2DY2YEXT, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, - "textureProj", samplerExternal2DY2YEXT, float4, float1); - } - } - - const TType *sampler2DShadow = TCache::getType(EbtSampler2DShadow); - const TType *samplerCubeShadow = TCache::getType(EbtSamplerCubeShadow); - const TType *sampler2DArrayShadow = TCache::getType(EbtSampler2DArrayShadow); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DArrayShadow, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProj", sampler2DShadow, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLod", sampler2DShadow, float3, - float1); - - if (type == GL_FRAGMENT_SHADER) - { - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3, - float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4, - float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProj", sampler2DShadow, float4, - float1); - } - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsampler2D, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", gsampler3D, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsamplerCube, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", gsampler2DArray, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", sampler2DShadow, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerCubeShadow, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", sampler2DArrayShadow, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsampler2DMS); - - if (resources.OES_EGL_image_external_essl3) - { - const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerExternalOES, int1); - } - - if (resources.EXT_YUV_target) - { - const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, int2, "textureSize", - samplerExternal2DY2YEXT, int1); - } - - if (type == GL_FRAGMENT_SHADER) - { - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDFdx, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDFdy, genType, genType); - symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFwidth, genType, genType); - } - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3, - int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3, - int2); - - if (type == GL_FRAGMENT_SHADER) - { - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2, - float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3, - float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3, - int2, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3, - int2, float1); - } - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, int3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, float4, - int2); - - if (type == GL_FRAGMENT_SHADER) - { - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, - int2, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, - int2, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, - int3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, - float4, int2, float1); - } - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler2D, float2, float1, - int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler3D, float3, float1, - int3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLodOffset", sampler2DShadow, float3, - float1, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler2DArray, float3, - float1, int2); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler2D, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler2D, float4, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler3D, float4, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjLod", sampler2DShadow, float4, - float1); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler2D, float3, - float1, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler2D, float4, - float1, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler3D, float4, - float1, int3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjLodOffset", sampler2DShadow, - float4, float1, int2); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler2D, int2, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler3D, int3, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler2DArray, int3, int1); - - if (resources.OES_EGL_image_external_essl3) - { - const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texelFetch", samplerExternalOES, int2, - int1); - } - - if (resources.EXT_YUV_target) - { - const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texelFetch", - samplerExternal2DY2YEXT, int2, int1); - } - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2D, int2, int1, - int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler3D, int3, int1, - int3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2DArray, int3, - int1, int2); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler2D, float2, float2, - float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler3D, float3, float3, - float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsamplerCube, float3, float3, - float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", sampler2DShadow, float3, - float2, float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", samplerCubeShadow, float4, - float3, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler2DArray, float3, float2, - float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", sampler2DArrayShadow, float4, - float2, float2); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler2D, float2, - float2, float2, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler3D, float3, - float3, float3, int3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGradOffset", sampler2DShadow, float3, - float2, float2, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler2DArray, float3, - float2, float2, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGradOffset", sampler2DArrayShadow, - float4, float2, float2, int2); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler2D, float3, float2, - float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler2D, float4, float2, - float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler3D, float4, float3, - float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGrad", sampler2DShadow, float4, - float2, float2); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler2D, float3, - float2, float2, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler2D, float4, - float2, float2, int2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler3D, float4, - float3, float3, int3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGradOffset", sampler2DShadow, - float4, float2, float2, int2); - - const TType *atomicCounter = TCache::getType(EbtAtomicCounter); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounter", atomicCounter); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounterIncrement", atomicCounter); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounterDecrement", atomicCounter); - - // Insert all atomic memory functions - const TType *int1InOut = TCache::getType(EbtInt, EvqInOut); - const TType *uint1InOut = TCache::getType(EbtUInt, EvqInOut); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicAdd", uint1InOut, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicAdd", int1InOut, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicMin", uint1InOut, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicMin", int1InOut, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicMax", uint1InOut, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicMax", int1InOut, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicAnd", uint1InOut, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicAnd", int1InOut, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicOr", uint1InOut, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicOr", int1InOut, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicXor", uint1InOut, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicXor", int1InOut, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicExchange", uint1InOut, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicExchange", int1InOut, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCompSwap", uint1InOut, uint1, uint1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicCompSwap", int1InOut, int1, int1); - - const TType *gimage2D = TCache::getType(EbtGImage2D); - const TType *gimage3D = TCache::getType(EbtGImage3D); - const TType *gimage2DArray = TCache::getType(EbtGImage2DArray); - const TType *gimageCube = TCache::getType(EbtGImageCube); - - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage2D, int2, gvec4); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage3D, int3, gvec4); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage2DArray, int3, gvec4); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimageCube, int3, gvec4); - - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage2D, int2); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage3D, int3); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage2DArray, int3); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimageCube, int3); - - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int2, "imageSize", gimage2D); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage3D); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage2DArray); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int2, "imageSize", gimageCube); - - symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrier, voidType, - "memoryBarrier"); - symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierAtomicCounter, - voidType, "memoryBarrierAtomicCounter"); - symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierBuffer, - voidType, "memoryBarrierBuffer"); - symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierImage, voidType, - "memoryBarrierImage"); - - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "texelFetch", gsampler2DMS, int2, int1); - - // Insert all variations of textureGather. - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2D, float2); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2D, float2, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2DArray, float3); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2DArray, float3, - int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsamplerCube, float3); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsamplerCube, float3, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DShadow, float2); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DShadow, float2, - float1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DArrayShadow, - float3); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DArrayShadow, - float3, float1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", samplerCubeShadow, float3); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", samplerCubeShadow, float3, - float1); - - // Insert all variations of textureGatherOffset. - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2D, float2, - int2); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2D, float2, - int2, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2DArray, - float3, int2); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2DArray, - float3, int2, int1); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGatherOffset", sampler2DShadow, - float2, float1, int2); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGatherOffset", sampler2DArrayShadow, - float3, float1, int2); - - if (type == GL_COMPUTE_SHADER) - { - symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpBarrier, voidType, - "barrier"); - symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierShared, - voidType, "memoryBarrierShared"); - symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpGroupMemoryBarrier, - voidType, "groupMemoryBarrier"); - } - - if (type == GL_GEOMETRY_SHADER_OES) - { - TExtension extension = TExtension::OES_geometry_shader; - symbolTable.insertBuiltInFunctionNoParametersExt(ESSL3_1_BUILTINS, extension, EOpEmitVertex, - voidType, "EmitVertex"); - symbolTable.insertBuiltInFunctionNoParametersExt(ESSL3_1_BUILTINS, extension, - EOpEndPrimitive, voidType, "EndPrimitive"); - } - - // - // Depth range in window coordinates - // - TFieldList *fields = NewPoolTFieldList(); - TSourceLoc zeroSourceLoc = {0, 0, 0, 0}; - auto highpFloat1 = new TType(EbtFloat, EbpHigh, EvqGlobal, 1); - TField *near = new TField(highpFloat1, NewPoolTString("near"), zeroSourceLoc); - TField *far = new TField(highpFloat1, NewPoolTString("far"), zeroSourceLoc); - TField *diff = new TField(highpFloat1, NewPoolTString("diff"), zeroSourceLoc); - fields->push_back(near); - fields->push_back(far); - fields->push_back(diff); - TStructure *depthRangeStruct = - new TStructure(&symbolTable, NewPoolTString("gl_DepthRangeParameters"), fields); - symbolTable.insertStructType(COMMON_BUILTINS, depthRangeStruct); - TType depthRangeType(depthRangeStruct); - depthRangeType.setQualifier(EvqUniform); - symbolTable.insertVariable(COMMON_BUILTINS, "gl_DepthRange", depthRangeType); - - // - // Implementation dependent built-in constants. - // - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexAttribs", resources.MaxVertexAttribs, - EbpMedium); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexUniformVectors", - resources.MaxVertexUniformVectors, EbpMedium); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexTextureImageUnits", - resources.MaxVertexTextureImageUnits, EbpMedium); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxCombinedTextureImageUnits", - resources.MaxCombinedTextureImageUnits, EbpMedium); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxTextureImageUnits", - resources.MaxTextureImageUnits, EbpMedium); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxFragmentUniformVectors", - resources.MaxFragmentUniformVectors, EbpMedium); - - symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxVaryingVectors", resources.MaxVaryingVectors, - EbpMedium); - - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers, - EbpMedium); - if (resources.EXT_blend_func_extended) - { - symbolTable.insertConstIntExt(COMMON_BUILTINS, TExtension::EXT_blend_func_extended, - "gl_MaxDualSourceDrawBuffersEXT", - resources.MaxDualSourceDrawBuffers, EbpMedium); - } - - symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors", - resources.MaxVertexOutputVectors, EbpMedium); - symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxFragmentInputVectors", - resources.MaxFragmentInputVectors, EbpMedium); - symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MinProgramTexelOffset", - resources.MinProgramTexelOffset, EbpMedium); - symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxProgramTexelOffset", - resources.MaxProgramTexelOffset, EbpMedium); - - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxImageUnits", resources.MaxImageUnits, - EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexImageUniforms", - resources.MaxVertexImageUniforms, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentImageUniforms", - resources.MaxFragmentImageUniforms, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeImageUniforms", - resources.MaxComputeImageUniforms, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedImageUniforms", - resources.MaxCombinedImageUniforms, EbpMedium); - - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedShaderOutputResources", - resources.MaxCombinedShaderOutputResources, EbpMedium); - - symbolTable.insertConstIvec3(ESSL3_1_BUILTINS, "gl_MaxComputeWorkGroupCount", - resources.MaxComputeWorkGroupCount, EbpHigh); - symbolTable.insertConstIvec3(ESSL3_1_BUILTINS, "gl_MaxComputeWorkGroupSize", - resources.MaxComputeWorkGroupSize, EbpHigh); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeUniformComponents", - resources.MaxComputeUniformComponents, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeTextureImageUnits", - resources.MaxComputeTextureImageUnits, EbpMedium); - - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeAtomicCounters", - resources.MaxComputeAtomicCounters, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeAtomicCounterBuffers", - resources.MaxComputeAtomicCounterBuffers, EbpMedium); - - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexAtomicCounters", - resources.MaxVertexAtomicCounters, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentAtomicCounters", - resources.MaxFragmentAtomicCounters, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedAtomicCounters", - resources.MaxCombinedAtomicCounters, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxAtomicCounterBindings", - resources.MaxAtomicCounterBindings, EbpMedium); - - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexAtomicCounterBuffers", - resources.MaxVertexAtomicCounterBuffers, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentAtomicCounterBuffers", - resources.MaxFragmentAtomicCounterBuffers, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedAtomicCounterBuffers", - resources.MaxCombinedAtomicCounterBuffers, EbpMedium); - symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxAtomicCounterBufferSize", - resources.MaxAtomicCounterBufferSize, EbpMedium); - - if (resources.OES_geometry_shader) - { - TExtension ext = TExtension::OES_geometry_shader; - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryInputComponents", - resources.MaxGeometryInputComponents, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryOutputComponents", - resources.MaxGeometryOutputComponents, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryImageUniforms", - resources.MaxGeometryImageUniforms, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryTextureImageUnits", - resources.MaxGeometryTextureImageUnits, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryOutputVertices", - resources.MaxGeometryOutputVertices, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryTotalOutputComponents", - resources.MaxGeometryTotalOutputComponents, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryUniformComponents", - resources.MaxGeometryUniformComponents, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryAtomicCounters", - resources.MaxGeometryAtomicCounters, EbpMedium); - symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryAtomicCounterBuffers", - resources.MaxGeometryAtomicCounterBuffers, EbpMedium); - } -} - -void IdentifyBuiltIns(sh::GLenum type, - ShShaderSpec spec, - const ShBuiltInResources &resources, - TSymbolTable &symbolTable) -{ - // - // Insert some special built-in variables that are not in - // the built-in header files. - // - - if (resources.OVR_multiview && type != GL_COMPUTE_SHADER) - { - symbolTable.insertVariableExt(ESSL3_BUILTINS, TExtension::OVR_multiview, "gl_ViewID_OVR", - TType(EbtUInt, EbpHigh, EvqViewIDOVR, 1)); - - // ESSL 1.00 doesn't have unsigned integers, so gl_ViewID_OVR is a signed integer in ESSL - // 1.00. This is specified in the WEBGL_multiview spec. - symbolTable.insertVariableExt(ESSL1_BUILTINS, TExtension::OVR_multiview, "gl_ViewID_OVR", - TType(EbtInt, EbpHigh, EvqViewIDOVR, 1)); - } - - switch (type) - { - case GL_FRAGMENT_SHADER: - { - symbolTable.insertVariable(COMMON_BUILTINS, "gl_FragCoord", - TType(EbtFloat, EbpMedium, EvqFragCoord, 4)); - symbolTable.insertVariable(COMMON_BUILTINS, "gl_FrontFacing", - TType(EbtBool, EbpUndefined, EvqFrontFacing, 1)); - symbolTable.insertVariable(COMMON_BUILTINS, "gl_PointCoord", - TType(EbtFloat, EbpMedium, EvqPointCoord, 2)); - - symbolTable.insertVariable(ESSL1_BUILTINS, "gl_FragColor", - TType(EbtFloat, EbpMedium, EvqFragColor, 4)); - TType fragData(EbtFloat, EbpMedium, EvqFragData, 4); - if (spec != SH_WEBGL2_SPEC && spec != SH_WEBGL3_SPEC) - { - fragData.makeArray(resources.MaxDrawBuffers); - } - else - { - fragData.makeArray(1u); - } - symbolTable.insertVariable(ESSL1_BUILTINS, "gl_FragData", fragData); - - if (resources.EXT_blend_func_extended) - { - symbolTable.insertVariableExt( - ESSL1_BUILTINS, TExtension::EXT_blend_func_extended, "gl_SecondaryFragColorEXT", - TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4)); - TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1); - secondaryFragData.makeArray(resources.MaxDualSourceDrawBuffers); - symbolTable.insertVariableExt(ESSL1_BUILTINS, TExtension::EXT_blend_func_extended, - "gl_SecondaryFragDataEXT", secondaryFragData); - } - - if (resources.EXT_frag_depth) - { - symbolTable.insertVariableExt( - ESSL1_BUILTINS, TExtension::EXT_frag_depth, "gl_FragDepthEXT", - TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, - EvqFragDepthEXT, 1)); - } - - symbolTable.insertVariable(ESSL3_BUILTINS, "gl_FragDepth", - TType(EbtFloat, EbpHigh, EvqFragDepth, 1)); - - if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch) - { - TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1); - lastFragData.makeArray(resources.MaxDrawBuffers); - - if (resources.EXT_shader_framebuffer_fetch) - { - symbolTable.insertVariableExt(ESSL1_BUILTINS, - TExtension::EXT_shader_framebuffer_fetch, - "gl_LastFragData", lastFragData); - } - else if (resources.NV_shader_framebuffer_fetch) - { - symbolTable.insertVariableExt( - ESSL1_BUILTINS, TExtension::NV_shader_framebuffer_fetch, "gl_LastFragColor", - TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)); - symbolTable.insertVariableExt(ESSL1_BUILTINS, - TExtension::NV_shader_framebuffer_fetch, - "gl_LastFragData", lastFragData); - } - } - else if (resources.ARM_shader_framebuffer_fetch) - { - symbolTable.insertVariableExt( - ESSL1_BUILTINS, TExtension::ARM_shader_framebuffer_fetch, "gl_LastFragColorARM", - TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)); - } - - if (resources.OES_geometry_shader) - { - TExtension extension = TExtension::OES_geometry_shader; - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveID", - TType(EbtInt, EbpHigh, EvqPrimitiveID, 1)); - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Layer", - TType(EbtInt, EbpHigh, EvqLayer, 1)); - } - - break; - } - case GL_VERTEX_SHADER: - { - symbolTable.insertVariable(COMMON_BUILTINS, "gl_Position", - TType(EbtFloat, EbpHigh, EvqPosition, 4)); - symbolTable.insertVariable(COMMON_BUILTINS, "gl_PointSize", - TType(EbtFloat, EbpMedium, EvqPointSize, 1)); - symbolTable.insertVariable(ESSL3_BUILTINS, "gl_InstanceID", - TType(EbtInt, EbpHigh, EvqInstanceID, 1)); - symbolTable.insertVariable(ESSL3_BUILTINS, "gl_VertexID", - TType(EbtInt, EbpHigh, EvqVertexID, 1)); - - // For internal use by ANGLE - not exposed to the parser. - symbolTable.insertVariable(GLSL_BUILTINS, "gl_ViewportIndex", - TType(EbtInt, EbpHigh, EvqViewportIndex)); - // gl_Layer exists in other shader stages in ESSL, but not in vertex shader so far. - symbolTable.insertVariable(GLSL_BUILTINS, "gl_Layer", TType(EbtInt, EbpHigh, EvqLayer)); - break; - } - case GL_COMPUTE_SHADER: - { - symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_NumWorkGroups", - TType(EbtUInt, EbpUndefined, EvqNumWorkGroups, 3)); - symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_WorkGroupSize", - TType(EbtUInt, EbpUndefined, EvqWorkGroupSize, 3)); - symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_WorkGroupID", - TType(EbtUInt, EbpUndefined, EvqWorkGroupID, 3)); - symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_LocalInvocationID", - TType(EbtUInt, EbpUndefined, EvqLocalInvocationID, 3)); - symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_GlobalInvocationID", - TType(EbtUInt, EbpUndefined, EvqGlobalInvocationID, 3)); - symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_LocalInvocationIndex", - TType(EbtUInt, EbpUndefined, EvqLocalInvocationIndex, 1)); - break; - } - - case GL_GEOMETRY_SHADER_OES: - { - TExtension extension = TExtension::OES_geometry_shader; - - // Add built-in interface block gl_PerVertex and the built-in array gl_in. - // TODO(jiawei.shao@intel.com): implement GL_OES_geometry_point_size. - const TString *glPerVertexString = NewPoolTString("gl_PerVertex"); - symbolTable.insertInterfaceBlockNameExt(ESSL3_1_BUILTINS, extension, glPerVertexString); - - TFieldList *fieldList = NewPoolTFieldList(); - TSourceLoc zeroSourceLoc = {0, 0, 0, 0}; - TField *glPositionField = new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4), - NewPoolTString("gl_Position"), zeroSourceLoc); - fieldList->push_back(glPositionField); - - TInterfaceBlock *glInBlock = new TInterfaceBlock( - glPerVertexString, fieldList, NewPoolTString("gl_in"), TLayoutQualifier::Create()); - - // The array size of gl_in is undefined until we get a valid input primitive - // declaration. - TType glInType(glInBlock, EvqPerVertexIn, TLayoutQualifier::Create()); - glInType.makeArray(0u); - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_in", glInType); - - TType glPositionType(EbtFloat, EbpHigh, EvqPosition, 4); - glPositionType.setInterfaceBlock(new TInterfaceBlock( - glPerVertexString, fieldList, nullptr, TLayoutQualifier::Create())); - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Position", - glPositionType); - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveIDIn", - TType(EbtInt, EbpHigh, EvqPrimitiveIDIn, 1)); - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_InvocationID", - TType(EbtInt, EbpHigh, EvqInvocationID, 1)); - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveID", - TType(EbtInt, EbpHigh, EvqPrimitiveID, 1)); - symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Layer", - TType(EbtInt, EbpHigh, EvqLayer, 1)); - - break; - } - default: - UNREACHABLE(); - } -} - -void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavior &extBehavior) -{ - if (resources.OES_standard_derivatives) - { - extBehavior[TExtension::OES_standard_derivatives] = EBhUndefined; - } - if (resources.OES_EGL_image_external) - { - extBehavior[TExtension::OES_EGL_image_external] = EBhUndefined; - } - if (resources.OES_EGL_image_external_essl3) - { - extBehavior[TExtension::OES_EGL_image_external_essl3] = EBhUndefined; - } - if (resources.NV_EGL_stream_consumer_external) - { - extBehavior[TExtension::NV_EGL_stream_consumer_external] = EBhUndefined; - } - if (resources.ARB_texture_rectangle) - { - // Special: ARB_texture_rectangle extension does not follow the standard for #extension - // directives - it is enabled by default. An extension directive may still disable it. - extBehavior[TExtension::ARB_texture_rectangle] = EBhEnable; - } - if (resources.EXT_blend_func_extended) - { - extBehavior[TExtension::EXT_blend_func_extended] = EBhUndefined; - } - if (resources.EXT_draw_buffers) - { - extBehavior[TExtension::EXT_draw_buffers] = EBhUndefined; - } - if (resources.EXT_frag_depth) - { - extBehavior[TExtension::EXT_frag_depth] = EBhUndefined; - } - if (resources.EXT_shader_texture_lod) - { - extBehavior[TExtension::EXT_shader_texture_lod] = EBhUndefined; - } - if (resources.EXT_shader_framebuffer_fetch) - { - extBehavior[TExtension::EXT_shader_framebuffer_fetch] = EBhUndefined; - } - if (resources.NV_shader_framebuffer_fetch) - { - extBehavior[TExtension::NV_shader_framebuffer_fetch] = EBhUndefined; - } - if (resources.ARM_shader_framebuffer_fetch) - { - extBehavior[TExtension::ARM_shader_framebuffer_fetch] = EBhUndefined; - } - if (resources.OVR_multiview) - { - extBehavior[TExtension::OVR_multiview] = EBhUndefined; - } - if (resources.EXT_YUV_target) - { - extBehavior[TExtension::EXT_YUV_target] = EBhUndefined; - } - if (resources.OES_geometry_shader) - { - extBehavior[TExtension::OES_geometry_shader] = EBhUndefined; - extBehavior[TExtension::EXT_geometry_shader] = EBhUndefined; - } -} - -void ResetExtensionBehavior(TExtensionBehavior &extBehavior) -{ - for (auto &ext : extBehavior) - { - if (ext.first == TExtension::ARB_texture_rectangle) - { - ext.second = EBhEnable; - } - else - { - ext.second = EBhUndefined; - } - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.h b/src/3rdparty/angle/src/compiler/translator/Initialize.h deleted file mode 100644 index 2e61218a0f..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Initialize.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_INITIALIZE_H_ -#define COMPILER_TRANSLATOR_INITIALIZE_H_ - -#include "compiler/translator/Common.h" -#include "compiler/translator/Compiler.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -void InsertBuiltInFunctions(sh::GLenum type, - ShShaderSpec spec, - const ShBuiltInResources &resources, - TSymbolTable &table); - -void IdentifyBuiltIns(sh::GLenum type, - ShShaderSpec spec, - const ShBuiltInResources &resources, - TSymbolTable &symbolTable); - -void InitExtensionBehavior(const ShBuiltInResources &resources, - TExtensionBehavior &extensionBehavior); - -// Resets the behavior of the extensions listed in |extensionBehavior| to the -// undefined state. These extensions will only be those initially supported in -// the ShBuiltInResources object for this compiler instance. All other -// extensions will remain unsupported. -void ResetExtensionBehavior(TExtensionBehavior &extensionBehavior); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INITIALIZE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp deleted file mode 100644 index 43c215f52b..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/Cache.h" -#include "compiler/translator/InitializeDll.h" -#include "compiler/translator/InitializeGlobals.h" - -#include "common/platform.h" - -#include <assert.h> - -namespace sh -{ - -bool InitProcess() -{ - if (!InitializePoolIndex()) - { - assert(0 && "InitProcess(): Failed to initalize global pool"); - return false; - } - - TCache::initialize(); - - return true; -} - -void DetachProcess() -{ - FreePoolIndex(); - TCache::destroy(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h b/src/3rdparty/angle/src/compiler/translator/InitializeDll.h deleted file mode 100644 index 87f7251470..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -#ifndef COMPILER_TRANSLATOR_INITIALIZEDLL_H_ -#define COMPILER_TRANSLATOR_INITIALIZEDLL_H_ - -namespace sh -{ -bool InitProcess(); -void DetachProcess(); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INITIALIZEDLL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h b/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h deleted file mode 100644 index 9a67ed0e04..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ -#define COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ - -bool InitializePoolIndex(); -void FreePoolIndex(); - -#endif // COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp deleted file mode 100644 index aa1a042fac..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp +++ /dev/null @@ -1,290 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/InitializeVariables.h" - -#include "angle_gl.h" -#include "common/debug.h" -#include "compiler/translator/FindMain.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -void AddArrayZeroInitSequence(const TIntermTyped *initializedNode, - bool canUseLoopsToInitialize, - TIntermSequence *initSequenceOut, - TSymbolTable *symbolTable); - -void AddStructZeroInitSequence(const TIntermTyped *initializedNode, - bool canUseLoopsToInitialize, - TIntermSequence *initSequenceOut, - TSymbolTable *symbolTable); - -TIntermBinary *CreateZeroInitAssignment(const TIntermTyped *initializedNode) -{ - TIntermTyped *zero = CreateZeroNode(initializedNode->getType()); - return new TIntermBinary(EOpAssign, initializedNode->deepCopy(), zero); -} - -void AddZeroInitSequence(const TIntermTyped *initializedNode, - bool canUseLoopsToInitialize, - TIntermSequence *initSequenceOut, - TSymbolTable *symbolTable) -{ - if (initializedNode->isArray()) - { - AddArrayZeroInitSequence(initializedNode, canUseLoopsToInitialize, initSequenceOut, - symbolTable); - } - else if (initializedNode->getType().isStructureContainingArrays() || - initializedNode->getType().isNamelessStruct()) - { - AddStructZeroInitSequence(initializedNode, canUseLoopsToInitialize, initSequenceOut, - symbolTable); - } - else - { - initSequenceOut->push_back(CreateZeroInitAssignment(initializedNode)); - } -} - -void AddStructZeroInitSequence(const TIntermTyped *initializedNode, - bool canUseLoopsToInitialize, - TIntermSequence *initSequenceOut, - TSymbolTable *symbolTable) -{ - ASSERT(initializedNode->getBasicType() == EbtStruct); - const TStructure *structType = initializedNode->getType().getStruct(); - for (int i = 0; i < static_cast<int>(structType->fields().size()); ++i) - { - TIntermBinary *element = new TIntermBinary(EOpIndexDirectStruct, - initializedNode->deepCopy(), CreateIndexNode(i)); - // Structs can't be defined inside structs, so the type of a struct field can't be a - // nameless struct. - ASSERT(!element->getType().isNamelessStruct()); - AddZeroInitSequence(element, canUseLoopsToInitialize, initSequenceOut, symbolTable); - } -} - -void AddArrayZeroInitStatementList(const TIntermTyped *initializedNode, - bool canUseLoopsToInitialize, - TIntermSequence *initSequenceOut, - TSymbolTable *symbolTable) -{ - for (unsigned int i = 0; i < initializedNode->getOutermostArraySize(); ++i) - { - TIntermBinary *element = - new TIntermBinary(EOpIndexDirect, initializedNode->deepCopy(), CreateIndexNode(i)); - AddZeroInitSequence(element, canUseLoopsToInitialize, initSequenceOut, symbolTable); - } -} - -void AddArrayZeroInitForLoop(const TIntermTyped *initializedNode, - TIntermSequence *initSequenceOut, - TSymbolTable *symbolTable) -{ - ASSERT(initializedNode->isArray()); - TSymbolUniqueId indexSymbol(symbolTable); - - TIntermSymbol *indexSymbolNode = CreateTempSymbolNode(indexSymbol, TType(EbtInt), EvqTemporary); - TIntermDeclaration *indexInit = - CreateTempInitDeclarationNode(indexSymbol, CreateZeroNode(TType(EbtInt)), EvqTemporary); - TIntermConstantUnion *arraySizeNode = CreateIndexNode(initializedNode->getOutermostArraySize()); - TIntermBinary *indexSmallerThanSize = - new TIntermBinary(EOpLessThan, indexSymbolNode->deepCopy(), arraySizeNode); - TIntermUnary *indexIncrement = new TIntermUnary(EOpPreIncrement, indexSymbolNode->deepCopy()); - - TIntermBlock *forLoopBody = new TIntermBlock(); - TIntermSequence *forLoopBodySeq = forLoopBody->getSequence(); - - TIntermBinary *element = new TIntermBinary(EOpIndexIndirect, initializedNode->deepCopy(), - indexSymbolNode->deepCopy()); - AddZeroInitSequence(element, true, forLoopBodySeq, symbolTable); - - TIntermLoop *forLoop = - new TIntermLoop(ELoopFor, indexInit, indexSmallerThanSize, indexIncrement, forLoopBody); - initSequenceOut->push_back(forLoop); -} - -void AddArrayZeroInitSequence(const TIntermTyped *initializedNode, - bool canUseLoopsToInitialize, - TIntermSequence *initSequenceOut, - TSymbolTable *symbolTable) -{ - // The array elements are assigned one by one to keep the AST compatible with ESSL 1.00 which - // doesn't have array assignment. We'll do this either with a for loop or just a list of - // statements assigning to each array index. Note that it is important to have the array init in - // the right order to workaround http://crbug.com/709317 - bool isSmallArray = initializedNode->getOutermostArraySize() <= 1u || - (initializedNode->getBasicType() != EbtStruct && - !initializedNode->getType().isArrayOfArrays() && - initializedNode->getOutermostArraySize() <= 3u); - if (initializedNode->getQualifier() == EvqFragData || - initializedNode->getQualifier() == EvqFragmentOut || isSmallArray || - !canUseLoopsToInitialize) - { - // Fragment outputs should not be indexed by non-constant indices. - // Also it doesn't make sense to use loops to initialize very small arrays. - AddArrayZeroInitStatementList(initializedNode, canUseLoopsToInitialize, initSequenceOut, - symbolTable); - } - else - { - AddArrayZeroInitForLoop(initializedNode, initSequenceOut, symbolTable); - } -} - -void InsertInitCode(TIntermSequence *mainBody, - const InitVariableList &variables, - TSymbolTable *symbolTable, - int shaderVersion, - const TExtensionBehavior &extensionBehavior, - bool canUseLoopsToInitialize) -{ - for (const auto &var : variables) - { - TString name = TString(var.name.c_str()); - size_t pos = name.find_last_of('['); - if (pos != TString::npos) - { - name = name.substr(0, pos); - } - - TIntermTyped *initializedSymbol = nullptr; - if (var.isBuiltIn()) - { - initializedSymbol = ReferenceBuiltInVariable(name, *symbolTable, shaderVersion); - if (initializedSymbol->getQualifier() == EvqFragData && - !IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers)) - { - // If GL_EXT_draw_buffers is disabled, only the 0th index of gl_FragData can be - // written to. - // TODO(oetuaho): This is a bit hacky and would be better to remove, if we came up - // with a good way to do it. Right now "gl_FragData" in symbol table is initialized - // to have the array size of MaxDrawBuffers, and the initialization happens before - // the shader sets the extensions it is using. - initializedSymbol = - new TIntermBinary(EOpIndexDirect, initializedSymbol, CreateIndexNode(0)); - } - } - else - { - initializedSymbol = ReferenceGlobalVariable(name, *symbolTable); - } - ASSERT(initializedSymbol != nullptr); - - TIntermSequence *initCode = - CreateInitCode(initializedSymbol, canUseLoopsToInitialize, symbolTable); - mainBody->insert(mainBody->begin(), initCode->begin(), initCode->end()); - } -} - -class InitializeLocalsTraverser : public TIntermTraverser -{ - public: - InitializeLocalsTraverser(int shaderVersion, - TSymbolTable *symbolTable, - bool canUseLoopsToInitialize) - : TIntermTraverser(true, false, false, symbolTable), - mShaderVersion(shaderVersion), - mCanUseLoopsToInitialize(canUseLoopsToInitialize) - { - } - - protected: - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override - { - for (TIntermNode *declarator : *node->getSequence()) - { - if (!mInGlobalScope && !declarator->getAsBinaryNode()) - { - TIntermSymbol *symbol = declarator->getAsSymbolNode(); - ASSERT(symbol); - if (symbol->getSymbol() == "") - { - continue; - } - - // Arrays may need to be initialized one element at a time, since ESSL 1.00 does not - // support array constructors or assigning arrays. - bool arrayConstructorUnavailable = - (symbol->isArray() || symbol->getType().isStructureContainingArrays()) && - mShaderVersion == 100; - // Nameless struct constructors can't be referred to, so they also need to be - // initialized one element at a time. - // TODO(oetuaho): Check if it makes sense to initialize using a loop, even if we - // could use an initializer. It could at least reduce code size for very large - // arrays, but could hurt runtime performance. - if (arrayConstructorUnavailable || symbol->getType().isNamelessStruct()) - { - // SimplifyLoopConditions should have been run so the parent node of this node - // should not be a loop. - ASSERT(getParentNode()->getAsLoopNode() == nullptr); - // SeparateDeclarations should have already been run, so we don't need to worry - // about further declarators in this declaration depending on the effects of - // this declarator. - ASSERT(node->getSequence()->size() == 1); - insertStatementsInParentBlock( - TIntermSequence(), - *CreateInitCode(symbol, mCanUseLoopsToInitialize, mSymbolTable)); - } - else - { - TIntermBinary *init = - new TIntermBinary(EOpInitialize, symbol, CreateZeroNode(symbol->getType())); - queueReplacementWithParent(node, symbol, init, OriginalNode::BECOMES_CHILD); - } - } - } - return false; - } - - private: - int mShaderVersion; - bool mCanUseLoopsToInitialize; -}; - -} // namespace anonymous - -TIntermSequence *CreateInitCode(const TIntermTyped *initializedSymbol, - bool canUseLoopsToInitialize, - TSymbolTable *symbolTable) -{ - TIntermSequence *initCode = new TIntermSequence(); - AddZeroInitSequence(initializedSymbol, canUseLoopsToInitialize, initCode, symbolTable); - return initCode; -} - -void InitializeUninitializedLocals(TIntermBlock *root, - int shaderVersion, - bool canUseLoopsToInitialize, - TSymbolTable *symbolTable) -{ - InitializeLocalsTraverser traverser(shaderVersion, symbolTable, canUseLoopsToInitialize); - root->traverse(&traverser); - traverser.updateTree(); -} - -void InitializeVariables(TIntermBlock *root, - const InitVariableList &vars, - TSymbolTable *symbolTable, - int shaderVersion, - const TExtensionBehavior &extensionBehavior, - bool canUseLoopsToInitialize) -{ - TIntermBlock *body = FindMainBody(root); - InsertInitCode(body->getSequence(), vars, symbolTable, shaderVersion, extensionBehavior, - canUseLoopsToInitialize); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h deleted file mode 100644 index 1a7b3c0f24..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ -#define COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ - -#include <GLSLANG/ShaderLang.h> - -#include "compiler/translator/ExtensionBehavior.h" -#include "compiler/translator/IntermNode.h" - -namespace sh -{ -class TSymbolTable; - -typedef std::vector<sh::ShaderVariable> InitVariableList; - -// For all of the functions below: If canUseLoopsToInitialize is set, for loops are used instead of -// a large number of initializers where it can make sense, such as for initializing large arrays. - -// Return a sequence of assignment operations to initialize "initializedSymbol". initializedSymbol -// may be an array, struct or any combination of these, as long as it contains only basic types. -TIntermSequence *CreateInitCode(const TIntermTyped *initializedSymbol, - bool canUseLoopsToInitialize, - TSymbolTable *symbolTable); - -// Initialize all uninitialized local variables, so that undefined behavior is avoided. -void InitializeUninitializedLocals(TIntermBlock *root, - int shaderVersion, - bool canUseLoopsToInitialize, - TSymbolTable *symbolTable); - -// This function can initialize all the types that CreateInitCode is able to initialize. All -// variables must be globals which can be found in the symbol table. For now it is used for the -// following two scenarios: -// 1. Initializing gl_Position; -// 2. Initializing output variables referred to in the shader source. -// Note: The type of each lvalue in an initializer is retrieved from the symbol table. gl_FragData -// requires special handling because the number of indices which can be initialized is determined by -// enabled extensions. -void InitializeVariables(TIntermBlock *root, - const InitVariableList &vars, - TSymbolTable *symbolTable, - int shaderVersion, - const TExtensionBehavior &extensionBehavior, - bool canUseLoopsToInitialize); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp deleted file mode 100644 index a57ffcb4bc..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp +++ /dev/null @@ -1,3330 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// Build the intermediate representation. -// - -#include <float.h> -#include <limits.h> -#include <math.h> -#include <stdlib.h> -#include <algorithm> -#include <vector> - -#include "common/mathutil.h" -#include "common/matrix_utils.h" -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -const float kPi = 3.14159265358979323846f; -const float kDegreesToRadiansMultiplier = kPi / 180.0f; -const float kRadiansToDegreesMultiplier = 180.0f / kPi; - -TPrecision GetHigherPrecision(TPrecision left, TPrecision right) -{ - return left > right ? left : right; -} - -TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size) -{ - TConstantUnion *constUnion = new TConstantUnion[size]; - for (unsigned int i = 0; i < size; ++i) - constUnion[i] = constant; - - return constUnion; -} - -void UndefinedConstantFoldingError(const TSourceLoc &loc, - TOperator op, - TBasicType basicType, - TDiagnostics *diagnostics, - TConstantUnion *result) -{ - diagnostics->warning(loc, "operation result is undefined for the values passed in", - GetOperatorString(op)); - - switch (basicType) - { - case EbtFloat: - result->setFConst(0.0f); - break; - case EbtInt: - result->setIConst(0); - break; - case EbtUInt: - result->setUConst(0u); - break; - case EbtBool: - result->setBConst(false); - break; - default: - break; - } -} - -float VectorLength(const TConstantUnion *paramArray, size_t paramArraySize) -{ - float result = 0.0f; - for (size_t i = 0; i < paramArraySize; i++) - { - float f = paramArray[i].getFConst(); - result += f * f; - } - return sqrtf(result); -} - -float VectorDotProduct(const TConstantUnion *paramArray1, - const TConstantUnion *paramArray2, - size_t paramArraySize) -{ - float result = 0.0f; - for (size_t i = 0; i < paramArraySize; i++) - result += paramArray1[i].getFConst() * paramArray2[i].getFConst(); - return result; -} - -TIntermTyped *CreateFoldedNode(const TConstantUnion *constArray, - const TIntermTyped *originalNode, - TQualifier qualifier) -{ - if (constArray == nullptr) - { - return nullptr; - } - TIntermTyped *folded = new TIntermConstantUnion(constArray, originalNode->getType()); - folded->getTypePointer()->setQualifier(qualifier); - folded->setLine(originalNode->getLine()); - return folded; -} - -angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray, - const unsigned int &rows, - const unsigned int &cols) -{ - std::vector<float> elements; - for (size_t i = 0; i < rows * cols; i++) - elements.push_back(paramArray[i].getFConst()); - // Transpose is used since the Matrix constructor expects arguments in row-major order, - // whereas the paramArray is in column-major order. Rows/cols parameters are also flipped below - // so that the created matrix will have the expected dimensions after the transpose. - return angle::Matrix<float>(elements, cols, rows).transpose(); -} - -angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray, const unsigned int &size) -{ - std::vector<float> elements; - for (size_t i = 0; i < size * size; i++) - elements.push_back(paramArray[i].getFConst()); - // Transpose is used since the Matrix constructor expects arguments in row-major order, - // whereas the paramArray is in column-major order. - return angle::Matrix<float>(elements, size).transpose(); -} - -void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resultArray) -{ - // Transpose is used since the input Matrix is in row-major order, - // whereas the actual result should be in column-major order. - angle::Matrix<float> result = m.transpose(); - std::vector<float> resultElements = result.elements(); - for (size_t i = 0; i < resultElements.size(); i++) - resultArray[i].setFConst(resultElements[i]); -} - -} // namespace anonymous - -//////////////////////////////////////////////////////////////// -// -// Member functions of the nodes used for building the tree. -// -//////////////////////////////////////////////////////////////// - -void TIntermTyped::setTypePreservePrecision(const TType &t) -{ - TPrecision precision = getPrecision(); - mType = t; - ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined); - mType.setPrecision(precision); -} - -#define REPLACE_IF_IS(node, type, original, replacement) \ - if (node == original) \ - { \ - node = static_cast<type *>(replacement); \ - return true; \ - } - -bool TIntermLoop::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - ASSERT(original != nullptr); // This risks replacing multiple children. - REPLACE_IF_IS(mInit, TIntermNode, original, replacement); - REPLACE_IF_IS(mCond, TIntermTyped, original, replacement); - REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement); - REPLACE_IF_IS(mBody, TIntermBlock, original, replacement); - return false; -} - -bool TIntermBranch::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement); - return false; -} - -bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType()); - REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); - return false; -} - -bool TIntermBinary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement); - REPLACE_IF_IS(mRight, TIntermTyped, original, replacement); - return false; -} - -bool TIntermUnary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType()); - REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); - return false; -} - -bool TIntermInvariantDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mSymbol, TIntermSymbol, original, replacement); - return false; -} - -bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mPrototype, TIntermFunctionPrototype, original, replacement); - REPLACE_IF_IS(mBody, TIntermBlock, original, replacement); - return false; -} - -bool TIntermAggregate::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - return replaceChildNodeInternal(original, replacement); -} - -bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - return replaceChildNodeInternal(original, replacement); -} - -bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - return replaceChildNodeInternal(original, replacement); -} - -bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - return replaceChildNodeInternal(original, replacement); -} - -bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement) -{ - for (size_t ii = 0; ii < getSequence()->size(); ++ii) - { - REPLACE_IF_IS((*getSequence())[ii], TIntermNode, original, replacement); - } - return false; -} - -bool TIntermAggregateBase::replaceChildNodeWithMultiple(TIntermNode *original, - const TIntermSequence &replacements) -{ - for (auto it = getSequence()->begin(); it < getSequence()->end(); ++it) - { - if (*it == original) - { - it = getSequence()->erase(it); - getSequence()->insert(it, replacements.begin(), replacements.end()); - return true; - } - } - return false; -} - -bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position, - const TIntermSequence &insertions) -{ - if (position > getSequence()->size()) - { - return false; - } - auto it = getSequence()->begin() + position; - getSequence()->insert(it, insertions.begin(), insertions.end()); - return true; -} - -TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TFunction &func, - TIntermSequence *arguments) -{ - TIntermAggregate *callNode = - new TIntermAggregate(func.getReturnType(), EOpCallFunctionInAST, arguments); - callNode->getFunctionSymbolInfo()->setFromFunction(func); - return callNode; -} - -TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TType &type, - const TSymbolUniqueId &id, - const TName &name, - TIntermSequence *arguments) -{ - TIntermAggregate *callNode = new TIntermAggregate(type, EOpCallFunctionInAST, arguments); - callNode->getFunctionSymbolInfo()->setId(id); - callNode->getFunctionSymbolInfo()->setNameObj(name); - return callNode; -} - -TIntermAggregate *TIntermAggregate::CreateBuiltInFunctionCall(const TFunction &func, - TIntermSequence *arguments) -{ - TIntermAggregate *callNode = - new TIntermAggregate(func.getReturnType(), EOpCallBuiltInFunction, arguments); - callNode->getFunctionSymbolInfo()->setFromFunction(func); - // Note that name needs to be set before texture function type is determined. - callNode->setBuiltInFunctionPrecision(); - return callNode; -} - -TIntermAggregate *TIntermAggregate::CreateConstructor(const TType &type, - TIntermSequence *arguments) -{ - return new TIntermAggregate(type, EOpConstruct, arguments); -} - -TIntermAggregate *TIntermAggregate::Create(const TType &type, - TOperator op, - TIntermSequence *arguments) -{ - TIntermAggregate *node = new TIntermAggregate(type, op, arguments); - ASSERT(op != EOpCallFunctionInAST); // Should use CreateFunctionCall - ASSERT(op != EOpCallBuiltInFunction); // Should use CreateBuiltInFunctionCall - ASSERT(!node->isConstructor()); // Should use CreateConstructor - return node; -} - -TIntermAggregate::TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments) - : TIntermOperator(op), mUseEmulatedFunction(false), mGotPrecisionFromChildren(false) -{ - if (arguments != nullptr) - { - mArguments.swap(*arguments); - } - setTypePrecisionAndQualifier(type); -} - -void TIntermAggregate::setTypePrecisionAndQualifier(const TType &type) -{ - setType(type); - mType.setQualifier(EvqTemporary); - if (!isFunctionCall()) - { - if (isConstructor()) - { - // Structs should not be precision qualified, the individual members may be. - // Built-in types on the other hand should be precision qualified. - if (getBasicType() != EbtStruct) - { - setPrecisionFromChildren(); - } - } - else - { - setPrecisionForBuiltInOp(); - } - if (areChildrenConstQualified()) - { - mType.setQualifier(EvqConst); - } - } -} - -bool TIntermAggregate::areChildrenConstQualified() -{ - for (TIntermNode *&arg : mArguments) - { - TIntermTyped *typedArg = arg->getAsTyped(); - if (typedArg && typedArg->getQualifier() != EvqConst) - { - return false; - } - } - return true; -} - -void TIntermAggregate::setPrecisionFromChildren() -{ - mGotPrecisionFromChildren = true; - if (getBasicType() == EbtBool) - { - mType.setPrecision(EbpUndefined); - return; - } - - TPrecision precision = EbpUndefined; - TIntermSequence::iterator childIter = mArguments.begin(); - while (childIter != mArguments.end()) - { - TIntermTyped *typed = (*childIter)->getAsTyped(); - if (typed) - precision = GetHigherPrecision(typed->getPrecision(), precision); - ++childIter; - } - mType.setPrecision(precision); -} - -void TIntermAggregate::setPrecisionForBuiltInOp() -{ - ASSERT(!isConstructor()); - ASSERT(!isFunctionCall()); - if (!setPrecisionForSpecialBuiltInOp()) - { - setPrecisionFromChildren(); - } -} - -bool TIntermAggregate::setPrecisionForSpecialBuiltInOp() -{ - switch (mOp) - { - case EOpBitfieldExtract: - mType.setPrecision(mArguments[0]->getAsTyped()->getPrecision()); - mGotPrecisionFromChildren = true; - return true; - case EOpBitfieldInsert: - mType.setPrecision(GetHigherPrecision(mArguments[0]->getAsTyped()->getPrecision(), - mArguments[1]->getAsTyped()->getPrecision())); - mGotPrecisionFromChildren = true; - return true; - case EOpUaddCarry: - case EOpUsubBorrow: - mType.setPrecision(EbpHigh); - return true; - default: - return false; - } -} - -void TIntermAggregate::setBuiltInFunctionPrecision() -{ - // All built-ins returning bool should be handled as ops, not functions. - ASSERT(getBasicType() != EbtBool); - ASSERT(mOp == EOpCallBuiltInFunction); - - TPrecision precision = EbpUndefined; - for (TIntermNode *arg : mArguments) - { - TIntermTyped *typed = arg->getAsTyped(); - // ESSL spec section 8: texture functions get their precision from the sampler. - if (typed && IsSampler(typed->getBasicType())) - { - precision = typed->getPrecision(); - break; - } - } - // ESSL 3.0 spec section 8: textureSize always gets highp precision. - // All other functions that take a sampler are assumed to be texture functions. - if (mFunctionInfo.getName().find("textureSize") == 0) - mType.setPrecision(EbpHigh); - else - mType.setPrecision(precision); -} - -TString TIntermAggregate::getSymbolTableMangledName() const -{ - ASSERT(!isConstructor()); - switch (mOp) - { - case EOpCallInternalRawFunction: - case EOpCallBuiltInFunction: - case EOpCallFunctionInAST: - return TFunction::GetMangledNameFromCall(mFunctionInfo.getName(), mArguments); - default: - TString opString = GetOperatorString(mOp); - return TFunction::GetMangledNameFromCall(opString, mArguments); - } -} - -bool TIntermAggregate::hasSideEffects() const -{ - if (isFunctionCall() && mFunctionInfo.isKnownToNotHaveSideEffects()) - { - for (TIntermNode *arg : mArguments) - { - if (arg->getAsTyped()->hasSideEffects()) - { - return true; - } - } - return false; - } - // Conservatively assume most aggregate operators have side-effects - return true; -} - -void TIntermBlock::appendStatement(TIntermNode *statement) -{ - // Declaration nodes with no children can appear if it was an empty declaration or if all the - // declarators just added constants to the symbol table instead of generating code. We still - // need to add the declaration to the AST in that case because it might be relevant to the - // validity of switch/case. - if (statement != nullptr) - { - mStatements.push_back(statement); - } -} - -void TIntermFunctionPrototype::appendParameter(TIntermSymbol *parameter) -{ - ASSERT(parameter != nullptr); - mParameters.push_back(parameter); -} - -void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator) -{ - ASSERT(declarator != nullptr); - ASSERT(declarator->getAsSymbolNode() != nullptr || - (declarator->getAsBinaryNode() != nullptr && - declarator->getAsBinaryNode()->getOp() == EOpInitialize)); - ASSERT(mDeclarators.empty() || - declarator->getType().sameNonArrayType(mDeclarators.back()->getAsTyped()->getType())); - mDeclarators.push_back(declarator); -} - -bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); - REPLACE_IF_IS(mTrueExpression, TIntermTyped, original, replacement); - REPLACE_IF_IS(mFalseExpression, TIntermTyped, original, replacement); - return false; -} - -bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); - REPLACE_IF_IS(mTrueBlock, TIntermBlock, original, replacement); - REPLACE_IF_IS(mFalseBlock, TIntermBlock, original, replacement); - return false; -} - -bool TIntermSwitch::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mInit, TIntermTyped, original, replacement); - REPLACE_IF_IS(mStatementList, TIntermBlock, original, replacement); - ASSERT(mStatementList); - return false; -} - -bool TIntermCase::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); - return false; -} - -TIntermTyped::TIntermTyped(const TIntermTyped &node) : TIntermNode(), mType(node.mType) -{ - // Copy constructor is disallowed for TIntermNode in order to disallow it for subclasses that - // don't explicitly allow it, so normal TIntermNode constructor is used to construct the copy. - // We need to manually copy any fields of TIntermNode besides handling fields in TIntermTyped. - mLine = node.mLine; -} - -bool TIntermTyped::isConstructorWithOnlyConstantUnionParameters() -{ - TIntermAggregate *constructor = getAsAggregate(); - if (!constructor || !constructor->isConstructor()) - { - return false; - } - for (TIntermNode *&node : *constructor->getSequence()) - { - if (!node->getAsConstantUnion()) - return false; - } - return true; -} - -TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) : TIntermTyped(node) -{ - mUnionArrayPointer = node.mUnionArrayPointer; -} - -void TFunctionSymbolInfo::setFromFunction(const TFunction &function) -{ - setName(function.getName()); - setId(TSymbolUniqueId(function)); -} - -TFunctionSymbolInfo::TFunctionSymbolInfo(const TSymbolUniqueId &id) - : mId(new TSymbolUniqueId(id)), mKnownToNotHaveSideEffects(false) -{ -} - -TFunctionSymbolInfo::TFunctionSymbolInfo(const TFunctionSymbolInfo &info) - : mName(info.mName), mId(nullptr), mKnownToNotHaveSideEffects(info.mKnownToNotHaveSideEffects) -{ - if (info.mId) - { - mId = new TSymbolUniqueId(*info.mId); - } -} - -TFunctionSymbolInfo &TFunctionSymbolInfo::operator=(const TFunctionSymbolInfo &info) -{ - mName = info.mName; - if (info.mId) - { - mId = new TSymbolUniqueId(*info.mId); - } - else - { - mId = nullptr; - } - return *this; -} - -void TFunctionSymbolInfo::setId(const TSymbolUniqueId &id) -{ - mId = new TSymbolUniqueId(id); -} - -const TSymbolUniqueId &TFunctionSymbolInfo::getId() const -{ - ASSERT(mId); - return *mId; -} - -TIntermAggregate::TIntermAggregate(const TIntermAggregate &node) - : TIntermOperator(node), - mUseEmulatedFunction(node.mUseEmulatedFunction), - mGotPrecisionFromChildren(node.mGotPrecisionFromChildren), - mFunctionInfo(node.mFunctionInfo) -{ - for (TIntermNode *arg : node.mArguments) - { - TIntermTyped *typedArg = arg->getAsTyped(); - ASSERT(typedArg != nullptr); - TIntermTyped *argCopy = typedArg->deepCopy(); - mArguments.push_back(argCopy); - } -} - -TIntermAggregate *TIntermAggregate::shallowCopy() const -{ - TIntermSequence *copySeq = new TIntermSequence(); - copySeq->insert(copySeq->begin(), getSequence()->begin(), getSequence()->end()); - TIntermAggregate *copyNode = new TIntermAggregate(mType, mOp, copySeq); - *copyNode->getFunctionSymbolInfo() = mFunctionInfo; - copyNode->setLine(mLine); - return copyNode; -} - -TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermTyped(node) -{ - TIntermTyped *operandCopy = node.mOperand->deepCopy(); - ASSERT(operandCopy != nullptr); - mOperand = operandCopy; - mSwizzleOffsets = node.mSwizzleOffsets; -} - -TIntermBinary::TIntermBinary(const TIntermBinary &node) - : TIntermOperator(node), mAddIndexClamp(node.mAddIndexClamp) -{ - TIntermTyped *leftCopy = node.mLeft->deepCopy(); - TIntermTyped *rightCopy = node.mRight->deepCopy(); - ASSERT(leftCopy != nullptr && rightCopy != nullptr); - mLeft = leftCopy; - mRight = rightCopy; -} - -TIntermUnary::TIntermUnary(const TIntermUnary &node) - : TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction) -{ - TIntermTyped *operandCopy = node.mOperand->deepCopy(); - ASSERT(operandCopy != nullptr); - mOperand = operandCopy; -} - -TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermTyped(node) -{ - TIntermTyped *conditionCopy = node.mCondition->deepCopy(); - TIntermTyped *trueCopy = node.mTrueExpression->deepCopy(); - TIntermTyped *falseCopy = node.mFalseExpression->deepCopy(); - ASSERT(conditionCopy != nullptr && trueCopy != nullptr && falseCopy != nullptr); - mCondition = conditionCopy; - mTrueExpression = trueCopy; - mFalseExpression = falseCopy; -} - -bool TIntermOperator::isAssignment() const -{ - return IsAssignment(mOp); -} - -bool TIntermOperator::isMultiplication() const -{ - switch (mOp) - { - case EOpMul: - case EOpMatrixTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpVectorTimesMatrix: - case EOpVectorTimesScalar: - return true; - default: - return false; - } -} - -bool TIntermOperator::isConstructor() const -{ - return (mOp == EOpConstruct); -} - -bool TIntermOperator::isFunctionCall() const -{ - switch (mOp) - { - case EOpCallFunctionInAST: - case EOpCallBuiltInFunction: - case EOpCallInternalRawFunction: - return true; - default: - return false; - } -} - -TOperator TIntermBinary::GetMulOpBasedOnOperands(const TType &left, const TType &right) -{ - if (left.isMatrix()) - { - if (right.isMatrix()) - { - return EOpMatrixTimesMatrix; - } - else - { - if (right.isVector()) - { - return EOpMatrixTimesVector; - } - else - { - return EOpMatrixTimesScalar; - } - } - } - else - { - if (right.isMatrix()) - { - if (left.isVector()) - { - return EOpVectorTimesMatrix; - } - else - { - return EOpMatrixTimesScalar; - } - } - else - { - // Neither operand is a matrix. - if (left.isVector() == right.isVector()) - { - // Leave as component product. - return EOpMul; - } - else - { - return EOpVectorTimesScalar; - } - } - } -} - -TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const TType &right) -{ - if (left.isMatrix()) - { - if (right.isMatrix()) - { - return EOpMatrixTimesMatrixAssign; - } - else - { - // right should be scalar, but this may not be validated yet. - return EOpMatrixTimesScalarAssign; - } - } - else - { - if (right.isMatrix()) - { - // Left should be a vector, but this may not be validated yet. - return EOpVectorTimesMatrixAssign; - } - else - { - // Neither operand is a matrix. - if (left.isVector() == right.isVector()) - { - // Leave as component product. - return EOpMulAssign; - } - else - { - // left should be vector and right should be scalar, but this may not be validated - // yet. - return EOpVectorTimesScalarAssign; - } - } - } -} - -// -// Make sure the type of a unary operator is appropriate for its -// combination of operation and operand type. -// -void TIntermUnary::promote() -{ - if (mOp == EOpArrayLength) - { - // Special case: the qualifier of .length() doesn't depend on the operand qualifier. - setType(TType(EbtInt, EbpUndefined, EvqConst)); - return; - } - - TQualifier resultQualifier = EvqTemporary; - if (mOperand->getQualifier() == EvqConst) - resultQualifier = EvqConst; - - unsigned char operandPrimarySize = - static_cast<unsigned char>(mOperand->getType().getNominalSize()); - switch (mOp) - { - case EOpFloatBitsToInt: - setType(TType(EbtInt, EbpHigh, resultQualifier, operandPrimarySize)); - break; - case EOpFloatBitsToUint: - setType(TType(EbtUInt, EbpHigh, resultQualifier, operandPrimarySize)); - break; - case EOpIntBitsToFloat: - case EOpUintBitsToFloat: - setType(TType(EbtFloat, EbpHigh, resultQualifier, operandPrimarySize)); - break; - case EOpPackSnorm2x16: - case EOpPackUnorm2x16: - case EOpPackHalf2x16: - case EOpPackUnorm4x8: - case EOpPackSnorm4x8: - setType(TType(EbtUInt, EbpHigh, resultQualifier)); - break; - case EOpUnpackSnorm2x16: - case EOpUnpackUnorm2x16: - setType(TType(EbtFloat, EbpHigh, resultQualifier, 2)); - break; - case EOpUnpackHalf2x16: - setType(TType(EbtFloat, EbpMedium, resultQualifier, 2)); - break; - case EOpUnpackUnorm4x8: - case EOpUnpackSnorm4x8: - setType(TType(EbtFloat, EbpMedium, resultQualifier, 4)); - break; - case EOpAny: - case EOpAll: - setType(TType(EbtBool, EbpUndefined, resultQualifier)); - break; - case EOpLength: - case EOpDeterminant: - setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier)); - break; - case EOpTranspose: - setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier, - static_cast<unsigned char>(mOperand->getType().getRows()), - static_cast<unsigned char>(mOperand->getType().getCols()))); - break; - case EOpIsInf: - case EOpIsNan: - setType(TType(EbtBool, EbpUndefined, resultQualifier, operandPrimarySize)); - break; - case EOpBitfieldReverse: - setType(TType(mOperand->getBasicType(), EbpHigh, resultQualifier, operandPrimarySize)); - break; - case EOpBitCount: - setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize)); - break; - case EOpFindLSB: - setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize)); - break; - case EOpFindMSB: - setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize)); - break; - default: - setType(mOperand->getType()); - mType.setQualifier(resultQualifier); - break; - } -} - -TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets) - : TIntermTyped(TType(EbtFloat, EbpUndefined)), - mOperand(operand), - mSwizzleOffsets(swizzleOffsets) -{ - ASSERT(mSwizzleOffsets.size() <= 4); - promote(); -} - -TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand) - : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false) -{ - promote(); -} - -TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right) - : TIntermOperator(op), mLeft(left), mRight(right), mAddIndexClamp(false) -{ - promote(); -} - -TIntermInvariantDeclaration::TIntermInvariantDeclaration(TIntermSymbol *symbol, const TSourceLoc &line) - : TIntermNode(), mSymbol(symbol) -{ - ASSERT(symbol); - setLine(line); -} - -TIntermTernary::TIntermTernary(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression) - : TIntermTyped(trueExpression->getType()), - mCondition(cond), - mTrueExpression(trueExpression), - mFalseExpression(falseExpression) -{ - getTypePointer()->setQualifier( - TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression)); -} - -TIntermLoop::TIntermLoop(TLoopType type, - TIntermNode *init, - TIntermTyped *cond, - TIntermTyped *expr, - TIntermBlock *body) - : mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body) -{ - // Declaration nodes with no children can appear if all the declarators just added constants to - // the symbol table instead of generating code. They're no-ops so don't add them to the tree. - if (mInit && mInit->getAsDeclarationNode() && - mInit->getAsDeclarationNode()->getSequence()->empty()) - { - mInit = nullptr; - } -} - -TIntermIfElse::TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB) - : TIntermNode(), mCondition(cond), mTrueBlock(trueB), mFalseBlock(falseB) -{ - // Prune empty false blocks so that there won't be unnecessary operations done on it. - if (mFalseBlock && mFalseBlock->getSequence()->empty()) - { - mFalseBlock = nullptr; - } -} - -TIntermSwitch::TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList) - : TIntermNode(), mInit(init), mStatementList(statementList) -{ - ASSERT(mStatementList); -} - -void TIntermSwitch::setStatementList(TIntermBlock *statementList) -{ - ASSERT(statementList); - mStatementList = statementList; -} - -// static -TQualifier TIntermTernary::DetermineQualifier(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression) -{ - if (cond->getQualifier() == EvqConst && trueExpression->getQualifier() == EvqConst && - falseExpression->getQualifier() == EvqConst) - { - return EvqConst; - } - return EvqTemporary; -} - -TIntermTyped *TIntermTernary::fold() -{ - if (mCondition->getAsConstantUnion()) - { - if (mCondition->getAsConstantUnion()->getBConst(0)) - { - mTrueExpression->getTypePointer()->setQualifier(mType.getQualifier()); - return mTrueExpression; - } - else - { - mFalseExpression->getTypePointer()->setQualifier(mType.getQualifier()); - return mFalseExpression; - } - } - return this; -} - -void TIntermSwizzle::promote() -{ - TQualifier resultQualifier = EvqTemporary; - if (mOperand->getQualifier() == EvqConst) - resultQualifier = EvqConst; - - auto numFields = mSwizzleOffsets.size(); - setType(TType(mOperand->getBasicType(), mOperand->getPrecision(), resultQualifier, - static_cast<unsigned char>(numFields))); -} - -bool TIntermSwizzle::hasDuplicateOffsets() const -{ - int offsetCount[4] = {0u, 0u, 0u, 0u}; - for (const auto offset : mSwizzleOffsets) - { - offsetCount[offset]++; - if (offsetCount[offset] > 1) - { - return true; - } - } - return false; -} - -bool TIntermSwizzle::offsetsMatch(int offset) const -{ - return mSwizzleOffsets.size() == 1 && mSwizzleOffsets[0] == offset; -} - -void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const -{ - for (const int offset : mSwizzleOffsets) - { - switch (offset) - { - case 0: - *out << "x"; - break; - case 1: - *out << "y"; - break; - case 2: - *out << "z"; - break; - case 3: - *out << "w"; - break; - default: - UNREACHABLE(); - } - } -} - -TQualifier TIntermBinary::GetCommaQualifier(int shaderVersion, - const TIntermTyped *left, - const TIntermTyped *right) -{ - // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression. - if (shaderVersion >= 300 || left->getQualifier() != EvqConst || - right->getQualifier() != EvqConst) - { - return EvqTemporary; - } - return EvqConst; -} - -// Establishes the type of the result of the binary operation. -void TIntermBinary::promote() -{ - ASSERT(!isMultiplication() || - mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType())); - - // Comma is handled as a special case. Note that the comma node qualifier depends on the shader - // version and so is not being set here. - if (mOp == EOpComma) - { - setType(mRight->getType()); - return; - } - - // Base assumption: just make the type the same as the left - // operand. Then only deviations from this need be coded. - setType(mLeft->getType()); - - TQualifier resultQualifier = EvqConst; - // Binary operations results in temporary variables unless both - // operands are const. - if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst) - { - resultQualifier = EvqTemporary; - getTypePointer()->setQualifier(EvqTemporary); - } - - // Handle indexing ops. - switch (mOp) - { - case EOpIndexDirect: - case EOpIndexIndirect: - if (mLeft->isArray()) - { - mType.toArrayElementType(); - } - else if (mLeft->isMatrix()) - { - setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier, - static_cast<unsigned char>(mLeft->getRows()))); - } - else if (mLeft->isVector()) - { - setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier)); - } - else - { - UNREACHABLE(); - } - return; - case EOpIndexDirectStruct: - { - const TFieldList &fields = mLeft->getType().getStruct()->fields(); - const int i = mRight->getAsConstantUnion()->getIConst(0); - setType(*fields[i]->type()); - getTypePointer()->setQualifier(resultQualifier); - return; - } - case EOpIndexDirectInterfaceBlock: - { - const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields(); - const int i = mRight->getAsConstantUnion()->getIConst(0); - setType(*fields[i]->type()); - getTypePointer()->setQualifier(resultQualifier); - return; - } - default: - break; - } - - ASSERT(mLeft->isArray() == mRight->isArray()); - - // The result gets promoted to the highest precision. - TPrecision higherPrecision = GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision()); - getTypePointer()->setPrecision(higherPrecision); - - const int nominalSize = std::max(mLeft->getNominalSize(), mRight->getNominalSize()); - - // - // All scalars or structs. Code after this test assumes this case is removed! - // - if (nominalSize == 1) - { - switch (mOp) - { - // - // Promote to conditional - // - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - setType(TType(EbtBool, EbpUndefined, resultQualifier)); - break; - - // - // And and Or operate on conditionals - // - case EOpLogicalAnd: - case EOpLogicalXor: - case EOpLogicalOr: - ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool); - setType(TType(EbtBool, EbpUndefined, resultQualifier)); - break; - - default: - break; - } - return; - } - - // If we reach here, at least one of the operands is vector or matrix. - // The other operand could be a scalar, vector, or matrix. - TBasicType basicType = mLeft->getBasicType(); - - switch (mOp) - { - case EOpMul: - break; - case EOpMatrixTimesScalar: - if (mRight->isMatrix()) - { - setType(TType(basicType, higherPrecision, resultQualifier, - static_cast<unsigned char>(mRight->getCols()), - static_cast<unsigned char>(mRight->getRows()))); - } - break; - case EOpMatrixTimesVector: - setType(TType(basicType, higherPrecision, resultQualifier, - static_cast<unsigned char>(mLeft->getRows()), 1)); - break; - case EOpMatrixTimesMatrix: - setType(TType(basicType, higherPrecision, resultQualifier, - static_cast<unsigned char>(mRight->getCols()), - static_cast<unsigned char>(mLeft->getRows()))); - break; - case EOpVectorTimesScalar: - setType(TType(basicType, higherPrecision, resultQualifier, - static_cast<unsigned char>(nominalSize), 1)); - break; - case EOpVectorTimesMatrix: - setType(TType(basicType, higherPrecision, resultQualifier, - static_cast<unsigned char>(mRight->getCols()), 1)); - break; - case EOpMulAssign: - case EOpVectorTimesScalarAssign: - case EOpVectorTimesMatrixAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - ASSERT(mOp == GetMulAssignOpBasedOnOperands(mLeft->getType(), mRight->getType())); - break; - case EOpAssign: - case EOpInitialize: - ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) && - (mLeft->getSecondarySize() == mRight->getSecondarySize())); - break; - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpIMod: - case EOpBitShiftLeft: - case EOpBitShiftRight: - case EOpBitwiseAnd: - case EOpBitwiseXor: - case EOpBitwiseOr: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - case EOpIModAssign: - case EOpBitShiftLeftAssign: - case EOpBitShiftRightAssign: - case EOpBitwiseAndAssign: - case EOpBitwiseXorAssign: - case EOpBitwiseOrAssign: - { - const int secondarySize = - std::max(mLeft->getSecondarySize(), mRight->getSecondarySize()); - setType(TType(basicType, higherPrecision, resultQualifier, - static_cast<unsigned char>(nominalSize), - static_cast<unsigned char>(secondarySize))); - ASSERT(!mLeft->isArray() && !mRight->isArray()); - break; - } - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) && - (mLeft->getSecondarySize() == mRight->getSecondarySize())); - setType(TType(EbtBool, EbpUndefined, resultQualifier)); - break; - - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectInterfaceBlock: - case EOpIndexDirectStruct: - // These ops should be already fully handled. - UNREACHABLE(); - break; - default: - UNREACHABLE(); - break; - } -} - -const TConstantUnion *TIntermConstantUnion::foldIndexing(int index) -{ - if (isArray()) - { - ASSERT(index < static_cast<int>(getType().getOutermostArraySize())); - TType arrayElementType = getType(); - arrayElementType.toArrayElementType(); - size_t arrayElementSize = arrayElementType.getObjectSize(); - return &mUnionArrayPointer[arrayElementSize * index]; - } - else if (isMatrix()) - { - ASSERT(index < getType().getCols()); - int size = getType().getRows(); - return &mUnionArrayPointer[size * index]; - } - else if (isVector()) - { - ASSERT(index < getType().getNominalSize()); - return &mUnionArrayPointer[index]; - } - else - { - UNREACHABLE(); - return nullptr; - } -} - -TIntermTyped *TIntermSwizzle::fold() -{ - TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion(); - if (operandConstant == nullptr) - { - return this; - } - - TConstantUnion *constArray = new TConstantUnion[mSwizzleOffsets.size()]; - for (size_t i = 0; i < mSwizzleOffsets.size(); ++i) - { - constArray[i] = *operandConstant->foldIndexing(mSwizzleOffsets.at(i)); - } - return CreateFoldedNode(constArray, this, mType.getQualifier()); -} - -TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics) -{ - TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion(); - TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion(); - switch (mOp) - { - case EOpComma: - { - if (mLeft->hasSideEffects()) - { - return this; - } - mRight->getTypePointer()->setQualifier(mType.getQualifier()); - return mRight; - } - case EOpIndexDirect: - { - if (leftConstant == nullptr || rightConstant == nullptr) - { - return this; - } - int index = rightConstant->getIConst(0); - - const TConstantUnion *constArray = leftConstant->foldIndexing(index); - if (!constArray) - { - return this; - } - return CreateFoldedNode(constArray, this, mType.getQualifier()); - } - case EOpIndexDirectStruct: - { - if (leftConstant == nullptr || rightConstant == nullptr) - { - return this; - } - const TFieldList &fields = mLeft->getType().getStruct()->fields(); - size_t index = static_cast<size_t>(rightConstant->getIConst(0)); - - size_t previousFieldsSize = 0; - for (size_t i = 0; i < index; ++i) - { - previousFieldsSize += fields[i]->type()->getObjectSize(); - } - - const TConstantUnion *constArray = leftConstant->getUnionArrayPointer(); - return CreateFoldedNode(constArray + previousFieldsSize, this, mType.getQualifier()); - } - case EOpIndexIndirect: - case EOpIndexDirectInterfaceBlock: - // Can never be constant folded. - return this; - default: - { - if (leftConstant == nullptr || rightConstant == nullptr) - { - return this; - } - TConstantUnion *constArray = - leftConstant->foldBinary(mOp, rightConstant, diagnostics, mLeft->getLine()); - if (!constArray) - { - return this; - } - - // Nodes may be constant folded without being qualified as constant. - return CreateFoldedNode(constArray, this, mType.getQualifier()); - } - } -} - -TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics) -{ - TConstantUnion *constArray = nullptr; - - if (mOp == EOpArrayLength) - { - // The size of runtime-sized arrays may only be determined at runtime. - if (mOperand->hasSideEffects() || mOperand->getType().isUnsizedArray()) - { - return this; - } - constArray = new TConstantUnion[1]; - constArray->setIConst(mOperand->getOutermostArraySize()); - } - else - { - TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion(); - if (operandConstant == nullptr) - { - return this; - } - - switch (mOp) - { - case EOpAny: - case EOpAll: - case EOpLength: - case EOpTranspose: - case EOpDeterminant: - case EOpInverse: - case EOpPackSnorm2x16: - case EOpUnpackSnorm2x16: - case EOpPackUnorm2x16: - case EOpUnpackUnorm2x16: - case EOpPackHalf2x16: - case EOpUnpackHalf2x16: - case EOpPackUnorm4x8: - case EOpPackSnorm4x8: - case EOpUnpackUnorm4x8: - case EOpUnpackSnorm4x8: - constArray = operandConstant->foldUnaryNonComponentWise(mOp); - break; - default: - constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics); - break; - } - } - if (constArray == nullptr) - { - return this; - } - - // Nodes may be constant folded without being qualified as constant. - return CreateFoldedNode(constArray, this, mType.getQualifier()); -} - -TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics) -{ - // Make sure that all params are constant before actual constant folding. - for (auto *param : *getSequence()) - { - if (param->getAsConstantUnion() == nullptr) - { - return this; - } - } - TConstantUnion *constArray = nullptr; - if (isConstructor()) - constArray = TIntermConstantUnion::FoldAggregateConstructor(this); - else - constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics); - - // Nodes may be constant folded without being qualified as constant. - return CreateFoldedNode(constArray, this, getQualifier()); -} - -// -// The fold functions see if an operation on a constant can be done in place, -// without generating run-time code. -// -// Returns the constant value to keep using or nullptr. -// -TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, - TIntermConstantUnion *rightNode, - TDiagnostics *diagnostics, - const TSourceLoc &line) -{ - const TConstantUnion *leftArray = getUnionArrayPointer(); - const TConstantUnion *rightArray = rightNode->getUnionArrayPointer(); - - ASSERT(leftArray && rightArray); - - size_t objectSize = getType().getObjectSize(); - - // for a case like float f = vec4(2, 3, 4, 5) + 1.2; - if (rightNode->getType().getObjectSize() == 1 && objectSize > 1) - { - rightArray = Vectorize(*rightNode->getUnionArrayPointer(), objectSize); - } - else if (rightNode->getType().getObjectSize() > 1 && objectSize == 1) - { - // for a case like float f = 1.2 + vec4(2, 3, 4, 5); - leftArray = Vectorize(*getUnionArrayPointer(), rightNode->getType().getObjectSize()); - objectSize = rightNode->getType().getObjectSize(); - } - - TConstantUnion *resultArray = nullptr; - - switch (op) - { - case EOpAdd: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = - TConstantUnion::add(leftArray[i], rightArray[i], diagnostics, line); - break; - case EOpSub: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = - TConstantUnion::sub(leftArray[i], rightArray[i], diagnostics, line); - break; - - case EOpMul: - case EOpVectorTimesScalar: - case EOpMatrixTimesScalar: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = - TConstantUnion::mul(leftArray[i], rightArray[i], diagnostics, line); - break; - - case EOpMatrixTimesMatrix: - { - // TODO(jmadll): This code should check for overflows. - ASSERT(getType().getBasicType() == EbtFloat && rightNode->getBasicType() == EbtFloat); - - const int leftCols = getCols(); - const int leftRows = getRows(); - const int rightCols = rightNode->getType().getCols(); - const int rightRows = rightNode->getType().getRows(); - const int resultCols = rightCols; - const int resultRows = leftRows; - - resultArray = new TConstantUnion[resultCols * resultRows]; - for (int row = 0; row < resultRows; row++) - { - for (int column = 0; column < resultCols; column++) - { - resultArray[resultRows * column + row].setFConst(0.0f); - for (int i = 0; i < leftCols; i++) - { - resultArray[resultRows * column + row].setFConst( - resultArray[resultRows * column + row].getFConst() + - leftArray[i * leftRows + row].getFConst() * - rightArray[column * rightRows + i].getFConst()); - } - } - } - } - break; - - case EOpDiv: - case EOpIMod: - { - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - switch (getType().getBasicType()) - { - case EbtFloat: - { - ASSERT(op == EOpDiv); - float dividend = leftArray[i].getFConst(); - float divisor = rightArray[i].getFConst(); - if (divisor == 0.0f) - { - if (dividend == 0.0f) - { - diagnostics->warning( - getLine(), - "Zero divided by zero during constant folding generated NaN", - "/"); - resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN()); - } - else - { - diagnostics->warning(getLine(), - "Divide by zero during constant folding", "/"); - bool negativeResult = - std::signbit(dividend) != std::signbit(divisor); - resultArray[i].setFConst( - negativeResult ? -std::numeric_limits<float>::infinity() - : std::numeric_limits<float>::infinity()); - } - } - else if (gl::isInf(dividend) && gl::isInf(divisor)) - { - diagnostics->warning(getLine(), - "Infinity divided by infinity during constant " - "folding generated NaN", - "/"); - resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN()); - } - else - { - float result = dividend / divisor; - if (!gl::isInf(dividend) && gl::isInf(result)) - { - diagnostics->warning( - getLine(), "Constant folded division overflowed to infinity", - "/"); - } - resultArray[i].setFConst(result); - } - break; - } - case EbtInt: - if (rightArray[i] == 0) - { - diagnostics->warning( - getLine(), "Divide by zero error during constant folding", "/"); - resultArray[i].setIConst(INT_MAX); - } - else - { - int lhs = leftArray[i].getIConst(); - int divisor = rightArray[i].getIConst(); - if (op == EOpDiv) - { - // Check for the special case where the minimum representable number - // is - // divided by -1. If left alone this leads to integer overflow in - // C++. - // ESSL 3.00.6 section 4.1.3 Integers: - // "However, for the case where the minimum representable value is - // divided by -1, it is allowed to return either the minimum - // representable value or the maximum representable value." - if (lhs == -0x7fffffff - 1 && divisor == -1) - { - resultArray[i].setIConst(0x7fffffff); - } - else - { - resultArray[i].setIConst(lhs / divisor); - } - } - else - { - ASSERT(op == EOpIMod); - if (lhs < 0 || divisor < 0) - { - // ESSL 3.00.6 section 5.9: Results of modulus are undefined - // when - // either one of the operands is negative. - diagnostics->warning(getLine(), - "Negative modulus operator operand " - "encountered during constant folding", - "%"); - resultArray[i].setIConst(0); - } - else - { - resultArray[i].setIConst(lhs % divisor); - } - } - } - break; - - case EbtUInt: - if (rightArray[i] == 0) - { - diagnostics->warning( - getLine(), "Divide by zero error during constant folding", "/"); - resultArray[i].setUConst(UINT_MAX); - } - else - { - if (op == EOpDiv) - { - resultArray[i].setUConst(leftArray[i].getUConst() / - rightArray[i].getUConst()); - } - else - { - ASSERT(op == EOpIMod); - resultArray[i].setUConst(leftArray[i].getUConst() % - rightArray[i].getUConst()); - } - } - break; - - default: - UNREACHABLE(); - return nullptr; - } - } - } - break; - - case EOpMatrixTimesVector: - { - // TODO(jmadll): This code should check for overflows. - ASSERT(rightNode->getBasicType() == EbtFloat); - - const int matrixCols = getCols(); - const int matrixRows = getRows(); - - resultArray = new TConstantUnion[matrixRows]; - - for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) - { - resultArray[matrixRow].setFConst(0.0f); - for (int col = 0; col < matrixCols; col++) - { - resultArray[matrixRow].setFConst( - resultArray[matrixRow].getFConst() + - leftArray[col * matrixRows + matrixRow].getFConst() * - rightArray[col].getFConst()); - } - } - } - break; - - case EOpVectorTimesMatrix: - { - // TODO(jmadll): This code should check for overflows. - ASSERT(getType().getBasicType() == EbtFloat); - - const int matrixCols = rightNode->getType().getCols(); - const int matrixRows = rightNode->getType().getRows(); - - resultArray = new TConstantUnion[matrixCols]; - - for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++) - { - resultArray[matrixCol].setFConst(0.0f); - for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) - { - resultArray[matrixCol].setFConst( - resultArray[matrixCol].getFConst() + - leftArray[matrixRow].getFConst() * - rightArray[matrixCol * matrixRows + matrixRow].getFConst()); - } - } - } - break; - - case EOpLogicalAnd: - { - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - resultArray[i] = leftArray[i] && rightArray[i]; - } - } - break; - - case EOpLogicalOr: - { - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - resultArray[i] = leftArray[i] || rightArray[i]; - } - } - break; - - case EOpLogicalXor: - { - ASSERT(getType().getBasicType() == EbtBool); - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - resultArray[i].setBConst(leftArray[i] != rightArray[i]); - } - } - break; - - case EOpBitwiseAnd: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = leftArray[i] & rightArray[i]; - break; - case EOpBitwiseXor: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = leftArray[i] ^ rightArray[i]; - break; - case EOpBitwiseOr: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = leftArray[i] | rightArray[i]; - break; - case EOpBitShiftLeft: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = - TConstantUnion::lshift(leftArray[i], rightArray[i], diagnostics, line); - break; - case EOpBitShiftRight: - resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - resultArray[i] = - TConstantUnion::rshift(leftArray[i], rightArray[i], diagnostics, line); - break; - - case EOpLessThan: - ASSERT(objectSize == 1); - resultArray = new TConstantUnion[1]; - resultArray->setBConst(*leftArray < *rightArray); - break; - - case EOpGreaterThan: - ASSERT(objectSize == 1); - resultArray = new TConstantUnion[1]; - resultArray->setBConst(*leftArray > *rightArray); - break; - - case EOpLessThanEqual: - ASSERT(objectSize == 1); - resultArray = new TConstantUnion[1]; - resultArray->setBConst(!(*leftArray > *rightArray)); - break; - - case EOpGreaterThanEqual: - ASSERT(objectSize == 1); - resultArray = new TConstantUnion[1]; - resultArray->setBConst(!(*leftArray < *rightArray)); - break; - - case EOpEqual: - case EOpNotEqual: - { - resultArray = new TConstantUnion[1]; - bool equal = true; - for (size_t i = 0; i < objectSize; i++) - { - if (leftArray[i] != rightArray[i]) - { - equal = false; - break; // break out of for loop - } - } - if (op == EOpEqual) - { - resultArray->setBConst(equal); - } - else - { - resultArray->setBConst(!equal); - } - } - break; - - default: - UNREACHABLE(); - return nullptr; - } - return resultArray; -} - -// The fold functions do operations on a constant at GLSL compile time, without generating run-time -// code. Returns the constant value to keep using. Nullptr should not be returned. -TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op) -{ - // Do operations where the return type may have a different number of components compared to the - // operand type. - - const TConstantUnion *operandArray = getUnionArrayPointer(); - ASSERT(operandArray); - - size_t objectSize = getType().getObjectSize(); - TConstantUnion *resultArray = nullptr; - switch (op) - { - case EOpAny: - ASSERT(getType().getBasicType() == EbtBool); - resultArray = new TConstantUnion(); - resultArray->setBConst(false); - for (size_t i = 0; i < objectSize; i++) - { - if (operandArray[i].getBConst()) - { - resultArray->setBConst(true); - break; - } - } - break; - - case EOpAll: - ASSERT(getType().getBasicType() == EbtBool); - resultArray = new TConstantUnion(); - resultArray->setBConst(true); - for (size_t i = 0; i < objectSize; i++) - { - if (!operandArray[i].getBConst()) - { - resultArray->setBConst(false); - break; - } - } - break; - - case EOpLength: - ASSERT(getType().getBasicType() == EbtFloat); - resultArray = new TConstantUnion(); - resultArray->setFConst(VectorLength(operandArray, objectSize)); - break; - - case EOpTranspose: - { - ASSERT(getType().getBasicType() == EbtFloat); - resultArray = new TConstantUnion[objectSize]; - angle::Matrix<float> result = - GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose(); - SetUnionArrayFromMatrix(result, resultArray); - break; - } - - case EOpDeterminant: - { - ASSERT(getType().getBasicType() == EbtFloat); - unsigned int size = getType().getNominalSize(); - ASSERT(size >= 2 && size <= 4); - resultArray = new TConstantUnion(); - resultArray->setFConst(GetMatrix(operandArray, size).determinant()); - break; - } - - case EOpInverse: - { - ASSERT(getType().getBasicType() == EbtFloat); - unsigned int size = getType().getNominalSize(); - ASSERT(size >= 2 && size <= 4); - resultArray = new TConstantUnion[objectSize]; - angle::Matrix<float> result = GetMatrix(operandArray, size).inverse(); - SetUnionArrayFromMatrix(result, resultArray); - break; - } - - case EOpPackSnorm2x16: - ASSERT(getType().getBasicType() == EbtFloat); - ASSERT(getType().getNominalSize() == 2); - resultArray = new TConstantUnion(); - resultArray->setUConst( - gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); - break; - - case EOpUnpackSnorm2x16: - { - ASSERT(getType().getBasicType() == EbtUInt); - resultArray = new TConstantUnion[2]; - float f1, f2; - gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2); - resultArray[0].setFConst(f1); - resultArray[1].setFConst(f2); - break; - } - - case EOpPackUnorm2x16: - ASSERT(getType().getBasicType() == EbtFloat); - ASSERT(getType().getNominalSize() == 2); - resultArray = new TConstantUnion(); - resultArray->setUConst( - gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); - break; - - case EOpUnpackUnorm2x16: - { - ASSERT(getType().getBasicType() == EbtUInt); - resultArray = new TConstantUnion[2]; - float f1, f2; - gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2); - resultArray[0].setFConst(f1); - resultArray[1].setFConst(f2); - break; - } - - case EOpPackHalf2x16: - ASSERT(getType().getBasicType() == EbtFloat); - ASSERT(getType().getNominalSize() == 2); - resultArray = new TConstantUnion(); - resultArray->setUConst( - gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); - break; - - case EOpUnpackHalf2x16: - { - ASSERT(getType().getBasicType() == EbtUInt); - resultArray = new TConstantUnion[2]; - float f1, f2; - gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2); - resultArray[0].setFConst(f1); - resultArray[1].setFConst(f2); - break; - } - - case EOpPackUnorm4x8: - { - ASSERT(getType().getBasicType() == EbtFloat); - resultArray = new TConstantUnion(); - resultArray->setUConst( - gl::PackUnorm4x8(operandArray[0].getFConst(), operandArray[1].getFConst(), - operandArray[2].getFConst(), operandArray[3].getFConst())); - break; - } - case EOpPackSnorm4x8: - { - ASSERT(getType().getBasicType() == EbtFloat); - resultArray = new TConstantUnion(); - resultArray->setUConst( - gl::PackSnorm4x8(operandArray[0].getFConst(), operandArray[1].getFConst(), - operandArray[2].getFConst(), operandArray[3].getFConst())); - break; - } - case EOpUnpackUnorm4x8: - { - ASSERT(getType().getBasicType() == EbtUInt); - resultArray = new TConstantUnion[4]; - float f[4]; - gl::UnpackUnorm4x8(operandArray[0].getUConst(), f); - for (size_t i = 0; i < 4; ++i) - { - resultArray[i].setFConst(f[i]); - } - break; - } - case EOpUnpackSnorm4x8: - { - ASSERT(getType().getBasicType() == EbtUInt); - resultArray = new TConstantUnion[4]; - float f[4]; - gl::UnpackSnorm4x8(operandArray[0].getUConst(), f); - for (size_t i = 0; i < 4; ++i) - { - resultArray[i].setFConst(f[i]); - } - break; - } - - default: - UNREACHABLE(); - break; - } - - return resultArray; -} - -TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op, - TDiagnostics *diagnostics) -{ - // Do unary operations where each component of the result is computed based on the corresponding - // component of the operand. Also folds normalize, though the divisor in that case takes all - // components into account. - - const TConstantUnion *operandArray = getUnionArrayPointer(); - ASSERT(operandArray); - - size_t objectSize = getType().getObjectSize(); - - TConstantUnion *resultArray = new TConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - switch (op) - { - case EOpNegative: - switch (getType().getBasicType()) - { - case EbtFloat: - resultArray[i].setFConst(-operandArray[i].getFConst()); - break; - case EbtInt: - if (operandArray[i] == std::numeric_limits<int>::min()) - { - // The minimum representable integer doesn't have a positive - // counterpart, rather the negation overflows and in ESSL is supposed to - // wrap back to the minimum representable integer. Make sure that we - // don't actually let the negation overflow, which has undefined - // behavior in C++. - resultArray[i].setIConst(std::numeric_limits<int>::min()); - } - else - { - resultArray[i].setIConst(-operandArray[i].getIConst()); - } - break; - case EbtUInt: - if (operandArray[i] == 0x80000000u) - { - resultArray[i].setUConst(0x80000000u); - } - else - { - resultArray[i].setUConst(static_cast<unsigned int>( - -static_cast<int>(operandArray[i].getUConst()))); - } - break; - default: - UNREACHABLE(); - return nullptr; - } - break; - - case EOpPositive: - switch (getType().getBasicType()) - { - case EbtFloat: - resultArray[i].setFConst(operandArray[i].getFConst()); - break; - case EbtInt: - resultArray[i].setIConst(operandArray[i].getIConst()); - break; - case EbtUInt: - resultArray[i].setUConst(static_cast<unsigned int>( - static_cast<int>(operandArray[i].getUConst()))); - break; - default: - UNREACHABLE(); - return nullptr; - } - break; - - case EOpLogicalNot: - switch (getType().getBasicType()) - { - case EbtBool: - resultArray[i].setBConst(!operandArray[i].getBConst()); - break; - default: - UNREACHABLE(); - return nullptr; - } - break; - - case EOpBitwiseNot: - switch (getType().getBasicType()) - { - case EbtInt: - resultArray[i].setIConst(~operandArray[i].getIConst()); - break; - case EbtUInt: - resultArray[i].setUConst(~operandArray[i].getUConst()); - break; - default: - UNREACHABLE(); - return nullptr; - } - break; - - case EOpRadians: - ASSERT(getType().getBasicType() == EbtFloat); - resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst()); - break; - - case EOpDegrees: - ASSERT(getType().getBasicType() == EbtFloat); - resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst()); - break; - - case EOpSin: - foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]); - break; - - case EOpCos: - foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]); - break; - - case EOpTan: - foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]); - break; - - case EOpAsin: - // For asin(x), results are undefined if |x| > 1, we are choosing to set result to - // 0. - if (fabsf(operandArray[i].getFConst()) > 1.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]); - break; - - case EOpAcos: - // For acos(x), results are undefined if |x| > 1, we are choosing to set result to - // 0. - if (fabsf(operandArray[i].getFConst()) > 1.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]); - break; - - case EOpAtan: - foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]); - break; - - case EOpSinh: - foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]); - break; - - case EOpCosh: - foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]); - break; - - case EOpTanh: - foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]); - break; - - case EOpAsinh: - foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]); - break; - - case EOpAcosh: - // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0. - if (operandArray[i].getFConst() < 1.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]); - break; - - case EOpAtanh: - // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to - // 0. - if (fabsf(operandArray[i].getFConst()) >= 1.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]); - break; - - case EOpAbs: - switch (getType().getBasicType()) - { - case EbtFloat: - resultArray[i].setFConst(fabsf(operandArray[i].getFConst())); - break; - case EbtInt: - resultArray[i].setIConst(abs(operandArray[i].getIConst())); - break; - default: - UNREACHABLE(); - return nullptr; - } - break; - - case EOpSign: - switch (getType().getBasicType()) - { - case EbtFloat: - { - float fConst = operandArray[i].getFConst(); - float fResult = 0.0f; - if (fConst > 0.0f) - fResult = 1.0f; - else if (fConst < 0.0f) - fResult = -1.0f; - resultArray[i].setFConst(fResult); - break; - } - case EbtInt: - { - int iConst = operandArray[i].getIConst(); - int iResult = 0; - if (iConst > 0) - iResult = 1; - else if (iConst < 0) - iResult = -1; - resultArray[i].setIConst(iResult); - break; - } - default: - UNREACHABLE(); - return nullptr; - } - break; - - case EOpFloor: - foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]); - break; - - case EOpTrunc: - foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]); - break; - - case EOpRound: - foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]); - break; - - case EOpRoundEven: - { - ASSERT(getType().getBasicType() == EbtFloat); - float x = operandArray[i].getFConst(); - float result; - float fractPart = modff(x, &result); - if (fabsf(fractPart) == 0.5f) - result = 2.0f * roundf(x / 2.0f); - else - result = roundf(x); - resultArray[i].setFConst(result); - break; - } - - case EOpCeil: - foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]); - break; - - case EOpFract: - { - ASSERT(getType().getBasicType() == EbtFloat); - float x = operandArray[i].getFConst(); - resultArray[i].setFConst(x - floorf(x)); - break; - } - - case EOpIsNan: - ASSERT(getType().getBasicType() == EbtFloat); - resultArray[i].setBConst(gl::isNaN(operandArray[0].getFConst())); - break; - - case EOpIsInf: - ASSERT(getType().getBasicType() == EbtFloat); - resultArray[i].setBConst(gl::isInf(operandArray[0].getFConst())); - break; - - case EOpFloatBitsToInt: - ASSERT(getType().getBasicType() == EbtFloat); - resultArray[i].setIConst(gl::bitCast<int32_t>(operandArray[0].getFConst())); - break; - - case EOpFloatBitsToUint: - ASSERT(getType().getBasicType() == EbtFloat); - resultArray[i].setUConst(gl::bitCast<uint32_t>(operandArray[0].getFConst())); - break; - - case EOpIntBitsToFloat: - ASSERT(getType().getBasicType() == EbtInt); - resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getIConst())); - break; - - case EOpUintBitsToFloat: - ASSERT(getType().getBasicType() == EbtUInt); - resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getUConst())); - break; - - case EOpExp: - foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]); - break; - - case EOpLog: - // For log(x), results are undefined if x <= 0, we are choosing to set result to 0. - if (operandArray[i].getFConst() <= 0.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]); - break; - - case EOpExp2: - foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]); - break; - - case EOpLog2: - // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0. - // And log2f is not available on some plarforms like old android, so just using - // log(x)/log(2) here. - if (operandArray[i].getFConst() <= 0.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - { - foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]); - resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f)); - } - break; - - case EOpSqrt: - // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0. - if (operandArray[i].getFConst() < 0.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]); - break; - - case EOpInverseSqrt: - // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(), - // so getting the square root first using builtin function sqrt() and then taking - // its inverse. - // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set - // result to 0. - if (operandArray[i].getFConst() <= 0.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - { - foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]); - resultArray[i].setFConst(1.0f / resultArray[i].getFConst()); - } - break; - - case EOpLogicalNotComponentWise: - ASSERT(getType().getBasicType() == EbtBool); - resultArray[i].setBConst(!operandArray[i].getBConst()); - break; - - case EOpNormalize: - { - ASSERT(getType().getBasicType() == EbtFloat); - float x = operandArray[i].getFConst(); - float length = VectorLength(operandArray, objectSize); - if (length) - resultArray[i].setFConst(x / length); - else - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - break; - } - case EOpBitfieldReverse: - { - uint32_t value; - if (getType().getBasicType() == EbtInt) - { - value = static_cast<uint32_t>(operandArray[i].getIConst()); - } - else - { - ASSERT(getType().getBasicType() == EbtUInt); - value = operandArray[i].getUConst(); - } - uint32_t result = gl::BitfieldReverse(value); - if (getType().getBasicType() == EbtInt) - { - resultArray[i].setIConst(static_cast<int32_t>(result)); - } - else - { - resultArray[i].setUConst(result); - } - break; - } - case EOpBitCount: - { - uint32_t value; - if (getType().getBasicType() == EbtInt) - { - value = static_cast<uint32_t>(operandArray[i].getIConst()); - } - else - { - ASSERT(getType().getBasicType() == EbtUInt); - value = operandArray[i].getUConst(); - } - int result = gl::BitCount(value); - resultArray[i].setIConst(result); - break; - } - case EOpFindLSB: - { - uint32_t value; - if (getType().getBasicType() == EbtInt) - { - value = static_cast<uint32_t>(operandArray[i].getIConst()); - } - else - { - ASSERT(getType().getBasicType() == EbtUInt); - value = operandArray[i].getUConst(); - } - resultArray[i].setIConst(gl::FindLSB(value)); - break; - } - case EOpFindMSB: - { - uint32_t value; - if (getType().getBasicType() == EbtInt) - { - int intValue = operandArray[i].getIConst(); - value = static_cast<uint32_t>(intValue); - if (intValue < 0) - { - // Look for zero instead of one in value. This also handles the intValue == - // -1 special case, where the return value needs to be -1. - value = ~value; - } - } - else - { - ASSERT(getType().getBasicType() == EbtUInt); - value = operandArray[i].getUConst(); - } - resultArray[i].setIConst(gl::FindMSB(value)); - break; - } - case EOpDFdx: - case EOpDFdy: - case EOpFwidth: - ASSERT(getType().getBasicType() == EbtFloat); - // Derivatives of constant arguments should be 0. - resultArray[i].setFConst(0.0f); - break; - - default: - return nullptr; - } - } - - return resultArray; -} - -void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion ¶meter, - FloatTypeUnaryFunc builtinFunc, - TConstantUnion *result) const -{ - ASSERT(builtinFunc); - - ASSERT(getType().getBasicType() == EbtFloat); - result->setFConst(builtinFunc(parameter.getFConst())); -} - -// static -TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate) -{ - ASSERT(aggregate->getSequence()->size() > 0u); - size_t resultSize = aggregate->getType().getObjectSize(); - TConstantUnion *resultArray = new TConstantUnion[resultSize]; - TBasicType basicType = aggregate->getBasicType(); - - size_t resultIndex = 0u; - - if (aggregate->getSequence()->size() == 1u) - { - TIntermNode *argument = aggregate->getSequence()->front(); - TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion(); - const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer(); - // Check the special case of constructing a matrix diagonal from a single scalar, - // or a vector from a single scalar. - if (argumentConstant->getType().getObjectSize() == 1u) - { - if (aggregate->isMatrix()) - { - int resultCols = aggregate->getType().getCols(); - int resultRows = aggregate->getType().getRows(); - for (int col = 0; col < resultCols; ++col) - { - for (int row = 0; row < resultRows; ++row) - { - if (col == row) - { - resultArray[resultIndex].cast(basicType, argumentUnionArray[0]); - } - else - { - resultArray[resultIndex].setFConst(0.0f); - } - ++resultIndex; - } - } - } - else - { - while (resultIndex < resultSize) - { - resultArray[resultIndex].cast(basicType, argumentUnionArray[0]); - ++resultIndex; - } - } - ASSERT(resultIndex == resultSize); - return resultArray; - } - else if (aggregate->isMatrix() && argumentConstant->isMatrix()) - { - // The special case of constructing a matrix from a matrix. - int argumentCols = argumentConstant->getType().getCols(); - int argumentRows = argumentConstant->getType().getRows(); - int resultCols = aggregate->getType().getCols(); - int resultRows = aggregate->getType().getRows(); - for (int col = 0; col < resultCols; ++col) - { - for (int row = 0; row < resultRows; ++row) - { - if (col < argumentCols && row < argumentRows) - { - resultArray[resultIndex].cast(basicType, - argumentUnionArray[col * argumentRows + row]); - } - else if (col == row) - { - resultArray[resultIndex].setFConst(1.0f); - } - else - { - resultArray[resultIndex].setFConst(0.0f); - } - ++resultIndex; - } - } - ASSERT(resultIndex == resultSize); - return resultArray; - } - } - - for (TIntermNode *&argument : *aggregate->getSequence()) - { - TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion(); - size_t argumentSize = argumentConstant->getType().getObjectSize(); - const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer(); - for (size_t i = 0u; i < argumentSize; ++i) - { - if (resultIndex >= resultSize) - break; - resultArray[resultIndex].cast(basicType, argumentUnionArray[i]); - ++resultIndex; - } - } - ASSERT(resultIndex == resultSize); - return resultArray; -} - -bool TIntermAggregate::CanFoldAggregateBuiltInOp(TOperator op) -{ - switch (op) - { - case EOpAtan: - case EOpPow: - case EOpMod: - case EOpMin: - case EOpMax: - case EOpClamp: - case EOpMix: - case EOpStep: - case EOpSmoothStep: - case EOpLdexp: - case EOpMulMatrixComponentWise: - case EOpOuterProduct: - case EOpEqualComponentWise: - case EOpNotEqualComponentWise: - case EOpLessThanComponentWise: - case EOpLessThanEqualComponentWise: - case EOpGreaterThanComponentWise: - case EOpGreaterThanEqualComponentWise: - case EOpDistance: - case EOpDot: - case EOpCross: - case EOpFaceforward: - case EOpReflect: - case EOpRefract: - case EOpBitfieldExtract: - case EOpBitfieldInsert: - return true; - default: - return false; - } -} - -// static -TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate, - TDiagnostics *diagnostics) -{ - TOperator op = aggregate->getOp(); - TIntermSequence *arguments = aggregate->getSequence(); - unsigned int argsCount = static_cast<unsigned int>(arguments->size()); - std::vector<const TConstantUnion *> unionArrays(argsCount); - std::vector<size_t> objectSizes(argsCount); - size_t maxObjectSize = 0; - TBasicType basicType = EbtVoid; - TSourceLoc loc; - for (unsigned int i = 0; i < argsCount; i++) - { - TIntermConstantUnion *argConstant = (*arguments)[i]->getAsConstantUnion(); - ASSERT(argConstant != nullptr); // Should be checked already. - - if (i == 0) - { - basicType = argConstant->getType().getBasicType(); - loc = argConstant->getLine(); - } - unionArrays[i] = argConstant->getUnionArrayPointer(); - objectSizes[i] = argConstant->getType().getObjectSize(); - if (objectSizes[i] > maxObjectSize) - maxObjectSize = objectSizes[i]; - } - - if (!(*arguments)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct) - { - for (unsigned int i = 0; i < argsCount; i++) - if (objectSizes[i] != maxObjectSize) - unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize); - } - - TConstantUnion *resultArray = nullptr; - - switch (op) - { - case EOpAtan: - { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - float y = unionArrays[0][i].getFConst(); - float x = unionArrays[1][i].getFConst(); - // Results are undefined if x and y are both 0. - if (x == 0.0f && y == 0.0f) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]); - else - resultArray[i].setFConst(atan2f(y, x)); - } - break; - } - - case EOpPow: - { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - float x = unionArrays[0][i].getFConst(); - float y = unionArrays[1][i].getFConst(); - // Results are undefined if x < 0. - // Results are undefined if x = 0 and y <= 0. - if (x < 0.0f) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]); - else if (x == 0.0f && y <= 0.0f) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]); - else - resultArray[i].setFConst(powf(x, y)); - } - break; - } - - case EOpMod: - { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - float x = unionArrays[0][i].getFConst(); - float y = unionArrays[1][i].getFConst(); - resultArray[i].setFConst(x - y * floorf(x / y)); - } - break; - } - - case EOpMin: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setFConst( - std::min(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst())); - break; - case EbtInt: - resultArray[i].setIConst( - std::min(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst())); - break; - case EbtUInt: - resultArray[i].setUConst( - std::min(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst())); - break; - default: - UNREACHABLE(); - break; - } - } - break; - } - - case EOpMax: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setFConst( - std::max(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst())); - break; - case EbtInt: - resultArray[i].setIConst( - std::max(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst())); - break; - case EbtUInt: - resultArray[i].setUConst( - std::max(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst())); - break; - default: - UNREACHABLE(); - break; - } - } - break; - } - - case EOpStep: - { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - resultArray[i].setFConst( - unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f : 1.0f); - break; - } - - case EOpLessThanComponentWise: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() < - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() < - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() < - unionArrays[1][i].getUConst()); - break; - default: - UNREACHABLE(); - break; - } - } - break; - } - - case EOpLessThanEqualComponentWise: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() <= - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() <= - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() <= - unionArrays[1][i].getUConst()); - break; - default: - UNREACHABLE(); - break; - } - } - break; - } - - case EOpGreaterThanComponentWise: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() > - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() > - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() > - unionArrays[1][i].getUConst()); - break; - default: - UNREACHABLE(); - break; - } - } - break; - } - case EOpGreaterThanEqualComponentWise: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() >= - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() >= - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() >= - unionArrays[1][i].getUConst()); - break; - default: - UNREACHABLE(); - break; - } - } - } - break; - - case EOpEqualComponentWise: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() == - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() == - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() == - unionArrays[1][i].getUConst()); - break; - case EbtBool: - resultArray[i].setBConst(unionArrays[0][i].getBConst() == - unionArrays[1][i].getBConst()); - break; - default: - UNREACHABLE(); - break; - } - } - break; - } - - case EOpNotEqualComponentWise: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() != - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() != - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() != - unionArrays[1][i].getUConst()); - break; - case EbtBool: - resultArray[i].setBConst(unionArrays[0][i].getBConst() != - unionArrays[1][i].getBConst()); - break; - default: - UNREACHABLE(); - break; - } - } - break; - } - - case EOpDistance: - { - ASSERT(basicType == EbtFloat); - TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize]; - resultArray = new TConstantUnion(); - for (size_t i = 0; i < maxObjectSize; i++) - { - float x = unionArrays[0][i].getFConst(); - float y = unionArrays[1][i].getFConst(); - distanceArray[i].setFConst(x - y); - } - resultArray->setFConst(VectorLength(distanceArray, maxObjectSize)); - break; - } - - case EOpDot: - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion(); - resultArray->setFConst(VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize)); - break; - - case EOpCross: - { - ASSERT(basicType == EbtFloat && maxObjectSize == 3); - resultArray = new TConstantUnion[maxObjectSize]; - float x0 = unionArrays[0][0].getFConst(); - float x1 = unionArrays[0][1].getFConst(); - float x2 = unionArrays[0][2].getFConst(); - float y0 = unionArrays[1][0].getFConst(); - float y1 = unionArrays[1][1].getFConst(); - float y2 = unionArrays[1][2].getFConst(); - resultArray[0].setFConst(x1 * y2 - y1 * x2); - resultArray[1].setFConst(x2 * y0 - y2 * x0); - resultArray[2].setFConst(x0 * y1 - y0 * x1); - break; - } - - case EOpReflect: - { - ASSERT(basicType == EbtFloat); - // genType reflect (genType I, genType N) : - // For the incident vector I and surface orientation N, returns the reflection - // direction: - // I - 2 * dot(N, I) * N. - resultArray = new TConstantUnion[maxObjectSize]; - float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize); - for (size_t i = 0; i < maxObjectSize; i++) - { - float result = unionArrays[0][i].getFConst() - - 2.0f * dotProduct * unionArrays[1][i].getFConst(); - resultArray[i].setFConst(result); - } - break; - } - - case EOpMulMatrixComponentWise: - { - ASSERT(basicType == EbtFloat && (*arguments)[0]->getAsTyped()->isMatrix() && - (*arguments)[1]->getAsTyped()->isMatrix()); - // Perform component-wise matrix multiplication. - resultArray = new TConstantUnion[maxObjectSize]; - int size = (*arguments)[0]->getAsTyped()->getNominalSize(); - angle::Matrix<float> result = - GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size)); - SetUnionArrayFromMatrix(result, resultArray); - break; - } - - case EOpOuterProduct: - { - ASSERT(basicType == EbtFloat); - size_t numRows = (*arguments)[0]->getAsTyped()->getType().getObjectSize(); - size_t numCols = (*arguments)[1]->getAsTyped()->getType().getObjectSize(); - resultArray = new TConstantUnion[numRows * numCols]; - angle::Matrix<float> result = - GetMatrix(unionArrays[0], static_cast<int>(numRows), 1) - .outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols))); - SetUnionArrayFromMatrix(result, resultArray); - break; - } - - case EOpClamp: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - switch (basicType) - { - case EbtFloat: - { - float x = unionArrays[0][i].getFConst(); - float min = unionArrays[1][i].getFConst(); - float max = unionArrays[2][i].getFConst(); - // Results are undefined if min > max. - if (min > max) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, - &resultArray[i]); - else - resultArray[i].setFConst(gl::clamp(x, min, max)); - break; - } - - case EbtInt: - { - int x = unionArrays[0][i].getIConst(); - int min = unionArrays[1][i].getIConst(); - int max = unionArrays[2][i].getIConst(); - // Results are undefined if min > max. - if (min > max) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, - &resultArray[i]); - else - resultArray[i].setIConst(gl::clamp(x, min, max)); - break; - } - case EbtUInt: - { - unsigned int x = unionArrays[0][i].getUConst(); - unsigned int min = unionArrays[1][i].getUConst(); - unsigned int max = unionArrays[2][i].getUConst(); - // Results are undefined if min > max. - if (min > max) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, - &resultArray[i]); - else - resultArray[i].setUConst(gl::clamp(x, min, max)); - break; - } - default: - UNREACHABLE(); - break; - } - } - break; - } - - case EOpMix: - { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - float x = unionArrays[0][i].getFConst(); - float y = unionArrays[1][i].getFConst(); - TBasicType type = (*arguments)[2]->getAsTyped()->getType().getBasicType(); - if (type == EbtFloat) - { - // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a. - float a = unionArrays[2][i].getFConst(); - resultArray[i].setFConst(x * (1.0f - a) + y * a); - } - else // 3rd parameter is EbtBool - { - ASSERT(type == EbtBool); - // Selects which vector each returned component comes from. - // For a component of a that is false, the corresponding component of x is - // returned. - // For a component of a that is true, the corresponding component of y is - // returned. - bool a = unionArrays[2][i].getBConst(); - resultArray[i].setFConst(a ? y : x); - } - } - break; - } - - case EOpSmoothStep: - { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - float edge0 = unionArrays[0][i].getFConst(); - float edge1 = unionArrays[1][i].getFConst(); - float x = unionArrays[2][i].getFConst(); - // Results are undefined if edge0 >= edge1. - if (edge0 >= edge1) - { - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]); - } - else - { - // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth - // Hermite interpolation between 0 and 1 when edge0 < x < edge1. - float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f); - resultArray[i].setFConst(t * t * (3.0f - 2.0f * t)); - } - } - break; - } - - case EOpLdexp: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - { - float x = unionArrays[0][i].getFConst(); - int exp = unionArrays[1][i].getIConst(); - if (exp > 128) - { - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]); - } - else - { - resultArray[i].setFConst(gl::Ldexp(x, exp)); - } - } - break; - } - - case EOpFaceforward: - { - ASSERT(basicType == EbtFloat); - // genType faceforward(genType N, genType I, genType Nref) : - // If dot(Nref, I) < 0 return N, otherwise return -N. - resultArray = new TConstantUnion[maxObjectSize]; - float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize); - for (size_t i = 0; i < maxObjectSize; i++) - { - if (dotProduct < 0) - resultArray[i].setFConst(unionArrays[0][i].getFConst()); - else - resultArray[i].setFConst(-unionArrays[0][i].getFConst()); - } - break; - } - - case EOpRefract: - { - ASSERT(basicType == EbtFloat); - // genType refract(genType I, genType N, float eta) : - // For the incident vector I and surface normal N, and the ratio of indices of - // refraction eta, - // return the refraction vector. The result is computed by - // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) - // if (k < 0.0) - // return genType(0.0) - // else - // return eta * I - (eta * dot(N, I) + sqrt(k)) * N - resultArray = new TConstantUnion[maxObjectSize]; - float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize); - for (size_t i = 0; i < maxObjectSize; i++) - { - float eta = unionArrays[2][i].getFConst(); - float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct); - if (k < 0.0f) - resultArray[i].setFConst(0.0f); - else - resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() - - (eta * dotProduct + sqrtf(k)) * - unionArrays[1][i].getFConst()); - } - break; - } - case EOpBitfieldExtract: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; ++i) - { - int offset = unionArrays[1][0].getIConst(); - int bits = unionArrays[2][0].getIConst(); - if (bits == 0) - { - if (aggregate->getBasicType() == EbtInt) - { - resultArray[i].setIConst(0); - } - else - { - ASSERT(aggregate->getBasicType() == EbtUInt); - resultArray[i].setUConst(0); - } - } - else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32) - { - UndefinedConstantFoldingError(loc, op, aggregate->getBasicType(), diagnostics, - &resultArray[i]); - } - else - { - // bits can be 32 here, so we need to avoid bit shift overflow. - uint32_t maskMsb = 1u << (bits - 1); - uint32_t mask = ((maskMsb - 1u) | maskMsb) << offset; - if (aggregate->getBasicType() == EbtInt) - { - uint32_t value = static_cast<uint32_t>(unionArrays[0][i].getIConst()); - uint32_t resultUnsigned = (value & mask) >> offset; - if ((resultUnsigned & maskMsb) != 0) - { - // The most significant bits (from bits+1 to the most significant bit) - // should be set to 1. - uint32_t higherBitsMask = ((1u << (32 - bits)) - 1u) << bits; - resultUnsigned |= higherBitsMask; - } - resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned)); - } - else - { - ASSERT(aggregate->getBasicType() == EbtUInt); - uint32_t value = unionArrays[0][i].getUConst(); - resultArray[i].setUConst((value & mask) >> offset); - } - } - } - break; - } - case EOpBitfieldInsert: - { - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; ++i) - { - int offset = unionArrays[2][0].getIConst(); - int bits = unionArrays[3][0].getIConst(); - if (bits == 0) - { - if (aggregate->getBasicType() == EbtInt) - { - int32_t base = unionArrays[0][i].getIConst(); - resultArray[i].setIConst(base); - } - else - { - ASSERT(aggregate->getBasicType() == EbtUInt); - uint32_t base = unionArrays[0][i].getUConst(); - resultArray[i].setUConst(base); - } - } - else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32) - { - UndefinedConstantFoldingError(loc, op, aggregate->getBasicType(), diagnostics, - &resultArray[i]); - } - else - { - // bits can be 32 here, so we need to avoid bit shift overflow. - uint32_t maskMsb = 1u << (bits - 1); - uint32_t insertMask = ((maskMsb - 1u) | maskMsb) << offset; - uint32_t baseMask = ~insertMask; - if (aggregate->getBasicType() == EbtInt) - { - uint32_t base = static_cast<uint32_t>(unionArrays[0][i].getIConst()); - uint32_t insert = static_cast<uint32_t>(unionArrays[1][i].getIConst()); - uint32_t resultUnsigned = - (base & baseMask) | ((insert << offset) & insertMask); - resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned)); - } - else - { - ASSERT(aggregate->getBasicType() == EbtUInt); - uint32_t base = unionArrays[0][i].getUConst(); - uint32_t insert = unionArrays[1][i].getUConst(); - resultArray[i].setUConst((base & baseMask) | - ((insert << offset) & insertMask)); - } - } - } - break; - } - - default: - UNREACHABLE(); - return nullptr; - } - return resultArray; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.h b/src/3rdparty/angle/src/compiler/translator/IntermNode.h deleted file mode 100644 index 2170916201..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode.h +++ /dev/null @@ -1,917 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// Definition of the in-memory high-level intermediate representation -// of shaders. This is a tree that parser creates. -// -// Nodes in the tree are defined as a hierarchy of classes derived from -// TIntermNode. Each is a node in a tree. There is no preset branching factor; -// each node can have it's own type of list of children. -// - -#ifndef COMPILER_TRANSLATOR_INTERMNODE_H_ -#define COMPILER_TRANSLATOR_INTERMNODE_H_ - -#include "GLSLANG/ShaderLang.h" - -#include <algorithm> -#include <queue> - -#include "common/angleutils.h" -#include "compiler/translator/Common.h" -#include "compiler/translator/ConstantUnion.h" -#include "compiler/translator/Operator.h" -#include "compiler/translator/SymbolUniqueId.h" -#include "compiler/translator/Types.h" - -namespace sh -{ - -class TDiagnostics; - -class TIntermTraverser; -class TIntermAggregate; -class TIntermBlock; -class TIntermInvariantDeclaration; -class TIntermDeclaration; -class TIntermFunctionPrototype; -class TIntermFunctionDefinition; -class TIntermSwizzle; -class TIntermBinary; -class TIntermUnary; -class TIntermConstantUnion; -class TIntermTernary; -class TIntermIfElse; -class TIntermSwitch; -class TIntermCase; -class TIntermTyped; -class TIntermSymbol; -class TIntermLoop; -class TInfoSink; -class TInfoSinkBase; -class TIntermRaw; -class TIntermBranch; - -class TSymbolTable; -class TFunction; - -// Encapsulate an identifier string and track whether it is coming from the original shader code -// (not internal) or from ANGLE (internal). Usually internal names shouldn't be decorated or hashed. -class TName -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - explicit TName(const TString &name) : mName(name), mIsInternal(false) {} - TName() : mName(), mIsInternal(false) {} - TName(const TName &) = default; - TName &operator=(const TName &) = default; - - const TString &getString() const { return mName; } - void setString(const TString &string) { mName = string; } - bool isInternal() const { return mIsInternal; } - void setInternal(bool isInternal) { mIsInternal = isInternal; } - - private: - TString mName; - bool mIsInternal; -}; - -// -// Base class for the tree nodes -// -class TIntermNode : angle::NonCopyable -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TIntermNode() - { - // TODO: Move this to TSourceLoc constructor - // after getting rid of TPublicType. - mLine.first_file = mLine.last_file = 0; - mLine.first_line = mLine.last_line = 0; - } - virtual ~TIntermNode() {} - - const TSourceLoc &getLine() const { return mLine; } - void setLine(const TSourceLoc &l) { mLine = l; } - - virtual void traverse(TIntermTraverser *) = 0; - virtual TIntermTyped *getAsTyped() { return 0; } - virtual TIntermConstantUnion *getAsConstantUnion() { return 0; } - virtual TIntermFunctionDefinition *getAsFunctionDefinition() { return nullptr; } - virtual TIntermAggregate *getAsAggregate() { return 0; } - virtual TIntermBlock *getAsBlock() { return nullptr; } - virtual TIntermFunctionPrototype *getAsFunctionPrototypeNode() { return nullptr; } - virtual TIntermInvariantDeclaration *getAsInvariantDeclarationNode() { return nullptr; } - virtual TIntermDeclaration *getAsDeclarationNode() { return nullptr; } - virtual TIntermSwizzle *getAsSwizzleNode() { return nullptr; } - virtual TIntermBinary *getAsBinaryNode() { return 0; } - virtual TIntermUnary *getAsUnaryNode() { return 0; } - virtual TIntermTernary *getAsTernaryNode() { return nullptr; } - virtual TIntermIfElse *getAsIfElseNode() { return nullptr; } - virtual TIntermSwitch *getAsSwitchNode() { return 0; } - virtual TIntermCase *getAsCaseNode() { return 0; } - virtual TIntermSymbol *getAsSymbolNode() { return 0; } - virtual TIntermLoop *getAsLoopNode() { return 0; } - virtual TIntermRaw *getAsRawNode() { return 0; } - virtual TIntermBranch *getAsBranchNode() { return 0; } - - // Replace a child node. Return true if |original| is a child - // node and it is replaced; otherwise, return false. - virtual bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) = 0; - - protected: - TSourceLoc mLine; -}; - -// -// This is just to help yacc. -// -struct TIntermNodePair -{ - TIntermNode *node1; - TIntermNode *node2; -}; - -// -// Intermediate class for nodes that have a type. -// -class TIntermTyped : public TIntermNode -{ - public: - TIntermTyped(const TType &t) : mType(t) {} - - virtual TIntermTyped *deepCopy() const = 0; - - TIntermTyped *getAsTyped() override { return this; } - - // True if executing the expression represented by this node affects state, like values of - // variables. False if the executing the expression only computes its return value without - // affecting state. May return true conservatively. - virtual bool hasSideEffects() const = 0; - - void setType(const TType &t) { mType = t; } - void setTypePreservePrecision(const TType &t); - const TType &getType() const { return mType; } - TType *getTypePointer() { return &mType; } - - TBasicType getBasicType() const { return mType.getBasicType(); } - TQualifier getQualifier() const { return mType.getQualifier(); } - TPrecision getPrecision() const { return mType.getPrecision(); } - TMemoryQualifier getMemoryQualifier() const { return mType.getMemoryQualifier(); } - int getCols() const { return mType.getCols(); } - int getRows() const { return mType.getRows(); } - int getNominalSize() const { return mType.getNominalSize(); } - int getSecondarySize() const { return mType.getSecondarySize(); } - - bool isInterfaceBlock() const { return mType.isInterfaceBlock(); } - bool isMatrix() const { return mType.isMatrix(); } - bool isArray() const { return mType.isArray(); } - bool isVector() const { return mType.isVector(); } - bool isScalar() const { return mType.isScalar(); } - bool isScalarInt() const { return mType.isScalarInt(); } - const char *getBasicString() const { return mType.getBasicString(); } - TString getCompleteString() const { return mType.getCompleteString(); } - - unsigned int getOutermostArraySize() const { return mType.getOutermostArraySize(); } - - bool isConstructorWithOnlyConstantUnionParameters(); - - protected: - TType mType; - - TIntermTyped(const TIntermTyped &node); -}; - -// -// Handle for, do-while, and while loops. -// -enum TLoopType -{ - ELoopFor, - ELoopWhile, - ELoopDoWhile -}; - -class TIntermLoop : public TIntermNode -{ - public: - TIntermLoop(TLoopType type, - TIntermNode *init, - TIntermTyped *cond, - TIntermTyped *expr, - TIntermBlock *body); - - TIntermLoop *getAsLoopNode() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TLoopType getType() const { return mType; } - TIntermNode *getInit() { return mInit; } - TIntermTyped *getCondition() { return mCond; } - TIntermTyped *getExpression() { return mExpr; } - TIntermBlock *getBody() { return mBody; } - - void setInit(TIntermNode *init) { mInit = init; } - void setCondition(TIntermTyped *condition) { mCond = condition; } - void setExpression(TIntermTyped *expression) { mExpr = expression; } - void setBody(TIntermBlock *body) { mBody = body; } - - protected: - TLoopType mType; - TIntermNode *mInit; // for-loop initialization - TIntermTyped *mCond; // loop exit condition - TIntermTyped *mExpr; // for-loop expression - TIntermBlock *mBody; // loop body -}; - -// -// Handle break, continue, return, and kill. -// -class TIntermBranch : public TIntermNode -{ - public: - TIntermBranch(TOperator op, TIntermTyped *e) : mFlowOp(op), mExpression(e) {} - - void traverse(TIntermTraverser *it) override; - TIntermBranch *getAsBranchNode() override { return this; } - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TOperator getFlowOp() { return mFlowOp; } - TIntermTyped *getExpression() { return mExpression; } - - protected: - TOperator mFlowOp; - TIntermTyped *mExpression; // non-zero except for "return exp;" statements -}; - -// -// Nodes that correspond to symbols or constants in the source code. -// -class TIntermSymbol : public TIntermTyped -{ - public: - // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. - // If sym comes from per process globalpoolallocator, then it causes increased memory usage - // per compile it is essential to use "symbol = sym" to assign to symbol - TIntermSymbol(const TSymbolUniqueId &id, const TString &symbol, const TType &type) - : TIntermTyped(type), mId(id), mSymbol(symbol) - { - } - - TIntermTyped *deepCopy() const override { return new TIntermSymbol(*this); } - - bool hasSideEffects() const override { return false; } - - int getId() const { return mId.get(); } - const TString &getSymbol() const { return mSymbol.getString(); } - const TName &getName() const { return mSymbol; } - TName &getName() { return mSymbol; } - - void setInternal(bool internal) { mSymbol.setInternal(internal); } - - void traverse(TIntermTraverser *it) override; - TIntermSymbol *getAsSymbolNode() override { return this; } - bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; } - - protected: - const TSymbolUniqueId mId; - TName mSymbol; - - private: - TIntermSymbol(const TIntermSymbol &) = default; // Note: not deleted, just private! -}; - -// A Raw node stores raw code, that the translator will insert verbatim -// into the output stream. Useful for transformation operations that make -// complex code that might not fit naturally into the GLSL model. -class TIntermRaw : public TIntermTyped -{ - public: - TIntermRaw(const TType &type, const TString &rawText) : TIntermTyped(type), mRawText(rawText) {} - TIntermRaw(const TIntermRaw &) = delete; - - TIntermTyped *deepCopy() const override - { - UNREACHABLE(); - return nullptr; - } - - bool hasSideEffects() const override { return false; } - - TString getRawText() const { return mRawText; } - - void traverse(TIntermTraverser *it) override; - - TIntermRaw *getAsRawNode() override { return this; } - bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; } - - protected: - TString mRawText; -}; - -// Constant folded node. -// Note that nodes may be constant folded and not be constant expressions with the EvqConst -// qualifier. This happens for example when the following expression is processed: -// "true ? 1.0 : non_constant" -// Other nodes than TIntermConstantUnion may also be constant expressions. -// -class TIntermConstantUnion : public TIntermTyped -{ - public: - TIntermConstantUnion(const TConstantUnion *unionPointer, const TType &type) - : TIntermTyped(type), mUnionArrayPointer(unionPointer) - { - ASSERT(unionPointer); - } - - TIntermTyped *deepCopy() const override { return new TIntermConstantUnion(*this); } - - bool hasSideEffects() const override { return false; } - - const TConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; } - - int getIConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0; - } - unsigned int getUConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0; - } - float getFConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f; - } - bool getBConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false; - } - - void replaceConstantUnion(const TConstantUnion *safeConstantUnion) - { - ASSERT(safeConstantUnion); - // Previous union pointer freed on pool deallocation. - mUnionArrayPointer = safeConstantUnion; - } - - TIntermConstantUnion *getAsConstantUnion() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; } - - TConstantUnion *foldBinary(TOperator op, - TIntermConstantUnion *rightNode, - TDiagnostics *diagnostics, - const TSourceLoc &line); - const TConstantUnion *foldIndexing(int index); - TConstantUnion *foldUnaryNonComponentWise(TOperator op); - TConstantUnion *foldUnaryComponentWise(TOperator op, TDiagnostics *diagnostics); - - static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate); - static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate, - TDiagnostics *diagnostics); - - protected: - // Same data may be shared between multiple constant unions, so it can't be modified. - const TConstantUnion *mUnionArrayPointer; - - private: - typedef float (*FloatTypeUnaryFunc)(float); - void foldFloatTypeUnary(const TConstantUnion ¶meter, - FloatTypeUnaryFunc builtinFunc, - TConstantUnion *result) const; - - TIntermConstantUnion(const TIntermConstantUnion &node); // Note: not deleted, just private! -}; - -// -// Intermediate class for node types that hold operators. -// -class TIntermOperator : public TIntermTyped -{ - public: - TOperator getOp() const { return mOp; } - - bool isAssignment() const; - bool isMultiplication() const; - bool isConstructor() const; - - // Returns true for calls mapped to EOpCall*, false for built-ins that have their own specific - // ops. - bool isFunctionCall() const; - - bool hasSideEffects() const override { return isAssignment(); } - - protected: - TIntermOperator(TOperator op) : TIntermTyped(TType(EbtFloat, EbpUndefined)), mOp(op) {} - TIntermOperator(TOperator op, const TType &type) : TIntermTyped(type), mOp(op) {} - - TIntermOperator(const TIntermOperator &) = default; - - const TOperator mOp; -}; - -// Node for vector swizzles. -class TIntermSwizzle : public TIntermTyped -{ - public: - // This constructor determines the type of the node based on the operand. - TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets); - - TIntermTyped *deepCopy() const override { return new TIntermSwizzle(*this); } - - TIntermSwizzle *getAsSwizzleNode() override { return this; }; - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - bool hasSideEffects() const override { return mOperand->hasSideEffects(); } - - TIntermTyped *getOperand() { return mOperand; } - void writeOffsetsAsXYZW(TInfoSinkBase *out) const; - - bool hasDuplicateOffsets() const; - bool offsetsMatch(int offset) const; - - TIntermTyped *fold(); - - protected: - TIntermTyped *mOperand; - TVector<int> mSwizzleOffsets; - - private: - void promote(); - - TIntermSwizzle(const TIntermSwizzle &node); // Note: not deleted, just private! -}; - -// -// Nodes for all the basic binary math operators. -// -class TIntermBinary : public TIntermOperator -{ - public: - // This constructor determines the type of the binary node based on the operands and op. - TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right); - - TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); } - - static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right); - static TOperator GetMulAssignOpBasedOnOperands(const TType &left, const TType &right); - static TQualifier GetCommaQualifier(int shaderVersion, - const TIntermTyped *left, - const TIntermTyped *right); - - TIntermBinary *getAsBinaryNode() override { return this; }; - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - bool hasSideEffects() const override - { - return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects(); - } - - TIntermTyped *getLeft() const { return mLeft; } - TIntermTyped *getRight() const { return mRight; } - TIntermTyped *fold(TDiagnostics *diagnostics); - - void setAddIndexClamp() { mAddIndexClamp = true; } - bool getAddIndexClamp() { return mAddIndexClamp; } - - protected: - TIntermTyped *mLeft; - TIntermTyped *mRight; - - // If set to true, wrap any EOpIndexIndirect with a clamp to bounds. - bool mAddIndexClamp; - - private: - void promote(); - - TIntermBinary(const TIntermBinary &node); // Note: not deleted, just private! -}; - -// -// Nodes for unary math operators. -// -class TIntermUnary : public TIntermOperator -{ - public: - TIntermUnary(TOperator op, TIntermTyped *operand); - - TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); } - - void traverse(TIntermTraverser *it) override; - TIntermUnary *getAsUnaryNode() override { return this; } - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); } - - TIntermTyped *getOperand() { return mOperand; } - TIntermTyped *fold(TDiagnostics *diagnostics); - - void setUseEmulatedFunction() { mUseEmulatedFunction = true; } - bool getUseEmulatedFunction() { return mUseEmulatedFunction; } - - protected: - TIntermTyped *mOperand; - - // If set to true, replace the built-in function call with an emulated one - // to work around driver bugs. - bool mUseEmulatedFunction; - - private: - void promote(); - - TIntermUnary(const TIntermUnary &node); // note: not deleted, just private! -}; - -class TFunctionSymbolInfo -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TFunctionSymbolInfo(const TSymbolUniqueId &id); - TFunctionSymbolInfo() : mId(nullptr), mKnownToNotHaveSideEffects(false) {} - - TFunctionSymbolInfo(const TFunctionSymbolInfo &info); - TFunctionSymbolInfo &operator=(const TFunctionSymbolInfo &info); - - void setFromFunction(const TFunction &function); - - void setNameObj(const TName &name) { mName = name; } - const TName &getNameObj() const { return mName; } - - const TString &getName() const { return mName.getString(); } - void setName(const TString &name) { mName.setString(name); } - bool isMain() const { return mName.getString() == "main"; } - - void setKnownToNotHaveSideEffects(bool knownToNotHaveSideEffects) - { - mKnownToNotHaveSideEffects = knownToNotHaveSideEffects; - } - bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; } - - void setId(const TSymbolUniqueId &functionId); - const TSymbolUniqueId &getId() const; - - bool isImageFunction() const - { - return getName() == "imageSize" || getName() == "imageLoad" || getName() == "imageStore"; - } - - private: - TName mName; - TSymbolUniqueId *mId; - bool mKnownToNotHaveSideEffects; -}; - -typedef TVector<TIntermNode *> TIntermSequence; -typedef TVector<int> TQualifierList; - -// -// This is just to help yacc. -// -struct TIntermFunctionCallOrMethod -{ - TIntermSequence *arguments; - TIntermNode *thisNode; -}; - -// Interface for node classes that have an arbitrarily sized set of children. -class TIntermAggregateBase -{ - public: - virtual ~TIntermAggregateBase() {} - - virtual TIntermSequence *getSequence() = 0; - virtual const TIntermSequence *getSequence() const = 0; - - bool replaceChildNodeWithMultiple(TIntermNode *original, const TIntermSequence &replacements); - bool insertChildNodes(TIntermSequence::size_type position, const TIntermSequence &insertions); - - protected: - TIntermAggregateBase() {} - - bool replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement); -}; - -// -// Nodes that operate on an arbitrary sized set of children. -// -class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase -{ - public: - static TIntermAggregate *CreateFunctionCall(const TFunction &func, TIntermSequence *arguments); - - // If using this, ensure that there's a consistent function definition with the same symbol id - // added to the AST. - static TIntermAggregate *CreateFunctionCall(const TType &type, - const TSymbolUniqueId &id, - const TName &name, - TIntermSequence *arguments); - - static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func, - TIntermSequence *arguments); - static TIntermAggregate *CreateConstructor(const TType &type, - TIntermSequence *arguments); - static TIntermAggregate *Create(const TType &type, TOperator op, TIntermSequence *arguments); - ~TIntermAggregate() {} - - // Note: only supported for nodes that can be a part of an expression. - TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); } - - TIntermAggregate *shallowCopy() const; - - TIntermAggregate *getAsAggregate() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - bool hasSideEffects() const override; - - static bool CanFoldAggregateBuiltInOp(TOperator op); - TIntermTyped *fold(TDiagnostics *diagnostics); - - TIntermSequence *getSequence() override { return &mArguments; } - const TIntermSequence *getSequence() const override { return &mArguments; } - - TString getSymbolTableMangledName() const; - - void setUseEmulatedFunction() { mUseEmulatedFunction = true; } - bool getUseEmulatedFunction() { return mUseEmulatedFunction; } - - // Returns true if changing parameter precision may affect the return value. - bool gotPrecisionFromChildren() const { return mGotPrecisionFromChildren; } - - TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; } - const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; } - - protected: - TIntermSequence mArguments; - - // If set to true, replace the built-in function call with an emulated one - // to work around driver bugs. Only for calls mapped to ops other than EOpCall*. - bool mUseEmulatedFunction; - - bool mGotPrecisionFromChildren; - - TFunctionSymbolInfo mFunctionInfo; - - private: - TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments); - - TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private! - - void setTypePrecisionAndQualifier(const TType &type); - - bool areChildrenConstQualified(); - - void setPrecisionFromChildren(); - - void setPrecisionForBuiltInOp(); - - // Returns true if precision was set according to special rules for this built-in. - bool setPrecisionForSpecialBuiltInOp(); - - // Used for built-in functions under EOpCallBuiltInFunction. The function name in the symbol - // info needs to be set before calling this. - void setBuiltInFunctionPrecision(); -}; - -// A list of statements. Either the root node which contains declarations and function definitions, -// or a block that can be marked with curly braces {}. -class TIntermBlock : public TIntermNode, public TIntermAggregateBase -{ - public: - TIntermBlock() : TIntermNode() {} - ~TIntermBlock() {} - - TIntermBlock *getAsBlock() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - // Only intended for initially building the block. - void appendStatement(TIntermNode *statement); - - TIntermSequence *getSequence() override { return &mStatements; } - const TIntermSequence *getSequence() const override { return &mStatements; } - - protected: - TIntermSequence mStatements; -}; - -// Function prototype. May be in the AST either as a function prototype declaration or as a part of -// a function definition. The type of the node is the function return type. -class TIntermFunctionPrototype : public TIntermTyped, public TIntermAggregateBase -{ - public: - // TODO(oetuaho@nvidia.com): See if TFunctionSymbolInfo could be added to constructor - // parameters. - TIntermFunctionPrototype(const TType &type, const TSymbolUniqueId &id) - : TIntermTyped(type), mFunctionInfo(id) - { - } - ~TIntermFunctionPrototype() {} - - TIntermFunctionPrototype *getAsFunctionPrototypeNode() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TIntermTyped *deepCopy() const override - { - UNREACHABLE(); - return nullptr; - } - bool hasSideEffects() const override - { - UNREACHABLE(); - return true; - } - - // Only intended for initially building the declaration. - void appendParameter(TIntermSymbol *parameter); - - TIntermSequence *getSequence() override { return &mParameters; } - const TIntermSequence *getSequence() const override { return &mParameters; } - - TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; } - const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; } - - protected: - TIntermSequence mParameters; - - TFunctionSymbolInfo mFunctionInfo; -}; - -// Node for function definitions. The prototype child node stores the function header including -// parameters, and the body child node stores the function body. -class TIntermFunctionDefinition : public TIntermNode -{ - public: - TIntermFunctionDefinition(TIntermFunctionPrototype *prototype, TIntermBlock *body) - : TIntermNode(), mPrototype(prototype), mBody(body) - { - ASSERT(prototype != nullptr); - ASSERT(body != nullptr); - } - - TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TIntermFunctionPrototype *getFunctionPrototype() const { return mPrototype; } - TIntermBlock *getBody() const { return mBody; } - - const TFunctionSymbolInfo *getFunctionSymbolInfo() const - { - return mPrototype->getFunctionSymbolInfo(); - } - - private: - TIntermFunctionPrototype *mPrototype; - TIntermBlock *mBody; -}; - -// Struct, interface block or variable declaration. Can contain multiple variable declarators. -class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase -{ - public: - TIntermDeclaration() : TIntermNode() {} - ~TIntermDeclaration() {} - - TIntermDeclaration *getAsDeclarationNode() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - // Only intended for initially building the declaration. - // The declarator node should be either TIntermSymbol or TIntermBinary with op set to - // EOpInitialize. - void appendDeclarator(TIntermTyped *declarator); - - TIntermSequence *getSequence() override { return &mDeclarators; } - const TIntermSequence *getSequence() const override { return &mDeclarators; } - protected: - TIntermSequence mDeclarators; -}; - -// Specialized declarations for attributing invariance. -class TIntermInvariantDeclaration : public TIntermNode -{ - public: - TIntermInvariantDeclaration(TIntermSymbol *symbol, const TSourceLoc &line); - - virtual TIntermInvariantDeclaration *getAsInvariantDeclarationNode() override { return this; } - - TIntermSymbol *getSymbol() { return mSymbol; } - - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - private: - TIntermSymbol *mSymbol; -}; - -// For ternary operators like a ? b : c. -class TIntermTernary : public TIntermTyped -{ - public: - TIntermTernary(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression); - - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TIntermTyped *getCondition() const { return mCondition; } - TIntermTyped *getTrueExpression() const { return mTrueExpression; } - TIntermTyped *getFalseExpression() const { return mFalseExpression; } - TIntermTernary *getAsTernaryNode() override { return this; } - - TIntermTyped *deepCopy() const override { return new TIntermTernary(*this); } - - bool hasSideEffects() const override - { - return mCondition->hasSideEffects() || mTrueExpression->hasSideEffects() || - mFalseExpression->hasSideEffects(); - } - - TIntermTyped *fold(); - - private: - TIntermTernary(const TIntermTernary &node); // Note: not deleted, just private! - - static TQualifier DetermineQualifier(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression); - - TIntermTyped *mCondition; - TIntermTyped *mTrueExpression; - TIntermTyped *mFalseExpression; -}; - -class TIntermIfElse : public TIntermNode -{ - public: - TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB); - - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TIntermTyped *getCondition() const { return mCondition; } - TIntermBlock *getTrueBlock() const { return mTrueBlock; } - TIntermBlock *getFalseBlock() const { return mFalseBlock; } - TIntermIfElse *getAsIfElseNode() override { return this; } - - protected: - TIntermTyped *mCondition; - TIntermBlock *mTrueBlock; - TIntermBlock *mFalseBlock; -}; - -// -// Switch statement. -// -class TIntermSwitch : public TIntermNode -{ - public: - TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList); - - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TIntermSwitch *getAsSwitchNode() override { return this; } - - TIntermTyped *getInit() { return mInit; } - TIntermBlock *getStatementList() { return mStatementList; } - - // Must be called with a non-null statementList. - void setStatementList(TIntermBlock *statementList); - - protected: - TIntermTyped *mInit; - TIntermBlock *mStatementList; -}; - -// -// Case label. -// -class TIntermCase : public TIntermNode -{ - public: - TIntermCase(TIntermTyped *condition) : TIntermNode(), mCondition(condition) {} - - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TIntermCase *getAsCaseNode() override { return this; } - - bool hasCondition() const { return mCondition != nullptr; } - TIntermTyped *getCondition() const { return mCondition; } - - protected: - TIntermTyped *mCondition; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INTERMNODE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp deleted file mode 100644 index 567e8f7440..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp +++ /dev/null @@ -1,157 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// IntermNodePatternMatcher is a helper class for matching node trees to given patterns. -// It can be used whenever the same checks for certain node structures are common to multiple AST -// traversers. -// - -#include "compiler/translator/IntermNodePatternMatcher.h" - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask) -{ -} - -// static -bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node) -{ - return node->getOp() == EOpIndexIndirect && !node->getLeft()->isArray() && - node->getLeft()->getBasicType() != EbtStruct; -} - -bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode) -{ - if ((mMask & kExpressionReturningArray) != 0) - { - if (node->isArray() && node->getOp() == EOpAssign && parentNode != nullptr && - !parentNode->getAsBlock()) - { - return true; - } - } - - if ((mMask & kUnfoldedShortCircuitExpression) != 0) - { - if (node->getRight()->hasSideEffects() && - (node->getOp() == EOpLogicalOr || node->getOp() == EOpLogicalAnd)) - { - return true; - } - } - return false; -} - -bool IntermNodePatternMatcher::match(TIntermUnary *node) -{ - if ((mMask & kArrayLengthMethod) != 0) - { - if (node->getOp() == EOpArrayLength) - { - return true; - } - } - return false; -} - -bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode) -{ - // L-value tracking information is needed to check for dynamic indexing in L-value. - // Traversers that don't track l-values can still use this class and match binary nodes with - // this variation of this method if they don't need to check for dynamic indexing in l-values. - ASSERT((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) == 0); - return matchInternal(node, parentNode); -} - -bool IntermNodePatternMatcher::match(TIntermBinary *node, - TIntermNode *parentNode, - bool isLValueRequiredHere) -{ - if (matchInternal(node, parentNode)) - { - return true; - } - if ((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) != 0) - { - if (isLValueRequiredHere && IsDynamicIndexingOfVectorOrMatrix(node)) - { - return true; - } - } - return false; -} - -bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode) -{ - if ((mMask & kExpressionReturningArray) != 0) - { - if (parentNode != nullptr) - { - TIntermBinary *parentBinary = parentNode->getAsBinaryNode(); - bool parentIsAssignment = - (parentBinary != nullptr && - (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize)); - - if (node->getType().isArray() && !parentIsAssignment && - (node->isConstructor() || node->isFunctionCall()) && !parentNode->getAsBlock()) - { - return true; - } - } - } - return false; -} - -bool IntermNodePatternMatcher::match(TIntermTernary *node) -{ - if ((mMask & kUnfoldedShortCircuitExpression) != 0) - { - return true; - } - return false; -} - -bool IntermNodePatternMatcher::match(TIntermDeclaration *node) -{ - if ((mMask & kMultiDeclaration) != 0) - { - if (node->getSequence()->size() > 1) - { - return true; - } - } - if ((mMask & kArrayDeclaration) != 0) - { - if (node->getSequence()->front()->getAsTyped()->getType().isStructureContainingArrays()) - { - return true; - } - // Need to check from all declarators whether they are arrays since that may vary between - // declarators. - for (TIntermNode *declarator : *node->getSequence()) - { - if (declarator->getAsTyped()->isArray()) - { - return true; - } - } - } - if ((mMask & kNamelessStructDeclaration) != 0) - { - TIntermTyped *declarator = node->getSequence()->front()->getAsTyped(); - if (declarator->getBasicType() == EbtStruct && - declarator->getType().getStruct()->name() == "") - { - return true; - } - } - return false; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h b/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h deleted file mode 100644 index 997fc2ef10..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// IntermNodePatternMatcher is a helper class for matching node trees to given patterns. -// It can be used whenever the same checks for certain node structures are common to multiple AST -// traversers. -// - -#ifndef COMPILER_TRANSLATOR_INTERMNODEPATTERNMATCHER_H_ -#define COMPILER_TRANSLATOR_INTERMNODEPATTERNMATCHER_H_ - -namespace sh -{ - -class TIntermAggregate; -class TIntermBinary; -class TIntermDeclaration; -class TIntermNode; -class TIntermTernary; -class TIntermUnary; - -class IntermNodePatternMatcher -{ - public: - static bool IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node); - - enum PatternType - { - // Matches expressions that are unfolded to if statements by UnfoldShortCircuitToIf - kUnfoldedShortCircuitExpression = 0x0001, - - // Matches expressions that return arrays with the exception of simple statements where a - // constructor or function call result is assigned. - kExpressionReturningArray = 0x0001 << 1, - - // Matches dynamic indexing of vectors or matrices in l-values. - kDynamicIndexingOfVectorOrMatrixInLValue = 0x0001 << 2, - - // Matches declarations with more than one declared variables. - kMultiDeclaration = 0x0001 << 3, - - // Matches declarations of arrays. - kArrayDeclaration = 0x0001 << 4, - - // Matches declarations of structs where the struct type does not have a name. - kNamelessStructDeclaration = 0x0001 << 5, - - // Matches array length() method. - kArrayLengthMethod = 0x0001 << 6 - }; - IntermNodePatternMatcher(const unsigned int mask); - - bool match(TIntermUnary *node); - - bool match(TIntermBinary *node, TIntermNode *parentNode); - - // Use this version for checking binary node matches in case you're using flag - // kDynamicIndexingOfVectorOrMatrixInLValue. - bool match(TIntermBinary *node, TIntermNode *parentNode, bool isLValueRequiredHere); - - bool match(TIntermAggregate *node, TIntermNode *parentNode); - bool match(TIntermTernary *node); - bool match(TIntermDeclaration *node); - - private: - const unsigned int mMask; - - bool matchInternal(TIntermBinary *node, TIntermNode *parentNode); -}; - -} // namespace sh - -#endif diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp deleted file mode 100644 index 9f1f596c43..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp +++ /dev/null @@ -1,254 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// IntermNode_util.cpp: High-level utilities for creating AST nodes and node hierarchies. Mostly -// meant to be used in AST transforms. - -#include "compiler/translator/IntermNode_util.h" - -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -TName GetInternalFunctionName(const char *name) -{ - TString nameStr(name); - TName nameObj(nameStr); - nameObj.setInternal(true); - return nameObj; -} - -const TFunction *LookUpBuiltInFunction(const TString &name, - const TIntermSequence *arguments, - const TSymbolTable &symbolTable, - int shaderVersion) -{ - TString mangledName = TFunction::GetMangledNameFromCall(name, *arguments); - TSymbol *symbol = symbolTable.findBuiltIn(mangledName, shaderVersion); - if (symbol) - { - ASSERT(symbol->isFunction()); - return static_cast<const TFunction *>(symbol); - } - return nullptr; -} - -} // anonymous namespace - -TIntermFunctionPrototype *CreateInternalFunctionPrototypeNode(const TType &returnType, - const char *name, - const TSymbolUniqueId &functionId) -{ - TIntermFunctionPrototype *functionNode = new TIntermFunctionPrototype(returnType, functionId); - functionNode->getFunctionSymbolInfo()->setNameObj(GetInternalFunctionName(name)); - return functionNode; -} - -TIntermFunctionDefinition *CreateInternalFunctionDefinitionNode(const TType &returnType, - const char *name, - TIntermBlock *functionBody, - const TSymbolUniqueId &functionId) -{ - TIntermFunctionPrototype *prototypeNode = - CreateInternalFunctionPrototypeNode(returnType, name, functionId); - return new TIntermFunctionDefinition(prototypeNode, functionBody); -} - -TIntermAggregate *CreateInternalFunctionCallNode(const TType &returnType, - const char *name, - const TSymbolUniqueId &functionId, - TIntermSequence *arguments) -{ - TIntermAggregate *functionNode = TIntermAggregate::CreateFunctionCall( - returnType, functionId, GetInternalFunctionName(name), arguments); - return functionNode; -} - -TIntermTyped *CreateZeroNode(const TType &type) -{ - TType constType(type); - constType.setQualifier(EvqConst); - - if (!type.isArray() && type.getBasicType() != EbtStruct) - { - size_t size = constType.getObjectSize(); - TConstantUnion *u = new TConstantUnion[size]; - for (size_t i = 0; i < size; ++i) - { - switch (type.getBasicType()) - { - case EbtFloat: - u[i].setFConst(0.0f); - break; - case EbtInt: - u[i].setIConst(0); - break; - case EbtUInt: - u[i].setUConst(0u); - break; - case EbtBool: - u[i].setBConst(false); - break; - default: - // CreateZeroNode is called by ParseContext that keeps parsing even when an - // error occurs, so it is possible for CreateZeroNode to be called with - // non-basic types. This happens only on error condition but CreateZeroNode - // needs to return a value with the correct type to continue the typecheck. - // That's why we handle non-basic type by setting whatever value, we just need - // the type to be right. - u[i].setIConst(42); - break; - } - } - - TIntermConstantUnion *node = new TIntermConstantUnion(u, constType); - return node; - } - - if (type.getBasicType() == EbtVoid) - { - // Void array. This happens only on error condition, similarly to the case above. We don't - // have a constructor operator for void, so this needs special handling. We'll end up with a - // value without the array type, but that should not be a problem. - while (constType.isArray()) - { - constType.toArrayElementType(); - } - return CreateZeroNode(constType); - } - - TIntermSequence *arguments = new TIntermSequence(); - - if (type.isArray()) - { - TType elementType(type); - elementType.toArrayElementType(); - - size_t arraySize = type.getOutermostArraySize(); - for (size_t i = 0; i < arraySize; ++i) - { - arguments->push_back(CreateZeroNode(elementType)); - } - } - else - { - ASSERT(type.getBasicType() == EbtStruct); - - const TStructure *structure = type.getStruct(); - for (const auto &field : structure->fields()) - { - arguments->push_back(CreateZeroNode(*field->type())); - } - } - - return TIntermAggregate::CreateConstructor(constType, arguments); -} - -TIntermConstantUnion *CreateIndexNode(int index) -{ - TConstantUnion *u = new TConstantUnion[1]; - u[0].setIConst(index); - - TType type(EbtInt, EbpUndefined, EvqConst, 1); - TIntermConstantUnion *node = new TIntermConstantUnion(u, type); - return node; -} - -TIntermConstantUnion *CreateBoolNode(bool value) -{ - TConstantUnion *u = new TConstantUnion[1]; - u[0].setBConst(value); - - TType type(EbtBool, EbpUndefined, EvqConst, 1); - TIntermConstantUnion *node = new TIntermConstantUnion(u, type); - return node; -} - -TIntermSymbol *CreateTempSymbolNode(const TSymbolUniqueId &id, - const TType &type, - TQualifier qualifier) -{ - TInfoSinkBase symbolNameOut; - symbolNameOut << "s" << id.get(); - TString symbolName = symbolNameOut.c_str(); - - TIntermSymbol *node = new TIntermSymbol(id, symbolName, type); - node->setInternal(true); - - ASSERT(qualifier == EvqTemporary || qualifier == EvqConst || qualifier == EvqGlobal); - node->getTypePointer()->setQualifier(qualifier); - - // TODO(oetuaho): Might be useful to sanitize layout qualifier etc. on the type of the created - // symbol. This might need to be done in other places as well. - return node; -} - -TIntermDeclaration *CreateTempInitDeclarationNode(const TSymbolUniqueId &id, - TIntermTyped *initializer, - TQualifier qualifier) -{ - ASSERT(initializer != nullptr); - TIntermSymbol *tempSymbol = CreateTempSymbolNode(id, initializer->getType(), qualifier); - TIntermDeclaration *tempDeclaration = new TIntermDeclaration(); - TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer); - tempDeclaration->appendDeclarator(tempInit); - return tempDeclaration; -} - -TIntermBlock *EnsureBlock(TIntermNode *node) -{ - if (node == nullptr) - return nullptr; - TIntermBlock *blockNode = node->getAsBlock(); - if (blockNode != nullptr) - return blockNode; - - blockNode = new TIntermBlock(); - blockNode->setLine(node->getLine()); - blockNode->appendStatement(node); - return blockNode; -} - -TIntermSymbol *ReferenceGlobalVariable(const TString &name, const TSymbolTable &symbolTable) -{ - TVariable *var = reinterpret_cast<TVariable *>(symbolTable.findGlobal(name)); - ASSERT(var); - return new TIntermSymbol(var->getUniqueId(), name, var->getType()); -} - -TIntermSymbol *ReferenceBuiltInVariable(const TString &name, - const TSymbolTable &symbolTable, - int shaderVersion) -{ - const TVariable *var = - reinterpret_cast<const TVariable *>(symbolTable.findBuiltIn(name, shaderVersion, true)); - ASSERT(var); - return new TIntermSymbol(var->getUniqueId(), name, var->getType()); -} - -TIntermTyped *CreateBuiltInFunctionCallNode(const TString &name, - TIntermSequence *arguments, - const TSymbolTable &symbolTable, - int shaderVersion) -{ - const TFunction *fn = LookUpBuiltInFunction(name, arguments, symbolTable, shaderVersion); - ASSERT(fn); - TOperator op = fn->getBuiltInOp(); - if (op != EOpNull) - { - if (arguments->size() == 1) - { - return new TIntermUnary(op, arguments->at(0)->getAsTyped()); - } - return TIntermAggregate::Create(fn->getReturnType(), op, arguments); - } - return TIntermAggregate::CreateBuiltInFunctionCall(*fn, arguments); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode_util.h b/src/3rdparty/angle/src/compiler/translator/IntermNode_util.h deleted file mode 100644 index 6f3b0674f0..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode_util.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// IntermNode_util.h: High-level utilities for creating AST nodes and node hierarchies. Mostly meant -// to be used in AST transforms. - -#ifndef COMPILER_TRANSLATOR_INTERMNODEUTIL_H_ -#define COMPILER_TRANSLATOR_INTERMNODEUTIL_H_ - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -TIntermFunctionPrototype *CreateInternalFunctionPrototypeNode(const TType &returnType, - const char *name, - const TSymbolUniqueId &functionId); -TIntermFunctionDefinition *CreateInternalFunctionDefinitionNode(const TType &returnType, - const char *name, - TIntermBlock *functionBody, - const TSymbolUniqueId &functionId); -TIntermAggregate *CreateInternalFunctionCallNode(const TType &returnType, - const char *name, - const TSymbolUniqueId &functionId, - TIntermSequence *arguments); - -TIntermTyped *CreateZeroNode(const TType &type); -TIntermConstantUnion *CreateIndexNode(int index); -TIntermConstantUnion *CreateBoolNode(bool value); - -TIntermSymbol *CreateTempSymbolNode(const TSymbolUniqueId &id, - const TType &type, - TQualifier qualifier); -TIntermDeclaration *CreateTempInitDeclarationNode(const TSymbolUniqueId &id, - TIntermTyped *initializer, - TQualifier qualifier); - -// If the input node is nullptr, return nullptr. -// If the input node is a block node, return it. -// If the input node is not a block node, put it inside a block node and return that. -TIntermBlock *EnsureBlock(TIntermNode *node); - -// Should be called from inside Compiler::compileTreeImpl() where the global level is in scope. -TIntermSymbol *ReferenceGlobalVariable(const TString &name, const TSymbolTable &symbolTable); - -// Note: this can access desktop GLSL built-ins that are hidden from the parser. -TIntermSymbol *ReferenceBuiltInVariable(const TString &name, - const TSymbolTable &symbolTable, - int shaderVersion); - -TIntermTyped *CreateBuiltInFunctionCallNode(const TString &name, - TIntermSequence *arguments, - const TSymbolTable &symbolTable, - int shaderVersion); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INTERMNODEUTIL_H_
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp deleted file mode 100644 index 6c25c6c35a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp +++ /dev/null @@ -1,983 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/IntermTraverse.h" - -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -void TIntermSymbol::traverse(TIntermTraverser *it) -{ - it->traverseSymbol(this); -} - -void TIntermRaw::traverse(TIntermTraverser *it) -{ - it->traverseRaw(this); -} - -void TIntermConstantUnion::traverse(TIntermTraverser *it) -{ - it->traverseConstantUnion(this); -} - -void TIntermSwizzle::traverse(TIntermTraverser *it) -{ - it->traverseSwizzle(this); -} - -void TIntermBinary::traverse(TIntermTraverser *it) -{ - it->traverseBinary(this); -} - -void TIntermUnary::traverse(TIntermTraverser *it) -{ - it->traverseUnary(this); -} - -void TIntermTernary::traverse(TIntermTraverser *it) -{ - it->traverseTernary(this); -} - -void TIntermIfElse::traverse(TIntermTraverser *it) -{ - it->traverseIfElse(this); -} - -void TIntermSwitch::traverse(TIntermTraverser *it) -{ - it->traverseSwitch(this); -} - -void TIntermCase::traverse(TIntermTraverser *it) -{ - it->traverseCase(this); -} - -void TIntermFunctionDefinition::traverse(TIntermTraverser *it) -{ - it->traverseFunctionDefinition(this); -} - -void TIntermBlock::traverse(TIntermTraverser *it) -{ - it->traverseBlock(this); -} - -void TIntermInvariantDeclaration::traverse(TIntermTraverser *it) -{ - it->traverseInvariantDeclaration(this); -} - -void TIntermDeclaration::traverse(TIntermTraverser *it) -{ - it->traverseDeclaration(this); -} - -void TIntermFunctionPrototype::traverse(TIntermTraverser *it) -{ - it->traverseFunctionPrototype(this); -} - -void TIntermAggregate::traverse(TIntermTraverser *it) -{ - it->traverseAggregate(this); -} - -void TIntermLoop::traverse(TIntermTraverser *it) -{ - it->traverseLoop(this); -} - -void TIntermBranch::traverse(TIntermTraverser *it) -{ - it->traverseBranch(this); -} - -TIntermTraverser::TIntermTraverser(bool preVisit, - bool inVisit, - bool postVisit, - TSymbolTable *symbolTable) - : preVisit(preVisit), - inVisit(inVisit), - postVisit(postVisit), - mDepth(-1), - mMaxDepth(0), - mInGlobalScope(true), - mSymbolTable(symbolTable), - mTemporaryId(nullptr) -{ -} - -TIntermTraverser::~TIntermTraverser() -{ -} - -const TIntermBlock *TIntermTraverser::getParentBlock() const -{ - if (!mParentBlockStack.empty()) - { - return mParentBlockStack.back().node; - } - return nullptr; -} - -void TIntermTraverser::pushParentBlock(TIntermBlock *node) -{ - mParentBlockStack.push_back(ParentBlock(node, 0)); -} - -void TIntermTraverser::incrementParentBlockPos() -{ - ++mParentBlockStack.back().pos; -} - -void TIntermTraverser::popParentBlock() -{ - ASSERT(!mParentBlockStack.empty()); - mParentBlockStack.pop_back(); -} - -void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions) -{ - TIntermSequence emptyInsertionsAfter; - insertStatementsInParentBlock(insertions, emptyInsertionsAfter); -} - -void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore, - const TIntermSequence &insertionsAfter) -{ - ASSERT(!mParentBlockStack.empty()); - ParentBlock &parentBlock = mParentBlockStack.back(); - if (mPath.back() == parentBlock.node) - { - ASSERT(mParentBlockStack.size() >= 2u); - // The current node is a block node, so the parent block is not the topmost one in the block - // stack, but the one below that. - parentBlock = mParentBlockStack.at(mParentBlockStack.size() - 2u); - } - NodeInsertMultipleEntry insert(parentBlock.node, parentBlock.pos, insertionsBefore, - insertionsAfter); - mInsertions.push_back(insert); -} - -void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement) -{ - TIntermSequence insertions; - insertions.push_back(statement); - insertStatementsInParentBlock(insertions); -} - -TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier) -{ - ASSERT(mTemporaryId != nullptr); - // nextTemporaryId() needs to be called when the code wants to start using another temporary - // symbol. - return CreateTempSymbolNode(*mTemporaryId, type, qualifier); -} - -TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type) -{ - return createTempSymbol(type, EvqTemporary); -} - -TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type) -{ - ASSERT(mTemporaryId != nullptr); - TIntermDeclaration *tempDeclaration = new TIntermDeclaration(); - tempDeclaration->appendDeclarator(CreateTempSymbolNode(*mTemporaryId, type, EvqTemporary)); - return tempDeclaration; -} - -TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, - TQualifier qualifier) -{ - ASSERT(mTemporaryId != nullptr); - return CreateTempInitDeclarationNode(*mTemporaryId, initializer, qualifier); -} - -TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer) -{ - return createTempInitDeclaration(initializer, EvqTemporary); -} - -TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode) -{ - ASSERT(rightNode != nullptr); - TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType()); - TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode); - return assignment; -} - -void TIntermTraverser::nextTemporaryId() -{ - ASSERT(mSymbolTable); - if (!mTemporaryId) - { - mTemporaryId = new TSymbolUniqueId(mSymbolTable); - return; - } - *mTemporaryId = TSymbolUniqueId(mSymbolTable); -} - -void TLValueTrackingTraverser::addToFunctionMap(const TSymbolUniqueId &id, - TIntermSequence *paramSequence) -{ - mFunctionMap[id.get()] = paramSequence; -} - -bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const -{ - ASSERT(callNode->getOp() == EOpCallFunctionInAST); - return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getId().get()) != - mFunctionMap.end()); -} - -TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode) -{ - ASSERT(isInFunctionMap(callNode)); - return mFunctionMap[callNode->getFunctionSymbolInfo()->getId().get()]; -} - -void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter) -{ - mInFunctionCallOutParameter = inOutParameter; -} - -bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const -{ - return mInFunctionCallOutParameter; -} - -// -// Traverse the intermediate representation tree, and -// call a node type specific function for each node. -// Done recursively through the member function Traverse(). -// Node types can be skipped if their function to call is 0, -// but their subtree will still be traversed. -// Nodes with children can have their whole subtree skipped -// if preVisit is turned on and the type specific function -// returns false. -// - -// -// Traversal functions for terminals are straighforward.... -// -void TIntermTraverser::traverseSymbol(TIntermSymbol *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - visitSymbol(node); -} - -void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - visitConstantUnion(node); -} - -void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitSwizzle(PreVisit, node); - - if (visit) - { - node->getOperand()->traverse(this); - } - - if (visit && postVisit) - visitSwizzle(PostVisit, node); -} - -// -// Traverse a binary node. -// -void TIntermTraverser::traverseBinary(TIntermBinary *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - // - // visit the node before children if pre-visiting. - // - if (preVisit) - visit = visitBinary(PreVisit, node); - - // - // Visit the children, in the right order. - // - if (visit) - { - if (node->getLeft()) - node->getLeft()->traverse(this); - - if (inVisit) - visit = visitBinary(InVisit, node); - - if (visit && node->getRight()) - node->getRight()->traverse(this); - } - - // - // Visit the node after the children, if requested and the traversal - // hasn't been cancelled yet. - // - if (visit && postVisit) - visitBinary(PostVisit, node); -} - -void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - // - // visit the node before children if pre-visiting. - // - if (preVisit) - visit = visitBinary(PreVisit, node); - - // - // Visit the children, in the right order. - // - if (visit) - { - // Some binary operations like indexing can be inside an expression which must be an - // l-value. - bool parentOperatorRequiresLValue = operatorRequiresLValue(); - bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter(); - if (node->isAssignment()) - { - ASSERT(!isLValueRequiredHere()); - setOperatorRequiresLValue(true); - } - - if (node->getLeft()) - node->getLeft()->traverse(this); - - if (inVisit) - visit = visitBinary(InVisit, node); - - if (node->isAssignment()) - setOperatorRequiresLValue(false); - - // Index is not required to be an l-value even when the surrounding expression is required - // to be an l-value. - TOperator op = node->getOp(); - if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock || - op == EOpIndexDirectStruct || op == EOpIndexIndirect) - { - setOperatorRequiresLValue(false); - setInFunctionCallOutParameter(false); - } - - if (visit && node->getRight()) - node->getRight()->traverse(this); - - setOperatorRequiresLValue(parentOperatorRequiresLValue); - setInFunctionCallOutParameter(parentInFunctionCallOutParameter); - } - - // - // Visit the node after the children, if requested and the traversal - // hasn't been cancelled yet. - // - if (visit && postVisit) - visitBinary(PostVisit, node); -} - -// -// Traverse a unary node. Same comments in binary node apply here. -// -void TIntermTraverser::traverseUnary(TIntermUnary *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitUnary(PreVisit, node); - - if (visit) - { - node->getOperand()->traverse(this); - } - - if (visit && postVisit) - visitUnary(PostVisit, node); -} - -void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitUnary(PreVisit, node); - - if (visit) - { - ASSERT(!operatorRequiresLValue()); - switch (node->getOp()) - { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - setOperatorRequiresLValue(true); - break; - default: - break; - } - - node->getOperand()->traverse(this); - - setOperatorRequiresLValue(false); - } - - if (visit && postVisit) - visitUnary(PostVisit, node); -} - -// Traverse a function definition node. -void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitFunctionDefinition(PreVisit, node); - - if (visit) - { - mInGlobalScope = false; - - node->getFunctionPrototype()->traverse(this); - if (inVisit) - visit = visitFunctionDefinition(InVisit, node); - node->getBody()->traverse(this); - - mInGlobalScope = true; - } - - if (visit && postVisit) - visitFunctionDefinition(PostVisit, node); -} - -// Traverse a block node. -void TIntermTraverser::traverseBlock(TIntermBlock *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - pushParentBlock(node); - - bool visit = true; - - TIntermSequence *sequence = node->getSequence(); - - if (preVisit) - visit = visitBlock(PreVisit, node); - - if (visit) - { - for (auto *child : *sequence) - { - child->traverse(this); - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitBlock(InVisit, node); - } - - incrementParentBlockPos(); - } - } - - if (visit && postVisit) - visitBlock(PostVisit, node); - - popParentBlock(); -} - -void TIntermTraverser::traverseInvariantDeclaration(TIntermInvariantDeclaration *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - { - visit = visitInvariantDeclaration(PreVisit, node); - } - - if (visit) - { - node->getSymbol()->traverse(this); - if (postVisit) - { - visitInvariantDeclaration(PostVisit, node); - } - } -} - -// Traverse a declaration node. -void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - TIntermSequence *sequence = node->getSequence(); - - if (preVisit) - visit = visitDeclaration(PreVisit, node); - - if (visit) - { - for (auto *child : *sequence) - { - child->traverse(this); - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitDeclaration(InVisit, node); - } - } - } - - if (visit && postVisit) - visitDeclaration(PostVisit, node); -} - -void TIntermTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - TIntermSequence *sequence = node->getSequence(); - - if (preVisit) - visit = visitFunctionPrototype(PreVisit, node); - - if (visit) - { - for (auto *child : *sequence) - { - child->traverse(this); - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitFunctionPrototype(InVisit, node); - } - } - } - - if (visit && postVisit) - visitFunctionPrototype(PostVisit, node); -} - -// Traverse an aggregate node. Same comments in binary node apply here. -void TIntermTraverser::traverseAggregate(TIntermAggregate *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - TIntermSequence *sequence = node->getSequence(); - - if (preVisit) - visit = visitAggregate(PreVisit, node); - - if (visit) - { - for (auto *child : *sequence) - { - child->traverse(this); - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitAggregate(InVisit, node); - } - } - } - - if (visit && postVisit) - visitAggregate(PostVisit, node); -} - -bool TIntermTraverser::CompareInsertion(const NodeInsertMultipleEntry &a, - const NodeInsertMultipleEntry &b) -{ - if (a.parent != b.parent) - { - return a.parent > b.parent; - } - return a.position > b.position; -} - -void TIntermTraverser::updateTree() -{ - // Sort the insertions so that insertion position is decreasing. This way multiple insertions to - // the same parent node are handled correctly. - std::sort(mInsertions.begin(), mInsertions.end(), CompareInsertion); - for (size_t ii = 0; ii < mInsertions.size(); ++ii) - { - // We can't know here what the intended ordering of two insertions to the same position is, - // so it is not supported. - ASSERT(ii == 0 || mInsertions[ii].position != mInsertions[ii - 1].position || - mInsertions[ii].parent != mInsertions[ii - 1].parent); - const NodeInsertMultipleEntry &insertion = mInsertions[ii]; - ASSERT(insertion.parent); - if (!insertion.insertionsAfter.empty()) - { - bool inserted = insertion.parent->insertChildNodes(insertion.position + 1, - insertion.insertionsAfter); - ASSERT(inserted); - } - if (!insertion.insertionsBefore.empty()) - { - bool inserted = - insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore); - ASSERT(inserted); - } - } - for (size_t ii = 0; ii < mReplacements.size(); ++ii) - { - const NodeUpdateEntry &replacement = mReplacements[ii]; - ASSERT(replacement.parent); - bool replaced = - replacement.parent->replaceChildNode(replacement.original, replacement.replacement); - ASSERT(replaced); - - if (!replacement.originalBecomesChildOfReplacement) - { - // In AST traversing, a parent is visited before its children. - // After we replace a node, if its immediate child is to - // be replaced, we need to make sure we don't update the replaced - // node; instead, we update the replacement node. - for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj) - { - NodeUpdateEntry &replacement2 = mReplacements[jj]; - if (replacement2.parent == replacement.original) - replacement2.parent = replacement.replacement; - } - } - } - for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii) - { - const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii]; - ASSERT(replacement.parent); - bool replaced = replacement.parent->replaceChildNodeWithMultiple(replacement.original, - replacement.replacements); - ASSERT(replaced); - } - - clearReplacementQueue(); -} - -void TIntermTraverser::clearReplacementQueue() -{ - mReplacements.clear(); - mMultiReplacements.clear(); - mInsertions.clear(); -} - -void TIntermTraverser::queueReplacement(TIntermNode *replacement, OriginalNode originalStatus) -{ - queueReplacementWithParent(getParentNode(), mPath.back(), replacement, originalStatus); -} - -void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent, - TIntermNode *original, - TIntermNode *replacement, - OriginalNode originalStatus) -{ - bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD); - mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild)); -} - -TLValueTrackingTraverser::TLValueTrackingTraverser(bool preVisit, - bool inVisit, - bool postVisit, - TSymbolTable *symbolTable, - int shaderVersion) - : TIntermTraverser(preVisit, inVisit, postVisit, symbolTable), - mOperatorRequiresLValue(false), - mInFunctionCallOutParameter(false), - mShaderVersion(shaderVersion) -{ - ASSERT(symbolTable); -} - -void TLValueTrackingTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node) -{ - TIntermSequence *sequence = node->getSequence(); - addToFunctionMap(node->getFunctionSymbolInfo()->getId(), sequence); - - TIntermTraverser::traverseFunctionPrototype(node); -} - -void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - TIntermSequence *sequence = node->getSequence(); - - if (preVisit) - visit = visitAggregate(PreVisit, node); - - if (visit) - { - if (node->getOp() == EOpCallFunctionInAST) - { - if (isInFunctionMap(node)) - { - TIntermSequence *params = getFunctionParameters(node); - TIntermSequence::iterator paramIter = params->begin(); - for (auto *child : *sequence) - { - ASSERT(paramIter != params->end()); - TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier(); - setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut); - - child->traverse(this); - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitAggregate(InVisit, node); - } - - ++paramIter; - } - } - else - { - // The node might not be in the function map in case we're in the middle of - // transforming the AST, and have inserted function call nodes without inserting the - // function definitions yet. - setInFunctionCallOutParameter(false); - for (auto *child : *sequence) - { - child->traverse(this); - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitAggregate(InVisit, node); - } - } - } - - setInFunctionCallOutParameter(false); - } - else - { - // Find the built-in function corresponding to this op so that we can determine the - // in/out qualifiers of its parameters. - TFunction *builtInFunc = nullptr; - if (!node->isFunctionCall() && !node->isConstructor()) - { - builtInFunc = static_cast<TFunction *>( - mSymbolTable->findBuiltIn(node->getSymbolTableMangledName(), mShaderVersion)); - } - - size_t paramIndex = 0; - - for (auto *child : *sequence) - { - // This assumes that raw functions called with - // EOpCallInternalRawFunction don't have out parameters. - TQualifier qualifier = EvqIn; - if (builtInFunc != nullptr) - qualifier = builtInFunc->getParam(paramIndex).type->getQualifier(); - setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut); - child->traverse(this); - - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitAggregate(InVisit, node); - } - - ++paramIndex; - } - - setInFunctionCallOutParameter(false); - } - } - - if (visit && postVisit) - visitAggregate(PostVisit, node); -} - -// -// Traverse a ternary node. Same comments in binary node apply here. -// -void TIntermTraverser::traverseTernary(TIntermTernary *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitTernary(PreVisit, node); - - if (visit) - { - node->getCondition()->traverse(this); - if (node->getTrueExpression()) - node->getTrueExpression()->traverse(this); - if (node->getFalseExpression()) - node->getFalseExpression()->traverse(this); - } - - if (visit && postVisit) - visitTernary(PostVisit, node); -} - -// Traverse an if-else node. Same comments in binary node apply here. -void TIntermTraverser::traverseIfElse(TIntermIfElse *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitIfElse(PreVisit, node); - - if (visit) - { - node->getCondition()->traverse(this); - if (node->getTrueBlock()) - node->getTrueBlock()->traverse(this); - if (node->getFalseBlock()) - node->getFalseBlock()->traverse(this); - } - - if (visit && postVisit) - visitIfElse(PostVisit, node); -} - -// -// Traverse a switch node. Same comments in binary node apply here. -// -void TIntermTraverser::traverseSwitch(TIntermSwitch *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitSwitch(PreVisit, node); - - if (visit) - { - node->getInit()->traverse(this); - if (inVisit) - visit = visitSwitch(InVisit, node); - if (visit && node->getStatementList()) - node->getStatementList()->traverse(this); - } - - if (visit && postVisit) - visitSwitch(PostVisit, node); -} - -// -// Traverse a case node. Same comments in binary node apply here. -// -void TIntermTraverser::traverseCase(TIntermCase *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitCase(PreVisit, node); - - if (visit && node->getCondition()) - { - node->getCondition()->traverse(this); - } - - if (visit && postVisit) - visitCase(PostVisit, node); -} - -// -// Traverse a loop node. Same comments in binary node apply here. -// -void TIntermTraverser::traverseLoop(TIntermLoop *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitLoop(PreVisit, node); - - if (visit) - { - if (node->getInit()) - node->getInit()->traverse(this); - - if (node->getCondition()) - node->getCondition()->traverse(this); - - if (node->getBody()) - node->getBody()->traverse(this); - - if (node->getExpression()) - node->getExpression()->traverse(this); - } - - if (visit && postVisit) - visitLoop(PostVisit, node); -} - -// -// Traverse a branch node. Same comments in binary node apply here. -// -void TIntermTraverser::traverseBranch(TIntermBranch *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitBranch(PreVisit, node); - - if (visit && node->getExpression()) - { - node->getExpression()->traverse(this); - } - - if (visit && postVisit) - visitBranch(PostVisit, node); -} - -void TIntermTraverser::traverseRaw(TIntermRaw *node) -{ - ScopedNodeInTraversalPath addToPath(this, node); - visitRaw(node); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.h b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.h deleted file mode 100644 index f0300b586b..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.h +++ /dev/null @@ -1,355 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// IntermTraverse.h : base classes for AST traversers that walk the AST and -// also have the ability to transform it by replacing nodes. - -#ifndef COMPILER_TRANSLATOR_INTERMTRAVERSE_H_ -#define COMPILER_TRANSLATOR_INTERMTRAVERSE_H_ - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -class TSymbolTable; -class TSymbolUniqueId; - -enum Visit -{ - PreVisit, - InVisit, - PostVisit -}; - -// For traversing the tree. User should derive from this class overriding the visit functions, -// and then pass an object of the subclass to a traverse method of a node. -// -// The traverse*() functions may also be overridden to do other bookkeeping on the tree to provide -// contextual information to the visit functions, such as whether the node is the target of an -// assignment. This is complex to maintain and so should only be done in special cases. -// -// When using this, just fill in the methods for nodes you want visited. -// Return false from a pre-visit to skip visiting that node's subtree. -class TIntermTraverser : angle::NonCopyable -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TIntermTraverser(bool preVisit, - bool inVisit, - bool postVisit, - TSymbolTable *symbolTable = nullptr); - virtual ~TIntermTraverser(); - - virtual void visitSymbol(TIntermSymbol *node) {} - virtual void visitRaw(TIntermRaw *node) {} - virtual void visitConstantUnion(TIntermConstantUnion *node) {} - virtual bool visitSwizzle(Visit visit, TIntermSwizzle *node) { return true; } - virtual bool visitBinary(Visit visit, TIntermBinary *node) { return true; } - virtual bool visitUnary(Visit visit, TIntermUnary *node) { return true; } - virtual bool visitTernary(Visit visit, TIntermTernary *node) { return true; } - virtual bool visitIfElse(Visit visit, TIntermIfElse *node) { return true; } - virtual bool visitSwitch(Visit visit, TIntermSwitch *node) { return true; } - virtual bool visitCase(Visit visit, TIntermCase *node) { return true; } - virtual bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) - { - return true; - } - virtual bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) - { - return true; - } - virtual bool visitAggregate(Visit visit, TIntermAggregate *node) { return true; } - virtual bool visitBlock(Visit visit, TIntermBlock *node) { return true; } - virtual bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) - { - return true; - } - virtual bool visitDeclaration(Visit visit, TIntermDeclaration *node) { return true; } - virtual bool visitLoop(Visit visit, TIntermLoop *node) { return true; } - virtual bool visitBranch(Visit visit, TIntermBranch *node) { return true; } - - // The traverse functions contain logic for iterating over the children of the node - // and calling the visit functions in the appropriate places. They also track some - // context that may be used by the visit functions. - virtual void traverseSymbol(TIntermSymbol *node); - virtual void traverseRaw(TIntermRaw *node); - virtual void traverseConstantUnion(TIntermConstantUnion *node); - virtual void traverseSwizzle(TIntermSwizzle *node); - virtual void traverseBinary(TIntermBinary *node); - virtual void traverseUnary(TIntermUnary *node); - virtual void traverseTernary(TIntermTernary *node); - virtual void traverseIfElse(TIntermIfElse *node); - virtual void traverseSwitch(TIntermSwitch *node); - virtual void traverseCase(TIntermCase *node); - virtual void traverseFunctionPrototype(TIntermFunctionPrototype *node); - virtual void traverseFunctionDefinition(TIntermFunctionDefinition *node); - virtual void traverseAggregate(TIntermAggregate *node); - virtual void traverseBlock(TIntermBlock *node); - virtual void traverseInvariantDeclaration(TIntermInvariantDeclaration *node); - virtual void traverseDeclaration(TIntermDeclaration *node); - virtual void traverseLoop(TIntermLoop *node); - virtual void traverseBranch(TIntermBranch *node); - - int getMaxDepth() const { return mMaxDepth; } - - // If traversers need to replace nodes, they can add the replacements in - // mReplacements/mMultiReplacements during traversal and the user of the traverser should call - // this function after traversal to perform them. - void updateTree(); - - protected: - // Should only be called from traverse*() functions - void incrementDepth(TIntermNode *current) - { - mDepth++; - mMaxDepth = std::max(mMaxDepth, mDepth); - mPath.push_back(current); - } - - // Should only be called from traverse*() functions - void decrementDepth() - { - mDepth--; - mPath.pop_back(); - } - - // RAII helper for incrementDepth/decrementDepth - class ScopedNodeInTraversalPath - { - public: - ScopedNodeInTraversalPath(TIntermTraverser *traverser, TIntermNode *current) - : mTraverser(traverser) - { - mTraverser->incrementDepth(current); - } - ~ScopedNodeInTraversalPath() { mTraverser->decrementDepth(); } - - private: - TIntermTraverser *mTraverser; - }; - - TIntermNode *getParentNode() { return mPath.size() <= 1 ? nullptr : mPath[mPath.size() - 2u]; } - - // Return the nth ancestor of the node being traversed. getAncestorNode(0) == getParentNode() - TIntermNode *getAncestorNode(unsigned int n) - { - if (mPath.size() > n + 1u) - { - return mPath[mPath.size() - n - 2u]; - } - return nullptr; - } - - const TIntermBlock *getParentBlock() const; - - void pushParentBlock(TIntermBlock *node); - void incrementParentBlockPos(); - void popParentBlock(); - - // To replace a single node with multiple nodes in the parent aggregate. May be used with blocks - // but also with other nodes like declarations. - struct NodeReplaceWithMultipleEntry - { - NodeReplaceWithMultipleEntry(TIntermAggregateBase *_parent, - TIntermNode *_original, - TIntermSequence _replacements) - : parent(_parent), original(_original), replacements(_replacements) - { - } - - TIntermAggregateBase *parent; - TIntermNode *original; - TIntermSequence replacements; - }; - - // Helper to insert statements in the parent block of the node currently being traversed. - // The statements will be inserted before the node being traversed once updateTree is called. - // Should only be called during PreVisit or PostVisit if called from block nodes. - // Note that two insertions to the same position in the same block are not supported. - void insertStatementsInParentBlock(const TIntermSequence &insertions); - - // Same as above, but supports simultaneous insertion of statements before and after the node - // currently being traversed. - void insertStatementsInParentBlock(const TIntermSequence &insertionsBefore, - const TIntermSequence &insertionsAfter); - - // Helper to insert a single statement. - void insertStatementInParentBlock(TIntermNode *statement); - - // Helper to create a temporary symbol node with the given qualifier. - TIntermSymbol *createTempSymbol(const TType &type, TQualifier qualifier); - // Helper to create a temporary symbol node. - TIntermSymbol *createTempSymbol(const TType &type); - // Create a node that declares but doesn't initialize a temporary symbol. - TIntermDeclaration *createTempDeclaration(const TType &type); - // Create a node that initializes the current temporary symbol with initializer. The symbol will - // have the given qualifier. - TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier); - // Create a node that initializes the current temporary symbol with initializer. - TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer); - // Create a node that assigns rightNode to the current temporary symbol. - TIntermBinary *createTempAssignment(TIntermTyped *rightNode); - // Increment temporary symbol index. - void nextTemporaryId(); - - enum class OriginalNode - { - BECOMES_CHILD, - IS_DROPPED - }; - - void clearReplacementQueue(); - - // Replace the node currently being visited with replacement. - void queueReplacement(TIntermNode *replacement, OriginalNode originalStatus); - // Explicitly specify a node to replace with replacement. - void queueReplacementWithParent(TIntermNode *parent, - TIntermNode *original, - TIntermNode *replacement, - OriginalNode originalStatus); - - const bool preVisit; - const bool inVisit; - const bool postVisit; - - int mDepth; - int mMaxDepth; - - bool mInGlobalScope; - - // During traversing, save all the changes that need to happen into - // mReplacements/mMultiReplacements, then do them by calling updateTree(). - // Multi replacements are processed after single replacements. - std::vector<NodeReplaceWithMultipleEntry> mMultiReplacements; - - TSymbolTable *mSymbolTable; - - private: - // To insert multiple nodes into the parent block. - struct NodeInsertMultipleEntry - { - NodeInsertMultipleEntry(TIntermBlock *_parent, - TIntermSequence::size_type _position, - TIntermSequence _insertionsBefore, - TIntermSequence _insertionsAfter) - : parent(_parent), - position(_position), - insertionsBefore(_insertionsBefore), - insertionsAfter(_insertionsAfter) - { - } - - TIntermBlock *parent; - TIntermSequence::size_type position; - TIntermSequence insertionsBefore; - TIntermSequence insertionsAfter; - }; - - static bool CompareInsertion(const NodeInsertMultipleEntry &a, - const NodeInsertMultipleEntry &b); - - // To replace a single node with another on the parent node - struct NodeUpdateEntry - { - NodeUpdateEntry(TIntermNode *_parent, - TIntermNode *_original, - TIntermNode *_replacement, - bool _originalBecomesChildOfReplacement) - : parent(_parent), - original(_original), - replacement(_replacement), - originalBecomesChildOfReplacement(_originalBecomesChildOfReplacement) - { - } - - TIntermNode *parent; - TIntermNode *original; - TIntermNode *replacement; - bool originalBecomesChildOfReplacement; - }; - - struct ParentBlock - { - ParentBlock(TIntermBlock *nodeIn, TIntermSequence::size_type posIn) - : node(nodeIn), pos(posIn) - { - } - - TIntermBlock *node; - TIntermSequence::size_type pos; - }; - - std::vector<NodeInsertMultipleEntry> mInsertions; - std::vector<NodeUpdateEntry> mReplacements; - - // All the nodes from root to the current node during traversing. - TVector<TIntermNode *> mPath; - - // All the code blocks from the root to the current node's parent during traversal. - std::vector<ParentBlock> mParentBlockStack; - - TSymbolUniqueId *mTemporaryId; -}; - -// Traverser parent class that tracks where a node is a destination of a write operation and so is -// required to be an l-value. -class TLValueTrackingTraverser : public TIntermTraverser -{ - public: - TLValueTrackingTraverser(bool preVisit, - bool inVisit, - bool postVisit, - TSymbolTable *symbolTable, - int shaderVersion); - virtual ~TLValueTrackingTraverser() {} - - void traverseBinary(TIntermBinary *node) final; - void traverseUnary(TIntermUnary *node) final; - void traverseFunctionPrototype(TIntermFunctionPrototype *node) final; - void traverseAggregate(TIntermAggregate *node) final; - - protected: - bool isLValueRequiredHere() const - { - return mOperatorRequiresLValue || mInFunctionCallOutParameter; - } - - private: - // Track whether an l-value is required in the node that is currently being traversed by the - // surrounding operator. - // Use isLValueRequiredHere to check all conditions which require an l-value. - void setOperatorRequiresLValue(bool lValueRequired) - { - mOperatorRequiresLValue = lValueRequired; - } - bool operatorRequiresLValue() const { return mOperatorRequiresLValue; } - - // Add a function encountered during traversal to the function map. - void addToFunctionMap(const TSymbolUniqueId &id, TIntermSequence *paramSequence); - - // Return true if the prototype or definition of the function being called has been encountered - // during traversal. - bool isInFunctionMap(const TIntermAggregate *callNode) const; - - // Return the parameters sequence from the function definition or prototype. - TIntermSequence *getFunctionParameters(const TIntermAggregate *callNode); - - // Track whether an l-value is required inside a function call. - void setInFunctionCallOutParameter(bool inOutParameter); - bool isInFunctionCallOutParameter() const; - - bool mOperatorRequiresLValue; - bool mInFunctionCallOutParameter; - - // Map from function symbol id values to their parameter sequences - TMap<int, TIntermSequence *> mFunctionMap; - - const int mShaderVersion; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_INTERMTRAVERSE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp b/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp deleted file mode 100644 index aaad4f3c68..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/IsASTDepthBelowLimit.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -// Traverse the tree and compute max depth. Takes a maximum depth limit to prevent stack overflow. -class MaxDepthTraverser : public TIntermTraverser -{ - public: - MaxDepthTraverser(int depthLimit) : TIntermTraverser(true, true, false), mDepthLimit(depthLimit) - { - } - - bool visitBinary(Visit, TIntermBinary *) override { return depthCheck(); } - bool visitUnary(Visit, TIntermUnary *) override { return depthCheck(); } - bool visitTernary(Visit, TIntermTernary *) override { return depthCheck(); } - bool visitSwizzle(Visit, TIntermSwizzle *) override { return depthCheck(); } - bool visitIfElse(Visit, TIntermIfElse *) override { return depthCheck(); } - bool visitAggregate(Visit, TIntermAggregate *) override { return depthCheck(); } - bool visitBlock(Visit, TIntermBlock *) override { return depthCheck(); } - bool visitLoop(Visit, TIntermLoop *) override { return depthCheck(); } - bool visitBranch(Visit, TIntermBranch *) override { return depthCheck(); } - - protected: - bool depthCheck() const { return mMaxDepth < mDepthLimit; } - - int mDepthLimit; -}; - -} // anonymous namespace - -bool IsASTDepthBelowLimit(TIntermNode *root, int maxDepth) -{ - MaxDepthTraverser traverser(maxDepth + 1); - root->traverse(&traverser); - - return traverser.getMaxDepth() <= maxDepth; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h b/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h deleted file mode 100644 index ef2f02c974..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// IsASTDepthBelowLimit: Check whether AST depth is below a specific limit. - -#ifndef COMPILER_TRANSLATOR_ISASTDEPTHBELOWLIMIT_H_ -#define COMPILER_TRANSLATOR_ISASTDEPTHBELOWLIMIT_H_ - -namespace sh -{ - -class TIntermNode; - -bool IsASTDepthBelowLimit(TIntermNode *root, int maxDepth); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_ISASTDEPTHBELOWLIMIT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h deleted file mode 100644 index af86b8bde4..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// NodeSearch.h: Utilities for searching translator node graphs -// - -#ifndef COMPILER_TRANSLATOR_NODESEARCH_H_ -#define COMPILER_TRANSLATOR_NODESEARCH_H_ - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -template <class Parent> -class NodeSearchTraverser : public TIntermTraverser -{ - public: - NodeSearchTraverser() : TIntermTraverser(true, false, false), mFound(false) {} - - bool found() const { return mFound; } - - static bool search(TIntermNode *node) - { - Parent searchTraverser; - node->traverse(&searchTraverser); - return searchTraverser.found(); - } - - protected: - bool mFound; -}; - -class FindDiscard : public NodeSearchTraverser<FindDiscard> -{ - public: - virtual bool visitBranch(Visit visit, TIntermBranch *node) - { - switch (node->getFlowOp()) - { - case EOpKill: - mFound = true; - break; - - default: - break; - } - - return !mFound; - } -}; -} - -#endif // COMPILER_TRANSLATOR_NODESEARCH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Operator.cpp b/src/3rdparty/angle/src/compiler/translator/Operator.cpp deleted file mode 100644 index 7a2156611a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Operator.cpp +++ /dev/null @@ -1,385 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/Operator.h" - -const char *GetOperatorString(TOperator op) -{ - switch (op) - { - // Note: EOpNull and EOpCall* can't be handled here. - - case EOpNegative: - return "-"; - case EOpPositive: - return "+"; - case EOpLogicalNot: - return "!"; - case EOpBitwiseNot: - return "~"; - - case EOpPostIncrement: - return "++"; - case EOpPostDecrement: - return "--"; - case EOpPreIncrement: - return "++"; - case EOpPreDecrement: - return "--"; - - case EOpArrayLength: - return ".length()"; - - case EOpAdd: - return "+"; - case EOpSub: - return "-"; - case EOpMul: - return "*"; - case EOpDiv: - return "/"; - case EOpIMod: - return "%"; - - case EOpEqual: - return "=="; - case EOpNotEqual: - return "!="; - case EOpLessThan: - return "<"; - case EOpGreaterThan: - return ">"; - case EOpLessThanEqual: - return "<="; - case EOpGreaterThanEqual: - return ">="; - - case EOpEqualComponentWise: - return "equal"; - case EOpNotEqualComponentWise: - return "notEqual"; - case EOpLessThanComponentWise: - return "lessThan"; - case EOpGreaterThanComponentWise: - return "greaterThan"; - case EOpLessThanEqualComponentWise: - return "lessThanEqual"; - case EOpGreaterThanEqualComponentWise: - return "greaterThanEqual"; - - case EOpComma: - return ","; - - // Fall-through. - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: - return "*"; - - case EOpLogicalOr: - return "||"; - case EOpLogicalXor: - return "^^"; - case EOpLogicalAnd: - return "&&"; - - case EOpBitShiftLeft: - return "<<"; - case EOpBitShiftRight: - return ">>"; - - case EOpBitwiseAnd: - return "&"; - case EOpBitwiseXor: - return "^"; - case EOpBitwiseOr: - return "|"; - - // Fall-through. - case EOpIndexDirect: - case EOpIndexIndirect: - return "[]"; - - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: - return "."; - - case EOpRadians: - return "radians"; - case EOpDegrees: - return "degrees"; - case EOpSin: - return "sin"; - case EOpCos: - return "cos"; - case EOpTan: - return "tan"; - case EOpAsin: - return "asin"; - case EOpAcos: - return "acos"; - case EOpAtan: - return "atan"; - - case EOpSinh: - return "sinh"; - case EOpCosh: - return "cosh"; - case EOpTanh: - return "tanh"; - case EOpAsinh: - return "asinh"; - case EOpAcosh: - return "acosh"; - case EOpAtanh: - return "atanh"; - - case EOpPow: - return "pow"; - case EOpExp: - return "exp"; - case EOpLog: - return "log"; - case EOpExp2: - return "exp2"; - case EOpLog2: - return "log2"; - case EOpSqrt: - return "sqrt"; - case EOpInverseSqrt: - return "inversesqrt"; - - case EOpAbs: - return "abs"; - case EOpSign: - return "sign"; - case EOpFloor: - return "floor"; - case EOpTrunc: - return "trunc"; - case EOpRound: - return "round"; - case EOpRoundEven: - return "roundEven"; - case EOpCeil: - return "ceil"; - case EOpFract: - return "fract"; - case EOpMod: - return "mod"; - case EOpModf: - return "modf"; - case EOpMin: - return "min"; - case EOpMax: - return "max"; - case EOpClamp: - return "clamp"; - case EOpMix: - return "mix"; - case EOpStep: - return "step"; - case EOpSmoothStep: - return "smoothstep"; - case EOpIsNan: - return "isnan"; - case EOpIsInf: - return "isinf"; - - case EOpFloatBitsToInt: - return "floatBitsToInt"; - case EOpFloatBitsToUint: - return "floatBitsToUint"; - case EOpIntBitsToFloat: - return "intBitsToFloat"; - case EOpUintBitsToFloat: - return "uintBitsToFloat"; - - case EOpFrexp: - return "frexp"; - case EOpLdexp: - return "ldexp"; - - case EOpPackSnorm2x16: - return "packSnorm2x16"; - case EOpPackUnorm2x16: - return "packUnorm2x16"; - case EOpPackHalf2x16: - return "packHalf2x16"; - case EOpUnpackSnorm2x16: - return "unpackSnorm2x16"; - case EOpUnpackUnorm2x16: - return "unpackUnorm2x16"; - case EOpUnpackHalf2x16: - return "unpackHalf2x16"; - - case EOpPackUnorm4x8: - return "packUnorm4x8"; - case EOpPackSnorm4x8: - return "packSnorm4x8"; - case EOpUnpackUnorm4x8: - return "unpackUnorm4x8"; - case EOpUnpackSnorm4x8: - return "unpackSnorm4x8"; - - case EOpLength: - return "length"; - case EOpDistance: - return "distance"; - case EOpDot: - return "dot"; - case EOpCross: - return "cross"; - case EOpNormalize: - return "normalize"; - case EOpFaceforward: - return "faceforward"; - case EOpReflect: - return "reflect"; - case EOpRefract: - return "refract"; - - case EOpDFdx: - return "dFdx"; - case EOpDFdy: - return "dFdy"; - case EOpFwidth: - return "fwidth"; - - case EOpMulMatrixComponentWise: - return "matrixCompMult"; - case EOpOuterProduct: - return "outerProduct"; - case EOpTranspose: - return "transpose"; - case EOpDeterminant: - return "determinant"; - case EOpInverse: - return "inverse"; - - case EOpAny: - return "any"; - case EOpAll: - return "all"; - case EOpLogicalNotComponentWise: - return "not"; - - case EOpBitfieldExtract: - return "bitfieldExtract"; - case EOpBitfieldInsert: - return "bitfieldInsert"; - case EOpBitfieldReverse: - return "bitfieldReverse"; - case EOpBitCount: - return "bitCount"; - case EOpFindLSB: - return "findLSB"; - case EOpFindMSB: - return "findMSB"; - case EOpUaddCarry: - return "uaddCarry"; - case EOpUsubBorrow: - return "usubBorrow"; - case EOpUmulExtended: - return "umulExtended"; - case EOpImulExtended: - return "imulExtended"; - - case EOpKill: - return "kill"; - case EOpReturn: - return "return"; - case EOpBreak: - return "break"; - case EOpContinue: - return "continue"; - - case EOpAssign: - return "="; - case EOpInitialize: - return "="; - case EOpAddAssign: - return "+="; - case EOpSubAssign: - return "-="; - - // Fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - return "*="; - - case EOpDivAssign: - return "/="; - case EOpIModAssign: - return "%="; - case EOpBitShiftLeftAssign: - return "<<="; - case EOpBitShiftRightAssign: - return ">>="; - case EOpBitwiseAndAssign: - return "&="; - case EOpBitwiseXorAssign: - return "^="; - case EOpBitwiseOrAssign: - return "|="; - case EOpBarrier: - return "barrier"; - case EOpMemoryBarrier: - return "memoryBarrier"; - case EOpMemoryBarrierAtomicCounter: - return "memoryBarrierAtomicCounter"; - case EOpMemoryBarrierBuffer: - return "memoryBarrierBuffer"; - case EOpMemoryBarrierImage: - return "memoryBarrierImage"; - case EOpMemoryBarrierShared: - return "memoryBarrierShared"; - case EOpGroupMemoryBarrier: - return "groupMemoryBarrier"; - - case EOpEmitVertex: - return "EmitVertex"; - case EOpEndPrimitive: - return "EndPrimitive"; - default: - break; - } - return ""; -} - -bool IsAssignment(TOperator op) -{ - switch (op) - { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - case EOpDivAssign: - case EOpIModAssign: - case EOpBitShiftLeftAssign: - case EOpBitShiftRightAssign: - case EOpBitwiseAndAssign: - case EOpBitwiseXorAssign: - case EOpBitwiseOrAssign: - return true; - default: - return false; - } -}
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/Operator.h b/src/3rdparty/angle/src/compiler/translator/Operator.h deleted file mode 100644 index 72f3dbf3f6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Operator.h +++ /dev/null @@ -1,255 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_OPERATOR_H_ -#define COMPILER_TRANSLATOR_OPERATOR_H_ - -// -// Operators used by the high-level (parse tree) representation. -// -enum TOperator -{ - EOpNull, // if in a node, should only mean a node is still being built - - // Call a function defined in the AST. This might be a user-defined function or a function - // inserted by an AST transformation. - EOpCallFunctionInAST, - - // Call an internal helper function with a raw implementation - the implementation can't be - // subject to AST transformations. Raw functions have a few constraints to keep them compatible - // with AST traversers: - // * They should not return arrays. - // * They should not have out parameters. - EOpCallInternalRawFunction, - - // Call a built-in function like a texture or image function. - EOpCallBuiltInFunction, - - // - // Unary operators - // - - EOpNegative, - EOpPositive, - EOpLogicalNot, - EOpBitwiseNot, - - EOpPostIncrement, - EOpPostDecrement, - EOpPreIncrement, - EOpPreDecrement, - - EOpArrayLength, - - // - // binary operations (ones with special GLSL syntax are used in TIntermBinary nodes, others in - // TIntermAggregate nodes) - // - - EOpAdd, - EOpSub, - EOpMul, - EOpDiv, - EOpIMod, - - EOpEqual, - EOpNotEqual, - EOpLessThan, - EOpGreaterThan, - EOpLessThanEqual, - EOpGreaterThanEqual, - - EOpEqualComponentWise, - EOpNotEqualComponentWise, - EOpLessThanComponentWise, - EOpLessThanEqualComponentWise, - EOpGreaterThanComponentWise, - EOpGreaterThanEqualComponentWise, - - EOpComma, - - EOpVectorTimesScalar, - EOpVectorTimesMatrix, - EOpMatrixTimesVector, - EOpMatrixTimesScalar, - EOpMatrixTimesMatrix, - - EOpLogicalOr, - EOpLogicalXor, - EOpLogicalAnd, - - EOpBitShiftLeft, - EOpBitShiftRight, - - EOpBitwiseAnd, - EOpBitwiseXor, - EOpBitwiseOr, - - EOpIndexDirect, - EOpIndexIndirect, - EOpIndexDirectStruct, - EOpIndexDirectInterfaceBlock, - - // - // Built-in functions mapped to operators (either unary or with multiple parameters) - // - - EOpRadians, - EOpDegrees, - EOpSin, - EOpCos, - EOpTan, - EOpAsin, - EOpAcos, - EOpAtan, - - EOpSinh, - EOpCosh, - EOpTanh, - EOpAsinh, - EOpAcosh, - EOpAtanh, - - EOpPow, - EOpExp, - EOpLog, - EOpExp2, - EOpLog2, - EOpSqrt, - EOpInverseSqrt, - - EOpAbs, - EOpSign, - EOpFloor, - EOpTrunc, - EOpRound, - EOpRoundEven, - EOpCeil, - EOpFract, - EOpMod, - EOpModf, - EOpMin, - EOpMax, - EOpClamp, - EOpMix, - EOpStep, - EOpSmoothStep, - EOpIsNan, - EOpIsInf, - - EOpFloatBitsToInt, - EOpFloatBitsToUint, - EOpIntBitsToFloat, - EOpUintBitsToFloat, - - EOpFrexp, - EOpLdexp, - - EOpPackSnorm2x16, - EOpPackUnorm2x16, - EOpPackHalf2x16, - EOpUnpackSnorm2x16, - EOpUnpackUnorm2x16, - EOpUnpackHalf2x16, - - EOpPackUnorm4x8, - EOpPackSnorm4x8, - EOpUnpackUnorm4x8, - EOpUnpackSnorm4x8, - - EOpLength, - EOpDistance, - EOpDot, - EOpCross, - EOpNormalize, - EOpFaceforward, - EOpReflect, - EOpRefract, - - EOpDFdx, // Fragment only, OES_standard_derivatives extension - EOpDFdy, // Fragment only, OES_standard_derivatives extension - EOpFwidth, // Fragment only, OES_standard_derivatives extension - - EOpMulMatrixComponentWise, - EOpOuterProduct, - EOpTranspose, - EOpDeterminant, - EOpInverse, - - EOpAny, - EOpAll, - EOpLogicalNotComponentWise, - - EOpBitfieldExtract, - EOpBitfieldInsert, - EOpBitfieldReverse, - EOpBitCount, - EOpFindLSB, - EOpFindMSB, - EOpUaddCarry, - EOpUsubBorrow, - EOpUmulExtended, - EOpImulExtended, - - // - // Branch - // - - EOpKill, // Fragment only - EOpReturn, - EOpBreak, - EOpContinue, - - // - // Constructor - // - - EOpConstruct, - - // - // moves - // - - EOpAssign, - EOpInitialize, - EOpAddAssign, - EOpSubAssign, - - EOpMulAssign, - EOpVectorTimesMatrixAssign, - EOpVectorTimesScalarAssign, - EOpMatrixTimesScalarAssign, - EOpMatrixTimesMatrixAssign, - - EOpDivAssign, - EOpIModAssign, - EOpBitShiftLeftAssign, - EOpBitShiftRightAssign, - EOpBitwiseAndAssign, - EOpBitwiseXorAssign, - EOpBitwiseOrAssign, - - // barriers - EOpBarrier, - EOpMemoryBarrier, - EOpMemoryBarrierAtomicCounter, - EOpMemoryBarrierBuffer, - EOpMemoryBarrierImage, - EOpMemoryBarrierShared, - EOpGroupMemoryBarrier, - - // Geometry only - EOpEmitVertex, - EOpEndPrimitive -}; - -// Returns the string corresponding to the operator in GLSL -const char *GetOperatorString(TOperator op); - -// Say whether or not a binary or unary operation changes the value of a variable. -bool IsAssignment(TOperator op); - -#endif // COMPILER_TRANSLATOR_OPERATOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp deleted file mode 100644 index 50626c91c0..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/OutputESSL.h" - -namespace sh -{ - -TOutputESSL::TOutputESSL(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - bool forceHighp, - ShCompileOptions compileOptions) - : TOutputGLSLBase(objSink, - clampingStrategy, - hashFunction, - nameMap, - symbolTable, - shaderType, - shaderVersion, - SH_ESSL_OUTPUT, - compileOptions), - mForceHighp(forceHighp) -{ -} - -bool TOutputESSL::writeVariablePrecision(TPrecision precision) -{ - if (precision == EbpUndefined) - return false; - - TInfoSinkBase &out = objSink(); - if (mForceHighp) - out << getPrecisionString(EbpHigh); - else - out << getPrecisionString(precision); - return true; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h deleted file mode 100644 index e0c7bf2ae6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_OUTPUTESSL_H_ -#define COMPILER_TRANSLATOR_OUTPUTESSL_H_ - -#include "compiler/translator/OutputGLSLBase.h" - -namespace sh -{ - -class TOutputESSL : public TOutputGLSLBase -{ - public: - TOutputESSL(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - bool forceHighp, - ShCompileOptions compileOptions); - - protected: - bool writeVariablePrecision(TPrecision precision) override; - - private: - bool mForceHighp; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_OUTPUTESSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp deleted file mode 100644 index 1bad05dab9..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/OutputGLSL.h" - -#include "compiler/translator/Compiler.h" - -namespace sh -{ - -TOutputGLSL::TOutputGLSL(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions) - : TOutputGLSLBase(objSink, - clampingStrategy, - hashFunction, - nameMap, - symbolTable, - shaderType, - shaderVersion, - output, - compileOptions) -{ -} - -bool TOutputGLSL::writeVariablePrecision(TPrecision) -{ - return false; -} - -void TOutputGLSL::visitSymbol(TIntermSymbol *node) -{ - TInfoSinkBase &out = objSink(); - - const TString &symbol = node->getSymbol(); - if (symbol == "gl_FragDepthEXT") - { - out << "gl_FragDepth"; - } - else if (symbol == "gl_FragColor" && sh::IsGLSL130OrNewer(getShaderOutput())) - { - out << "webgl_FragColor"; - } - else if (symbol == "gl_FragData" && sh::IsGLSL130OrNewer(getShaderOutput())) - { - out << "webgl_FragData"; - } - else if (symbol == "gl_SecondaryFragColorEXT") - { - out << "angle_SecondaryFragColor"; - } - else if (symbol == "gl_SecondaryFragDataEXT") - { - out << "angle_SecondaryFragData"; - } - else - { - TOutputGLSLBase::visitSymbol(node); - } -} - -TString TOutputGLSL::translateTextureFunction(const TString &name) -{ - static const char *simpleRename[] = {"texture2DLodEXT", - "texture2DLod", - "texture2DProjLodEXT", - "texture2DProjLod", - "textureCubeLodEXT", - "textureCubeLod", - "texture2DGradEXT", - "texture2DGradARB", - "texture2DProjGradEXT", - "texture2DProjGradARB", - "textureCubeGradEXT", - "textureCubeGradARB", - nullptr, - nullptr}; - static const char *legacyToCoreRename[] = { - "texture2D", "texture", "texture2DProj", "textureProj", "texture2DLod", "textureLod", - "texture2DProjLod", "textureProjLod", "texture2DRect", "texture", "textureCube", "texture", - "textureCubeLod", "textureLod", - // Extensions - "texture2DLodEXT", "textureLod", "texture2DProjLodEXT", "textureProjLod", - "textureCubeLodEXT", "textureLod", "texture2DGradEXT", "textureGrad", - "texture2DProjGradEXT", "textureProjGrad", "textureCubeGradEXT", "textureGrad", nullptr, - nullptr}; - const char **mapping = - (sh::IsGLSL130OrNewer(getShaderOutput())) ? legacyToCoreRename : simpleRename; - - for (int i = 0; mapping[i] != nullptr; i += 2) - { - if (name == mapping[i]) - { - return mapping[i + 1]; - } - } - - return name; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h deleted file mode 100644 index c80abec1a6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_OUTPUTGLSL_H_ -#define COMPILER_TRANSLATOR_OUTPUTGLSL_H_ - -#include "compiler/translator/OutputGLSLBase.h" - -namespace sh -{ - -class TOutputGLSL : public TOutputGLSLBase -{ - public: - TOutputGLSL(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions); - - protected: - bool writeVariablePrecision(TPrecision) override; - void visitSymbol(TIntermSymbol *node) override; - TString translateTextureFunction(const TString &name) override; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_OUTPUTGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp deleted file mode 100644 index edaf2ebebf..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp +++ /dev/null @@ -1,1357 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/OutputGLSLBase.h" - -#include "angle_gl.h" -#include "common/debug.h" -#include "common/mathutil.h" -#include "compiler/translator/Compiler.h" -#include "compiler/translator/util.h" - -#include <cfloat> - -namespace sh -{ - -namespace -{ - -bool isSingleStatement(TIntermNode *node) -{ - if (node->getAsFunctionDefinition()) - { - return false; - } - else if (node->getAsBlock()) - { - return false; - } - else if (node->getAsIfElseNode()) - { - return false; - } - else if (node->getAsLoopNode()) - { - return false; - } - else if (node->getAsSwitchNode()) - { - return false; - } - else if (node->getAsCaseNode()) - { - return false; - } - return true; -} - -class CommaSeparatedListItemPrefixGenerator -{ - public: - CommaSeparatedListItemPrefixGenerator() : mFirst(true) {} - private: - bool mFirst; - - friend TInfoSinkBase &operator<<(TInfoSinkBase &out, - CommaSeparatedListItemPrefixGenerator &gen); -}; - -TInfoSinkBase &operator<<(TInfoSinkBase &out, CommaSeparatedListItemPrefixGenerator &gen) -{ - if (gen.mFirst) - { - gen.mFirst = false; - } - else - { - out << ", "; - } - return out; -} - -} // namespace - -TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions) - : TIntermTraverser(true, true, true, symbolTable), - mObjSink(objSink), - mDeclaringVariable(false), - mClampingStrategy(clampingStrategy), - mHashFunction(hashFunction), - mNameMap(nameMap), - mShaderType(shaderType), - mShaderVersion(shaderVersion), - mOutput(output), - mCompileOptions(compileOptions) -{ -} - -void TOutputGLSLBase::writeInvariantQualifier(const TType &type) -{ - if (!sh::RemoveInvariant(mShaderType, mShaderVersion, mOutput, mCompileOptions)) - { - TInfoSinkBase &out = objSink(); - out << "invariant "; - } -} - -void TOutputGLSLBase::writeFloat(TInfoSinkBase &out, float f) -{ - if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300) - { - out << "uintBitsToFloat(" << gl::bitCast<uint32_t>(f) << "u)"; - } - else - { - out << std::min(FLT_MAX, std::max(-FLT_MAX, f)); - } -} - -void TOutputGLSLBase::writeTriplet(Visit visit, - const char *preStr, - const char *inStr, - const char *postStr) -{ - TInfoSinkBase &out = objSink(); - if (visit == PreVisit && preStr) - out << preStr; - else if (visit == InVisit && inStr) - out << inStr; - else if (visit == PostVisit && postStr) - out << postStr; -} - -void TOutputGLSLBase::writeBuiltInFunctionTriplet(Visit visit, - TOperator op, - bool useEmulatedFunction) -{ - TInfoSinkBase &out = objSink(); - if (visit == PreVisit) - { - const char *opStr(GetOperatorString(op)); - if (useEmulatedFunction) - { - BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, opStr); - } - else - { - out << opStr; - } - out << "("; - } - else - { - writeTriplet(visit, nullptr, ", ", ")"); - } -} - -void TOutputGLSLBase::writeLayoutQualifier(TIntermTyped *variable) -{ - const TType &type = variable->getType(); - - if (!NeedsToWriteLayoutQualifier(type)) - { - return; - } - - TInfoSinkBase &out = objSink(); - const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); - out << "layout("; - - CommaSeparatedListItemPrefixGenerator listItemPrefix; - - if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn || - IsVarying(type.getQualifier())) - { - if (layoutQualifier.location >= 0) - { - out << listItemPrefix << "location = " << layoutQualifier.location; - } - } - - if (type.getQualifier() == EvqFragmentOut) - { - if (layoutQualifier.yuv == true) - { - out << listItemPrefix << "yuv"; - } - } - - if (IsOpaqueType(type.getBasicType())) - { - if (layoutQualifier.binding >= 0) - { - out << listItemPrefix << "binding = " << layoutQualifier.binding; - } - } - - if (IsImage(type.getBasicType())) - { - if (layoutQualifier.imageInternalFormat != EiifUnspecified) - { - ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform); - out << listItemPrefix - << getImageInternalFormatString(layoutQualifier.imageInternalFormat); - } - } - - if (IsAtomicCounter(type.getBasicType())) - { - out << listItemPrefix << "offset = " << layoutQualifier.offset; - } - - out << ") "; -} - -const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier) -{ - if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 && - (mCompileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0) - { - switch (qualifier) - { - // The return string is consistent with sh::getQualifierString() from - // BaseTypes.h minus the "centroid" keyword. - case EvqCentroid: - return ""; - case EvqCentroidIn: - return "smooth in"; - case EvqCentroidOut: - return "smooth out"; - default: - break; - } - } - if (sh::IsGLSL130OrNewer(mOutput)) - { - switch (qualifier) - { - case EvqAttribute: - return "in"; - case EvqVaryingIn: - return "in"; - case EvqVaryingOut: - return "out"; - default: - break; - } - } - return sh::getQualifierString(qualifier); -} - -void TOutputGLSLBase::writeVariableType(const TType &type) -{ - TQualifier qualifier = type.getQualifier(); - TInfoSinkBase &out = objSink(); - if (type.isInvariant()) - { - writeInvariantQualifier(type); - } - if (type.getBasicType() == EbtInterfaceBlock) - { - TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); - declareInterfaceBlockLayout(interfaceBlock); - } - if (qualifier != EvqTemporary && qualifier != EvqGlobal) - { - const char *qualifierString = mapQualifierToString(qualifier); - if (qualifierString && qualifierString[0] != '\0') - { - out << qualifierString << " "; - } - } - - const TMemoryQualifier &memoryQualifier = type.getMemoryQualifier(); - if (memoryQualifier.readonly) - { - ASSERT(IsImage(type.getBasicType())); - out << "readonly "; - } - - if (memoryQualifier.writeonly) - { - ASSERT(IsImage(type.getBasicType())); - out << "writeonly "; - } - - if (memoryQualifier.coherent) - { - ASSERT(IsImage(type.getBasicType())); - out << "coherent "; - } - - if (memoryQualifier.restrictQualifier) - { - ASSERT(IsImage(type.getBasicType())); - out << "restrict "; - } - - if (memoryQualifier.volatileQualifier) - { - ASSERT(IsImage(type.getBasicType())); - out << "volatile "; - } - - // Declare the struct if we have not done so already. - if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct())) - { - const TStructure *structure = type.getStruct(); - - declareStruct(structure); - - if (!structure->name().empty()) - { - mDeclaredStructs.insert(structure->uniqueId()); - } - } - else if (type.getBasicType() == EbtInterfaceBlock) - { - TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); - declareInterfaceBlock(interfaceBlock); - } - else - { - if (writeVariablePrecision(type.getPrecision())) - out << " "; - out << getTypeName(type); - } -} - -void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args) -{ - TInfoSinkBase &out = objSink(); - for (TIntermSequence::const_iterator iter = args.begin(); iter != args.end(); ++iter) - { - const TIntermSymbol *arg = (*iter)->getAsSymbolNode(); - ASSERT(arg != nullptr); - - const TType &type = arg->getType(); - writeVariableType(type); - - if (!arg->getName().getString().empty()) - out << " " << hashName(arg->getName()); - if (type.isArray()) - out << ArrayString(type); - - // Put a comma if this is not the last argument. - if (iter != args.end() - 1) - out << ", "; - } -} - -const TConstantUnion *TOutputGLSLBase::writeConstantUnion(const TType &type, - const TConstantUnion *pConstUnion) -{ - TInfoSinkBase &out = objSink(); - - if (type.getBasicType() == EbtStruct) - { - const TStructure *structure = type.getStruct(); - out << hashName(TName(structure->name())) << "("; - - const TFieldList &fields = structure->fields(); - for (size_t i = 0; i < fields.size(); ++i) - { - const TType *fieldType = fields[i]->type(); - ASSERT(fieldType != nullptr); - pConstUnion = writeConstantUnion(*fieldType, pConstUnion); - if (i != fields.size() - 1) - out << ", "; - } - out << ")"; - } - else - { - size_t size = type.getObjectSize(); - bool writeType = size > 1; - if (writeType) - out << getTypeName(type) << "("; - for (size_t i = 0; i < size; ++i, ++pConstUnion) - { - switch (pConstUnion->getType()) - { - case EbtFloat: - writeFloat(out, pConstUnion->getFConst()); - break; - case EbtInt: - out << pConstUnion->getIConst(); - break; - case EbtUInt: - out << pConstUnion->getUConst() << "u"; - break; - case EbtBool: - out << pConstUnion->getBConst(); - break; - case EbtYuvCscStandardEXT: - out << getYuvCscStandardEXTString(pConstUnion->getYuvCscStandardEXTConst()); - break; - default: - UNREACHABLE(); - } - if (i != size - 1) - out << ", "; - } - if (writeType) - out << ")"; - } - return pConstUnion; -} - -void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type) -{ - TInfoSinkBase &out = objSink(); - if (visit == PreVisit) - { - if (type.isArray()) - { - out << getTypeName(type); - out << ArrayString(type); - out << "("; - } - else - { - out << getTypeName(type) << "("; - } - } - else - { - writeTriplet(visit, nullptr, ", ", ")"); - } -} - -void TOutputGLSLBase::visitSymbol(TIntermSymbol *node) -{ - TInfoSinkBase &out = objSink(); - out << hashVariableName(node->getName()); - - if (mDeclaringVariable && node->getType().isArray()) - out << ArrayString(node->getType()); -} - -void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node) -{ - writeConstantUnion(node->getType(), node->getUnionArrayPointer()); -} - -bool TOutputGLSLBase::visitSwizzle(Visit visit, TIntermSwizzle *node) -{ - TInfoSinkBase &out = objSink(); - if (visit == PostVisit) - { - out << "."; - node->writeOffsetsAsXYZW(&out); - } - return true; -} - -bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) -{ - bool visitChildren = true; - TInfoSinkBase &out = objSink(); - switch (node->getOp()) - { - case EOpComma: - writeTriplet(visit, "(", ", ", ")"); - break; - case EOpInitialize: - if (visit == InVisit) - { - out << " = "; - // RHS of initialize is not being declared. - mDeclaringVariable = false; - } - break; - case EOpAssign: - writeTriplet(visit, "(", " = ", ")"); - break; - case EOpAddAssign: - writeTriplet(visit, "(", " += ", ")"); - break; - case EOpSubAssign: - writeTriplet(visit, "(", " -= ", ")"); - break; - case EOpDivAssign: - writeTriplet(visit, "(", " /= ", ")"); - break; - case EOpIModAssign: - writeTriplet(visit, "(", " %= ", ")"); - break; - // Notice the fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - writeTriplet(visit, "(", " *= ", ")"); - break; - case EOpBitShiftLeftAssign: - writeTriplet(visit, "(", " <<= ", ")"); - break; - case EOpBitShiftRightAssign: - writeTriplet(visit, "(", " >>= ", ")"); - break; - case EOpBitwiseAndAssign: - writeTriplet(visit, "(", " &= ", ")"); - break; - case EOpBitwiseXorAssign: - writeTriplet(visit, "(", " ^= ", ")"); - break; - case EOpBitwiseOrAssign: - writeTriplet(visit, "(", " |= ", ")"); - break; - - case EOpIndexDirect: - writeTriplet(visit, nullptr, "[", "]"); - break; - case EOpIndexIndirect: - if (node->getAddIndexClamp()) - { - if (visit == InVisit) - { - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) - out << "[int(clamp(float("; - else - out << "[webgl_int_clamp("; - } - else if (visit == PostVisit) - { - TIntermTyped *left = node->getLeft(); - TType leftType = left->getType(); - - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) - out << "), 0.0, float("; - else - out << ", 0, "; - - if (leftType.isUnsizedArray()) - { - // For runtime-sized arrays in ESSL 3.10 we need to call the length method - // to get the length to clamp against. See ESSL 3.10 section 4.1.9. Note - // that a runtime-sized array expression is guaranteed not to have side - // effects, so it's fine to add the expression to the output twice. - ASSERT(mShaderVersion >= 310); - ASSERT(!left->hasSideEffects()); - left->traverse(this); - out << ".length() - 1"; - } - else - { - int maxSize; - if (leftType.isArray()) - { - maxSize = static_cast<int>(leftType.getOutermostArraySize()) - 1; - } - else - { - maxSize = leftType.getNominalSize() - 1; - } - out << maxSize; - } - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) - out << ")))]"; - else - out << ")]"; - } - } - else - { - writeTriplet(visit, nullptr, "[", "]"); - } - break; - case EOpIndexDirectStruct: - if (visit == InVisit) - { - // Here we are writing out "foo.bar", where "foo" is struct - // and "bar" is field. In AST, it is represented as a binary - // node, where left child represents "foo" and right child "bar". - // The node itself represents ".". The struct field "bar" is - // actually stored as an index into TStructure::fields. - out << "."; - const TStructure *structure = node->getLeft()->getType().getStruct(); - const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); - const TField *field = structure->fields()[index->getIConst(0)]; - - TString fieldName = field->name(); - if (!mSymbolTable->findBuiltIn(structure->name(), mShaderVersion)) - fieldName = hashName(TName(fieldName)); - - out << fieldName; - visitChildren = false; - } - break; - case EOpIndexDirectInterfaceBlock: - if (visit == InVisit) - { - out << "."; - const TInterfaceBlock *interfaceBlock = - node->getLeft()->getType().getInterfaceBlock(); - const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); - const TField *field = interfaceBlock->fields()[index->getIConst(0)]; - - TString fieldName = field->name(); - if (!mSymbolTable->findBuiltIn(interfaceBlock->name(), mShaderVersion)) - { - fieldName = hashName(TName(fieldName)); - } - else - { - ASSERT(interfaceBlock->name() == "gl_PerVertex"); - } - - out << fieldName; - visitChildren = false; - } - break; - - case EOpAdd: - writeTriplet(visit, "(", " + ", ")"); - break; - case EOpSub: - writeTriplet(visit, "(", " - ", ")"); - break; - case EOpMul: - writeTriplet(visit, "(", " * ", ")"); - break; - case EOpDiv: - writeTriplet(visit, "(", " / ", ")"); - break; - case EOpIMod: - writeTriplet(visit, "(", " % ", ")"); - break; - case EOpBitShiftLeft: - writeTriplet(visit, "(", " << ", ")"); - break; - case EOpBitShiftRight: - writeTriplet(visit, "(", " >> ", ")"); - break; - case EOpBitwiseAnd: - writeTriplet(visit, "(", " & ", ")"); - break; - case EOpBitwiseXor: - writeTriplet(visit, "(", " ^ ", ")"); - break; - case EOpBitwiseOr: - writeTriplet(visit, "(", " | ", ")"); - break; - - case EOpEqual: - writeTriplet(visit, "(", " == ", ")"); - break; - case EOpNotEqual: - writeTriplet(visit, "(", " != ", ")"); - break; - case EOpLessThan: - writeTriplet(visit, "(", " < ", ")"); - break; - case EOpGreaterThan: - writeTriplet(visit, "(", " > ", ")"); - break; - case EOpLessThanEqual: - writeTriplet(visit, "(", " <= ", ")"); - break; - case EOpGreaterThanEqual: - writeTriplet(visit, "(", " >= ", ")"); - break; - - // Notice the fall-through. - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: - writeTriplet(visit, "(", " * ", ")"); - break; - - case EOpLogicalOr: - writeTriplet(visit, "(", " || ", ")"); - break; - case EOpLogicalXor: - writeTriplet(visit, "(", " ^^ ", ")"); - break; - case EOpLogicalAnd: - writeTriplet(visit, "(", " && ", ")"); - break; - default: - UNREACHABLE(); - } - - return visitChildren; -} - -bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) -{ - TString preString; - TString postString = ")"; - - switch (node->getOp()) - { - case EOpNegative: - preString = "(-"; - break; - case EOpPositive: - preString = "(+"; - break; - case EOpLogicalNot: - preString = "(!"; - break; - case EOpBitwiseNot: - preString = "(~"; - break; - - case EOpPostIncrement: - preString = "("; - postString = "++)"; - break; - case EOpPostDecrement: - preString = "("; - postString = "--)"; - break; - case EOpPreIncrement: - preString = "(++"; - break; - case EOpPreDecrement: - preString = "(--"; - break; - case EOpArrayLength: - preString = "(("; - postString = ").length())"; - break; - - case EOpRadians: - case EOpDegrees: - case EOpSin: - case EOpCos: - case EOpTan: - case EOpAsin: - case EOpAcos: - case EOpAtan: - case EOpSinh: - case EOpCosh: - case EOpTanh: - case EOpAsinh: - case EOpAcosh: - case EOpAtanh: - case EOpExp: - case EOpLog: - case EOpExp2: - case EOpLog2: - case EOpSqrt: - case EOpInverseSqrt: - case EOpAbs: - case EOpSign: - case EOpFloor: - case EOpTrunc: - case EOpRound: - case EOpRoundEven: - case EOpCeil: - case EOpFract: - case EOpIsNan: - case EOpIsInf: - case EOpFloatBitsToInt: - case EOpFloatBitsToUint: - case EOpIntBitsToFloat: - case EOpUintBitsToFloat: - case EOpPackSnorm2x16: - case EOpPackUnorm2x16: - case EOpPackHalf2x16: - case EOpUnpackSnorm2x16: - case EOpUnpackUnorm2x16: - case EOpUnpackHalf2x16: - case EOpPackUnorm4x8: - case EOpPackSnorm4x8: - case EOpUnpackUnorm4x8: - case EOpUnpackSnorm4x8: - case EOpLength: - case EOpNormalize: - case EOpDFdx: - case EOpDFdy: - case EOpFwidth: - case EOpTranspose: - case EOpDeterminant: - case EOpInverse: - case EOpAny: - case EOpAll: - case EOpLogicalNotComponentWise: - case EOpBitfieldReverse: - case EOpBitCount: - case EOpFindLSB: - case EOpFindMSB: - writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction()); - return true; - default: - UNREACHABLE(); - } - - writeTriplet(visit, preString.c_str(), nullptr, postString.c_str()); - - return true; -} - -bool TOutputGLSLBase::visitTernary(Visit visit, TIntermTernary *node) -{ - TInfoSinkBase &out = objSink(); - // Notice two brackets at the beginning and end. The outer ones - // encapsulate the whole ternary expression. This preserves the - // order of precedence when ternary expressions are used in a - // compound expression, i.e., c = 2 * (a < b ? 1 : 2). - out << "(("; - node->getCondition()->traverse(this); - out << ") ? ("; - node->getTrueExpression()->traverse(this); - out << ") : ("; - node->getFalseExpression()->traverse(this); - out << "))"; - return false; -} - -bool TOutputGLSLBase::visitIfElse(Visit visit, TIntermIfElse *node) -{ - TInfoSinkBase &out = objSink(); - - out << "if ("; - node->getCondition()->traverse(this); - out << ")\n"; - - visitCodeBlock(node->getTrueBlock()); - - if (node->getFalseBlock()) - { - out << "else\n"; - visitCodeBlock(node->getFalseBlock()); - } - return false; -} - -bool TOutputGLSLBase::visitSwitch(Visit visit, TIntermSwitch *node) -{ - ASSERT(node->getStatementList()); - writeTriplet(visit, "switch (", ") ", nullptr); - // The curly braces get written when visiting the statementList aggregate - return true; -} - -bool TOutputGLSLBase::visitCase(Visit visit, TIntermCase *node) -{ - if (node->hasCondition()) - { - writeTriplet(visit, "case (", nullptr, "):\n"); - return true; - } - else - { - TInfoSinkBase &out = objSink(); - out << "default:\n"; - return false; - } -} - -bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node) -{ - TInfoSinkBase &out = objSink(); - // Scope the blocks except when at the global scope. - if (mDepth > 0) - { - out << "{\n"; - } - - for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); - iter != node->getSequence()->end(); ++iter) - { - TIntermNode *curNode = *iter; - ASSERT(curNode != nullptr); - curNode->traverse(this); - - if (isSingleStatement(curNode)) - out << ";\n"; - } - - // Scope the blocks except when at the global scope. - if (mDepth > 0) - { - out << "}\n"; - } - return false; -} - -bool TOutputGLSLBase::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) -{ - TIntermFunctionPrototype *prototype = node->getFunctionPrototype(); - prototype->traverse(this); - visitCodeBlock(node->getBody()); - - // Fully processed; no need to visit children. - return false; -} - -bool TOutputGLSLBase::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) -{ - TInfoSinkBase &out = objSink(); - ASSERT(visit == PreVisit); - const TIntermSymbol *symbol = node->getSymbol(); - out << "invariant " << hashVariableName(symbol->getName()); - return false; -} - -bool TOutputGLSLBase::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) -{ - TInfoSinkBase &out = objSink(); - ASSERT(visit == PreVisit); - - const TType &type = node->getType(); - writeVariableType(type); - if (type.isArray()) - out << ArrayString(type); - - out << " " << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo()); - - out << "("; - writeFunctionParameters(*(node->getSequence())); - out << ")"; - - return false; -} - -bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) -{ - bool visitChildren = true; - TInfoSinkBase &out = objSink(); - switch (node->getOp()) - { - case EOpCallFunctionInAST: - case EOpCallInternalRawFunction: - case EOpCallBuiltInFunction: - // Function call. - if (visit == PreVisit) - { - if (node->getOp() == EOpCallBuiltInFunction) - { - out << translateTextureFunction(node->getFunctionSymbolInfo()->getName()); - } - else - { - out << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo()); - } - out << "("; - } - else if (visit == InVisit) - out << ", "; - else - out << ")"; - break; - case EOpConstruct: - writeConstructorTriplet(visit, node->getType()); - break; - - case EOpEqualComponentWise: - case EOpNotEqualComponentWise: - case EOpLessThanComponentWise: - case EOpGreaterThanComponentWise: - case EOpLessThanEqualComponentWise: - case EOpGreaterThanEqualComponentWise: - case EOpMod: - case EOpModf: - case EOpPow: - case EOpAtan: - case EOpMin: - case EOpMax: - case EOpClamp: - case EOpMix: - case EOpStep: - case EOpSmoothStep: - case EOpFrexp: - case EOpLdexp: - case EOpDistance: - case EOpDot: - case EOpCross: - case EOpFaceforward: - case EOpReflect: - case EOpRefract: - case EOpMulMatrixComponentWise: - case EOpOuterProduct: - case EOpBitfieldExtract: - case EOpBitfieldInsert: - case EOpUaddCarry: - case EOpUsubBorrow: - case EOpUmulExtended: - case EOpImulExtended: - case EOpBarrier: - case EOpMemoryBarrier: - case EOpMemoryBarrierAtomicCounter: - case EOpMemoryBarrierBuffer: - case EOpMemoryBarrierImage: - case EOpMemoryBarrierShared: - case EOpGroupMemoryBarrier: - case EOpEmitVertex: - case EOpEndPrimitive: - writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction()); - break; - default: - UNREACHABLE(); - } - return visitChildren; -} - -bool TOutputGLSLBase::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - TInfoSinkBase &out = objSink(); - - // Variable declaration. - if (visit == PreVisit) - { - const TIntermSequence &sequence = *(node->getSequence()); - TIntermTyped *variable = sequence.front()->getAsTyped(); - writeLayoutQualifier(variable); - writeVariableType(variable->getType()); - if (variable->getAsSymbolNode() == nullptr || - !variable->getAsSymbolNode()->getSymbol().empty()) - { - out << " "; - } - mDeclaringVariable = true; - } - else if (visit == InVisit) - { - UNREACHABLE(); - } - else - { - mDeclaringVariable = false; - } - return true; -} - -bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) -{ - TInfoSinkBase &out = objSink(); - - TLoopType loopType = node->getType(); - - if (loopType == ELoopFor) // for loop - { - out << "for ("; - if (node->getInit()) - node->getInit()->traverse(this); - out << "; "; - - if (node->getCondition()) - node->getCondition()->traverse(this); - out << "; "; - - if (node->getExpression()) - node->getExpression()->traverse(this); - out << ")\n"; - - visitCodeBlock(node->getBody()); - } - else if (loopType == ELoopWhile) // while loop - { - out << "while ("; - ASSERT(node->getCondition() != nullptr); - node->getCondition()->traverse(this); - out << ")\n"; - - visitCodeBlock(node->getBody()); - } - else // do-while loop - { - ASSERT(loopType == ELoopDoWhile); - out << "do\n"; - - visitCodeBlock(node->getBody()); - - out << "while ("; - ASSERT(node->getCondition() != nullptr); - node->getCondition()->traverse(this); - out << ");\n"; - } - - // No need to visit children. They have been already processed in - // this function. - return false; -} - -bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch *node) -{ - switch (node->getFlowOp()) - { - case EOpKill: - writeTriplet(visit, "discard", nullptr, nullptr); - break; - case EOpBreak: - writeTriplet(visit, "break", nullptr, nullptr); - break; - case EOpContinue: - writeTriplet(visit, "continue", nullptr, nullptr); - break; - case EOpReturn: - writeTriplet(visit, "return ", nullptr, nullptr); - break; - default: - UNREACHABLE(); - } - - return true; -} - -void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node) -{ - TInfoSinkBase &out = objSink(); - if (node != nullptr) - { - node->traverse(this); - // Single statements not part of a sequence need to be terminated - // with semi-colon. - if (isSingleStatement(node)) - out << ";\n"; - } - else - { - out << "{\n}\n"; // Empty code block. - } -} - -TString TOutputGLSLBase::getTypeName(const TType &type) -{ - return GetTypeName(type, mHashFunction, &mNameMap); -} - -TString TOutputGLSLBase::hashName(const TName &name) -{ - return HashName(name, mHashFunction, &mNameMap); -} - -TString TOutputGLSLBase::hashVariableName(const TName &name) -{ - if (mSymbolTable->findBuiltIn(name.getString(), mShaderVersion) != nullptr || - name.getString().substr(0, 3) == "gl_") - { - if (mCompileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM && - name.getString() == "gl_ViewID_OVR") - { - TName uniformName(TString("ViewID_OVR")); - uniformName.setInternal(true); - return hashName(uniformName); - } - return name.getString(); - } - return hashName(name); -} - -TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info) -{ - if (info.isMain()) - { - return info.getName(); - } - else - { - return hashName(info.getNameObj()); - } -} - -bool TOutputGLSLBase::structDeclared(const TStructure *structure) const -{ - ASSERT(structure); - if (structure->name().empty()) - { - return false; - } - - return (mDeclaredStructs.count(structure->uniqueId()) > 0); -} - -void TOutputGLSLBase::declareStruct(const TStructure *structure) -{ - TInfoSinkBase &out = objSink(); - - out << "struct " << hashName(TName(structure->name())) << "{\n"; - const TFieldList &fields = structure->fields(); - for (size_t i = 0; i < fields.size(); ++i) - { - const TField *field = fields[i]; - if (writeVariablePrecision(field->type()->getPrecision())) - out << " "; - out << getTypeName(*field->type()) << " " << hashName(TName(field->name())); - if (field->type()->isArray()) - out << ArrayString(*field->type()); - out << ";\n"; - } - out << "}"; -} - -void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock) -{ - TInfoSinkBase &out = objSink(); - - out << "layout("; - - switch (interfaceBlock->blockStorage()) - { - case EbsUnspecified: - case EbsShared: - // Default block storage is shared. - out << "shared"; - break; - - case EbsPacked: - out << "packed"; - break; - - case EbsStd140: - out << "std140"; - break; - - case EbsStd430: - out << "std430"; - break; - - default: - UNREACHABLE(); - break; - } - - out << ", "; - - if (interfaceBlock->blockBinding() > 0) - { - out << "binding = " << interfaceBlock->blockBinding(); - out << ", "; - } - - switch (interfaceBlock->matrixPacking()) - { - case EmpUnspecified: - case EmpColumnMajor: - // Default matrix packing is column major. - out << "column_major"; - break; - - case EmpRowMajor: - out << "row_major"; - break; - - default: - UNREACHABLE(); - break; - } - - out << ") "; -} - -void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBlock) -{ - TInfoSinkBase &out = objSink(); - - out << hashName(TName(interfaceBlock->name())) << "{\n"; - const TFieldList &fields = interfaceBlock->fields(); - for (size_t i = 0; i < fields.size(); ++i) - { - const TField *field = fields[i]; - if (writeVariablePrecision(field->type()->getPrecision())) - out << " "; - out << getTypeName(*field->type()) << " " << hashName(TName(field->name())); - if (field->type()->isArray()) - out << ArrayString(*field->type()); - out << ";\n"; - } - out << "}"; -} - -void WriteGeometryShaderLayoutQualifiers(TInfoSinkBase &out, - sh::TLayoutPrimitiveType inputPrimitive, - int invocations, - sh::TLayoutPrimitiveType outputPrimitive, - int maxVertices) -{ - // Omit 'invocations = 1' - if (inputPrimitive != EptUndefined || invocations > 1) - { - out << "layout ("; - - if (inputPrimitive != EptUndefined) - { - out << getGeometryShaderPrimitiveTypeString(inputPrimitive); - } - - if (invocations > 1) - { - if (inputPrimitive != EptUndefined) - { - out << ", "; - } - out << "invocations = " << invocations; - } - out << ") in;\n"; - } - - if (outputPrimitive != EptUndefined || maxVertices != -1) - { - out << "layout ("; - - if (outputPrimitive != EptUndefined) - { - out << getGeometryShaderPrimitiveTypeString(outputPrimitive); - } - - if (maxVertices != -1) - { - if (outputPrimitive != EptUndefined) - { - out << ", "; - } - out << "max_vertices = " << maxVertices; - } - out << ") out;\n"; - } -} - -// If SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS is enabled, layout qualifiers are spilled whenever -// variables with specified layout qualifiers are copied. Additional checks are needed against the -// type and storage qualifier of the variable to verify that layout qualifiers have to be outputted. -// TODO (mradev): Fix layout qualifier spilling in ScalarizeVecAndMatConstructorArgs and remove -// NeedsToWriteLayoutQualifier. -bool NeedsToWriteLayoutQualifier(const TType &type) -{ - if (type.getBasicType() == EbtInterfaceBlock) - { - return false; - } - - const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); - - if ((type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn || - IsVarying(type.getQualifier())) && - layoutQualifier.location >= 0) - { - return true; - } - - if (type.getQualifier() == EvqFragmentOut && layoutQualifier.yuv == true) - { - return true; - } - - if (IsOpaqueType(type.getBasicType()) && layoutQualifier.binding != -1) - { - return true; - } - - if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified) - { - return true; - } - return false; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h deleted file mode 100644 index 592a310be4..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h +++ /dev/null @@ -1,122 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ -#define COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ - -#include <set> - -#include "compiler/translator/HashNames.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -class TOutputGLSLBase : public TIntermTraverser -{ - public: - TOutputGLSLBase(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions); - - ShShaderOutput getShaderOutput() const { return mOutput; } - - // Return the original name if hash function pointer is NULL; - // otherwise return the hashed name. Has special handling for internal names, which are not - // hashed. - TString hashName(const TName &name); - - protected: - TInfoSinkBase &objSink() { return mObjSink; } - void writeFloat(TInfoSinkBase &out, float f); - void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr); - virtual void writeLayoutQualifier(TIntermTyped *variable); - void writeInvariantQualifier(const TType &type); - void writeVariableType(const TType &type); - virtual bool writeVariablePrecision(TPrecision precision) = 0; - void writeFunctionParameters(const TIntermSequence &args); - const TConstantUnion *writeConstantUnion(const TType &type, const TConstantUnion *pConstUnion); - void writeConstructorTriplet(Visit visit, const TType &type); - TString getTypeName(const TType &type); - - void visitSymbol(TIntermSymbol *node) override; - void visitConstantUnion(TIntermConstantUnion *node) override; - bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitUnary(Visit visit, TIntermUnary *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - bool visitIfElse(Visit visit, TIntermIfElse *node) override; - bool visitSwitch(Visit visit, TIntermSwitch *node) override; - bool visitCase(Visit visit, TIntermCase *node) override; - bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitBlock(Visit visit, TIntermBlock *node) override; - bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override; - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - bool visitLoop(Visit visit, TIntermLoop *node) override; - bool visitBranch(Visit visit, TIntermBranch *node) override; - - void visitCodeBlock(TIntermBlock *node); - - // Same as hashName(), but without hashing built-in variables. - TString hashVariableName(const TName &name); - // Same as hashName(), but without hashing internal functions or "main". - TString hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info); - // Used to translate function names for differences between ESSL and GLSL - virtual TString translateTextureFunction(const TString &name) { return name; } - - private: - bool structDeclared(const TStructure *structure) const; - void declareStruct(const TStructure *structure); - - void declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock); - void declareInterfaceBlock(const TInterfaceBlock *interfaceBlock); - - void writeBuiltInFunctionTriplet(Visit visit, TOperator op, bool useEmulatedFunction); - - const char *mapQualifierToString(TQualifier qialifier); - - TInfoSinkBase &mObjSink; - bool mDeclaringVariable; - - // This set contains all the ids of the structs from every scope. - std::set<int> mDeclaredStructs; - - ShArrayIndexClampingStrategy mClampingStrategy; - - // name hashing. - ShHashFunction64 mHashFunction; - - NameMap &mNameMap; - - sh::GLenum mShaderType; - - const int mShaderVersion; - - ShShaderOutput mOutput; - - ShCompileOptions mCompileOptions; -}; - -void WriteGeometryShaderLayoutQualifiers(TInfoSinkBase &out, - sh::TLayoutPrimitiveType inputPrimitive, - int invocations, - sh::TLayoutPrimitiveType outputPrimitive, - int maxVertices); - -bool NeedsToWriteLayoutQualifier(const TType &type); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp deleted file mode 100644 index d5ff761430..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp +++ /dev/null @@ -1,3084 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/OutputHLSL.h" - -#include <algorithm> -#include <cfloat> -#include <stdio.h> - -#include "common/angleutils.h" -#include "common/debug.h" -#include "common/utilities.h" -#include "compiler/translator/BuiltInFunctionEmulator.h" -#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h" -#include "compiler/translator/ImageFunctionHLSL.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/NodeSearch.h" -#include "compiler/translator/RemoveSwitchFallThrough.h" -#include "compiler/translator/SearchSymbol.h" -#include "compiler/translator/StructureHLSL.h" -#include "compiler/translator/TextureFunctionHLSL.h" -#include "compiler/translator/TranslatorHLSL.h" -#include "compiler/translator/UniformHLSL.h" -#include "compiler/translator/UtilsHLSL.h" -#include "compiler/translator/blocklayout.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -TString ArrayHelperFunctionName(const char *prefix, const TType &type) -{ - TStringStream fnName; - fnName << prefix << "_"; - if (type.isArray()) - { - for (unsigned int arraySize : *type.getArraySizes()) - { - fnName << arraySize << "_"; - } - } - fnName << TypeString(type); - return fnName.str(); -} - -bool IsDeclarationWrittenOut(TIntermDeclaration *node) -{ - TIntermSequence *sequence = node->getSequence(); - TIntermTyped *variable = (*sequence)[0]->getAsTyped(); - ASSERT(sequence->size() == 1); - ASSERT(variable); - return (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal || - variable->getQualifier() == EvqConst); -} - -bool IsInStd140InterfaceBlock(TIntermTyped *node) -{ - TIntermBinary *binaryNode = node->getAsBinaryNode(); - - if (binaryNode) - { - return IsInStd140InterfaceBlock(binaryNode->getLeft()); - } - - const TType &type = node->getType(); - - // determine if we are in the standard layout - const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); - if (interfaceBlock) - { - return (interfaceBlock->blockStorage() == EbsStd140); - } - - return false; -} - -} // anonymous namespace - -void OutputHLSL::writeFloat(TInfoSinkBase &out, float f) -{ - // This is known not to work for NaN on all drivers but make the best effort to output NaNs - // regardless. - if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300 && - mOutputType == SH_HLSL_4_1_OUTPUT) - { - out << "asfloat(" << gl::bitCast<uint32_t>(f) << "u)"; - } - else - { - out << std::min(FLT_MAX, std::max(-FLT_MAX, f)); - } -} - -void OutputHLSL::writeSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion) -{ - ASSERT(constUnion != nullptr); - switch (constUnion->getType()) - { - case EbtFloat: - writeFloat(out, constUnion->getFConst()); - break; - case EbtInt: - out << constUnion->getIConst(); - break; - case EbtUInt: - out << constUnion->getUConst(); - break; - case EbtBool: - out << constUnion->getBConst(); - break; - default: - UNREACHABLE(); - } -} - -const TConstantUnion *OutputHLSL::writeConstantUnionArray(TInfoSinkBase &out, - const TConstantUnion *const constUnion, - const size_t size) -{ - const TConstantUnion *constUnionIterated = constUnion; - for (size_t i = 0; i < size; i++, constUnionIterated++) - { - writeSingleConstant(out, constUnionIterated); - - if (i != size - 1) - { - out << ", "; - } - } - return constUnionIterated; -} - -OutputHLSL::OutputHLSL(sh::GLenum shaderType, - int shaderVersion, - const TExtensionBehavior &extensionBehavior, - const char *sourcePath, - ShShaderOutput outputType, - int numRenderTargets, - const std::vector<Uniform> &uniforms, - ShCompileOptions compileOptions, - TSymbolTable *symbolTable, - PerformanceDiagnostics *perfDiagnostics) - : TIntermTraverser(true, true, true, symbolTable), - mShaderType(shaderType), - mShaderVersion(shaderVersion), - mExtensionBehavior(extensionBehavior), - mSourcePath(sourcePath), - mOutputType(outputType), - mCompileOptions(compileOptions), - mNumRenderTargets(numRenderTargets), - mCurrentFunctionMetadata(nullptr), - mPerfDiagnostics(perfDiagnostics) -{ - mInsideFunction = false; - - mUsesFragColor = false; - mUsesFragData = false; - mUsesDepthRange = false; - mUsesFragCoord = false; - mUsesPointCoord = false; - mUsesFrontFacing = false; - mUsesPointSize = false; - mUsesInstanceID = false; - mHasMultiviewExtensionEnabled = - IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview); - mUsesViewID = false; - mUsesVertexID = false; - mUsesFragDepth = false; - mUsesNumWorkGroups = false; - mUsesWorkGroupID = false; - mUsesLocalInvocationID = false; - mUsesGlobalInvocationID = false; - mUsesLocalInvocationIndex = false; - mUsesXor = false; - mUsesDiscardRewriting = false; - mUsesNestedBreak = false; - mRequiresIEEEStrictCompiling = false; - - mUniqueIndex = 0; - - mOutputLod0Function = false; - mInsideDiscontinuousLoop = false; - mNestedLoopDepth = 0; - - mExcessiveLoopIndex = nullptr; - - mStructureHLSL = new StructureHLSL; - mUniformHLSL = new UniformHLSL(shaderType, mStructureHLSL, outputType, uniforms); - mTextureFunctionHLSL = new TextureFunctionHLSL; - mImageFunctionHLSL = new ImageFunctionHLSL; - - if (mOutputType == SH_HLSL_3_0_OUTPUT) - { - // Fragment shaders need dx_DepthRange, dx_ViewCoords and dx_DepthFront. - // Vertex shaders need a slightly different set: dx_DepthRange, dx_ViewCoords and - // dx_ViewAdjust. - // In both cases total 3 uniform registers need to be reserved. - mUniformHLSL->reserveUniformRegisters(3); - } - - // Reserve registers for the default uniform block and driver constants - mUniformHLSL->reserveUniformBlockRegisters(2); -} - -OutputHLSL::~OutputHLSL() -{ - SafeDelete(mStructureHLSL); - SafeDelete(mUniformHLSL); - SafeDelete(mTextureFunctionHLSL); - SafeDelete(mImageFunctionHLSL); - for (auto &eqFunction : mStructEqualityFunctions) - { - SafeDelete(eqFunction); - } - for (auto &eqFunction : mArrayEqualityFunctions) - { - SafeDelete(eqFunction); - } -} - -void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink) -{ - BuiltInFunctionEmulator builtInFunctionEmulator; - InitBuiltInFunctionEmulatorForHLSL(&builtInFunctionEmulator); - if ((mCompileOptions & SH_EMULATE_ISNAN_FLOAT_FUNCTION) != 0) - { - InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(&builtInFunctionEmulator, - mShaderVersion); - } - - builtInFunctionEmulator.markBuiltInFunctionsForEmulation(treeRoot); - - // Now that we are done changing the AST, do the analyses need for HLSL generation - CallDAG::InitResult success = mCallDag.init(treeRoot, nullptr); - ASSERT(success == CallDAG::INITDAG_SUCCESS); - mASTMetadataList = CreateASTMetadataHLSL(treeRoot, mCallDag); - - const std::vector<MappedStruct> std140Structs = FlagStd140Structs(treeRoot); - // TODO(oetuaho): The std140Structs could be filtered based on which ones actually get used in - // the shader code. When we add shader storage blocks we might also consider an alternative - // solution, since the struct mapping won't work very well for shader storage blocks. - - // Output the body and footer first to determine what has to go in the header - mInfoSinkStack.push(&mBody); - treeRoot->traverse(this); - mInfoSinkStack.pop(); - - mInfoSinkStack.push(&mFooter); - mInfoSinkStack.pop(); - - mInfoSinkStack.push(&mHeader); - header(mHeader, std140Structs, &builtInFunctionEmulator); - mInfoSinkStack.pop(); - - objSink << mHeader.c_str(); - objSink << mBody.c_str(); - objSink << mFooter.c_str(); - - builtInFunctionEmulator.cleanup(); -} - -const std::map<std::string, unsigned int> &OutputHLSL::getUniformBlockRegisterMap() const -{ - return mUniformHLSL->getUniformBlockRegisterMap(); -} - -const std::map<std::string, unsigned int> &OutputHLSL::getUniformRegisterMap() const -{ - return mUniformHLSL->getUniformRegisterMap(); -} - -TString OutputHLSL::structInitializerString(int indent, - const TType &type, - const TString &name) const -{ - TString init; - - TString indentString; - for (int spaces = 0; spaces < indent; spaces++) - { - indentString += " "; - } - - if (type.isArray()) - { - init += indentString + "{\n"; - for (unsigned int arrayIndex = 0u; arrayIndex < type.getOutermostArraySize(); ++arrayIndex) - { - TStringStream indexedString; - indexedString << name << "[" << arrayIndex << "]"; - TType elementType = type; - elementType.toArrayElementType(); - init += structInitializerString(indent + 1, elementType, indexedString.str()); - if (arrayIndex < type.getOutermostArraySize() - 1) - { - init += ","; - } - init += "\n"; - } - init += indentString + "}"; - } - else if (type.getBasicType() == EbtStruct) - { - init += indentString + "{\n"; - const TStructure &structure = *type.getStruct(); - const TFieldList &fields = structure.fields(); - for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) - { - const TField &field = *fields[fieldIndex]; - const TString &fieldName = name + "." + Decorate(field.name()); - const TType &fieldType = *field.type(); - - init += structInitializerString(indent + 1, fieldType, fieldName); - if (fieldIndex < fields.size() - 1) - { - init += ","; - } - init += "\n"; - } - init += indentString + "}"; - } - else - { - init += indentString + name; - } - - return init; -} - -TString OutputHLSL::generateStructMapping(const std::vector<MappedStruct> &std140Structs) const -{ - TString mappedStructs; - - for (auto &mappedStruct : std140Structs) - { - TInterfaceBlock *interfaceBlock = - mappedStruct.blockDeclarator->getType().getInterfaceBlock(); - const TString &interfaceBlockName = interfaceBlock->name(); - const TName &instanceName = mappedStruct.blockDeclarator->getName(); - if (mReferencedUniformBlocks.count(interfaceBlockName) == 0 && - (instanceName.getString() == "" || - mReferencedUniformBlocks.count(instanceName.getString()) == 0)) - { - continue; - } - - unsigned int instanceCount = 1u; - bool isInstanceArray = mappedStruct.blockDeclarator->isArray(); - if (isInstanceArray) - { - instanceCount = mappedStruct.blockDeclarator->getOutermostArraySize(); - } - - for (unsigned int instanceArrayIndex = 0; instanceArrayIndex < instanceCount; - ++instanceArrayIndex) - { - TString originalName; - TString mappedName("map"); - - if (instanceName.getString() != "") - { - unsigned int instanceStringArrayIndex = GL_INVALID_INDEX; - if (isInstanceArray) - instanceStringArrayIndex = instanceArrayIndex; - TString instanceString = mUniformHLSL->uniformBlockInstanceString( - *interfaceBlock, instanceStringArrayIndex); - originalName += instanceString; - mappedName += instanceString; - originalName += "."; - mappedName += "_"; - } - - TString fieldName = Decorate(mappedStruct.field->name()); - originalName += fieldName; - mappedName += fieldName; - - TType *structType = mappedStruct.field->type(); - mappedStructs += - "static " + Decorate(structType->getStruct()->name()) + " " + mappedName; - - if (structType->isArray()) - { - mappedStructs += ArrayString(*mappedStruct.field->type()); - } - - mappedStructs += " =\n"; - mappedStructs += structInitializerString(0, *structType, originalName); - mappedStructs += ";\n"; - } - } - return mappedStructs; -} - -void OutputHLSL::header(TInfoSinkBase &out, - const std::vector<MappedStruct> &std140Structs, - const BuiltInFunctionEmulator *builtInFunctionEmulator) const -{ - TString varyings; - TString attributes; - TString mappedStructs = generateStructMapping(std140Structs); - - for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); - varying != mReferencedVaryings.end(); varying++) - { - const TType &type = varying->second->getType(); - const TString &name = varying->second->getSymbol(); - - // Program linking depends on this exact format - varyings += "static " + InterpolationString(type.getQualifier()) + " " + TypeString(type) + - " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n"; - } - - for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); - attribute != mReferencedAttributes.end(); attribute++) - { - const TType &type = attribute->second->getType(); - const TString &name = attribute->second->getSymbol(); - - attributes += "static " + TypeString(type) + " " + Decorate(name) + ArrayString(type) + - " = " + initializer(type) + ";\n"; - } - - out << mStructureHLSL->structsHeader(); - - mUniformHLSL->uniformsHeader(out, mOutputType, mReferencedUniforms, mSymbolTable); - out << mUniformHLSL->uniformBlocksHeader(mReferencedUniformBlocks); - - if (!mEqualityFunctions.empty()) - { - out << "\n// Equality functions\n\n"; - for (const auto &eqFunction : mEqualityFunctions) - { - out << eqFunction->functionDefinition << "\n"; - } - } - if (!mArrayAssignmentFunctions.empty()) - { - out << "\n// Assignment functions\n\n"; - for (const auto &assignmentFunction : mArrayAssignmentFunctions) - { - out << assignmentFunction.functionDefinition << "\n"; - } - } - if (!mArrayConstructIntoFunctions.empty()) - { - out << "\n// Array constructor functions\n\n"; - for (const auto &constructIntoFunction : mArrayConstructIntoFunctions) - { - out << constructIntoFunction.functionDefinition << "\n"; - } - } - - if (mUsesDiscardRewriting) - { - out << "#define ANGLE_USES_DISCARD_REWRITING\n"; - } - - if (mUsesNestedBreak) - { - out << "#define ANGLE_USES_NESTED_BREAK\n"; - } - - if (mRequiresIEEEStrictCompiling) - { - out << "#define ANGLE_REQUIRES_IEEE_STRICT_COMPILING\n"; - } - - out << "#ifdef ANGLE_ENABLE_LOOP_FLATTEN\n" - "#define LOOP [loop]\n" - "#define FLATTEN [flatten]\n" - "#else\n" - "#define LOOP\n" - "#define FLATTEN\n" - "#endif\n"; - - if (mShaderType == GL_FRAGMENT_SHADER) - { - const bool usingMRTExtension = - IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers); - - out << "// Varyings\n"; - out << varyings; - out << "\n"; - - if (mShaderVersion >= 300) - { - for (ReferencedSymbols::const_iterator outputVariableIt = - mReferencedOutputVariables.begin(); - outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++) - { - const TString &variableName = outputVariableIt->first; - const TType &variableType = outputVariableIt->second->getType(); - - out << "static " + TypeString(variableType) + " out_" + variableName + - ArrayString(variableType) + " = " + initializer(variableType) + ";\n"; - } - } - else - { - const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1; - - out << "static float4 gl_Color[" << numColorValues << "] =\n" - "{\n"; - for (unsigned int i = 0; i < numColorValues; i++) - { - out << " float4(0, 0, 0, 0)"; - if (i + 1 != numColorValues) - { - out << ","; - } - out << "\n"; - } - - out << "};\n"; - } - - if (mUsesFragDepth) - { - out << "static float gl_Depth = 0.0;\n"; - } - - if (mUsesFragCoord) - { - out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n"; - } - - if (mUsesPointCoord) - { - out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n"; - } - - if (mUsesFrontFacing) - { - out << "static bool gl_FrontFacing = false;\n"; - } - - out << "\n"; - - if (mUsesDepthRange) - { - out << "struct gl_DepthRangeParameters\n" - "{\n" - " float near;\n" - " float far;\n" - " float diff;\n" - "};\n" - "\n"; - } - - if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - out << "cbuffer DriverConstants : register(b1)\n" - "{\n"; - - if (mUsesDepthRange) - { - out << " float3 dx_DepthRange : packoffset(c0);\n"; - } - - if (mUsesFragCoord) - { - out << " float4 dx_ViewCoords : packoffset(c1);\n"; - } - - if (mUsesFragCoord || mUsesFrontFacing) - { - out << " float3 dx_DepthFront : packoffset(c2);\n"; - } - - if (mUsesFragCoord) - { - // dx_ViewScale is only used in the fragment shader to correct - // the value for glFragCoord if necessary - out << " float2 dx_ViewScale : packoffset(c3);\n"; - } - - if (mHasMultiviewExtensionEnabled) - { - // We have to add a value which we can use to keep track of which multi-view code - // path is to be selected in the GS. - out << " float multiviewSelectViewportIndex : packoffset(c3.z);\n"; - } - - if (mOutputType == SH_HLSL_4_1_OUTPUT) - { - mUniformHLSL->samplerMetadataUniforms(out, "c4"); - } - - out << "};\n"; - } - else - { - if (mUsesDepthRange) - { - out << "uniform float3 dx_DepthRange : register(c0);"; - } - - if (mUsesFragCoord) - { - out << "uniform float4 dx_ViewCoords : register(c1);\n"; - } - - if (mUsesFragCoord || mUsesFrontFacing) - { - out << "uniform float3 dx_DepthFront : register(c2);\n"; - } - } - - out << "\n"; - - if (mUsesDepthRange) - { - out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, " - "dx_DepthRange.y, dx_DepthRange.z};\n" - "\n"; - } - - if (!mappedStructs.empty()) - { - out << "// Structures from std140 blocks with padding removed\n"; - out << "\n"; - out << mappedStructs; - out << "\n"; - } - - if (usingMRTExtension && mNumRenderTargets > 1) - { - out << "#define GL_USES_MRT\n"; - } - - if (mUsesFragColor) - { - out << "#define GL_USES_FRAG_COLOR\n"; - } - - if (mUsesFragData) - { - out << "#define GL_USES_FRAG_DATA\n"; - } - } - else if (mShaderType == GL_VERTEX_SHADER) - { - out << "// Attributes\n"; - out << attributes; - out << "\n" - "static float4 gl_Position = float4(0, 0, 0, 0);\n"; - - if (mUsesPointSize) - { - out << "static float gl_PointSize = float(1);\n"; - } - - if (mUsesInstanceID) - { - out << "static int gl_InstanceID;"; - } - - if (mUsesVertexID) - { - out << "static int gl_VertexID;"; - } - - out << "\n" - "// Varyings\n"; - out << varyings; - out << "\n"; - - if (mUsesDepthRange) - { - out << "struct gl_DepthRangeParameters\n" - "{\n" - " float near;\n" - " float far;\n" - " float diff;\n" - "};\n" - "\n"; - } - - if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - out << "cbuffer DriverConstants : register(b1)\n" - "{\n"; - - if (mUsesDepthRange) - { - out << " float3 dx_DepthRange : packoffset(c0);\n"; - } - - // dx_ViewAdjust and dx_ViewCoords will only be used in Feature Level 9 - // shaders. However, we declare it for all shaders (including Feature Level 10+). - // The bytecode is the same whether we declare it or not, since D3DCompiler removes it - // if it's unused. - out << " float4 dx_ViewAdjust : packoffset(c1);\n"; - out << " float2 dx_ViewCoords : packoffset(c2);\n"; - out << " float2 dx_ViewScale : packoffset(c3);\n"; - - if (mHasMultiviewExtensionEnabled) - { - // We have to add a value which we can use to keep track of which multi-view code - // path is to be selected in the GS. - out << " float multiviewSelectViewportIndex : packoffset(c3.z);\n"; - } - - if (mOutputType == SH_HLSL_4_1_OUTPUT) - { - mUniformHLSL->samplerMetadataUniforms(out, "c4"); - } - - out << "};\n" - "\n"; - } - else - { - if (mUsesDepthRange) - { - out << "uniform float3 dx_DepthRange : register(c0);\n"; - } - - out << "uniform float4 dx_ViewAdjust : register(c1);\n"; - out << "uniform float2 dx_ViewCoords : register(c2);\n" - "\n"; - } - - if (mUsesDepthRange) - { - out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, " - "dx_DepthRange.y, dx_DepthRange.z};\n" - "\n"; - } - - if (!mappedStructs.empty()) - { - out << "// Structures from std140 blocks with padding removed\n"; - out << "\n"; - out << mappedStructs; - out << "\n"; - } - } - else // Compute shader - { - ASSERT(mShaderType == GL_COMPUTE_SHADER); - - out << "cbuffer DriverConstants : register(b1)\n" - "{\n"; - if (mUsesNumWorkGroups) - { - out << " uint3 gl_NumWorkGroups : packoffset(c0);\n"; - } - ASSERT(mOutputType == SH_HLSL_4_1_OUTPUT); - mUniformHLSL->samplerMetadataUniforms(out, "c1"); - out << "};\n"; - - // Follow built-in variables would be initialized in - // DynamicHLSL::generateComputeShaderLinkHLSL, if they - // are used in compute shader. - if (mUsesWorkGroupID) - { - out << "static uint3 gl_WorkGroupID = uint3(0, 0, 0);\n"; - } - - if (mUsesLocalInvocationID) - { - out << "static uint3 gl_LocalInvocationID = uint3(0, 0, 0);\n"; - } - - if (mUsesGlobalInvocationID) - { - out << "static uint3 gl_GlobalInvocationID = uint3(0, 0, 0);\n"; - } - - if (mUsesLocalInvocationIndex) - { - out << "static uint gl_LocalInvocationIndex = uint(0);\n"; - } - } - - bool getDimensionsIgnoresBaseLevel = - (mCompileOptions & SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL) != 0; - mTextureFunctionHLSL->textureFunctionHeader(out, mOutputType, getDimensionsIgnoresBaseLevel); - mImageFunctionHLSL->imageFunctionHeader(out); - - if (mUsesFragCoord) - { - out << "#define GL_USES_FRAG_COORD\n"; - } - - if (mUsesPointCoord) - { - out << "#define GL_USES_POINT_COORD\n"; - } - - if (mUsesFrontFacing) - { - out << "#define GL_USES_FRONT_FACING\n"; - } - - if (mUsesPointSize) - { - out << "#define GL_USES_POINT_SIZE\n"; - } - - if (mHasMultiviewExtensionEnabled) - { - out << "#define GL_ANGLE_MULTIVIEW_ENABLED\n"; - } - - if (mUsesViewID) - { - out << "#define GL_USES_VIEW_ID\n"; - } - - if (mUsesFragDepth) - { - out << "#define GL_USES_FRAG_DEPTH\n"; - } - - if (mUsesDepthRange) - { - out << "#define GL_USES_DEPTH_RANGE\n"; - } - - if (mUsesNumWorkGroups) - { - out << "#define GL_USES_NUM_WORK_GROUPS\n"; - } - - if (mUsesWorkGroupID) - { - out << "#define GL_USES_WORK_GROUP_ID\n"; - } - - if (mUsesLocalInvocationID) - { - out << "#define GL_USES_LOCAL_INVOCATION_ID\n"; - } - - if (mUsesGlobalInvocationID) - { - out << "#define GL_USES_GLOBAL_INVOCATION_ID\n"; - } - - if (mUsesLocalInvocationIndex) - { - out << "#define GL_USES_LOCAL_INVOCATION_INDEX\n"; - } - - if (mUsesXor) - { - out << "bool xor(bool p, bool q)\n" - "{\n" - " return (p || q) && !(p && q);\n" - "}\n" - "\n"; - } - - builtInFunctionEmulator->outputEmulatedFunctions(out); -} - -void OutputHLSL::visitSymbol(TIntermSymbol *node) -{ - TInfoSinkBase &out = getInfoSink(); - - // Handle accessing std140 structs by value - if (IsInStd140InterfaceBlock(node) && node->getBasicType() == EbtStruct) - { - out << "map"; - } - - TString name = node->getSymbol(); - - if (name == "gl_DepthRange") - { - mUsesDepthRange = true; - out << name; - } - else - { - const TType &nodeType = node->getType(); - TQualifier qualifier = node->getQualifier(); - - ensureStructDefined(nodeType); - - if (qualifier == EvqUniform) - { - const TInterfaceBlock *interfaceBlock = nodeType.getInterfaceBlock(); - - if (interfaceBlock) - { - mReferencedUniformBlocks[interfaceBlock->name()] = node; - } - else - { - mReferencedUniforms[name] = node; - } - - out << DecorateVariableIfNeeded(node->getName()); - } - else if (qualifier == EvqAttribute || qualifier == EvqVertexIn) - { - mReferencedAttributes[name] = node; - out << Decorate(name); - } - else if (IsVarying(qualifier)) - { - mReferencedVaryings[name] = node; - out << Decorate(name); - if (name == "ViewID_OVR") - { - mUsesViewID = true; - } - } - else if (qualifier == EvqFragmentOut) - { - mReferencedOutputVariables[name] = node; - out << "out_" << name; - } - else if (qualifier == EvqFragColor) - { - out << "gl_Color[0]"; - mUsesFragColor = true; - } - else if (qualifier == EvqFragData) - { - out << "gl_Color"; - mUsesFragData = true; - } - else if (qualifier == EvqFragCoord) - { - mUsesFragCoord = true; - out << name; - } - else if (qualifier == EvqPointCoord) - { - mUsesPointCoord = true; - out << name; - } - else if (qualifier == EvqFrontFacing) - { - mUsesFrontFacing = true; - out << name; - } - else if (qualifier == EvqPointSize) - { - mUsesPointSize = true; - out << name; - } - else if (qualifier == EvqInstanceID) - { - mUsesInstanceID = true; - out << name; - } - else if (qualifier == EvqVertexID) - { - mUsesVertexID = true; - out << name; - } - else if (name == "gl_FragDepthEXT" || name == "gl_FragDepth") - { - mUsesFragDepth = true; - out << "gl_Depth"; - } - else if (qualifier == EvqNumWorkGroups) - { - mUsesNumWorkGroups = true; - out << name; - } - else if (qualifier == EvqWorkGroupID) - { - mUsesWorkGroupID = true; - out << name; - } - else if (qualifier == EvqLocalInvocationID) - { - mUsesLocalInvocationID = true; - out << name; - } - else if (qualifier == EvqGlobalInvocationID) - { - mUsesGlobalInvocationID = true; - out << name; - } - else if (qualifier == EvqLocalInvocationIndex) - { - mUsesLocalInvocationIndex = true; - out << name; - } - else - { - out << DecorateVariableIfNeeded(node->getName()); - } - } -} - -void OutputHLSL::visitRaw(TIntermRaw *node) -{ - getInfoSink() << node->getRawText(); -} - -void OutputHLSL::outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out) -{ - if (type.isScalar() && !type.isArray()) - { - if (op == EOpEqual) - { - outputTriplet(out, visit, "(", " == ", ")"); - } - else - { - outputTriplet(out, visit, "(", " != ", ")"); - } - } - else - { - if (visit == PreVisit && op == EOpNotEqual) - { - out << "!"; - } - - if (type.isArray()) - { - const TString &functionName = addArrayEqualityFunction(type); - outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")"); - } - else if (type.getBasicType() == EbtStruct) - { - const TStructure &structure = *type.getStruct(); - const TString &functionName = addStructEqualityFunction(structure); - outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")"); - } - else - { - ASSERT(type.isMatrix() || type.isVector()); - outputTriplet(out, visit, "all(", " == ", ")"); - } - } -} - -void OutputHLSL::outputAssign(Visit visit, const TType &type, TInfoSinkBase &out) -{ - if (type.isArray()) - { - const TString &functionName = addArrayAssignmentFunction(type); - outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")"); - } - else - { - outputTriplet(out, visit, "(", " = ", ")"); - } -} - -bool OutputHLSL::ancestorEvaluatesToSamplerInStruct() -{ - for (unsigned int n = 0u; getAncestorNode(n) != nullptr; ++n) - { - TIntermNode *ancestor = getAncestorNode(n); - const TIntermBinary *ancestorBinary = ancestor->getAsBinaryNode(); - if (ancestorBinary == nullptr) - { - return false; - } - switch (ancestorBinary->getOp()) - { - case EOpIndexDirectStruct: - { - const TStructure *structure = ancestorBinary->getLeft()->getType().getStruct(); - const TIntermConstantUnion *index = - ancestorBinary->getRight()->getAsConstantUnion(); - const TField *field = structure->fields()[index->getIConst(0)]; - if (IsSampler(field->type()->getBasicType())) - { - return true; - } - break; - } - case EOpIndexDirect: - break; - default: - // Returning a sampler from indirect indexing is not supported. - return false; - } - } - return false; -} - -bool OutputHLSL::visitSwizzle(Visit visit, TIntermSwizzle *node) -{ - TInfoSinkBase &out = getInfoSink(); - if (visit == PostVisit) - { - out << "."; - node->writeOffsetsAsXYZW(&out); - } - return true; -} - -bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) -{ - TInfoSinkBase &out = getInfoSink(); - - switch (node->getOp()) - { - case EOpComma: - outputTriplet(out, visit, "(", ", ", ")"); - break; - case EOpAssign: - if (node->isArray()) - { - TIntermAggregate *rightAgg = node->getRight()->getAsAggregate(); - if (rightAgg != nullptr && rightAgg->isConstructor()) - { - const TString &functionName = addArrayConstructIntoFunction(node->getType()); - out << functionName << "("; - node->getLeft()->traverse(this); - TIntermSequence *seq = rightAgg->getSequence(); - for (auto &arrayElement : *seq) - { - out << ", "; - arrayElement->traverse(this); - } - out << ")"; - return false; - } - // ArrayReturnValueToOutParameter should have eliminated expressions where a - // function call is assigned. - ASSERT(rightAgg == nullptr); - } - outputAssign(visit, node->getType(), out); - break; - case EOpInitialize: - if (visit == PreVisit) - { - TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode(); - ASSERT(symbolNode); - TIntermTyped *expression = node->getRight(); - - // Global initializers must be constant at this point. - ASSERT(symbolNode->getQualifier() != EvqGlobal || - canWriteAsHLSLLiteral(expression)); - - // GLSL allows to write things like "float x = x;" where a new variable x is defined - // and the value of an existing variable x is assigned. HLSL uses C semantics (the - // new variable is created before the assignment is evaluated), so we need to - // convert - // this to "float t = x, x = t;". - if (writeSameSymbolInitializer(out, symbolNode, expression)) - { - // Skip initializing the rest of the expression - return false; - } - else if (writeConstantInitialization(out, symbolNode, expression)) - { - return false; - } - } - else if (visit == InVisit) - { - out << " = "; - } - break; - case EOpAddAssign: - outputTriplet(out, visit, "(", " += ", ")"); - break; - case EOpSubAssign: - outputTriplet(out, visit, "(", " -= ", ")"); - break; - case EOpMulAssign: - outputTriplet(out, visit, "(", " *= ", ")"); - break; - case EOpVectorTimesScalarAssign: - outputTriplet(out, visit, "(", " *= ", ")"); - break; - case EOpMatrixTimesScalarAssign: - outputTriplet(out, visit, "(", " *= ", ")"); - break; - case EOpVectorTimesMatrixAssign: - if (visit == PreVisit) - { - out << "("; - } - else if (visit == InVisit) - { - out << " = mul("; - node->getLeft()->traverse(this); - out << ", transpose("; - } - else - { - out << ")))"; - } - break; - case EOpMatrixTimesMatrixAssign: - if (visit == PreVisit) - { - out << "("; - } - else if (visit == InVisit) - { - out << " = transpose(mul(transpose("; - node->getLeft()->traverse(this); - out << "), transpose("; - } - else - { - out << "))))"; - } - break; - case EOpDivAssign: - outputTriplet(out, visit, "(", " /= ", ")"); - break; - case EOpIModAssign: - outputTriplet(out, visit, "(", " %= ", ")"); - break; - case EOpBitShiftLeftAssign: - outputTriplet(out, visit, "(", " <<= ", ")"); - break; - case EOpBitShiftRightAssign: - outputTriplet(out, visit, "(", " >>= ", ")"); - break; - case EOpBitwiseAndAssign: - outputTriplet(out, visit, "(", " &= ", ")"); - break; - case EOpBitwiseXorAssign: - outputTriplet(out, visit, "(", " ^= ", ")"); - break; - case EOpBitwiseOrAssign: - outputTriplet(out, visit, "(", " |= ", ")"); - break; - case EOpIndexDirect: - { - const TType &leftType = node->getLeft()->getType(); - if (leftType.isInterfaceBlock()) - { - if (visit == PreVisit) - { - TInterfaceBlock *interfaceBlock = leftType.getInterfaceBlock(); - const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0); - mReferencedUniformBlocks[interfaceBlock->instanceName()] = - node->getLeft()->getAsSymbolNode(); - out << mUniformHLSL->uniformBlockInstanceString(*interfaceBlock, arrayIndex); - return false; - } - } - else if (ancestorEvaluatesToSamplerInStruct()) - { - // All parts of an expression that access a sampler in a struct need to use _ as - // separator to access the sampler variable that has been moved out of the struct. - outputTriplet(out, visit, "", "_", ""); - } - else - { - outputTriplet(out, visit, "", "[", "]"); - } - } - break; - case EOpIndexIndirect: - // We do not currently support indirect references to interface blocks - ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock); - outputTriplet(out, visit, "", "[", "]"); - break; - case EOpIndexDirectStruct: - { - const TStructure *structure = node->getLeft()->getType().getStruct(); - const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); - const TField *field = structure->fields()[index->getIConst(0)]; - - // In cases where indexing returns a sampler, we need to access the sampler variable - // that has been moved out of the struct. - bool indexingReturnsSampler = IsSampler(field->type()->getBasicType()); - if (visit == PreVisit && indexingReturnsSampler) - { - // Samplers extracted from structs have "angle" prefix to avoid name conflicts. - // This prefix is only output at the beginning of the indexing expression, which - // may have multiple parts. - out << "angle"; - } - if (!indexingReturnsSampler) - { - // All parts of an expression that access a sampler in a struct need to use _ as - // separator to access the sampler variable that has been moved out of the struct. - indexingReturnsSampler = ancestorEvaluatesToSamplerInStruct(); - } - if (visit == InVisit) - { - if (indexingReturnsSampler) - { - out << "_" + field->name(); - } - else - { - out << "." + DecorateField(field->name(), *structure); - } - - return false; - } - } - break; - case EOpIndexDirectInterfaceBlock: - { - bool structInStd140Block = - node->getBasicType() == EbtStruct && IsInStd140InterfaceBlock(node->getLeft()); - if (visit == PreVisit && structInStd140Block) - { - out << "map"; - } - if (visit == InVisit) - { - const TInterfaceBlock *interfaceBlock = - node->getLeft()->getType().getInterfaceBlock(); - const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); - const TField *field = interfaceBlock->fields()[index->getIConst(0)]; - if (structInStd140Block) - { - out << "_"; - } - else - { - out << "."; - } - out << Decorate(field->name()); - - return false; - } - break; - } - case EOpAdd: - outputTriplet(out, visit, "(", " + ", ")"); - break; - case EOpSub: - outputTriplet(out, visit, "(", " - ", ")"); - break; - case EOpMul: - outputTriplet(out, visit, "(", " * ", ")"); - break; - case EOpDiv: - outputTriplet(out, visit, "(", " / ", ")"); - break; - case EOpIMod: - outputTriplet(out, visit, "(", " % ", ")"); - break; - case EOpBitShiftLeft: - outputTriplet(out, visit, "(", " << ", ")"); - break; - case EOpBitShiftRight: - outputTriplet(out, visit, "(", " >> ", ")"); - break; - case EOpBitwiseAnd: - outputTriplet(out, visit, "(", " & ", ")"); - break; - case EOpBitwiseXor: - outputTriplet(out, visit, "(", " ^ ", ")"); - break; - case EOpBitwiseOr: - outputTriplet(out, visit, "(", " | ", ")"); - break; - case EOpEqual: - case EOpNotEqual: - outputEqual(visit, node->getLeft()->getType(), node->getOp(), out); - break; - case EOpLessThan: - outputTriplet(out, visit, "(", " < ", ")"); - break; - case EOpGreaterThan: - outputTriplet(out, visit, "(", " > ", ")"); - break; - case EOpLessThanEqual: - outputTriplet(out, visit, "(", " <= ", ")"); - break; - case EOpGreaterThanEqual: - outputTriplet(out, visit, "(", " >= ", ")"); - break; - case EOpVectorTimesScalar: - outputTriplet(out, visit, "(", " * ", ")"); - break; - case EOpMatrixTimesScalar: - outputTriplet(out, visit, "(", " * ", ")"); - break; - case EOpVectorTimesMatrix: - outputTriplet(out, visit, "mul(", ", transpose(", "))"); - break; - case EOpMatrixTimesVector: - outputTriplet(out, visit, "mul(transpose(", "), ", ")"); - break; - case EOpMatrixTimesMatrix: - outputTriplet(out, visit, "transpose(mul(transpose(", "), transpose(", ")))"); - break; - case EOpLogicalOr: - // HLSL doesn't short-circuit ||, so we assume that || affected by short-circuiting have - // been unfolded. - ASSERT(!node->getRight()->hasSideEffects()); - outputTriplet(out, visit, "(", " || ", ")"); - return true; - case EOpLogicalXor: - mUsesXor = true; - outputTriplet(out, visit, "xor(", ", ", ")"); - break; - case EOpLogicalAnd: - // HLSL doesn't short-circuit &&, so we assume that && affected by short-circuiting have - // been unfolded. - ASSERT(!node->getRight()->hasSideEffects()); - outputTriplet(out, visit, "(", " && ", ")"); - return true; - default: - UNREACHABLE(); - } - - return true; -} - -bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) -{ - TInfoSinkBase &out = getInfoSink(); - - switch (node->getOp()) - { - case EOpNegative: - outputTriplet(out, visit, "(-", "", ")"); - break; - case EOpPositive: - outputTriplet(out, visit, "(+", "", ")"); - break; - case EOpLogicalNot: - outputTriplet(out, visit, "(!", "", ")"); - break; - case EOpBitwiseNot: - outputTriplet(out, visit, "(~", "", ")"); - break; - case EOpPostIncrement: - outputTriplet(out, visit, "(", "", "++)"); - break; - case EOpPostDecrement: - outputTriplet(out, visit, "(", "", "--)"); - break; - case EOpPreIncrement: - outputTriplet(out, visit, "(++", "", ")"); - break; - case EOpPreDecrement: - outputTriplet(out, visit, "(--", "", ")"); - break; - case EOpRadians: - outputTriplet(out, visit, "radians(", "", ")"); - break; - case EOpDegrees: - outputTriplet(out, visit, "degrees(", "", ")"); - break; - case EOpSin: - outputTriplet(out, visit, "sin(", "", ")"); - break; - case EOpCos: - outputTriplet(out, visit, "cos(", "", ")"); - break; - case EOpTan: - outputTriplet(out, visit, "tan(", "", ")"); - break; - case EOpAsin: - outputTriplet(out, visit, "asin(", "", ")"); - break; - case EOpAcos: - outputTriplet(out, visit, "acos(", "", ")"); - break; - case EOpAtan: - outputTriplet(out, visit, "atan(", "", ")"); - break; - case EOpSinh: - outputTriplet(out, visit, "sinh(", "", ")"); - break; - case EOpCosh: - outputTriplet(out, visit, "cosh(", "", ")"); - break; - case EOpTanh: - outputTriplet(out, visit, "tanh(", "", ")"); - break; - case EOpAsinh: - case EOpAcosh: - case EOpAtanh: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpExp: - outputTriplet(out, visit, "exp(", "", ")"); - break; - case EOpLog: - outputTriplet(out, visit, "log(", "", ")"); - break; - case EOpExp2: - outputTriplet(out, visit, "exp2(", "", ")"); - break; - case EOpLog2: - outputTriplet(out, visit, "log2(", "", ")"); - break; - case EOpSqrt: - outputTriplet(out, visit, "sqrt(", "", ")"); - break; - case EOpInverseSqrt: - outputTriplet(out, visit, "rsqrt(", "", ")"); - break; - case EOpAbs: - outputTriplet(out, visit, "abs(", "", ")"); - break; - case EOpSign: - outputTriplet(out, visit, "sign(", "", ")"); - break; - case EOpFloor: - outputTriplet(out, visit, "floor(", "", ")"); - break; - case EOpTrunc: - outputTriplet(out, visit, "trunc(", "", ")"); - break; - case EOpRound: - outputTriplet(out, visit, "round(", "", ")"); - break; - case EOpRoundEven: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpCeil: - outputTriplet(out, visit, "ceil(", "", ")"); - break; - case EOpFract: - outputTriplet(out, visit, "frac(", "", ")"); - break; - case EOpIsNan: - if (node->getUseEmulatedFunction()) - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - else - outputTriplet(out, visit, "isnan(", "", ")"); - mRequiresIEEEStrictCompiling = true; - break; - case EOpIsInf: - outputTriplet(out, visit, "isinf(", "", ")"); - break; - case EOpFloatBitsToInt: - outputTriplet(out, visit, "asint(", "", ")"); - break; - case EOpFloatBitsToUint: - outputTriplet(out, visit, "asuint(", "", ")"); - break; - case EOpIntBitsToFloat: - outputTriplet(out, visit, "asfloat(", "", ")"); - break; - case EOpUintBitsToFloat: - outputTriplet(out, visit, "asfloat(", "", ")"); - break; - case EOpPackSnorm2x16: - case EOpPackUnorm2x16: - case EOpPackHalf2x16: - case EOpUnpackSnorm2x16: - case EOpUnpackUnorm2x16: - case EOpUnpackHalf2x16: - case EOpPackUnorm4x8: - case EOpPackSnorm4x8: - case EOpUnpackUnorm4x8: - case EOpUnpackSnorm4x8: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpLength: - outputTriplet(out, visit, "length(", "", ")"); - break; - case EOpNormalize: - outputTriplet(out, visit, "normalize(", "", ")"); - break; - case EOpDFdx: - if (mInsideDiscontinuousLoop || mOutputLod0Function) - { - outputTriplet(out, visit, "(", "", ", 0.0)"); - } - else - { - outputTriplet(out, visit, "ddx(", "", ")"); - } - break; - case EOpDFdy: - if (mInsideDiscontinuousLoop || mOutputLod0Function) - { - outputTriplet(out, visit, "(", "", ", 0.0)"); - } - else - { - outputTriplet(out, visit, "ddy(", "", ")"); - } - break; - case EOpFwidth: - if (mInsideDiscontinuousLoop || mOutputLod0Function) - { - outputTriplet(out, visit, "(", "", ", 0.0)"); - } - else - { - outputTriplet(out, visit, "fwidth(", "", ")"); - } - break; - case EOpTranspose: - outputTriplet(out, visit, "transpose(", "", ")"); - break; - case EOpDeterminant: - outputTriplet(out, visit, "determinant(transpose(", "", "))"); - break; - case EOpInverse: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - - case EOpAny: - outputTriplet(out, visit, "any(", "", ")"); - break; - case EOpAll: - outputTriplet(out, visit, "all(", "", ")"); - break; - case EOpLogicalNotComponentWise: - outputTriplet(out, visit, "(!", "", ")"); - break; - case EOpBitfieldReverse: - outputTriplet(out, visit, "reversebits(", "", ")"); - break; - case EOpBitCount: - outputTriplet(out, visit, "countbits(", "", ")"); - break; - case EOpFindLSB: - // Note that it's unclear from the HLSL docs what this returns for 0, but this is tested - // in GLSLTest and results are consistent with GL. - outputTriplet(out, visit, "firstbitlow(", "", ")"); - break; - case EOpFindMSB: - // Note that it's unclear from the HLSL docs what this returns for 0 or -1, but this is - // tested in GLSLTest and results are consistent with GL. - outputTriplet(out, visit, "firstbithigh(", "", ")"); - break; - default: - UNREACHABLE(); - } - - return true; -} - -TString OutputHLSL::samplerNamePrefixFromStruct(TIntermTyped *node) -{ - if (node->getAsSymbolNode()) - { - return node->getAsSymbolNode()->getSymbol(); - } - TIntermBinary *nodeBinary = node->getAsBinaryNode(); - switch (nodeBinary->getOp()) - { - case EOpIndexDirect: - { - int index = nodeBinary->getRight()->getAsConstantUnion()->getIConst(0); - - TInfoSinkBase prefixSink; - prefixSink << samplerNamePrefixFromStruct(nodeBinary->getLeft()) << "_" << index; - return TString(prefixSink.c_str()); - } - case EOpIndexDirectStruct: - { - const TStructure *s = nodeBinary->getLeft()->getAsTyped()->getType().getStruct(); - int index = nodeBinary->getRight()->getAsConstantUnion()->getIConst(0); - const TField *field = s->fields()[index]; - - TInfoSinkBase prefixSink; - prefixSink << samplerNamePrefixFromStruct(nodeBinary->getLeft()) << "_" - << field->name(); - return TString(prefixSink.c_str()); - } - default: - UNREACHABLE(); - return TString(""); - } -} - -bool OutputHLSL::visitBlock(Visit visit, TIntermBlock *node) -{ - TInfoSinkBase &out = getInfoSink(); - - if (mInsideFunction) - { - outputLineDirective(out, node->getLine().first_line); - out << "{\n"; - } - - for (TIntermNode *statement : *node->getSequence()) - { - outputLineDirective(out, statement->getLine().first_line); - - statement->traverse(this); - - // Don't output ; after case labels, they're terminated by : - // This is needed especially since outputting a ; after a case statement would turn empty - // case statements into non-empty case statements, disallowing fall-through from them. - // Also the output code is clearer if we don't output ; after statements where it is not - // needed: - // * if statements - // * switch statements - // * blocks - // * function definitions - // * loops (do-while loops output the semicolon in VisitLoop) - // * declarations that don't generate output. - if (statement->getAsCaseNode() == nullptr && statement->getAsIfElseNode() == nullptr && - statement->getAsBlock() == nullptr && statement->getAsLoopNode() == nullptr && - statement->getAsSwitchNode() == nullptr && - statement->getAsFunctionDefinition() == nullptr && - (statement->getAsDeclarationNode() == nullptr || - IsDeclarationWrittenOut(statement->getAsDeclarationNode())) && - statement->getAsInvariantDeclarationNode() == nullptr) - { - out << ";\n"; - } - } - - if (mInsideFunction) - { - outputLineDirective(out, node->getLine().last_line); - out << "}\n"; - } - - return false; -} - -bool OutputHLSL::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) -{ - TInfoSinkBase &out = getInfoSink(); - - ASSERT(mCurrentFunctionMetadata == nullptr); - - size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo()); - ASSERT(index != CallDAG::InvalidIndex); - mCurrentFunctionMetadata = &mASTMetadataList[index]; - - out << TypeString(node->getFunctionPrototype()->getType()) << " "; - - TIntermSequence *parameters = node->getFunctionPrototype()->getSequence(); - - if (node->getFunctionSymbolInfo()->isMain()) - { - out << "gl_main("; - } - else - { - out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) - << DisambiguateFunctionName(parameters) << (mOutputLod0Function ? "Lod0(" : "("); - } - - for (unsigned int i = 0; i < parameters->size(); i++) - { - TIntermSymbol *symbol = (*parameters)[i]->getAsSymbolNode(); - - if (symbol) - { - ensureStructDefined(symbol->getType()); - - out << argumentString(symbol); - - if (i < parameters->size() - 1) - { - out << ", "; - } - } - else - UNREACHABLE(); - } - - out << ")\n"; - - mInsideFunction = true; - // The function body node will output braces. - node->getBody()->traverse(this); - mInsideFunction = false; - - mCurrentFunctionMetadata = nullptr; - - bool needsLod0 = mASTMetadataList[index].mNeedsLod0; - if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER) - { - ASSERT(!node->getFunctionSymbolInfo()->isMain()); - mOutputLod0Function = true; - node->traverse(this); - mOutputLod0Function = false; - } - - return false; -} - -bool OutputHLSL::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - if (visit == PreVisit) - { - TIntermSequence *sequence = node->getSequence(); - TIntermTyped *variable = (*sequence)[0]->getAsTyped(); - ASSERT(sequence->size() == 1); - ASSERT(variable); - - if (IsDeclarationWrittenOut(node)) - { - TInfoSinkBase &out = getInfoSink(); - ensureStructDefined(variable->getType()); - - if (!variable->getAsSymbolNode() || - variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration - { - if (!mInsideFunction) - { - out << "static "; - } - - out << TypeString(variable->getType()) + " "; - - TIntermSymbol *symbol = variable->getAsSymbolNode(); - - if (symbol) - { - symbol->traverse(this); - out << ArrayString(symbol->getType()); - out << " = " + initializer(symbol->getType()); - } - else - { - variable->traverse(this); - } - } - else if (variable->getAsSymbolNode() && - variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration - { - ASSERT(variable->getBasicType() == EbtStruct); - // ensureStructDefined has already been called. - } - else - UNREACHABLE(); - } - else if (IsVaryingOut(variable->getQualifier())) - { - TIntermSymbol *symbol = variable->getAsSymbolNode(); - ASSERT(symbol); // Varying declarations can't have initializers. - - // Vertex outputs which are declared but not written to should still be declared to - // allow successful linking. - mReferencedVaryings[symbol->getSymbol()] = symbol; - } - } - return false; -} - -bool OutputHLSL::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) -{ - // Do not do any translation - return false; -} - -bool OutputHLSL::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) -{ - TInfoSinkBase &out = getInfoSink(); - - ASSERT(visit == PreVisit); - size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo()); - // Skip the prototype if it is not implemented (and thus not used) - if (index == CallDAG::InvalidIndex) - { - return false; - } - - TIntermSequence *arguments = node->getSequence(); - - TString name = DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()); - out << TypeString(node->getType()) << " " << name << DisambiguateFunctionName(arguments) - << (mOutputLod0Function ? "Lod0(" : "("); - - for (unsigned int i = 0; i < arguments->size(); i++) - { - TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode(); - ASSERT(symbol != nullptr); - - out << argumentString(symbol); - - if (i < arguments->size() - 1) - { - out << ", "; - } - } - - out << ");\n"; - - // Also prototype the Lod0 variant if needed - bool needsLod0 = mASTMetadataList[index].mNeedsLod0; - if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER) - { - mOutputLod0Function = true; - node->traverse(this); - mOutputLod0Function = false; - } - - return false; -} - -bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) -{ - TInfoSinkBase &out = getInfoSink(); - - switch (node->getOp()) - { - case EOpCallBuiltInFunction: - case EOpCallFunctionInAST: - case EOpCallInternalRawFunction: - { - TIntermSequence *arguments = node->getSequence(); - - bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function; - if (node->getOp() == EOpCallFunctionInAST) - { - if (node->isArray()) - { - UNIMPLEMENTED(); - } - size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo()); - ASSERT(index != CallDAG::InvalidIndex); - lod0 &= mASTMetadataList[index].mNeedsLod0; - - out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()); - out << DisambiguateFunctionName(node->getSequence()); - out << (lod0 ? "Lod0(" : "("); - } - else if (node->getOp() == EOpCallInternalRawFunction) - { - // This path is used for internal functions that don't have their definitions in the - // AST, such as precision emulation functions. - out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "("; - } - else if (node->getFunctionSymbolInfo()->isImageFunction()) - { - TString name = node->getFunctionSymbolInfo()->getName(); - TType type = (*arguments)[0]->getAsTyped()->getType(); - TString imageFunctionName = mImageFunctionHLSL->useImageFunction( - name, type.getBasicType(), type.getLayoutQualifier().imageInternalFormat, - type.getMemoryQualifier().readonly); - out << imageFunctionName << "("; - } - else - { - const TString &name = node->getFunctionSymbolInfo()->getName(); - TBasicType samplerType = (*arguments)[0]->getAsTyped()->getType().getBasicType(); - int coords = 0; // textureSize(gsampler2DMS) doesn't have a second argument. - if (arguments->size() > 1) - { - coords = (*arguments)[1]->getAsTyped()->getNominalSize(); - } - TString textureFunctionName = mTextureFunctionHLSL->useTextureFunction( - name, samplerType, coords, arguments->size(), lod0, mShaderType); - out << textureFunctionName << "("; - } - - for (TIntermSequence::iterator arg = arguments->begin(); arg != arguments->end(); arg++) - { - TIntermTyped *typedArg = (*arg)->getAsTyped(); - if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(typedArg->getBasicType())) - { - out << "texture_"; - (*arg)->traverse(this); - out << ", sampler_"; - } - - (*arg)->traverse(this); - - if (typedArg->getType().isStructureContainingSamplers()) - { - const TType &argType = typedArg->getType(); - TVector<TIntermSymbol *> samplerSymbols; - TString structName = samplerNamePrefixFromStruct(typedArg); - argType.createSamplerSymbols("angle_" + structName, "", &samplerSymbols, - nullptr, mSymbolTable); - for (const TIntermSymbol *sampler : samplerSymbols) - { - if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - out << ", texture_" << sampler->getSymbol(); - out << ", sampler_" << sampler->getSymbol(); - } - else - { - // In case of HLSL 4.1+, this symbol is the sampler index, and in case - // of D3D9, it's the sampler variable. - out << ", " + sampler->getSymbol(); - } - } - } - - if (arg < arguments->end() - 1) - { - out << ", "; - } - } - - out << ")"; - - return false; - } - case EOpConstruct: - outputConstructor(out, visit, node); - break; - case EOpEqualComponentWise: - outputTriplet(out, visit, "(", " == ", ")"); - break; - case EOpNotEqualComponentWise: - outputTriplet(out, visit, "(", " != ", ")"); - break; - case EOpLessThanComponentWise: - outputTriplet(out, visit, "(", " < ", ")"); - break; - case EOpGreaterThanComponentWise: - outputTriplet(out, visit, "(", " > ", ")"); - break; - case EOpLessThanEqualComponentWise: - outputTriplet(out, visit, "(", " <= ", ")"); - break; - case EOpGreaterThanEqualComponentWise: - outputTriplet(out, visit, "(", " >= ", ")"); - break; - case EOpMod: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpModf: - outputTriplet(out, visit, "modf(", ", ", ")"); - break; - case EOpPow: - outputTriplet(out, visit, "pow(", ", ", ")"); - break; - case EOpAtan: - ASSERT(node->getSequence()->size() == 2); // atan(x) is a unary operator - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpMin: - outputTriplet(out, visit, "min(", ", ", ")"); - break; - case EOpMax: - outputTriplet(out, visit, "max(", ", ", ")"); - break; - case EOpClamp: - outputTriplet(out, visit, "clamp(", ", ", ")"); - break; - case EOpMix: - { - TIntermTyped *lastParamNode = (*(node->getSequence()))[2]->getAsTyped(); - if (lastParamNode->getType().getBasicType() == EbtBool) - { - // There is no HLSL equivalent for ESSL3 built-in "genType mix (genType x, genType - // y, genBType a)", - // so use emulated version. - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - } - else - { - outputTriplet(out, visit, "lerp(", ", ", ")"); - } - break; - } - case EOpStep: - outputTriplet(out, visit, "step(", ", ", ")"); - break; - case EOpSmoothStep: - outputTriplet(out, visit, "smoothstep(", ", ", ")"); - break; - case EOpFrexp: - case EOpLdexp: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpDistance: - outputTriplet(out, visit, "distance(", ", ", ")"); - break; - case EOpDot: - outputTriplet(out, visit, "dot(", ", ", ")"); - break; - case EOpCross: - outputTriplet(out, visit, "cross(", ", ", ")"); - break; - case EOpFaceforward: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpReflect: - outputTriplet(out, visit, "reflect(", ", ", ")"); - break; - case EOpRefract: - outputTriplet(out, visit, "refract(", ", ", ")"); - break; - case EOpOuterProduct: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - case EOpMulMatrixComponentWise: - outputTriplet(out, visit, "(", " * ", ")"); - break; - case EOpBitfieldExtract: - case EOpBitfieldInsert: - case EOpUaddCarry: - case EOpUsubBorrow: - case EOpUmulExtended: - case EOpImulExtended: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, node->getOp()); - break; - default: - UNREACHABLE(); - } - - return true; -} - -void OutputHLSL::writeIfElse(TInfoSinkBase &out, TIntermIfElse *node) -{ - out << "if ("; - - node->getCondition()->traverse(this); - - out << ")\n"; - - outputLineDirective(out, node->getLine().first_line); - - bool discard = false; - - if (node->getTrueBlock()) - { - // The trueBlock child node will output braces. - node->getTrueBlock()->traverse(this); - - // Detect true discard - discard = (discard || FindDiscard::search(node->getTrueBlock())); - } - else - { - // TODO(oetuaho): Check if the semicolon inside is necessary. - // It's there as a result of conservative refactoring of the output. - out << "{;}\n"; - } - - outputLineDirective(out, node->getLine().first_line); - - if (node->getFalseBlock()) - { - out << "else\n"; - - outputLineDirective(out, node->getFalseBlock()->getLine().first_line); - - // The falseBlock child node will output braces. - node->getFalseBlock()->traverse(this); - - outputLineDirective(out, node->getFalseBlock()->getLine().first_line); - - // Detect false discard - discard = (discard || FindDiscard::search(node->getFalseBlock())); - } - - // ANGLE issue 486: Detect problematic conditional discard - if (discard) - { - mUsesDiscardRewriting = true; - } -} - -bool OutputHLSL::visitTernary(Visit, TIntermTernary *) -{ - // Ternary ops should have been already converted to something else in the AST. HLSL ternary - // operator doesn't short-circuit, so it's not the same as the GLSL ternary operator. - UNREACHABLE(); - return false; -} - -bool OutputHLSL::visitIfElse(Visit visit, TIntermIfElse *node) -{ - TInfoSinkBase &out = getInfoSink(); - - ASSERT(mInsideFunction); - - // D3D errors when there is a gradient operation in a loop in an unflattened if. - if (mShaderType == GL_FRAGMENT_SHADER && mCurrentFunctionMetadata->hasGradientLoop(node)) - { - out << "FLATTEN "; - } - - writeIfElse(out, node); - - return false; -} - -bool OutputHLSL::visitSwitch(Visit visit, TIntermSwitch *node) -{ - TInfoSinkBase &out = getInfoSink(); - - ASSERT(node->getStatementList()); - if (visit == PreVisit) - { - node->setStatementList(RemoveSwitchFallThrough(node->getStatementList(), mPerfDiagnostics)); - } - outputTriplet(out, visit, "switch (", ") ", ""); - // The curly braces get written when visiting the statementList block. - return true; -} - -bool OutputHLSL::visitCase(Visit visit, TIntermCase *node) -{ - TInfoSinkBase &out = getInfoSink(); - - if (node->hasCondition()) - { - outputTriplet(out, visit, "case (", "", "):\n"); - return true; - } - else - { - out << "default:\n"; - return false; - } -} - -void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node) -{ - TInfoSinkBase &out = getInfoSink(); - writeConstantUnion(out, node->getType(), node->getUnionArrayPointer()); -} - -bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) -{ - mNestedLoopDepth++; - - bool wasDiscontinuous = mInsideDiscontinuousLoop; - mInsideDiscontinuousLoop = - mInsideDiscontinuousLoop || mCurrentFunctionMetadata->mDiscontinuousLoops.count(node) > 0; - - TInfoSinkBase &out = getInfoSink(); - - if (mOutputType == SH_HLSL_3_0_OUTPUT) - { - if (handleExcessiveLoop(out, node)) - { - mInsideDiscontinuousLoop = wasDiscontinuous; - mNestedLoopDepth--; - - return false; - } - } - - const char *unroll = mCurrentFunctionMetadata->hasGradientInCallGraph(node) ? "LOOP" : ""; - if (node->getType() == ELoopDoWhile) - { - out << "{" << unroll << " do\n"; - - outputLineDirective(out, node->getLine().first_line); - } - else - { - out << "{" << unroll << " for("; - - if (node->getInit()) - { - node->getInit()->traverse(this); - } - - out << "; "; - - if (node->getCondition()) - { - node->getCondition()->traverse(this); - } - - out << "; "; - - if (node->getExpression()) - { - node->getExpression()->traverse(this); - } - - out << ")\n"; - - outputLineDirective(out, node->getLine().first_line); - } - - if (node->getBody()) - { - // The loop body node will output braces. - node->getBody()->traverse(this); - } - else - { - // TODO(oetuaho): Check if the semicolon inside is necessary. - // It's there as a result of conservative refactoring of the output. - out << "{;}\n"; - } - - outputLineDirective(out, node->getLine().first_line); - - if (node->getType() == ELoopDoWhile) - { - outputLineDirective(out, node->getCondition()->getLine().first_line); - out << "while ("; - - node->getCondition()->traverse(this); - - out << ");\n"; - } - - out << "}\n"; - - mInsideDiscontinuousLoop = wasDiscontinuous; - mNestedLoopDepth--; - - return false; -} - -bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) -{ - if (visit == PreVisit) - { - TInfoSinkBase &out = getInfoSink(); - - switch (node->getFlowOp()) - { - case EOpKill: - out << "discard"; - break; - case EOpBreak: - if (mNestedLoopDepth > 1) - { - mUsesNestedBreak = true; - } - - if (mExcessiveLoopIndex) - { - out << "{Break"; - mExcessiveLoopIndex->traverse(this); - out << " = true; break;}\n"; - } - else - { - out << "break"; - } - break; - case EOpContinue: - out << "continue"; - break; - case EOpReturn: - if (node->getExpression()) - { - out << "return "; - } - else - { - out << "return"; - } - break; - default: - UNREACHABLE(); - } - } - - return true; -} - -// Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them -// (The D3D documentation says 255 iterations, but the compiler complains at anything more than -// 254). -bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node) -{ - const int MAX_LOOP_ITERATIONS = 254; - - // Parse loops of the form: - // for(int index = initial; index [comparator] limit; index += increment) - TIntermSymbol *index = nullptr; - TOperator comparator = EOpNull; - int initial = 0; - int limit = 0; - int increment = 0; - - // Parse index name and intial value - if (node->getInit()) - { - TIntermDeclaration *init = node->getInit()->getAsDeclarationNode(); - - if (init) - { - TIntermSequence *sequence = init->getSequence(); - TIntermTyped *variable = (*sequence)[0]->getAsTyped(); - - if (variable && variable->getQualifier() == EvqTemporary) - { - TIntermBinary *assign = variable->getAsBinaryNode(); - - if (assign->getOp() == EOpInitialize) - { - TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode(); - TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion(); - - if (symbol && constant) - { - if (constant->getBasicType() == EbtInt && constant->isScalar()) - { - index = symbol; - initial = constant->getIConst(0); - } - } - } - } - } - } - - // Parse comparator and limit value - if (index != nullptr && node->getCondition()) - { - TIntermBinary *test = node->getCondition()->getAsBinaryNode(); - - if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId()) - { - TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion(); - - if (constant) - { - if (constant->getBasicType() == EbtInt && constant->isScalar()) - { - comparator = test->getOp(); - limit = constant->getIConst(0); - } - } - } - } - - // Parse increment - if (index != nullptr && comparator != EOpNull && node->getExpression()) - { - TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode(); - TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode(); - - if (binaryTerminal) - { - TOperator op = binaryTerminal->getOp(); - TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion(); - - if (constant) - { - if (constant->getBasicType() == EbtInt && constant->isScalar()) - { - int value = constant->getIConst(0); - - switch (op) - { - case EOpAddAssign: - increment = value; - break; - case EOpSubAssign: - increment = -value; - break; - default: - UNIMPLEMENTED(); - } - } - } - } - else if (unaryTerminal) - { - TOperator op = unaryTerminal->getOp(); - - switch (op) - { - case EOpPostIncrement: - increment = 1; - break; - case EOpPostDecrement: - increment = -1; - break; - case EOpPreIncrement: - increment = 1; - break; - case EOpPreDecrement: - increment = -1; - break; - default: - UNIMPLEMENTED(); - } - } - } - - if (index != nullptr && comparator != EOpNull && increment != 0) - { - if (comparator == EOpLessThanEqual) - { - comparator = EOpLessThan; - limit += 1; - } - - if (comparator == EOpLessThan) - { - int iterations = (limit - initial) / increment; - - if (iterations <= MAX_LOOP_ITERATIONS) - { - return false; // Not an excessive loop - } - - TIntermSymbol *restoreIndex = mExcessiveLoopIndex; - mExcessiveLoopIndex = index; - - out << "{int "; - index->traverse(this); - out << ";\n" - "bool Break"; - index->traverse(this); - out << " = false;\n"; - - bool firstLoopFragment = true; - - while (iterations > 0) - { - int clampedLimit = initial + increment * std::min(MAX_LOOP_ITERATIONS, iterations); - - if (!firstLoopFragment) - { - out << "if (!Break"; - index->traverse(this); - out << ") {\n"; - } - - if (iterations <= MAX_LOOP_ITERATIONS) // Last loop fragment - { - mExcessiveLoopIndex = nullptr; // Stops setting the Break flag - } - - // for(int index = initial; index < clampedLimit; index += increment) - const char *unroll = - mCurrentFunctionMetadata->hasGradientInCallGraph(node) ? "LOOP" : ""; - - out << unroll << " for("; - index->traverse(this); - out << " = "; - out << initial; - - out << "; "; - index->traverse(this); - out << " < "; - out << clampedLimit; - - out << "; "; - index->traverse(this); - out << " += "; - out << increment; - out << ")\n"; - - outputLineDirective(out, node->getLine().first_line); - out << "{\n"; - - if (node->getBody()) - { - node->getBody()->traverse(this); - } - - outputLineDirective(out, node->getLine().first_line); - out << ";}\n"; - - if (!firstLoopFragment) - { - out << "}\n"; - } - - firstLoopFragment = false; - - initial += MAX_LOOP_ITERATIONS * increment; - iterations -= MAX_LOOP_ITERATIONS; - } - - out << "}"; - - mExcessiveLoopIndex = restoreIndex; - - return true; - } - else - UNIMPLEMENTED(); - } - - return false; // Not handled as an excessive loop -} - -void OutputHLSL::outputTriplet(TInfoSinkBase &out, - Visit visit, - const char *preString, - const char *inString, - const char *postString) -{ - if (visit == PreVisit) - { - out << preString; - } - else if (visit == InVisit) - { - out << inString; - } - else if (visit == PostVisit) - { - out << postString; - } -} - -void OutputHLSL::outputLineDirective(TInfoSinkBase &out, int line) -{ - if ((mCompileOptions & SH_LINE_DIRECTIVES) && (line > 0)) - { - out << "\n"; - out << "#line " << line; - - if (mSourcePath) - { - out << " \"" << mSourcePath << "\""; - } - - out << "\n"; - } -} - -TString OutputHLSL::argumentString(const TIntermSymbol *symbol) -{ - TQualifier qualifier = symbol->getQualifier(); - const TType &type = symbol->getType(); - const TName &name = symbol->getName(); - TString nameStr; - - if (name.getString().empty()) // HLSL demands named arguments, also for prototypes - { - nameStr = "x" + str(mUniqueIndex++); - } - else - { - nameStr = DecorateVariableIfNeeded(name); - } - - if (IsSampler(type.getBasicType())) - { - if (mOutputType == SH_HLSL_4_1_OUTPUT) - { - // Samplers are passed as indices to the sampler array. - ASSERT(qualifier != EvqOut && qualifier != EvqInOut); - return "const uint " + nameStr + ArrayString(type); - } - if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - return QualifierString(qualifier) + " " + TextureString(type.getBasicType()) + - " texture_" + nameStr + ArrayString(type) + ", " + QualifierString(qualifier) + - " " + SamplerString(type.getBasicType()) + " sampler_" + nameStr + - ArrayString(type); - } - } - - TStringStream argString; - argString << QualifierString(qualifier) << " " << TypeString(type) << " " << nameStr - << ArrayString(type); - - // If the structure parameter contains samplers, they need to be passed into the function as - // separate parameters. HLSL doesn't natively support samplers in structs. - if (type.isStructureContainingSamplers()) - { - ASSERT(qualifier != EvqOut && qualifier != EvqInOut); - TVector<TIntermSymbol *> samplerSymbols; - type.createSamplerSymbols("angle" + nameStr, "", &samplerSymbols, nullptr, mSymbolTable); - for (const TIntermSymbol *sampler : samplerSymbols) - { - const TType &samplerType = sampler->getType(); - if (mOutputType == SH_HLSL_4_1_OUTPUT) - { - argString << ", const uint " << sampler->getSymbol() << ArrayString(samplerType); - } - else if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - ASSERT(IsSampler(samplerType.getBasicType())); - argString << ", " << QualifierString(qualifier) << " " - << TextureString(samplerType.getBasicType()) << " texture_" - << sampler->getSymbol() << ArrayString(samplerType) << ", " - << QualifierString(qualifier) << " " - << SamplerString(samplerType.getBasicType()) << " sampler_" - << sampler->getSymbol() << ArrayString(samplerType); - } - else - { - ASSERT(IsSampler(samplerType.getBasicType())); - argString << ", " << QualifierString(qualifier) << " " << TypeString(samplerType) - << " " << sampler->getSymbol() << ArrayString(samplerType); - } - } - } - - return argString.str(); -} - -TString OutputHLSL::initializer(const TType &type) -{ - TString string; - - size_t size = type.getObjectSize(); - for (size_t component = 0; component < size; component++) - { - string += "0"; - - if (component + 1 < size) - { - string += ", "; - } - } - - return "{" + string + "}"; -} - -void OutputHLSL::outputConstructor(TInfoSinkBase &out, Visit visit, TIntermAggregate *node) -{ - // Array constructors should have been already pruned from the code. - ASSERT(!node->getType().isArray()); - - if (visit == PreVisit) - { - TString constructorName; - if (node->getBasicType() == EbtStruct) - { - constructorName = mStructureHLSL->addStructConstructor(*node->getType().getStruct()); - } - else - { - constructorName = - mStructureHLSL->addBuiltInConstructor(node->getType(), node->getSequence()); - } - out << constructorName << "("; - } - else if (visit == InVisit) - { - out << ", "; - } - else if (visit == PostVisit) - { - out << ")"; - } -} - -const TConstantUnion *OutputHLSL::writeConstantUnion(TInfoSinkBase &out, - const TType &type, - const TConstantUnion *const constUnion) -{ - const TConstantUnion *constUnionIterated = constUnion; - - const TStructure *structure = type.getStruct(); - if (structure) - { - out << mStructureHLSL->addStructConstructor(*structure) << "("; - - const TFieldList &fields = structure->fields(); - - for (size_t i = 0; i < fields.size(); i++) - { - const TType *fieldType = fields[i]->type(); - constUnionIterated = writeConstantUnion(out, *fieldType, constUnionIterated); - - if (i != fields.size() - 1) - { - out << ", "; - } - } - - out << ")"; - } - else - { - size_t size = type.getObjectSize(); - bool writeType = size > 1; - - if (writeType) - { - out << TypeString(type) << "("; - } - constUnionIterated = writeConstantUnionArray(out, constUnionIterated, size); - if (writeType) - { - out << ")"; - } - } - - return constUnionIterated; -} - -void OutputHLSL::writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, TOperator op) -{ - if (visit == PreVisit) - { - const char *opStr = GetOperatorString(op); - BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, opStr); - out << "("; - } - else - { - outputTriplet(out, visit, nullptr, ", ", ")"); - } -} - -bool OutputHLSL::writeSameSymbolInitializer(TInfoSinkBase &out, - TIntermSymbol *symbolNode, - TIntermTyped *expression) -{ - sh::SearchSymbol searchSymbol(symbolNode->getSymbol()); - expression->traverse(&searchSymbol); - - if (searchSymbol.foundMatch()) - { - // Type already printed - out << "t" + str(mUniqueIndex) + " = "; - expression->traverse(this); - out << ", "; - symbolNode->traverse(this); - out << " = t" + str(mUniqueIndex); - - mUniqueIndex++; - return true; - } - - return false; -} - -bool OutputHLSL::canWriteAsHLSLLiteral(TIntermTyped *expression) -{ - // We support writing constant unions and constructors that only take constant unions as - // parameters as HLSL literals. - return !expression->getType().isArrayOfArrays() && - (expression->getAsConstantUnion() || - expression->isConstructorWithOnlyConstantUnionParameters()); -} - -bool OutputHLSL::writeConstantInitialization(TInfoSinkBase &out, - TIntermSymbol *symbolNode, - TIntermTyped *initializer) -{ - if (canWriteAsHLSLLiteral(initializer)) - { - symbolNode->traverse(this); - ASSERT(!symbolNode->getType().isArrayOfArrays()); - if (symbolNode->getType().isArray()) - { - out << "[" << symbolNode->getType().getOutermostArraySize() << "]"; - } - out << " = {"; - if (initializer->getAsConstantUnion()) - { - TIntermConstantUnion *nodeConst = initializer->getAsConstantUnion(); - const TConstantUnion *constUnion = nodeConst->getUnionArrayPointer(); - writeConstantUnionArray(out, constUnion, nodeConst->getType().getObjectSize()); - } - else - { - TIntermAggregate *constructor = initializer->getAsAggregate(); - ASSERT(constructor != nullptr); - for (TIntermNode *&node : *constructor->getSequence()) - { - TIntermConstantUnion *nodeConst = node->getAsConstantUnion(); - ASSERT(nodeConst); - const TConstantUnion *constUnion = nodeConst->getUnionArrayPointer(); - writeConstantUnionArray(out, constUnion, nodeConst->getType().getObjectSize()); - if (node != constructor->getSequence()->back()) - { - out << ", "; - } - } - } - out << "}"; - return true; - } - return false; -} - -TString OutputHLSL::addStructEqualityFunction(const TStructure &structure) -{ - const TFieldList &fields = structure.fields(); - - for (const auto &eqFunction : mStructEqualityFunctions) - { - if (eqFunction->structure == &structure) - { - return eqFunction->functionName; - } - } - - const TString &structNameString = StructNameString(structure); - - StructEqualityFunction *function = new StructEqualityFunction(); - function->structure = &structure; - function->functionName = "angle_eq_" + structNameString; - - TInfoSinkBase fnOut; - - fnOut << "bool " << function->functionName << "(" << structNameString << " a, " - << structNameString + " b)\n" - << "{\n" - " return "; - - for (size_t i = 0; i < fields.size(); i++) - { - const TField *field = fields[i]; - const TType *fieldType = field->type(); - - const TString &fieldNameA = "a." + Decorate(field->name()); - const TString &fieldNameB = "b." + Decorate(field->name()); - - if (i > 0) - { - fnOut << " && "; - } - - fnOut << "("; - outputEqual(PreVisit, *fieldType, EOpEqual, fnOut); - fnOut << fieldNameA; - outputEqual(InVisit, *fieldType, EOpEqual, fnOut); - fnOut << fieldNameB; - outputEqual(PostVisit, *fieldType, EOpEqual, fnOut); - fnOut << ")"; - } - - fnOut << ";\n" - << "}\n"; - - function->functionDefinition = fnOut.c_str(); - - mStructEqualityFunctions.push_back(function); - mEqualityFunctions.push_back(function); - - return function->functionName; -} - -TString OutputHLSL::addArrayEqualityFunction(const TType &type) -{ - for (const auto &eqFunction : mArrayEqualityFunctions) - { - if (eqFunction->type == type) - { - return eqFunction->functionName; - } - } - - TType elementType(type); - elementType.toArrayElementType(); - - ArrayHelperFunction *function = new ArrayHelperFunction(); - function->type = type; - - function->functionName = ArrayHelperFunctionName("angle_eq", type); - - TInfoSinkBase fnOut; - - const TString &typeName = TypeString(type); - fnOut << "bool " << function->functionName << "(" << typeName << " a" << ArrayString(type) - << ", " << typeName << " b" << ArrayString(type) << ")\n" - << "{\n" - " for (int i = 0; i < " - << type.getOutermostArraySize() - << "; ++i)\n" - " {\n" - " if ("; - - outputEqual(PreVisit, elementType, EOpNotEqual, fnOut); - fnOut << "a[i]"; - outputEqual(InVisit, elementType, EOpNotEqual, fnOut); - fnOut << "b[i]"; - outputEqual(PostVisit, elementType, EOpNotEqual, fnOut); - - fnOut << ") { return false; }\n" - " }\n" - " return true;\n" - "}\n"; - - function->functionDefinition = fnOut.c_str(); - - mArrayEqualityFunctions.push_back(function); - mEqualityFunctions.push_back(function); - - return function->functionName; -} - -TString OutputHLSL::addArrayAssignmentFunction(const TType &type) -{ - for (const auto &assignFunction : mArrayAssignmentFunctions) - { - if (assignFunction.type == type) - { - return assignFunction.functionName; - } - } - - TType elementType(type); - elementType.toArrayElementType(); - - ArrayHelperFunction function; - function.type = type; - - function.functionName = ArrayHelperFunctionName("angle_assign", type); - - TInfoSinkBase fnOut; - - const TString &typeName = TypeString(type); - fnOut << "void " << function.functionName << "(out " << typeName << " a" << ArrayString(type) - << ", " << typeName << " b" << ArrayString(type) << ")\n" - << "{\n" - " for (int i = 0; i < " - << type.getOutermostArraySize() - << "; ++i)\n" - " {\n" - " "; - - outputAssign(PreVisit, elementType, fnOut); - fnOut << "a[i]"; - outputAssign(InVisit, elementType, fnOut); - fnOut << "b[i]"; - outputAssign(PostVisit, elementType, fnOut); - - fnOut << ";\n" - " }\n" - "}\n"; - - function.functionDefinition = fnOut.c_str(); - - mArrayAssignmentFunctions.push_back(function); - - return function.functionName; -} - -TString OutputHLSL::addArrayConstructIntoFunction(const TType &type) -{ - for (const auto &constructIntoFunction : mArrayConstructIntoFunctions) - { - if (constructIntoFunction.type == type) - { - return constructIntoFunction.functionName; - } - } - - TType elementType(type); - elementType.toArrayElementType(); - - ArrayHelperFunction function; - function.type = type; - - function.functionName = ArrayHelperFunctionName("angle_construct_into", type); - - TInfoSinkBase fnOut; - - const TString &typeName = TypeString(type); - fnOut << "void " << function.functionName << "(out " << typeName << " a" << ArrayString(type); - for (unsigned int i = 0u; i < type.getOutermostArraySize(); ++i) - { - fnOut << ", " << typeName << " b" << i << ArrayString(elementType); - } - fnOut << ")\n" - "{\n"; - - for (unsigned int i = 0u; i < type.getOutermostArraySize(); ++i) - { - fnOut << " "; - outputAssign(PreVisit, elementType, fnOut); - fnOut << "a[" << i << "]"; - outputAssign(InVisit, elementType, fnOut); - fnOut << "b" << i; - outputAssign(PostVisit, elementType, fnOut); - fnOut << ";\n"; - } - fnOut << "}\n"; - - function.functionDefinition = fnOut.c_str(); - - mArrayConstructIntoFunctions.push_back(function); - - return function.functionName; -} - -void OutputHLSL::ensureStructDefined(const TType &type) -{ - const TStructure *structure = type.getStruct(); - if (structure) - { - ASSERT(type.getBasicType() == EbtStruct); - mStructureHLSL->ensureStructDefined(*structure); - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h deleted file mode 100644 index 014f4f5002..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h +++ /dev/null @@ -1,248 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_OUTPUTHLSL_H_ -#define COMPILER_TRANSLATOR_OUTPUTHLSL_H_ - -#include <list> -#include <map> -#include <stack> - -#include "angle_gl.h" -#include "compiler/translator/ASTMetadataHLSL.h" -#include "compiler/translator/Compiler.h" -#include "compiler/translator/FlagStd140Structs.h" -#include "compiler/translator/IntermTraverse.h" - -class BuiltInFunctionEmulator; - -namespace sh -{ -class StructureHLSL; -class TextureFunctionHLSL; -class TSymbolTable; -class ImageFunctionHLSL; -class UnfoldShortCircuit; -class UniformHLSL; - -typedef std::map<TString, TIntermSymbol *> ReferencedSymbols; - -class OutputHLSL : public TIntermTraverser -{ - public: - OutputHLSL(sh::GLenum shaderType, - int shaderVersion, - const TExtensionBehavior &extensionBehavior, - const char *sourcePath, - ShShaderOutput outputType, - int numRenderTargets, - const std::vector<Uniform> &uniforms, - ShCompileOptions compileOptions, - TSymbolTable *symbolTable, - PerformanceDiagnostics *perfDiagnostics); - - ~OutputHLSL(); - - void output(TIntermNode *treeRoot, TInfoSinkBase &objSink); - - const std::map<std::string, unsigned int> &getUniformBlockRegisterMap() const; - const std::map<std::string, unsigned int> &getUniformRegisterMap() const; - - static TString initializer(const TType &type); - - TInfoSinkBase &getInfoSink() - { - ASSERT(!mInfoSinkStack.empty()); - return *mInfoSinkStack.top(); - } - - static bool canWriteAsHLSLLiteral(TIntermTyped *expression); - - protected: - void header(TInfoSinkBase &out, - const std::vector<MappedStruct> &std140Structs, - const BuiltInFunctionEmulator *builtInFunctionEmulator) const; - - void writeFloat(TInfoSinkBase &out, float f); - void writeSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion); - const TConstantUnion *writeConstantUnionArray(TInfoSinkBase &out, - const TConstantUnion *const constUnion, - const size_t size); - - // Visit AST nodes and output their code to the body stream - void visitSymbol(TIntermSymbol *) override; - void visitRaw(TIntermRaw *) override; - void visitConstantUnion(TIntermConstantUnion *) override; - bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; - bool visitBinary(Visit visit, TIntermBinary *) override; - bool visitUnary(Visit visit, TIntermUnary *) override; - bool visitTernary(Visit visit, TIntermTernary *) override; - bool visitIfElse(Visit visit, TIntermIfElse *) override; - bool visitSwitch(Visit visit, TIntermSwitch *) override; - bool visitCase(Visit visit, TIntermCase *) override; - bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *) override; - bool visitBlock(Visit visit, TIntermBlock *node) override; - bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override; - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - bool visitLoop(Visit visit, TIntermLoop *) override; - bool visitBranch(Visit visit, TIntermBranch *) override; - - bool handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node); - - // Emit one of three strings depending on traverse phase. Called with literal strings so using - // const char* instead of TString. - void outputTriplet(TInfoSinkBase &out, - Visit visit, - const char *preString, - const char *inString, - const char *postString); - void outputLineDirective(TInfoSinkBase &out, int line); - TString argumentString(const TIntermSymbol *symbol); - - void outputConstructor(TInfoSinkBase &out, Visit visit, TIntermAggregate *node); - const TConstantUnion *writeConstantUnion(TInfoSinkBase &out, - const TType &type, - const TConstantUnion *constUnion); - - void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out); - void outputAssign(Visit visit, const TType &type, TInfoSinkBase &out); - - void writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, TOperator op); - - // Returns true if it found a 'same symbol' initializer (initializer that references the - // variable it's initting) - bool writeSameSymbolInitializer(TInfoSinkBase &out, - TIntermSymbol *symbolNode, - TIntermTyped *expression); - // Returns true if variable initializer could be written using literal {} notation. - bool writeConstantInitialization(TInfoSinkBase &out, - TIntermSymbol *symbolNode, - TIntermTyped *expression); - - void writeIfElse(TInfoSinkBase &out, TIntermIfElse *node); - - // Returns the function name - TString addStructEqualityFunction(const TStructure &structure); - TString addArrayEqualityFunction(const TType &type); - TString addArrayAssignmentFunction(const TType &type); - TString addArrayConstructIntoFunction(const TType &type); - - // Ensures if the type is a struct, the struct is defined - void ensureStructDefined(const TType &type); - - sh::GLenum mShaderType; - int mShaderVersion; - const TExtensionBehavior &mExtensionBehavior; - const char *mSourcePath; - const ShShaderOutput mOutputType; - ShCompileOptions mCompileOptions; - - bool mInsideFunction; - - // Output streams - TInfoSinkBase mHeader; - TInfoSinkBase mBody; - TInfoSinkBase mFooter; - - // A stack is useful when we want to traverse in the header, or in helper functions, but not - // always write to the body. Instead use an InfoSink stack to keep our current state intact. - // TODO (jmadill): Just passing an InfoSink in function parameters would be simpler. - std::stack<TInfoSinkBase *> mInfoSinkStack; - - ReferencedSymbols mReferencedUniforms; - ReferencedSymbols mReferencedUniformBlocks; - ReferencedSymbols mReferencedAttributes; - ReferencedSymbols mReferencedVaryings; - ReferencedSymbols mReferencedOutputVariables; - - StructureHLSL *mStructureHLSL; - UniformHLSL *mUniformHLSL; - TextureFunctionHLSL *mTextureFunctionHLSL; - ImageFunctionHLSL *mImageFunctionHLSL; - - // Parameters determining what goes in the header output - bool mUsesFragColor; - bool mUsesFragData; - bool mUsesDepthRange; - bool mUsesFragCoord; - bool mUsesPointCoord; - bool mUsesFrontFacing; - bool mUsesPointSize; - bool mUsesInstanceID; - bool mHasMultiviewExtensionEnabled; - bool mUsesViewID; - bool mUsesVertexID; - bool mUsesFragDepth; - bool mUsesNumWorkGroups; - bool mUsesWorkGroupID; - bool mUsesLocalInvocationID; - bool mUsesGlobalInvocationID; - bool mUsesLocalInvocationIndex; - bool mUsesXor; - bool mUsesDiscardRewriting; - bool mUsesNestedBreak; - bool mRequiresIEEEStrictCompiling; - - int mNumRenderTargets; - - int mUniqueIndex; // For creating unique names - - CallDAG mCallDag; - MetadataList mASTMetadataList; - ASTMetadataHLSL *mCurrentFunctionMetadata; - bool mOutputLod0Function; - bool mInsideDiscontinuousLoop; - int mNestedLoopDepth; - - TIntermSymbol *mExcessiveLoopIndex; - - TString structInitializerString(int indent, const TType &type, const TString &name) const; - - struct HelperFunction - { - TString functionName; - TString functionDefinition; - - virtual ~HelperFunction() {} - }; - - // A list of all equality comparison functions. It's important to preserve the order at - // which we add the functions, since nested structures call each other recursively, and - // structure equality functions may need to call array equality functions and vice versa. - // The ownership of the pointers is maintained by the type-specific arrays. - std::vector<HelperFunction *> mEqualityFunctions; - - struct StructEqualityFunction : public HelperFunction - { - const TStructure *structure; - }; - std::vector<StructEqualityFunction *> mStructEqualityFunctions; - - struct ArrayHelperFunction : public HelperFunction - { - TType type; - }; - std::vector<ArrayHelperFunction *> mArrayEqualityFunctions; - - std::vector<ArrayHelperFunction> mArrayAssignmentFunctions; - - // The construct-into functions are functions that fill an N-element array passed as an out - // parameter with the other N parameters of the function. This is used to work around that - // arrays can't be return values in HLSL. - std::vector<ArrayHelperFunction> mArrayConstructIntoFunctions; - - PerformanceDiagnostics *mPerfDiagnostics; - - private: - TString generateStructMapping(const std::vector<MappedStruct> &std140Structs) const; - TString samplerNamePrefixFromStruct(TIntermTyped *node); - bool ancestorEvaluatesToSamplerInStruct(); -}; -} - -#endif // COMPILER_TRANSLATOR_OUTPUTHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputTree.cpp b/src/3rdparty/angle/src/compiler/translator/OutputTree.cpp deleted file mode 100644 index 25e8298af3..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputTree.cpp +++ /dev/null @@ -1,682 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -void OutputFunction(TInfoSinkBase &out, const char *str, TFunctionSymbolInfo *info) -{ - const char *internal = info->getNameObj().isInternal() ? " (internal function)" : ""; - out << str << internal << ": " << info->getNameObj().getString() << " (symbol id " - << info->getId().get() << ")"; -} - -// Two purposes: -// 1. Show an example of how to iterate tree. Functions can also directly call traverse() on -// children themselves to have finer grained control over the process than shown here, though -// that's not recommended if it can be avoided. -// 2. Print out a text based description of the tree. - -// The traverser subclass is used to carry along data from node to node in the traversal. -class TOutputTraverser : public TIntermTraverser -{ - public: - TOutputTraverser(TInfoSinkBase &out) : TIntermTraverser(true, false, false), mOut(out) {} - - protected: - void visitSymbol(TIntermSymbol *) override; - void visitConstantUnion(TIntermConstantUnion *) override; - bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; - bool visitBinary(Visit visit, TIntermBinary *) override; - bool visitUnary(Visit visit, TIntermUnary *) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - bool visitIfElse(Visit visit, TIntermIfElse *node) override; - bool visitSwitch(Visit visit, TIntermSwitch *node) override; - bool visitCase(Visit visit, TIntermCase *node) override; - bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *) override; - bool visitBlock(Visit visit, TIntermBlock *) override; - bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override; - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - bool visitLoop(Visit visit, TIntermLoop *) override; - bool visitBranch(Visit visit, TIntermBranch *) override; - - TInfoSinkBase &mOut; -}; - -// -// Helper functions for printing, not part of traversing. -// -void OutputTreeText(TInfoSinkBase &out, TIntermNode *node, const int depth) -{ - int i; - - out.location(node->getLine().first_file, node->getLine().first_line); - - for (i = 0; i < depth; ++i) - out << " "; -} - -// -// The rest of the file are the traversal functions. The last one -// is the one that starts the traversal. -// -// Return true from interior nodes to have the external traversal -// continue on to children. If you process children yourself, -// return false. -// - -void TOutputTraverser::visitSymbol(TIntermSymbol *node) -{ - OutputTreeText(mOut, node, mDepth); - - mOut << "'" << node->getSymbol() << "' "; - mOut << "(symbol id " << node->getId() << ") "; - mOut << "(" << node->getCompleteString() << ")"; - mOut << "\n"; -} - -bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node) -{ - OutputTreeText(mOut, node, mDepth); - mOut << "vector swizzle ("; - node->writeOffsetsAsXYZW(&mOut); - mOut << ")"; - - mOut << " (" << node->getCompleteString() << ")"; - mOut << "\n"; - return true; -} - -bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - OutputTreeText(mOut, node, mDepth); - - switch (node->getOp()) - { - case EOpComma: - mOut << "comma"; - break; - case EOpAssign: - mOut << "move second child to first child"; - break; - case EOpInitialize: - mOut << "initialize first child with second child"; - break; - case EOpAddAssign: - mOut << "add second child into first child"; - break; - case EOpSubAssign: - mOut << "subtract second child into first child"; - break; - case EOpMulAssign: - mOut << "multiply second child into first child"; - break; - case EOpVectorTimesMatrixAssign: - mOut << "matrix mult second child into first child"; - break; - case EOpVectorTimesScalarAssign: - mOut << "vector scale second child into first child"; - break; - case EOpMatrixTimesScalarAssign: - mOut << "matrix scale second child into first child"; - break; - case EOpMatrixTimesMatrixAssign: - mOut << "matrix mult second child into first child"; - break; - case EOpDivAssign: - mOut << "divide second child into first child"; - break; - case EOpIModAssign: - mOut << "modulo second child into first child"; - break; - case EOpBitShiftLeftAssign: - mOut << "bit-wise shift first child left by second child"; - break; - case EOpBitShiftRightAssign: - mOut << "bit-wise shift first child right by second child"; - break; - case EOpBitwiseAndAssign: - mOut << "bit-wise and second child into first child"; - break; - case EOpBitwiseXorAssign: - mOut << "bit-wise xor second child into first child"; - break; - case EOpBitwiseOrAssign: - mOut << "bit-wise or second child into first child"; - break; - - case EOpIndexDirect: - mOut << "direct index"; - break; - case EOpIndexIndirect: - mOut << "indirect index"; - break; - case EOpIndexDirectStruct: - mOut << "direct index for structure"; - break; - case EOpIndexDirectInterfaceBlock: - mOut << "direct index for interface block"; - break; - - case EOpAdd: - mOut << "add"; - break; - case EOpSub: - mOut << "subtract"; - break; - case EOpMul: - mOut << "component-wise multiply"; - break; - case EOpDiv: - mOut << "divide"; - break; - case EOpIMod: - mOut << "modulo"; - break; - case EOpBitShiftLeft: - mOut << "bit-wise shift left"; - break; - case EOpBitShiftRight: - mOut << "bit-wise shift right"; - break; - case EOpBitwiseAnd: - mOut << "bit-wise and"; - break; - case EOpBitwiseXor: - mOut << "bit-wise xor"; - break; - case EOpBitwiseOr: - mOut << "bit-wise or"; - break; - - case EOpEqual: - mOut << "Compare Equal"; - break; - case EOpNotEqual: - mOut << "Compare Not Equal"; - break; - case EOpLessThan: - mOut << "Compare Less Than"; - break; - case EOpGreaterThan: - mOut << "Compare Greater Than"; - break; - case EOpLessThanEqual: - mOut << "Compare Less Than or Equal"; - break; - case EOpGreaterThanEqual: - mOut << "Compare Greater Than or Equal"; - break; - - case EOpVectorTimesScalar: - mOut << "vector-scale"; - break; - case EOpVectorTimesMatrix: - mOut << "vector-times-matrix"; - break; - case EOpMatrixTimesVector: - mOut << "matrix-times-vector"; - break; - case EOpMatrixTimesScalar: - mOut << "matrix-scale"; - break; - case EOpMatrixTimesMatrix: - mOut << "matrix-multiply"; - break; - - case EOpLogicalOr: - mOut << "logical-or"; - break; - case EOpLogicalXor: - mOut << "logical-xor"; - break; - case EOpLogicalAnd: - mOut << "logical-and"; - break; - default: - mOut << "<unknown op>"; - } - - mOut << " (" << node->getCompleteString() << ")"; - - mOut << "\n"; - - // Special handling for direct indexes. Because constant - // unions are not aware they are struct indexes, treat them - // here where we have that contextual knowledge. - if (node->getOp() == EOpIndexDirectStruct || node->getOp() == EOpIndexDirectInterfaceBlock) - { - node->getLeft()->traverse(this); - - TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion(); - ASSERT(intermConstantUnion); - - OutputTreeText(mOut, intermConstantUnion, mDepth + 1); - - // The following code finds the field name from the constant union - const TConstantUnion *constantUnion = intermConstantUnion->getUnionArrayPointer(); - const TStructure *structure = node->getLeft()->getType().getStruct(); - const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock(); - ASSERT(structure || interfaceBlock); - - const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields(); - - const TField *field = fields[constantUnion->getIConst()]; - - mOut << constantUnion->getIConst() << " (field '" << field->name() << "')"; - - mOut << "\n"; - - return false; - } - - return true; -} - -bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) -{ - OutputTreeText(mOut, node, mDepth); - - switch (node->getOp()) - { - // Give verbose names for ops that have special syntax and some built-in functions that are - // easy to confuse with others, but mostly use GLSL names for functions. - case EOpNegative: - mOut << "Negate value"; - break; - case EOpPositive: - mOut << "Positive sign"; - break; - case EOpLogicalNot: - mOut << "negation"; - break; - case EOpBitwiseNot: - mOut << "bit-wise not"; - break; - - case EOpPostIncrement: - mOut << "Post-Increment"; - break; - case EOpPostDecrement: - mOut << "Post-Decrement"; - break; - case EOpPreIncrement: - mOut << "Pre-Increment"; - break; - case EOpPreDecrement: - mOut << "Pre-Decrement"; - break; - - case EOpArrayLength: - mOut << "Array length"; - break; - - case EOpLogicalNotComponentWise: - mOut << "component-wise not"; - break; - - default: - mOut << GetOperatorString(node->getOp()); - break; - } - - mOut << " (" << node->getCompleteString() << ")"; - - mOut << "\n"; - - return true; -} - -bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) -{ - OutputTreeText(mOut, node, mDepth); - mOut << "Function Definition:\n"; - mOut << "\n"; - return true; -} - -bool TOutputTraverser::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) -{ - OutputTreeText(mOut, node, mDepth); - mOut << "Invariant Declaration:\n"; - return true; -} - -bool TOutputTraverser::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) -{ - OutputTreeText(mOut, node, mDepth); - OutputFunction(mOut, "Function Prototype", node->getFunctionSymbolInfo()); - mOut << " (" << node->getCompleteString() << ")"; - mOut << "\n"; - - return true; -} - -bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - OutputTreeText(mOut, node, mDepth); - - if (node->getOp() == EOpNull) - { - mOut.prefix(SH_ERROR); - mOut << "node is still EOpNull!\n"; - return true; - } - - // Give verbose names for some built-in functions that are easy to confuse with others, but - // mostly use GLSL names for functions. - switch (node->getOp()) - { - case EOpCallFunctionInAST: - OutputFunction(mOut, "Call an user-defined function", node->getFunctionSymbolInfo()); - break; - case EOpCallInternalRawFunction: - OutputFunction(mOut, "Call an internal function with raw implementation", - node->getFunctionSymbolInfo()); - break; - case EOpCallBuiltInFunction: - OutputFunction(mOut, "Call a built-in function", node->getFunctionSymbolInfo()); - break; - - case EOpConstruct: - // The type of the constructor will be printed below. - mOut << "Construct"; - break; - - case EOpEqualComponentWise: - mOut << "component-wise equal"; - break; - case EOpNotEqualComponentWise: - mOut << "component-wise not equal"; - break; - case EOpLessThanComponentWise: - mOut << "component-wise less than"; - break; - case EOpGreaterThanComponentWise: - mOut << "component-wise greater than"; - break; - case EOpLessThanEqualComponentWise: - mOut << "component-wise less than or equal"; - break; - case EOpGreaterThanEqualComponentWise: - mOut << "component-wise greater than or equal"; - break; - - case EOpDot: - mOut << "dot product"; - break; - case EOpCross: - mOut << "cross product"; - break; - case EOpMulMatrixComponentWise: - mOut << "component-wise multiply"; - break; - - default: - mOut << GetOperatorString(node->getOp()); - break; - } - - mOut << " (" << node->getCompleteString() << ")"; - - mOut << "\n"; - - return true; -} - -bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node) -{ - OutputTreeText(mOut, node, mDepth); - mOut << "Code block\n"; - - return true; -} - -bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - OutputTreeText(mOut, node, mDepth); - mOut << "Declaration\n"; - - return true; -} - -bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node) -{ - OutputTreeText(mOut, node, mDepth); - - mOut << "Ternary selection"; - mOut << " (" << node->getCompleteString() << ")\n"; - - ++mDepth; - - OutputTreeText(mOut, node, mDepth); - mOut << "Condition\n"; - node->getCondition()->traverse(this); - - OutputTreeText(mOut, node, mDepth); - if (node->getTrueExpression()) - { - mOut << "true case\n"; - node->getTrueExpression()->traverse(this); - } - if (node->getFalseExpression()) - { - OutputTreeText(mOut, node, mDepth); - mOut << "false case\n"; - node->getFalseExpression()->traverse(this); - } - - --mDepth; - - return false; -} - -bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node) -{ - OutputTreeText(mOut, node, mDepth); - - mOut << "If test\n"; - - ++mDepth; - - OutputTreeText(mOut, node, mDepth); - mOut << "Condition\n"; - node->getCondition()->traverse(this); - - OutputTreeText(mOut, node, mDepth); - if (node->getTrueBlock()) - { - mOut << "true case\n"; - node->getTrueBlock()->traverse(this); - } - else - { - mOut << "true case is null\n"; - } - - if (node->getFalseBlock()) - { - OutputTreeText(mOut, node, mDepth); - mOut << "false case\n"; - node->getFalseBlock()->traverse(this); - } - - --mDepth; - - return false; -} - -bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node) -{ - OutputTreeText(mOut, node, mDepth); - - mOut << "Switch\n"; - - return true; -} - -bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node) -{ - OutputTreeText(mOut, node, mDepth); - - if (node->getCondition() == nullptr) - { - mOut << "Default\n"; - } - else - { - mOut << "Case\n"; - } - - return true; -} - -void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node) -{ - size_t size = node->getType().getObjectSize(); - - for (size_t i = 0; i < size; i++) - { - OutputTreeText(mOut, node, mDepth); - switch (node->getUnionArrayPointer()[i].getType()) - { - case EbtBool: - if (node->getUnionArrayPointer()[i].getBConst()) - mOut << "true"; - else - mOut << "false"; - - mOut << " (" - << "const bool" - << ")"; - mOut << "\n"; - break; - case EbtFloat: - mOut << node->getUnionArrayPointer()[i].getFConst(); - mOut << " (const float)\n"; - break; - case EbtInt: - mOut << node->getUnionArrayPointer()[i].getIConst(); - mOut << " (const int)\n"; - break; - case EbtUInt: - mOut << node->getUnionArrayPointer()[i].getUConst(); - mOut << " (const uint)\n"; - break; - case EbtYuvCscStandardEXT: - mOut << getYuvCscStandardEXTString( - node->getUnionArrayPointer()[i].getYuvCscStandardEXTConst()); - mOut << " (const yuvCscStandardEXT)\n"; - break; - default: - mOut.prefix(SH_ERROR); - mOut << "Unknown constant\n"; - break; - } - } -} - -bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node) -{ - OutputTreeText(mOut, node, mDepth); - - mOut << "Loop with condition "; - if (node->getType() == ELoopDoWhile) - mOut << "not "; - mOut << "tested first\n"; - - ++mDepth; - - OutputTreeText(mOut, node, mDepth); - if (node->getCondition()) - { - mOut << "Loop Condition\n"; - node->getCondition()->traverse(this); - } - else - { - mOut << "No loop condition\n"; - } - - OutputTreeText(mOut, node, mDepth); - if (node->getBody()) - { - mOut << "Loop Body\n"; - node->getBody()->traverse(this); - } - else - { - mOut << "No loop body\n"; - } - - if (node->getExpression()) - { - OutputTreeText(mOut, node, mDepth); - mOut << "Loop Terminal Expression\n"; - node->getExpression()->traverse(this); - } - - --mDepth; - - return false; -} - -bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node) -{ - OutputTreeText(mOut, node, mDepth); - - switch (node->getFlowOp()) - { - case EOpKill: - mOut << "Branch: Kill"; - break; - case EOpBreak: - mOut << "Branch: Break"; - break; - case EOpContinue: - mOut << "Branch: Continue"; - break; - case EOpReturn: - mOut << "Branch: Return"; - break; - default: - mOut << "Branch: Unknown Branch"; - break; - } - - if (node->getExpression()) - { - mOut << " with expression\n"; - ++mDepth; - node->getExpression()->traverse(this); - --mDepth; - } - else - { - mOut << "\n"; - } - - return false; -} - -} // anonymous namespace - -void OutputTree(TIntermNode *root, TInfoSinkBase &out) -{ - TOutputTraverser it(out); - ASSERT(root); - root->traverse(&it); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/OutputTree.h b/src/3rdparty/angle/src/compiler/translator/OutputTree.h deleted file mode 100644 index 9f11989cb1..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputTree.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Output the AST intermediate representation of the GLSL code. - -#ifndef COMPILER_TRANSLATOR_OUTPUTTREE_H_ -#define COMPILER_TRANSLATOR_OUTPUTTREE_H_ - -namespace sh -{ - -class TIntermNode; -class TInfoSinkBase; - -// Output the AST along with metadata. -void OutputTree(TIntermNode *root, TInfoSinkBase &out); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_OUTPUTTREE_H_
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp deleted file mode 100644 index 6d11deb898..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// OutputVulkanGLSL: -// Code that outputs shaders that fit GL_KHR_vulkan_glsl. -// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side). -// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt -// - -#include "compiler/translator/OutputVulkanGLSL.h" - -#include "compiler/translator/util.h" - -namespace sh -{ - -TOutputVulkanGLSL::TOutputVulkanGLSL(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions) - : TOutputGLSL(objSink, - clampingStrategy, - hashFunction, - nameMap, - symbolTable, - shaderType, - shaderVersion, - output, - compileOptions) -{ -} - -// TODO(jmadill): This is not complete. -void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable) -{ - const TType &type = variable->getType(); - - bool needsCustomLayout = - (type.getQualifier() == EvqAttribute || type.getQualifier() == EvqFragmentOut || - type.getQualifier() == EvqVertexIn || IsVarying(type.getQualifier()) || - IsSampler(type.getBasicType())); - - if (!NeedsToWriteLayoutQualifier(type) && !needsCustomLayout) - { - return; - } - - TInfoSinkBase &out = objSink(); - const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); - out << "layout("; - - // This isn't super clean, but it gets the job done. - // See corresponding code in GlslangWrapper.cpp. - // TODO(jmadill): Ensure declarations are separated. - - TIntermSymbol *symbol = variable->getAsSymbolNode(); - ASSERT(symbol); - - if (needsCustomLayout) - { - out << "@@ LAYOUT-" << symbol->getName().getString() << " @@"; - } - - if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified) - { - ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform); - out << getImageInternalFormatString(layoutQualifier.imageInternalFormat); - } - - out << ") "; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h deleted file mode 100644 index 6e5da8b53e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// OutputVulkanGLSL: -// Code that outputs shaders that fit GL_KHR_vulkan_glsl. -// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side). -// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt -// - -#include "compiler/translator/OutputGLSL.h" - -namespace sh -{ - -class TOutputVulkanGLSL : public TOutputGLSL -{ - public: - TOutputVulkanGLSL(TInfoSinkBase &objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable *symbolTable, - sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions); - - protected: - void writeLayoutQualifier(TIntermTyped *variable) override; -}; - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ParamType.h b/src/3rdparty/angle/src/compiler/translator/ParamType.h deleted file mode 100644 index dddb4e9901..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ParamType.h +++ /dev/null @@ -1,102 +0,0 @@ -// -// Copyright 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ParamType: -// Helper type for built-in function emulator tables. Defines types for parameters. - -#ifndef COMPILER_TRANSLATOR_PARAMTYPE_H_ -#define COMPILER_TRANSLATOR_PARAMTYPE_H_ - -#include "common/angleutils.h" -#include "compiler/translator/BaseTypes.h" - -namespace sh -{ - -enum class ParamType : uint8_t -{ - Void, - Bool1, - Bool2, - Bool3, - Bool4, - Float1, - Float2, - Float3, - Float4, - Int1, - Int2, - Int3, - Int4, - Mat2, - Mat3, - Mat4, - Uint1, - Uint2, - Uint3, - Uint4, - Last, -}; - -struct ParamTypeInfo -{ - ParamType self; - TBasicType basicType; - int primarySize; - int secondarySize; -}; - -constexpr ParamTypeInfo g_ParamTypeInfo[] = { - {ParamType::Void, EbtVoid, 1, 1}, {ParamType::Bool1, EbtBool, 1, 1}, - {ParamType::Bool2, EbtBool, 2, 1}, {ParamType::Bool3, EbtBool, 3, 1}, - {ParamType::Bool4, EbtBool, 4, 1}, {ParamType::Float1, EbtFloat, 1, 1}, - {ParamType::Float2, EbtFloat, 2, 1}, {ParamType::Float3, EbtFloat, 3, 1}, - {ParamType::Float4, EbtFloat, 4, 1}, {ParamType::Int1, EbtInt, 1, 1}, - {ParamType::Int2, EbtInt, 2, 1}, {ParamType::Int3, EbtInt, 3, 1}, - {ParamType::Int4, EbtInt, 4, 1}, {ParamType::Mat2, EbtFloat, 2, 2}, - {ParamType::Mat3, EbtFloat, 3, 3}, {ParamType::Mat4, EbtFloat, 4, 4}, - {ParamType::Uint1, EbtUInt, 1, 1}, {ParamType::Uint2, EbtUInt, 2, 1}, - {ParamType::Uint3, EbtUInt, 3, 1}, {ParamType::Uint4, EbtUInt, 4, 1}, -}; - -constexpr size_t ParamTypeIndex(ParamType paramType) -{ - return static_cast<size_t>(paramType); -} - -constexpr size_t NumParamTypes() -{ - return ParamTypeIndex(ParamType::Last); -} - -static_assert(ArraySize(g_ParamTypeInfo) == NumParamTypes(), "Invalid array size"); - -constexpr TBasicType GetBasicType(ParamType paramType) -{ - return g_ParamTypeInfo[ParamTypeIndex(paramType)].basicType; -} - -constexpr int GetPrimarySize(ParamType paramType) -{ - return g_ParamTypeInfo[ParamTypeIndex(paramType)].primarySize; -} - -constexpr int GetSecondarySize(ParamType paramType) -{ - return g_ParamTypeInfo[ParamTypeIndex(paramType)].secondarySize; -} - -constexpr bool SameParamType(ParamType paramType, - TBasicType basicType, - int primarySize, - int secondarySize) -{ - return GetBasicType(paramType) == basicType && primarySize == GetPrimarySize(paramType) && - secondarySize == GetSecondarySize(paramType); -} - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_PARAMTYPE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp deleted file mode 100644 index c97f91d781..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp +++ /dev/null @@ -1,6022 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/ParseContext.h" - -#include <stdarg.h> -#include <stdio.h> - -#include "common/mathutil.h" -#include "compiler/preprocessor/SourceLocation.h" -#include "compiler/translator/Cache.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/ValidateGlobalInitializer.h" -#include "compiler/translator/ValidateSwitch.h" -#include "compiler/translator/glslang.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -/////////////////////////////////////////////////////////////////////// -// -// Sub- vector and matrix fields -// -//////////////////////////////////////////////////////////////////////// - -namespace -{ - -const int kWebGLMaxStructNesting = 4; - -const std::array<const char *, 8> kAtomicBuiltin = {{"atomicAdd", "atomicMin", "atomicMax", - "atomicAnd", "atomicOr", "atomicXor", - "atomicExchange", "atomicCompSwap"}}; - -bool IsAtomicBuiltin(const TString &name) -{ - for (size_t i = 0; i < kAtomicBuiltin.size(); ++i) - { - if (name.compare(kAtomicBuiltin[i]) == 0) - { - return true; - } - } - return false; -} - -bool ContainsSampler(const TStructure *structType); - -bool ContainsSampler(const TType &type) -{ - if (IsSampler(type.getBasicType())) - { - return true; - } - if (type.getBasicType() == EbtStruct) - { - return ContainsSampler(type.getStruct()); - } - - return false; -} - -bool ContainsSampler(const TStructure *structType) -{ - for (const auto &field : structType->fields()) - { - if (ContainsSampler(*field->type())) - return true; - } - return false; -} - -// Get a token from an image argument to use as an error message token. -const char *GetImageArgumentToken(TIntermTyped *imageNode) -{ - ASSERT(IsImage(imageNode->getBasicType())); - while (imageNode->getAsBinaryNode() && - (imageNode->getAsBinaryNode()->getOp() == EOpIndexIndirect || - imageNode->getAsBinaryNode()->getOp() == EOpIndexDirect)) - { - imageNode = imageNode->getAsBinaryNode()->getLeft(); - } - TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode(); - if (imageSymbol) - { - return imageSymbol->getSymbol().c_str(); - } - return "image"; -} - -bool CanSetDefaultPrecisionOnType(const TPublicType &type) -{ - if (!SupportsPrecision(type.getBasicType())) - { - return false; - } - if (type.getBasicType() == EbtUInt) - { - // ESSL 3.00.4 section 4.5.4 - return false; - } - if (type.isAggregate()) - { - // Not allowed to set for aggregate types - return false; - } - return true; -} - -// Map input primitive types to input array sizes in a geometry shader. -GLuint GetGeometryShaderInputArraySize(TLayoutPrimitiveType primitiveType) -{ - switch (primitiveType) - { - case EptPoints: - return 1u; - case EptLines: - return 2u; - case EptTriangles: - return 3u; - case EptLinesAdjacency: - return 4u; - case EptTrianglesAdjacency: - return 6u; - default: - UNREACHABLE(); - return 0u; - } -} - -bool IsBufferOrSharedVariable(TIntermTyped *var) -{ - if (var->isInterfaceBlock() || var->getQualifier() == EvqBuffer || - var->getQualifier() == EvqShared) - { - return true; - } - return false; -} - -} // namespace - -// This tracks each binding point's current default offset for inheritance of subsequent -// variables using the same binding, and keeps offsets unique and non overlapping. -// See GLSL ES 3.1, section 4.4.6. -class TParseContext::AtomicCounterBindingState -{ - public: - AtomicCounterBindingState() : mDefaultOffset(0) {} - // Inserts a new span and returns -1 if overlapping, else returns the starting offset of - // newly inserted span. - int insertSpan(int start, size_t length) - { - gl::RangeI newSpan(start, start + static_cast<int>(length)); - for (const auto &span : mSpans) - { - if (newSpan.intersects(span)) - { - return -1; - } - } - mSpans.push_back(newSpan); - mDefaultOffset = newSpan.high(); - return start; - } - // Inserts a new span starting from the default offset. - int appendSpan(size_t length) { return insertSpan(mDefaultOffset, length); } - void setDefaultOffset(int offset) { mDefaultOffset = offset; } - - private: - int mDefaultOffset; - std::vector<gl::RangeI> mSpans; -}; - -TParseContext::TParseContext(TSymbolTable &symt, - TExtensionBehavior &ext, - sh::GLenum type, - ShShaderSpec spec, - ShCompileOptions options, - bool checksPrecErrors, - TDiagnostics *diagnostics, - const ShBuiltInResources &resources) - : symbolTable(symt), - mDeferredNonEmptyDeclarationErrorCheck(false), - mShaderType(type), - mShaderSpec(spec), - mCompileOptions(options), - mShaderVersion(100), - mTreeRoot(nullptr), - mLoopNestingLevel(0), - mStructNestingLevel(0), - mSwitchNestingLevel(0), - mCurrentFunctionType(nullptr), - mFunctionReturnsValue(false), - mChecksPrecisionErrors(checksPrecErrors), - mFragmentPrecisionHighOnESSL1(false), - mDefaultUniformMatrixPacking(EmpColumnMajor), - mDefaultUniformBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared), - mDefaultBufferMatrixPacking(EmpColumnMajor), - mDefaultBufferBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared), - mDiagnostics(diagnostics), - mDirectiveHandler(ext, - *mDiagnostics, - mShaderVersion, - mShaderType, - resources.WEBGL_debug_shader_precision == 1), - mPreprocessor(mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()), - mScanner(nullptr), - mUsesFragData(false), - mUsesFragColor(false), - mUsesSecondaryOutputs(false), - mMinProgramTexelOffset(resources.MinProgramTexelOffset), - mMaxProgramTexelOffset(resources.MaxProgramTexelOffset), - mMinProgramTextureGatherOffset(resources.MinProgramTextureGatherOffset), - mMaxProgramTextureGatherOffset(resources.MaxProgramTextureGatherOffset), - mComputeShaderLocalSizeDeclared(false), - mComputeShaderLocalSize(-1), - mNumViews(-1), - mMaxNumViews(resources.MaxViewsOVR), - mMaxImageUnits(resources.MaxImageUnits), - mMaxCombinedTextureImageUnits(resources.MaxCombinedTextureImageUnits), - mMaxUniformLocations(resources.MaxUniformLocations), - mMaxUniformBufferBindings(resources.MaxUniformBufferBindings), - mMaxAtomicCounterBindings(resources.MaxAtomicCounterBindings), - mMaxShaderStorageBufferBindings(resources.MaxShaderStorageBufferBindings), - mDeclaringFunction(false), - mGeometryShaderInputPrimitiveType(EptUndefined), - mGeometryShaderOutputPrimitiveType(EptUndefined), - mGeometryShaderInvocations(0), - mGeometryShaderMaxVertices(-1), - mMaxGeometryShaderInvocations(resources.MaxGeometryShaderInvocations), - mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices), - mGeometryShaderInputArraySize(0u) -{ -} - -TParseContext::~TParseContext() -{ -} - -bool TParseContext::parseVectorFields(const TSourceLoc &line, - const TString &compString, - int vecSize, - TVector<int> *fieldOffsets) -{ - ASSERT(fieldOffsets); - size_t fieldCount = compString.size(); - if (fieldCount > 4u) - { - error(line, "illegal vector field selection", compString.c_str()); - return false; - } - fieldOffsets->resize(fieldCount); - - enum - { - exyzw, - ergba, - estpq - } fieldSet[4]; - - for (unsigned int i = 0u; i < fieldOffsets->size(); ++i) - { - switch (compString[i]) - { - case 'x': - (*fieldOffsets)[i] = 0; - fieldSet[i] = exyzw; - break; - case 'r': - (*fieldOffsets)[i] = 0; - fieldSet[i] = ergba; - break; - case 's': - (*fieldOffsets)[i] = 0; - fieldSet[i] = estpq; - break; - case 'y': - (*fieldOffsets)[i] = 1; - fieldSet[i] = exyzw; - break; - case 'g': - (*fieldOffsets)[i] = 1; - fieldSet[i] = ergba; - break; - case 't': - (*fieldOffsets)[i] = 1; - fieldSet[i] = estpq; - break; - case 'z': - (*fieldOffsets)[i] = 2; - fieldSet[i] = exyzw; - break; - case 'b': - (*fieldOffsets)[i] = 2; - fieldSet[i] = ergba; - break; - case 'p': - (*fieldOffsets)[i] = 2; - fieldSet[i] = estpq; - break; - - case 'w': - (*fieldOffsets)[i] = 3; - fieldSet[i] = exyzw; - break; - case 'a': - (*fieldOffsets)[i] = 3; - fieldSet[i] = ergba; - break; - case 'q': - (*fieldOffsets)[i] = 3; - fieldSet[i] = estpq; - break; - default: - error(line, "illegal vector field selection", compString.c_str()); - return false; - } - } - - for (unsigned int i = 0u; i < fieldOffsets->size(); ++i) - { - if ((*fieldOffsets)[i] >= vecSize) - { - error(line, "vector field selection out of range", compString.c_str()); - return false; - } - - if (i > 0) - { - if (fieldSet[i] != fieldSet[i - 1]) - { - error(line, "illegal - vector component fields not from the same set", - compString.c_str()); - return false; - } - } - } - - return true; -} - -/////////////////////////////////////////////////////////////////////// -// -// Errors -// -//////////////////////////////////////////////////////////////////////// - -// -// Used by flex/bison to output all syntax and parsing errors. -// -void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token) -{ - mDiagnostics->error(loc, reason, token); -} - -void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token) -{ - mDiagnostics->warning(loc, reason, token); -} - -void TParseContext::outOfRangeError(bool isError, - const TSourceLoc &loc, - const char *reason, - const char *token) -{ - if (isError) - { - error(loc, reason, token); - } - else - { - warning(loc, reason, token); - } -} - -// -// Same error message for all places assignments don't work. -// -void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right) -{ - std::stringstream reasonStream; - reasonStream << "cannot convert from '" << right << "' to '" << left << "'"; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), op); -} - -// -// Same error message for all places unary operations don't work. -// -void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand) -{ - std::stringstream reasonStream; - reasonStream << "wrong operand type - no operation '" << op - << "' exists that takes an operand of type " << operand - << " (or there is no acceptable conversion)"; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), op); -} - -// -// Same error message for all binary operations don't work. -// -void TParseContext::binaryOpError(const TSourceLoc &line, - const char *op, - TString left, - TString right) -{ - std::stringstream reasonStream; - reasonStream << "wrong operand types - no operation '" << op - << "' exists that takes a left-hand operand of type '" << left - << "' and a right operand of type '" << right - << "' (or there is no acceptable conversion)"; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), op); -} - -void TParseContext::checkPrecisionSpecified(const TSourceLoc &line, - TPrecision precision, - TBasicType type) -{ - if (!mChecksPrecisionErrors) - return; - - if (precision != EbpUndefined && !SupportsPrecision(type)) - { - error(line, "illegal type for precision qualifier", getBasicString(type)); - } - - if (precision == EbpUndefined) - { - switch (type) - { - case EbtFloat: - error(line, "No precision specified for (float)", ""); - return; - case EbtInt: - case EbtUInt: - UNREACHABLE(); // there's always a predeclared qualifier - error(line, "No precision specified (int)", ""); - return; - default: - if (IsOpaqueType(type)) - { - error(line, "No precision specified", getBasicString(type)); - return; - } - } - } -} - -// Both test and if necessary, spit out an error, to see if the node is really -// an l-value that can be operated on this way. -bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node) -{ - TIntermSymbol *symNode = node->getAsSymbolNode(); - TIntermBinary *binaryNode = node->getAsBinaryNode(); - TIntermSwizzle *swizzleNode = node->getAsSwizzleNode(); - - if (swizzleNode) - { - bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand()); - if (ok && swizzleNode->hasDuplicateOffsets()) - { - error(line, " l-value of swizzle cannot have duplicate components", op); - return false; - } - return ok; - } - - if (binaryNode) - { - switch (binaryNode->getOp()) - { - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: - return checkCanBeLValue(line, op, binaryNode->getLeft()); - default: - break; - } - error(line, " l-value required", op); - return false; - } - - std::string message; - switch (node->getQualifier()) - { - case EvqConst: - message = "can't modify a const"; - break; - case EvqConstReadOnly: - message = "can't modify a const"; - break; - case EvqAttribute: - message = "can't modify an attribute"; - break; - case EvqFragmentIn: - case EvqVertexIn: - case EvqGeometryIn: - case EvqFlatIn: - case EvqSmoothIn: - case EvqCentroidIn: - message = "can't modify an input"; - break; - case EvqUniform: - message = "can't modify a uniform"; - break; - case EvqVaryingIn: - message = "can't modify a varying"; - break; - case EvqFragCoord: - message = "can't modify gl_FragCoord"; - break; - case EvqFrontFacing: - message = "can't modify gl_FrontFacing"; - break; - case EvqPointCoord: - message = "can't modify gl_PointCoord"; - break; - case EvqNumWorkGroups: - message = "can't modify gl_NumWorkGroups"; - break; - case EvqWorkGroupSize: - message = "can't modify gl_WorkGroupSize"; - break; - case EvqWorkGroupID: - message = "can't modify gl_WorkGroupID"; - break; - case EvqLocalInvocationID: - message = "can't modify gl_LocalInvocationID"; - break; - case EvqGlobalInvocationID: - message = "can't modify gl_GlobalInvocationID"; - break; - case EvqLocalInvocationIndex: - message = "can't modify gl_LocalInvocationIndex"; - break; - case EvqViewIDOVR: - message = "can't modify gl_ViewID_OVR"; - break; - case EvqComputeIn: - message = "can't modify work group size variable"; - break; - case EvqPerVertexIn: - message = "can't modify any member in gl_in"; - break; - case EvqPrimitiveIDIn: - message = "can't modify gl_PrimitiveIDIn"; - break; - case EvqInvocationID: - message = "can't modify gl_InvocationID"; - break; - case EvqPrimitiveID: - if (mShaderType == GL_FRAGMENT_SHADER) - { - message = "can't modify gl_PrimitiveID in a fragment shader"; - } - break; - case EvqLayer: - if (mShaderType == GL_FRAGMENT_SHADER) - { - message = "can't modify gl_Layer in a fragment shader"; - } - break; - default: - // - // Type that can't be written to? - // - if (node->getBasicType() == EbtVoid) - { - message = "can't modify void"; - } - if (IsOpaqueType(node->getBasicType())) - { - message = "can't modify a variable with type "; - message += getBasicString(node->getBasicType()); - } - else if (node->getMemoryQualifier().readonly) - { - message = "can't modify a readonly variable"; - } - } - - if (message.empty() && binaryNode == 0 && symNode == 0) - { - error(line, "l-value required", op); - - return false; - } - - // - // Everything else is okay, no error. - // - if (message.empty()) - return true; - - // - // If we get here, we have an error and a message. - // - if (symNode) - { - const char *symbol = symNode->getSymbol().c_str(); - std::stringstream reasonStream; - reasonStream << "l-value required (" << message << " \"" << symbol << "\")"; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), op); - } - else - { - std::stringstream reasonStream; - reasonStream << "l-value required (" << message << ")"; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), op); - } - - return false; -} - -// Both test, and if necessary spit out an error, to see if the node is really -// a constant. -void TParseContext::checkIsConst(TIntermTyped *node) -{ - if (node->getQualifier() != EvqConst) - { - error(node->getLine(), "constant expression required", ""); - } -} - -// Both test, and if necessary spit out an error, to see if the node is really -// an integer. -void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token) -{ - if (!node->isScalarInt()) - { - error(node->getLine(), "integer expression required", token); - } -} - -// Both test, and if necessary spit out an error, to see if we are currently -// globally scoped. -bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token) -{ - if (!symbolTable.atGlobalLevel()) - { - error(line, "only allowed at global scope", token); - return false; - } - return true; -} - -// ESSL 3.00.5 sections 3.8 and 3.9. -// If it starts "gl_" or contains two consecutive underscores, it's reserved. -// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a webgl shader. -bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier) -{ - static const char *reservedErrMsg = "reserved built-in name"; - if (identifier.compare(0, 3, "gl_") == 0) - { - error(line, reservedErrMsg, "gl_"); - return false; - } - if (sh::IsWebGLBasedSpec(mShaderSpec)) - { - if (identifier.compare(0, 6, "webgl_") == 0) - { - error(line, reservedErrMsg, "webgl_"); - return false; - } - if (identifier.compare(0, 7, "_webgl_") == 0) - { - error(line, reservedErrMsg, "_webgl_"); - return false; - } - } - if (identifier.find("__") != TString::npos) - { - error(line, - "identifiers containing two consecutive underscores (__) are reserved as " - "possible future keywords", - identifier.c_str()); - return false; - } - return true; -} - -// Make sure the argument types are correct for constructing a specific type. -bool TParseContext::checkConstructorArguments(const TSourceLoc &line, - const TIntermSequence *arguments, - const TType &type) -{ - if (arguments->empty()) - { - error(line, "constructor does not have any arguments", "constructor"); - return false; - } - - for (TIntermNode *arg : *arguments) - { - const TIntermTyped *argTyped = arg->getAsTyped(); - ASSERT(argTyped != nullptr); - if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType())) - { - std::string reason("cannot convert a variable with type "); - reason += getBasicString(argTyped->getBasicType()); - error(line, reason.c_str(), "constructor"); - return false; - } - else if (argTyped->getMemoryQualifier().writeonly) - { - error(line, "cannot convert a variable with writeonly", "constructor"); - return false; - } - if (argTyped->getBasicType() == EbtVoid) - { - error(line, "cannot convert a void", "constructor"); - return false; - } - } - - if (type.isArray()) - { - // The size of an unsized constructor should already have been determined. - ASSERT(!type.isUnsizedArray()); - if (static_cast<size_t>(type.getOutermostArraySize()) != arguments->size()) - { - error(line, "array constructor needs one argument per array element", "constructor"); - return false; - } - // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of - // the array. - for (TIntermNode *const &argNode : *arguments) - { - const TType &argType = argNode->getAsTyped()->getType(); - if (mShaderVersion < 310 && argType.isArray()) - { - error(line, "constructing from a non-dereferenced array", "constructor"); - return false; - } - if (!argType.isElementTypeOf(type)) - { - error(line, "Array constructor argument has an incorrect type", "constructor"); - return false; - } - } - } - else if (type.getBasicType() == EbtStruct) - { - const TFieldList &fields = type.getStruct()->fields(); - if (fields.size() != arguments->size()) - { - error(line, - "Number of constructor parameters does not match the number of structure fields", - "constructor"); - return false; - } - - for (size_t i = 0; i < fields.size(); i++) - { - if (i >= arguments->size() || - (*arguments)[i]->getAsTyped()->getType() != *fields[i]->type()) - { - error(line, "Structure constructor arguments do not match structure fields", - "constructor"); - return false; - } - } - } - else - { - // We're constructing a scalar, vector, or matrix. - - // Note: It's okay to have too many components available, but not okay to have unused - // arguments. 'full' will go to true when enough args have been seen. If we loop again, - // there is an extra argument, so 'overFull' will become true. - - size_t size = 0; - bool full = false; - bool overFull = false; - bool matrixArg = false; - for (TIntermNode *arg : *arguments) - { - const TIntermTyped *argTyped = arg->getAsTyped(); - ASSERT(argTyped != nullptr); - - if (argTyped->getBasicType() == EbtStruct) - { - error(line, "a struct cannot be used as a constructor argument for this type", - "constructor"); - return false; - } - if (argTyped->getType().isArray()) - { - error(line, "constructing from a non-dereferenced array", "constructor"); - return false; - } - if (argTyped->getType().isMatrix()) - { - matrixArg = true; - } - - size += argTyped->getType().getObjectSize(); - if (full) - { - overFull = true; - } - if (size >= type.getObjectSize()) - { - full = true; - } - } - - if (type.isMatrix() && matrixArg) - { - if (arguments->size() != 1) - { - error(line, "constructing matrix from matrix can only take one argument", - "constructor"); - return false; - } - } - else - { - if (size != 1 && size < type.getObjectSize()) - { - error(line, "not enough data provided for construction", "constructor"); - return false; - } - if (overFull) - { - error(line, "too many arguments", "constructor"); - return false; - } - } - } - - return true; -} - -// This function checks to see if a void variable has been declared and raise an error message for -// such a case -// -// returns true in case of an error -// -bool TParseContext::checkIsNonVoid(const TSourceLoc &line, - const TString &identifier, - const TBasicType &type) -{ - if (type == EbtVoid) - { - error(line, "illegal use of type 'void'", identifier.c_str()); - return false; - } - - return true; -} - -// This function checks to see if the node (for the expression) contains a scalar boolean expression -// or not. -bool TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type) -{ - if (type->getBasicType() != EbtBool || !type->isScalar()) - { - error(line, "boolean expression expected", ""); - return false; - } - return true; -} - -// This function checks to see if the node (for the expression) contains a scalar boolean expression -// or not. -void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType) -{ - if (pType.getBasicType() != EbtBool || pType.isAggregate()) - { - error(line, "boolean expression expected", ""); - } -} - -bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line, - const TTypeSpecifierNonArray &pType, - const char *reason) -{ - if (pType.type == EbtStruct) - { - if (ContainsSampler(pType.userDef)) - { - std::stringstream reasonStream; - reasonStream << reason << " (structure contains a sampler)"; - std::string reasonStr = reasonStream.str(); - error(line, reasonStr.c_str(), getBasicString(pType.type)); - return false; - } - // only samplers need to be checked from structs, since other opaque types can't be struct - // members. - return true; - } - else if (IsOpaqueType(pType.type)) - { - error(line, reason, getBasicString(pType.type)); - return false; - } - - return true; -} - -void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line, - const TPublicType &pType) -{ - if (pType.layoutQualifier.location != -1) - { - error(line, "location must only be specified for a single input or output variable", - "location"); - } -} - -void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location, - const TLayoutQualifier &layoutQualifier) -{ - if (layoutQualifier.location != -1) - { - const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs"; - if (mShaderVersion >= 310) - { - errorMsg = - "invalid layout qualifier: only valid on shader inputs, outputs, and uniforms"; - } - error(location, errorMsg, "location"); - } -} - -void TParseContext::checkStd430IsForShaderStorageBlock(const TSourceLoc &location, - const TLayoutBlockStorage &blockStorage, - const TQualifier &qualifier) -{ - if (blockStorage == EbsStd430 && qualifier != EvqBuffer) - { - error(location, "The std430 layout is supported only for shader storage blocks.", "std430"); - } -} - -void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line, - TQualifier qualifier, - const TType &type) -{ - ASSERT(qualifier == EvqOut || qualifier == EvqInOut); - if (IsOpaqueType(type.getBasicType())) - { - error(line, "opaque types cannot be output parameters", type.getBasicString()); - } -} - -// Do size checking for an array type's size. -unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr) -{ - TIntermConstantUnion *constant = expr->getAsConstantUnion(); - - // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant - // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't - // fold as array size. - if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt()) - { - error(line, "array size must be a constant integer expression", ""); - return 1u; - } - - unsigned int size = 0u; - - if (constant->getBasicType() == EbtUInt) - { - size = constant->getUConst(0); - } - else - { - int signedSize = constant->getIConst(0); - - if (signedSize < 0) - { - error(line, "array size must be non-negative", ""); - return 1u; - } - - size = static_cast<unsigned int>(signedSize); - } - - if (size == 0u) - { - error(line, "array size must be greater than zero", ""); - return 1u; - } - - // The size of arrays is restricted here to prevent issues further down the - // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to - // 4096 registers so this should be reasonable even for aggressively optimizable code. - const unsigned int sizeLimit = 65536; - - if (size > sizeLimit) - { - error(line, "array size too large", ""); - return 1u; - } - - return size; -} - -// See if this qualifier can be an array. -bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line, - const TPublicType &elementQualifier) -{ - if ((elementQualifier.qualifier == EvqAttribute) || - (elementQualifier.qualifier == EvqVertexIn) || - (elementQualifier.qualifier == EvqConst && mShaderVersion < 300)) - { - error(line, "cannot declare arrays of this qualifier", - TType(elementQualifier).getQualifierString()); - return false; - } - - return true; -} - -// See if this element type can be formed into an array. -bool TParseContext::checkArrayElementIsNotArray(const TSourceLoc &line, - const TPublicType &elementType) -{ - if (mShaderVersion < 310 && elementType.isArray()) - { - error(line, "cannot declare arrays of arrays", - TType(elementType).getCompleteString().c_str()); - return false; - } - return true; -} - -// Check if this qualified element type can be formed into an array. This is only called when array -// brackets are associated with an identifier in a declaration, like this: -// float a[2]; -// Similar checks are done in addFullySpecifiedType for array declarations where the array brackets -// are associated with the type, like this: -// float[2] a; -bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation, - const TPublicType &elementType) -{ - if (!checkArrayElementIsNotArray(indexLocation, elementType)) - { - return false; - } - // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere. - // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section - // 4.3.4). - if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct && - sh::IsVarying(elementType.qualifier)) - { - error(indexLocation, "cannot declare arrays of structs of this qualifier", - TType(elementType).getCompleteString().c_str()); - return false; - } - return checkIsValidQualifierForArray(indexLocation, elementType); -} - -// Enforce non-initializer type/qualifier rules. -void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line, - const TString &identifier, - TType *type) -{ - ASSERT(type != nullptr); - if (type->getQualifier() == EvqConst) - { - // Make the qualifier make sense. - type->setQualifier(EvqTemporary); - - // Generate informative error messages for ESSL1. - // In ESSL3 arrays and structures containing arrays can be constant. - if (mShaderVersion < 300 && type->isStructureContainingArrays()) - { - error(line, - "structures containing arrays may not be declared constant since they cannot be " - "initialized", - identifier.c_str()); - } - else - { - error(line, "variables with qualifier 'const' must be initialized", identifier.c_str()); - } - } - // This will make the type sized if it isn't sized yet. - checkIsNotUnsizedArray(line, "implicitly sized arrays need to be initialized", - identifier.c_str(), type); -} - -// Do some simple checks that are shared between all variable declarations, -// and update the symbol table. -// -// Returns true if declaring the variable succeeded. -// -bool TParseContext::declareVariable(const TSourceLoc &line, - const TString &identifier, - const TType &type, - TVariable **variable) -{ - ASSERT((*variable) == nullptr); - - checkBindingIsValid(line, type); - - bool needsReservedCheck = true; - - // gl_LastFragData may be redeclared with a new precision qualifier - if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0) - { - const TVariable *maxDrawBuffers = static_cast<const TVariable *>( - symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion)); - if (type.isArrayOfArrays()) - { - error(line, "redeclaration of gl_LastFragData as an array of arrays", - identifier.c_str()); - return false; - } - else if (static_cast<int>(type.getOutermostArraySize()) == - maxDrawBuffers->getConstPointer()->getIConst()) - { - if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion)) - { - needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension()); - } - } - else - { - error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers", - identifier.c_str()); - return false; - } - } - - if (needsReservedCheck && !checkIsNotReserved(line, identifier)) - return false; - - (*variable) = symbolTable.declareVariable(&identifier, type); - if (!(*variable)) - { - error(line, "redefinition", identifier.c_str()); - return false; - } - - if (!checkIsNonVoid(line, identifier, type.getBasicType())) - return false; - - return true; -} - -void TParseContext::checkIsParameterQualifierValid( - const TSourceLoc &line, - const TTypeQualifierBuilder &typeQualifierBuilder, - TType *type) -{ - // The only parameter qualifiers a parameter can have are in, out, inout or const. - TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics); - - if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut) - { - checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type); - } - - if (!IsImage(type->getBasicType())) - { - checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line); - } - else - { - type->setMemoryQualifier(typeQualifier.memoryQualifier); - } - - type->setQualifier(typeQualifier.qualifier); - - if (typeQualifier.precision != EbpUndefined) - { - type->setPrecision(typeQualifier.precision); - } -} - -template <size_t size> -bool TParseContext::checkCanUseOneOfExtensions(const TSourceLoc &line, - const std::array<TExtension, size> &extensions) -{ - ASSERT(!extensions.empty()); - const TExtensionBehavior &extBehavior = extensionBehavior(); - - bool canUseWithWarning = false; - bool canUseWithoutWarning = false; - - const char *errorMsgString = ""; - TExtension errorMsgExtension = TExtension::UNDEFINED; - - for (TExtension extension : extensions) - { - auto extIter = extBehavior.find(extension); - if (canUseWithWarning) - { - // We already have an extension that we can use, but with a warning. - // See if we can use the alternative extension without a warning. - if (extIter == extBehavior.end()) - { - continue; - } - if (extIter->second == EBhEnable || extIter->second == EBhRequire) - { - canUseWithoutWarning = true; - break; - } - continue; - } - if (extIter == extBehavior.end()) - { - errorMsgString = "extension is not supported"; - errorMsgExtension = extension; - } - else if (extIter->second == EBhUndefined || extIter->second == EBhDisable) - { - errorMsgString = "extension is disabled"; - errorMsgExtension = extension; - } - else if (extIter->second == EBhWarn) - { - errorMsgExtension = extension; - canUseWithWarning = true; - } - else - { - ASSERT(extIter->second == EBhEnable || extIter->second == EBhRequire); - canUseWithoutWarning = true; - break; - } - } - - if (canUseWithoutWarning) - { - return true; - } - if (canUseWithWarning) - { - warning(line, "extension is being used", GetExtensionNameString(errorMsgExtension)); - return true; - } - error(line, errorMsgString, GetExtensionNameString(errorMsgExtension)); - return false; -} - -template bool TParseContext::checkCanUseOneOfExtensions( - const TSourceLoc &line, - const std::array<TExtension, 1> &extensions); -template bool TParseContext::checkCanUseOneOfExtensions( - const TSourceLoc &line, - const std::array<TExtension, 2> &extensions); -template bool TParseContext::checkCanUseOneOfExtensions( - const TSourceLoc &line, - const std::array<TExtension, 3> &extensions); - -bool TParseContext::checkCanUseExtension(const TSourceLoc &line, TExtension extension) -{ - ASSERT(extension != TExtension::UNDEFINED); - ASSERT(extension != TExtension::EXT_geometry_shader); - if (extension == TExtension::OES_geometry_shader) - { - // OES_geometry_shader and EXT_geometry_shader are always interchangeable. - constexpr std::array<TExtension, 2u> extensions{ - {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}; - return checkCanUseOneOfExtensions(line, extensions); - } - return checkCanUseOneOfExtensions(line, std::array<TExtension, 1u>{{extension}}); -} - -// ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause -// compile-time or link-time errors are the same whether or not the declaration is empty". -// This function implements all the checks that are done on qualifiers regardless of if the -// declaration is empty. -void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier, - const sh::TLayoutQualifier &layoutQualifier, - const TSourceLoc &location) -{ - if (qualifier == EvqShared && !layoutQualifier.isEmpty()) - { - error(location, "Shared memory declarations cannot have layout specified", "layout"); - } - - if (layoutQualifier.matrixPacking != EmpUnspecified) - { - error(location, "layout qualifier only valid for interface blocks", - getMatrixPackingString(layoutQualifier.matrixPacking)); - return; - } - - if (layoutQualifier.blockStorage != EbsUnspecified) - { - error(location, "layout qualifier only valid for interface blocks", - getBlockStorageString(layoutQualifier.blockStorage)); - return; - } - - if (qualifier == EvqFragmentOut) - { - if (layoutQualifier.location != -1 && layoutQualifier.yuv == true) - { - error(location, "invalid layout qualifier combination", "yuv"); - return; - } - } - else - { - checkYuvIsNotSpecified(location, layoutQualifier.yuv); - } - - // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous - // parsing steps. So it needs to be checked here. - if (isExtensionEnabled(TExtension::OVR_multiview) && mShaderVersion < 300 && - qualifier == EvqVertexIn) - { - error(location, "storage qualifier supported in GLSL ES 3.00 and above only", "in"); - } - - bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut; - if (mShaderVersion >= 310) - { - canHaveLocation = canHaveLocation || qualifier == EvqUniform || IsVarying(qualifier); - // We're not checking whether the uniform location is in range here since that depends on - // the type of the variable. - // The type can only be fully determined for non-empty declarations. - } - if (!canHaveLocation) - { - checkLocationIsNotSpecified(location, layoutQualifier); - } -} - -void TParseContext::atomicCounterQualifierErrorCheck(const TPublicType &publicType, - const TSourceLoc &location) -{ - if (publicType.precision != EbpHigh) - { - error(location, "Can only be highp", "atomic counter"); - } - // dEQP enforces compile error if location is specified. See uniform_location.test. - if (publicType.layoutQualifier.location != -1) - { - error(location, "location must not be set for atomic_uint", "layout"); - } - if (publicType.layoutQualifier.binding == -1) - { - error(location, "no binding specified", "atomic counter"); - } -} - -void TParseContext::emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location) -{ - if (type.isUnsizedArray()) - { - // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an - // error. It is assumed that this applies to empty declarations as well. - error(location, "empty array declaration needs to specify a size", ""); - } -} - -// These checks are done for all declarations that are non-empty. They're done for non-empty -// declarations starting a declarator list, and declarators that follow an empty declaration. -void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType, - const TSourceLoc &identifierLocation) -{ - switch (publicType.qualifier) - { - case EvqVaryingIn: - case EvqVaryingOut: - case EvqAttribute: - case EvqVertexIn: - case EvqFragmentOut: - case EvqComputeIn: - if (publicType.getBasicType() == EbtStruct) - { - error(identifierLocation, "cannot be used with a structure", - getQualifierString(publicType.qualifier)); - return; - } - break; - case EvqBuffer: - if (publicType.getBasicType() != EbtInterfaceBlock) - { - error(identifierLocation, - "cannot declare buffer variables at global scope(outside a block)", - getQualifierString(publicType.qualifier)); - return; - } - break; - default: - break; - } - std::string reason(getBasicString(publicType.getBasicType())); - reason += "s must be uniform"; - if (publicType.qualifier != EvqUniform && - !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str())) - { - return; - } - - if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal && - publicType.qualifier != EvqConst) && - publicType.getBasicType() == EbtYuvCscStandardEXT) - { - error(identifierLocation, "cannot be used with a yuvCscStandardEXT", - getQualifierString(publicType.qualifier)); - return; - } - - if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform) - { - // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized. - // But invalid shaders may still reach here with an unsized array declaration. - TType type(publicType); - if (!type.isUnsizedArray()) - { - checkUniformLocationInRange(identifierLocation, type.getLocationCount(), - publicType.layoutQualifier); - } - } - - // check for layout qualifier issues - const TLayoutQualifier layoutQualifier = publicType.layoutQualifier; - - if (IsImage(publicType.getBasicType())) - { - - switch (layoutQualifier.imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - case EiifRGBA8: - case EiifRGBA8_SNORM: - if (!IsFloatImage(publicType.getBasicType())) - { - error(identifierLocation, - "internal image format requires a floating image type", - getBasicString(publicType.getBasicType())); - return; - } - break; - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - if (!IsIntegerImage(publicType.getBasicType())) - { - error(identifierLocation, - "internal image format requires an integer image type", - getBasicString(publicType.getBasicType())); - return; - } - break; - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - if (!IsUnsignedImage(publicType.getBasicType())) - { - error(identifierLocation, - "internal image format requires an unsigned image type", - getBasicString(publicType.getBasicType())); - return; - } - break; - case EiifUnspecified: - error(identifierLocation, "layout qualifier", "No image internal format specified"); - return; - default: - error(identifierLocation, "layout qualifier", "unrecognized token"); - return; - } - - // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers - switch (layoutQualifier.imageInternalFormat) - { - case EiifR32F: - case EiifR32I: - case EiifR32UI: - break; - default: - if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly) - { - error(identifierLocation, "layout qualifier", - "Except for images with the r32f, r32i and r32ui format qualifiers, " - "image variables must be qualified readonly and/or writeonly"); - return; - } - break; - } - } - else - { - checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat); - checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation); - } - - if (IsAtomicCounter(publicType.getBasicType())) - { - atomicCounterQualifierErrorCheck(publicType, identifierLocation); - } - else - { - checkOffsetIsNotSpecified(identifierLocation, layoutQualifier.offset); - } -} - -void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type) -{ - TLayoutQualifier layoutQualifier = type.getLayoutQualifier(); - // Note that the ESSL 3.10 section 4.4.5 is not particularly clear on how the binding qualifier - // on arrays of arrays should be handled. We interpret the spec so that the binding value is - // incremented for each element of the innermost nested arrays. This is in line with how arrays - // of arrays of blocks are specified to behave in GLSL 4.50 and a conservative interpretation - // when it comes to which shaders are accepted by the compiler. - int arrayTotalElementCount = type.getArraySizeProduct(); - if (IsImage(type.getBasicType())) - { - checkImageBindingIsValid(identifierLocation, layoutQualifier.binding, - arrayTotalElementCount); - } - else if (IsSampler(type.getBasicType())) - { - checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding, - arrayTotalElementCount); - } - else if (IsAtomicCounter(type.getBasicType())) - { - checkAtomicCounterBindingIsValid(identifierLocation, layoutQualifier.binding); - } - else - { - ASSERT(!IsOpaqueType(type.getBasicType())); - checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding); - } -} - -void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location, - const TString &layoutQualifierName, - int versionRequired) -{ - - if (mShaderVersion < versionRequired) - { - error(location, "invalid layout qualifier: not supported", layoutQualifierName.c_str()); - } -} - -bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location, - const TLayoutQualifier &layoutQualifier) -{ - const sh::WorkGroupSize &localSize = layoutQualifier.localSize; - for (size_t i = 0u; i < localSize.size(); ++i) - { - if (localSize[i] != -1) - { - error(location, - "invalid layout qualifier: only valid when used with 'in' in a compute shader " - "global layout declaration", - getWorkGroupSizeString(i)); - return false; - } - } - - return true; -} - -void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location, - TLayoutImageInternalFormat internalFormat) -{ - if (internalFormat != EiifUnspecified) - { - error(location, "invalid layout qualifier: only valid when used with images", - getImageInternalFormatString(internalFormat)); - } -} - -void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding) -{ - if (binding != -1) - { - error(location, - "invalid layout qualifier: only valid when used with opaque types or blocks", - "binding"); - } -} - -void TParseContext::checkOffsetIsNotSpecified(const TSourceLoc &location, int offset) -{ - if (offset != -1) - { - error(location, "invalid layout qualifier: only valid when used with atomic counters", - "offset"); - } -} - -void TParseContext::checkImageBindingIsValid(const TSourceLoc &location, - int binding, - int arrayTotalElementCount) -{ - // Expects arraySize to be 1 when setting binding for only a single variable. - if (binding >= 0 && binding + arrayTotalElementCount > mMaxImageUnits) - { - error(location, "image binding greater than gl_MaxImageUnits", "binding"); - } -} - -void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location, - int binding, - int arrayTotalElementCount) -{ - // Expects arraySize to be 1 when setting binding for only a single variable. - if (binding >= 0 && binding + arrayTotalElementCount > mMaxCombinedTextureImageUnits) - { - error(location, "sampler binding greater than maximum texture units", "binding"); - } -} - -void TParseContext::checkBlockBindingIsValid(const TSourceLoc &location, - const TQualifier &qualifier, - int binding, - int arraySize) -{ - int size = (arraySize == 0 ? 1 : arraySize); - if (qualifier == EvqUniform) - { - if (binding + size > mMaxUniformBufferBindings) - { - error(location, "uniform block binding greater than MAX_UNIFORM_BUFFER_BINDINGS", - "binding"); - } - } - else if (qualifier == EvqBuffer) - { - if (binding + size > mMaxShaderStorageBufferBindings) - { - error(location, - "shader storage block binding greater than MAX_SHADER_STORAGE_BUFFER_BINDINGS", - "binding"); - } - } -} -void TParseContext::checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding) -{ - if (binding >= mMaxAtomicCounterBindings) - { - error(location, "atomic counter binding greater than gl_MaxAtomicCounterBindings", - "binding"); - } -} - -void TParseContext::checkUniformLocationInRange(const TSourceLoc &location, - int objectLocationCount, - const TLayoutQualifier &layoutQualifier) -{ - int loc = layoutQualifier.location; - if (loc >= 0 && loc + objectLocationCount > mMaxUniformLocations) - { - error(location, "Uniform location out of range", "location"); - } -} - -void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv) -{ - if (yuv != false) - { - error(location, "invalid layout qualifier: only valid on program outputs", "yuv"); - } -} - -void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandidate, - TIntermAggregate *fnCall) -{ - for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) - { - TQualifier qual = fnCandidate->getParam(i).type->getQualifier(); - TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped(); - if (!IsImage(argument->getBasicType()) && (IsQualifierUnspecified(qual) || qual == EvqIn || - qual == EvqInOut || qual == EvqConstReadOnly)) - { - if (argument->getMemoryQualifier().writeonly) - { - error(argument->getLine(), - "Writeonly value cannot be passed for 'in' or 'inout' parameters.", - fnCall->getFunctionSymbolInfo()->getName().c_str()); - return; - } - } - if (qual == EvqOut || qual == EvqInOut) - { - if (!checkCanBeLValue(argument->getLine(), "assign", argument)) - { - error(argument->getLine(), - "Constant value cannot be passed for 'out' or 'inout' parameters.", - fnCall->getFunctionSymbolInfo()->getName().c_str()); - return; - } - } - } -} - -void TParseContext::checkInvariantVariableQualifier(bool invariant, - const TQualifier qualifier, - const TSourceLoc &invariantLocation) -{ - if (!invariant) - return; - - if (mShaderVersion < 300) - { - // input variables in the fragment shader can be also qualified as invariant - if (!sh::CanBeInvariantESSL1(qualifier)) - { - error(invariantLocation, "Cannot be qualified as invariant.", "invariant"); - } - } - else - { - if (!sh::CanBeInvariantESSL3OrGreater(qualifier)) - { - error(invariantLocation, "Cannot be qualified as invariant.", "invariant"); - } - } -} - -bool TParseContext::isExtensionEnabled(TExtension extension) const -{ - return IsExtensionEnabled(extensionBehavior(), extension); -} - -void TParseContext::handleExtensionDirective(const TSourceLoc &loc, - const char *extName, - const char *behavior) -{ - pp::SourceLocation srcLoc; - srcLoc.file = loc.first_file; - srcLoc.line = loc.first_line; - mDirectiveHandler.handleExtension(srcLoc, extName, behavior); -} - -void TParseContext::handlePragmaDirective(const TSourceLoc &loc, - const char *name, - const char *value, - bool stdgl) -{ - pp::SourceLocation srcLoc; - srcLoc.file = loc.first_file; - srcLoc.line = loc.first_line; - mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl); -} - -sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const -{ - sh::WorkGroupSize result(-1); - for (size_t i = 0u; i < result.size(); ++i) - { - if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1) - { - result[i] = 1; - } - else - { - result[i] = mComputeShaderLocalSize[i]; - } - } - return result; -} - -TIntermConstantUnion *TParseContext::addScalarLiteral(const TConstantUnion *constantUnion, - const TSourceLoc &line) -{ - TIntermConstantUnion *node = new TIntermConstantUnion( - constantUnion, TType(constantUnion->getType(), EbpUndefined, EvqConst)); - node->setLine(line); - return node; -} - -///////////////////////////////////////////////////////////////////////////////// -// -// Non-Errors. -// -///////////////////////////////////////////////////////////////////////////////// - -const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location, - const TString *name, - const TSymbol *symbol) -{ - if (!symbol) - { - error(location, "undeclared identifier", name->c_str()); - return nullptr; - } - - if (!symbol->isVariable()) - { - error(location, "variable expected", name->c_str()); - return nullptr; - } - - const TVariable *variable = static_cast<const TVariable *>(symbol); - - if (variable->getExtension() != TExtension::UNDEFINED) - { - checkCanUseExtension(location, variable->getExtension()); - } - - // Reject shaders using both gl_FragData and gl_FragColor - TQualifier qualifier = variable->getType().getQualifier(); - if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT) - { - mUsesFragData = true; - } - else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT) - { - mUsesFragColor = true; - } - if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT) - { - mUsesSecondaryOutputs = true; - } - - // This validation is not quite correct - it's only an error to write to - // both FragData and FragColor. For simplicity, and because users shouldn't - // be rewarded for reading from undefined varaibles, return an error - // if they are both referenced, rather than assigned. - if (mUsesFragData && mUsesFragColor) - { - const char *errorMessage = "cannot use both gl_FragData and gl_FragColor"; - if (mUsesSecondaryOutputs) - { - errorMessage = - "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)" - " and (gl_FragColor, gl_SecondaryFragColorEXT)"; - } - error(location, errorMessage, name->c_str()); - } - - // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables - if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared && - qualifier == EvqWorkGroupSize) - { - error(location, - "It is an error to use gl_WorkGroupSize before declaring the local group size", - "gl_WorkGroupSize"); - } - return variable; -} - -TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location, - const TString *name, - const TSymbol *symbol) -{ - const TVariable *variable = getNamedVariable(location, name, symbol); - - if (!variable) - { - TIntermTyped *node = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); - node->setLine(location); - return node; - } - - const TType &variableType = variable->getType(); - TIntermTyped *node = nullptr; - - if (variable->getConstPointer()) - { - const TConstantUnion *constArray = variable->getConstPointer(); - node = new TIntermConstantUnion(constArray, variableType); - } - else if (variableType.getQualifier() == EvqWorkGroupSize && mComputeShaderLocalSizeDeclared) - { - // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it - // needs to be added to the AST as a constant and not as a symbol. - sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize(); - TConstantUnion *constArray = new TConstantUnion[3]; - for (size_t i = 0; i < 3; ++i) - { - constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i])); - } - - ASSERT(variableType.getBasicType() == EbtUInt); - ASSERT(variableType.getObjectSize() == 3); - - TType type(variableType); - type.setQualifier(EvqConst); - node = new TIntermConstantUnion(constArray, type); - } - else if ((mGeometryShaderInputPrimitiveType != EptUndefined) && - (variableType.getQualifier() == EvqPerVertexIn)) - { - ASSERT(mGeometryShaderInputArraySize > 0u); - - node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), variableType); - node->getTypePointer()->sizeOutermostUnsizedArray(mGeometryShaderInputArraySize); - } - else - { - node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), variableType); - } - ASSERT(node != nullptr); - node->setLine(location); - return node; -} - -// Initializers show up in several places in the grammar. Have one set of -// code to handle them here. -// -// Returns true on success. -bool TParseContext::executeInitializer(const TSourceLoc &line, - const TString &identifier, - TType type, - TIntermTyped *initializer, - TIntermBinary **initNode) -{ - ASSERT(initNode != nullptr); - ASSERT(*initNode == nullptr); - - TVariable *variable = nullptr; - if (type.isUnsizedArray()) - { - // In case initializer is not an array or type has more dimensions than initializer, this - // will default to setting array sizes to 1. We have not checked yet whether the initializer - // actually is an array or not. Having a non-array initializer for an unsized array will - // result in an error later, so we don't generate an error message here. - auto *arraySizes = initializer->getType().getArraySizes(); - type.sizeUnsizedArrays(arraySizes); - } - if (!declareVariable(line, identifier, type, &variable)) - { - return false; - } - - bool globalInitWarning = false; - if (symbolTable.atGlobalLevel() && - !ValidateGlobalInitializer(initializer, this, &globalInitWarning)) - { - // Error message does not completely match behavior with ESSL 1.00, but - // we want to steer developers towards only using constant expressions. - error(line, "global variable initializers must be constant expressions", "="); - return false; - } - if (globalInitWarning) - { - warning( - line, - "global variable initializers should be constant expressions " - "(uniforms and globals are allowed in global initializers for legacy compatibility)", - "="); - } - - // - // identifier must be of type constant, a global, or a temporary - // - TQualifier qualifier = variable->getType().getQualifier(); - if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) - { - error(line, " cannot initialize this type of qualifier ", - variable->getType().getQualifierString()); - return false; - } - // - // test for and propagate constant - // - - if (qualifier == EvqConst) - { - if (qualifier != initializer->getType().getQualifier()) - { - std::stringstream reasonStream; - reasonStream << "assigning non-constant to '" << variable->getType().getCompleteString() - << "'"; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), "="); - variable->getType().setQualifier(EvqTemporary); - return false; - } - if (type != initializer->getType()) - { - error(line, " non-matching types for const initializer ", - variable->getType().getQualifierString()); - variable->getType().setQualifier(EvqTemporary); - return false; - } - - // Save the constant folded value to the variable if possible. For example array - // initializers are not folded, since that way copying the array literal to multiple places - // in the shader is avoided. - // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where - // it would be beneficial. - if (initializer->getAsConstantUnion()) - { - variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); - ASSERT(*initNode == nullptr); - return true; - } - else if (initializer->getAsSymbolNode()) - { - const TSymbol *symbol = - symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0); - const TVariable *tVar = static_cast<const TVariable *>(symbol); - - const TConstantUnion *constArray = tVar->getConstPointer(); - if (constArray) - { - variable->shareConstPointer(constArray); - ASSERT(*initNode == nullptr); - return true; - } - } - } - - TIntermSymbol *intermSymbol = - new TIntermSymbol(variable->getUniqueId(), variable->getName(), variable->getType()); - intermSymbol->setLine(line); - *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line); - if (*initNode == nullptr) - { - assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); - return false; - } - - return true; -} - -TIntermNode *TParseContext::addConditionInitializer(const TPublicType &pType, - const TString &identifier, - TIntermTyped *initializer, - const TSourceLoc &loc) -{ - checkIsScalarBool(loc, pType); - TIntermBinary *initNode = nullptr; - TType type(pType); - if (executeInitializer(loc, identifier, type, initializer, &initNode)) - { - // The initializer is valid. The init condition needs to have a node - either the - // initializer node, or a constant node in case the initialized variable is const and won't - // be recorded in the AST. - if (initNode == nullptr) - { - return initializer; - } - else - { - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->appendDeclarator(initNode); - return declaration; - } - } - return nullptr; -} - -TIntermNode *TParseContext::addLoop(TLoopType type, - TIntermNode *init, - TIntermNode *cond, - TIntermTyped *expr, - TIntermNode *body, - const TSourceLoc &line) -{ - TIntermNode *node = nullptr; - TIntermTyped *typedCond = nullptr; - if (cond) - { - typedCond = cond->getAsTyped(); - } - if (cond == nullptr || typedCond) - { - if (type == ELoopDoWhile) - { - checkIsScalarBool(line, typedCond); - } - // In the case of other loops, it was checked before that the condition is a scalar boolean. - ASSERT(mDiagnostics->numErrors() > 0 || typedCond == nullptr || - (typedCond->getBasicType() == EbtBool && !typedCond->isArray() && - !typedCond->isVector())); - - node = new TIntermLoop(type, init, typedCond, expr, EnsureBlock(body)); - node->setLine(line); - return node; - } - - ASSERT(type != ELoopDoWhile); - - TIntermDeclaration *declaration = cond->getAsDeclarationNode(); - ASSERT(declaration); - TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode(); - ASSERT(declarator->getLeft()->getAsSymbolNode()); - - // The condition is a declaration. In the AST representation we don't support declarations as - // loop conditions. Wrap the loop to a block that declares the condition variable and contains - // the loop. - TIntermBlock *block = new TIntermBlock(); - - TIntermDeclaration *declareCondition = new TIntermDeclaration(); - declareCondition->appendDeclarator(declarator->getLeft()->deepCopy()); - block->appendStatement(declareCondition); - - TIntermBinary *conditionInit = new TIntermBinary(EOpAssign, declarator->getLeft()->deepCopy(), - declarator->getRight()->deepCopy()); - TIntermLoop *loop = new TIntermLoop(type, init, conditionInit, expr, EnsureBlock(body)); - block->appendStatement(loop); - loop->setLine(line); - block->setLine(line); - return block; -} - -TIntermNode *TParseContext::addIfElse(TIntermTyped *cond, - TIntermNodePair code, - const TSourceLoc &loc) -{ - bool isScalarBool = checkIsScalarBool(loc, cond); - - // For compile time constant conditions, prune the code now. - if (isScalarBool && cond->getAsConstantUnion()) - { - if (cond->getAsConstantUnion()->getBConst(0) == true) - { - return EnsureBlock(code.node1); - } - else - { - return EnsureBlock(code.node2); - } - } - - TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2)); - node->setLine(loc); - - return node; -} - -void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier) -{ - checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision, - typeSpecifier->getBasicType()); - - if (mShaderVersion < 300 && typeSpecifier->isArray()) - { - error(typeSpecifier->getLine(), "not supported", "first-class array"); - typeSpecifier->clearArrayness(); - } -} - -TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder, - const TPublicType &typeSpecifier) -{ - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); - - TPublicType returnType = typeSpecifier; - returnType.qualifier = typeQualifier.qualifier; - returnType.invariant = typeQualifier.invariant; - returnType.layoutQualifier = typeQualifier.layoutQualifier; - returnType.memoryQualifier = typeQualifier.memoryQualifier; - returnType.precision = typeSpecifier.precision; - - if (typeQualifier.precision != EbpUndefined) - { - returnType.precision = typeQualifier.precision; - } - - checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision, - typeSpecifier.getBasicType()); - - checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier, - typeSpecifier.getLine()); - - checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier); - - if (mShaderVersion < 300) - { - if (typeSpecifier.isArray()) - { - error(typeSpecifier.getLine(), "not supported", "first-class array"); - returnType.clearArrayness(); - } - - if (returnType.qualifier == EvqAttribute && - (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt)) - { - error(typeSpecifier.getLine(), "cannot be bool or int", - getQualifierString(returnType.qualifier)); - } - - if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) && - (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt)) - { - error(typeSpecifier.getLine(), "cannot be bool or int", - getQualifierString(returnType.qualifier)); - } - } - else - { - if (!returnType.layoutQualifier.isEmpty()) - { - checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout"); - } - if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn || - returnType.qualifier == EvqFragmentOut) - { - checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier, - typeSpecifier.getLine()); - } - if (returnType.qualifier == EvqComputeIn) - { - error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size", - "in"); - } - } - - return returnType; -} - -void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier, - const TPublicType &type, - const TSourceLoc &qualifierLocation) -{ - // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere. - if (type.getBasicType() == EbtBool) - { - error(qualifierLocation, "cannot be bool", getQualifierString(qualifier)); - } - - // Specific restrictions apply for vertex shader inputs and fragment shader outputs. - switch (qualifier) - { - case EvqVertexIn: - // ESSL 3.00 section 4.3.4 - if (type.isArray()) - { - error(qualifierLocation, "cannot be array", getQualifierString(qualifier)); - } - // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck - return; - case EvqFragmentOut: - // ESSL 3.00 section 4.3.6 - if (type.typeSpecifierNonArray.isMatrix()) - { - error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier)); - } - // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck - return; - default: - break; - } - - // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of - // restrictions. - bool typeContainsIntegers = - (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt || - type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt)); - if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut) - { - error(qualifierLocation, "must use 'flat' interpolation here", - getQualifierString(qualifier)); - } - - if (type.getBasicType() == EbtStruct) - { - // ESSL 3.00 sections 4.3.4 and 4.3.6. - // These restrictions are only implied by the ESSL 3.00 spec, but - // the ESSL 3.10 spec lists these restrictions explicitly. - if (type.isArray()) - { - error(qualifierLocation, "cannot be an array of structures", - getQualifierString(qualifier)); - } - if (type.isStructureContainingArrays()) - { - error(qualifierLocation, "cannot be a structure containing an array", - getQualifierString(qualifier)); - } - if (type.isStructureContainingType(EbtStruct)) - { - error(qualifierLocation, "cannot be a structure containing a structure", - getQualifierString(qualifier)); - } - if (type.isStructureContainingType(EbtBool)) - { - error(qualifierLocation, "cannot be a structure containing a bool", - getQualifierString(qualifier)); - } - } -} - -void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier) -{ - if (qualifier.getType() == QtStorage) - { - const TStorageQualifierWrapper &storageQualifier = - static_cast<const TStorageQualifierWrapper &>(qualifier); - if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst && - !symbolTable.atGlobalLevel()) - { - error(storageQualifier.getLine(), - "Local variables can only use the const storage qualifier.", - storageQualifier.getQualifierString().c_str()); - } - } -} - -void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier, - const TSourceLoc &location) -{ - const std::string reason( - "Only allowed with shader storage blocks, variables declared within shader storage blocks " - "and variables declared as image types."); - if (memoryQualifier.readonly) - { - error(location, reason.c_str(), "readonly"); - } - if (memoryQualifier.writeonly) - { - error(location, reason.c_str(), "writeonly"); - } - if (memoryQualifier.coherent) - { - error(location, reason.c_str(), "coherent"); - } - if (memoryQualifier.restrictQualifier) - { - error(location, reason.c_str(), "restrict"); - } - if (memoryQualifier.volatileQualifier) - { - error(location, reason.c_str(), "volatile"); - } -} - -// Make sure there is no offset overlapping, and store the newly assigned offset to "type" in -// intermediate tree. -void TParseContext::checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend, - const TSourceLoc &loc, - TType *type) -{ - if (!IsAtomicCounter(type->getBasicType())) - { - return; - } - - const size_t size = type->isArray() ? kAtomicCounterArrayStride * type->getArraySizeProduct() - : kAtomicCounterSize; - TLayoutQualifier layoutQualifier = type->getLayoutQualifier(); - auto &bindingState = mAtomicCounterBindingStates[layoutQualifier.binding]; - int offset; - if (layoutQualifier.offset == -1 || forceAppend) - { - offset = bindingState.appendSpan(size); - } - else - { - offset = bindingState.insertSpan(layoutQualifier.offset, size); - } - if (offset == -1) - { - error(loc, "Offset overlapping", "atomic counter"); - return; - } - layoutQualifier.offset = offset; - type->setLayoutQualifier(layoutQualifier); -} - -void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location, - const char *token, - TType *type) -{ - if (IsGeometryShaderInput(mShaderType, type->getQualifier())) - { - if (type->isArray() && type->getOutermostArraySize() == 0u) - { - // Set size for the unsized geometry shader inputs if they are declared after a valid - // input primitive declaration. - if (mGeometryShaderInputPrimitiveType != EptUndefined) - { - ASSERT(mGeometryShaderInputArraySize > 0u); - type->sizeOutermostUnsizedArray(mGeometryShaderInputArraySize); - } - else - { - // [GLSL ES 3.2 SPEC Chapter 4.4.1.2] - // An input can be declared without an array size if there is a previous layout - // which specifies the size. - error(location, - "Missing a valid input primitive declaration before declaring an unsized " - "array input", - token); - } - } - else if (type->isArray()) - { - setGeometryShaderInputArraySize(type->getOutermostArraySize(), location); - } - else - { - error(location, "Geometry shader input variable must be declared as an array", token); - } - } -} - -TIntermDeclaration *TParseContext::parseSingleDeclaration( - TPublicType &publicType, - const TSourceLoc &identifierOrTypeLocation, - const TString &identifier) -{ - TType type(publicType); - if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) && - mDirectiveHandler.pragma().stdgl.invariantAll) - { - TQualifier qualifier = type.getQualifier(); - - // The directive handler has already taken care of rejecting invalid uses of this pragma - // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all - // affected variable declarations: - // - // 1. Built-in special variables which are inputs to the fragment shader. (These are handled - // elsewhere, in TranslatorGLSL.) - // - // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It - // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but - // the way this is currently implemented we have to enable this compiler option before - // parsing the shader and determining the shading language version it uses. If this were - // implemented as a post-pass, the workaround could be more targeted. - // - // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of - // the specification, but there are desktop OpenGL drivers that expect that this is the - // behavior of the #pragma when specified in ESSL 1.00 fragment shaders. - if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn) - { - type.setInvariant(true); - } - } - - checkGeometryShaderInputAndSetArraySize(identifierOrTypeLocation, identifier.c_str(), &type); - - declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier, - identifierOrTypeLocation); - - bool emptyDeclaration = (identifier == ""); - mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration; - - TIntermSymbol *symbol = nullptr; - if (emptyDeclaration) - { - emptyDeclarationErrorCheck(type, identifierOrTypeLocation); - // In most cases we don't need to create a symbol node for an empty declaration. - // But if the empty declaration is declaring a struct type, the symbol node will store that. - if (type.getBasicType() == EbtStruct) - { - symbol = new TIntermSymbol(symbolTable.getEmptySymbolId(), "", type); - } - else if (IsAtomicCounter(publicType.getBasicType())) - { - setAtomicCounterBindingDefaultOffset(publicType, identifierOrTypeLocation); - } - } - else - { - nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation); - - checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &type); - - checkAtomicCounterOffsetDoesNotOverlap(false, identifierOrTypeLocation, &type); - - TVariable *variable = nullptr; - declareVariable(identifierOrTypeLocation, identifier, type, &variable); - - if (variable) - { - symbol = new TIntermSymbol(variable->getUniqueId(), identifier, type); - } - } - - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->setLine(identifierOrTypeLocation); - if (symbol) - { - symbol->setLine(identifierOrTypeLocation); - declaration->appendDeclarator(symbol); - } - return declaration; -} - -TIntermDeclaration *TParseContext::parseSingleArrayDeclaration( - TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - const TVector<unsigned int> &arraySizes) -{ - mDeferredNonEmptyDeclarationErrorCheck = false; - - declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier, - identifierLocation); - - nonEmptyDeclarationErrorCheck(elementType, identifierLocation); - - checkIsValidTypeAndQualifierForArray(indexLocation, elementType); - - TType arrayType(elementType); - arrayType.makeArrays(arraySizes); - - checkGeometryShaderInputAndSetArraySize(indexLocation, identifier.c_str(), &arrayType); - - checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &arrayType); - - checkAtomicCounterOffsetDoesNotOverlap(false, identifierLocation, &arrayType); - - TVariable *variable = nullptr; - declareVariable(identifierLocation, identifier, arrayType, &variable); - - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->setLine(identifierLocation); - - if (variable) - { - TIntermSymbol *symbol = new TIntermSymbol(variable->getUniqueId(), identifier, arrayType); - symbol->setLine(identifierLocation); - declaration->appendDeclarator(symbol); - } - - return declaration; -} - -TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &initLocation, - TIntermTyped *initializer) -{ - mDeferredNonEmptyDeclarationErrorCheck = false; - - declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier, - identifierLocation); - - nonEmptyDeclarationErrorCheck(publicType, identifierLocation); - - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->setLine(identifierLocation); - - TIntermBinary *initNode = nullptr; - TType type(publicType); - if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode)) - { - if (initNode) - { - declaration->appendDeclarator(initNode); - } - } - return declaration; -} - -TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration( - TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - const TVector<unsigned int> &arraySizes, - const TSourceLoc &initLocation, - TIntermTyped *initializer) -{ - mDeferredNonEmptyDeclarationErrorCheck = false; - - declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier, - identifierLocation); - - nonEmptyDeclarationErrorCheck(elementType, identifierLocation); - - checkIsValidTypeAndQualifierForArray(indexLocation, elementType); - - TType arrayType(elementType); - arrayType.makeArrays(arraySizes); - - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->setLine(identifierLocation); - - // initNode will correspond to the whole of "type b[n] = initializer". - TIntermBinary *initNode = nullptr; - if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode)) - { - if (initNode) - { - declaration->appendDeclarator(initNode); - } - } - - return declaration; -} - -TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration( - const TTypeQualifierBuilder &typeQualifierBuilder, - const TSourceLoc &identifierLoc, - const TString *identifier, - const TSymbol *symbol) -{ - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); - - if (!typeQualifier.invariant) - { - error(identifierLoc, "Expected invariant", identifier->c_str()); - return nullptr; - } - if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying")) - { - return nullptr; - } - if (!symbol) - { - error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str()); - return nullptr; - } - if (!IsQualifierUnspecified(typeQualifier.qualifier)) - { - error(identifierLoc, "invariant declaration specifies qualifier", - getQualifierString(typeQualifier.qualifier)); - } - if (typeQualifier.precision != EbpUndefined) - { - error(identifierLoc, "invariant declaration specifies precision", - getPrecisionString(typeQualifier.precision)); - } - if (!typeQualifier.layoutQualifier.isEmpty()) - { - error(identifierLoc, "invariant declaration specifies layout", "'layout'"); - } - - const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); - if (!variable) - { - return nullptr; - } - const TType &type = variable->getType(); - - checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(), - typeQualifier.line); - checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line); - - symbolTable.addInvariantVarying(std::string(identifier->c_str())); - - TIntermSymbol *intermSymbol = new TIntermSymbol(variable->getUniqueId(), *identifier, type); - intermSymbol->setLine(identifierLoc); - - return new TIntermInvariantDeclaration(intermSymbol, identifierLoc); -} - -void TParseContext::parseDeclarator(TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - TIntermDeclaration *declarationOut) -{ - // If the declaration starting this declarator list was empty (example: int,), some checks were - // not performed. - if (mDeferredNonEmptyDeclarationErrorCheck) - { - nonEmptyDeclarationErrorCheck(publicType, identifierLocation); - mDeferredNonEmptyDeclarationErrorCheck = false; - } - - checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType); - - TVariable *variable = nullptr; - TType type(publicType); - - checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier.c_str(), &type); - - checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &type); - - checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, &type); - - declareVariable(identifierLocation, identifier, type, &variable); - - if (variable) - { - TIntermSymbol *symbol = new TIntermSymbol(variable->getUniqueId(), identifier, type); - symbol->setLine(identifierLocation); - declarationOut->appendDeclarator(symbol); - } -} - -void TParseContext::parseArrayDeclarator(TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &arrayLocation, - const TVector<unsigned int> &arraySizes, - TIntermDeclaration *declarationOut) -{ - // If the declaration starting this declarator list was empty (example: int,), some checks were - // not performed. - if (mDeferredNonEmptyDeclarationErrorCheck) - { - nonEmptyDeclarationErrorCheck(elementType, identifierLocation); - mDeferredNonEmptyDeclarationErrorCheck = false; - } - - checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType); - - if (checkIsValidTypeAndQualifierForArray(arrayLocation, elementType)) - { - TType arrayType(elementType); - arrayType.makeArrays(arraySizes); - - checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier.c_str(), &arrayType); - - checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &arrayType); - - checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, &arrayType); - - TVariable *variable = nullptr; - declareVariable(identifierLocation, identifier, arrayType, &variable); - - if (variable) - { - TIntermSymbol *symbol = - new TIntermSymbol(variable->getUniqueId(), identifier, arrayType); - symbol->setLine(identifierLocation); - declarationOut->appendDeclarator(symbol); - } - } -} - -void TParseContext::parseInitDeclarator(const TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &initLocation, - TIntermTyped *initializer, - TIntermDeclaration *declarationOut) -{ - // If the declaration starting this declarator list was empty (example: int,), some checks were - // not performed. - if (mDeferredNonEmptyDeclarationErrorCheck) - { - nonEmptyDeclarationErrorCheck(publicType, identifierLocation); - mDeferredNonEmptyDeclarationErrorCheck = false; - } - - checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType); - - TIntermBinary *initNode = nullptr; - TType type(publicType); - if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode)) - { - // - // build the intermediate representation - // - if (initNode) - { - declarationOut->appendDeclarator(initNode); - } - } -} - -void TParseContext::parseArrayInitDeclarator(const TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - const TVector<unsigned int> &arraySizes, - const TSourceLoc &initLocation, - TIntermTyped *initializer, - TIntermDeclaration *declarationOut) -{ - // If the declaration starting this declarator list was empty (example: int,), some checks were - // not performed. - if (mDeferredNonEmptyDeclarationErrorCheck) - { - nonEmptyDeclarationErrorCheck(elementType, identifierLocation); - mDeferredNonEmptyDeclarationErrorCheck = false; - } - - checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType); - - checkIsValidTypeAndQualifierForArray(indexLocation, elementType); - - TType arrayType(elementType); - arrayType.makeArrays(arraySizes); - - // initNode will correspond to the whole of "b[n] = initializer". - TIntermBinary *initNode = nullptr; - if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode)) - { - if (initNode) - { - declarationOut->appendDeclarator(initNode); - } - } -} - -TIntermNode *TParseContext::addEmptyStatement(const TSourceLoc &location) -{ - // It's simpler to parse an empty statement as a constant expression rather than having a - // different type of node just for empty statements, that will be pruned from the AST anyway. - TIntermNode *node = CreateZeroNode(TType(EbtInt, EbpMedium)); - node->setLine(location); - return node; -} - -void TParseContext::setAtomicCounterBindingDefaultOffset(const TPublicType &publicType, - const TSourceLoc &location) -{ - const TLayoutQualifier &layoutQualifier = publicType.layoutQualifier; - checkAtomicCounterBindingIsValid(location, layoutQualifier.binding); - if (layoutQualifier.binding == -1 || layoutQualifier.offset == -1) - { - error(location, "Requires both binding and offset", "layout"); - return; - } - mAtomicCounterBindingStates[layoutQualifier.binding].setDefaultOffset(layoutQualifier.offset); -} - -void TParseContext::parseDefaultPrecisionQualifier(const TPrecision precision, - const TPublicType &type, - const TSourceLoc &loc) -{ - if ((precision == EbpHigh) && (getShaderType() == GL_FRAGMENT_SHADER) && - !getFragmentPrecisionHigh()) - { - error(loc, "precision is not supported in fragment shader", "highp"); - } - - if (!CanSetDefaultPrecisionOnType(type)) - { - error(loc, "illegal type argument for default precision qualifier", - getBasicString(type.getBasicType())); - return; - } - symbolTable.setDefaultPrecision(type.getBasicType(), precision); -} - -bool TParseContext::checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier) -{ - switch (typeQualifier.layoutQualifier.primitiveType) - { - case EptLines: - case EptLinesAdjacency: - case EptTriangles: - case EptTrianglesAdjacency: - return typeQualifier.qualifier == EvqGeometryIn; - - case EptLineStrip: - case EptTriangleStrip: - return typeQualifier.qualifier == EvqGeometryOut; - - case EptPoints: - return true; - - default: - UNREACHABLE(); - return false; - } -} - -void TParseContext::setGeometryShaderInputArraySize(unsigned int inputArraySize, - const TSourceLoc &line) -{ - if (mGeometryShaderInputArraySize == 0u) - { - mGeometryShaderInputArraySize = inputArraySize; - } - else if (mGeometryShaderInputArraySize != inputArraySize) - { - error(line, - "Array size or input primitive declaration doesn't match the size of earlier sized " - "array inputs.", - "layout"); - } -} - -bool TParseContext::parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier) -{ - ASSERT(typeQualifier.qualifier == EvqGeometryIn); - - const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier; - - if (layoutQualifier.maxVertices != -1) - { - error(typeQualifier.line, - "max_vertices can only be declared in 'out' layout in a geometry shader", "layout"); - return false; - } - - // Set mGeometryInputPrimitiveType if exists - if (layoutQualifier.primitiveType != EptUndefined) - { - if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier)) - { - error(typeQualifier.line, "invalid primitive type for 'in' layout", "layout"); - return false; - } - - if (mGeometryShaderInputPrimitiveType == EptUndefined) - { - mGeometryShaderInputPrimitiveType = layoutQualifier.primitiveType; - setGeometryShaderInputArraySize( - GetGeometryShaderInputArraySize(mGeometryShaderInputPrimitiveType), - typeQualifier.line); - } - else if (mGeometryShaderInputPrimitiveType != layoutQualifier.primitiveType) - { - error(typeQualifier.line, "primitive doesn't match earlier input primitive declaration", - "layout"); - return false; - } - } - - // Set mGeometryInvocations if exists - if (layoutQualifier.invocations > 0) - { - if (mGeometryShaderInvocations == 0) - { - mGeometryShaderInvocations = layoutQualifier.invocations; - } - else if (mGeometryShaderInvocations != layoutQualifier.invocations) - { - error(typeQualifier.line, "invocations contradicts to the earlier declaration", - "layout"); - return false; - } - } - - return true; -} - -bool TParseContext::parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier) -{ - ASSERT(typeQualifier.qualifier == EvqGeometryOut); - - const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier; - - if (layoutQualifier.invocations > 0) - { - error(typeQualifier.line, - "invocations can only be declared in 'in' layout in a geometry shader", "layout"); - return false; - } - - // Set mGeometryOutputPrimitiveType if exists - if (layoutQualifier.primitiveType != EptUndefined) - { - if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier)) - { - error(typeQualifier.line, "invalid primitive type for 'out' layout", "layout"); - return false; - } - - if (mGeometryShaderOutputPrimitiveType == EptUndefined) - { - mGeometryShaderOutputPrimitiveType = layoutQualifier.primitiveType; - } - else if (mGeometryShaderOutputPrimitiveType != layoutQualifier.primitiveType) - { - error(typeQualifier.line, - "primitive doesn't match earlier output primitive declaration", "layout"); - return false; - } - } - - // Set mGeometryMaxVertices if exists - if (layoutQualifier.maxVertices > -1) - { - if (mGeometryShaderMaxVertices == -1) - { - mGeometryShaderMaxVertices = layoutQualifier.maxVertices; - } - else if (mGeometryShaderMaxVertices != layoutQualifier.maxVertices) - { - error(typeQualifier.line, "max_vertices contradicts to the earlier declaration", - "layout"); - return false; - } - } - - return true; -} - -void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder) -{ - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); - const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier; - - checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier, - typeQualifier.line); - - // It should never be the case, but some strange parser errors can send us here. - if (layoutQualifier.isEmpty()) - { - error(typeQualifier.line, "Error during layout qualifier parsing.", "?"); - return; - } - - if (!layoutQualifier.isCombinationValid()) - { - error(typeQualifier.line, "invalid layout qualifier combination", "layout"); - return; - } - - checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding); - - checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line); - - checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat); - - checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv); - - checkOffsetIsNotSpecified(typeQualifier.line, layoutQualifier.offset); - - checkStd430IsForShaderStorageBlock(typeQualifier.line, layoutQualifier.blockStorage, - typeQualifier.qualifier); - - if (typeQualifier.qualifier == EvqComputeIn) - { - if (mComputeShaderLocalSizeDeclared && - !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize)) - { - error(typeQualifier.line, "Work group size does not match the previous declaration", - "layout"); - return; - } - - if (mShaderVersion < 310) - { - error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout"); - return; - } - - if (!layoutQualifier.localSize.isAnyValueSet()) - { - error(typeQualifier.line, "No local work group size specified", "layout"); - return; - } - - const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>( - symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion)); - - const TConstantUnion *maxComputeWorkGroupSizeData = - maxComputeWorkGroupSize->getConstPointer(); - - for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i) - { - if (layoutQualifier.localSize[i] != -1) - { - mComputeShaderLocalSize[i] = layoutQualifier.localSize[i]; - const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst(); - if (mComputeShaderLocalSize[i] < 1 || - mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue) - { - std::stringstream reasonStream; - reasonStream << "invalid value: Value must be at least 1 and no greater than " - << maxComputeWorkGroupSizeValue; - const std::string &reason = reasonStream.str(); - - error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i)); - return; - } - } - } - - mComputeShaderLocalSizeDeclared = true; - } - else if (typeQualifier.qualifier == EvqGeometryIn) - { - if (mShaderVersion < 310) - { - error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout"); - return; - } - - if (!parseGeometryShaderInputLayoutQualifier(typeQualifier)) - { - return; - } - } - else if (typeQualifier.qualifier == EvqGeometryOut) - { - if (mShaderVersion < 310) - { - error(typeQualifier.line, "out type qualifier supported in GLSL ES 3.10 only", - "layout"); - return; - } - - if (!parseGeometryShaderOutputLayoutQualifier(typeQualifier)) - { - return; - } - } - else if (isExtensionEnabled(TExtension::OVR_multiview) && - typeQualifier.qualifier == EvqVertexIn) - { - // This error is only specified in WebGL, but tightens unspecified behavior in the native - // specification. - if (mNumViews != -1 && layoutQualifier.numViews != mNumViews) - { - error(typeQualifier.line, "Number of views does not match the previous declaration", - "layout"); - return; - } - - if (layoutQualifier.numViews == -1) - { - error(typeQualifier.line, "No num_views specified", "layout"); - return; - } - - if (layoutQualifier.numViews > mMaxNumViews) - { - error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR", - "layout"); - return; - } - - mNumViews = layoutQualifier.numViews; - } - else - { - if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier)) - { - return; - } - - if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer) - { - error(typeQualifier.line, "invalid qualifier: global layout can only be set for blocks", - getQualifierString(typeQualifier.qualifier)); - return; - } - - if (mShaderVersion < 300) - { - error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above", - "layout"); - return; - } - - checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier); - - if (layoutQualifier.matrixPacking != EmpUnspecified) - { - if (typeQualifier.qualifier == EvqUniform) - { - mDefaultUniformMatrixPacking = layoutQualifier.matrixPacking; - } - else if (typeQualifier.qualifier == EvqBuffer) - { - mDefaultBufferMatrixPacking = layoutQualifier.matrixPacking; - } - } - - if (layoutQualifier.blockStorage != EbsUnspecified) - { - if (typeQualifier.qualifier == EvqUniform) - { - mDefaultUniformBlockStorage = layoutQualifier.blockStorage; - } - else if (typeQualifier.qualifier == EvqBuffer) - { - mDefaultBufferBlockStorage = layoutQualifier.blockStorage; - } - } - } -} - -TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction( - const TFunction &function, - const TSourceLoc &location, - bool insertParametersToSymbolTable) -{ - checkIsNotReserved(location, function.getName()); - - TIntermFunctionPrototype *prototype = - new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function)); - // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could - // point to the data that already exists in the symbol table. - prototype->getFunctionSymbolInfo()->setFromFunction(function); - prototype->setLine(location); - - for (size_t i = 0; i < function.getParamCount(); i++) - { - const TConstParameter ¶m = function.getParam(i); - - TIntermSymbol *symbol = nullptr; - - // If the parameter has no name, it's not an error, just don't add it to symbol table (could - // be used for unused args). - if (param.name != nullptr) - { - // Insert the parameter in the symbol table. - if (insertParametersToSymbolTable) - { - TVariable *variable = symbolTable.declareVariable(param.name, *param.type); - if (variable) - { - symbol = new TIntermSymbol(variable->getUniqueId(), variable->getName(), - variable->getType()); - } - else - { - error(location, "redefinition", param.name->c_str()); - } - } - // Unsized type of a named parameter should have already been checked and sanitized. - ASSERT(!param.type->isUnsizedArray()); - } - else - { - if (param.type->isUnsizedArray()) - { - error(location, "function parameter array must be sized at compile time", "[]"); - // We don't need to size the arrays since the parameter is unnamed and hence - // inaccessible. - } - } - if (!symbol) - { - // The parameter had no name or declaring the symbol failed - either way, add a nameless - // symbol. - symbol = new TIntermSymbol(symbolTable.getEmptySymbolId(), "", *param.type); - } - symbol->setLine(location); - prototype->appendParameter(symbol); - } - return prototype; -} - -TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration( - const TFunction &parsedFunction, - const TSourceLoc &location) -{ - // Note: function found from the symbol table could be the same as parsedFunction if this is the - // first declaration. Either way the instance in the symbol table is used to track whether the - // function is declared multiple times. - TFunction *function = static_cast<TFunction *>( - symbolTable.find(parsedFunction.getMangledName(), getShaderVersion())); - if (function->hasPrototypeDeclaration() && mShaderVersion == 100) - { - // ESSL 1.00.17 section 4.2.7. - // Doesn't apply to ESSL 3.00.4: see section 4.2.3. - error(location, "duplicate function prototype declarations are not allowed", "function"); - } - function->setHasPrototypeDeclaration(); - - TIntermFunctionPrototype *prototype = - createPrototypeNodeFromFunction(*function, location, false); - - symbolTable.pop(); - - if (!symbolTable.atGlobalLevel()) - { - // ESSL 3.00.4 section 4.2.4. - error(location, "local function prototype declarations are not allowed", "function"); - } - - return prototype; -} - -TIntermFunctionDefinition *TParseContext::addFunctionDefinition( - TIntermFunctionPrototype *functionPrototype, - TIntermBlock *functionBody, - const TSourceLoc &location) -{ - // Check that non-void functions have at least one return statement. - if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue) - { - error(location, "function does not return a value:", - functionPrototype->getFunctionSymbolInfo()->getName().c_str()); - } - - if (functionBody == nullptr) - { - functionBody = new TIntermBlock(); - functionBody->setLine(location); - } - TIntermFunctionDefinition *functionNode = - new TIntermFunctionDefinition(functionPrototype, functionBody); - functionNode->setLine(location); - - symbolTable.pop(); - return functionNode; -} - -void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location, - TFunction **function, - TIntermFunctionPrototype **prototypeOut) -{ - ASSERT(function); - ASSERT(*function); - const TSymbol *builtIn = - symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion()); - - if (builtIn) - { - error(location, "built-in functions cannot be redefined", (*function)->getName().c_str()); - } - else - { - TFunction *prevDec = static_cast<TFunction *>( - symbolTable.find((*function)->getMangledName(), getShaderVersion())); - - // Note: 'prevDec' could be 'function' if this is the first time we've seen function as it - // would have just been put in the symbol table. Otherwise, we're looking up an earlier - // occurance. - if (*function != prevDec) - { - // Swap the parameters of the previous declaration to the parameters of the function - // definition (parameter names may differ). - prevDec->swapParameters(**function); - - // The function definition will share the same symbol as any previous declaration. - *function = prevDec; - } - - if ((*function)->isDefined()) - { - error(location, "function already has a body", (*function)->getName().c_str()); - } - - (*function)->setDefined(); - } - - // Remember the return type for later checking for return statements. - mCurrentFunctionType = &((*function)->getReturnType()); - mFunctionReturnsValue = false; - - *prototypeOut = createPrototypeNodeFromFunction(**function, location, true); - setLoopNestingLevel(0); -} - -TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function) -{ - // - // We don't know at this point whether this is a function definition or a prototype. - // The definition production code will check for redefinitions. - // In the case of ESSL 1.00 the prototype production code will also check for redeclarations. - // - // Return types and parameter qualifiers must match in all redeclarations, so those are checked - // here. - // - TFunction *prevDec = - static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion())); - - for (size_t i = 0u; i < function->getParamCount(); ++i) - { - auto ¶m = function->getParam(i); - if (param.type->isStructSpecifier()) - { - // ESSL 3.00.6 section 12.10. - error(location, "Function parameter type cannot be a structure definition", - function->getName().c_str()); - } - } - - if (getShaderVersion() >= 300 && - symbolTable.hasUnmangledBuiltInForShaderVersion(function->getName().c_str(), - getShaderVersion())) - { - // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions. - // Therefore overloading or redefining builtin functions is an error. - error(location, "Name of a built-in function cannot be redeclared as function", - function->getName().c_str()); - } - else if (prevDec) - { - if (prevDec->getReturnType() != function->getReturnType()) - { - error(location, "function must have the same return type in all of its declarations", - function->getReturnType().getBasicString()); - } - for (size_t i = 0; i < prevDec->getParamCount(); ++i) - { - if (prevDec->getParam(i).type->getQualifier() != - function->getParam(i).type->getQualifier()) - { - error(location, - "function must have the same parameter qualifiers in all of its declarations", - function->getParam(i).type->getQualifierString()); - } - } - } - - // - // Check for previously declared variables using the same name. - // - TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion()); - if (prevSym) - { - if (!prevSym->isFunction()) - { - error(location, "redefinition of a function", function->getName().c_str()); - } - } - else - { - // Insert the unmangled name to detect potential future redefinition as a variable. - symbolTable.getOuterLevel()->insertUnmangled(function); - } - - // We're at the inner scope level of the function's arguments and body statement. - // Add the function prototype to the surrounding scope instead. - symbolTable.getOuterLevel()->insert(function); - - // Raise error message if main function takes any parameters or return anything other than void - if (function->getName() == "main") - { - if (function->getParamCount() > 0) - { - error(location, "function cannot take any parameter(s)", "main"); - } - if (function->getReturnType().getBasicType() != EbtVoid) - { - error(location, "main function cannot return a value", - function->getReturnType().getBasicString()); - } - } - - // - // If this is a redeclaration, it could also be a definition, in which case, we want to use the - // variable names from this one, and not the one that's - // being redeclared. So, pass back up this declaration, not the one in the symbol table. - // - return function; -} - -TFunction *TParseContext::parseFunctionHeader(const TPublicType &type, - const TString *name, - const TSourceLoc &location) -{ - if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary) - { - error(location, "no qualifiers allowed for function return", - getQualifierString(type.qualifier)); - } - if (!type.layoutQualifier.isEmpty()) - { - error(location, "no qualifiers allowed for function return", "layout"); - } - // make sure an opaque type is not involved as well... - std::string reason(getBasicString(type.getBasicType())); - reason += "s can't be function return values"; - checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str()); - if (mShaderVersion < 300) - { - // Array return values are forbidden, but there's also no valid syntax for declaring array - // return values in ESSL 1.00. - ASSERT(!type.isArray() || mDiagnostics->numErrors() > 0); - - if (type.isStructureContainingArrays()) - { - // ESSL 1.00.17 section 6.1 Function Definitions - error(location, "structures containing arrays can't be function return values", - TType(type).getCompleteString().c_str()); - } - } - - // Add the function as a prototype after parsing it (we do not support recursion) - return new TFunction(&symbolTable, name, new TType(type)); -} - -TFunction *TParseContext::addNonConstructorFunc(const TString *name, const TSourceLoc &loc) -{ - const TType *returnType = TCache::getType(EbtVoid, EbpUndefined); - return new TFunction(&symbolTable, name, returnType); -} - -TFunction *TParseContext::addConstructorFunc(const TPublicType &publicType) -{ - if (mShaderVersion < 300 && publicType.isArray()) - { - error(publicType.getLine(), "array constructor supported in GLSL ES 3.00 and above only", - "[]"); - } - if (publicType.isStructSpecifier()) - { - error(publicType.getLine(), "constructor can't be a structure definition", - getBasicString(publicType.getBasicType())); - } - - TType *type = new TType(publicType); - if (!type->canBeConstructed()) - { - error(publicType.getLine(), "cannot construct this type", - getBasicString(publicType.getBasicType())); - type->setBasicType(EbtFloat); - } - - return new TFunction(&symbolTable, nullptr, type, EOpConstruct); -} - -void TParseContext::checkIsNotUnsizedArray(const TSourceLoc &line, - const char *errorMessage, - const char *token, - TType *arrayType) -{ - if (arrayType->isUnsizedArray()) - { - error(line, errorMessage, token); - arrayType->sizeUnsizedArrays(nullptr); - } -} - -TParameter TParseContext::parseParameterDeclarator(TType *type, - const TString *name, - const TSourceLoc &nameLoc) -{ - ASSERT(type); - checkIsNotUnsizedArray(nameLoc, "function parameter array must specify a size", name->c_str(), - type); - if (type->getBasicType() == EbtVoid) - { - error(nameLoc, "illegal use of type 'void'", name->c_str()); - } - checkIsNotReserved(nameLoc, *name); - TParameter param = {name, type}; - return param; -} - -TParameter TParseContext::parseParameterDeclarator(const TPublicType &publicType, - const TString *name, - const TSourceLoc &nameLoc) -{ - TType *type = new TType(publicType); - return parseParameterDeclarator(type, name, nameLoc); -} - -TParameter TParseContext::parseParameterArrayDeclarator(const TString *name, - const TSourceLoc &nameLoc, - const TVector<unsigned int> &arraySizes, - const TSourceLoc &arrayLoc, - TPublicType *elementType) -{ - checkArrayElementIsNotArray(arrayLoc, *elementType); - TType *arrayType = new TType(*elementType); - arrayType->makeArrays(arraySizes); - return parseParameterDeclarator(arrayType, name, nameLoc); -} - -bool TParseContext::checkUnsizedArrayConstructorArgumentDimensionality(TIntermSequence *arguments, - TType type, - const TSourceLoc &line) -{ - if (arguments->empty()) - { - error(line, "implicitly sized array constructor must have at least one argument", "[]"); - return false; - } - for (TIntermNode *arg : *arguments) - { - TIntermTyped *element = arg->getAsTyped(); - ASSERT(element); - size_t dimensionalityFromElement = element->getType().getNumArraySizes() + 1u; - if (dimensionalityFromElement > type.getNumArraySizes()) - { - error(line, "constructing from a non-dereferenced array", "constructor"); - return false; - } - else if (dimensionalityFromElement < type.getNumArraySizes()) - { - if (dimensionalityFromElement == 1u) - { - error(line, "implicitly sized array of arrays constructor argument is not an array", - "constructor"); - } - else - { - error(line, - "implicitly sized array of arrays constructor argument dimensionality is too " - "low", - "constructor"); - } - return false; - } - } - return true; -} - -// This function is used to test for the correctness of the parameters passed to various constructor -// functions and also convert them to the right datatype if it is allowed and required. -// -// Returns a node to add to the tree regardless of if an error was generated or not. -// -TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments, - TType type, - const TSourceLoc &line) -{ - if (type.isUnsizedArray()) - { - if (!checkUnsizedArrayConstructorArgumentDimensionality(arguments, type, line)) - { - type.sizeUnsizedArrays(nullptr); - return CreateZeroNode(type); - } - TIntermTyped *firstElement = arguments->at(0)->getAsTyped(); - ASSERT(firstElement); - if (type.getOutermostArraySize() == 0u) - { - type.sizeOutermostUnsizedArray(static_cast<unsigned int>(arguments->size())); - } - for (size_t i = 0; i < firstElement->getType().getNumArraySizes(); ++i) - { - if ((*type.getArraySizes())[i] == 0u) - { - type.setArraySize(i, (*firstElement->getType().getArraySizes())[i]); - } - } - ASSERT(!type.isUnsizedArray()); - } - - if (!checkConstructorArguments(line, arguments, type)) - { - return CreateZeroNode(type); - } - - TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, arguments); - constructorNode->setLine(line); - - // TODO(oetuaho@nvidia.com): Add support for folding array constructors. - if (!constructorNode->isArray()) - { - return constructorNode->fold(mDiagnostics); - } - return constructorNode; -} - -// -// Interface/uniform blocks -// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks. -// -TIntermDeclaration *TParseContext::addInterfaceBlock( - const TTypeQualifierBuilder &typeQualifierBuilder, - const TSourceLoc &nameLine, - const TString &blockName, - TFieldList *fieldList, - const TString *instanceName, - const TSourceLoc &instanceLine, - TIntermTyped *arrayIndex, - const TSourceLoc &arrayIndexLine) -{ - checkIsNotReserved(nameLine, blockName); - - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); - - if (mShaderVersion < 310 && typeQualifier.qualifier != EvqUniform) - { - error(typeQualifier.line, - "invalid qualifier: interface blocks must be uniform in version lower than GLSL ES " - "3.10", - getQualifierString(typeQualifier.qualifier)); - } - else if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer) - { - error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform or buffer", - getQualifierString(typeQualifier.qualifier)); - } - - if (typeQualifier.invariant) - { - error(typeQualifier.line, "invalid qualifier on interface block member", "invariant"); - } - - if (typeQualifier.qualifier != EvqBuffer) - { - checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line); - } - - // add array index - unsigned int arraySize = 0; - if (arrayIndex != nullptr) - { - arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex); - } - - if (mShaderVersion < 310) - { - checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding); - } - else - { - checkBlockBindingIsValid(typeQualifier.line, typeQualifier.qualifier, - typeQualifier.layoutQualifier.binding, arraySize); - } - - checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv); - - TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier; - checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier); - checkStd430IsForShaderStorageBlock(typeQualifier.line, blockLayoutQualifier.blockStorage, - typeQualifier.qualifier); - - if (blockLayoutQualifier.matrixPacking == EmpUnspecified) - { - if (typeQualifier.qualifier == EvqUniform) - { - blockLayoutQualifier.matrixPacking = mDefaultUniformMatrixPacking; - } - else if (typeQualifier.qualifier == EvqBuffer) - { - blockLayoutQualifier.matrixPacking = mDefaultBufferMatrixPacking; - } - } - - if (blockLayoutQualifier.blockStorage == EbsUnspecified) - { - if (typeQualifier.qualifier == EvqUniform) - { - blockLayoutQualifier.blockStorage = mDefaultUniformBlockStorage; - } - else if (typeQualifier.qualifier == EvqBuffer) - { - blockLayoutQualifier.blockStorage = mDefaultBufferBlockStorage; - } - } - - checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier); - - checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat); - - if (!symbolTable.declareInterfaceBlockName(&blockName)) - { - error(nameLine, "redefinition of an interface block name", blockName.c_str()); - } - - // check for sampler types and apply layout qualifiers - for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) - { - TField *field = (*fieldList)[memberIndex]; - TType *fieldType = field->type(); - if (IsOpaqueType(fieldType->getBasicType())) - { - std::string reason("unsupported type - "); - reason += fieldType->getBasicString(); - reason += " types are not allowed in interface blocks"; - error(field->line(), reason.c_str(), fieldType->getBasicString()); - } - - const TQualifier qualifier = fieldType->getQualifier(); - switch (qualifier) - { - case EvqGlobal: - break; - case EvqUniform: - if (typeQualifier.qualifier == EvqBuffer) - { - error(field->line(), "invalid qualifier on shader storage block member", - getQualifierString(qualifier)); - } - break; - case EvqBuffer: - if (typeQualifier.qualifier == EvqUniform) - { - error(field->line(), "invalid qualifier on uniform block member", - getQualifierString(qualifier)); - } - break; - default: - error(field->line(), "invalid qualifier on interface block member", - getQualifierString(qualifier)); - break; - } - - if (fieldType->isInvariant()) - { - error(field->line(), "invalid qualifier on interface block member", "invariant"); - } - - // check layout qualifiers - TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier(); - checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier); - checkBindingIsNotSpecified(field->line(), fieldLayoutQualifier.binding); - - if (fieldLayoutQualifier.blockStorage != EbsUnspecified) - { - error(field->line(), "invalid layout qualifier: cannot be used here", - getBlockStorageString(fieldLayoutQualifier.blockStorage)); - } - - if (fieldLayoutQualifier.matrixPacking == EmpUnspecified) - { - fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking; - } - else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct) - { - warning(field->line(), - "extraneous layout qualifier: only has an effect on matrix types", - getMatrixPackingString(fieldLayoutQualifier.matrixPacking)); - } - - fieldType->setLayoutQualifier(fieldLayoutQualifier); - - if (mShaderVersion < 310 || memberIndex != fieldList->size() - 1u || - typeQualifier.qualifier != EvqBuffer) - { - // ESSL 3.10 spec section 4.1.9 allows for runtime-sized arrays. - checkIsNotUnsizedArray(field->line(), - "array members of interface blocks must specify a size", - field->name().c_str(), field->type()); - } - - if (typeQualifier.qualifier == EvqBuffer) - { - // set memory qualifiers - // GLSL ES 3.10 session 4.9 [Memory Access Qualifiers]. When a block declaration is - // qualified with a memory qualifier, it is as if all of its members were declared with - // the same memory qualifier. - const TMemoryQualifier &blockMemoryQualifier = typeQualifier.memoryQualifier; - TMemoryQualifier fieldMemoryQualifier = fieldType->getMemoryQualifier(); - fieldMemoryQualifier.readonly |= blockMemoryQualifier.readonly; - fieldMemoryQualifier.writeonly |= blockMemoryQualifier.writeonly; - fieldMemoryQualifier.coherent |= blockMemoryQualifier.coherent; - fieldMemoryQualifier.restrictQualifier |= blockMemoryQualifier.restrictQualifier; - fieldMemoryQualifier.volatileQualifier |= blockMemoryQualifier.volatileQualifier; - // TODO(jiajia.qin@intel.com): Decide whether if readonly and writeonly buffer variable - // is legal. See bug https://github.com/KhronosGroup/OpenGL-API/issues/7 - fieldType->setMemoryQualifier(fieldMemoryQualifier); - } - } - - TInterfaceBlock *interfaceBlock = - new TInterfaceBlock(&blockName, fieldList, instanceName, blockLayoutQualifier); - TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier); - if (arrayIndex != nullptr) - { - interfaceBlockType.makeArray(arraySize); - } - - TString symbolName = ""; - const TSymbolUniqueId *symbolId = nullptr; - - if (!instanceName) - { - // define symbols for the members of the interface block - for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) - { - TField *field = (*fieldList)[memberIndex]; - TType *fieldType = field->type(); - - // set parent pointer of the field variable - fieldType->setInterfaceBlock(interfaceBlock); - - TVariable *fieldVariable = symbolTable.declareVariable(&field->name(), *fieldType); - - if (fieldVariable) - { - fieldVariable->setQualifier(typeQualifier.qualifier); - } - else - { - error(field->line(), "redefinition of an interface block member name", - field->name().c_str()); - } - } - symbolId = &symbolTable.getEmptySymbolId(); - } - else - { - checkIsNotReserved(instanceLine, *instanceName); - - // add a symbol for this interface block - TVariable *instanceTypeDef = symbolTable.declareVariable(instanceName, interfaceBlockType); - if (instanceTypeDef) - { - instanceTypeDef->setQualifier(typeQualifier.qualifier); - symbolId = &instanceTypeDef->getUniqueId(); - } - else - { - error(instanceLine, "redefinition of an interface block instance name", - instanceName->c_str()); - } - symbolName = *instanceName; - } - - TIntermDeclaration *declaration = nullptr; - - if (symbolId) - { - TIntermSymbol *blockSymbol = new TIntermSymbol(*symbolId, symbolName, interfaceBlockType); - blockSymbol->setLine(typeQualifier.line); - declaration = new TIntermDeclaration(); - declaration->appendDeclarator(blockSymbol); - declaration->setLine(nameLine); - } - - exitStructDeclaration(); - return declaration; -} - -void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier) -{ - ++mStructNestingLevel; - - // Embedded structure definitions are not supported per GLSL ES spec. - // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11. - if (mStructNestingLevel > 1) - { - error(line, "Embedded struct definitions are not allowed", "struct"); - } -} - -void TParseContext::exitStructDeclaration() -{ - --mStructNestingLevel; -} - -void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field) -{ - if (!sh::IsWebGLBasedSpec(mShaderSpec)) - { - return; - } - - if (field.type()->getBasicType() != EbtStruct) - { - return; - } - - // We're already inside a structure definition at this point, so add - // one to the field's struct nesting. - if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) - { - std::stringstream reasonStream; - reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str() - << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), field.name().c_str()); - return; - } -} - -// -// Parse an array index expression -// -TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, - const TSourceLoc &location, - TIntermTyped *indexExpression) -{ - if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector()) - { - if (baseExpression->getAsSymbolNode()) - { - error(location, " left of '[' is not of type array, matrix, or vector ", - baseExpression->getAsSymbolNode()->getSymbol().c_str()); - } - else - { - error(location, " left of '[' is not of type array, matrix, or vector ", "expression"); - } - - return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); - } - - if (baseExpression->getQualifier() == EvqPerVertexIn) - { - ASSERT(mShaderType == GL_GEOMETRY_SHADER_OES); - if (mGeometryShaderInputPrimitiveType == EptUndefined) - { - error(location, "missing input primitive declaration before indexing gl_in.", "["); - return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); - } - } - - TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion(); - - // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able - // to constant fold all constant expressions. Right now we don't allow indexing interface blocks - // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the - // index is a constant expression. - if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr) - { - if (baseExpression->isInterfaceBlock()) - { - // TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks. - switch (baseExpression->getQualifier()) - { - case EvqPerVertexIn: - break; - case EvqUniform: - case EvqBuffer: - error(location, - "array indexes for uniform block arrays and shader storage block arrays " - "must be constant integral expressions", - "["); - break; - default: - // We can reach here only in error cases. - ASSERT(mDiagnostics->numErrors() > 0); - break; - } - } - else if (baseExpression->getQualifier() == EvqFragmentOut) - { - error(location, - "array indexes for fragment outputs must be constant integral expressions", "["); - } - else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData) - { - error(location, "array index for gl_FragData must be constant zero", "["); - } - } - - if (indexConstantUnion) - { - // If an out-of-range index is not qualified as constant, the behavior in the spec is - // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may - // constant fold expressions that are not constant expressions). The most compatible way to - // handle this case is to report a warning instead of an error and force the index to be in - // the correct range. - bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst; - int index = 0; - if (indexConstantUnion->getBasicType() == EbtInt) - { - index = indexConstantUnion->getIConst(0); - } - else if (indexConstantUnion->getBasicType() == EbtUInt) - { - index = static_cast<int>(indexConstantUnion->getUConst(0)); - } - - int safeIndex = -1; - - if (index < 0) - { - outOfRangeError(outOfRangeIndexIsError, location, "index expression is negative", "[]"); - safeIndex = 0; - } - - if (!baseExpression->getType().isUnsizedArray()) - { - if (baseExpression->isArray()) - { - if (baseExpression->getQualifier() == EvqFragData && index > 0) - { - if (!isExtensionEnabled(TExtension::EXT_draw_buffers)) - { - outOfRangeError(outOfRangeIndexIsError, location, - "array index for gl_FragData must be zero when " - "GL_EXT_draw_buffers is disabled", - "[]"); - safeIndex = 0; - } - } - // Only do generic out-of-range check if similar error hasn't already been reported. - if (safeIndex < 0) - { - safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index, - baseExpression->getOutermostArraySize(), - "array index out of range"); - } - } - else if (baseExpression->isMatrix()) - { - safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index, - baseExpression->getType().getCols(), - "matrix field selection out of range"); - } - else if (baseExpression->isVector()) - { - safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index, - baseExpression->getType().getNominalSize(), - "vector field selection out of range"); - } - - ASSERT(safeIndex >= 0); - // Data of constant unions can't be changed, because it may be shared with other - // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new - // sanitized object. - if (safeIndex != index || indexConstantUnion->getBasicType() != EbtInt) - { - TConstantUnion *safeConstantUnion = new TConstantUnion(); - safeConstantUnion->setIConst(safeIndex); - indexConstantUnion->replaceConstantUnion(safeConstantUnion); - indexConstantUnion->getTypePointer()->setBasicType(EbtInt); - } - - TIntermBinary *node = - new TIntermBinary(EOpIndexDirect, baseExpression, indexExpression); - node->setLine(location); - return node->fold(mDiagnostics); - } - } - - TIntermBinary *node = new TIntermBinary(EOpIndexIndirect, baseExpression, indexExpression); - node->setLine(location); - // Indirect indexing can never be constant folded. - return node; -} - -int TParseContext::checkIndexLessThan(bool outOfRangeIndexIsError, - const TSourceLoc &location, - int index, - int arraySize, - const char *reason) -{ - // Should not reach here with an unsized / runtime-sized array. - ASSERT(arraySize > 0); - if (index >= arraySize) - { - std::stringstream reasonStream; - reasonStream << reason << " '" << index << "'"; - std::string token = reasonStream.str(); - outOfRangeError(outOfRangeIndexIsError, location, reason, "[]"); - return arraySize - 1; - } - return index; -} - -TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression, - const TSourceLoc &dotLocation, - const TString &fieldString, - const TSourceLoc &fieldLocation) -{ - if (baseExpression->isArray()) - { - error(fieldLocation, "cannot apply dot operator to an array", "."); - return baseExpression; - } - - if (baseExpression->isVector()) - { - TVector<int> fieldOffsets; - if (!parseVectorFields(fieldLocation, fieldString, baseExpression->getNominalSize(), - &fieldOffsets)) - { - fieldOffsets.resize(1); - fieldOffsets[0] = 0; - } - TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldOffsets); - node->setLine(dotLocation); - - return node->fold(); - } - else if (baseExpression->getBasicType() == EbtStruct) - { - const TFieldList &fields = baseExpression->getType().getStruct()->fields(); - if (fields.empty()) - { - error(dotLocation, "structure has no fields", "Internal Error"); - return baseExpression; - } - else - { - bool fieldFound = false; - unsigned int i; - for (i = 0; i < fields.size(); ++i) - { - if (fields[i]->name() == fieldString) - { - fieldFound = true; - break; - } - } - if (fieldFound) - { - TIntermTyped *index = CreateIndexNode(i); - index->setLine(fieldLocation); - TIntermBinary *node = - new TIntermBinary(EOpIndexDirectStruct, baseExpression, index); - node->setLine(dotLocation); - return node->fold(mDiagnostics); - } - else - { - error(dotLocation, " no such field in structure", fieldString.c_str()); - return baseExpression; - } - } - } - else if (baseExpression->isInterfaceBlock()) - { - const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields(); - if (fields.empty()) - { - error(dotLocation, "interface block has no fields", "Internal Error"); - return baseExpression; - } - else - { - bool fieldFound = false; - unsigned int i; - for (i = 0; i < fields.size(); ++i) - { - if (fields[i]->name() == fieldString) - { - fieldFound = true; - break; - } - } - if (fieldFound) - { - TIntermTyped *index = CreateIndexNode(i); - index->setLine(fieldLocation); - TIntermBinary *node = - new TIntermBinary(EOpIndexDirectInterfaceBlock, baseExpression, index); - node->setLine(dotLocation); - // Indexing interface blocks can never be constant folded. - return node; - } - else - { - error(dotLocation, " no such field in interface block", fieldString.c_str()); - return baseExpression; - } - } - } - else - { - if (mShaderVersion < 300) - { - error(dotLocation, " field selection requires structure or vector on left hand side", - fieldString.c_str()); - } - else - { - error(dotLocation, - " field selection requires structure, vector, or interface block on left hand " - "side", - fieldString.c_str()); - } - return baseExpression; - } -} - -TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, - const TSourceLoc &qualifierTypeLine) -{ - TLayoutQualifier qualifier = TLayoutQualifier::Create(); - - if (qualifierType == "shared") - { - if (sh::IsWebGLBasedSpec(mShaderSpec)) - { - error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared"); - } - qualifier.blockStorage = EbsShared; - } - else if (qualifierType == "packed") - { - if (sh::IsWebGLBasedSpec(mShaderSpec)) - { - error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed"); - } - qualifier.blockStorage = EbsPacked; - } - else if (qualifierType == "std430") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.blockStorage = EbsStd430; - } - else if (qualifierType == "std140") - { - qualifier.blockStorage = EbsStd140; - } - else if (qualifierType == "row_major") - { - qualifier.matrixPacking = EmpRowMajor; - } - else if (qualifierType == "column_major") - { - qualifier.matrixPacking = EmpColumnMajor; - } - else if (qualifierType == "location") - { - error(qualifierTypeLine, "invalid layout qualifier: location requires an argument", - qualifierType.c_str()); - } - else if (qualifierType == "yuv" && mShaderType == GL_FRAGMENT_SHADER) - { - if (checkCanUseExtension(qualifierTypeLine, TExtension::EXT_YUV_target)) - { - qualifier.yuv = true; - } - } - else if (qualifierType == "rgba32f") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA32F; - } - else if (qualifierType == "rgba16f") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA16F; - } - else if (qualifierType == "r32f") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifR32F; - } - else if (qualifierType == "rgba8") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA8; - } - else if (qualifierType == "rgba8_snorm") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA8_SNORM; - } - else if (qualifierType == "rgba32i") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA32I; - } - else if (qualifierType == "rgba16i") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA16I; - } - else if (qualifierType == "rgba8i") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA8I; - } - else if (qualifierType == "r32i") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifR32I; - } - else if (qualifierType == "rgba32ui") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA32UI; - } - else if (qualifierType == "rgba16ui") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA16UI; - } - else if (qualifierType == "rgba8ui") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA8UI; - } - else if (qualifierType == "r32ui") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifR32UI; - } - else if (qualifierType == "points" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.primitiveType = EptPoints; - } - else if (qualifierType == "lines" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.primitiveType = EptLines; - } - else if (qualifierType == "lines_adjacency" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.primitiveType = EptLinesAdjacency; - } - else if (qualifierType == "triangles" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.primitiveType = EptTriangles; - } - else if (qualifierType == "triangles_adjacency" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.primitiveType = EptTrianglesAdjacency; - } - else if (qualifierType == "line_strip" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.primitiveType = EptLineStrip; - } - else if (qualifierType == "triangle_strip" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.primitiveType = EptTriangleStrip; - } - - else - { - error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str()); - } - - return qualifier; -} - -void TParseContext::parseLocalSize(const TString &qualifierType, - const TSourceLoc &qualifierTypeLine, - int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - size_t index, - sh::WorkGroupSize *localSize) -{ - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - if (intValue < 1) - { - std::stringstream reasonStream; - reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive"; - std::string reason = reasonStream.str(); - error(intValueLine, reason.c_str(), intValueString.c_str()); - } - (*localSize)[index] = intValue; -} - -void TParseContext::parseNumViews(int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - int *numViews) -{ - // This error is only specified in WebGL, but tightens unspecified behavior in the native - // specification. - if (intValue < 1) - { - error(intValueLine, "out of range: num_views must be positive", intValueString.c_str()); - } - *numViews = intValue; -} - -void TParseContext::parseInvocations(int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - int *numInvocations) -{ - // Although SPEC isn't clear whether invocations can be less than 1, we add this limit because - // it doesn't make sense to accept invocations <= 0. - if (intValue < 1 || intValue > mMaxGeometryShaderInvocations) - { - error(intValueLine, - "out of range: invocations must be in the range of [1, " - "MAX_GEOMETRY_SHADER_INVOCATIONS_OES]", - intValueString.c_str()); - } - else - { - *numInvocations = intValue; - } -} - -void TParseContext::parseMaxVertices(int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - int *maxVertices) -{ - // Although SPEC isn't clear whether max_vertices can be less than 0, we add this limit because - // it doesn't make sense to accept max_vertices < 0. - if (intValue < 0 || intValue > mMaxGeometryShaderMaxVertices) - { - error( - intValueLine, - "out of range: max_vertices must be in the range of [0, gl_MaxGeometryOutputVertices]", - intValueString.c_str()); - } - else - { - *maxVertices = intValue; - } -} - -TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, - const TSourceLoc &qualifierTypeLine, - int intValue, - const TSourceLoc &intValueLine) -{ - TLayoutQualifier qualifier = TLayoutQualifier::Create(); - - std::string intValueString = Str(intValue); - - if (qualifierType == "location") - { - // must check that location is non-negative - if (intValue < 0) - { - error(intValueLine, "out of range: location must be non-negative", - intValueString.c_str()); - } - else - { - qualifier.location = intValue; - qualifier.locationsSpecified = 1; - } - } - else if (qualifierType == "binding") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - if (intValue < 0) - { - error(intValueLine, "out of range: binding must be non-negative", - intValueString.c_str()); - } - else - { - qualifier.binding = intValue; - } - } - else if (qualifierType == "offset") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - if (intValue < 0) - { - error(intValueLine, "out of range: offset must be non-negative", - intValueString.c_str()); - } - else - { - qualifier.offset = intValue; - } - } - else if (qualifierType == "local_size_x") - { - parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u, - &qualifier.localSize); - } - else if (qualifierType == "local_size_y") - { - parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u, - &qualifier.localSize); - } - else if (qualifierType == "local_size_z") - { - parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u, - &qualifier.localSize); - } - else if (qualifierType == "num_views" && mShaderType == GL_VERTEX_SHADER) - { - if (checkCanUseExtension(qualifierTypeLine, TExtension::OVR_multiview)) - { - parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews); - } - } - else if (qualifierType == "invocations" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - parseInvocations(intValue, intValueLine, intValueString, &qualifier.invocations); - } - else if (qualifierType == "max_vertices" && mShaderType == GL_GEOMETRY_SHADER_OES && - checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) - { - parseMaxVertices(intValue, intValueLine, intValueString, &qualifier.maxVertices); - } - - else - { - error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str()); - } - - return qualifier; -} - -TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc) -{ - return new TTypeQualifierBuilder( - new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc), - mShaderVersion); -} - -TStorageQualifierWrapper *TParseContext::parseGlobalStorageQualifier(TQualifier qualifier, - const TSourceLoc &loc) -{ - checkIsAtGlobalLevel(loc, getQualifierString(qualifier)); - return new TStorageQualifierWrapper(qualifier, loc); -} - -TStorageQualifierWrapper *TParseContext::parseVaryingQualifier(const TSourceLoc &loc) -{ - if (getShaderType() == GL_VERTEX_SHADER) - { - return parseGlobalStorageQualifier(EvqVaryingOut, loc); - } - return parseGlobalStorageQualifier(EvqVaryingIn, loc); -} - -TStorageQualifierWrapper *TParseContext::parseInQualifier(const TSourceLoc &loc) -{ - if (declaringFunction()) - { - return new TStorageQualifierWrapper(EvqIn, loc); - } - - switch (getShaderType()) - { - case GL_VERTEX_SHADER: - { - if (mShaderVersion < 300 && !isExtensionEnabled(TExtension::OVR_multiview)) - { - error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in"); - } - return new TStorageQualifierWrapper(EvqVertexIn, loc); - } - case GL_FRAGMENT_SHADER: - { - if (mShaderVersion < 300) - { - error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in"); - } - return new TStorageQualifierWrapper(EvqFragmentIn, loc); - } - case GL_COMPUTE_SHADER: - { - return new TStorageQualifierWrapper(EvqComputeIn, loc); - } - case GL_GEOMETRY_SHADER_OES: - { - return new TStorageQualifierWrapper(EvqGeometryIn, loc); - } - default: - { - UNREACHABLE(); - return new TStorageQualifierWrapper(EvqLast, loc); - } - } -} - -TStorageQualifierWrapper *TParseContext::parseOutQualifier(const TSourceLoc &loc) -{ - if (declaringFunction()) - { - return new TStorageQualifierWrapper(EvqOut, loc); - } - switch (getShaderType()) - { - case GL_VERTEX_SHADER: - { - if (mShaderVersion < 300) - { - error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out"); - } - return new TStorageQualifierWrapper(EvqVertexOut, loc); - } - case GL_FRAGMENT_SHADER: - { - if (mShaderVersion < 300) - { - error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out"); - } - return new TStorageQualifierWrapper(EvqFragmentOut, loc); - } - case GL_COMPUTE_SHADER: - { - error(loc, "storage qualifier isn't supported in compute shaders", "out"); - return new TStorageQualifierWrapper(EvqLast, loc); - } - case GL_GEOMETRY_SHADER_OES: - { - return new TStorageQualifierWrapper(EvqGeometryOut, loc); - } - default: - { - UNREACHABLE(); - return new TStorageQualifierWrapper(EvqLast, loc); - } - } -} - -TStorageQualifierWrapper *TParseContext::parseInOutQualifier(const TSourceLoc &loc) -{ - if (!declaringFunction()) - { - error(loc, "invalid qualifier: can be only used with function parameters", "inout"); - } - return new TStorageQualifierWrapper(EvqInOut, loc); -} - -TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, - TLayoutQualifier rightQualifier, - const TSourceLoc &rightQualifierLocation) -{ - return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation, - mDiagnostics); -} - -TField *TParseContext::parseStructDeclarator(TString *identifier, const TSourceLoc &loc) -{ - checkIsNotReserved(loc, *identifier); - TType *type = new TType(EbtVoid, EbpUndefined); - return new TField(type, identifier, loc); -} - -TField *TParseContext::parseStructArrayDeclarator(TString *identifier, - const TSourceLoc &loc, - const TVector<unsigned int> &arraySizes, - const TSourceLoc &arraySizeLoc) -{ - checkIsNotReserved(loc, *identifier); - - TType *type = new TType(EbtVoid, EbpUndefined); - type->makeArrays(arraySizes); - - return new TField(type, identifier, loc); -} - -void TParseContext::checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin, - const TFieldList::const_iterator end, - const TString &name, - const TSourceLoc &location) -{ - for (auto fieldIter = begin; fieldIter != end; ++fieldIter) - { - if ((*fieldIter)->name() == name) - { - error(location, "duplicate field name in structure", name.c_str()); - } - } -} - -TFieldList *TParseContext::addStructFieldList(TFieldList *fields, const TSourceLoc &location) -{ - for (TFieldList::const_iterator fieldIter = fields->begin(); fieldIter != fields->end(); - ++fieldIter) - { - checkDoesNotHaveDuplicateFieldName(fields->begin(), fieldIter, (*fieldIter)->name(), - location); - } - return fields; -} - -TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields, - const TFieldList *newlyAddedFields, - const TSourceLoc &location) -{ - for (TField *field : *newlyAddedFields) - { - checkDoesNotHaveDuplicateFieldName(processedFields->begin(), processedFields->end(), - field->name(), location); - processedFields->push_back(field); - } - return processedFields; -} - -TFieldList *TParseContext::addStructDeclaratorListWithQualifiers( - const TTypeQualifierBuilder &typeQualifierBuilder, - TPublicType *typeSpecifier, - TFieldList *fieldList) -{ - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); - - typeSpecifier->qualifier = typeQualifier.qualifier; - typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier; - typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier; - typeSpecifier->invariant = typeQualifier.invariant; - if (typeQualifier.precision != EbpUndefined) - { - typeSpecifier->precision = typeQualifier.precision; - } - return addStructDeclaratorList(*typeSpecifier, fieldList); -} - -TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier, - TFieldList *declaratorList) -{ - checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision, - typeSpecifier.getBasicType()); - - checkIsNonVoid(typeSpecifier.getLine(), (*declaratorList)[0]->name(), - typeSpecifier.getBasicType()); - - checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier); - - for (TField *declarator : *declaratorList) - { - // Don't allow arrays of arrays in ESSL < 3.10. - if (declarator->type()->isArray()) - { - checkArrayElementIsNotArray(typeSpecifier.getLine(), typeSpecifier); - } - - auto *declaratorArraySizes = declarator->type()->getArraySizes(); - - TType *type = declarator->type(); - *type = TType(typeSpecifier); - if (declaratorArraySizes != nullptr) - { - for (unsigned int arraySize : *declaratorArraySizes) - { - type->makeArray(arraySize); - } - } - - checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *declarator); - } - - return declaratorList; -} - -TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine, - const TSourceLoc &nameLine, - const TString *structName, - TFieldList *fieldList) -{ - TStructure *structure = new TStructure(&symbolTable, structName, fieldList); - - // Store a bool in the struct if we're at global scope, to allow us to - // skip the local struct scoping workaround in HLSL. - structure->setAtGlobalScope(symbolTable.atGlobalLevel()); - - if (!structName->empty()) - { - checkIsNotReserved(nameLine, *structName); - if (!symbolTable.declareStructType(structure)) - { - error(nameLine, "redefinition of a struct", structName->c_str()); - } - } - - // ensure we do not specify any storage qualifiers on the struct members - for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++) - { - TField &field = *(*fieldList)[typeListIndex]; - const TQualifier qualifier = field.type()->getQualifier(); - switch (qualifier) - { - case EvqGlobal: - case EvqTemporary: - break; - default: - error(field.line(), "invalid qualifier on struct member", - getQualifierString(qualifier)); - break; - } - if (field.type()->isInvariant()) - { - error(field.line(), "invalid qualifier on struct member", "invariant"); - } - // ESSL 3.10 section 4.1.8 -- atomic_uint or images are not allowed as structure member. - if (IsImage(field.type()->getBasicType()) || IsAtomicCounter(field.type()->getBasicType())) - { - error(field.line(), "disallowed type in struct", field.type()->getBasicString()); - } - - checkIsNotUnsizedArray(field.line(), "array members of structs must specify a size", - field.name().c_str(), field.type()); - - checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line()); - - checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding); - - checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier()); - } - - TTypeSpecifierNonArray typeSpecifierNonArray; - typeSpecifierNonArray.initializeStruct(structure, true, structLine); - exitStructDeclaration(); - - return typeSpecifierNonArray; -} - -TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, - TIntermBlock *statementList, - const TSourceLoc &loc) -{ - TBasicType switchType = init->getBasicType(); - if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() || - init->isVector()) - { - error(init->getLine(), "init-expression in a switch statement must be a scalar integer", - "switch"); - return nullptr; - } - - ASSERT(statementList); - if (!ValidateSwitchStatementList(switchType, mShaderVersion, mDiagnostics, statementList, loc)) - { - ASSERT(mDiagnostics->numErrors() > 0); - return nullptr; - } - - TIntermSwitch *node = new TIntermSwitch(init, statementList); - node->setLine(loc); - return node; -} - -TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc) -{ - if (mSwitchNestingLevel == 0) - { - error(loc, "case labels need to be inside switch statements", "case"); - return nullptr; - } - if (condition == nullptr) - { - error(loc, "case label must have a condition", "case"); - return nullptr; - } - if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) || - condition->isMatrix() || condition->isArray() || condition->isVector()) - { - error(condition->getLine(), "case label must be a scalar integer", "case"); - } - TIntermConstantUnion *conditionConst = condition->getAsConstantUnion(); - // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant - // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't - // fold in case labels. - if (condition->getQualifier() != EvqConst || conditionConst == nullptr) - { - error(condition->getLine(), "case label must be constant", "case"); - } - TIntermCase *node = new TIntermCase(condition); - node->setLine(loc); - return node; -} - -TIntermCase *TParseContext::addDefault(const TSourceLoc &loc) -{ - if (mSwitchNestingLevel == 0) - { - error(loc, "default labels need to be inside switch statements", "default"); - return nullptr; - } - TIntermCase *node = new TIntermCase(nullptr); - node->setLine(loc); - return node; -} - -TIntermTyped *TParseContext::createUnaryMath(TOperator op, - TIntermTyped *child, - const TSourceLoc &loc) -{ - ASSERT(child != nullptr); - - switch (op) - { - case EOpLogicalNot: - if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() || - child->isVector()) - { - unaryOpError(loc, GetOperatorString(op), child->getCompleteString()); - return nullptr; - } - break; - case EOpBitwiseNot: - if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) || - child->isMatrix() || child->isArray()) - { - unaryOpError(loc, GetOperatorString(op), child->getCompleteString()); - return nullptr; - } - break; - case EOpPostIncrement: - case EOpPreIncrement: - case EOpPostDecrement: - case EOpPreDecrement: - case EOpNegative: - case EOpPositive: - if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() || - child->getBasicType() == EbtBool || child->isArray() || - IsOpaqueType(child->getBasicType())) - { - unaryOpError(loc, GetOperatorString(op), child->getCompleteString()); - return nullptr; - } - // Operators for built-ins are already type checked against their prototype. - default: - break; - } - - if (child->getMemoryQualifier().writeonly) - { - unaryOpError(loc, GetOperatorString(op), child->getCompleteString()); - return nullptr; - } - - TIntermUnary *node = new TIntermUnary(op, child); - node->setLine(loc); - - return node->fold(mDiagnostics); -} - -TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc) -{ - ASSERT(op != EOpNull); - TIntermTyped *node = createUnaryMath(op, child, loc); - if (node == nullptr) - { - return child; - } - return node; -} - -TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op, - TIntermTyped *child, - const TSourceLoc &loc) -{ - checkCanBeLValue(loc, GetOperatorString(op), child); - return addUnaryMath(op, child, loc); -} - -bool TParseContext::binaryOpCommonCheck(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) -{ - // Check opaque types are not allowed to be operands in expressions other than array indexing - // and structure member selection. - if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType())) - { - switch (op) - { - case EOpIndexDirect: - case EOpIndexIndirect: - break; - case EOpIndexDirectStruct: - UNREACHABLE(); - - default: - error(loc, "Invalid operation for variables with an opaque type", - GetOperatorString(op)); - return false; - } - } - - if (right->getMemoryQualifier().writeonly) - { - error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op)); - return false; - } - - if (left->getMemoryQualifier().writeonly) - { - switch (op) - { - case EOpAssign: - case EOpInitialize: - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: - break; - default: - error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op)); - return false; - } - } - - if (left->getType().getStruct() || right->getType().getStruct()) - { - switch (op) - { - case EOpIndexDirectStruct: - ASSERT(left->getType().getStruct()); - break; - case EOpEqual: - case EOpNotEqual: - case EOpAssign: - case EOpInitialize: - if (left->getType() != right->getType()) - { - return false; - } - break; - default: - error(loc, "Invalid operation for structs", GetOperatorString(op)); - return false; - } - } - - if (left->isInterfaceBlock() || right->isInterfaceBlock()) - { - switch (op) - { - case EOpIndexDirectInterfaceBlock: - ASSERT(left->getType().getInterfaceBlock()); - break; - default: - error(loc, "Invalid operation for interface blocks", GetOperatorString(op)); - return false; - } - } - - if (left->isArray() != right->isArray()) - { - error(loc, "array / non-array mismatch", GetOperatorString(op)); - return false; - } - - if (left->isArray()) - { - ASSERT(right->isArray()); - if (mShaderVersion < 300) - { - error(loc, "Invalid operation for arrays", GetOperatorString(op)); - return false; - } - - switch (op) - { - case EOpEqual: - case EOpNotEqual: - case EOpAssign: - case EOpInitialize: - break; - default: - error(loc, "Invalid operation for arrays", GetOperatorString(op)); - return false; - } - // At this point, size of implicitly sized arrays should be resolved. - if (*left->getType().getArraySizes() != *right->getType().getArraySizes()) - { - error(loc, "array size mismatch", GetOperatorString(op)); - return false; - } - } - - // Check ops which require integer / ivec parameters - bool isBitShift = false; - switch (op) - { - case EOpBitShiftLeft: - case EOpBitShiftRight: - case EOpBitShiftLeftAssign: - case EOpBitShiftRightAssign: - // Unsigned can be bit-shifted by signed and vice versa, but we need to - // check that the basic type is an integer type. - isBitShift = true; - if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType())) - { - return false; - } - break; - case EOpBitwiseAnd: - case EOpBitwiseXor: - case EOpBitwiseOr: - case EOpBitwiseAndAssign: - case EOpBitwiseXorAssign: - case EOpBitwiseOrAssign: - // It is enough to check the type of only one operand, since later it - // is checked that the operand types match. - if (!IsInteger(left->getBasicType())) - { - return false; - } - break; - default: - break; - } - - // GLSL ES 1.00 and 3.00 do not support implicit type casting. - // So the basic type should usually match. - if (!isBitShift && left->getBasicType() != right->getBasicType()) - { - return false; - } - - // Check that: - // 1. Type sizes match exactly on ops that require that. - // 2. Restrictions for structs that contain arrays or samplers are respected. - // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected. - switch (op) - { - case EOpAssign: - case EOpInitialize: - case EOpEqual: - case EOpNotEqual: - // ESSL 1.00 sections 5.7, 5.8, 5.9 - if (mShaderVersion < 300 && left->getType().isStructureContainingArrays()) - { - error(loc, "undefined operation for structs containing arrays", - GetOperatorString(op)); - return false; - } - // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7, - // we interpret the spec so that this extends to structs containing samplers, - // similarly to ESSL 1.00 spec. - if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) && - left->getType().isStructureContainingSamplers()) - { - error(loc, "undefined operation for structs containing samplers", - GetOperatorString(op)); - return false; - } - - if ((left->getNominalSize() != right->getNominalSize()) || - (left->getSecondarySize() != right->getSecondarySize())) - { - error(loc, "dimension mismatch", GetOperatorString(op)); - return false; - } - break; - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if (!left->isScalar() || !right->isScalar()) - { - error(loc, "comparison operator only defined for scalars", GetOperatorString(op)); - return false; - } - break; - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpIMod: - case EOpBitShiftLeft: - case EOpBitShiftRight: - case EOpBitwiseAnd: - case EOpBitwiseXor: - case EOpBitwiseOr: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - case EOpIModAssign: - case EOpBitShiftLeftAssign: - case EOpBitShiftRightAssign: - case EOpBitwiseAndAssign: - case EOpBitwiseXorAssign: - case EOpBitwiseOrAssign: - if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix())) - { - return false; - } - - // Are the sizes compatible? - if (left->getNominalSize() != right->getNominalSize() || - left->getSecondarySize() != right->getSecondarySize()) - { - // If the nominal sizes of operands do not match: - // One of them must be a scalar. - if (!left->isScalar() && !right->isScalar()) - return false; - - // In the case of compound assignment other than multiply-assign, - // the right side needs to be a scalar. Otherwise a vector/matrix - // would be assigned to a scalar. A scalar can't be shifted by a - // vector either. - if (!right->isScalar() && - (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight)) - return false; - } - break; - default: - break; - } - - return true; -} - -bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op, - const TType &left, - const TType &right) -{ - switch (op) - { - case EOpMul: - case EOpMulAssign: - return left.getNominalSize() == right.getNominalSize() && - left.getSecondarySize() == right.getSecondarySize(); - case EOpVectorTimesScalar: - return true; - case EOpVectorTimesScalarAssign: - ASSERT(!left.isMatrix() && !right.isMatrix()); - return left.isVector() && !right.isVector(); - case EOpVectorTimesMatrix: - return left.getNominalSize() == right.getRows(); - case EOpVectorTimesMatrixAssign: - ASSERT(!left.isMatrix() && right.isMatrix()); - return left.isVector() && left.getNominalSize() == right.getRows() && - left.getNominalSize() == right.getCols(); - case EOpMatrixTimesVector: - return left.getCols() == right.getNominalSize(); - case EOpMatrixTimesScalar: - return true; - case EOpMatrixTimesScalarAssign: - ASSERT(left.isMatrix() && !right.isMatrix()); - return !right.isVector(); - case EOpMatrixTimesMatrix: - return left.getCols() == right.getRows(); - case EOpMatrixTimesMatrixAssign: - ASSERT(left.isMatrix() && right.isMatrix()); - // We need to check two things: - // 1. The matrix multiplication step is valid. - // 2. The result will have the same number of columns as the lvalue. - return left.getCols() == right.getRows() && left.getCols() == right.getCols(); - - default: - UNREACHABLE(); - return false; - } -} - -TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) -{ - if (!binaryOpCommonCheck(op, left, right, loc)) - return nullptr; - - switch (op) - { - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - break; - case EOpLogicalOr: - case EOpLogicalXor: - case EOpLogicalAnd: - ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() && - !right->getType().getStruct()); - if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar()) - { - return nullptr; - } - // Basic types matching should have been already checked. - ASSERT(right->getBasicType() == EbtBool); - break; - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpMul: - ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() && - !right->getType().getStruct()); - if (left->getBasicType() == EbtBool) - { - return nullptr; - } - break; - case EOpIMod: - ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() && - !right->getType().getStruct()); - // Note that this is only for the % operator, not for mod() - if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat) - { - return nullptr; - } - break; - default: - break; - } - - if (op == EOpMul) - { - op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType()); - if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType())) - { - return nullptr; - } - } - - TIntermBinary *node = new TIntermBinary(op, left, right); - node->setLine(loc); - - // See if we can fold constants. - return node->fold(mDiagnostics); -} - -TIntermTyped *TParseContext::addBinaryMath(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) -{ - TIntermTyped *node = addBinaryMathInternal(op, left, right, loc); - if (node == 0) - { - binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), - right->getCompleteString()); - return left; - } - return node; -} - -TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) -{ - TIntermTyped *node = addBinaryMathInternal(op, left, right, loc); - if (node == nullptr) - { - binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), - right->getCompleteString()); - node = CreateBoolNode(false); - node->setLine(loc); - } - return node; -} - -TIntermBinary *TParseContext::createAssign(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) -{ - if (binaryOpCommonCheck(op, left, right, loc)) - { - if (op == EOpMulAssign) - { - op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType()); - if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType())) - { - return nullptr; - } - } - TIntermBinary *node = new TIntermBinary(op, left, right); - node->setLine(loc); - - return node; - } - return nullptr; -} - -TIntermTyped *TParseContext::addAssign(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) -{ - checkCanBeLValue(loc, "assign", left); - TIntermTyped *node = createAssign(op, left, right, loc); - if (node == nullptr) - { - assignError(loc, "assign", left->getCompleteString(), right->getCompleteString()); - return left; - } - return node; -} - -TIntermTyped *TParseContext::addComma(TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) -{ - // WebGL2 section 5.26, the following results in an error: - // "Sequence operator applied to void, arrays, or structs containing arrays" - if (mShaderSpec == SH_WEBGL2_SPEC && - (left->isArray() || left->getBasicType() == EbtVoid || - left->getType().isStructureContainingArrays() || right->isArray() || - right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays())) - { - error(loc, - "sequence operator is not allowed for void, arrays, or structs containing arrays", - ","); - } - - TIntermBinary *commaNode = new TIntermBinary(EOpComma, left, right); - TQualifier resultQualifier = TIntermBinary::GetCommaQualifier(mShaderVersion, left, right); - commaNode->getTypePointer()->setQualifier(resultQualifier); - return commaNode->fold(mDiagnostics); -} - -TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc) -{ - switch (op) - { - case EOpContinue: - if (mLoopNestingLevel <= 0) - { - error(loc, "continue statement only allowed in loops", ""); - } - break; - case EOpBreak: - if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0) - { - error(loc, "break statement only allowed in loops and switch statements", ""); - } - break; - case EOpReturn: - if (mCurrentFunctionType->getBasicType() != EbtVoid) - { - error(loc, "non-void function must return a value", "return"); - } - break; - case EOpKill: - if (mShaderType != GL_FRAGMENT_SHADER) - { - error(loc, "discard supported in fragment shaders only", "discard"); - } - break; - default: - UNREACHABLE(); - break; - } - return addBranch(op, nullptr, loc); -} - -TIntermBranch *TParseContext::addBranch(TOperator op, - TIntermTyped *expression, - const TSourceLoc &loc) -{ - if (expression != nullptr) - { - ASSERT(op == EOpReturn); - mFunctionReturnsValue = true; - if (mCurrentFunctionType->getBasicType() == EbtVoid) - { - error(loc, "void function cannot return a value", "return"); - } - else if (*mCurrentFunctionType != expression->getType()) - { - error(loc, "function return is not matching type:", "return"); - } - } - TIntermBranch *node = new TIntermBranch(op, expression); - node->setLine(loc); - return node; -} - -void TParseContext::checkTextureGather(TIntermAggregate *functionCall) -{ - ASSERT(functionCall->getOp() == EOpCallBuiltInFunction); - const TString &name = functionCall->getFunctionSymbolInfo()->getName(); - bool isTextureGather = (name == "textureGather"); - bool isTextureGatherOffset = (name == "textureGatherOffset"); - if (isTextureGather || isTextureGatherOffset) - { - TIntermNode *componentNode = nullptr; - TIntermSequence *arguments = functionCall->getSequence(); - ASSERT(arguments->size() >= 2u && arguments->size() <= 4u); - const TIntermTyped *sampler = arguments->front()->getAsTyped(); - ASSERT(sampler != nullptr); - switch (sampler->getBasicType()) - { - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - if ((isTextureGather && arguments->size() == 3u) || - (isTextureGatherOffset && arguments->size() == 4u)) - { - componentNode = arguments->back(); - } - break; - case EbtSamplerCube: - case EbtISamplerCube: - case EbtUSamplerCube: - ASSERT(!isTextureGatherOffset); - if (arguments->size() == 3u) - { - componentNode = arguments->back(); - } - break; - case EbtSampler2DShadow: - case EbtSampler2DArrayShadow: - case EbtSamplerCubeShadow: - break; - default: - UNREACHABLE(); - break; - } - if (componentNode) - { - const TIntermConstantUnion *componentConstantUnion = - componentNode->getAsConstantUnion(); - if (componentNode->getAsTyped()->getQualifier() != EvqConst || !componentConstantUnion) - { - error(functionCall->getLine(), "Texture component must be a constant expression", - name.c_str()); - } - else - { - int component = componentConstantUnion->getIConst(0); - if (component < 0 || component > 3) - { - error(functionCall->getLine(), "Component must be in the range [0;3]", - name.c_str()); - } - } - } - } -} - -void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall) -{ - ASSERT(functionCall->getOp() == EOpCallBuiltInFunction); - const TString &name = functionCall->getFunctionSymbolInfo()->getName(); - TIntermNode *offset = nullptr; - TIntermSequence *arguments = functionCall->getSequence(); - bool useTextureGatherOffsetConstraints = false; - if (name == "texelFetchOffset" || name == "textureLodOffset" || - name == "textureProjLodOffset" || name == "textureGradOffset" || - name == "textureProjGradOffset") - { - offset = arguments->back(); - } - else if (name == "textureOffset" || name == "textureProjOffset") - { - // A bias parameter might follow the offset parameter. - ASSERT(arguments->size() >= 3); - offset = (*arguments)[2]; - } - else if (name == "textureGatherOffset") - { - ASSERT(arguments->size() >= 3u); - const TIntermTyped *sampler = arguments->front()->getAsTyped(); - ASSERT(sampler != nullptr); - switch (sampler->getBasicType()) - { - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - offset = (*arguments)[2]; - break; - case EbtSampler2DShadow: - case EbtSampler2DArrayShadow: - offset = (*arguments)[3]; - break; - default: - UNREACHABLE(); - break; - } - useTextureGatherOffsetConstraints = true; - } - if (offset != nullptr) - { - TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion(); - if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion) - { - error(functionCall->getLine(), "Texture offset must be a constant expression", - name.c_str()); - } - else - { - ASSERT(offsetConstantUnion->getBasicType() == EbtInt); - size_t size = offsetConstantUnion->getType().getObjectSize(); - const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer(); - int minOffsetValue = useTextureGatherOffsetConstraints ? mMinProgramTextureGatherOffset - : mMinProgramTexelOffset; - int maxOffsetValue = useTextureGatherOffsetConstraints ? mMaxProgramTextureGatherOffset - : mMaxProgramTexelOffset; - for (size_t i = 0u; i < size; ++i) - { - int offsetValue = values[i].getIConst(); - if (offsetValue > maxOffsetValue || offsetValue < minOffsetValue) - { - std::stringstream tokenStream; - tokenStream << offsetValue; - std::string token = tokenStream.str(); - error(offset->getLine(), "Texture offset value out of valid range", - token.c_str()); - } - } - } - } -} - -void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall) -{ - const TString &name = functionCall->getFunctionSymbolInfo()->getName(); - if (IsAtomicBuiltin(name)) - { - TIntermSequence *arguments = functionCall->getSequence(); - TIntermTyped *memNode = (*arguments)[0]->getAsTyped(); - - if (IsBufferOrSharedVariable(memNode)) - { - return; - } - - while (memNode->getAsBinaryNode()) - { - memNode = memNode->getAsBinaryNode()->getLeft(); - if (IsBufferOrSharedVariable(memNode)) - { - return; - } - } - - error(memNode->getLine(), - "The value passed to the mem argument of an atomic memory function does not " - "correspond to a buffer or shared variable.", - functionCall->getFunctionSymbolInfo()->getName().c_str()); - } -} - -// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers -void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall) -{ - ASSERT(functionCall->getOp() == EOpCallBuiltInFunction); - const TString &name = functionCall->getFunctionSymbolInfo()->getName(); - - if (name.compare(0, 5, "image") == 0) - { - TIntermSequence *arguments = functionCall->getSequence(); - TIntermTyped *imageNode = (*arguments)[0]->getAsTyped(); - - const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier(); - - if (name.compare(5, 5, "Store") == 0) - { - if (memoryQualifier.readonly) - { - error(imageNode->getLine(), - "'imageStore' cannot be used with images qualified as 'readonly'", - GetImageArgumentToken(imageNode)); - } - } - else if (name.compare(5, 4, "Load") == 0) - { - if (memoryQualifier.writeonly) - { - error(imageNode->getLine(), - "'imageLoad' cannot be used with images qualified as 'writeonly'", - GetImageArgumentToken(imageNode)); - } - } - } -} - -// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters -void TParseContext::checkImageMemoryAccessForUserDefinedFunctions( - const TFunction *functionDefinition, - const TIntermAggregate *functionCall) -{ - ASSERT(functionCall->getOp() == EOpCallFunctionInAST); - - const TIntermSequence &arguments = *functionCall->getSequence(); - - ASSERT(functionDefinition->getParamCount() == arguments.size()); - - for (size_t i = 0; i < arguments.size(); ++i) - { - TIntermTyped *typedArgument = arguments[i]->getAsTyped(); - const TType &functionArgumentType = typedArgument->getType(); - const TType &functionParameterType = *functionDefinition->getParam(i).type; - ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType()); - - if (IsImage(functionArgumentType.getBasicType())) - { - const TMemoryQualifier &functionArgumentMemoryQualifier = - functionArgumentType.getMemoryQualifier(); - const TMemoryQualifier &functionParameterMemoryQualifier = - functionParameterType.getMemoryQualifier(); - if (functionArgumentMemoryQualifier.readonly && - !functionParameterMemoryQualifier.readonly) - { - error(functionCall->getLine(), - "Function call discards the 'readonly' qualifier from image", - GetImageArgumentToken(typedArgument)); - } - - if (functionArgumentMemoryQualifier.writeonly && - !functionParameterMemoryQualifier.writeonly) - { - error(functionCall->getLine(), - "Function call discards the 'writeonly' qualifier from image", - GetImageArgumentToken(typedArgument)); - } - - if (functionArgumentMemoryQualifier.coherent && - !functionParameterMemoryQualifier.coherent) - { - error(functionCall->getLine(), - "Function call discards the 'coherent' qualifier from image", - GetImageArgumentToken(typedArgument)); - } - - if (functionArgumentMemoryQualifier.volatileQualifier && - !functionParameterMemoryQualifier.volatileQualifier) - { - error(functionCall->getLine(), - "Function call discards the 'volatile' qualifier from image", - GetImageArgumentToken(typedArgument)); - } - } - } -} - -TIntermSequence *TParseContext::createEmptyArgumentsList() -{ - return new TIntermSequence(); -} - -TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, - TIntermSequence *arguments, - TIntermNode *thisNode, - const TSourceLoc &loc) -{ - if (thisNode != nullptr) - { - return addMethod(fnCall, arguments, thisNode, loc); - } - - TOperator op = fnCall->getBuiltInOp(); - if (op == EOpConstruct) - { - return addConstructor(arguments, fnCall->getReturnType(), loc); - } - else - { - ASSERT(op == EOpNull); - return addNonConstructorFunctionCall(fnCall, arguments, loc); - } -} - -TIntermTyped *TParseContext::addMethod(TFunction *fnCall, - TIntermSequence *arguments, - TIntermNode *thisNode, - const TSourceLoc &loc) -{ - TIntermTyped *typedThis = thisNode->getAsTyped(); - // It's possible for the name pointer in the TFunction to be null in case it gets parsed as - // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS - // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead. - // So accessing fnCall->getName() below is safe. - if (fnCall->getName() != "length") - { - error(loc, "invalid method", fnCall->getName().c_str()); - } - else if (!arguments->empty()) - { - error(loc, "method takes no parameters", "length"); - } - else if (typedThis == nullptr || !typedThis->isArray()) - { - error(loc, "length can only be called on arrays", "length"); - } - else if (typedThis->getQualifier() == EvqPerVertexIn && - mGeometryShaderInputPrimitiveType == EptUndefined) - { - ASSERT(mShaderType == GL_GEOMETRY_SHADER_OES); - error(loc, "missing input primitive declaration before calling length on gl_in", "length"); - } - else - { - TIntermUnary *node = new TIntermUnary(EOpArrayLength, typedThis); - node->setLine(loc); - return node->fold(mDiagnostics); - } - return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst)); -} - -TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall, - TIntermSequence *arguments, - const TSourceLoc &loc) -{ - // First find by unmangled name to check whether the function name has been - // hidden by a variable name or struct typename. - // If a function is found, check for one with a matching argument list. - bool builtIn; - const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn); - if (symbol != nullptr && !symbol->isFunction()) - { - error(loc, "function name expected", fnCall->getName().c_str()); - } - else - { - symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments), - mShaderVersion, &builtIn); - if (symbol == nullptr) - { - error(loc, "no matching overloaded function found", fnCall->getName().c_str()); - } - else - { - const TFunction *fnCandidate = static_cast<const TFunction *>(symbol); - // - // A declared function. - // - if (builtIn && fnCandidate->getExtension() != TExtension::UNDEFINED) - { - checkCanUseExtension(loc, fnCandidate->getExtension()); - } - TOperator op = fnCandidate->getBuiltInOp(); - if (builtIn && op != EOpNull) - { - // A function call mapped to a built-in operation. - if (fnCandidate->getParamCount() == 1) - { - // Treat it like a built-in unary operator. - TIntermNode *unaryParamNode = arguments->front(); - TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc); - ASSERT(callNode != nullptr); - return callNode; - } - else - { - TIntermAggregate *callNode = - TIntermAggregate::Create(fnCandidate->getReturnType(), op, arguments); - callNode->setLine(loc); - - // Some built-in functions have out parameters too. - functionCallRValueLValueErrorCheck(fnCandidate, callNode); - - if (TIntermAggregate::CanFoldAggregateBuiltInOp(callNode->getOp())) - { - // See if we can constant fold a built-in. Note that this may be possible - // even if it is not const-qualified. - return callNode->fold(mDiagnostics); - } - else - { - return callNode; - } - } - } - else - { - // This is a real function call - TIntermAggregate *callNode = nullptr; - - // If builtIn == false, the function is user defined - could be an overloaded - // built-in as well. - // if builtIn == true, it's a builtIn function with no op associated with it. - // This needs to happen after the function info including name is set. - if (builtIn) - { - callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, arguments); - checkTextureOffsetConst(callNode); - checkTextureGather(callNode); - checkImageMemoryAccessForBuiltinFunctions(callNode); - checkAtomicMemoryBuiltinFunctions(callNode); - } - else - { - callNode = TIntermAggregate::CreateFunctionCall(*fnCandidate, arguments); - checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode); - } - - functionCallRValueLValueErrorCheck(fnCandidate, callNode); - - callNode->setLine(loc); - - return callNode; - } - } - } - - // Error message was already written. Put on a dummy node for error recovery. - return CreateZeroNode(TType(EbtFloat, EbpMedium, EvqConst)); -} - -TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression, - const TSourceLoc &loc) -{ - if (!checkIsScalarBool(loc, cond)) - { - return falseExpression; - } - - if (trueExpression->getType() != falseExpression->getType()) - { - std::stringstream reasonStream; - reasonStream << "mismatching ternary operator operand types '" - << trueExpression->getCompleteString() << " and '" - << falseExpression->getCompleteString() << "'"; - std::string reason = reasonStream.str(); - error(loc, reason.c_str(), "?:"); - return falseExpression; - } - if (IsOpaqueType(trueExpression->getBasicType())) - { - // ESSL 1.00 section 4.1.7 - // ESSL 3.00.6 section 4.1.7 - // Opaque/sampler types are not allowed in most types of expressions, including ternary. - // Note that structs containing opaque types don't need to be checked as structs are - // forbidden below. - error(loc, "ternary operator is not allowed for opaque types", "?:"); - return falseExpression; - } - - if (cond->getMemoryQualifier().writeonly || trueExpression->getMemoryQualifier().writeonly || - falseExpression->getMemoryQualifier().writeonly) - { - error(loc, "ternary operator is not allowed for variables with writeonly", "?:"); - return falseExpression; - } - - // ESSL 1.00.17 sections 5.2 and 5.7: - // Ternary operator is not among the operators allowed for structures/arrays. - // ESSL 3.00.6 section 5.7: - // Ternary operator support is optional for arrays. No certainty that it works across all - // devices with struct either, so we err on the side of caution here. TODO (oetuaho@nvidia.com): - // Would be nice to make the spec and implementation agree completely here. - if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct) - { - error(loc, "ternary operator is not allowed for structures or arrays", "?:"); - return falseExpression; - } - if (trueExpression->getBasicType() == EbtInterfaceBlock) - { - error(loc, "ternary operator is not allowed for interface blocks", "?:"); - return falseExpression; - } - - // WebGL2 section 5.26, the following results in an error: - // "Ternary operator applied to void, arrays, or structs containing arrays" - if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid) - { - error(loc, "ternary operator is not allowed for void", "?:"); - return falseExpression; - } - - // Note that the node resulting from here can be a constant union without being qualified as - // constant. - TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression); - node->setLine(loc); - - return node->fold(); -} - -// -// Parse an array of strings using yyparse. -// -// Returns 0 for success. -// -int PaParseStrings(size_t count, - const char *const string[], - const int length[], - TParseContext *context) -{ - if ((count == 0) || (string == nullptr)) - return 1; - - if (glslang_initialize(context)) - return 1; - - int error = glslang_scan(count, string, length, context); - if (!error) - error = glslang_parse(context); - - glslang_finalize(context); - - return (error == 0) && (context->numErrors() == 0) ? 0 : 1; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h deleted file mode 100644 index 8bfdbd5e3f..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.h +++ /dev/null @@ -1,657 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -#ifndef COMPILER_TRANSLATOR_PARSECONTEXT_H_ -#define COMPILER_TRANSLATOR_PARSECONTEXT_H_ - -#include "compiler/translator/Compiler.h" -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/DirectiveHandler.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/QualifierTypes.h" -#include "compiler/preprocessor/Preprocessor.h" - -namespace sh -{ - -struct TMatrixFields -{ - bool wholeRow; - bool wholeCol; - int row; - int col; -}; - -// -// The following are extra variables needed during parsing, grouped together so -// they can be passed to the parser without needing a global. -// -class TParseContext : angle::NonCopyable -{ - public: - TParseContext(TSymbolTable &symt, - TExtensionBehavior &ext, - sh::GLenum type, - ShShaderSpec spec, - ShCompileOptions options, - bool checksPrecErrors, - TDiagnostics *diagnostics, - const ShBuiltInResources &resources); - ~TParseContext(); - - const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; } - pp::Preprocessor &getPreprocessor() { return mPreprocessor; } - void *getScanner() const { return mScanner; } - void setScanner(void *scanner) { mScanner = scanner; } - int getShaderVersion() const { return mShaderVersion; } - sh::GLenum getShaderType() const { return mShaderType; } - ShShaderSpec getShaderSpec() const { return mShaderSpec; } - int numErrors() const { return mDiagnostics->numErrors(); } - void error(const TSourceLoc &loc, const char *reason, const char *token); - void warning(const TSourceLoc &loc, const char *reason, const char *token); - - // If isError is false, a warning will be reported instead. - void outOfRangeError(bool isError, - const TSourceLoc &loc, - const char *reason, - const char *token); - - TIntermBlock *getTreeRoot() const { return mTreeRoot; } - void setTreeRoot(TIntermBlock *treeRoot) { mTreeRoot = treeRoot; } - - bool getFragmentPrecisionHigh() const - { - return mFragmentPrecisionHighOnESSL1 || mShaderVersion >= 300; - } - void setFragmentPrecisionHighOnESSL1(bool fragmentPrecisionHigh) - { - mFragmentPrecisionHighOnESSL1 = fragmentPrecisionHigh; - } - - void setLoopNestingLevel(int loopNestintLevel) { mLoopNestingLevel = loopNestintLevel; } - - void incrLoopNestingLevel() { ++mLoopNestingLevel; } - void decrLoopNestingLevel() { --mLoopNestingLevel; } - - void incrSwitchNestingLevel() { ++mSwitchNestingLevel; } - void decrSwitchNestingLevel() { --mSwitchNestingLevel; } - - bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; } - sh::WorkGroupSize getComputeShaderLocalSize() const; - - int getNumViews() const { return mNumViews; } - - void enterFunctionDeclaration() { mDeclaringFunction = true; } - - void exitFunctionDeclaration() { mDeclaringFunction = false; } - - bool declaringFunction() const { return mDeclaringFunction; } - - TIntermConstantUnion *addScalarLiteral(const TConstantUnion *constantUnion, - const TSourceLoc &line); - - // This method is guaranteed to succeed, even if no variable with 'name' exists. - const TVariable *getNamedVariable(const TSourceLoc &location, - const TString *name, - const TSymbol *symbol); - TIntermTyped *parseVariableIdentifier(const TSourceLoc &location, - const TString *name, - const TSymbol *symbol); - - // Look at a '.' field selector string and change it into offsets for a vector. - bool parseVectorFields(const TSourceLoc &line, - const TString &compString, - int vecSize, - TVector<int> *fieldOffsets); - - void assignError(const TSourceLoc &line, const char *op, TString left, TString right); - void unaryOpError(const TSourceLoc &line, const char *op, TString operand); - void binaryOpError(const TSourceLoc &line, const char *op, TString left, TString right); - - // Check functions - the ones that return bool return false if an error was generated. - - bool checkIsNotReserved(const TSourceLoc &line, const TString &identifier); - void checkPrecisionSpecified(const TSourceLoc &line, TPrecision precision, TBasicType type); - bool checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node); - void checkIsConst(TIntermTyped *node); - void checkIsScalarInteger(TIntermTyped *node, const char *token); - bool checkIsAtGlobalLevel(const TSourceLoc &line, const char *token); - bool checkConstructorArguments(const TSourceLoc &line, - const TIntermSequence *arguments, - const TType &type); - - // Returns a sanitized array size to use (the size is at least 1). - unsigned int checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr); - bool checkIsValidQualifierForArray(const TSourceLoc &line, const TPublicType &elementQualifier); - bool checkArrayElementIsNotArray(const TSourceLoc &line, const TPublicType &elementType); - bool checkIsNonVoid(const TSourceLoc &line, const TString &identifier, const TBasicType &type); - bool checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type); - void checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType); - bool checkIsNotOpaqueType(const TSourceLoc &line, - const TTypeSpecifierNonArray &pType, - const char *reason); - void checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line, const TPublicType &pType); - void checkLocationIsNotSpecified(const TSourceLoc &location, - const TLayoutQualifier &layoutQualifier); - void checkStd430IsForShaderStorageBlock(const TSourceLoc &location, - const TLayoutBlockStorage &blockStorage, - const TQualifier &qualifier); - void checkIsParameterQualifierValid(const TSourceLoc &line, - const TTypeQualifierBuilder &typeQualifierBuilder, - TType *type); - - // Check if at least one of the specified extensions can be used, and generate error/warning as - // appropriate according to the spec. - // This function is only needed for a few different small constant sizes of extension array, and - // we want to avoid unnecessary dynamic allocations. That's why checkCanUseOneOfExtensions is a - // template function rather than one taking a vector. - template <size_t size> - bool checkCanUseOneOfExtensions(const TSourceLoc &line, - const std::array<TExtension, size> &extensions); - bool checkCanUseExtension(const TSourceLoc &line, TExtension extension); - - // Done for all declarations, whether empty or not. - void declarationQualifierErrorCheck(const sh::TQualifier qualifier, - const sh::TLayoutQualifier &layoutQualifier, - const TSourceLoc &location); - // Done for the first non-empty declarator in a declaration. - void nonEmptyDeclarationErrorCheck(const TPublicType &publicType, - const TSourceLoc &identifierLocation); - // Done only for empty declarations. - void emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location); - - void checkLayoutQualifierSupported(const TSourceLoc &location, - const TString &layoutQualifierName, - int versionRequired); - bool checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location, - const TLayoutQualifier &layoutQualifier); - void functionCallRValueLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *fnCall); - void checkInvariantVariableQualifier(bool invariant, - const TQualifier qualifier, - const TSourceLoc &invariantLocation); - void checkInputOutputTypeIsValidES3(const TQualifier qualifier, - const TPublicType &type, - const TSourceLoc &qualifierLocation); - void checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier); - const TPragma &pragma() const { return mDirectiveHandler.pragma(); } - const TExtensionBehavior &extensionBehavior() const - { - return mDirectiveHandler.extensionBehavior(); - } - - bool isExtensionEnabled(TExtension extension) const; - void handleExtensionDirective(const TSourceLoc &loc, const char *extName, const char *behavior); - void handlePragmaDirective(const TSourceLoc &loc, - const char *name, - const char *value, - bool stdgl); - - // Returns true on success. *initNode may still be nullptr on success in case the initialization - // is not needed in the AST. - bool executeInitializer(const TSourceLoc &line, - const TString &identifier, - TType type, - TIntermTyped *initializer, - TIntermBinary **initNode); - TIntermNode *addConditionInitializer(const TPublicType &pType, - const TString &identifier, - TIntermTyped *initializer, - const TSourceLoc &loc); - TIntermNode *addLoop(TLoopType type, - TIntermNode *init, - TIntermNode *cond, - TIntermTyped *expr, - TIntermNode *body, - const TSourceLoc &loc); - - // For "if" test nodes. There are three children: a condition, a true path, and a false path. - // The two paths are in TIntermNodePair code. - TIntermNode *addIfElse(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &loc); - - void addFullySpecifiedType(TPublicType *typeSpecifier); - TPublicType addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder, - const TPublicType &typeSpecifier); - - TIntermDeclaration *parseSingleDeclaration(TPublicType &publicType, - const TSourceLoc &identifierOrTypeLocation, - const TString &identifier); - TIntermDeclaration *parseSingleArrayDeclaration(TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - const TVector<unsigned int> &arraySizes); - TIntermDeclaration *parseSingleInitDeclaration(const TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &initLocation, - TIntermTyped *initializer); - - // Parse a declaration like "type a[n] = initializer" - // Note that this does not apply to declarations like "type[n] a = initializer" - TIntermDeclaration *parseSingleArrayInitDeclaration(TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - const TVector<unsigned int> &arraySizes, - const TSourceLoc &initLocation, - TIntermTyped *initializer); - - TIntermInvariantDeclaration *parseInvariantDeclaration( - const TTypeQualifierBuilder &typeQualifierBuilder, - const TSourceLoc &identifierLoc, - const TString *identifier, - const TSymbol *symbol); - - void parseDeclarator(TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - TIntermDeclaration *declarationOut); - void parseArrayDeclarator(TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &arrayLocation, - const TVector<unsigned int> &arraySizes, - TIntermDeclaration *declarationOut); - void parseInitDeclarator(const TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &initLocation, - TIntermTyped *initializer, - TIntermDeclaration *declarationOut); - - // Parse a declarator like "a[n] = initializer" - void parseArrayInitDeclarator(const TPublicType &elementType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - const TVector<unsigned int> &arraySizes, - const TSourceLoc &initLocation, - TIntermTyped *initializer, - TIntermDeclaration *declarationOut); - - TIntermNode *addEmptyStatement(const TSourceLoc &location); - - void parseDefaultPrecisionQualifier(const TPrecision precision, - const TPublicType &type, - const TSourceLoc &loc); - void parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder); - - TIntermFunctionPrototype *addFunctionPrototypeDeclaration(const TFunction &parsedFunction, - const TSourceLoc &location); - TIntermFunctionDefinition *addFunctionDefinition(TIntermFunctionPrototype *functionPrototype, - TIntermBlock *functionBody, - const TSourceLoc &location); - void parseFunctionDefinitionHeader(const TSourceLoc &location, - TFunction **function, - TIntermFunctionPrototype **prototypeOut); - TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function); - TFunction *parseFunctionHeader(const TPublicType &type, - const TString *name, - const TSourceLoc &location); - TFunction *addNonConstructorFunc(const TString *name, const TSourceLoc &loc); - TFunction *addConstructorFunc(const TPublicType &publicType); - TParameter parseParameterDeclarator(const TPublicType &publicType, - const TString *name, - const TSourceLoc &nameLoc); - - TParameter parseParameterArrayDeclarator(const TString *name, - const TSourceLoc &nameLoc, - const TVector<unsigned int> &arraySizes, - const TSourceLoc &arrayLoc, - TPublicType *elementType); - - TIntermTyped *addIndexExpression(TIntermTyped *baseExpression, - const TSourceLoc &location, - TIntermTyped *indexExpression); - TIntermTyped *addFieldSelectionExpression(TIntermTyped *baseExpression, - const TSourceLoc &dotLocation, - const TString &fieldString, - const TSourceLoc &fieldLocation); - - // Parse declarator for a single field - TField *parseStructDeclarator(TString *identifier, const TSourceLoc &loc); - TField *parseStructArrayDeclarator(TString *identifier, - const TSourceLoc &loc, - const TVector<unsigned int> &arraySizes, - const TSourceLoc &arraySizeLoc); - - void checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin, - const TFieldList::const_iterator end, - const TString &name, - const TSourceLoc &location); - TFieldList *addStructFieldList(TFieldList *fields, const TSourceLoc &location); - TFieldList *combineStructFieldLists(TFieldList *processedFields, - const TFieldList *newlyAddedFields, - const TSourceLoc &location); - TFieldList *addStructDeclaratorListWithQualifiers( - const TTypeQualifierBuilder &typeQualifierBuilder, - TPublicType *typeSpecifier, - TFieldList *fieldList); - TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList); - TTypeSpecifierNonArray addStructure(const TSourceLoc &structLine, - const TSourceLoc &nameLine, - const TString *structName, - TFieldList *fieldList); - - TIntermDeclaration *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder, - const TSourceLoc &nameLine, - const TString &blockName, - TFieldList *fieldList, - const TString *instanceName, - const TSourceLoc &instanceLine, - TIntermTyped *arrayIndex, - const TSourceLoc &arrayIndexLine); - - void parseLocalSize(const TString &qualifierType, - const TSourceLoc &qualifierTypeLine, - int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - size_t index, - sh::WorkGroupSize *localSize); - void parseNumViews(int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - int *numViews); - void parseInvocations(int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - int *numInvocations); - void parseMaxVertices(int intValue, - const TSourceLoc &intValueLine, - const std::string &intValueString, - int *numMaxVertices); - TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, - const TSourceLoc &qualifierTypeLine); - TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, - const TSourceLoc &qualifierTypeLine, - int intValue, - const TSourceLoc &intValueLine); - TTypeQualifierBuilder *createTypeQualifierBuilder(const TSourceLoc &loc); - TStorageQualifierWrapper *parseGlobalStorageQualifier(TQualifier qualifier, - const TSourceLoc &loc); - TStorageQualifierWrapper *parseVaryingQualifier(const TSourceLoc &loc); - TStorageQualifierWrapper *parseInQualifier(const TSourceLoc &loc); - TStorageQualifierWrapper *parseOutQualifier(const TSourceLoc &loc); - TStorageQualifierWrapper *parseInOutQualifier(const TSourceLoc &loc); - TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, - TLayoutQualifier rightQualifier, - const TSourceLoc &rightQualifierLocation); - - // Performs an error check for embedded struct declarations. - void enterStructDeclaration(const TSourceLoc &line, const TString &identifier); - void exitStructDeclaration(); - - void checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field); - - TIntermSwitch *addSwitch(TIntermTyped *init, - TIntermBlock *statementList, - const TSourceLoc &loc); - TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc); - TIntermCase *addDefault(const TSourceLoc &loc); - - TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc); - TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc); - TIntermTyped *addBinaryMath(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc); - TIntermTyped *addBinaryMathBooleanResult(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc); - TIntermTyped *addAssign(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc); - - TIntermTyped *addComma(TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); - - TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc); - TIntermBranch *addBranch(TOperator op, TIntermTyped *expression, const TSourceLoc &loc); - - void checkTextureGather(TIntermAggregate *functionCall); - void checkTextureOffsetConst(TIntermAggregate *functionCall); - void checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall); - void checkImageMemoryAccessForUserDefinedFunctions(const TFunction *functionDefinition, - const TIntermAggregate *functionCall); - void checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall); - TIntermSequence *createEmptyArgumentsList(); - - // fnCall is only storing the built-in op, and function name or constructor type. arguments - // has the arguments. - TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, - TIntermSequence *arguments, - TIntermNode *thisNode, - const TSourceLoc &loc); - - TIntermTyped *addTernarySelection(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression, - const TSourceLoc &line); - - int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; } - int getGeometryShaderInvocations() const - { - return (mGeometryShaderInvocations > 0) ? mGeometryShaderInvocations : 1; - } - TLayoutPrimitiveType getGeometryShaderInputPrimitiveType() const - { - return mGeometryShaderInputPrimitiveType; - } - TLayoutPrimitiveType getGeometryShaderOutputPrimitiveType() const - { - return mGeometryShaderOutputPrimitiveType; - } - - // TODO(jmadill): make this private - TSymbolTable &symbolTable; // symbol table that goes with the language currently being parsed - - private: - class AtomicCounterBindingState; - constexpr static size_t kAtomicCounterSize = 4; - // UNIFORM_ARRAY_STRIDE for atomic counter arrays is an implementation-dependent value which - // can be queried after a program is linked according to ES 3.10 section 7.7.1. This is - // controversial with the offset inheritance as described in ESSL 3.10 section 4.4.6. Currently - // we treat it as always 4 in favour of the original interpretation in - // "ARB_shader_atomic_counters". - // TODO(jie.a.chen@intel.com): Double check this once the spec vagueness is resolved. - // Note that there may be tests in AtomicCounter_test that will need to be updated as well. - constexpr static size_t kAtomicCounterArrayStride = 4; - - // Returns a clamped index. If it prints out an error message, the token is "[]". - int checkIndexLessThan(bool outOfRangeIndexIsError, - const TSourceLoc &location, - int index, - int arraySize, - const char *reason); - - bool declareVariable(const TSourceLoc &line, - const TString &identifier, - const TType &type, - TVariable **variable); - - void checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line, - const TString &identifier, - TType *type); - - TParameter parseParameterDeclarator(TType *type, - const TString *name, - const TSourceLoc &nameLoc); - - bool checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation, - const TPublicType &elementType); - // Done for all atomic counter declarations, whether empty or not. - void atomicCounterQualifierErrorCheck(const TPublicType &publicType, - const TSourceLoc &location); - - // Assumes that multiplication op has already been set based on the types. - bool isMultiplicationTypeCombinationValid(TOperator op, const TType &left, const TType &right); - - void checkOutParameterIsNotOpaqueType(const TSourceLoc &line, - TQualifier qualifier, - const TType &type); - - void checkInternalFormatIsNotSpecified(const TSourceLoc &location, - TLayoutImageInternalFormat internalFormat); - void checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier, - const TSourceLoc &location); - void checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend, - const TSourceLoc &loc, - TType *type); - void checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type); - void checkBindingIsNotSpecified(const TSourceLoc &location, int binding); - void checkOffsetIsNotSpecified(const TSourceLoc &location, int offset); - void checkImageBindingIsValid(const TSourceLoc &location, - int binding, - int arrayTotalElementCount); - void checkSamplerBindingIsValid(const TSourceLoc &location, - int binding, - int arrayTotalElementCount); - void checkBlockBindingIsValid(const TSourceLoc &location, - const TQualifier &qualifier, - int binding, - int arraySize); - void checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding); - - void checkUniformLocationInRange(const TSourceLoc &location, - int objectLocationCount, - const TLayoutQualifier &layoutQualifier); - - void checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv); - - bool checkUnsizedArrayConstructorArgumentDimensionality(TIntermSequence *arguments, - TType type, - const TSourceLoc &line); - - // Will set the size of the outermost array according to geometry shader input layout. - void checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location, - const char *token, - TType *type); - - // Will size any unsized array type so unsized arrays won't need to be taken into account - // further along the line in parsing. - void checkIsNotUnsizedArray(const TSourceLoc &line, - const char *errorMessage, - const char *token, - TType *arrayType); - - TIntermTyped *addBinaryMathInternal(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc); - TIntermBinary *createAssign(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc); - TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc); - - TIntermTyped *addMethod(TFunction *fnCall, - TIntermSequence *arguments, - TIntermNode *thisNode, - const TSourceLoc &loc); - TIntermTyped *addConstructor(TIntermSequence *arguments, - TType type, - const TSourceLoc &line); - TIntermTyped *addNonConstructorFunctionCall(TFunction *fnCall, - TIntermSequence *arguments, - const TSourceLoc &loc); - - // Return true if the checks pass - bool binaryOpCommonCheck(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc); - - TIntermFunctionPrototype *createPrototypeNodeFromFunction(const TFunction &function, - const TSourceLoc &location, - bool insertParametersToSymbolTable); - - void setAtomicCounterBindingDefaultOffset(const TPublicType &declaration, - const TSourceLoc &location); - - bool checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier); - bool parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier); - bool parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier); - void setGeometryShaderInputArraySize(unsigned int inputArraySize, const TSourceLoc &line); - - // Set to true when the last/current declarator list was started with an empty declaration. The - // non-empty declaration error check will need to be performed if the empty declaration is - // followed by a declarator. - bool mDeferredNonEmptyDeclarationErrorCheck; - - sh::GLenum mShaderType; // vertex or fragment language (future: pack or unpack) - ShShaderSpec mShaderSpec; // The language specification compiler conforms to - GLES2 or WebGL. - ShCompileOptions mCompileOptions; // Options passed to TCompiler - int mShaderVersion; - TIntermBlock *mTreeRoot; // root of parse tree being created - int mLoopNestingLevel; // 0 if outside all loops - int mStructNestingLevel; // incremented while parsing a struct declaration - int mSwitchNestingLevel; // 0 if outside all switch statements - const TType - *mCurrentFunctionType; // the return type of the function that's currently being parsed - bool mFunctionReturnsValue; // true if a non-void function has a return - bool mChecksPrecisionErrors; // true if an error will be generated when a variable is declared - // without precision, explicit or implicit. - bool mFragmentPrecisionHighOnESSL1; // true if highp precision is supported when compiling - // ESSL1. - TLayoutMatrixPacking mDefaultUniformMatrixPacking; - TLayoutBlockStorage mDefaultUniformBlockStorage; - TLayoutMatrixPacking mDefaultBufferMatrixPacking; - TLayoutBlockStorage mDefaultBufferBlockStorage; - TString mHashErrMsg; - TDiagnostics *mDiagnostics; - TDirectiveHandler mDirectiveHandler; - pp::Preprocessor mPreprocessor; - void *mScanner; - bool mUsesFragData; // track if we are using both gl_FragData and gl_FragColor - bool mUsesFragColor; - bool mUsesSecondaryOutputs; // Track if we are using either gl_SecondaryFragData or - // gl_Secondary FragColor or both. - int mMinProgramTexelOffset; - int mMaxProgramTexelOffset; - - int mMinProgramTextureGatherOffset; - int mMaxProgramTextureGatherOffset; - - // keep track of local group size declared in layout. It should be declared only once. - bool mComputeShaderLocalSizeDeclared; - sh::WorkGroupSize mComputeShaderLocalSize; - // keep track of number of views declared in layout. - int mNumViews; - int mMaxNumViews; - int mMaxImageUnits; - int mMaxCombinedTextureImageUnits; - int mMaxUniformLocations; - int mMaxUniformBufferBindings; - int mMaxAtomicCounterBindings; - int mMaxShaderStorageBufferBindings; - - // keeps track whether we are declaring / defining a function - bool mDeclaringFunction; - - // Track the state of each atomic counter binding. - std::map<int, AtomicCounterBindingState> mAtomicCounterBindingStates; - - // Track the geometry shader global parameters declared in layout. - TLayoutPrimitiveType mGeometryShaderInputPrimitiveType; - TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType; - int mGeometryShaderInvocations; - int mGeometryShaderMaxVertices; - int mMaxGeometryShaderInvocations; - int mMaxGeometryShaderMaxVertices; - - // Track if all input array sizes are same and matches the latter input primitive declaration. - unsigned int mGeometryShaderInputArraySize; -}; - -int PaParseStrings(size_t count, - const char *const string[], - const int length[], - TParseContext *context); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_PARSECONTEXT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp deleted file mode 100644 index 0f1cd8b5c9..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp +++ /dev/null @@ -1,360 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/PoolAlloc.h" - -#include <stdint.h> -#include <stdio.h> -#include <assert.h> - -#include "common/angleutils.h" -#include "common/debug.h" -#include "common/platform.h" -#include "common/tls.h" -#include "compiler/translator/InitializeGlobals.h" - -TLSIndex PoolIndex = TLS_INVALID_INDEX; - -bool InitializePoolIndex() -{ - assert(PoolIndex == TLS_INVALID_INDEX); - - PoolIndex = CreateTLSIndex(); - return PoolIndex != TLS_INVALID_INDEX; -} - -void FreePoolIndex() -{ - assert(PoolIndex != TLS_INVALID_INDEX); - - DestroyTLSIndex(PoolIndex); - PoolIndex = TLS_INVALID_INDEX; -} - -TPoolAllocator *GetGlobalPoolAllocator() -{ - assert(PoolIndex != TLS_INVALID_INDEX); - return static_cast<TPoolAllocator *>(GetTLSValue(PoolIndex)); -} - -void SetGlobalPoolAllocator(TPoolAllocator *poolAllocator) -{ - assert(PoolIndex != TLS_INVALID_INDEX); - SetTLSValue(PoolIndex, poolAllocator); -} - -// -// Implement the functionality of the TPoolAllocator class, which -// is documented in PoolAlloc.h. -// -TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) - : alignment(allocationAlignment), -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - pageSize(growthIncrement), - freeList(0), - inUseList(0), - numCalls(0), - totalBytes(0), -#endif - mLocked(false) -{ - // - // Adjust alignment to be at least pointer aligned and - // power of 2. - // - size_t minAlign = sizeof(void *); - alignment &= ~(minAlign - 1); - if (alignment < minAlign) - alignment = minAlign; - size_t a = 1; - while (a < alignment) - a <<= 1; - alignment = a; - alignmentMask = a - 1; - -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - // - // Don't allow page sizes we know are smaller than all common - // OS page sizes. - // - if (pageSize < 4 * 1024) - pageSize = 4 * 1024; - - // - // A large currentPageOffset indicates a new page needs to - // be obtained to allocate memory. - // - currentPageOffset = pageSize; - - // - // Align header skip - // - headerSkip = minAlign; - if (headerSkip < sizeof(tHeader)) - { - headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask; - } -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - mStack.push_back({}); -#endif -} - -TPoolAllocator::~TPoolAllocator() -{ -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - while (inUseList) - { - tHeader *next = inUseList->nextPage; - inUseList->~tHeader(); - delete[] reinterpret_cast<char *>(inUseList); - inUseList = next; - } - - // We should not check the guard blocks - // here, because we did it already when the block was - // placed into the free list. - // - while (freeList) - { - tHeader *next = freeList->nextPage; - delete[] reinterpret_cast<char *>(freeList); - freeList = next; - } -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - for (auto &allocs : mStack) - { - for (auto alloc : allocs) - { - free(alloc); - } - } - mStack.clear(); -#endif -} - -// Support MSVC++ 6.0 -const unsigned char TAllocation::guardBlockBeginVal = 0xfb; -const unsigned char TAllocation::guardBlockEndVal = 0xfe; -const unsigned char TAllocation::userDataFill = 0xcd; - -#ifdef GUARD_BLOCKS -const size_t TAllocation::guardBlockSize = 16; -#else -const size_t TAllocation::guardBlockSize = 0; -#endif - -// -// Check a single guard block for damage -// -void TAllocation::checkGuardBlock(unsigned char *blockMem, - unsigned char val, - const char *locText) const -{ -#ifdef GUARD_BLOCKS - for (size_t x = 0; x < guardBlockSize; x++) - { - if (blockMem[x] != val) - { - char assertMsg[80]; - -// We don't print the assert message. It's here just to be helpful. -#if defined(_MSC_VER) - snprintf(assertMsg, sizeof(assertMsg), - "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n", locText, size, data()); -#else - snprintf(assertMsg, sizeof(assertMsg), - "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n", locText, size, data()); -#endif - assert(0 && "PoolAlloc: Damage in guard block"); - } - } -#endif -} - -void TPoolAllocator::push() -{ -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - tAllocState state = {currentPageOffset, inUseList}; - - mStack.push_back(state); - - // - // Indicate there is no current page to allocate from. - // - currentPageOffset = pageSize; -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - mStack.push_back({}); -#endif -} - -// -// Do a mass-deallocation of all the individual allocations -// that have occurred since the last push(), or since the -// last pop(), or since the object's creation. -// -// The deallocated pages are saved for future allocations. -// -void TPoolAllocator::pop() -{ - if (mStack.size() < 1) - return; - -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - tHeader *page = mStack.back().page; - currentPageOffset = mStack.back().offset; - - while (inUseList != page) - { - // invoke destructor to free allocation list - inUseList->~tHeader(); - - tHeader *nextInUse = inUseList->nextPage; - if (inUseList->pageCount > 1) - delete[] reinterpret_cast<char *>(inUseList); - else - { - inUseList->nextPage = freeList; - freeList = inUseList; - } - inUseList = nextInUse; - } - - mStack.pop_back(); -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - for (auto &alloc : mStack.back()) - { - free(alloc); - } - mStack.pop_back(); -#endif -} - -// -// Do a mass-deallocation of all the individual allocations -// that have occurred. -// -void TPoolAllocator::popAll() -{ - while (mStack.size() > 0) - pop(); -} - -void *TPoolAllocator::allocate(size_t numBytes) -{ - ASSERT(!mLocked); - -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - // - // Just keep some interesting statistics. - // - ++numCalls; - totalBytes += numBytes; - - // If we are using guard blocks, all allocations are bracketed by - // them: [guardblock][allocation][guardblock]. numBytes is how - // much memory the caller asked for. allocationSize is the total - // size including guard blocks. In release build, - // guardBlockSize=0 and this all gets optimized away. - size_t allocationSize = TAllocation::allocationSize(numBytes); - // Detect integer overflow. - if (allocationSize < numBytes) - return 0; - - // - // Do the allocation, most likely case first, for efficiency. - // This step could be moved to be inline sometime. - // - if (allocationSize <= pageSize - currentPageOffset) - { - // - // Safe to allocate from currentPageOffset. - // - unsigned char *memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset; - currentPageOffset += allocationSize; - currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask; - - return initializeAllocation(inUseList, memory, numBytes); - } - - if (allocationSize > pageSize - headerSkip) - { - // - // Do a multi-page allocation. Don't mix these with the others. - // The OS is efficient and allocating and free-ing multiple pages. - // - size_t numBytesToAlloc = allocationSize + headerSkip; - // Detect integer overflow. - if (numBytesToAlloc < allocationSize) - return 0; - - tHeader *memory = reinterpret_cast<tHeader *>(::new char[numBytesToAlloc]); - if (memory == 0) - return 0; - - // Use placement-new to initialize header - new (memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize); - inUseList = memory; - - currentPageOffset = pageSize; // make next allocation come from a new page - - // No guard blocks for multi-page allocations (yet) - return reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(memory) + headerSkip); - } - - // - // Need a simple page to allocate from. - // - tHeader *memory; - if (freeList) - { - memory = freeList; - freeList = freeList->nextPage; - } - else - { - memory = reinterpret_cast<tHeader *>(::new char[pageSize]); - if (memory == 0) - return 0; - } - - // Use placement-new to initialize header - new (memory) tHeader(inUseList, 1); - inUseList = memory; - - unsigned char *ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip; - currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask; - - return initializeAllocation(inUseList, ret, numBytes); -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - void *alloc = malloc(numBytes + alignmentMask); - mStack.back().push_back(alloc); - - intptr_t intAlloc = reinterpret_cast<intptr_t>(alloc); - intAlloc = (intAlloc + alignmentMask) & ~alignmentMask; - return reinterpret_cast<void *>(intAlloc); -#endif -} - -void TPoolAllocator::lock() -{ - ASSERT(!mLocked); - mLocked = true; -} - -void TPoolAllocator::unlock() -{ - ASSERT(mLocked); - mLocked = false; -} - -// -// Check all allocations in a list for damage by calling check on each. -// -void TAllocation::checkAllocList() const -{ - for (const TAllocation *alloc = this; alloc != 0; alloc = alloc->prevAlloc) - alloc->check(); -} diff --git a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h deleted file mode 100644 index ad63bc4cd6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h +++ /dev/null @@ -1,319 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_POOLALLOC_H_ -#define COMPILER_TRANSLATOR_POOLALLOC_H_ - -#ifdef _DEBUG -#define GUARD_BLOCKS // define to enable guard block sanity checking -#endif - -// -// This header defines an allocator that can be used to efficiently -// allocate a large number of small requests for heap memory, with the -// intention that they are not individually deallocated, but rather -// collectively deallocated at one time. -// -// This simultaneously -// -// * Makes each individual allocation much more efficient; the -// typical allocation is trivial. -// * Completely avoids the cost of doing individual deallocation. -// * Saves the trouble of tracking down and plugging a large class of leaks. -// -// Individual classes can use this allocator by supplying their own -// new and delete methods. -// -// STL containers can use this allocator by using the pool_allocator -// class as the allocator (second) template argument. -// - -#include <stddef.h> -#include <string.h> -#include <vector> - -// If we are using guard blocks, we must track each indivual -// allocation. If we aren't using guard blocks, these -// never get instantiated, so won't have any impact. -// - -class TAllocation -{ - public: - TAllocation(size_t size, unsigned char *mem, TAllocation *prev = 0) - : size(size), mem(mem), prevAlloc(prev) - { -// Allocations are bracketed: -// [allocationHeader][initialGuardBlock][userData][finalGuardBlock] -// This would be cleaner with if (guardBlockSize)..., but that -// makes the compiler print warnings about 0 length memsets, -// even with the if() protecting them. -#ifdef GUARD_BLOCKS - memset(preGuard(), guardBlockBeginVal, guardBlockSize); - memset(data(), userDataFill, size); - memset(postGuard(), guardBlockEndVal, guardBlockSize); -#endif - } - - void check() const - { - checkGuardBlock(preGuard(), guardBlockBeginVal, "before"); - checkGuardBlock(postGuard(), guardBlockEndVal, "after"); - } - - void checkAllocList() const; - - // Return total size needed to accomodate user buffer of 'size', - // plus our tracking data. - inline static size_t allocationSize(size_t size) - { - return size + 2 * guardBlockSize + headerSize(); - } - - // Offset from surrounding buffer to get to user data buffer. - inline static unsigned char *offsetAllocation(unsigned char *m) - { - return m + guardBlockSize + headerSize(); - } - - private: - void checkGuardBlock(unsigned char *blockMem, unsigned char val, const char *locText) const; - - // Find offsets to pre and post guard blocks, and user data buffer - unsigned char *preGuard() const { return mem + headerSize(); } - unsigned char *data() const { return preGuard() + guardBlockSize; } - unsigned char *postGuard() const { return data() + size; } - - size_t size; // size of the user data area - unsigned char *mem; // beginning of our allocation (pts to header) - TAllocation *prevAlloc; // prior allocation in the chain - - // Support MSVC++ 6.0 - const static unsigned char guardBlockBeginVal; - const static unsigned char guardBlockEndVal; - const static unsigned char userDataFill; - - const static size_t guardBlockSize; -#ifdef GUARD_BLOCKS - inline static size_t headerSize() { return sizeof(TAllocation); } -#else - inline static size_t headerSize() { return 0; } -#endif -}; - -// -// There are several stacks. One is to track the pushing and popping -// of the user, and not yet implemented. The others are simply a -// repositories of free pages or used pages. -// -// Page stacks are linked together with a simple header at the beginning -// of each allocation obtained from the underlying OS. Multi-page allocations -// are returned to the OS. Individual page allocations are kept for future -// re-use. -// -// The "page size" used is not, nor must it match, the underlying OS -// page size. But, having it be about that size or equal to a set of -// pages is likely most optimal. -// -class TPoolAllocator -{ - public: - TPoolAllocator(int growthIncrement = 8 * 1024, int allocationAlignment = 16); - - // - // Don't call the destructor just to free up the memory, call pop() - // - ~TPoolAllocator(); - - // - // Call push() to establish a new place to pop memory too. Does not - // have to be called to get things started. - // - void push(); - - // - // Call pop() to free all memory allocated since the last call to push(), - // or if no last call to push, frees all memory since first allocation. - // - void pop(); - - // - // Call popAll() to free all memory allocated. - // - void popAll(); - - // - // Call allocate() to actually acquire memory. Returns 0 if no memory - // available, otherwise a properly aligned pointer to 'numBytes' of memory. - // - void *allocate(size_t numBytes); - - // - // There is no deallocate. The point of this class is that - // deallocation can be skipped by the user of it, as the model - // of use is to simultaneously deallocate everything at once - // by calling pop(), and to not have to solve memory leak problems. - // - - // Catch unwanted allocations. - // TODO(jmadill): Remove this when we remove the global allocator. - void lock(); - void unlock(); - - private: - size_t alignment; // all returned allocations will be aligned at - // this granularity, which will be a power of 2 - size_t alignmentMask; - -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - friend struct tHeader; - - struct tHeader - { - tHeader(tHeader *nextPage, size_t pageCount) - : nextPage(nextPage), - pageCount(pageCount) -#ifdef GUARD_BLOCKS - , - lastAllocation(0) -#endif - { - } - - ~tHeader() - { -#ifdef GUARD_BLOCKS - if (lastAllocation) - lastAllocation->checkAllocList(); -#endif - } - - tHeader *nextPage; - size_t pageCount; -#ifdef GUARD_BLOCKS - TAllocation *lastAllocation; -#endif - }; - - struct tAllocState - { - size_t offset; - tHeader *page; - }; - typedef std::vector<tAllocState> tAllocStack; - - // Track allocations if and only if we're using guard blocks - void *initializeAllocation(tHeader *block, unsigned char *memory, size_t numBytes) - { -#ifdef GUARD_BLOCKS - new (memory) TAllocation(numBytes, memory, block->lastAllocation); - block->lastAllocation = reinterpret_cast<TAllocation *>(memory); -#endif - // This is optimized entirely away if GUARD_BLOCKS is not defined. - return TAllocation::offsetAllocation(memory); - } - - size_t pageSize; // granularity of allocation from the OS - size_t headerSkip; // amount of memory to skip to make room for the - // header (basically, size of header, rounded - // up to make it aligned - size_t currentPageOffset; // next offset in top of inUseList to allocate from - tHeader *freeList; // list of popped memory - tHeader *inUseList; // list of all memory currently being used - tAllocStack mStack; // stack of where to allocate from, to partition pool - - int numCalls; // just an interesting statistic - size_t totalBytes; // just an interesting statistic - -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - std::vector<std::vector<void *>> mStack; -#endif - - TPoolAllocator &operator=(const TPoolAllocator &); // dont allow assignment operator - TPoolAllocator(const TPoolAllocator &); // dont allow default copy constructor - bool mLocked; -}; - -// -// There could potentially be many pools with pops happening at -// different times. But a simple use is to have a global pop -// with everyone using the same global allocator. -// -extern TPoolAllocator *GetGlobalPoolAllocator(); -extern void SetGlobalPoolAllocator(TPoolAllocator *poolAllocator); - -// -// This STL compatible allocator is intended to be used as the allocator -// parameter to templatized STL containers, like vector and map. -// -// It will use the pools for allocation, and not -// do any deallocation, but will still do destruction. -// -template <class T> -class pool_allocator -{ - public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T *pointer; - typedef const T *const_pointer; - typedef T &reference; - typedef const T &const_reference; - typedef T value_type; - - template <class Other> - struct rebind - { - typedef pool_allocator<Other> other; - }; - pointer address(reference x) const { return &x; } - const_pointer address(const_reference x) const { return &x; } - - pool_allocator() {} - - template <class Other> - pool_allocator(const pool_allocator<Other> &p) - { - } - - template <class Other> - pool_allocator<T> &operator=(const pool_allocator<Other> &p) - { - return *this; - } - -#if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR) - // libCStd on some platforms have a different allocate/deallocate interface. - // Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be - // allocated, not the number of elements. - void *allocate(size_type n) { return getAllocator().allocate(n); } - void *allocate(size_type n, const void *) { return getAllocator().allocate(n); } - void deallocate(void *, size_type) {} -#else - pointer allocate(size_type n) - { - return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); - } - pointer allocate(size_type n, const void *) - { - return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); - } - void deallocate(pointer, size_type) {} -#endif // _RWSTD_ALLOCATOR - - void construct(pointer p, const T &val) { new ((void *)p) T(val); } - void destroy(pointer p) { p->T::~T(); } - - bool operator==(const pool_allocator &rhs) const { return true; } - bool operator!=(const pool_allocator &rhs) const { return false; } - - size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); } - size_type max_size(int size) const { return static_cast<size_type>(-1) / size; } - - TPoolAllocator &getAllocator() const { return *GetGlobalPoolAllocator(); } -}; - -#endif // COMPILER_TRANSLATOR_POOLALLOC_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Pragma.h b/src/3rdparty/angle/src/compiler/translator/Pragma.h deleted file mode 100644 index 8c419fc17e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Pragma.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_PRAGMA_H_ -#define COMPILER_TRANSLATOR_PRAGMA_H_ - -struct TPragma -{ - struct STDGL - { - STDGL() : invariantAll(false) {} - - bool invariantAll; - }; - - // By default optimization is turned on and debug is turned off. - // Precision emulation is turned on by default, but has no effect unless - // the extension is enabled. - TPragma() : optimize(true), debug(false), debugShaderPrecision(true) {} - TPragma(bool o, bool d) : optimize(o), debug(d), debugShaderPrecision(true) {} - - bool optimize; - bool debug; - bool debugShaderPrecision; - STDGL stdgl; -}; - -#endif // COMPILER_TRANSLATOR_PRAGMA_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp b/src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp deleted file mode 100644 index 6c9a02cd1c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp +++ /dev/null @@ -1,156 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// PruneNoOps.cpp: The PruneNoOps function prunes: -// 1. Empty declarations "int;". Empty declarators will be pruned as well, so for example: -// int , a; -// is turned into -// int a; -// 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision for float, -// so float literal statements would end up with no precision which is invalid ESSL. - -#include "compiler/translator/PruneNoOps.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -bool IsNoOp(TIntermNode *node) -{ - if (node->getAsConstantUnion() != nullptr) - { - return true; - } - bool isEmptyDeclaration = node->getAsDeclarationNode() != nullptr && - node->getAsDeclarationNode()->getSequence()->empty(); - if (isEmptyDeclaration) - { - return true; - } - return false; -} - -class PruneNoOpsTraverser : private TIntermTraverser -{ - public: - static void apply(TIntermBlock *root); - - private: - PruneNoOpsTraverser(); - bool visitDeclaration(Visit, TIntermDeclaration *node) override; - bool visitBlock(Visit visit, TIntermBlock *node) override; - bool visitLoop(Visit visit, TIntermLoop *loop) override; -}; - -void PruneNoOpsTraverser::apply(TIntermBlock *root) -{ - PruneNoOpsTraverser prune; - root->traverse(&prune); - prune.updateTree(); -} - -PruneNoOpsTraverser::PruneNoOpsTraverser() : TIntermTraverser(true, false, false) -{ -} - -bool PruneNoOpsTraverser::visitDeclaration(Visit, TIntermDeclaration *node) -{ - TIntermSequence *sequence = node->getSequence(); - if (sequence->size() >= 1) - { - TIntermSymbol *sym = sequence->front()->getAsSymbolNode(); - // Prune declarations without a variable name, unless it's an interface block declaration. - if (sym != nullptr && sym->getSymbol() == "" && !sym->isInterfaceBlock()) - { - if (sequence->size() > 1) - { - // Generate a replacement that will remove the empty declarator in the beginning of - // a declarator list. Example of a declaration that will be changed: - // float, a; - // will be changed to - // float a; - // This applies also to struct declarations. - TIntermSequence emptyReplacement; - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(node, sym, emptyReplacement)); - } - else if (sym->getBasicType() != EbtStruct) - { - // If there are entirely empty non-struct declarations, they result in - // TIntermDeclaration nodes without any children in the parsing stage. These are - // handled in visitBlock and visitLoop. - UNREACHABLE(); - } - else if (sym->getType().getQualifier() != EvqGlobal && - sym->getType().getQualifier() != EvqTemporary) - { - // Single struct declarations may just declare the struct type and no variables, so - // they should not be pruned. Here we handle an empty struct declaration with a - // qualifier, for example like this: - // const struct a { int i; }; - // NVIDIA GL driver version 367.27 doesn't accept this kind of declarations, so we - // convert the declaration to a regular struct declaration. This is okay, since ESSL - // 1.00 spec section 4.1.8 says about structs that "The optional qualifiers only - // apply to any declarators, and are not part of the type being defined for name." - - if (mInGlobalScope) - { - sym->getTypePointer()->setQualifier(EvqGlobal); - } - else - { - sym->getTypePointer()->setQualifier(EvqTemporary); - } - } - } - } - return false; -} - -bool PruneNoOpsTraverser::visitBlock(Visit visit, TIntermBlock *node) -{ - TIntermSequence *statements = node->getSequence(); - - for (TIntermNode *statement : *statements) - { - if (IsNoOp(statement)) - { - TIntermSequence emptyReplacement; - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(node, statement, emptyReplacement)); - } - } - - return true; -} - -bool PruneNoOpsTraverser::visitLoop(Visit visit, TIntermLoop *loop) -{ - TIntermTyped *expr = loop->getExpression(); - if (expr != nullptr && IsNoOp(expr)) - { - loop->setExpression(nullptr); - } - TIntermNode *init = loop->getInit(); - if (init != nullptr && IsNoOp(init)) - { - loop->setInit(nullptr); - } - - return true; -} - -} // namespace - -void PruneNoOps(TIntermBlock *root) -{ - PruneNoOpsTraverser::apply(root); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/PruneNoOps.h b/src/3rdparty/angle/src/compiler/translator/PruneNoOps.h deleted file mode 100644 index c421cecca4..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/PruneNoOps.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// PruneNoOps.h: The PruneNoOps function prunes: -// 1. Empty declarations "int;". Empty declarators will be pruned as well, so for example: -// int , a; -// is turned into -// int a; -// 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision for float, -// so float literal statements would end up with no precision which is invalid ESSL. - -#ifndef COMPILER_TRANSLATOR_PRUNENOOPS_H_ -#define COMPILER_TRANSLATOR_PRUNENOOPS_H_ - -namespace sh -{ -class TIntermBlock; - -void PruneNoOps(TIntermBlock *root); -} - -#endif // COMPILER_TRANSLATOR_PRUNENOOPS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp b/src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp deleted file mode 100644 index f748175957..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp +++ /dev/null @@ -1,784 +0,0 @@ -// -// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/QualifierTypes.h" - -#include "compiler/translator/Diagnostics.h" - -#include <algorithm> - -namespace sh -{ - -namespace -{ - -// GLSL ES 3.10 does not impose a strict order on type qualifiers and allows multiple layout -// declarations. -// GLSL ES 3.10 Revision 4, 4.10 Order of Qualification -bool AreTypeQualifierChecksRelaxed(int shaderVersion) -{ - return shaderVersion >= 310; -} - -bool IsScopeQualifier(TQualifier qualifier) -{ - return qualifier == EvqGlobal || qualifier == EvqTemporary; -} - -bool IsScopeQualifierWrapper(const TQualifierWrapperBase *qualifier) -{ - if (qualifier->getType() != QtStorage) - return false; - const TStorageQualifierWrapper *storageQualifier = - static_cast<const TStorageQualifierWrapper *>(qualifier); - TQualifier q = storageQualifier->getQualifier(); - return IsScopeQualifier(q); -} - -// Returns true if the invariant for the qualifier sequence holds -bool IsInvariantCorrect(const TTypeQualifierBuilder::QualifierSequence &qualifiers) -{ - // We should have at least one qualifier. - // The first qualifier always tells the scope. - return qualifiers.size() >= 1 && IsScopeQualifierWrapper(qualifiers[0]); -} - -// Returns true if there are qualifiers which have been specified multiple times -// If areQualifierChecksRelaxed is set to true, then layout qualifier repetition is allowed. -bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qualifiers, - bool areQualifierChecksRelaxed, - std::string *errorMessage) -{ - bool invariantFound = false; - bool precisionFound = false; - bool layoutFound = false; - bool interpolationFound = false; - - unsigned int locationsSpecified = 0; - bool isOut = false; - - // The iteration starts from one since the first qualifier only reveals the scope of the - // expression. It is inserted first whenever the sequence gets created. - for (size_t i = 1; i < qualifiers.size(); ++i) - { - switch (qualifiers[i]->getType()) - { - case QtInvariant: - { - if (invariantFound) - { - *errorMessage = "The invariant qualifier specified multiple times."; - return true; - } - invariantFound = true; - break; - } - case QtPrecision: - { - if (precisionFound) - { - *errorMessage = "The precision qualifier specified multiple times."; - return true; - } - precisionFound = true; - break; - } - case QtLayout: - { - if (layoutFound && !areQualifierChecksRelaxed) - { - *errorMessage = "The layout qualifier specified multiple times."; - return true; - } - if (invariantFound && !areQualifierChecksRelaxed) - { - // This combination is not correct according to the syntax specified in the - // formal grammar in the ESSL 3.00 spec. In ESSL 3.10 the grammar does not have - // a similar restriction. - *errorMessage = - "The layout qualifier and invariant qualifier cannot coexist in the same " - "declaration according to the grammar."; - return true; - } - layoutFound = true; - const TLayoutQualifier ¤tQualifier = - static_cast<const TLayoutQualifierWrapper *>(qualifiers[i])->getQualifier(); - locationsSpecified += currentQualifier.locationsSpecified; - break; - } - case QtInterpolation: - { - // 'centroid' is treated as a storage qualifier - // 'flat centroid' will be squashed to 'flat' - // 'smooth centroid' will be squashed to 'centroid' - if (interpolationFound) - { - *errorMessage = "The interpolation qualifier specified multiple times."; - return true; - } - interpolationFound = true; - break; - } - case QtStorage: - { - // Go over all of the storage qualifiers up until the current one and check for - // repetitions. - TQualifier currentQualifier = - static_cast<const TStorageQualifierWrapper *>(qualifiers[i])->getQualifier(); - if (currentQualifier == EvqVertexOut || currentQualifier == EvqFragmentOut) - { - isOut = true; - } - for (size_t j = 1; j < i; ++j) - { - if (qualifiers[j]->getType() == QtStorage) - { - const TStorageQualifierWrapper *previousQualifierWrapper = - static_cast<const TStorageQualifierWrapper *>(qualifiers[j]); - TQualifier previousQualifier = previousQualifierWrapper->getQualifier(); - if (currentQualifier == previousQualifier) - { - *errorMessage = previousQualifierWrapper->getQualifierString().c_str(); - *errorMessage += " specified multiple times"; - return true; - } - } - } - break; - } - case QtMemory: - { - // Go over all of the memory qualifiers up until the current one and check for - // repetitions. - // Having both readonly and writeonly in a sequence is valid. - // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers - TQualifier currentQualifier = - static_cast<const TMemoryQualifierWrapper *>(qualifiers[i])->getQualifier(); - for (size_t j = 1; j < i; ++j) - { - if (qualifiers[j]->getType() == QtMemory) - { - const TMemoryQualifierWrapper *previousQualifierWrapper = - static_cast<const TMemoryQualifierWrapper *>(qualifiers[j]); - TQualifier previousQualifier = previousQualifierWrapper->getQualifier(); - if (currentQualifier == previousQualifier) - { - *errorMessage = previousQualifierWrapper->getQualifierString().c_str(); - *errorMessage += " specified multiple times"; - return true; - } - } - } - break; - } - default: - UNREACHABLE(); - } - } - - if (locationsSpecified > 1 && isOut) - { - // GLSL ES 3.00.6 section 4.3.8.2 Output Layout Qualifiers - // GLSL ES 3.10 section 4.4.2 Output Layout Qualifiers - // "The qualifier may appear at most once within a declaration." - *errorMessage = "Output layout location specified multiple times."; - return true; - } - - return false; -} - -// GLSL ES 3.00_6, 4.7 Order of Qualification -// The correct order of qualifiers is: -// invariant-qualifier interpolation-qualifier storage-qualifier precision-qualifier -// layout-qualifier has to be before storage-qualifier. -bool AreQualifiersInOrder(const TTypeQualifierBuilder::QualifierSequence &qualifiers, - std::string *errorMessage) -{ - bool foundInterpolation = false; - bool foundStorage = false; - bool foundPrecision = false; - for (size_t i = 1; i < qualifiers.size(); ++i) - { - switch (qualifiers[i]->getType()) - { - case QtInvariant: - if (foundInterpolation || foundStorage || foundPrecision) - { - *errorMessage = "The invariant qualifier has to be first in the expression."; - return false; - } - break; - case QtInterpolation: - if (foundStorage) - { - *errorMessage = "Storage qualifiers have to be after interpolation qualifiers."; - return false; - } - else if (foundPrecision) - { - *errorMessage = - "Precision qualifiers have to be after interpolation qualifiers."; - return false; - } - foundInterpolation = true; - break; - case QtLayout: - if (foundStorage) - { - *errorMessage = "Storage qualifiers have to be after layout qualifiers."; - return false; - } - else if (foundPrecision) - { - *errorMessage = "Precision qualifiers have to be after layout qualifiers."; - return false; - } - break; - case QtStorage: - if (foundPrecision) - { - *errorMessage = "Precision qualifiers have to be after storage qualifiers."; - return false; - } - foundStorage = true; - break; - case QtMemory: - if (foundPrecision) - { - *errorMessage = "Precision qualifiers have to be after memory qualifiers."; - return false; - } - break; - case QtPrecision: - foundPrecision = true; - break; - default: - UNREACHABLE(); - } - } - return true; -} - -struct QualifierComparator -{ - bool operator()(const TQualifierWrapperBase *q1, const TQualifierWrapperBase *q2) - { - return q1->getRank() < q2->getRank(); - } -}; - -void SortSequence(TTypeQualifierBuilder::QualifierSequence &qualifiers) -{ - // We need a stable sorting algorithm since the order of layout-qualifier declarations matter. - // The sorting starts from index 1, instead of 0, since the element at index 0 tells the scope - // and we always want it to be first. - std::stable_sort(qualifiers.begin() + 1, qualifiers.end(), QualifierComparator()); -} - -// Handles the joining of storage qualifiers for variables. -bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier) -{ - switch (*joinedQualifier) - { - case EvqGlobal: - *joinedQualifier = storageQualifier; - break; - case EvqTemporary: - { - switch (storageQualifier) - { - case EvqConst: - *joinedQualifier = storageQualifier; - break; - default: - return false; - } - break; - } - case EvqSmooth: - { - switch (storageQualifier) - { - case EvqCentroid: - *joinedQualifier = EvqCentroid; - break; - case EvqVertexOut: - case EvqGeometryOut: - *joinedQualifier = EvqSmoothOut; - break; - case EvqFragmentIn: - case EvqGeometryIn: - *joinedQualifier = EvqSmoothIn; - break; - default: - return false; - } - break; - } - case EvqFlat: - { - switch (storageQualifier) - { - case EvqCentroid: - *joinedQualifier = EvqFlat; - break; - case EvqVertexOut: - case EvqGeometryOut: - *joinedQualifier = EvqFlatOut; - break; - case EvqFragmentIn: - case EvqGeometryIn: - *joinedQualifier = EvqFlatIn; - break; - default: - return false; - } - break; - } - case EvqCentroid: - { - switch (storageQualifier) - { - case EvqVertexOut: - case EvqGeometryOut: - *joinedQualifier = EvqCentroidOut; - break; - case EvqFragmentIn: - case EvqGeometryIn: - *joinedQualifier = EvqCentroidIn; - break; - default: - return false; - } - break; - } - default: - return false; - } - return true; -} - -// Handles the joining of storage qualifiers for a parameter in a function. -bool JoinParameterStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier) -{ - switch (*joinedQualifier) - { - case EvqTemporary: - *joinedQualifier = storageQualifier; - break; - case EvqConst: - { - switch (storageQualifier) - { - case EvqIn: - *joinedQualifier = EvqConstReadOnly; - break; - default: - return false; - } - break; - } - default: - return false; - } - return true; -} - -bool JoinMemoryQualifier(TMemoryQualifier *joinedMemoryQualifier, TQualifier memoryQualifier) -{ - switch (memoryQualifier) - { - case EvqReadOnly: - joinedMemoryQualifier->readonly = true; - break; - case EvqWriteOnly: - joinedMemoryQualifier->writeonly = true; - break; - case EvqCoherent: - joinedMemoryQualifier->coherent = true; - break; - case EvqRestrict: - joinedMemoryQualifier->restrictQualifier = true; - break; - case EvqVolatile: - // Variables having the volatile qualifier are automatcally treated as coherent as well. - // GLSL ES 3.10, Revision 4, 4.9 Memory Access Qualifiers - joinedMemoryQualifier->volatileQualifier = true; - joinedMemoryQualifier->coherent = true; - break; - default: - UNREACHABLE(); - } - return true; -} - -TTypeQualifier GetVariableTypeQualifierFromSortedSequence( - const TTypeQualifierBuilder::QualifierSequence &sortedSequence, - TDiagnostics *diagnostics) -{ - TTypeQualifier typeQualifier( - static_cast<const TStorageQualifierWrapper *>(sortedSequence[0])->getQualifier(), - sortedSequence[0]->getLine()); - for (size_t i = 1; i < sortedSequence.size(); ++i) - { - const TQualifierWrapperBase *qualifier = sortedSequence[i]; - bool isQualifierValid = false; - switch (qualifier->getType()) - { - case QtInvariant: - isQualifierValid = true; - typeQualifier.invariant = true; - break; - case QtInterpolation: - { - switch (typeQualifier.qualifier) - { - case EvqGlobal: - isQualifierValid = true; - typeQualifier.qualifier = - static_cast<const TInterpolationQualifierWrapper *>(qualifier) - ->getQualifier(); - break; - default: - isQualifierValid = false; - } - break; - } - case QtLayout: - { - const TLayoutQualifierWrapper *layoutQualifierWrapper = - static_cast<const TLayoutQualifierWrapper *>(qualifier); - isQualifierValid = true; - typeQualifier.layoutQualifier = sh::JoinLayoutQualifiers( - typeQualifier.layoutQualifier, layoutQualifierWrapper->getQualifier(), - layoutQualifierWrapper->getLine(), diagnostics); - break; - } - case QtStorage: - isQualifierValid = JoinVariableStorageQualifier( - &typeQualifier.qualifier, - static_cast<const TStorageQualifierWrapper *>(qualifier)->getQualifier()); - break; - case QtPrecision: - isQualifierValid = true; - typeQualifier.precision = - static_cast<const TPrecisionQualifierWrapper *>(qualifier)->getQualifier(); - ASSERT(typeQualifier.precision != EbpUndefined); - break; - case QtMemory: - isQualifierValid = JoinMemoryQualifier( - &typeQualifier.memoryQualifier, - static_cast<const TMemoryQualifierWrapper *>(qualifier)->getQualifier()); - break; - default: - UNREACHABLE(); - } - if (!isQualifierValid) - { - const TString &qualifierString = qualifier->getQualifierString(); - diagnostics->error(qualifier->getLine(), "invalid qualifier combination", - qualifierString.c_str()); - break; - } - } - return typeQualifier; -} - -TTypeQualifier GetParameterTypeQualifierFromSortedSequence( - const TTypeQualifierBuilder::QualifierSequence &sortedSequence, - TDiagnostics *diagnostics) -{ - TTypeQualifier typeQualifier(EvqTemporary, sortedSequence[0]->getLine()); - for (size_t i = 1; i < sortedSequence.size(); ++i) - { - const TQualifierWrapperBase *qualifier = sortedSequence[i]; - bool isQualifierValid = false; - switch (qualifier->getType()) - { - case QtInvariant: - case QtInterpolation: - case QtLayout: - break; - case QtMemory: - isQualifierValid = JoinMemoryQualifier( - &typeQualifier.memoryQualifier, - static_cast<const TMemoryQualifierWrapper *>(qualifier)->getQualifier()); - break; - case QtStorage: - isQualifierValid = JoinParameterStorageQualifier( - &typeQualifier.qualifier, - static_cast<const TStorageQualifierWrapper *>(qualifier)->getQualifier()); - break; - case QtPrecision: - isQualifierValid = true; - typeQualifier.precision = - static_cast<const TPrecisionQualifierWrapper *>(qualifier)->getQualifier(); - ASSERT(typeQualifier.precision != EbpUndefined); - break; - default: - UNREACHABLE(); - } - if (!isQualifierValid) - { - const TString &qualifierString = qualifier->getQualifierString(); - diagnostics->error(qualifier->getLine(), "invalid parameter qualifier", - qualifierString.c_str()); - break; - } - } - - switch (typeQualifier.qualifier) - { - case EvqIn: - case EvqConstReadOnly: // const in - case EvqOut: - case EvqInOut: - break; - case EvqConst: - typeQualifier.qualifier = EvqConstReadOnly; - break; - case EvqTemporary: - // no qualifier has been specified, set it to EvqIn which is the default - typeQualifier.qualifier = EvqIn; - break; - default: - diagnostics->error(sortedSequence[0]->getLine(), "Invalid parameter qualifier ", - getQualifierString(typeQualifier.qualifier)); - } - return typeQualifier; -} -} // namespace - -TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier, - TLayoutQualifier rightQualifier, - const TSourceLoc &rightQualifierLocation, - TDiagnostics *diagnostics) -{ - TLayoutQualifier joinedQualifier = leftQualifier; - - if (rightQualifier.location != -1) - { - joinedQualifier.location = rightQualifier.location; - ++joinedQualifier.locationsSpecified; - } - if (rightQualifier.yuv != false) - { - joinedQualifier.yuv = rightQualifier.yuv; - } - if (rightQualifier.binding != -1) - { - joinedQualifier.binding = rightQualifier.binding; - } - if (rightQualifier.offset != -1) - { - joinedQualifier.offset = rightQualifier.offset; - } - if (rightQualifier.matrixPacking != EmpUnspecified) - { - joinedQualifier.matrixPacking = rightQualifier.matrixPacking; - } - if (rightQualifier.blockStorage != EbsUnspecified) - { - joinedQualifier.blockStorage = rightQualifier.blockStorage; - } - - for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i) - { - if (rightQualifier.localSize[i] != -1) - { - if (joinedQualifier.localSize[i] != -1 && - joinedQualifier.localSize[i] != rightQualifier.localSize[i]) - { - diagnostics->error(rightQualifierLocation, - "Cannot have multiple different work group size specifiers", - getWorkGroupSizeString(i)); - } - joinedQualifier.localSize[i] = rightQualifier.localSize[i]; - } - } - - if (rightQualifier.numViews != -1) - { - joinedQualifier.numViews = rightQualifier.numViews; - } - - if (rightQualifier.imageInternalFormat != EiifUnspecified) - { - joinedQualifier.imageInternalFormat = rightQualifier.imageInternalFormat; - } - - if (rightQualifier.primitiveType != EptUndefined) - { - if (joinedQualifier.primitiveType != EptUndefined && - joinedQualifier.primitiveType != rightQualifier.primitiveType) - { - diagnostics->error(rightQualifierLocation, - "Cannot have multiple different primitive specifiers", - getGeometryShaderPrimitiveTypeString(rightQualifier.primitiveType)); - } - joinedQualifier.primitiveType = rightQualifier.primitiveType; - } - - if (rightQualifier.invocations != 0) - { - if (joinedQualifier.invocations != 0 && - joinedQualifier.invocations != rightQualifier.invocations) - { - diagnostics->error(rightQualifierLocation, - "Cannot have multiple different invocations specifiers", - "invocations"); - } - joinedQualifier.invocations = rightQualifier.invocations; - } - - if (rightQualifier.maxVertices != -1) - { - if (joinedQualifier.maxVertices != -1 && - joinedQualifier.maxVertices != rightQualifier.maxVertices) - { - diagnostics->error(rightQualifierLocation, - "Cannot have multiple different max_vertices specifiers", - "max_vertices"); - } - joinedQualifier.maxVertices = rightQualifier.maxVertices; - } - - return joinedQualifier; -} - -unsigned int TInvariantQualifierWrapper::getRank() const -{ - return 0u; -} - -unsigned int TInterpolationQualifierWrapper::getRank() const -{ - return 1u; -} - -unsigned int TLayoutQualifierWrapper::getRank() const -{ - return 2u; -} - -unsigned int TStorageQualifierWrapper::getRank() const -{ - // Force the 'centroid' auxilary storage qualifier to be always first among all storage - // qualifiers. - if (mStorageQualifier == EvqCentroid) - { - return 3u; - } - else - { - return 4u; - } -} - -unsigned int TMemoryQualifierWrapper::getRank() const -{ - return 4u; -} - -unsigned int TPrecisionQualifierWrapper::getRank() const -{ - return 5u; -} - -TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc) - : layoutQualifier(TLayoutQualifier::Create()), - memoryQualifier(TMemoryQualifier::Create()), - precision(EbpUndefined), - qualifier(scope), - invariant(false), - line(loc) -{ - ASSERT(IsScopeQualifier(qualifier)); -} - -TTypeQualifierBuilder::TTypeQualifierBuilder(const TStorageQualifierWrapper *scope, - int shaderVersion) - : mShaderVersion(shaderVersion) -{ - ASSERT(IsScopeQualifier(scope->getQualifier())); - mQualifiers.push_back(scope); -} - -void TTypeQualifierBuilder::appendQualifier(const TQualifierWrapperBase *qualifier) -{ - mQualifiers.push_back(qualifier); -} - -bool TTypeQualifierBuilder::checkSequenceIsValid(TDiagnostics *diagnostics) const -{ - bool areQualifierChecksRelaxed = AreTypeQualifierChecksRelaxed(mShaderVersion); - std::string errorMessage; - if (HasRepeatingQualifiers(mQualifiers, areQualifierChecksRelaxed, &errorMessage)) - { - diagnostics->error(mQualifiers[0]->getLine(), errorMessage.c_str(), "qualifier sequence"); - return false; - } - - if (!areQualifierChecksRelaxed && !AreQualifiersInOrder(mQualifiers, &errorMessage)) - { - diagnostics->error(mQualifiers[0]->getLine(), errorMessage.c_str(), "qualifier sequence"); - return false; - } - - return true; -} - -TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier(TDiagnostics *diagnostics) const -{ - ASSERT(IsInvariantCorrect(mQualifiers)); - ASSERT(static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier() == - EvqTemporary); - - if (!checkSequenceIsValid(diagnostics)) - { - return TTypeQualifier(EvqTemporary, mQualifiers[0]->getLine()); - } - - // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so - // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to - // combine the qualifiers. - if (AreTypeQualifierChecksRelaxed(mShaderVersion)) - { - // Copy the qualifier sequence so that we can sort them. - QualifierSequence sortedQualifierSequence = mQualifiers; - SortSequence(sortedQualifierSequence); - return GetParameterTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics); - } - return GetParameterTypeQualifierFromSortedSequence(mQualifiers, diagnostics); -} - -TTypeQualifier TTypeQualifierBuilder::getVariableTypeQualifier(TDiagnostics *diagnostics) const -{ - ASSERT(IsInvariantCorrect(mQualifiers)); - - if (!checkSequenceIsValid(diagnostics)) - { - return TTypeQualifier( - static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier(), - mQualifiers[0]->getLine()); - } - - // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so - // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to - // combine the qualifiers. - if (AreTypeQualifierChecksRelaxed(mShaderVersion)) - { - // Copy the qualifier sequence so that we can sort them. - QualifierSequence sortedQualifierSequence = mQualifiers; - SortSequence(sortedQualifierSequence); - return GetVariableTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics); - } - return GetVariableTypeQualifierFromSortedSequence(mQualifiers, diagnostics); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierTypes.h b/src/3rdparty/angle/src/compiler/translator/QualifierTypes.h deleted file mode 100644 index 10bdeed89d..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/QualifierTypes.h +++ /dev/null @@ -1,191 +0,0 @@ -// -// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_ -#define COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_ - -#include "common/angleutils.h" -#include "compiler/translator/BaseTypes.h" -#include "compiler/translator/Types.h" - -namespace sh -{ -class TDiagnostics; - -TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier, - TLayoutQualifier rightQualifier, - const TSourceLoc &rightQualifierLocation, - TDiagnostics *diagnostics); - -enum TQualifierType -{ - QtInvariant, - QtInterpolation, - QtLayout, - QtStorage, - QtPrecision, - QtMemory -}; - -class TQualifierWrapperBase : angle::NonCopyable -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TQualifierWrapperBase(const TSourceLoc &line) : mLine(line) {} - virtual ~TQualifierWrapperBase(){}; - virtual TQualifierType getType() const = 0; - virtual TString getQualifierString() const = 0; - virtual unsigned int getRank() const = 0; - const TSourceLoc &getLine() const { return mLine; } - private: - TSourceLoc mLine; -}; - -class TInvariantQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TInvariantQualifierWrapper(const TSourceLoc &line) : TQualifierWrapperBase(line) {} - ~TInvariantQualifierWrapper() {} - - TQualifierType getType() const { return QtInvariant; } - TString getQualifierString() const { return "invariant"; } - unsigned int getRank() const; -}; - -class TInterpolationQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TInterpolationQualifierWrapper(TQualifier interpolationQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mInterpolationQualifier(interpolationQualifier) - { - } - ~TInterpolationQualifierWrapper() {} - - TQualifierType getType() const { return QtInterpolation; } - TString getQualifierString() const { return sh::getQualifierString(mInterpolationQualifier); } - TQualifier getQualifier() const { return mInterpolationQualifier; } - unsigned int getRank() const; - - private: - TQualifier mInterpolationQualifier; -}; - -class TLayoutQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TLayoutQualifierWrapper(TLayoutQualifier layoutQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mLayoutQualifier(layoutQualifier) - { - } - ~TLayoutQualifierWrapper() {} - - TQualifierType getType() const { return QtLayout; } - TString getQualifierString() const { return "layout"; } - const TLayoutQualifier &getQualifier() const { return mLayoutQualifier; } - unsigned int getRank() const; - - private: - TLayoutQualifier mLayoutQualifier; -}; - -class TStorageQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TStorageQualifierWrapper(TQualifier storageQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mStorageQualifier(storageQualifier) - { - } - ~TStorageQualifierWrapper() {} - - TQualifierType getType() const { return QtStorage; } - TString getQualifierString() const { return sh::getQualifierString(mStorageQualifier); } - TQualifier getQualifier() const { return mStorageQualifier; } - unsigned int getRank() const; - - private: - TQualifier mStorageQualifier; -}; - -class TPrecisionQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TPrecisionQualifierWrapper(TPrecision precisionQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mPrecisionQualifier(precisionQualifier) - { - } - ~TPrecisionQualifierWrapper() {} - - TQualifierType getType() const { return QtPrecision; } - TString getQualifierString() const { return sh::getPrecisionString(mPrecisionQualifier); } - TPrecision getQualifier() const { return mPrecisionQualifier; } - unsigned int getRank() const; - - private: - TPrecision mPrecisionQualifier; -}; - -class TMemoryQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TMemoryQualifierWrapper(TQualifier memoryQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mMemoryQualifier(memoryQualifier) - { - } - ~TMemoryQualifierWrapper() {} - - TQualifierType getType() const { return QtMemory; } - TString getQualifierString() const { return sh::getQualifierString(mMemoryQualifier); } - TQualifier getQualifier() const { return mMemoryQualifier; } - unsigned int getRank() const; - - private: - TQualifier mMemoryQualifier; -}; - -// TTypeQualifier tightly covers type_qualifier from the grammar -struct TTypeQualifier -{ - // initializes all of the qualifiers and sets the scope - TTypeQualifier(TQualifier scope, const TSourceLoc &loc); - - TLayoutQualifier layoutQualifier; - TMemoryQualifier memoryQualifier; - TPrecision precision; - TQualifier qualifier; - bool invariant; - TSourceLoc line; -}; - -// TTypeQualifierBuilder contains all of the qualifiers when type_qualifier gets parsed. -// It is to be used to validate the qualifier sequence and build a TTypeQualifier from it. -class TTypeQualifierBuilder : angle::NonCopyable -{ - public: - using QualifierSequence = TVector<const TQualifierWrapperBase *>; - - public: - POOL_ALLOCATOR_NEW_DELETE(); - TTypeQualifierBuilder(const TStorageQualifierWrapper *scope, int shaderVersion); - // Adds the passed qualifier to the end of the sequence. - void appendQualifier(const TQualifierWrapperBase *qualifier); - // Checks for the order of qualification and repeating qualifiers. - bool checkSequenceIsValid(TDiagnostics *diagnostics) const; - // Goes over the qualifier sequence and parses it to form a type qualifier for a function - // parameter. - // The returned object is initialized even if the parsing fails. - TTypeQualifier getParameterTypeQualifier(TDiagnostics *diagnostics) const; - // Goes over the qualifier sequence and parses it to form a type qualifier for a variable. - // The returned object is initialized even if the parsing fails. - TTypeQualifier getVariableTypeQualifier(TDiagnostics *diagnostics) const; - - private: - QualifierSequence mQualifiers; - int mShaderVersion; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp b/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp deleted file mode 100644 index 5233a29f19..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// During parsing, all constant expressions are folded to constant union nodes. The expressions that -// have been folded may have had precision qualifiers, which should affect the precision of the -// consuming operation. If the folded constant union nodes are written to output as such they won't -// have any precision qualifiers, and their effect on the precision of the consuming operation is -// lost. -// -// RecordConstantPrecision is an AST traverser that inspects the precision qualifiers of constants -// and hoists the constants outside the containing expression as precision qualified named variables -// in case that is required for correct precision propagation. -// - -#include "compiler/translator/RecordConstantPrecision.h" - -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class RecordConstantPrecisionTraverser : public TIntermTraverser -{ - public: - RecordConstantPrecisionTraverser(TSymbolTable *symbolTable); - - void visitConstantUnion(TIntermConstantUnion *node) override; - - void nextIteration(); - - bool foundHigherPrecisionConstant() const { return mFoundHigherPrecisionConstant; } - protected: - bool operandAffectsParentOperationPrecision(TIntermTyped *operand); - - bool mFoundHigherPrecisionConstant; -}; - -RecordConstantPrecisionTraverser::RecordConstantPrecisionTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, true, symbolTable), mFoundHigherPrecisionConstant(false) -{ -} - -bool RecordConstantPrecisionTraverser::operandAffectsParentOperationPrecision(TIntermTyped *operand) -{ - if (getParentNode()->getAsCaseNode() || getParentNode()->getAsBlock()) - { - return false; - } - - const TIntermBinary *parentAsBinary = getParentNode()->getAsBinaryNode(); - if (parentAsBinary != nullptr) - { - // If the constant is assigned or is used to initialize a variable, or if it's an index, - // its precision has no effect. - switch (parentAsBinary->getOp()) - { - case EOpInitialize: - case EOpAssign: - case EOpIndexDirect: - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: - case EOpIndexIndirect: - return false; - default: - break; - } - - TIntermTyped *otherOperand = parentAsBinary->getRight(); - if (otherOperand == operand) - { - otherOperand = parentAsBinary->getLeft(); - } - // If the precision of the other child is at least as high as the precision of the constant, - // the precision of the constant has no effect. - if (otherOperand->getAsConstantUnion() == nullptr && - otherOperand->getPrecision() >= operand->getPrecision()) - { - return false; - } - } - - TIntermAggregate *parentAsAggregate = getParentNode()->getAsAggregate(); - if (parentAsAggregate != nullptr) - { - if (!parentAsAggregate->gotPrecisionFromChildren()) - { - // This can be either: - // * a call to an user-defined function - // * a call to a texture function - // * some other kind of aggregate - // In any of these cases the constant precision has no effect. - return false; - } - if (parentAsAggregate->isConstructor() && parentAsAggregate->getBasicType() == EbtBool) - { - return false; - } - // If the precision of operands does affect the result, but the precision of any of the - // other children has a precision that's at least as high as the precision of the constant, - // the precision of the constant has no effect. - TIntermSequence *parameters = parentAsAggregate->getSequence(); - for (TIntermNode *parameter : *parameters) - { - const TIntermTyped *typedParameter = parameter->getAsTyped(); - if (parameter != operand && typedParameter != nullptr && - parameter->getAsConstantUnion() == nullptr && - typedParameter->getPrecision() >= operand->getPrecision()) - { - return false; - } - } - } - return true; -} - -void RecordConstantPrecisionTraverser::visitConstantUnion(TIntermConstantUnion *node) -{ - if (mFoundHigherPrecisionConstant) - return; - - // If the constant has lowp or undefined precision, it can't increase the precision of consuming - // operations. - if (node->getPrecision() < EbpMedium) - return; - - // It's possible the node has no effect on the precision of the consuming expression, depending - // on the consuming expression, and the precision of the other parameters of the expression. - if (!operandAffectsParentOperationPrecision(node)) - return; - - // Make the constant a precision-qualified named variable to make sure it affects the precision - // of the consuming expression. - TIntermSequence insertions; - insertions.push_back(createTempInitDeclaration(node, EvqConst)); - insertStatementsInParentBlock(insertions); - queueReplacement(createTempSymbol(node->getType()), OriginalNode::IS_DROPPED); - mFoundHigherPrecisionConstant = true; -} - -void RecordConstantPrecisionTraverser::nextIteration() -{ - nextTemporaryId(); - mFoundHigherPrecisionConstant = false; -} - -} // namespace - -void RecordConstantPrecision(TIntermNode *root, TSymbolTable *symbolTable) -{ - RecordConstantPrecisionTraverser traverser(symbolTable); - // Iterate as necessary, and reset the traverser between iterations. - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.foundHigherPrecisionConstant()) - traverser.updateTree(); - } while (traverser.foundHigherPrecisionConstant()); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h b/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h deleted file mode 100644 index f86c2a8693..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// During parsing, all constant expressions are folded to constant union nodes. The expressions that -// have been folded may have had precision qualifiers, which should affect the precision of the -// consuming operation. If the folded constant union nodes are written to output as such they won't -// have any precision qualifiers, and their effect on the precision of the consuming operation is -// lost. -// -// RecordConstantPrecision is an AST traverser that inspects the precision qualifiers of constants -// and hoists the constants outside the containing expression as precision qualified named variables -// in case that is required for correct precision propagation. -// - -#ifndef COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_ -#define COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_ - -namespace sh -{ -class TIntermNode; -class TSymbolTable; - -void RecordConstantPrecision(TIntermNode *root, TSymbolTable *symbolTable); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp deleted file mode 100644 index 55fb124a42..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "common/debug.h" -#include "compiler/translator/RegenerateStructNames.h" - -namespace sh -{ - -void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol) -{ - ASSERT(symbol); - TType *type = symbol->getTypePointer(); - ASSERT(type); - TStructure *userType = type->getStruct(); - if (!userType) - return; - - if (mSymbolTable->findBuiltIn(userType->name(), mShaderVersion)) - { - // Built-in struct, do not touch it. - return; - } - - int uniqueId = userType->uniqueId(); - - ASSERT(mScopeDepth > 0); - if (mScopeDepth == 1) - { - // If a struct is defined at global scope, we don't map its name. - // This is because at global level, the struct might be used to - // declare a uniform, so the same name needs to stay the same for - // vertex/fragment shaders. However, our mapping uses internal ID, - // which will be different for the same struct in vertex/fragment - // shaders. - // This is OK because names for any structs defined in other scopes - // will begin with "_webgl", which is reserved. So there will be - // no conflicts among unmapped struct names from global scope and - // mapped struct names from other scopes. - // However, we need to keep track of these global structs, so if a - // variable is used in a local scope, we don't try to modify the - // struct name through that variable. - mDeclaredGlobalStructs.insert(uniqueId); - return; - } - if (mDeclaredGlobalStructs.count(uniqueId) > 0) - return; - // Map {name} to _webgl_struct_{uniqueId}_{name}. - const char kPrefix[] = "_webgl_struct_"; - if (userType->name().find(kPrefix) == 0) - { - // The name has already been regenerated. - return; - } - std::string id = Str(uniqueId); - TString tmp = kPrefix + TString(id.c_str()); - tmp += "_" + userType->name(); - userType->setName(tmp); -} - -bool RegenerateStructNames::visitBlock(Visit, TIntermBlock *block) -{ - ++mScopeDepth; - TIntermSequence &sequence = *(block->getSequence()); - for (TIntermNode *node : sequence) - { - node->traverse(this); - } - --mScopeDepth; - return false; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h deleted file mode 100644 index 293720b6a4..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_ -#define COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_ - -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -#include <set> - -namespace sh -{ - -class RegenerateStructNames : public TIntermTraverser -{ - public: - RegenerateStructNames(TSymbolTable *symbolTable, int shaderVersion) - : TIntermTraverser(true, false, false, symbolTable), - mShaderVersion(shaderVersion), - mScopeDepth(0) - { - } - - protected: - void visitSymbol(TIntermSymbol *) override; - bool visitBlock(Visit, TIntermBlock *block) override; - - private: - int mShaderVersion; - - // Indicating the depth of the current scope. - // The global scope is 1. - int mScopeDepth; - - // If a struct's declared globally, push its ID in this set. - std::set<int> mDeclaredGlobalStructs; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp deleted file mode 100644 index e9e6a17013..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveArrayLengthMethod.cpp: -// Fold array length expressions, including cases where the "this" node has side effects. -// Example: -// int i = (a = b).length(); -// int j = (func()).length(); -// becomes: -// (a = b); -// int i = <constant array length>; -// func(); -// int j = <constant array length>; -// -// Must be run after SplitSequenceOperator, SimplifyLoopConditions and SeparateDeclarations steps -// have been done to expressions containing calls of the array length method. -// -// Does nothing to length method calls done on runtime-sized arrays. - -#include "compiler/translator/RemoveArrayLengthMethod.h" - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class RemoveArrayLengthTraverser : public TIntermTraverser -{ - public: - RemoveArrayLengthTraverser() : TIntermTraverser(true, false, false), mFoundArrayLength(false) {} - - bool visitUnary(Visit visit, TIntermUnary *node) override; - - void nextIteration() { mFoundArrayLength = false; } - - bool foundArrayLength() const { return mFoundArrayLength; } - - private: - bool mFoundArrayLength; -}; - -bool RemoveArrayLengthTraverser::visitUnary(Visit visit, TIntermUnary *node) -{ - // The only case where we leave array length() in place is for runtime-sized arrays. - if (node->getOp() == EOpArrayLength && !node->getOperand()->getType().isUnsizedArray()) - { - mFoundArrayLength = true; - if (!node->getOperand()->hasSideEffects()) - { - queueReplacement(node->fold(nullptr), OriginalNode::IS_DROPPED); - return false; - } - insertStatementInParentBlock(node->getOperand()->deepCopy()); - TConstantUnion *constArray = new TConstantUnion[1]; - constArray->setIConst(node->getOperand()->getOutermostArraySize()); - queueReplacement(new TIntermConstantUnion(constArray, node->getType()), - OriginalNode::IS_DROPPED); - return false; - } - return true; -} - -} // anonymous namespace - -void RemoveArrayLengthMethod(TIntermBlock *root) -{ - RemoveArrayLengthTraverser traverser; - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.foundArrayLength()) - traverser.updateTree(); - } while (traverser.foundArrayLength()); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h b/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h deleted file mode 100644 index 3b2c6df824..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveArrayLengthMethod.h: -// Fold array length expressions, including cases where the "this" node has side effects. -// Example: -// int i = (a = b).length(); -// int j = (func()).length(); -// becomes: -// (a = b); -// int i = <constant array length>; -// func(); -// int j = <constant array length>; -// -// Must be run after SplitSequenceOperator, SimplifyLoopConditions and SeparateDeclarations steps -// have been done to expressions containing calls of the array length method. -// -// Does nothing to length method calls done on runtime-sized arrays. - -namespace sh -{ - -class TIntermBlock; - -void RemoveArrayLengthMethod(TIntermBlock *root); - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp deleted file mode 100644 index 7766c1abc6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp +++ /dev/null @@ -1,550 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveDynamicIndexing is an AST traverser to remove dynamic indexing of vectors and matrices, -// replacing them with calls to functions that choose which component to return or write. -// - -#include "compiler/translator/RemoveDynamicIndexing.h" - -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermNodePatternMatcher.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -std::string GetIndexFunctionName(const TType &type, bool write) -{ - TInfoSinkBase nameSink; - nameSink << "dyn_index_"; - if (write) - { - nameSink << "write_"; - } - if (type.isMatrix()) - { - nameSink << "mat" << type.getCols() << "x" << type.getRows(); - } - else - { - switch (type.getBasicType()) - { - case EbtInt: - nameSink << "ivec"; - break; - case EbtBool: - nameSink << "bvec"; - break; - case EbtUInt: - nameSink << "uvec"; - break; - case EbtFloat: - nameSink << "vec"; - break; - default: - UNREACHABLE(); - } - nameSink << type.getNominalSize(); - } - return nameSink.str(); -} - -TIntermSymbol *CreateBaseSymbol(const TType &type, TQualifier qualifier, TSymbolTable *symbolTable) -{ - TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), "base", type); - symbol->setInternal(true); - symbol->getTypePointer()->setQualifier(qualifier); - return symbol; -} - -TIntermSymbol *CreateIndexSymbol(TSymbolTable *symbolTable) -{ - TIntermSymbol *symbol = - new TIntermSymbol(symbolTable->nextUniqueId(), "index", TType(EbtInt, EbpHigh)); - symbol->setInternal(true); - symbol->getTypePointer()->setQualifier(EvqIn); - return symbol; -} - -TIntermSymbol *CreateValueSymbol(const TType &type, TSymbolTable *symbolTable) -{ - TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), "value", type); - symbol->setInternal(true); - symbol->getTypePointer()->setQualifier(EvqIn); - return symbol; -} - -TIntermConstantUnion *CreateIntConstantNode(int i) -{ - TConstantUnion *constant = new TConstantUnion(); - constant->setIConst(i); - return new TIntermConstantUnion(constant, TType(EbtInt, EbpHigh)); -} - -TIntermTyped *EnsureSignedInt(TIntermTyped *node) -{ - if (node->getBasicType() == EbtInt) - return node; - - TIntermSequence *arguments = new TIntermSequence(); - arguments->push_back(node); - return TIntermAggregate::CreateConstructor(TType(EbtInt), arguments); -} - -TType GetFieldType(const TType &indexedType) -{ - if (indexedType.isMatrix()) - { - TType fieldType = TType(indexedType.getBasicType(), indexedType.getPrecision()); - fieldType.setPrimarySize(static_cast<unsigned char>(indexedType.getRows())); - return fieldType; - } - else - { - return TType(indexedType.getBasicType(), indexedType.getPrecision()); - } -} - -// Generate a read or write function for one field in a vector/matrix. -// Out-of-range indices are clamped. This is consistent with how ANGLE handles out-of-range -// indices in other places. -// Note that indices can be either int or uint. We create only int versions of the functions, -// and convert uint indices to int at the call site. -// read function example: -// float dyn_index_vec2(in vec2 base, in int index) -// { -// switch(index) -// { -// case (0): -// return base[0]; -// case (1): -// return base[1]; -// default: -// break; -// } -// if (index < 0) -// return base[0]; -// return base[1]; -// } -// write function example: -// void dyn_index_write_vec2(inout vec2 base, in int index, in float value) -// { -// switch(index) -// { -// case (0): -// base[0] = value; -// return; -// case (1): -// base[1] = value; -// return; -// default: -// break; -// } -// if (index < 0) -// { -// base[0] = value; -// return; -// } -// base[1] = value; -// } -// Note that else is not used in above functions to avoid the RewriteElseBlocks transformation. -TIntermFunctionDefinition *GetIndexFunctionDefinition(TType type, - bool write, - const TSymbolUniqueId &functionId, - TSymbolTable *symbolTable) -{ - ASSERT(!type.isArray()); - // Conservatively use highp here, even if the indexed type is not highp. That way the code can't - // end up using mediump version of an indexing function for a highp value, if both mediump and - // highp values are being indexed in the shader. For HLSL precision doesn't matter, but in - // principle this code could be used with multiple backends. - type.setPrecision(EbpHigh); - - TType fieldType = GetFieldType(type); - int numCases = 0; - if (type.isMatrix()) - { - numCases = type.getCols(); - } - else - { - numCases = type.getNominalSize(); - } - - TType returnType(EbtVoid); - if (!write) - { - returnType = fieldType; - } - - std::string functionName = GetIndexFunctionName(type, write); - TIntermFunctionPrototype *prototypeNode = - CreateInternalFunctionPrototypeNode(returnType, functionName.c_str(), functionId); - - TQualifier baseQualifier = EvqInOut; - if (!write) - baseQualifier = EvqIn; - TIntermSymbol *baseParam = CreateBaseSymbol(type, baseQualifier, symbolTable); - prototypeNode->getSequence()->push_back(baseParam); - TIntermSymbol *indexParam = CreateIndexSymbol(symbolTable); - prototypeNode->getSequence()->push_back(indexParam); - TIntermSymbol *valueParam = nullptr; - if (write) - { - valueParam = CreateValueSymbol(fieldType, symbolTable); - prototypeNode->getSequence()->push_back(valueParam); - } - - TIntermBlock *statementList = new TIntermBlock(); - for (int i = 0; i < numCases; ++i) - { - TIntermCase *caseNode = new TIntermCase(CreateIntConstantNode(i)); - statementList->getSequence()->push_back(caseNode); - - TIntermBinary *indexNode = - new TIntermBinary(EOpIndexDirect, baseParam->deepCopy(), CreateIndexNode(i)); - if (write) - { - TIntermBinary *assignNode = - new TIntermBinary(EOpAssign, indexNode, valueParam->deepCopy()); - statementList->getSequence()->push_back(assignNode); - TIntermBranch *returnNode = new TIntermBranch(EOpReturn, nullptr); - statementList->getSequence()->push_back(returnNode); - } - else - { - TIntermBranch *returnNode = new TIntermBranch(EOpReturn, indexNode); - statementList->getSequence()->push_back(returnNode); - } - } - - // Default case - TIntermCase *defaultNode = new TIntermCase(nullptr); - statementList->getSequence()->push_back(defaultNode); - TIntermBranch *breakNode = new TIntermBranch(EOpBreak, nullptr); - statementList->getSequence()->push_back(breakNode); - - TIntermSwitch *switchNode = new TIntermSwitch(indexParam->deepCopy(), statementList); - - TIntermBlock *bodyNode = new TIntermBlock(); - bodyNode->getSequence()->push_back(switchNode); - - TIntermBinary *cond = - new TIntermBinary(EOpLessThan, indexParam->deepCopy(), CreateIntConstantNode(0)); - cond->setType(TType(EbtBool, EbpUndefined)); - - // Two blocks: one accesses (either reads or writes) the first element and returns, - // the other accesses the last element. - TIntermBlock *useFirstBlock = new TIntermBlock(); - TIntermBlock *useLastBlock = new TIntermBlock(); - TIntermBinary *indexFirstNode = - new TIntermBinary(EOpIndexDirect, baseParam->deepCopy(), CreateIndexNode(0)); - TIntermBinary *indexLastNode = - new TIntermBinary(EOpIndexDirect, baseParam->deepCopy(), CreateIndexNode(numCases - 1)); - if (write) - { - TIntermBinary *assignFirstNode = - new TIntermBinary(EOpAssign, indexFirstNode, valueParam->deepCopy()); - useFirstBlock->getSequence()->push_back(assignFirstNode); - TIntermBranch *returnNode = new TIntermBranch(EOpReturn, nullptr); - useFirstBlock->getSequence()->push_back(returnNode); - - TIntermBinary *assignLastNode = - new TIntermBinary(EOpAssign, indexLastNode, valueParam->deepCopy()); - useLastBlock->getSequence()->push_back(assignLastNode); - } - else - { - TIntermBranch *returnFirstNode = new TIntermBranch(EOpReturn, indexFirstNode); - useFirstBlock->getSequence()->push_back(returnFirstNode); - - TIntermBranch *returnLastNode = new TIntermBranch(EOpReturn, indexLastNode); - useLastBlock->getSequence()->push_back(returnLastNode); - } - TIntermIfElse *ifNode = new TIntermIfElse(cond, useFirstBlock, nullptr); - bodyNode->getSequence()->push_back(ifNode); - bodyNode->getSequence()->push_back(useLastBlock); - - TIntermFunctionDefinition *indexingFunction = - new TIntermFunctionDefinition(prototypeNode, bodyNode); - return indexingFunction; -} - -class RemoveDynamicIndexingTraverser : public TLValueTrackingTraverser -{ - public: - RemoveDynamicIndexingTraverser(TSymbolTable *symbolTable, - int shaderVersion, - PerformanceDiagnostics *perfDiagnostics); - - bool visitBinary(Visit visit, TIntermBinary *node) override; - - void insertHelperDefinitions(TIntermNode *root); - - void nextIteration(); - - bool usedTreeInsertion() const { return mUsedTreeInsertion; } - - protected: - // Maps of types that are indexed to the indexing function ids used for them. Note that these - // can not store multiple variants of the same type with different precisions - only one - // precision gets stored. - std::map<TType, TSymbolUniqueId *> mIndexedVecAndMatrixTypes; - std::map<TType, TSymbolUniqueId *> mWrittenVecAndMatrixTypes; - - bool mUsedTreeInsertion; - - // When true, the traverser will remove side effects from any indexing expression. - // This is done so that in code like - // V[j++][i]++. - // where V is an array of vectors, j++ will only be evaluated once. - bool mRemoveIndexSideEffectsInSubtree; - - PerformanceDiagnostics *mPerfDiagnostics; -}; - -RemoveDynamicIndexingTraverser::RemoveDynamicIndexingTraverser( - TSymbolTable *symbolTable, - int shaderVersion, - PerformanceDiagnostics *perfDiagnostics) - : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion), - mUsedTreeInsertion(false), - mRemoveIndexSideEffectsInSubtree(false), - mPerfDiagnostics(perfDiagnostics) -{ -} - -void RemoveDynamicIndexingTraverser::insertHelperDefinitions(TIntermNode *root) -{ - TIntermBlock *rootBlock = root->getAsBlock(); - ASSERT(rootBlock != nullptr); - TIntermSequence insertions; - for (auto &type : mIndexedVecAndMatrixTypes) - { - insertions.push_back( - GetIndexFunctionDefinition(type.first, false, *type.second, mSymbolTable)); - } - for (auto &type : mWrittenVecAndMatrixTypes) - { - insertions.push_back( - GetIndexFunctionDefinition(type.first, true, *type.second, mSymbolTable)); - } - rootBlock->insertChildNodes(0, insertions); -} - -// Create a call to dyn_index_*() based on an indirect indexing op node -TIntermAggregate *CreateIndexFunctionCall(TIntermBinary *node, - TIntermTyped *index, - const TSymbolUniqueId &functionId) -{ - ASSERT(node->getOp() == EOpIndexIndirect); - TIntermSequence *arguments = new TIntermSequence(); - arguments->push_back(node->getLeft()); - arguments->push_back(index); - - TType fieldType = GetFieldType(node->getLeft()->getType()); - std::string functionName = GetIndexFunctionName(node->getLeft()->getType(), false); - TIntermAggregate *indexingCall = - CreateInternalFunctionCallNode(fieldType, functionName.c_str(), functionId, arguments); - indexingCall->setLine(node->getLine()); - indexingCall->getFunctionSymbolInfo()->setKnownToNotHaveSideEffects(true); - return indexingCall; -} - -TIntermAggregate *CreateIndexedWriteFunctionCall(TIntermBinary *node, - TIntermTyped *index, - TIntermTyped *writtenValue, - const TSymbolUniqueId &functionId) -{ - ASSERT(node->getOp() == EOpIndexIndirect); - TIntermSequence *arguments = new TIntermSequence(); - // Deep copy the child nodes so that two pointers to the same node don't end up in the tree. - arguments->push_back(node->getLeft()->deepCopy()); - arguments->push_back(index->deepCopy()); - arguments->push_back(writtenValue); - - std::string functionName = GetIndexFunctionName(node->getLeft()->getType(), true); - TIntermAggregate *indexedWriteCall = - CreateInternalFunctionCallNode(TType(EbtVoid), functionName.c_str(), functionId, arguments); - indexedWriteCall->setLine(node->getLine()); - return indexedWriteCall; -} - -bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - if (mUsedTreeInsertion) - return false; - - if (node->getOp() == EOpIndexIndirect) - { - if (mRemoveIndexSideEffectsInSubtree) - { - ASSERT(node->getRight()->hasSideEffects()); - // In case we're just removing index side effects, convert - // v_expr[index_expr] - // to this: - // int s0 = index_expr; v_expr[s0]; - // Now v_expr[s0] can be safely executed several times without unintended side effects. - - // Init the temp variable holding the index - TIntermDeclaration *initIndex = createTempInitDeclaration(node->getRight()); - insertStatementInParentBlock(initIndex); - mUsedTreeInsertion = true; - - // Replace the index with the temp variable - TIntermSymbol *tempIndex = createTempSymbol(node->getRight()->getType()); - queueReplacementWithParent(node, node->getRight(), tempIndex, OriginalNode::IS_DROPPED); - } - else if (IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(node)) - { - mPerfDiagnostics->warning(node->getLine(), - "Performance: dynamic indexing of vectors and " - "matrices is emulated and can be slow.", - "[]"); - bool write = isLValueRequiredHere(); - -#if defined(ANGLE_ENABLE_ASSERTS) - // Make sure that IntermNodePatternMatcher is consistent with the slightly differently - // implemented checks in this traverser. - IntermNodePatternMatcher matcher( - IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue); - ASSERT(matcher.match(node, getParentNode(), isLValueRequiredHere()) == write); -#endif - - const TType &type = node->getLeft()->getType(); - TSymbolUniqueId *indexingFunctionId = new TSymbolUniqueId(mSymbolTable); - if (mIndexedVecAndMatrixTypes.find(type) == mIndexedVecAndMatrixTypes.end()) - { - mIndexedVecAndMatrixTypes[type] = indexingFunctionId; - } - else - { - indexingFunctionId = mIndexedVecAndMatrixTypes[type]; - } - - if (write) - { - // Convert: - // v_expr[index_expr]++; - // to this: - // int s0 = index_expr; float s1 = dyn_index(v_expr, s0); s1++; - // dyn_index_write(v_expr, s0, s1); - // This works even if index_expr has some side effects. - if (node->getLeft()->hasSideEffects()) - { - // If v_expr has side effects, those need to be removed before proceeding. - // Otherwise the side effects of v_expr would be evaluated twice. - // The only case where an l-value can have side effects is when it is - // indexing. For example, it can be V[j++] where V is an array of vectors. - mRemoveIndexSideEffectsInSubtree = true; - return true; - } - - TIntermBinary *leftBinary = node->getLeft()->getAsBinaryNode(); - if (leftBinary != nullptr && - IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(leftBinary)) - { - // This is a case like: - // mat2 m; - // m[a][b]++; - // Process the child node m[a] first. - return true; - } - - // TODO(oetuaho@nvidia.com): This is not optimal if the expression using the value - // only writes it and doesn't need the previous value. http://anglebug.com/1116 - - TSymbolUniqueId *indexedWriteFunctionId = new TSymbolUniqueId(mSymbolTable); - if (mWrittenVecAndMatrixTypes.find(type) == mWrittenVecAndMatrixTypes.end()) - { - mWrittenVecAndMatrixTypes[type] = indexedWriteFunctionId; - } - else - { - indexedWriteFunctionId = mWrittenVecAndMatrixTypes[type]; - } - TType fieldType = GetFieldType(type); - - TIntermSequence insertionsBefore; - TIntermSequence insertionsAfter; - - // Store the index in a temporary signed int variable. - TIntermTyped *indexInitializer = EnsureSignedInt(node->getRight()); - TIntermDeclaration *initIndex = createTempInitDeclaration(indexInitializer); - initIndex->setLine(node->getLine()); - insertionsBefore.push_back(initIndex); - - // Create a node for referring to the index after the nextTemporaryId() call - // below. - TIntermSymbol *tempIndex = createTempSymbol(indexInitializer->getType()); - - TIntermAggregate *indexingCall = - CreateIndexFunctionCall(node, tempIndex, *indexingFunctionId); - - nextTemporaryId(); // From now on, creating temporary symbols that refer to the - // field value. - insertionsBefore.push_back(createTempInitDeclaration(indexingCall)); - - TIntermAggregate *indexedWriteCall = CreateIndexedWriteFunctionCall( - node, tempIndex, createTempSymbol(fieldType), *indexedWriteFunctionId); - insertionsAfter.push_back(indexedWriteCall); - insertStatementsInParentBlock(insertionsBefore, insertionsAfter); - queueReplacement(createTempSymbol(fieldType), OriginalNode::IS_DROPPED); - mUsedTreeInsertion = true; - } - else - { - // The indexed value is not being written, so we can simply convert - // v_expr[index_expr] - // into - // dyn_index(v_expr, index_expr) - // If the index_expr is unsigned, we'll convert it to signed. - ASSERT(!mRemoveIndexSideEffectsInSubtree); - TIntermAggregate *indexingCall = CreateIndexFunctionCall( - node, EnsureSignedInt(node->getRight()), *indexingFunctionId); - queueReplacement(indexingCall, OriginalNode::IS_DROPPED); - } - } - } - return !mUsedTreeInsertion; -} - -void RemoveDynamicIndexingTraverser::nextIteration() -{ - mUsedTreeInsertion = false; - mRemoveIndexSideEffectsInSubtree = false; - nextTemporaryId(); -} - -} // namespace - -void RemoveDynamicIndexing(TIntermNode *root, - TSymbolTable *symbolTable, - int shaderVersion, - PerformanceDiagnostics *perfDiagnostics) -{ - RemoveDynamicIndexingTraverser traverser(symbolTable, shaderVersion, perfDiagnostics); - do - { - traverser.nextIteration(); - root->traverse(&traverser); - traverser.updateTree(); - } while (traverser.usedTreeInsertion()); - // TODO(oetuaho@nvidia.com): It might be nicer to add the helper definitions also in the middle - // of traversal. Now the tree ends up in an inconsistent state in the middle, since there are - // function call nodes with no corresponding definition nodes. This needs special handling in - // TIntermLValueTrackingTraverser, and creates intricacies that are not easily apparent from a - // superficial reading of the code. - traverser.insertHelperDefinitions(root); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h b/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h deleted file mode 100644 index 543cf569a6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveDynamicIndexing is an AST traverser to remove dynamic indexing of vectors and matrices, -// replacing them with calls to functions that choose which component to return or write. -// - -#ifndef COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_ -#define COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_ - -namespace sh -{ - -class TIntermNode; -class TSymbolTable; -class PerformanceDiagnostics; - -void RemoveDynamicIndexing(TIntermNode *root, - TSymbolTable *symbolTable, - int shaderVersion, - PerformanceDiagnostics *perfDiagnostics); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp deleted file mode 100644 index b39c912e9c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveEmptySwitchStatements.cpp: Remove switch statements that have an empty statement list. - -#include "compiler/translator/RemoveEmptySwitchStatements.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class RemoveEmptySwitchStatementsTraverser : public TIntermTraverser -{ - public: - RemoveEmptySwitchStatementsTraverser() : TIntermTraverser(true, false, false) {} - - bool visitSwitch(Visit visit, TIntermSwitch *node); -}; - -bool RemoveEmptySwitchStatementsTraverser::visitSwitch(Visit visit, TIntermSwitch *node) -{ - if (node->getStatementList()->getSequence()->empty()) - { - // Just output the init statement. - if (node->getInit()->hasSideEffects()) - { - queueReplacement(node->getInit(), OriginalNode::IS_DROPPED); - } - else - { - TIntermSequence emptyReplacement; - ASSERT(getParentNode()->getAsBlock()); - mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), - node, emptyReplacement)); - } - return false; // Nothing inside the child nodes to traverse. - } - return true; -} - -} // anonymous namespace - -void RemoveEmptySwitchStatements(TIntermBlock *root) -{ - RemoveEmptySwitchStatementsTraverser traverser; - root->traverse(&traverser); - traverser.updateTree(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h b/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h deleted file mode 100644 index 1018a50d82..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveEmptySwitchStatements.h: Remove switch statements that have an empty statement list. - -#ifndef COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_ -#define COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_ - -namespace sh -{ -class TIntermBlock; - -void RemoveEmptySwitchStatements(TIntermBlock *root); -} - -#endif // COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp deleted file mode 100644 index 4b533dc7b5..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/RemoveInvariantDeclaration.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -// An AST traverser that removes invariant declaration for input in fragment shader -// when GLSL >= 4.20 and for output in vertex shader when GLSL < 4.2. -class RemoveInvariantDeclarationTraverser : public TIntermTraverser -{ - public: - RemoveInvariantDeclarationTraverser() : TIntermTraverser(true, false, false) {} - - private: - bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override - { - TIntermSequence emptyReplacement; - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, emptyReplacement)); - return false; - } -}; - -} // anonymous namespace - -void RemoveInvariantDeclaration(TIntermNode *root) -{ - RemoveInvariantDeclarationTraverser traverser; - root->traverse(&traverser); - traverser.updateTree(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h b/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h deleted file mode 100644 index cf9d4aa4c2..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_ -#define COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_ - -class TIntermNode; -namespace sh -{ - -void RemoveInvariantDeclaration(TIntermNode *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp deleted file mode 100644 index b86d64d7a3..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveNoOpCasesFromEndOfSwitchStatements.cpp: Clean up cases from the end of a switch statement -// that only contain no-ops. - -#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h" - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -bool AreEmptyBlocks(TIntermSequence *statements, size_t i); - -bool IsEmptyBlock(TIntermNode *node) -{ - TIntermBlock *asBlock = node->getAsBlock(); - if (asBlock) - { - if (asBlock->getSequence()->empty()) - { - return true; - } - return AreEmptyBlocks(asBlock->getSequence(), 0u); - } - // Empty declarations should have already been pruned, otherwise they would need to be handled - // here. Note that declarations for struct types do contain a nameless child node. - ASSERT(node->getAsDeclarationNode() == nullptr || - !node->getAsDeclarationNode()->getSequence()->empty()); - // Pure literal statements should also already be pruned. - ASSERT(node->getAsConstantUnion() == nullptr); - return false; -} - -// Return true if all statements in "statements" starting from index i consist only of empty blocks -// and no-op statements. Returns true also if there are no statements. -bool AreEmptyBlocks(TIntermSequence *statements, size_t i) -{ - for (; i < statements->size(); ++i) - { - if (!IsEmptyBlock(statements->at(i))) - { - return false; - } - } - return true; -} - -void RemoveNoOpCasesFromEndOfStatementList(TIntermBlock *statementList, TSymbolTable *symbolTable) -{ - TIntermSequence *statements = statementList->getSequence(); - - bool foundDeadCase = false; - do - { - if (statements->empty()) - { - return; - } - - // Find the last case label. - size_t i = statements->size(); - while (i > 0u && !(*statements)[i - 1]->getAsCaseNode()) - { - --i; - } - // Now i is the index of the first statement following the last label inside the switch - // statement. - ASSERT(i > 0u); - - foundDeadCase = AreEmptyBlocks(statements, i); - if (foundDeadCase) - { - statements->erase(statements->begin() + (i - 1u), statements->end()); - } - } while (foundDeadCase); -} - -class RemoveNoOpCasesFromEndOfSwitchTraverser : public TIntermTraverser -{ - public: - RemoveNoOpCasesFromEndOfSwitchTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, false, symbolTable) - { - } - - bool visitSwitch(Visit visit, TIntermSwitch *node) override; -}; - -bool RemoveNoOpCasesFromEndOfSwitchTraverser::visitSwitch(Visit visit, TIntermSwitch *node) -{ - // Here we may mutate the statement list, but it's safe since traversal has not yet reached - // there. - RemoveNoOpCasesFromEndOfStatementList(node->getStatementList(), mSymbolTable); - // Handle also nested switch statements. - return true; -} - -} // anonymous namespace - -void RemoveNoOpCasesFromEndOfSwitchStatements(TIntermBlock *root, TSymbolTable *symbolTable) -{ - RemoveNoOpCasesFromEndOfSwitchTraverser traverser(symbolTable); - root->traverse(&traverser); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h b/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h deleted file mode 100644 index ebd75eb774..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveNoOpCasesFromEndOfSwitchStatements.h: Clean up cases from the end of a switch statement -// that only contain no-ops. - -#ifndef COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_ -#define COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_ - -namespace sh -{ -class TIntermBlock; -class TSymbolTable; - -void RemoveNoOpCasesFromEndOfSwitchStatements(TIntermBlock *root, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemovePow.cpp b/src/3rdparty/angle/src/compiler/translator/RemovePow.cpp deleted file mode 100644 index b2cdac55f0..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemovePow.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemovePow is an AST traverser to convert pow(x, y) built-in calls where y is a -// constant to exp2(y * log2(x)). This works around an issue in NVIDIA 311 series -// OpenGL drivers. -// - -#include "compiler/translator/RemovePow.h" - -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -bool IsProblematicPow(TIntermTyped *node) -{ - TIntermAggregate *agg = node->getAsAggregate(); - if (agg != nullptr && agg->getOp() == EOpPow) - { - ASSERT(agg->getSequence()->size() == 2); - return agg->getSequence()->at(1)->getAsConstantUnion() != nullptr; - } - return false; -} - -// Traverser that converts all pow operations simultaneously. -class RemovePowTraverser : public TIntermTraverser -{ - public: - RemovePowTraverser(); - - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - - void nextIteration() { mNeedAnotherIteration = false; } - bool needAnotherIteration() const { return mNeedAnotherIteration; } - - protected: - bool mNeedAnotherIteration; -}; - -RemovePowTraverser::RemovePowTraverser() - : TIntermTraverser(true, false, false), mNeedAnotherIteration(false) -{ -} - -bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (IsProblematicPow(node)) - { - TIntermTyped *x = node->getSequence()->at(0)->getAsTyped(); - TIntermTyped *y = node->getSequence()->at(1)->getAsTyped(); - - TIntermUnary *log = new TIntermUnary(EOpLog2, x); - log->setLine(node->getLine()); - - TOperator op = TIntermBinary::GetMulOpBasedOnOperands(y->getType(), log->getType()); - TIntermBinary *mul = new TIntermBinary(op, y, log); - mul->setLine(node->getLine()); - - TIntermUnary *exp = new TIntermUnary(EOpExp2, mul); - exp->setLine(node->getLine()); - - queueReplacement(exp, OriginalNode::IS_DROPPED); - - // If the x parameter also needs to be replaced, we need to do that in another traversal, - // since it's parent node will change in a way that's not handled correctly by updateTree(). - if (IsProblematicPow(x)) - { - mNeedAnotherIteration = true; - return false; - } - } - return true; -} - -} // namespace - -void RemovePow(TIntermNode *root) -{ - RemovePowTraverser traverser; - // Iterate as necessary, and reset the traverser between iterations. - do - { - traverser.nextIteration(); - root->traverse(&traverser); - traverser.updateTree(); - } while (traverser.needAnotherIteration()); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemovePow.h b/src/3rdparty/angle/src/compiler/translator/RemovePow.h deleted file mode 100644 index 3cd84988a9..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemovePow.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemovePow is an AST traverser to convert pow(x, y) built-in calls where y is a -// constant to exp2(y * log2(x)). This works around an issue in NVIDIA 311 series -// OpenGL drivers. -// - -#ifndef COMPILER_TRANSLATOR_REMOVEPOW_H_ -#define COMPILER_TRANSLATOR_REMOVEPOW_H_ - -namespace sh -{ -class TIntermNode; - -void RemovePow(TIntermNode *root); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REMOVEPOW_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp deleted file mode 100644 index dea949f448..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp +++ /dev/null @@ -1,270 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveSwitchFallThrough.cpp: Remove fall-through from switch statements. -// Note that it is unsafe to do further AST transformations on the AST generated -// by this function. It leaves duplicate nodes in the AST making replacements -// unreliable. - -#include "compiler/translator/RemoveSwitchFallThrough.h" - -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class RemoveSwitchFallThroughTraverser : public TIntermTraverser -{ - public: - static TIntermBlock *removeFallThrough(TIntermBlock *statementList, - PerformanceDiagnostics *perfDiagnostics); - - private: - RemoveSwitchFallThroughTraverser(TIntermBlock *statementList, - PerformanceDiagnostics *perfDiagnostics); - - void visitSymbol(TIntermSymbol *node) override; - void visitConstantUnion(TIntermConstantUnion *node) override; - bool visitDeclaration(Visit, TIntermDeclaration *node) override; - bool visitBinary(Visit, TIntermBinary *node) override; - bool visitUnary(Visit, TIntermUnary *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - bool visitSwizzle(Visit, TIntermSwizzle *node) override; - bool visitIfElse(Visit visit, TIntermIfElse *node) override; - bool visitSwitch(Visit, TIntermSwitch *node) override; - bool visitCase(Visit, TIntermCase *node) override; - bool visitAggregate(Visit, TIntermAggregate *node) override; - bool visitBlock(Visit, TIntermBlock *node) override; - bool visitLoop(Visit, TIntermLoop *node) override; - bool visitBranch(Visit, TIntermBranch *node) override; - - void outputSequence(TIntermSequence *sequence, size_t startIndex); - void handlePreviousCase(); - - TIntermBlock *mStatementList; - TIntermBlock *mStatementListOut; - bool mLastStatementWasBreak; - TIntermBlock *mPreviousCase; - std::vector<TIntermBlock *> mCasesSharingBreak; - PerformanceDiagnostics *mPerfDiagnostics; -}; - -TIntermBlock *RemoveSwitchFallThroughTraverser::removeFallThrough( - TIntermBlock *statementList, - PerformanceDiagnostics *perfDiagnostics) -{ - RemoveSwitchFallThroughTraverser rm(statementList, perfDiagnostics); - ASSERT(statementList); - statementList->traverse(&rm); - ASSERT(rm.mPreviousCase || statementList->getSequence()->empty()); - if (!rm.mLastStatementWasBreak && rm.mPreviousCase) - { - // Make sure that there's a branch at the end of the final case inside the switch statement. - // This also ensures that any cases that fall through to the final case will get the break. - TIntermBranch *finalBreak = new TIntermBranch(EOpBreak, nullptr); - rm.mPreviousCase->getSequence()->push_back(finalBreak); - rm.mLastStatementWasBreak = true; - } - rm.handlePreviousCase(); - return rm.mStatementListOut; -} - -RemoveSwitchFallThroughTraverser::RemoveSwitchFallThroughTraverser( - TIntermBlock *statementList, - PerformanceDiagnostics *perfDiagnostics) - : TIntermTraverser(true, false, false), - mStatementList(statementList), - mLastStatementWasBreak(false), - mPreviousCase(nullptr), - mPerfDiagnostics(perfDiagnostics) -{ - mStatementListOut = new TIntermBlock(); -} - -void RemoveSwitchFallThroughTraverser::visitSymbol(TIntermSymbol *node) -{ - // Note that this assumes that switch statements which don't begin by a case statement - // have already been weeded out in validation. - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; -} - -void RemoveSwitchFallThroughTraverser::visitConstantUnion(TIntermConstantUnion *node) -{ - // Conditions of case labels are not traversed, so this is a constant statement like "0;". - // These are no-ops so there's no need to add them back to the statement list. Should have - // already been pruned out of the AST, in fact. - UNREACHABLE(); -} - -bool RemoveSwitchFallThroughTraverser::visitDeclaration(Visit, TIntermDeclaration *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitBinary(Visit, TIntermBinary *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitUnary(Visit, TIntermUnary *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitTernary(Visit, TIntermTernary *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitSwizzle(Visit, TIntermSwizzle *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitIfElse(Visit, TIntermIfElse *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitSwitch(Visit, TIntermSwitch *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - // Don't go into nested switch statements - return false; -} - -void RemoveSwitchFallThroughTraverser::outputSequence(TIntermSequence *sequence, size_t startIndex) -{ - for (size_t i = startIndex; i < sequence->size(); ++i) - { - mStatementListOut->getSequence()->push_back(sequence->at(i)); - } -} - -void RemoveSwitchFallThroughTraverser::handlePreviousCase() -{ - if (mPreviousCase) - mCasesSharingBreak.push_back(mPreviousCase); - if (mLastStatementWasBreak) - { - for (size_t i = 0; i < mCasesSharingBreak.size(); ++i) - { - ASSERT(!mCasesSharingBreak.at(i)->getSequence()->empty()); - if (mCasesSharingBreak.at(i)->getSequence()->size() == 1) - { - // Fall-through is allowed in case the label has no statements. - outputSequence(mCasesSharingBreak.at(i)->getSequence(), 0); - } - else - { - // Include all the statements that this case can fall through under the same label. - if (mCasesSharingBreak.size() > i + 1u) - { - mPerfDiagnostics->warning(mCasesSharingBreak.at(i)->getLine(), - "Performance: non-empty fall-through cases in " - "switch statements generate extra code.", - "switch"); - } - for (size_t j = i; j < mCasesSharingBreak.size(); ++j) - { - size_t startIndex = - j > i ? 1 : 0; // Add the label only from the first sequence. - outputSequence(mCasesSharingBreak.at(j)->getSequence(), startIndex); - } - } - } - mCasesSharingBreak.clear(); - } - mLastStatementWasBreak = false; - mPreviousCase = nullptr; -} - -bool RemoveSwitchFallThroughTraverser::visitCase(Visit, TIntermCase *node) -{ - handlePreviousCase(); - mPreviousCase = new TIntermBlock(); - mPreviousCase->getSequence()->push_back(node); - mPreviousCase->setLine(node->getLine()); - // Don't traverse the condition of the case statement - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitAggregate(Visit, TIntermAggregate *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool DoesBlockAlwaysBreak(TIntermBlock *node) -{ - if (node->getSequence()->empty()) - { - return false; - } - - TIntermBlock *lastStatementAsBlock = node->getSequence()->back()->getAsBlock(); - if (lastStatementAsBlock) - { - return DoesBlockAlwaysBreak(lastStatementAsBlock); - } - - TIntermBranch *lastStatementAsBranch = node->getSequence()->back()->getAsBranchNode(); - return lastStatementAsBranch != nullptr; -} - -bool RemoveSwitchFallThroughTraverser::visitBlock(Visit, TIntermBlock *node) -{ - if (node != mStatementList) - { - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = DoesBlockAlwaysBreak(node); - return false; - } - return true; -} - -bool RemoveSwitchFallThroughTraverser::visitLoop(Visit, TIntermLoop *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThroughTraverser::visitBranch(Visit, TIntermBranch *node) -{ - mPreviousCase->getSequence()->push_back(node); - // TODO: Verify that accepting return or continue statements here doesn't cause problems. - mLastStatementWasBreak = true; - return false; -} - -} // anonymous namespace - -TIntermBlock *RemoveSwitchFallThrough(TIntermBlock *statementList, - PerformanceDiagnostics *perfDiagnostics) -{ - return RemoveSwitchFallThroughTraverser::removeFallThrough(statementList, perfDiagnostics); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h deleted file mode 100644 index 7a3b1963f2..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveSwitchFallThrough.h: Remove fall-through from switch statements. -// Note that it is unsafe to do further AST transformations on the AST generated -// by this function. It leaves duplicate nodes in the AST making replacements -// unreliable. - -#ifndef COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ -#define COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ - -namespace sh -{ - -class TIntermBlock; -class PerformanceDiagnostics; - -// When given a statementList from a switch AST node, return an updated -// statementList that has fall-through removed. -TIntermBlock *RemoveSwitchFallThrough(TIntermBlock *statementList, - PerformanceDiagnostics *perfDiagnostics); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp deleted file mode 100644 index 74b5e73f71..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp +++ /dev/null @@ -1,358 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveUnreferencedVariables.cpp: -// Drop variables that are declared but never referenced in the AST. This avoids adding unnecessary -// initialization code for them. Also removes unreferenced struct types. -// - -#include "compiler/translator/RemoveUnreferencedVariables.h" - -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -class CollectVariableRefCountsTraverser : public TIntermTraverser -{ - public: - CollectVariableRefCountsTraverser(); - - using RefCountMap = std::unordered_map<int, unsigned int>; - RefCountMap &getSymbolIdRefCounts() { return mSymbolIdRefCounts; } - RefCountMap &getStructIdRefCounts() { return mStructIdRefCounts; } - - void visitSymbol(TIntermSymbol *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; - - private: - void incrementStructTypeRefCount(const TType &type); - - RefCountMap mSymbolIdRefCounts; - - // Structure reference counts are counted from symbols, constructors, function calls, function - // return values and from interface block and structure fields. We need to track both function - // calls and function return values since there's a compiler option not to prune unused - // functions. The type of a constant union may also be a struct, but statements that are just a - // constant union are always pruned, and if the constant union is used somehow it will get - // counted by something else. - RefCountMap mStructIdRefCounts; -}; - -CollectVariableRefCountsTraverser::CollectVariableRefCountsTraverser() - : TIntermTraverser(true, false, false) -{ -} - -void CollectVariableRefCountsTraverser::incrementStructTypeRefCount(const TType &type) -{ - if (type.isInterfaceBlock()) - { - const auto *block = type.getInterfaceBlock(); - ASSERT(block); - - // We can end up incrementing ref counts of struct types referenced from an interface block - // multiple times for the same block. This doesn't matter, because interface blocks can't be - // pruned so we'll never do the reverse operation. - for (const auto &field : block->fields()) - { - ASSERT(!field->type()->isInterfaceBlock()); - incrementStructTypeRefCount(*field->type()); - } - return; - } - - const auto *structure = type.getStruct(); - if (structure != nullptr) - { - auto structIter = mStructIdRefCounts.find(structure->uniqueId()); - if (structIter == mStructIdRefCounts.end()) - { - mStructIdRefCounts[structure->uniqueId()] = 1u; - - for (const auto &field : structure->fields()) - { - incrementStructTypeRefCount(*field->type()); - } - - return; - } - ++(structIter->second); - } -} - -void CollectVariableRefCountsTraverser::visitSymbol(TIntermSymbol *node) -{ - incrementStructTypeRefCount(node->getType()); - - auto iter = mSymbolIdRefCounts.find(node->getId()); - if (iter == mSymbolIdRefCounts.end()) - { - mSymbolIdRefCounts[node->getId()] = 1u; - return; - } - ++(iter->second); -} - -bool CollectVariableRefCountsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - // This tracks struct references in both function calls and constructors. - incrementStructTypeRefCount(node->getType()); - return true; -} - -bool CollectVariableRefCountsTraverser::visitFunctionPrototype(Visit visit, - TIntermFunctionPrototype *node) -{ - incrementStructTypeRefCount(node->getType()); - return true; -} - -// Traverser that removes all unreferenced variables on one traversal. -class RemoveUnreferencedVariablesTraverser : public TIntermTraverser -{ - public: - RemoveUnreferencedVariablesTraverser( - CollectVariableRefCountsTraverser::RefCountMap *symbolIdRefCounts, - CollectVariableRefCountsTraverser::RefCountMap *structIdRefCounts, - TSymbolTable *symbolTable); - - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - void visitSymbol(TIntermSymbol *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - - // Traverse loop and block nodes in reverse order. Note that this traverser does not track - // parent block positions, so insertStatementInParentBlock is unusable! - void traverseBlock(TIntermBlock *block) override; - void traverseLoop(TIntermLoop *loop) override; - - private: - void removeVariableDeclaration(TIntermDeclaration *node, TIntermTyped *declarator); - void decrementStructTypeRefCount(const TType &type); - - CollectVariableRefCountsTraverser::RefCountMap *mSymbolIdRefCounts; - CollectVariableRefCountsTraverser::RefCountMap *mStructIdRefCounts; - bool mRemoveReferences; -}; - -RemoveUnreferencedVariablesTraverser::RemoveUnreferencedVariablesTraverser( - CollectVariableRefCountsTraverser::RefCountMap *symbolIdRefCounts, - CollectVariableRefCountsTraverser::RefCountMap *structIdRefCounts, - TSymbolTable *symbolTable) - : TIntermTraverser(true, false, true, symbolTable), - mSymbolIdRefCounts(symbolIdRefCounts), - mStructIdRefCounts(structIdRefCounts), - mRemoveReferences(false) -{ -} - -void RemoveUnreferencedVariablesTraverser::decrementStructTypeRefCount(const TType &type) -{ - auto *structure = type.getStruct(); - if (structure != nullptr) - { - ASSERT(mStructIdRefCounts->find(structure->uniqueId()) != mStructIdRefCounts->end()); - unsigned int structRefCount = --(*mStructIdRefCounts)[structure->uniqueId()]; - - if (structRefCount == 0) - { - for (const auto &field : structure->fields()) - { - decrementStructTypeRefCount(*field->type()); - } - } - } -} - -void RemoveUnreferencedVariablesTraverser::removeVariableDeclaration(TIntermDeclaration *node, - TIntermTyped *declarator) -{ - if (declarator->getType().isStructSpecifier() && !declarator->getType().isNamelessStruct()) - { - unsigned int structId = declarator->getType().getStruct()->uniqueId(); - if ((*mStructIdRefCounts)[structId] > 1u) - { - // If this declaration declares a named struct type that is used elsewhere, we need to - // keep it. We can still change the declarator though so that it doesn't declare an - // unreferenced variable. - - // Note that since we're not removing the entire declaration, the struct's reference - // count will end up being one less than the correct refcount. But since the struct - // declaration is kept, the incorrect refcount can't cause any other problems. - - if (declarator->getAsSymbolNode() && declarator->getAsSymbolNode()->getSymbol().empty()) - { - // Already an empty declaration - nothing to do. - return; - } - queueReplacementWithParent(node, declarator, - new TIntermSymbol(mSymbolTable->getEmptySymbolId(), - TString(""), declarator->getType()), - OriginalNode::IS_DROPPED); - return; - } - } - - if (getParentNode()->getAsBlock()) - { - TIntermSequence emptyReplacement; - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, emptyReplacement)); - } - else - { - ASSERT(getParentNode()->getAsLoopNode()); - queueReplacement(nullptr, OriginalNode::IS_DROPPED); - } -} - -bool RemoveUnreferencedVariablesTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - if (visit == PreVisit) - { - // SeparateDeclarations should have already been run. - ASSERT(node->getSequence()->size() == 1u); - - TIntermTyped *declarator = node->getSequence()->back()->getAsTyped(); - ASSERT(declarator); - - // We can only remove variables that are not a part of the shader interface. - TQualifier qualifier = declarator->getQualifier(); - if (qualifier != EvqTemporary && qualifier != EvqGlobal) - { - return true; - } - - bool canRemoveVariable = false; - TIntermSymbol *symbolNode = declarator->getAsSymbolNode(); - if (symbolNode != nullptr) - { - canRemoveVariable = - (*mSymbolIdRefCounts)[symbolNode->getId()] == 1u || symbolNode->getSymbol().empty(); - } - TIntermBinary *initNode = declarator->getAsBinaryNode(); - if (initNode != nullptr) - { - ASSERT(initNode->getLeft()->getAsSymbolNode()); - int symbolId = initNode->getLeft()->getAsSymbolNode()->getId(); - canRemoveVariable = - (*mSymbolIdRefCounts)[symbolId] == 1u && !initNode->getRight()->hasSideEffects(); - } - - if (canRemoveVariable) - { - removeVariableDeclaration(node, declarator); - mRemoveReferences = true; - } - return true; - } - ASSERT(visit == PostVisit); - mRemoveReferences = false; - return true; -} - -void RemoveUnreferencedVariablesTraverser::visitSymbol(TIntermSymbol *node) -{ - if (mRemoveReferences) - { - ASSERT(mSymbolIdRefCounts->find(node->getId()) != mSymbolIdRefCounts->end()); - --(*mSymbolIdRefCounts)[node->getId()]; - - decrementStructTypeRefCount(node->getType()); - } -} - -bool RemoveUnreferencedVariablesTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (mRemoveReferences) - { - decrementStructTypeRefCount(node->getType()); - } - return true; -} - -void RemoveUnreferencedVariablesTraverser::traverseBlock(TIntermBlock *node) -{ - // We traverse blocks in reverse order. This way reference counts can be decremented when - // removing initializers, and variables that become unused when initializers are removed can be - // removed on the same traversal. - - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - TIntermSequence *sequence = node->getSequence(); - - if (preVisit) - visit = visitBlock(PreVisit, node); - - if (visit) - { - for (auto iter = sequence->rbegin(); iter != sequence->rend(); ++iter) - { - (*iter)->traverse(this); - if (visit && inVisit) - { - if ((iter + 1) != sequence->rend()) - visit = visitBlock(InVisit, node); - } - } - } - - if (visit && postVisit) - visitBlock(PostVisit, node); -} - -void RemoveUnreferencedVariablesTraverser::traverseLoop(TIntermLoop *node) -{ - // We traverse loops in reverse order as well. The loop body gets traversed before the init - // node. - - ScopedNodeInTraversalPath addToPath(this, node); - - bool visit = true; - - if (preVisit) - visit = visitLoop(PreVisit, node); - - if (visit) - { - // We don't need to traverse loop expressions or conditions since they can't be declarations - // in the AST (loops which have a declaration in their condition get transformed in the - // parsing stage). - ASSERT(node->getExpression() == nullptr || - node->getExpression()->getAsDeclarationNode() == nullptr); - ASSERT(node->getCondition() == nullptr || - node->getCondition()->getAsDeclarationNode() == nullptr); - - if (node->getBody()) - node->getBody()->traverse(this); - - if (node->getInit()) - node->getInit()->traverse(this); - } - - if (visit && postVisit) - visitLoop(PostVisit, node); -} - -} // namespace - -void RemoveUnreferencedVariables(TIntermBlock *root, TSymbolTable *symbolTable) -{ - CollectVariableRefCountsTraverser collector; - root->traverse(&collector); - RemoveUnreferencedVariablesTraverser traverser(&collector.getSymbolIdRefCounts(), - &collector.getStructIdRefCounts(), symbolTable); - root->traverse(&traverser); - traverser.updateTree(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h b/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h deleted file mode 100644 index 39c8327776..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RemoveUnreferencedVariables.h: -// Drop variables that are declared but never referenced in the AST. This avoids adding unnecessary -// initialization code for them. Also removes unreferenced struct types. -// - -#ifndef COMPILER_TRANSLATOR_REMOVEUNREFERENCEDVARIABLES_H_ -#define COMPILER_TRANSLATOR_REMOVEUNREFERENCEDVARIABLES_H_ - -namespace sh -{ - -class TIntermBlock; -class TSymbolTable; - -void RemoveUnreferencedVariables(TIntermBlock *root, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REMOVEUNREFERENCEDVARIABLES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp deleted file mode 100644 index dc3fb7a74e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RewriteDoWhile.cpp: rewrites do-while loops using another equivalent -// construct. - -#include "compiler/translator/RewriteDoWhile.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -// An AST traverser that rewrites loops of the form -// do { -// CODE; -// } while (CONDITION) -// -// to loops of the form -// bool temp = false; -// while (true) { -// if (temp) { -// if (!CONDITION) { -// break; -// } -// } -// temp = true; -// CODE; -// } -// -// The reason we don't use a simpler form, with for example just (temp && !CONDITION) in the -// while condition, is that short-circuit is often badly supported by driver shader compiler. -// The double if has the same effect, but forces shader compilers to behave. -// -// TODO(cwallez) when UnfoldShortCircuitIntoIf handles loops correctly, revisit this as we might -// be able to use while (temp || CONDITION) with temp initially set to true then run -// UnfoldShortCircuitIntoIf -class DoWhileRewriter : public TIntermTraverser -{ - public: - DoWhileRewriter(TSymbolTable *symbolTable) : TIntermTraverser(true, false, false, symbolTable) - { - } - - bool visitBlock(Visit, TIntermBlock *node) override - { - // A well-formed AST can only have do-while inside TIntermBlock. By doing a prefix traversal - // we are able to replace the do-while in the sequence directly as the content of the - // do-while will be traversed later. - - TIntermSequence *statements = node->getSequence(); - - // The statements vector will have new statements inserted when we encounter a do-while, - // which prevents us from using a range-based for loop. Using the usual i++ works, as - // the (two) new statements inserted replace the statement at the current position. - for (size_t i = 0; i < statements->size(); i++) - { - TIntermNode *statement = (*statements)[i]; - TIntermLoop *loop = statement->getAsLoopNode(); - - if (loop == nullptr || loop->getType() != ELoopDoWhile) - { - continue; - } - - // Found a loop to change. - nextTemporaryId(); - - TType boolType = TType(EbtBool); - - // bool temp = false; - TIntermDeclaration *tempDeclaration = nullptr; - { - TConstantUnion *falseConstant = new TConstantUnion(); - falseConstant->setBConst(false); - TIntermTyped *falseValue = new TIntermConstantUnion(falseConstant, boolType); - - tempDeclaration = createTempInitDeclaration(falseValue); - } - - // temp = true; - TIntermBinary *assignTrue = nullptr; - { - TConstantUnion *trueConstant = new TConstantUnion(); - trueConstant->setBConst(true); - TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, boolType); - - assignTrue = createTempAssignment(trueValue); - } - - // if (temp) { - // if (!CONDITION) { - // break; - // } - // } - TIntermIfElse *breakIf = nullptr; - { - TIntermBranch *breakStatement = new TIntermBranch(EOpBreak, nullptr); - - TIntermBlock *breakBlock = new TIntermBlock(); - breakBlock->getSequence()->push_back(breakStatement); - - TIntermUnary *negatedCondition = - new TIntermUnary(EOpLogicalNot, loop->getCondition()); - - TIntermIfElse *innerIf = new TIntermIfElse(negatedCondition, breakBlock, nullptr); - - TIntermBlock *innerIfBlock = new TIntermBlock(); - innerIfBlock->getSequence()->push_back(innerIf); - - breakIf = new TIntermIfElse(createTempSymbol(boolType), innerIfBlock, nullptr); - } - - // Assemble the replacement loops, reusing the do-while loop's body and inserting our - // statements at the front. - TIntermLoop *newLoop = nullptr; - { - TConstantUnion *trueConstant = new TConstantUnion(); - trueConstant->setBConst(true); - TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, boolType); - - TIntermBlock *body = loop->getBody(); - if (body == nullptr) - { - body = new TIntermBlock(); - } - auto sequence = body->getSequence(); - sequence->insert(sequence->begin(), assignTrue); - sequence->insert(sequence->begin(), breakIf); - - newLoop = new TIntermLoop(ELoopWhile, nullptr, trueValue, nullptr, body); - } - - TIntermSequence replacement; - replacement.push_back(tempDeclaration); - replacement.push_back(newLoop); - - node->replaceChildNodeWithMultiple(loop, replacement); - } - return true; - } -}; - -} // anonymous namespace - -void RewriteDoWhile(TIntermNode *root, TSymbolTable *symbolTable) -{ - DoWhileRewriter rewriter(symbolTable); - - root->traverse(&rewriter); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h b/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h deleted file mode 100644 index e83bfc4b56..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RewriteDoWhile.h: rewrite do-while loops as while loops to work around -// driver bugs - -#ifndef COMPILER_TRANSLATOR_REWRITEDOWHILE_H_ -#define COMPILER_TRANSLATOR_REWRITEDOWHILE_H_ - -namespace sh -{ - -class TIntermNode; -class TSymbolTable; - -void RewriteDoWhile(TIntermNode *root, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REWRITEDOWHILE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp deleted file mode 100644 index ed1bfad8a8..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RewriteElseBlocks.cpp: Implementation for tree transform to change -// all if-else blocks to if-if blocks. -// - -#include "compiler/translator/RewriteElseBlocks.h" - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/NodeSearch.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -class ElseBlockRewriter : public TIntermTraverser -{ - public: - ElseBlockRewriter(TSymbolTable *symbolTable); - - protected: - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *aggregate) override; - bool visitBlock(Visit visit, TIntermBlock *block) override; - - private: - TIntermNode *rewriteIfElse(TIntermIfElse *ifElse); - - const TType *mFunctionType; -}; - -ElseBlockRewriter::ElseBlockRewriter(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, true, symbolTable), mFunctionType(nullptr) -{ -} - -bool ElseBlockRewriter::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) -{ - // Store the current function context (see comment below) - mFunctionType = ((visit == PreVisit) ? &node->getFunctionPrototype()->getType() : nullptr); - return true; -} - -bool ElseBlockRewriter::visitBlock(Visit visit, TIntermBlock *node) -{ - if (visit == PostVisit) - { - for (size_t statementIndex = 0; statementIndex != node->getSequence()->size(); - statementIndex++) - { - TIntermNode *statement = (*node->getSequence())[statementIndex]; - TIntermIfElse *ifElse = statement->getAsIfElseNode(); - if (ifElse && ifElse->getFalseBlock() != nullptr) - { - (*node->getSequence())[statementIndex] = rewriteIfElse(ifElse); - } - } - } - return true; -} - -TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse) -{ - ASSERT(ifElse != nullptr); - - nextTemporaryId(); - - TIntermDeclaration *storeCondition = createTempInitDeclaration(ifElse->getCondition()); - - TIntermBlock *falseBlock = nullptr; - - TType boolType(EbtBool, EbpUndefined, EvqTemporary); - - if (ifElse->getFalseBlock()) - { - TIntermBlock *negatedElse = nullptr; - // crbug.com/346463 - // D3D generates error messages claiming a function has no return value, when rewriting - // an if-else clause that returns something non-void in a function. By appending dummy - // returns (that are unreachable) we can silence this compile error. - if (mFunctionType && mFunctionType->getBasicType() != EbtVoid) - { - TIntermNode *returnNode = new TIntermBranch(EOpReturn, CreateZeroNode(*mFunctionType)); - negatedElse = new TIntermBlock(); - negatedElse->appendStatement(returnNode); - } - - TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType); - TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse); - TIntermIfElse *falseIfElse = - new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse); - falseBlock = EnsureBlock(falseIfElse); - } - - TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType); - TIntermIfElse *newIfElse = - new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock); - - TIntermBlock *block = new TIntermBlock(); - block->getSequence()->push_back(storeCondition); - block->getSequence()->push_back(newIfElse); - - return block; -} - -} // anonymous namespace - -void RewriteElseBlocks(TIntermNode *node, TSymbolTable *symbolTable) -{ - ElseBlockRewriter rewriter(symbolTable); - node->traverse(&rewriter); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h deleted file mode 100644 index 2586b5405c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RewriteElseBlocks.h: Prototype for tree transform to change -// all if-else blocks to if-if blocks. -// - -#ifndef COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_ -#define COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_ - -namespace sh -{ - -class TIntermNode; -class TSymbolTable; - -void RewriteElseBlocks(TIntermNode *node, TSymbolTable *symbolTable); -} - -#endif // COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp deleted file mode 100644 index b602e0c923..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Implementation of texelFetchOffset translation issue workaround. -// See header for more info. - -#include "compiler/translator/RewriteTexelFetchOffset.h" - -#include "common/angleutils.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -class Traverser : public TIntermTraverser -{ - public: - static void Apply(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion); - - private: - Traverser(const TSymbolTable &symbolTable, int shaderVersion); - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - void nextIteration(); - - const TSymbolTable *symbolTable; - const int shaderVersion; - bool mFound = false; -}; - -Traverser::Traverser(const TSymbolTable &symbolTable, int shaderVersion) - : TIntermTraverser(true, false, false), symbolTable(&symbolTable), shaderVersion(shaderVersion) -{ -} - -// static -void Traverser::Apply(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion) -{ - Traverser traverser(symbolTable, shaderVersion); - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.mFound) - { - traverser.updateTree(); - } - } while (traverser.mFound); -} - -void Traverser::nextIteration() -{ - mFound = false; -} - -bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (mFound) - { - return false; - } - - // Decide if the node represents the call of texelFetchOffset. - if (node->getOp() != EOpCallBuiltInFunction) - { - return true; - } - - if (node->getFunctionSymbolInfo()->getName() != "texelFetchOffset") - { - return true; - } - - // Potential problem case detected, apply workaround. - const TIntermSequence *sequence = node->getSequence(); - ASSERT(sequence->size() == 4u); - - // Decide if the sampler is a 2DArray sampler. In that case position is ivec3 and offset is - // ivec2. - bool is2DArray = sequence->at(1)->getAsTyped()->getNominalSize() == 3 && - sequence->at(3)->getAsTyped()->getNominalSize() == 2; - - // Create new node that represents the call of function texelFetch. - // Its argument list will be: texelFetch(sampler, Position+offset, lod). - - TIntermSequence *texelFetchArguments = new TIntermSequence(); - - // sampler - texelFetchArguments->push_back(sequence->at(0)); - - // Position - TIntermTyped *texCoordNode = sequence->at(1)->getAsTyped(); - ASSERT(texCoordNode); - - // offset - TIntermTyped *offsetNode = nullptr; - ASSERT(sequence->at(3)->getAsTyped()); - if (is2DArray) - { - // For 2DArray samplers, Position is ivec3 and offset is ivec2; - // So offset must be converted into an ivec3 before being added to Position. - TIntermSequence *constructOffsetIvecArguments = new TIntermSequence(); - constructOffsetIvecArguments->push_back(sequence->at(3)->getAsTyped()); - - TIntermTyped *zeroNode = CreateZeroNode(TType(EbtInt)); - constructOffsetIvecArguments->push_back(zeroNode); - - offsetNode = TIntermAggregate::CreateConstructor(texCoordNode->getType(), - constructOffsetIvecArguments); - offsetNode->setLine(texCoordNode->getLine()); - } - else - { - offsetNode = sequence->at(3)->getAsTyped(); - } - - // Position+offset - TIntermBinary *add = new TIntermBinary(EOpAdd, texCoordNode, offsetNode); - add->setLine(texCoordNode->getLine()); - texelFetchArguments->push_back(add); - - // lod - texelFetchArguments->push_back(sequence->at(2)); - - ASSERT(texelFetchArguments->size() == 3u); - - TIntermTyped *texelFetchNode = CreateBuiltInFunctionCallNode("texelFetch", texelFetchArguments, - *symbolTable, shaderVersion); - texelFetchNode->setLine(node->getLine()); - - // Replace the old node by this new node. - queueReplacement(texelFetchNode, OriginalNode::IS_DROPPED); - mFound = true; - return false; -} - -} // anonymous namespace - -void RewriteTexelFetchOffset(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion) -{ - // texelFetchOffset is only valid in GLSL 3.0 and later. - if (shaderVersion < 300) - return; - - Traverser::Apply(root, symbolTable, shaderVersion); -} - -} // namespace sh
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h b/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h deleted file mode 100644 index 694d709f8e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This mutating tree traversal works around an issue on the translation -// from texelFetchOffset into HLSL function Load on INTEL drivers. It -// works by translating texelFetchOffset into texelFetch: -// -// - From: texelFetchOffset(sampler, Position, lod, offset) -// - To: texelFetch(sampler, Position+offset, lod) -// -// See http://anglebug.com/1469 - -#ifndef COMPILER_TRANSLATOR_REWRITE_TEXELFETCHOFFSET_H_ -#define COMPILER_TRANSLATOR_REWRITE_TEXELFETCHOFFSET_H_ - -class TIntermNode; -class TSymbolTable; - -namespace sh -{ - -void RewriteTexelFetchOffset(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REWRITE_TEXELFETCHOFFSET_H_
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp deleted file mode 100644 index 696a49536c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/RewriteUnaryMinusOperatorFloat.h" - -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class Traverser : public TIntermTraverser -{ - public: - static void Apply(TIntermNode *root); - - private: - Traverser(); - bool visitUnary(Visit visit, TIntermUnary *node) override; - void nextIteration(); - - bool mFound = false; -}; - -// static -void Traverser::Apply(TIntermNode *root) -{ - Traverser traverser; - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.mFound) - { - traverser.updateTree(); - } - } while (traverser.mFound); -} - -Traverser::Traverser() : TIntermTraverser(true, false, false) -{ -} - -void Traverser::nextIteration() -{ - mFound = false; -} - -bool Traverser::visitUnary(Visit visit, TIntermUnary *node) -{ - if (mFound) - { - return false; - } - - // Detect if the current operator is unary minus operator. - if (node->getOp() != EOpNegative) - { - return true; - } - - // Detect if the current operand is a float variable. - TIntermTyped *fValue = node->getOperand(); - if (!fValue->getType().isScalarFloat()) - { - return true; - } - - // 0.0 - float - TIntermTyped *zero = CreateZeroNode(fValue->getType()); - zero->setLine(fValue->getLine()); - TIntermBinary *sub = new TIntermBinary(EOpSub, zero, fValue); - sub->setLine(fValue->getLine()); - - queueReplacement(sub, OriginalNode::IS_DROPPED); - - mFound = true; - return false; -} - -} // anonymous namespace - -void RewriteUnaryMinusOperatorFloat(TIntermNode *root) -{ - Traverser::Apply(root); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h deleted file mode 100644 index ccbfbcbd9e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Rewrite "-float" to "0.0 - float" to work around unary minus operator on float issue on Intel Mac -// OSX 10.11. - -#ifndef COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORFLOAT_H_ -#define COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORFLOAT_H_ - -class TIntermNode; -namespace sh -{ - -void RewriteUnaryMinusOperatorFloat(TIntermNode *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORFLOAT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp deleted file mode 100644 index fe2ef948b4..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Implementation of evaluating unary integer variable bug workaround. -// See header for more info. - -#include "compiler/translator/RewriteUnaryMinusOperatorInt.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class Traverser : public TIntermTraverser -{ - public: - static void Apply(TIntermNode *root); - - private: - Traverser(); - bool visitUnary(Visit visit, TIntermUnary *node) override; - void nextIteration(); - - bool mFound = false; -}; - -// static -void Traverser::Apply(TIntermNode *root) -{ - Traverser traverser; - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.mFound) - { - traverser.updateTree(); - } - } while (traverser.mFound); -} - -Traverser::Traverser() : TIntermTraverser(true, false, false) -{ -} - -void Traverser::nextIteration() -{ - mFound = false; -} - -bool Traverser::visitUnary(Visit visit, TIntermUnary *node) -{ - if (mFound) - { - return false; - } - - // Decide if the current unary operator is unary minus. - if (node->getOp() != EOpNegative) - { - return true; - } - - // Decide if the current operand is an integer variable. - TIntermTyped *opr = node->getOperand(); - if (!opr->getType().isScalarInt()) - { - return true; - } - - // Potential problem case detected, apply workaround: -(int) -> ~(int) + 1. - // ~(int) - TIntermUnary *bitwiseNot = new TIntermUnary(EOpBitwiseNot, opr); - bitwiseNot->setLine(opr->getLine()); - - // Constant 1 (or 1u) - TConstantUnion *one = new TConstantUnion(); - if (opr->getType().getBasicType() == EbtInt) - { - one->setIConst(1); - } - else - { - one->setUConst(1u); - } - TIntermConstantUnion *oneNode = new TIntermConstantUnion(one, opr->getType()); - oneNode->getTypePointer()->setQualifier(EvqConst); - oneNode->setLine(opr->getLine()); - - // ~(int) + 1 - TIntermBinary *add = new TIntermBinary(EOpAdd, bitwiseNot, oneNode); - add->setLine(opr->getLine()); - - queueReplacement(add, OriginalNode::IS_DROPPED); - - mFound = true; - return false; -} - -} // anonymous namespace - -void RewriteUnaryMinusOperatorInt(TIntermNode *root) -{ - Traverser::Apply(root); -} - -} // namespace sh
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h deleted file mode 100644 index 50f0c442a7..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This mutating tree traversal works around a bug on evaluating unary -// integer variable on Intel D3D driver. It works by rewriting -(int) to -// ~(int) + 1 when evaluating unary integer variables. - -#ifndef COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_ -#define COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_ - -class TIntermNode; -namespace sh -{ - -void RewriteUnaryMinusOperatorInt(TIntermNode *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp b/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp deleted file mode 100644 index 3c4209c539..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RunAtTheEndOfShader.cpp: Add code to be run at the end of the shader. In case main() contains a -// return statement, this is done by replacing the main() function with another function that calls -// the old main, like this: -// -// void main() { body } -// => -// void main0() { body } -// void main() -// { -// main0(); -// codeToRun -// } -// -// This way the code will get run even if the return statement inside main is executed. -// - -#include "compiler/translator/RunAtTheEndOfShader.h" - -#include "compiler/translator/FindMain.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -namespace -{ - -class ContainsReturnTraverser : public TIntermTraverser -{ - public: - ContainsReturnTraverser() : TIntermTraverser(true, false, false), mContainsReturn(false) {} - - bool visitBranch(Visit visit, TIntermBranch *node) override - { - if (node->getFlowOp() == EOpReturn) - { - mContainsReturn = true; - } - return false; - } - - bool containsReturn() { return mContainsReturn; } - - private: - bool mContainsReturn; -}; - -bool ContainsReturn(TIntermNode *node) -{ - ContainsReturnTraverser traverser; - node->traverse(&traverser); - return traverser.containsReturn(); -} - -void WrapMainAndAppend(TIntermBlock *root, - TIntermFunctionDefinition *main, - TIntermNode *codeToRun, - TSymbolTable *symbolTable) -{ - // Replace main() with main0() with the same body. - TSymbolUniqueId oldMainId(symbolTable); - std::stringstream oldMainName; - oldMainName << "main" << oldMainId.get(); - TIntermFunctionDefinition *oldMain = CreateInternalFunctionDefinitionNode( - TType(EbtVoid), oldMainName.str().c_str(), main->getBody(), oldMainId); - - bool replaced = root->replaceChildNode(main, oldMain); - ASSERT(replaced); - - // void main() - TIntermFunctionPrototype *newMainProto = new TIntermFunctionPrototype( - TType(EbtVoid), main->getFunctionPrototype()->getFunctionSymbolInfo()->getId()); - newMainProto->getFunctionSymbolInfo()->setName("main"); - - // { - // main0(); - // codeToRun - // } - TIntermBlock *newMainBody = new TIntermBlock(); - TIntermAggregate *oldMainCall = CreateInternalFunctionCallNode( - TType(EbtVoid), oldMainName.str().c_str(), oldMainId, new TIntermSequence()); - newMainBody->appendStatement(oldMainCall); - newMainBody->appendStatement(codeToRun); - - // Add the new main() to the root node. - TIntermFunctionDefinition *newMain = new TIntermFunctionDefinition(newMainProto, newMainBody); - root->appendStatement(newMain); -} - -} // anonymous namespace - -void RunAtTheEndOfShader(TIntermBlock *root, TIntermNode *codeToRun, TSymbolTable *symbolTable) -{ - TIntermFunctionDefinition *main = FindMain(root); - if (!ContainsReturn(main)) - { - main->getBody()->appendStatement(codeToRun); - return; - } - - WrapMainAndAppend(root, main, codeToRun, symbolTable); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h b/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h deleted file mode 100644 index ed94c28dae..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// RunAtTheEndOfShader.h: Add code to be run at the end of the shader. -// - -#ifndef COMPILER_TRANSLATOR_RUNATTHEENDOFSHADER_H_ -#define COMPILER_TRANSLATOR_RUNATTHEENDOFSHADER_H_ - -namespace sh -{ - -class TIntermBlock; -class TIntermNode; -class TSymbolTable; - -void RunAtTheEndOfShader(TIntermBlock *root, TIntermNode *codeToRun, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_RUNATTHEENDOFSHADER_H_
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp deleted file mode 100644 index 746c16e2e6..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp +++ /dev/null @@ -1,238 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Scalarize vector and matrix constructor args, so that vectors built from components don't have -// matrix arguments, and matrices built from components don't have vector arguments. This avoids -// driver bugs around vector and matrix constructors. -// - -#include "common/debug.h" -#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h" - -#include <algorithm> - -#include "angle_gl.h" -#include "common/angleutils.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -bool ContainsMatrixNode(const TIntermSequence &sequence) -{ - for (size_t ii = 0; ii < sequence.size(); ++ii) - { - TIntermTyped *node = sequence[ii]->getAsTyped(); - if (node && node->isMatrix()) - return true; - } - return false; -} - -bool ContainsVectorNode(const TIntermSequence &sequence) -{ - for (size_t ii = 0; ii < sequence.size(); ++ii) - { - TIntermTyped *node = sequence[ii]->getAsTyped(); - if (node && node->isVector()) - return true; - } - return false; -} - -TIntermBinary *ConstructVectorIndexBinaryNode(TIntermSymbol *symbolNode, int index) -{ - return new TIntermBinary(EOpIndexDirect, symbolNode, CreateIndexNode(index)); -} - -TIntermBinary *ConstructMatrixIndexBinaryNode(TIntermSymbol *symbolNode, int colIndex, int rowIndex) -{ - TIntermBinary *colVectorNode = ConstructVectorIndexBinaryNode(symbolNode, colIndex); - - return new TIntermBinary(EOpIndexDirect, colVectorNode, CreateIndexNode(rowIndex)); -} - -class ScalarizeArgsTraverser : public TIntermTraverser -{ - public: - ScalarizeArgsTraverser(sh::GLenum shaderType, - bool fragmentPrecisionHigh, - TSymbolTable *symbolTable) - : TIntermTraverser(true, false, false, symbolTable), - mShaderType(shaderType), - mFragmentPrecisionHigh(fragmentPrecisionHigh) - { - } - - protected: - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitBlock(Visit visit, TIntermBlock *node) override; - - private: - void scalarizeArgs(TIntermAggregate *aggregate, bool scalarizeVector, bool scalarizeMatrix); - - // If we have the following code: - // mat4 m(0); - // vec4 v(1, m); - // We will rewrite to: - // mat4 m(0); - // mat4 s0 = m; - // vec4 v(1, s0[0][0], s0[0][1], s0[0][2]); - // This function is to create nodes for "mat4 s0 = m;" and insert it to the code sequence. This - // way the possible side effects of the constructor argument will only be evaluated once. - void createTempVariable(TIntermTyped *original); - - std::vector<TIntermSequence> mBlockStack; - - sh::GLenum mShaderType; - bool mFragmentPrecisionHigh; -}; - -bool ScalarizeArgsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (visit == PreVisit && node->getOp() == EOpConstruct) - { - if (node->getType().isVector() && ContainsMatrixNode(*(node->getSequence()))) - scalarizeArgs(node, false, true); - else if (node->getType().isMatrix() && ContainsVectorNode(*(node->getSequence()))) - scalarizeArgs(node, true, false); - } - return true; -} - -bool ScalarizeArgsTraverser::visitBlock(Visit visit, TIntermBlock *node) -{ - mBlockStack.push_back(TIntermSequence()); - { - for (TIntermNode *child : *node->getSequence()) - { - ASSERT(child != nullptr); - child->traverse(this); - mBlockStack.back().push_back(child); - } - } - if (mBlockStack.back().size() > node->getSequence()->size()) - { - node->getSequence()->clear(); - *(node->getSequence()) = mBlockStack.back(); - } - mBlockStack.pop_back(); - return false; -} - -void ScalarizeArgsTraverser::scalarizeArgs(TIntermAggregate *aggregate, - bool scalarizeVector, - bool scalarizeMatrix) -{ - ASSERT(aggregate); - ASSERT(!aggregate->isArray()); - int size = static_cast<int>(aggregate->getType().getObjectSize()); - TIntermSequence *sequence = aggregate->getSequence(); - TIntermSequence original(*sequence); - sequence->clear(); - for (size_t ii = 0; ii < original.size(); ++ii) - { - ASSERT(size > 0); - TIntermTyped *node = original[ii]->getAsTyped(); - ASSERT(node); - createTempVariable(node); - if (node->isScalar()) - { - sequence->push_back(createTempSymbol(node->getType())); - size--; - } - else if (node->isVector()) - { - if (scalarizeVector) - { - int repeat = std::min(size, node->getNominalSize()); - size -= repeat; - for (int index = 0; index < repeat; ++index) - { - TIntermSymbol *symbolNode = createTempSymbol(node->getType()); - TIntermBinary *newNode = ConstructVectorIndexBinaryNode(symbolNode, index); - sequence->push_back(newNode); - } - } - else - { - TIntermSymbol *symbolNode = createTempSymbol(node->getType()); - sequence->push_back(symbolNode); - size -= node->getNominalSize(); - } - } - else - { - ASSERT(node->isMatrix()); - if (scalarizeMatrix) - { - int colIndex = 0, rowIndex = 0; - int repeat = std::min(size, node->getCols() * node->getRows()); - size -= repeat; - while (repeat > 0) - { - TIntermSymbol *symbolNode = createTempSymbol(node->getType()); - TIntermBinary *newNode = - ConstructMatrixIndexBinaryNode(symbolNode, colIndex, rowIndex); - sequence->push_back(newNode); - rowIndex++; - if (rowIndex >= node->getRows()) - { - rowIndex = 0; - colIndex++; - } - repeat--; - } - } - else - { - TIntermSymbol *symbolNode = createTempSymbol(node->getType()); - sequence->push_back(symbolNode); - size -= node->getCols() * node->getRows(); - } - } - } -} - -void ScalarizeArgsTraverser::createTempVariable(TIntermTyped *original) -{ - ASSERT(original); - nextTemporaryId(); - TIntermDeclaration *decl = createTempInitDeclaration(original); - - TType type = original->getType(); - if (mShaderType == GL_FRAGMENT_SHADER && type.getBasicType() == EbtFloat && - type.getPrecision() == EbpUndefined) - { - // We use the highest available precision for the temporary variable - // to avoid computing the actual precision using the rules defined - // in GLSL ES 1.0 Section 4.5.2. - TIntermBinary *init = decl->getSequence()->at(0)->getAsBinaryNode(); - init->getTypePointer()->setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium); - init->getLeft()->getTypePointer()->setPrecision(mFragmentPrecisionHigh ? EbpHigh - : EbpMedium); - } - - ASSERT(mBlockStack.size() > 0); - TIntermSequence &sequence = mBlockStack.back(); - sequence.push_back(decl); -} - -} // namespace anonymous - -void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root, - sh::GLenum shaderType, - bool fragmentPrecisionHigh, - TSymbolTable *symbolTable) -{ - ScalarizeArgsTraverser scalarizer(shaderType, fragmentPrecisionHigh, symbolTable); - root->traverse(&scalarizer); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h deleted file mode 100644 index b8f782d1ec..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Scalarize vector and matrix constructor args, so that vectors built from components don't have -// matrix arguments, and matrices built from components don't have vector arguments. This avoids -// driver bugs around vector and matrix constructors. -// - -#ifndef COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ -#define COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ - -#include "GLSLANG/ShaderLang.h" - -namespace sh -{ -class TIntermBlock; -class TSymbolTable; - -void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root, - sh::GLenum shaderType, - bool fragmentPrecisionHigh, - TSymbolTable *symbolTable); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp deleted file mode 100644 index 34c644d028..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SearchSymbol is an AST traverser to detect the use of a given symbol name -// - -#include "compiler/translator/SearchSymbol.h" - -#include "compiler/translator/InfoSink.h" - -namespace sh -{ -SearchSymbol::SearchSymbol(const TString &symbol) - : TIntermTraverser(true, false, false), mSymbol(symbol) -{ - match = false; -} - -void SearchSymbol::traverse(TIntermNode *node) -{ - node->traverse(this); -} - -void SearchSymbol::visitSymbol(TIntermSymbol *symbolNode) -{ - if (symbolNode->getSymbol() == mSymbol) - { - match = true; - } -} - -bool SearchSymbol::foundMatch() const -{ - return match; -} -} diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h deleted file mode 100644 index b8379e041f..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SearchSymbol is an AST traverser to detect the use of a given symbol name -// - -#ifndef COMPILER_TRANSLATOR_SEARCHSYMBOL_H_ -#define COMPILER_TRANSLATOR_SEARCHSYMBOL_H_ - -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/ParseContext.h" - -namespace sh -{ -class SearchSymbol : public TIntermTraverser -{ - public: - SearchSymbol(const TString &symbol); - - void traverse(TIntermNode *node); - void visitSymbol(TIntermSymbol *symbolNode) override; - - bool foundMatch() const; - - protected: - const TString &mSymbol; - bool match; -}; -} - -#endif // COMPILER_TRANSLATOR_SEARCHSYMBOL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp b/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp deleted file mode 100644 index fe25823e38..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The SeparateArrayInitialization function splits each array initialization into a declaration and -// an assignment. -// Example: -// type[n] a = initializer; -// will effectively become -// type[n] a; -// a = initializer; -// -// Note that if the array is declared as const, the initialization may still be split, making the -// AST technically invalid. Because of that this transformation should only be used when subsequent -// stages don't care about const qualifiers. However, the initialization will not be split if the -// initializer can be written as a HLSL literal. - -#include "compiler/translator/SeparateArrayInitialization.h" - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/OutputHLSL.h" - -namespace sh -{ - -namespace -{ - -class SeparateArrayInitTraverser : private TIntermTraverser -{ - public: - static void apply(TIntermNode *root); - - private: - SeparateArrayInitTraverser(); - bool visitDeclaration(Visit, TIntermDeclaration *node) override; -}; - -void SeparateArrayInitTraverser::apply(TIntermNode *root) -{ - SeparateArrayInitTraverser separateInit; - root->traverse(&separateInit); - separateInit.updateTree(); -} - -SeparateArrayInitTraverser::SeparateArrayInitTraverser() : TIntermTraverser(true, false, false) -{ -} - -bool SeparateArrayInitTraverser::visitDeclaration(Visit, TIntermDeclaration *node) -{ - TIntermSequence *sequence = node->getSequence(); - TIntermBinary *initNode = sequence->back()->getAsBinaryNode(); - if (initNode != nullptr && initNode->getOp() == EOpInitialize) - { - TIntermTyped *initializer = initNode->getRight(); - if (initializer->isArray() && !sh::OutputHLSL::canWriteAsHLSLLiteral(initializer)) - { - // We rely on that array declarations have been isolated to single declarations. - ASSERT(sequence->size() == 1); - TIntermTyped *symbol = initNode->getLeft(); - TIntermBlock *parentBlock = getParentNode()->getAsBlock(); - ASSERT(parentBlock != nullptr); - - TIntermSequence replacements; - - TIntermDeclaration *replacementDeclaration = new TIntermDeclaration(); - replacementDeclaration->appendDeclarator(symbol); - replacementDeclaration->setLine(symbol->getLine()); - replacements.push_back(replacementDeclaration); - - TIntermBinary *replacementAssignment = - new TIntermBinary(EOpAssign, symbol, initializer); - replacementAssignment->setLine(symbol->getLine()); - replacements.push_back(replacementAssignment); - - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(parentBlock, node, replacements)); - } - } - return false; -} - -} // namespace - -void SeparateArrayInitialization(TIntermNode *root) -{ - SeparateArrayInitTraverser::apply(root); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h b/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h deleted file mode 100644 index 3a9bb55dd1..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The SeparateArrayInitialization function splits each array initialization into a declaration and -// an assignment. -// Example: -// type[n] a = initializer; -// will effectively become -// type[n] a; -// a = initializer; -// -// Note that if the array is declared as const, the initialization may still be split, making the -// AST technically invalid. Because of that this transformation should only be used when subsequent -// stages don't care about const qualifiers. However, the initialization will not be split if the -// initializer can be written as a HLSL literal. - -#ifndef COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_ -#define COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_ - -namespace sh -{ -class TIntermNode; - -void SeparateArrayInitialization(TIntermNode *root); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp b/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp deleted file mode 100644 index 9a066075c0..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The SeparateDeclarations function processes declarations, so that in the end each declaration -// contains only one declarator. -// This is useful as an intermediate step when initialization needs to be separated from -// declaration, or when things need to be unfolded out of the initializer. -// Example: -// int a[1] = int[1](1), b[1] = int[1](2); -// gets transformed when run through this class into the AST equivalent of: -// int a[1] = int[1](1); -// int b[1] = int[1](2); - -#include "compiler/translator/SeparateDeclarations.h" - -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class SeparateDeclarationsTraverser : private TIntermTraverser -{ - public: - static void apply(TIntermNode *root); - - private: - SeparateDeclarationsTraverser(); - bool visitDeclaration(Visit, TIntermDeclaration *node) override; -}; - -void SeparateDeclarationsTraverser::apply(TIntermNode *root) -{ - SeparateDeclarationsTraverser separateDecl; - root->traverse(&separateDecl); - separateDecl.updateTree(); -} - -SeparateDeclarationsTraverser::SeparateDeclarationsTraverser() - : TIntermTraverser(true, false, false) -{ -} - -bool SeparateDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node) -{ - TIntermSequence *sequence = node->getSequence(); - if (sequence->size() > 1) - { - TIntermBlock *parentBlock = getParentNode()->getAsBlock(); - ASSERT(parentBlock != nullptr); - - TIntermSequence replacementDeclarations; - for (size_t ii = 0; ii < sequence->size(); ++ii) - { - TIntermDeclaration *replacementDeclaration = new TIntermDeclaration(); - - replacementDeclaration->appendDeclarator(sequence->at(ii)->getAsTyped()); - replacementDeclaration->setLine(sequence->at(ii)->getLine()); - replacementDeclarations.push_back(replacementDeclaration); - } - - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(parentBlock, node, replacementDeclarations)); - } - return false; -} - -} // namespace - -void SeparateDeclarations(TIntermNode *root) -{ - SeparateDeclarationsTraverser::apply(root); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h b/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h deleted file mode 100644 index 8142faea1c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The SeparateDeclarations function processes declarations, so that in the end each declaration -// contains only one declarator. -// This is useful as an intermediate step when initialization needs to be separated from -// declaration, or when things need to be unfolded out of the initializer. -// Example: -// int a[1] = int[1](1), b[1] = int[1](2); -// gets transformed when run through this class into the AST equivalent of: -// int a[1] = int[1](1); -// int b[1] = int[1](2); - -#ifndef COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_ -#define COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_ - -namespace sh -{ -class TIntermNode; - -void SeparateDeclarations(TIntermNode *root); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp b/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp deleted file mode 100644 index 01d627937c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SeparateExpressionsReturningArrays splits array-returning expressions that are not array names -// from more complex expressions, assigning them to a temporary variable a#. -// Examples where a, b and c are all arrays: -// (a = b) == (a = c) is split into a = b; type[n] a1 = a; a = c; type[n] a2 = a; a1 == a2; -// type d = type[n](...)[i]; is split into type[n] a1 = type[n](...); type d = a1[i]; - -#include "compiler/translator/SeparateExpressionsReturningArrays.h" - -#include "compiler/translator/IntermNodePatternMatcher.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -// Traverser that separates one array expression into a statement at a time. -class SeparateExpressionsTraverser : public TIntermTraverser -{ - public: - SeparateExpressionsTraverser(TSymbolTable *symbolTable); - - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - - void nextIteration(); - bool foundArrayExpression() const { return mFoundArrayExpression; } - - protected: - // Marked to true once an operation that needs to be hoisted out of the expression has been - // found. After that, no more AST updates are performed on that traversal. - bool mFoundArrayExpression; - - IntermNodePatternMatcher mPatternToSeparateMatcher; -}; - -SeparateExpressionsTraverser::SeparateExpressionsTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, false, symbolTable), - mFoundArrayExpression(false), - mPatternToSeparateMatcher(IntermNodePatternMatcher::kExpressionReturningArray) -{ -} - -// Performs a shallow copy of an assignment node. -// These shallow copies are useful when a node gets inserted into an aggregate node -// and also needs to be replaced in its original location by a different node. -TIntermBinary *CopyAssignmentNode(TIntermBinary *node) -{ - return new TIntermBinary(node->getOp(), node->getLeft(), node->getRight()); -} - -bool SeparateExpressionsTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - if (mFoundArrayExpression) - return false; - - // Return if the expression is not an array or if we're not inside a complex expression. - if (!mPatternToSeparateMatcher.match(node, getParentNode())) - return true; - - ASSERT(node->getOp() == EOpAssign); - - mFoundArrayExpression = true; - - TIntermSequence insertions; - insertions.push_back(CopyAssignmentNode(node)); - // TODO(oetuaho): In some cases it would be more optimal to not add the temporary node, but just - // use the original target of the assignment. Care must be taken so that this doesn't happen - // when the same array symbol is a target of assignment more than once in one expression. - insertions.push_back(createTempInitDeclaration(node->getLeft())); - insertStatementsInParentBlock(insertions); - - queueReplacement(createTempSymbol(node->getType()), OriginalNode::IS_DROPPED); - - return false; -} - -bool SeparateExpressionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (mFoundArrayExpression) - return false; // No need to traverse further - - if (!mPatternToSeparateMatcher.match(node, getParentNode())) - return true; - - ASSERT(node->isConstructor() || node->getOp() == EOpCallFunctionInAST); - - mFoundArrayExpression = true; - - TIntermSequence insertions; - insertions.push_back(createTempInitDeclaration(node->shallowCopy())); - insertStatementsInParentBlock(insertions); - - queueReplacement(createTempSymbol(node->getType()), OriginalNode::IS_DROPPED); - - return false; -} - -void SeparateExpressionsTraverser::nextIteration() -{ - mFoundArrayExpression = false; - nextTemporaryId(); -} - -} // namespace - -void SeparateExpressionsReturningArrays(TIntermNode *root, TSymbolTable *symbolTable) -{ - SeparateExpressionsTraverser traverser(symbolTable); - // Separate one expression at a time, and reset the traverser between iterations. - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.foundArrayExpression()) - traverser.updateTree(); - } while (traverser.foundArrayExpression()); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h b/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h deleted file mode 100644 index f8eb438748..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SeparateExpressionsReturningArrays splits array-returning expressions that are not array names -// from more complex expressions, assigning them to a temporary variable a#. -// Examples where a, b and c are all arrays: -// (a = b) == (a = c) is split into a = b; type[n] a1 = a; a = c; type[n] a2 = a; a1 == a2; -// type d = type[n](...)[i]; is split into type[n] a1 = type[n](...); type d = a1[i]; - -#ifndef COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_ -#define COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_ - -namespace sh -{ -class TIntermNode; -class TSymbolTable; - -void SeparateExpressionsReturningArrays(TIntermNode *root, TSymbolTable *symbolTable); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Severity.h b/src/3rdparty/angle/src/compiler/translator/Severity.h deleted file mode 100644 index 47808a16a7..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Severity.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_SEVERITY_H_ -#define COMPILER_TRANSLATOR_SEVERITY_H_ - -namespace sh -{ - -// Severity is used to classify info log messages. -enum Severity -{ - SH_WARNING, - SH_ERROR -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SEVERITY_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp deleted file mode 100644 index eeb13f2ec0..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp +++ /dev/null @@ -1,578 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// Implement the top-level of interface to the compiler, -// as defined in ShaderLang.h -// - -#include "GLSLANG/ShaderLang.h" - -#include "compiler/translator/Compiler.h" -#include "compiler/translator/InitializeDll.h" -#include "compiler/translator/length_limits.h" -#ifdef ANGLE_ENABLE_HLSL -#include "compiler/translator/TranslatorHLSL.h" -#endif // ANGLE_ENABLE_HLSL -#include "compiler/translator/VariablePacker.h" -#include "angle_gl.h" - -namespace sh -{ - -namespace -{ - -bool isInitialized = false; - -// -// This is the platform independent interface between an OGL driver -// and the shading language compiler. -// - -template <typename VarT> -const std::vector<VarT> *GetVariableList(const TCompiler *compiler); - -template <> -const std::vector<Uniform> *GetVariableList(const TCompiler *compiler) -{ - return &compiler->getUniforms(); -} - -template <> -const std::vector<Varying> *GetVariableList(const TCompiler *compiler) -{ - switch (compiler->getShaderType()) - { - case GL_VERTEX_SHADER: - return &compiler->getOutputVaryings(); - case GL_FRAGMENT_SHADER: - return &compiler->getInputVaryings(); - case GL_COMPUTE_SHADER: - ASSERT(compiler->getOutputVaryings().empty() && compiler->getInputVaryings().empty()); - return &compiler->getOutputVaryings(); - // Since geometry shaders have both input and output varyings, we shouldn't call GetVaryings - // on a geometry shader. - default: - return nullptr; - } -} - -template <> -const std::vector<Attribute> *GetVariableList(const TCompiler *compiler) -{ - return &compiler->getAttributes(); -} - -template <> -const std::vector<OutputVariable> *GetVariableList(const TCompiler *compiler) -{ - return &compiler->getOutputVariables(); -} - -template <> -const std::vector<InterfaceBlock> *GetVariableList(const TCompiler *compiler) -{ - return &compiler->getInterfaceBlocks(); -} - -TCompiler *GetCompilerFromHandle(ShHandle handle) -{ - if (!handle) - { - return nullptr; - } - - TShHandleBase *base = static_cast<TShHandleBase *>(handle); - return base->getAsCompiler(); -} - -template <typename VarT> -const std::vector<VarT> *GetShaderVariables(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - if (!compiler) - { - return nullptr; - } - - return GetVariableList<VarT>(compiler); -} - -#ifdef ANGLE_ENABLE_HLSL -TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle) -{ - if (!handle) - return nullptr; - TShHandleBase *base = static_cast<TShHandleBase *>(handle); - return base->getAsTranslatorHLSL(); -} -#endif // ANGLE_ENABLE_HLSL - -GLenum GetGeometryShaderPrimitiveTypeEnum(sh::TLayoutPrimitiveType primitiveType) -{ - switch (primitiveType) - { - case EptPoints: - return GL_POINTS; - case EptLines: - return GL_LINES; - case EptLinesAdjacency: - return GL_LINES_ADJACENCY_EXT; - case EptTriangles: - return GL_TRIANGLES; - case EptTrianglesAdjacency: - return GL_TRIANGLES_ADJACENCY_EXT; - - case EptLineStrip: - return GL_LINE_STRIP; - case EptTriangleStrip: - return GL_TRIANGLE_STRIP; - - case EptUndefined: - return GL_INVALID_VALUE; - - default: - UNREACHABLE(); - return GL_INVALID_VALUE; - } -} - -} // anonymous namespace - -// -// Driver must call this first, once, before doing any other compiler operations. -// Subsequent calls to this function are no-op. -// -bool Initialize() -{ - if (!isInitialized) - { - isInitialized = InitProcess(); - } - return isInitialized; -} - -// -// Cleanup symbol tables -// -bool Finalize() -{ - if (isInitialized) - { - DetachProcess(); - isInitialized = false; - } - return true; -} - -// -// Initialize built-in resources with minimum expected values. -// -void InitBuiltInResources(ShBuiltInResources *resources) -{ - // Make comparable. - memset(resources, 0, sizeof(*resources)); - - // Constants. - resources->MaxVertexAttribs = 8; - resources->MaxVertexUniformVectors = 128; - resources->MaxVaryingVectors = 8; - resources->MaxVertexTextureImageUnits = 0; - resources->MaxCombinedTextureImageUnits = 8; - resources->MaxTextureImageUnits = 8; - resources->MaxFragmentUniformVectors = 16; - resources->MaxDrawBuffers = 1; - - // Extensions. - resources->OES_standard_derivatives = 0; - resources->OES_EGL_image_external = 0; - resources->OES_EGL_image_external_essl3 = 0; - resources->NV_EGL_stream_consumer_external = 0; - resources->ARB_texture_rectangle = 0; - resources->EXT_blend_func_extended = 0; - resources->EXT_draw_buffers = 0; - resources->EXT_frag_depth = 0; - resources->EXT_shader_texture_lod = 0; - resources->WEBGL_debug_shader_precision = 0; - resources->EXT_shader_framebuffer_fetch = 0; - resources->NV_shader_framebuffer_fetch = 0; - resources->ARM_shader_framebuffer_fetch = 0; - resources->OVR_multiview = 0; - resources->EXT_YUV_target = 0; - resources->OES_geometry_shader = 0; - - resources->NV_draw_buffers = 0; - - // Disable highp precision in fragment shader by default. - resources->FragmentPrecisionHigh = 0; - - // GLSL ES 3.0 constants. - resources->MaxVertexOutputVectors = 16; - resources->MaxFragmentInputVectors = 15; - resources->MinProgramTexelOffset = -8; - resources->MaxProgramTexelOffset = 7; - - // Extensions constants. - resources->MaxDualSourceDrawBuffers = 0; - - resources->MaxViewsOVR = 4; - - // Disable name hashing by default. - resources->HashFunction = nullptr; - - resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC; - - resources->MaxExpressionComplexity = 256; - resources->MaxCallStackDepth = 256; - resources->MaxFunctionParameters = 1024; - - // ES 3.1 Revision 4, 7.2 Built-in Constants - - // ES 3.1, Revision 4, 8.13 Texture minification - // "The value of MIN_PROGRAM_TEXTURE_GATHER_OFFSET must be less than or equal to the value of - // MIN_PROGRAM_TEXEL_OFFSET. The value of MAX_PROGRAM_TEXTURE_GATHER_OFFSET must be greater than - // or equal to the value of MAX_PROGRAM_TEXEL_OFFSET" - resources->MinProgramTextureGatherOffset = -8; - resources->MaxProgramTextureGatherOffset = 7; - - resources->MaxImageUnits = 4; - resources->MaxVertexImageUniforms = 0; - resources->MaxFragmentImageUniforms = 0; - resources->MaxComputeImageUniforms = 4; - resources->MaxCombinedImageUniforms = 4; - - resources->MaxUniformLocations = 1024; - - resources->MaxCombinedShaderOutputResources = 4; - - resources->MaxComputeWorkGroupCount[0] = 65535; - resources->MaxComputeWorkGroupCount[1] = 65535; - resources->MaxComputeWorkGroupCount[2] = 65535; - resources->MaxComputeWorkGroupSize[0] = 128; - resources->MaxComputeWorkGroupSize[1] = 128; - resources->MaxComputeWorkGroupSize[2] = 64; - resources->MaxComputeUniformComponents = 512; - resources->MaxComputeTextureImageUnits = 16; - - resources->MaxComputeAtomicCounters = 8; - resources->MaxComputeAtomicCounterBuffers = 1; - - resources->MaxVertexAtomicCounters = 0; - resources->MaxFragmentAtomicCounters = 0; - resources->MaxCombinedAtomicCounters = 8; - resources->MaxAtomicCounterBindings = 1; - - resources->MaxVertexAtomicCounterBuffers = 0; - resources->MaxFragmentAtomicCounterBuffers = 0; - resources->MaxCombinedAtomicCounterBuffers = 1; - resources->MaxAtomicCounterBufferSize = 32; - - resources->MaxUniformBufferBindings = 32; - resources->MaxShaderStorageBufferBindings = 4; - - resources->MaxGeometryUniformComponents = 1024; - resources->MaxGeometryUniformBlocks = 12; - resources->MaxGeometryInputComponents = 64; - resources->MaxGeometryOutputComponents = 64; - resources->MaxGeometryOutputVertices = 256; - resources->MaxGeometryTotalOutputComponents = 1024; - resources->MaxGeometryTextureImageUnits = 16; - resources->MaxGeometryAtomicCounterBuffers = 0; - resources->MaxGeometryAtomicCounters = 0; - resources->MaxGeometryShaderStorageBlocks = 0; - resources->MaxGeometryShaderInvocations = 32; - resources->MaxGeometryImageUniforms = 0; -} - -// -// Driver calls these to create and destroy compiler objects. -// -ShHandle ConstructCompiler(sh::GLenum type, - ShShaderSpec spec, - ShShaderOutput output, - const ShBuiltInResources *resources) -{ - TShHandleBase *base = static_cast<TShHandleBase *>(ConstructCompiler(type, spec, output)); - if (base == nullptr) - { - return 0; - } - - TCompiler *compiler = base->getAsCompiler(); - if (compiler == nullptr) - { - return 0; - } - - // Generate built-in symbol table. - if (!compiler->Init(*resources)) - { - Destruct(base); - return 0; - } - - return reinterpret_cast<void *>(base); -} - -void Destruct(ShHandle handle) -{ - if (handle == 0) - return; - - TShHandleBase *base = static_cast<TShHandleBase *>(handle); - - if (base->getAsCompiler()) - DeleteCompiler(base->getAsCompiler()); -} - -const std::string &GetBuiltInResourcesString(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - return compiler->getBuiltInResourcesString(); -} - -// -// Do an actual compile on the given strings. The result is left -// in the given compile object. -// -// Return: The return value of ShCompile is really boolean, indicating -// success or failure. -// -bool Compile(const ShHandle handle, - const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptions) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - - return compiler->compile(shaderStrings, numStrings, compileOptions); -} - -void ClearResults(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - compiler->clearResults(); -} - -int GetShaderVersion(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - return compiler->getShaderVersion(); -} - -ShShaderOutput GetShaderOutputType(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - return compiler->getOutputType(); -} - -// -// Return any compiler log of messages for the application. -// -const std::string &GetInfoLog(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - - TInfoSink &infoSink = compiler->getInfoSink(); - return infoSink.info.str(); -} - -// -// Return any object code. -// -const std::string &GetObjectCode(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - - TInfoSink &infoSink = compiler->getInfoSink(); - return infoSink.obj.str(); -} - -const std::map<std::string, std::string> *GetNameHashingMap(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - ASSERT(compiler); - return &(compiler->getNameMap()); -} - -const std::vector<Uniform> *GetUniforms(const ShHandle handle) -{ - return GetShaderVariables<Uniform>(handle); -} - -const std::vector<Varying> *GetInputVaryings(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - if (compiler == nullptr) - { - return nullptr; - } - return &compiler->getInputVaryings(); -} - -const std::vector<Varying> *GetOutputVaryings(const ShHandle handle) -{ - TCompiler *compiler = GetCompilerFromHandle(handle); - if (compiler == nullptr) - { - return nullptr; - } - return &compiler->getOutputVaryings(); -} - -const std::vector<Varying> *GetVaryings(const ShHandle handle) -{ - return GetShaderVariables<Varying>(handle); -} - -const std::vector<Attribute> *GetAttributes(const ShHandle handle) -{ - return GetShaderVariables<Attribute>(handle); -} - -const std::vector<OutputVariable> *GetOutputVariables(const ShHandle handle) -{ - return GetShaderVariables<OutputVariable>(handle); -} - -const std::vector<InterfaceBlock> *GetInterfaceBlocks(const ShHandle handle) -{ - return GetShaderVariables<InterfaceBlock>(handle); -} - -const std::vector<InterfaceBlock> *GetUniformBlocks(const ShHandle handle) -{ - ASSERT(handle); - TShHandleBase *base = static_cast<TShHandleBase *>(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return &compiler->getUniformBlocks(); -} - -const std::vector<InterfaceBlock> *GetShaderStorageBlocks(const ShHandle handle) -{ - ASSERT(handle); - TShHandleBase *base = static_cast<TShHandleBase *>(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return &compiler->getShaderStorageBlocks(); -} - -WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle) -{ - ASSERT(handle); - - TShHandleBase *base = static_cast<TShHandleBase *>(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return compiler->getComputeShaderLocalSize(); -} - -int GetVertexShaderNumViews(const ShHandle handle) -{ - ASSERT(handle); - TShHandleBase *base = static_cast<TShHandleBase *>(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return compiler->getNumViews(); -} - -bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector<ShaderVariable> &variables) -{ - return CheckVariablesInPackingLimits(maxVectors, variables); -} - -bool GetUniformBlockRegister(const ShHandle handle, - const std::string &uniformBlockName, - unsigned int *indexOut) -{ -#ifdef ANGLE_ENABLE_HLSL - ASSERT(indexOut); - - TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); - ASSERT(translator); - - if (!translator->hasUniformBlock(uniformBlockName)) - { - return false; - } - - *indexOut = translator->getUniformBlockRegister(uniformBlockName); - return true; -#else - return false; -#endif // ANGLE_ENABLE_HLSL -} - -const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle) -{ -#ifdef ANGLE_ENABLE_HLSL - TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); - ASSERT(translator); - - return translator->getUniformRegisterMap(); -#else - return nullptr; -#endif // ANGLE_ENABLE_HLSL -} - -GLenum GetGeometryShaderInputPrimitiveType(const ShHandle handle) -{ - ASSERT(handle); - - TShHandleBase *base = static_cast<TShHandleBase *>(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderInputPrimitiveType()); -} - -GLenum GetGeometryShaderOutputPrimitiveType(const ShHandle handle) -{ - ASSERT(handle); - - TShHandleBase *base = static_cast<TShHandleBase *>(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderOutputPrimitiveType()); -} - -int GetGeometryShaderInvocations(const ShHandle handle) -{ - ASSERT(handle); - - TShHandleBase *base = static_cast<TShHandleBase *>(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return compiler->getGeometryShaderInvocations(); -} - -int GetGeometryShaderMaxVertices(const ShHandle handle) -{ - ASSERT(handle); - - TShHandleBase *base = static_cast<TShHandleBase *>(handle); - TCompiler *compiler = base->getAsCompiler(); - ASSERT(compiler); - - return compiler->getGeometryShaderMaxVertices(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp deleted file mode 100644 index 4ab574e935..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp +++ /dev/null @@ -1,586 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ShaderVars.cpp: -// Methods for GL variable types (varyings, uniforms, etc) -// - -#include <GLSLANG/ShaderLang.h> - -#include "common/debug.h" -#include "common/utilities.h" - -namespace sh -{ - -namespace -{ - -InterpolationType GetNonAuxiliaryInterpolationType(InterpolationType interpolation) -{ - return (interpolation == INTERPOLATION_CENTROID ? INTERPOLATION_SMOOTH : interpolation); -} -} -// The ES 3.0 spec is not clear on this point, but the ES 3.1 spec, and discussion -// on Khronos.org, clarifies that a smooth/flat mismatch produces a link error, -// but auxiliary qualifier mismatch (centroid) does not. -bool InterpolationTypesMatch(InterpolationType a, InterpolationType b) -{ - return (GetNonAuxiliaryInterpolationType(a) == GetNonAuxiliaryInterpolationType(b)); -} - -ShaderVariable::ShaderVariable() - : type(0), precision(0), flattenedOffsetInParentArrays(0), staticUse(false) -{ -} - -ShaderVariable::ShaderVariable(GLenum typeIn) - : type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false) -{ -} - -ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn) - : type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false) -{ - ASSERT(arraySizeIn != 0); - arraySizes.push_back(arraySizeIn); -} - -ShaderVariable::~ShaderVariable() -{ -} - -ShaderVariable::ShaderVariable(const ShaderVariable &other) - : type(other.type), - precision(other.precision), - name(other.name), - mappedName(other.mappedName), - arraySizes(other.arraySizes), - flattenedOffsetInParentArrays(other.flattenedOffsetInParentArrays), - staticUse(other.staticUse), - fields(other.fields), - structName(other.structName) -{ -} - -ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other) -{ - type = other.type; - precision = other.precision; - name = other.name; - mappedName = other.mappedName; - arraySizes = other.arraySizes; - staticUse = other.staticUse; - flattenedOffsetInParentArrays = other.flattenedOffsetInParentArrays; - fields = other.fields; - structName = other.structName; - return *this; -} - -bool ShaderVariable::operator==(const ShaderVariable &other) const -{ - if (type != other.type || precision != other.precision || name != other.name || - mappedName != other.mappedName || arraySizes != other.arraySizes || - staticUse != other.staticUse || fields.size() != other.fields.size() || - structName != other.structName) - { - return false; - } - for (size_t ii = 0; ii < fields.size(); ++ii) - { - if (fields[ii] != other.fields[ii]) - return false; - } - return true; -} - -void ShaderVariable::setArraySize(unsigned int size) -{ - arraySizes.clear(); - if (size != 0) - { - arraySizes.push_back(size); - } -} - -unsigned int ShaderVariable::getArraySizeProduct() const -{ - return gl::ArraySizeProduct(arraySizes); -} - -void ShaderVariable::indexIntoArray(unsigned int arrayIndex) -{ - ASSERT(isArray()); - flattenedOffsetInParentArrays = - arrayIndex + getOutermostArraySize() * flattenedOffsetInParentArrays; - arraySizes.pop_back(); -} - -unsigned int ShaderVariable::getNestedArraySize(unsigned int arrayNestingIndex) const -{ - ASSERT(arraySizes.size() > arrayNestingIndex); - return arraySizes[arraySizes.size() - 1u - arrayNestingIndex]; -} - -unsigned int ShaderVariable::getBasicTypeElementCount() const -{ - // GLES 3.1 Nov 2016 section 7.3.1.1 page 77 specifies that a separate entry should be generated - // for each array element when dealing with an array of arrays or an array of structs. - ASSERT(!isArrayOfArrays()); - ASSERT(!isStruct() || !isArray()); - - // GLES 3.1 Nov 2016 page 82. - if (isArray()) - { - return getOutermostArraySize(); - } - return 1u; -} - -bool ShaderVariable::findInfoByMappedName(const std::string &mappedFullName, - const ShaderVariable **leafVar, - std::string *originalFullName) const -{ - ASSERT(leafVar && originalFullName); - // There are three cases: - // 1) the top variable is of struct type; - // 2) the top variable is an array; - // 3) otherwise. - size_t pos = mappedFullName.find_first_of(".["); - - if (pos == std::string::npos) - { - // Case 3. - if (mappedFullName != this->mappedName) - return false; - *originalFullName = this->name; - *leafVar = this; - return true; - } - else - { - std::string topName = mappedFullName.substr(0, pos); - if (topName != this->mappedName) - return false; - std::string originalName = this->name; - std::string remaining; - if (mappedFullName[pos] == '[') - { - // Case 2. - size_t closePos = mappedFullName.find_first_of(']'); - if (closePos < pos || closePos == std::string::npos) - return false; - // Append '[index]'. - originalName += mappedFullName.substr(pos, closePos - pos + 1); - if (closePos + 1 == mappedFullName.size()) - { - *originalFullName = originalName; - *leafVar = this; - return true; - } - else - { - // In the form of 'a[0].b', so after ']', '.' is expected. - if (mappedFullName[closePos + 1] != '.') - return false; - remaining = mappedFullName.substr(closePos + 2); // Skip "]." - } - } - else - { - // Case 1. - remaining = mappedFullName.substr(pos + 1); // Skip "." - } - for (size_t ii = 0; ii < this->fields.size(); ++ii) - { - const ShaderVariable *fieldVar = nullptr; - std::string originalFieldName; - bool found = fields[ii].findInfoByMappedName(remaining, &fieldVar, &originalFieldName); - if (found) - { - *originalFullName = originalName + "." + originalFieldName; - *leafVar = fieldVar; - return true; - } - } - return false; - } -} - -bool ShaderVariable::isBuiltIn() const -{ - return (name.size() >= 4 && name[0] == 'g' && name[1] == 'l' && name[2] == '_'); -} - -bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other, - bool matchPrecision, - bool matchName) const -{ - if (type != other.type) - return false; - if (matchPrecision && precision != other.precision) - return false; - if (matchName && name != other.name) - return false; - ASSERT(!matchName || mappedName == other.mappedName); - if (arraySizes != other.arraySizes) - return false; - if (fields.size() != other.fields.size()) - return false; - - // [OpenGL ES 3.1 SPEC Chapter 7.4.1] - // Variables declared as structures are considered to match in type if and only if structure - // members match in name, type, qualification, and declaration order. - for (size_t ii = 0; ii < fields.size(); ++ii) - { - if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii], matchPrecision, true)) - { - return false; - } - } - if (structName != other.structName) - return false; - return true; -} - -Uniform::Uniform() : binding(-1), offset(-1) -{ -} - -Uniform::~Uniform() -{ -} - -Uniform::Uniform(const Uniform &other) - : VariableWithLocation(other), binding(other.binding), offset(other.offset) -{ -} - -Uniform &Uniform::operator=(const Uniform &other) -{ - VariableWithLocation::operator=(other); - binding = other.binding; - offset = other.offset; - return *this; -} - -bool Uniform::operator==(const Uniform &other) const -{ - return VariableWithLocation::operator==(other) && binding == other.binding && - offset == other.offset; -} - -bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const -{ - // Enforce a consistent match. - // https://cvs.khronos.org/bugzilla/show_bug.cgi?id=16261 - if (binding != -1 && other.binding != -1 && binding != other.binding) - { - return false; - } - if (location != -1 && other.location != -1 && location != other.location) - { - return false; - } - if (offset != other.offset) - { - return false; - } - return VariableWithLocation::isSameVariableAtLinkTime(other, true, true); -} - -VariableWithLocation::VariableWithLocation() : location(-1) -{ -} - -VariableWithLocation::~VariableWithLocation() -{ -} - -VariableWithLocation::VariableWithLocation(const VariableWithLocation &other) - : ShaderVariable(other), location(other.location) -{ -} - -VariableWithLocation &VariableWithLocation::operator=(const VariableWithLocation &other) -{ - ShaderVariable::operator=(other); - location = other.location; - return *this; -} - -bool VariableWithLocation::operator==(const VariableWithLocation &other) const -{ - return (ShaderVariable::operator==(other) && location == other.location); -} - -Attribute::Attribute() -{ -} - -Attribute::~Attribute() -{ -} - -Attribute::Attribute(const Attribute &other) : VariableWithLocation(other) -{ -} - -Attribute &Attribute::operator=(const Attribute &other) -{ - VariableWithLocation::operator=(other); - return *this; -} - -bool Attribute::operator==(const Attribute &other) const -{ - return VariableWithLocation::operator==(other); -} - -OutputVariable::OutputVariable() -{ -} - -OutputVariable::~OutputVariable() -{ -} - -OutputVariable::OutputVariable(const OutputVariable &other) : VariableWithLocation(other) -{ -} - -OutputVariable &OutputVariable::operator=(const OutputVariable &other) -{ - VariableWithLocation::operator=(other); - return *this; -} - -bool OutputVariable::operator==(const OutputVariable &other) const -{ - return VariableWithLocation::operator==(other); -} - -InterfaceBlockField::InterfaceBlockField() : isRowMajorLayout(false) -{ -} - -InterfaceBlockField::~InterfaceBlockField() -{ -} - -InterfaceBlockField::InterfaceBlockField(const InterfaceBlockField &other) - : ShaderVariable(other), isRowMajorLayout(other.isRowMajorLayout) -{ -} - -InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &other) -{ - ShaderVariable::operator=(other); - isRowMajorLayout = other.isRowMajorLayout; - return *this; -} - -bool InterfaceBlockField::operator==(const InterfaceBlockField &other) const -{ - return (ShaderVariable::operator==(other) && isRowMajorLayout == other.isRowMajorLayout); -} - -bool InterfaceBlockField::isSameInterfaceBlockFieldAtLinkTime( - const InterfaceBlockField &other) const -{ - return (ShaderVariable::isSameVariableAtLinkTime(other, true, true) && - isRowMajorLayout == other.isRowMajorLayout); -} - -Varying::Varying() : interpolation(INTERPOLATION_SMOOTH), isInvariant(false) -{ -} - -Varying::~Varying() -{ -} - -Varying::Varying(const Varying &other) - : VariableWithLocation(other), - interpolation(other.interpolation), - isInvariant(other.isInvariant) -{ -} - -Varying &Varying::operator=(const Varying &other) -{ - VariableWithLocation::operator=(other); - interpolation = other.interpolation; - isInvariant = other.isInvariant; - return *this; -} - -bool Varying::operator==(const Varying &other) const -{ - return (VariableWithLocation::operator==(other) && interpolation == other.interpolation && - isInvariant == other.isInvariant); -} - -bool Varying::isSameVaryingAtLinkTime(const Varying &other) const -{ - return isSameVaryingAtLinkTime(other, 100); -} - -bool Varying::isSameVaryingAtLinkTime(const Varying &other, int shaderVersion) const -{ - return (ShaderVariable::isSameVariableAtLinkTime(other, false, false) && - InterpolationTypesMatch(interpolation, other.interpolation) && - (shaderVersion >= 300 || isInvariant == other.isInvariant) && - (location == other.location) && - (name == other.name || (shaderVersion >= 310 && location >= 0))); -} - -InterfaceBlock::InterfaceBlock() - : arraySize(0), - layout(BLOCKLAYOUT_PACKED), - isRowMajorLayout(false), - binding(-1), - staticUse(false), - blockType(BlockType::BLOCK_UNIFORM) -{ -} - -InterfaceBlock::~InterfaceBlock() -{ -} - -InterfaceBlock::InterfaceBlock(const InterfaceBlock &other) - : name(other.name), - mappedName(other.mappedName), - instanceName(other.instanceName), - arraySize(other.arraySize), - layout(other.layout), - isRowMajorLayout(other.isRowMajorLayout), - binding(other.binding), - staticUse(other.staticUse), - blockType(other.blockType), - fields(other.fields) -{ -} - -InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other) -{ - name = other.name; - mappedName = other.mappedName; - instanceName = other.instanceName; - arraySize = other.arraySize; - layout = other.layout; - isRowMajorLayout = other.isRowMajorLayout; - binding = other.binding; - staticUse = other.staticUse; - blockType = other.blockType; - fields = other.fields; - return *this; -} - -std::string InterfaceBlock::fieldPrefix() const -{ - return instanceName.empty() ? "" : name; -} - -std::string InterfaceBlock::fieldMappedPrefix() const -{ - return instanceName.empty() ? "" : mappedName; -} - -bool InterfaceBlock::isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const -{ - if (name != other.name || mappedName != other.mappedName || arraySize != other.arraySize || - layout != other.layout || isRowMajorLayout != other.isRowMajorLayout || - binding != other.binding || blockType != other.blockType || - fields.size() != other.fields.size()) - { - return false; - } - - for (size_t fieldIndex = 0; fieldIndex < fields.size(); ++fieldIndex) - { - if (!fields[fieldIndex].isSameInterfaceBlockFieldAtLinkTime(other.fields[fieldIndex])) - { - return false; - } - } - - return true; -} - -bool InterfaceBlock::isBuiltIn() const -{ - return (name.size() >= 4 && name[0] == 'g' && name[1] == 'l' && name[2] == '_'); -} - -void WorkGroupSize::fill(int fillValue) -{ - localSizeQualifiers[0] = fillValue; - localSizeQualifiers[1] = fillValue; - localSizeQualifiers[2] = fillValue; -} - -void WorkGroupSize::setLocalSize(int localSizeX, int localSizeY, int localSizeZ) -{ - localSizeQualifiers[0] = localSizeX; - localSizeQualifiers[1] = localSizeY; - localSizeQualifiers[2] = localSizeZ; -} - -// check that if one of them is less than 1, then all of them are. -// Or if one is positive, then all of them are positive. -bool WorkGroupSize::isLocalSizeValid() const -{ - return ( - (localSizeQualifiers[0] < 1 && localSizeQualifiers[1] < 1 && localSizeQualifiers[2] < 1) || - (localSizeQualifiers[0] > 0 && localSizeQualifiers[1] > 0 && localSizeQualifiers[2] > 0)); -} - -bool WorkGroupSize::isAnyValueSet() const -{ - return localSizeQualifiers[0] > 0 || localSizeQualifiers[1] > 0 || localSizeQualifiers[2] > 0; -} - -bool WorkGroupSize::isDeclared() const -{ - bool localSizeDeclared = localSizeQualifiers[0] > 0; - ASSERT(isLocalSizeValid()); - return localSizeDeclared; -} - -bool WorkGroupSize::isWorkGroupSizeMatching(const WorkGroupSize &right) const -{ - for (size_t i = 0u; i < size(); ++i) - { - bool result = (localSizeQualifiers[i] == right.localSizeQualifiers[i] || - (localSizeQualifiers[i] == 1 && right.localSizeQualifiers[i] == -1) || - (localSizeQualifiers[i] == -1 && right.localSizeQualifiers[i] == 1)); - if (!result) - { - return false; - } - } - return true; -} - -int &WorkGroupSize::operator[](size_t index) -{ - ASSERT(index < size()); - return localSizeQualifiers[index]; -} - -int WorkGroupSize::operator[](size_t index) const -{ - ASSERT(index < size()); - return localSizeQualifiers[index]; -} - -size_t WorkGroupSize::size() const -{ - return 3u; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp b/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp deleted file mode 100644 index 9704046839..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp +++ /dev/null @@ -1,300 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SimplifyLoopConditions is an AST traverser that converts loop conditions and loop expressions -// to regular statements inside the loop. This way further transformations that generate statements -// from loop conditions and loop expressions work correctly. -// - -#include "compiler/translator/SimplifyLoopConditions.h" - -#include "compiler/translator/IntermNodePatternMatcher.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class SimplifyLoopConditionsTraverser : public TLValueTrackingTraverser -{ - public: - SimplifyLoopConditionsTraverser(unsigned int conditionsToSimplifyMask, - TSymbolTable *symbolTable, - int shaderVersion); - - void traverseLoop(TIntermLoop *node) override; - - bool visitUnary(Visit visit, TIntermUnary *node) override; - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - - bool foundLoopToChange() const { return mFoundLoopToChange; } - - protected: - // Marked to true once an operation that needs to be hoisted out of a loop expression has been - // found. - bool mFoundLoopToChange; - bool mInsideLoopInitConditionOrExpression; - IntermNodePatternMatcher mConditionsToSimplify; -}; - -SimplifyLoopConditionsTraverser::SimplifyLoopConditionsTraverser( - unsigned int conditionsToSimplifyMask, - TSymbolTable *symbolTable, - int shaderVersion) - : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion), - mFoundLoopToChange(false), - mInsideLoopInitConditionOrExpression(false), - mConditionsToSimplify(conditionsToSimplifyMask) -{ -} - -// If we're inside a loop initialization, condition, or expression, we check for expressions that -// should be moved out of the loop condition or expression. If one is found, the loop is -// transformed. -// If we're not inside loop initialization, condition, or expression, we only need to traverse nodes -// that may contain loops. - -bool SimplifyLoopConditionsTraverser::visitUnary(Visit visit, TIntermUnary *node) -{ - if (!mInsideLoopInitConditionOrExpression) - return false; - - if (mFoundLoopToChange) - return false; // Already decided to change this loop. - - mFoundLoopToChange = mConditionsToSimplify.match(node); - return !mFoundLoopToChange; -} - -bool SimplifyLoopConditionsTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - if (!mInsideLoopInitConditionOrExpression) - return false; - - if (mFoundLoopToChange) - return false; // Already decided to change this loop. - - mFoundLoopToChange = mConditionsToSimplify.match(node, getParentNode(), isLValueRequiredHere()); - return !mFoundLoopToChange; -} - -bool SimplifyLoopConditionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (!mInsideLoopInitConditionOrExpression) - return false; - - if (mFoundLoopToChange) - return false; // Already decided to change this loop. - - mFoundLoopToChange = mConditionsToSimplify.match(node, getParentNode()); - return !mFoundLoopToChange; -} - -bool SimplifyLoopConditionsTraverser::visitTernary(Visit visit, TIntermTernary *node) -{ - if (!mInsideLoopInitConditionOrExpression) - return false; - - if (mFoundLoopToChange) - return false; // Already decided to change this loop. - - mFoundLoopToChange = mConditionsToSimplify.match(node); - return !mFoundLoopToChange; -} - -bool SimplifyLoopConditionsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - if (!mInsideLoopInitConditionOrExpression) - return false; - - if (mFoundLoopToChange) - return false; // Already decided to change this loop. - - mFoundLoopToChange = mConditionsToSimplify.match(node); - return !mFoundLoopToChange; -} - -void SimplifyLoopConditionsTraverser::traverseLoop(TIntermLoop *node) -{ - // Mark that we're inside a loop condition or expression, and determine if the loop needs to be - // transformed. - - ScopedNodeInTraversalPath addToPath(this, node); - - mInsideLoopInitConditionOrExpression = true; - mFoundLoopToChange = false; - - if (!mFoundLoopToChange && node->getInit()) - { - node->getInit()->traverse(this); - } - - if (!mFoundLoopToChange && node->getCondition()) - { - node->getCondition()->traverse(this); - } - - if (!mFoundLoopToChange && node->getExpression()) - { - node->getExpression()->traverse(this); - } - - mInsideLoopInitConditionOrExpression = false; - - if (mFoundLoopToChange) - { - nextTemporaryId(); - - // Replace the loop condition with a boolean variable that's updated on each iteration. - TLoopType loopType = node->getType(); - if (loopType == ELoopWhile) - { - // Transform: - // while (expr) { body; } - // into - // bool s0 = expr; - // while (s0) { { body; } s0 = expr; } - TIntermSequence tempInitSeq; - tempInitSeq.push_back(createTempInitDeclaration(node->getCondition()->deepCopy())); - insertStatementsInParentBlock(tempInitSeq); - - TIntermBlock *newBody = new TIntermBlock(); - if (node->getBody()) - { - newBody->getSequence()->push_back(node->getBody()); - } - newBody->getSequence()->push_back( - createTempAssignment(node->getCondition()->deepCopy())); - - // Can't use queueReplacement to replace old body, since it may have been nullptr. - // It's safe to do the replacements in place here - the new body will still be - // traversed, but that won't create any problems. - node->setBody(newBody); - node->setCondition(createTempSymbol(node->getCondition()->getType())); - } - else if (loopType == ELoopDoWhile) - { - // Transform: - // do { - // body; - // } while (expr); - // into - // bool s0 = true; - // do { - // { body; } - // s0 = expr; - // } while (s0); - TIntermSequence tempInitSeq; - tempInitSeq.push_back(createTempInitDeclaration(CreateBoolNode(true))); - insertStatementsInParentBlock(tempInitSeq); - - TIntermBlock *newBody = new TIntermBlock(); - if (node->getBody()) - { - newBody->getSequence()->push_back(node->getBody()); - } - newBody->getSequence()->push_back( - createTempAssignment(node->getCondition()->deepCopy())); - - // Can't use queueReplacement to replace old body, since it may have been nullptr. - // It's safe to do the replacements in place here - the new body will still be - // traversed, but that won't create any problems. - node->setBody(newBody); - node->setCondition(createTempSymbol(node->getCondition()->getType())); - } - else if (loopType == ELoopFor) - { - // Move the loop condition inside the loop. - // Transform: - // for (init; expr; exprB) { body; } - // into - // { - // init; - // bool s0 = expr; - // while (s0) { - // { body; } - // exprB; - // s0 = expr; - // } - // } - TIntermBlock *loopScope = new TIntermBlock(); - TIntermSequence *loopScopeSequence = loopScope->getSequence(); - - // Insert "init;" - if (node->getInit()) - { - loopScopeSequence->push_back(node->getInit()); - } - - // Insert "bool s0 = expr;" if applicable, "bool s0 = true;" otherwise - TIntermTyped *conditionInitializer = nullptr; - if (node->getCondition()) - { - conditionInitializer = node->getCondition()->deepCopy(); - } - else - { - conditionInitializer = CreateBoolNode(true); - } - loopScopeSequence->push_back(createTempInitDeclaration(conditionInitializer)); - - // Insert "{ body; }" in the while loop - TIntermBlock *whileLoopBody = new TIntermBlock(); - if (node->getBody()) - { - whileLoopBody->getSequence()->push_back(node->getBody()); - } - // Insert "exprB;" in the while loop - if (node->getExpression()) - { - whileLoopBody->getSequence()->push_back(node->getExpression()); - } - // Insert "s0 = expr;" in the while loop - if (node->getCondition()) - { - whileLoopBody->getSequence()->push_back( - createTempAssignment(node->getCondition()->deepCopy())); - } - - // Create "while(s0) { whileLoopBody }" - TIntermLoop *whileLoop = new TIntermLoop( - ELoopWhile, nullptr, createTempSymbol(conditionInitializer->getType()), nullptr, - whileLoopBody); - loopScope->getSequence()->push_back(whileLoop); - queueReplacement(loopScope, OriginalNode::IS_DROPPED); - - // After this the old body node will be traversed and loops inside it may be - // transformed. This is fine, since the old body node will still be in the AST after the - // transformation that's queued here, and transforming loops inside it doesn't need to - // know the exact post-transform path to it. - } - } - - mFoundLoopToChange = false; - - // We traverse the body of the loop even if the loop is transformed. - if (node->getBody()) - node->getBody()->traverse(this); -} - -} // namespace - -void SimplifyLoopConditions(TIntermNode *root, - unsigned int conditionsToSimplifyMask, - TSymbolTable *symbolTable, - int shaderVersion) -{ - SimplifyLoopConditionsTraverser traverser(conditionsToSimplifyMask, symbolTable, shaderVersion); - root->traverse(&traverser); - traverser.updateTree(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h b/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h deleted file mode 100644 index d8f95cd2c8..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SimplifyLoopConditions is an AST traverser that converts loop conditions and loop expressions -// to regular statements inside the loop. This way further transformations that generate statements -// from loop conditions and loop expressions work correctly. -// - -#ifndef COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_ -#define COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_ - -namespace sh -{ -class TIntermNode; -class TSymbolTable; - -void SimplifyLoopConditions(TIntermNode *root, - unsigned int conditionsToSimplify, - TSymbolTable *symbolTable, - int shaderVersion); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp b/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp deleted file mode 100644 index 5df3154560..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp +++ /dev/null @@ -1,171 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SplitSequenceOperator is an AST traverser that detects sequence operator expressions that -// go through further AST transformations that generate statements, and splits them so that -// possible side effects of earlier parts of the sequence operator expression are guaranteed to be -// evaluated before the latter parts of the sequence operator expression are evaluated. -// - -#include "compiler/translator/SplitSequenceOperator.h" - -#include "compiler/translator/IntermNodePatternMatcher.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser -{ - public: - SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask, - TSymbolTable *symbolTable, - int shaderVersion); - - bool visitUnary(Visit visit, TIntermUnary *node) override; - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - - void nextIteration(); - bool foundExpressionToSplit() const { return mFoundExpressionToSplit; } - - protected: - // Marked to true once an operation that needs to be hoisted out of the expression has been - // found. After that, no more AST updates are performed on that traversal. - bool mFoundExpressionToSplit; - int mInsideSequenceOperator; - - IntermNodePatternMatcher mPatternToSplitMatcher; -}; - -SplitSequenceOperatorTraverser::SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask, - TSymbolTable *symbolTable, - int shaderVersion) - : TLValueTrackingTraverser(true, false, true, symbolTable, shaderVersion), - mFoundExpressionToSplit(false), - mInsideSequenceOperator(0), - mPatternToSplitMatcher(patternsToSplitMask) -{ -} - -void SplitSequenceOperatorTraverser::nextIteration() -{ - mFoundExpressionToSplit = false; - mInsideSequenceOperator = 0; - nextTemporaryId(); -} - -bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (mFoundExpressionToSplit) - return false; - - if (mInsideSequenceOperator > 0 && visit == PreVisit) - { - // Detect expressions that need to be simplified - mFoundExpressionToSplit = mPatternToSplitMatcher.match(node, getParentNode()); - return !mFoundExpressionToSplit; - } - - return true; -} - -bool SplitSequenceOperatorTraverser::visitUnary(Visit visit, TIntermUnary *node) -{ - if (mFoundExpressionToSplit) - return false; - - if (mInsideSequenceOperator > 0 && visit == PreVisit) - { - // Detect expressions that need to be simplified - mFoundExpressionToSplit = mPatternToSplitMatcher.match(node); - return !mFoundExpressionToSplit; - } - - return true; -} - -bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - if (node->getOp() == EOpComma) - { - if (visit == PreVisit) - { - if (mFoundExpressionToSplit) - { - return false; - } - mInsideSequenceOperator++; - } - else if (visit == PostVisit) - { - // Split sequence operators starting from the outermost one to preserve correct - // execution order. - if (mFoundExpressionToSplit && mInsideSequenceOperator == 1) - { - // Move the left side operand into a separate statement in the parent block. - TIntermSequence insertions; - insertions.push_back(node->getLeft()); - insertStatementsInParentBlock(insertions); - // Replace the comma node with its right side operand. - queueReplacement(node->getRight(), OriginalNode::IS_DROPPED); - } - mInsideSequenceOperator--; - } - return true; - } - - if (mFoundExpressionToSplit) - return false; - - if (mInsideSequenceOperator > 0 && visit == PreVisit) - { - // Detect expressions that need to be simplified - mFoundExpressionToSplit = - mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere()); - return !mFoundExpressionToSplit; - } - - return true; -} - -bool SplitSequenceOperatorTraverser::visitTernary(Visit visit, TIntermTernary *node) -{ - if (mFoundExpressionToSplit) - return false; - - if (mInsideSequenceOperator > 0 && visit == PreVisit) - { - // Detect expressions that need to be simplified - mFoundExpressionToSplit = mPatternToSplitMatcher.match(node); - return !mFoundExpressionToSplit; - } - - return true; -} - -} // namespace - -void SplitSequenceOperator(TIntermNode *root, - int patternsToSplitMask, - TSymbolTable *symbolTable, - int shaderVersion) -{ - SplitSequenceOperatorTraverser traverser(patternsToSplitMask, symbolTable, shaderVersion); - // Separate one expression at a time, and reset the traverser between iterations. - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.foundExpressionToSplit()) - traverser.updateTree(); - } while (traverser.foundExpressionToSplit()); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h b/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h deleted file mode 100644 index 8f1a766775..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SplitSequenceOperator is an AST traverser that detects sequence operator expressions that -// go through further AST transformations that generate statements, and splits them so that -// possible side effects of earlier parts of the sequence operator expression are guaranteed to be -// evaluated before the latter parts of the sequence operator expression are evaluated. -// - -#ifndef COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_ -#define COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_ - -namespace sh -{ - -class TIntermNode; -class TSymbolTable; - -void SplitSequenceOperator(TIntermNode *root, - int patternsToSplitMask, - TSymbolTable *symbolTable, - int shaderVersion); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp deleted file mode 100644 index 61a9431ceb..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp +++ /dev/null @@ -1,594 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// StructureHLSL.cpp: -// HLSL translation of GLSL constructors and structures. -// - -#include "compiler/translator/StructureHLSL.h" -#include "common/utilities.h" -#include "compiler/translator/OutputHLSL.h" -#include "compiler/translator/Types.h" -#include "compiler/translator/util.h" -#include "compiler/translator/UtilsHLSL.h" - -namespace sh -{ - -namespace -{ - -TString Define(const TStructure &structure, - bool useHLSLRowMajorPacking, - bool useStd140Packing, - Std140PaddingHelper *padHelper) -{ - const TFieldList &fields = structure.fields(); - const bool isNameless = (structure.name() == ""); - const TString &structName = - QualifiedStructNameString(structure, useHLSLRowMajorPacking, useStd140Packing); - const TString declareString = (isNameless ? "struct" : "struct " + structName); - - TString string; - string += declareString + - "\n" - "{\n"; - - for (const TField *field : fields) - { - const TType &fieldType = *field->type(); - if (!IsSampler(fieldType.getBasicType())) - { - const TStructure *fieldStruct = fieldType.getStruct(); - const TString &fieldTypeString = - fieldStruct ? QualifiedStructNameString(*fieldStruct, useHLSLRowMajorPacking, - useStd140Packing) - : TypeString(fieldType); - - if (padHelper) - { - string += padHelper->prePaddingString(fieldType); - } - - string += " " + fieldTypeString + " " + DecorateField(field->name(), structure) + - ArrayString(fieldType) + ";\n"; - - if (padHelper) - { - string += padHelper->postPaddingString(fieldType, useHLSLRowMajorPacking); - } - } - } - - // Nameless structs do not finish with a semicolon and newline, to leave room for an instance - // variable - string += (isNameless ? "} " : "};\n"); - - return string; -} - -TString WriteParameterList(const std::vector<TType> ¶meters) -{ - TString parameterList; - for (size_t parameter = 0u; parameter < parameters.size(); parameter++) - { - const TType ¶mType = parameters[parameter]; - - parameterList += TypeString(paramType) + " x" + str(parameter) + ArrayString(paramType); - - if (parameter < parameters.size() - 1u) - { - parameterList += ", "; - } - } - return parameterList; -} - -} // anonymous namespace - -Std140PaddingHelper::Std140PaddingHelper(const std::map<TString, int> &structElementIndexes, - unsigned *uniqueCounter) - : mPaddingCounter(uniqueCounter), mElementIndex(0), mStructElementIndexes(&structElementIndexes) -{ -} - -Std140PaddingHelper::Std140PaddingHelper(const Std140PaddingHelper &other) - : mPaddingCounter(other.mPaddingCounter), - mElementIndex(other.mElementIndex), - mStructElementIndexes(other.mStructElementIndexes) -{ -} - -Std140PaddingHelper &Std140PaddingHelper::operator=(const Std140PaddingHelper &other) -{ - mPaddingCounter = other.mPaddingCounter; - mElementIndex = other.mElementIndex; - mStructElementIndexes = other.mStructElementIndexes; - return *this; -} - -TString Std140PaddingHelper::next() -{ - unsigned value = (*mPaddingCounter)++; - return str(value); -} - -int Std140PaddingHelper::prePadding(const TType &type) -{ - if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray()) - { - // no padding needed, HLSL will align the field to a new register - mElementIndex = 0; - return 0; - } - - const GLenum glType = GLVariableType(type); - const int numComponents = gl::VariableComponentCount(glType); - - if (numComponents >= 4) - { - // no padding needed, HLSL will align the field to a new register - mElementIndex = 0; - return 0; - } - - if (mElementIndex + numComponents > 4) - { - // no padding needed, HLSL will align the field to a new register - mElementIndex = numComponents; - return 0; - } - - const int alignment = numComponents == 3 ? 4 : numComponents; - const int paddingOffset = (mElementIndex % alignment); - const int paddingCount = (paddingOffset != 0 ? (alignment - paddingOffset) : 0); - - mElementIndex += paddingCount; - mElementIndex += numComponents; - mElementIndex %= 4; - - return paddingCount; -} - -TString Std140PaddingHelper::prePaddingString(const TType &type) -{ - int paddingCount = prePadding(type); - - TString padding; - - for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++) - { - padding += " float pad_" + next() + ";\n"; - } - - return padding; -} - -TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRowMajorPacking) -{ - if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct) - { - return ""; - } - - int numComponents = 0; - const TStructure *structure = type.getStruct(); - - if (type.isMatrix()) - { - // This method can also be called from structureString, which does not use layout - // qualifiers. - // Thus, use the method parameter for determining the matrix packing. - // - // Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we - // wish to always transpose GL matrices to play well with HLSL's matrix array indexing. - // - const bool isRowMajorMatrix = !useHLSLRowMajorPacking; - const GLenum glType = GLVariableType(type); - numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix); - } - else if (structure) - { - const TString &structName = - QualifiedStructNameString(*structure, useHLSLRowMajorPacking, true); - numComponents = mStructElementIndexes->find(structName)->second; - - if (numComponents == 0) - { - return ""; - } - } - else - { - const GLenum glType = GLVariableType(type); - numComponents = gl::VariableComponentCount(glType); - } - - TString padding; - for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++) - { - padding += " float pad_" + next() + ";\n"; - } - return padding; -} - -StructureHLSL::StructureHLSL() : mUniquePaddingCounter(0) -{ -} - -Std140PaddingHelper StructureHLSL::getPaddingHelper() -{ - return Std140PaddingHelper(mStd140StructElementIndexes, &mUniquePaddingCounter); -} - -TString StructureHLSL::defineQualified(const TStructure &structure, - bool useHLSLRowMajorPacking, - bool useStd140Packing) -{ - if (useStd140Packing) - { - Std140PaddingHelper padHelper = getPaddingHelper(); - return Define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper); - } - else - { - return Define(structure, useHLSLRowMajorPacking, useStd140Packing, nullptr); - } -} - -TString StructureHLSL::defineNameless(const TStructure &structure) -{ - return Define(structure, false, false, nullptr); -} - -StructureHLSL::DefinedStructs::iterator StructureHLSL::defineVariants(const TStructure &structure, - const TString &name) -{ - ASSERT(mDefinedStructs.find(name) == mDefinedStructs.end()); - - for (const TField *field : structure.fields()) - { - const TType *fieldType = field->type(); - if (fieldType->getBasicType() == EbtStruct) - { - ensureStructDefined(*fieldType->getStruct()); - } - } - - DefinedStructs::iterator addedStruct = - mDefinedStructs.insert(std::make_pair(name, new TStructProperties())).first; - // Add element index - storeStd140ElementIndex(structure, false); - storeStd140ElementIndex(structure, true); - - const TString &structString = defineQualified(structure, false, false); - - ASSERT(std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) == - mStructDeclarations.end()); - // Add row-major packed struct for interface blocks - TString rowMajorString = "#pragma pack_matrix(row_major)\n" + - defineQualified(structure, true, false) + - "#pragma pack_matrix(column_major)\n"; - - TString std140String = defineQualified(structure, false, true); - TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" + - defineQualified(structure, true, true) + - "#pragma pack_matrix(column_major)\n"; - - mStructDeclarations.push_back(structString); - mStructDeclarations.push_back(rowMajorString); - mStructDeclarations.push_back(std140String); - mStructDeclarations.push_back(std140RowMajorString); - return addedStruct; -} - -void StructureHLSL::ensureStructDefined(const TStructure &structure) -{ - const TString name = StructNameString(structure); - if (name == "") - { - return; // Nameless structures are not defined - } - if (mDefinedStructs.find(name) == mDefinedStructs.end()) - { - defineVariants(structure, name); - } -} - -TString StructureHLSL::addStructConstructor(const TStructure &structure) -{ - const TString name = StructNameString(structure); - - if (name == "") - { - return TString(); // Nameless structures don't have constructors - } - - auto definedStruct = mDefinedStructs.find(name); - if (definedStruct == mDefinedStructs.end()) - { - definedStruct = defineVariants(structure, name); - } - const TString constructorFunctionName = TString(name) + "_ctor"; - TString *constructor = &definedStruct->second->constructor; - if (!constructor->empty()) - { - return constructorFunctionName; // Already added - } - *constructor += name + " " + constructorFunctionName + "("; - - std::vector<TType> ctorParameters; - const TFieldList &fields = structure.fields(); - for (const TField *field : fields) - { - const TType *fieldType = field->type(); - if (!IsSampler(fieldType->getBasicType())) - { - ctorParameters.push_back(*fieldType); - } - } - // Structs that have sampler members should not have constructor calls, and otherwise structs - // are guaranteed to be non-empty by the grammar. Structs can't contain empty declarations - // either. - ASSERT(!ctorParameters.empty()); - - *constructor += WriteParameterList(ctorParameters); - - *constructor += - ")\n" - "{\n" - " " + - name + " structure = { "; - - for (size_t parameterIndex = 0u; parameterIndex < ctorParameters.size(); ++parameterIndex) - { - *constructor += "x" + str(parameterIndex); - if (parameterIndex < ctorParameters.size() - 1u) - { - *constructor += ", "; - } - } - *constructor += - "};\n" - " return structure;\n" - "}\n"; - - return constructorFunctionName; -} - -TString StructureHLSL::addBuiltInConstructor(const TType &type, const TIntermSequence *parameters) -{ - ASSERT(!type.isArray()); - ASSERT(type.getStruct() == nullptr); - ASSERT(parameters); - - TType ctorType = type; - ctorType.setPrecision(EbpHigh); - ctorType.setQualifier(EvqTemporary); - - const TString constructorFunctionName = - TString(type.getBuiltInTypeNameString()) + "_ctor" + DisambiguateFunctionName(parameters); - TString constructor = TypeString(ctorType) + " " + constructorFunctionName + "("; - - std::vector<TType> ctorParameters; - for (auto parameter : *parameters) - { - const TType ¶mType = parameter->getAsTyped()->getType(); - ASSERT(!paramType.isArray()); - ctorParameters.push_back(paramType); - } - constructor += WriteParameterList(ctorParameters); - - constructor += - ")\n" - "{\n" - " return " + - TypeString(ctorType) + "("; - - if (ctorType.isMatrix() && ctorParameters.size() == 1) - { - int rows = ctorType.getRows(); - int cols = ctorType.getCols(); - const TType ¶meter = ctorParameters[0]; - - if (parameter.isScalar()) - { - for (int col = 0; col < cols; col++) - { - for (int row = 0; row < rows; row++) - { - constructor += TString((row == col) ? "x0" : "0.0"); - - if (row < rows - 1 || col < cols - 1) - { - constructor += ", "; - } - } - } - } - else if (parameter.isMatrix()) - { - for (int col = 0; col < cols; col++) - { - for (int row = 0; row < rows; row++) - { - if (row < parameter.getRows() && col < parameter.getCols()) - { - constructor += TString("x0") + "[" + str(col) + "][" + str(row) + "]"; - } - else - { - constructor += TString((row == col) ? "1.0" : "0.0"); - } - - if (row < rows - 1 || col < cols - 1) - { - constructor += ", "; - } - } - } - } - else - { - ASSERT(rows == 2 && cols == 2 && parameter.isVector() && - parameter.getNominalSize() == 4); - - constructor += "x0"; - } - } - else - { - size_t remainingComponents = ctorType.getObjectSize(); - size_t parameterIndex = 0; - - while (remainingComponents > 0) - { - const TType ¶meter = ctorParameters[parameterIndex]; - const size_t parameterSize = parameter.getObjectSize(); - bool moreParameters = parameterIndex + 1 < ctorParameters.size(); - - constructor += "x" + str(parameterIndex); - - if (parameter.isScalar()) - { - remainingComponents -= parameter.getObjectSize(); - } - else if (parameter.isVector()) - { - if (remainingComponents == parameterSize || moreParameters) - { - ASSERT(parameterSize <= remainingComponents); - remainingComponents -= parameterSize; - } - else if (remainingComponents < static_cast<size_t>(parameter.getNominalSize())) - { - switch (remainingComponents) - { - case 1: - constructor += ".x"; - break; - case 2: - constructor += ".xy"; - break; - case 3: - constructor += ".xyz"; - break; - case 4: - constructor += ".xyzw"; - break; - default: - UNREACHABLE(); - } - - remainingComponents = 0; - } - else - UNREACHABLE(); - } - else if (parameter.isMatrix()) - { - int column = 0; - while (remainingComponents > 0 && column < parameter.getCols()) - { - constructor += "[" + str(column) + "]"; - - if (remainingComponents < static_cast<size_t>(parameter.getRows())) - { - switch (remainingComponents) - { - case 1: - constructor += ".x"; - break; - case 2: - constructor += ".xy"; - break; - case 3: - constructor += ".xyz"; - break; - default: - UNREACHABLE(); - } - - remainingComponents = 0; - } - else - { - remainingComponents -= parameter.getRows(); - - if (remainingComponents > 0) - { - constructor += ", x" + str(parameterIndex); - } - } - - column++; - } - } - else - { - UNREACHABLE(); - } - - if (moreParameters) - { - parameterIndex++; - } - - if (remainingComponents) - { - constructor += ", "; - } - } - } - - constructor += - ");\n" - "}\n"; - - mBuiltInConstructors.insert(constructor); - - return constructorFunctionName; -} - -std::string StructureHLSL::structsHeader() const -{ - TInfoSinkBase out; - - for (auto &declaration : mStructDeclarations) - { - out << declaration; - } - - for (auto &structure : mDefinedStructs) - { - out << structure.second->constructor; - } - - for (auto &constructor : mBuiltInConstructors) - { - out << constructor; - } - - return out.str(); -} - -void StructureHLSL::storeStd140ElementIndex(const TStructure &structure, - bool useHLSLRowMajorPacking) -{ - Std140PaddingHelper padHelper = getPaddingHelper(); - const TFieldList &fields = structure.fields(); - - for (const TField *field : fields) - { - padHelper.prePadding(*field->type()); - } - - // Add remaining element index to the global map, for use with nested structs in standard - // layouts - const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking, true); - mStd140StructElementIndexes[structName] = padHelper.elementIndex(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h deleted file mode 100644 index daced8f8d1..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h +++ /dev/null @@ -1,98 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// StructureHLSL.h: -// HLSL translation of GLSL constructors and structures. -// - -#ifndef COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ -#define COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ - -#include "compiler/translator/Common.h" -#include "compiler/translator/IntermNode.h" - -#include <set> - -class TInfoSinkBase; -class TScopeBracket; - -namespace sh -{ - -// This helper class assists structure and interface block definitions in determining -// how to pack std140 structs within HLSL's packing rules. -class Std140PaddingHelper -{ - public: - explicit Std140PaddingHelper(const std::map<TString, int> &structElementIndexes, - unsigned int *uniqueCounter); - Std140PaddingHelper(const Std140PaddingHelper &other); - Std140PaddingHelper &operator=(const Std140PaddingHelper &other); - - int elementIndex() const { return mElementIndex; } - int prePadding(const TType &type); - TString prePaddingString(const TType &type); - TString postPaddingString(const TType &type, bool useHLSLRowMajorPacking); - - private: - TString next(); - - unsigned *mPaddingCounter; - int mElementIndex; - const std::map<TString, int> *mStructElementIndexes; -}; - -class StructureHLSL : angle::NonCopyable -{ - public: - StructureHLSL(); - - // Returns the name of the constructor function. - TString addStructConstructor(const TStructure &structure); - TString addBuiltInConstructor(const TType &type, const TIntermSequence *parameters); - - static TString defineNameless(const TStructure &structure); - void ensureStructDefined(const TStructure &structure); - - std::string structsHeader() const; - - Std140PaddingHelper getPaddingHelper(); - - private: - unsigned mUniquePaddingCounter; - - std::map<TString, int> mStd140StructElementIndexes; - - struct TStructProperties : public angle::NonCopyable - { - POOL_ALLOCATOR_NEW_DELETE(); - - TStructProperties() {} - - // Constructor is an empty string in case the struct doesn't have a constructor yet. - TString constructor; - }; - - // Map from struct name to struct properties. - typedef std::map<TString, TStructProperties *> DefinedStructs; - DefinedStructs mDefinedStructs; - - // Struct declarations need to be kept in a vector instead of having them inside mDefinedStructs - // since maintaining the original order is necessary for nested structs. - typedef std::vector<TString> StructDeclarations; - StructDeclarations mStructDeclarations; - - typedef std::set<TString> BuiltInConstructors; - BuiltInConstructors mBuiltInConstructors; - - void storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking); - TString defineQualified(const TStructure &structure, - bool useHLSLRowMajorPacking, - bool useStd140Packing); - DefinedStructs::iterator defineVariants(const TStructure &structure, const TString &name); -}; -} - -#endif // COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp deleted file mode 100644 index 6c38461469..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp +++ /dev/null @@ -1,622 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Symbol table for parsing. The design principles and most of the functionality are documented in -// the header file. -// - -#if defined(_MSC_VER) -#pragma warning(disable : 4718) -#endif - -#include "compiler/translator/SymbolTable.h" - -#include "compiler/translator/Cache.h" -#include "compiler/translator/IntermNode.h" - -#include <stdio.h> -#include <algorithm> - -namespace sh -{ - -namespace -{ - -static const char kFunctionMangledNameSeparator = '('; - -} // anonymous namespace - -TSymbol::TSymbol(TSymbolTable *symbolTable, const TString *n) - : uniqueId(symbolTable->nextUniqueId()), name(n), extension(TExtension::UNDEFINED) -{ -} - -// -// Functions have buried pointers to delete. -// -TFunction::~TFunction() -{ - clearParameters(); -} - -void TFunction::clearParameters() -{ - for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) - delete (*i).type; - parameters.clear(); - mangledName = nullptr; -} - -void TFunction::swapParameters(const TFunction ¶metersSource) -{ - clearParameters(); - for (auto parameter : parametersSource.parameters) - { - addParameter(parameter); - } -} - -const TString *TFunction::buildMangledName() const -{ - std::string newName = getName().c_str(); - newName += kFunctionMangledNameSeparator; - - for (const auto &p : parameters) - { - newName += p.type->getMangledName(); - } - return NewPoolTString(newName.c_str()); -} - -const TString &TFunction::GetMangledNameFromCall(const TString &functionName, - const TIntermSequence &arguments) -{ - std::string newName = functionName.c_str(); - newName += kFunctionMangledNameSeparator; - - for (TIntermNode *argument : arguments) - { - newName += argument->getAsTyped()->getType().getMangledName(); - } - return *NewPoolTString(newName.c_str()); -} - -// -// Symbol table levels are a map of pointers to symbols that have to be deleted. -// -TSymbolTableLevel::~TSymbolTableLevel() -{ - for (tLevel::iterator it = level.begin(); it != level.end(); ++it) - delete (*it).second; -} - -bool TSymbolTableLevel::insert(TSymbol *symbol) -{ - // returning true means symbol was added to the table - tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol)); - - return result.second; -} - -bool TSymbolTableLevel::insertUnmangled(TFunction *function) -{ - // returning true means symbol was added to the table - tInsertResult result = level.insert(tLevelPair(function->getName(), function)); - - return result.second; -} - -TSymbol *TSymbolTableLevel::find(const TString &name) const -{ - tLevel::const_iterator it = level.find(name); - if (it == level.end()) - return 0; - else - return (*it).second; -} - -TSymbol *TSymbolTable::find(const TString &name, - int shaderVersion, - bool *builtIn, - bool *sameScope) const -{ - int level = currentLevel(); - TSymbol *symbol; - - do - { - if (level == GLSL_BUILTINS) - level--; - if (level == ESSL3_1_BUILTINS && shaderVersion != 310) - level--; - if (level == ESSL3_BUILTINS && shaderVersion < 300) - level--; - if (level == ESSL1_BUILTINS && shaderVersion != 100) - level--; - - symbol = table[level]->find(name); - } while (symbol == 0 && --level >= 0); - - if (builtIn) - *builtIn = (level <= LAST_BUILTIN_LEVEL); - if (sameScope) - *sameScope = (level == currentLevel()); - - return symbol; -} - -TSymbol *TSymbolTable::findGlobal(const TString &name) const -{ - ASSERT(table.size() > GLOBAL_LEVEL); - return table[GLOBAL_LEVEL]->find(name); -} - -TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) const -{ - return findBuiltIn(name, shaderVersion, false); -} - -TSymbol *TSymbolTable::findBuiltIn(const TString &name, - int shaderVersion, - bool includeGLSLBuiltins) const -{ - for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--) - { - if (level == GLSL_BUILTINS && !includeGLSLBuiltins) - level--; - if (level == ESSL3_1_BUILTINS && shaderVersion != 310) - level--; - if (level == ESSL3_BUILTINS && shaderVersion < 300) - level--; - if (level == ESSL1_BUILTINS && shaderVersion != 100) - level--; - - TSymbol *symbol = table[level]->find(name); - - if (symbol) - return symbol; - } - - return nullptr; -} - -TSymbolTable::~TSymbolTable() -{ - while (table.size() > 0) - pop(); -} - -bool IsGenType(const TType *type) -{ - if (type) - { - TBasicType basicType = type->getBasicType(); - return basicType == EbtGenType || basicType == EbtGenIType || basicType == EbtGenUType || - basicType == EbtGenBType; - } - - return false; -} - -bool IsVecType(const TType *type) -{ - if (type) - { - TBasicType basicType = type->getBasicType(); - return basicType == EbtVec || basicType == EbtIVec || basicType == EbtUVec || - basicType == EbtBVec; - } - - return false; -} - -const TType *SpecificType(const TType *type, int size) -{ - ASSERT(size >= 1 && size <= 4); - - if (!type) - { - return nullptr; - } - - ASSERT(!IsVecType(type)); - - switch (type->getBasicType()) - { - case EbtGenType: - return TCache::getType(EbtFloat, type->getQualifier(), - static_cast<unsigned char>(size)); - case EbtGenIType: - return TCache::getType(EbtInt, type->getQualifier(), static_cast<unsigned char>(size)); - case EbtGenUType: - return TCache::getType(EbtUInt, type->getQualifier(), static_cast<unsigned char>(size)); - case EbtGenBType: - return TCache::getType(EbtBool, type->getQualifier(), static_cast<unsigned char>(size)); - default: - return type; - } -} - -const TType *VectorType(const TType *type, int size) -{ - ASSERT(size >= 2 && size <= 4); - - if (!type) - { - return nullptr; - } - - ASSERT(!IsGenType(type)); - - switch (type->getBasicType()) - { - case EbtVec: - return TCache::getType(EbtFloat, static_cast<unsigned char>(size)); - case EbtIVec: - return TCache::getType(EbtInt, static_cast<unsigned char>(size)); - case EbtUVec: - return TCache::getType(EbtUInt, static_cast<unsigned char>(size)); - case EbtBVec: - return TCache::getType(EbtBool, static_cast<unsigned char>(size)); - default: - return type; - } -} - -TVariable *TSymbolTable::declareVariable(const TString *name, const TType &type) -{ - return insertVariable(currentLevel(), name, type); -} - -TVariable *TSymbolTable::declareStructType(TStructure *str) -{ - return insertStructType(currentLevel(), str); -} - -TInterfaceBlockName *TSymbolTable::declareInterfaceBlockName(const TString *name) -{ - TInterfaceBlockName *blockNameSymbol = new TInterfaceBlockName(this, name); - if (insert(currentLevel(), blockNameSymbol)) - { - return blockNameSymbol; - } - return nullptr; -} - -TInterfaceBlockName *TSymbolTable::insertInterfaceBlockNameExt(ESymbolLevel level, - TExtension ext, - const TString *name) -{ - TInterfaceBlockName *blockNameSymbol = new TInterfaceBlockName(this, name); - if (insert(level, ext, blockNameSymbol)) - { - return blockNameSymbol; - } - return nullptr; -} - -TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const char *name, const TType &type) -{ - return insertVariable(level, NewPoolTString(name), type); -} - -TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const TString *name, const TType &type) -{ - TVariable *var = new TVariable(this, name, type); - if (insert(level, var)) - { - // Do lazy initialization for struct types, so we allocate to the current scope. - if (var->getType().getBasicType() == EbtStruct) - { - var->getType().realize(); - } - return var; - } - return nullptr; -} - -TVariable *TSymbolTable::insertVariableExt(ESymbolLevel level, - TExtension ext, - const char *name, - const TType &type) -{ - TVariable *var = new TVariable(this, NewPoolTString(name), type); - if (insert(level, ext, var)) - { - if (var->getType().getBasicType() == EbtStruct) - { - var->getType().realize(); - } - return var; - } - return nullptr; -} - -TVariable *TSymbolTable::insertStructType(ESymbolLevel level, TStructure *str) -{ - TVariable *var = new TVariable(this, &str->name(), TType(str), true); - if (insert(level, var)) - { - var->getType().realize(); - return var; - } - return nullptr; -} - -void TSymbolTable::insertBuiltIn(ESymbolLevel level, - TOperator op, - TExtension ext, - const TType *rvalue, - const char *name, - const TType *ptype1, - const TType *ptype2, - const TType *ptype3, - const TType *ptype4, - const TType *ptype5) -{ - if (ptype1->getBasicType() == EbtGSampler2D) - { - insertUnmangledBuiltInName(name, level); - bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, - TCache::getType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, - TCache::getType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, - TCache::getType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5); - } - else if (ptype1->getBasicType() == EbtGSampler3D) - { - insertUnmangledBuiltInName(name, level); - bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, - TCache::getType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, - TCache::getType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, - TCache::getType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5); - } - else if (ptype1->getBasicType() == EbtGSamplerCube) - { - insertUnmangledBuiltInName(name, level); - bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, - TCache::getType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, - TCache::getType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, - TCache::getType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5); - } - else if (ptype1->getBasicType() == EbtGSampler2DArray) - { - insertUnmangledBuiltInName(name, level); - bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, - TCache::getType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, - TCache::getType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, - TCache::getType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5); - } - else if (ptype1->getBasicType() == EbtGSampler2DMS) - { - insertUnmangledBuiltInName(name, level); - bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, - TCache::getType(EbtSampler2DMS), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, - TCache::getType(EbtISampler2DMS), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, - TCache::getType(EbtUSampler2DMS), ptype2, ptype3, ptype4, ptype5); - } - else if (IsGImage(ptype1->getBasicType())) - { - insertUnmangledBuiltInName(name, level); - - const TType *floatType = TCache::getType(EbtFloat, 4); - const TType *intType = TCache::getType(EbtInt, 4); - const TType *unsignedType = TCache::getType(EbtUInt, 4); - - const TType *floatImage = - TCache::getType(convertGImageToFloatImage(ptype1->getBasicType())); - const TType *intImage = TCache::getType(convertGImageToIntImage(ptype1->getBasicType())); - const TType *unsignedImage = - TCache::getType(convertGImageToUnsignedImage(ptype1->getBasicType())); - - // GLSL ES 3.10, Revision 4, 8.12 Image Functions - if (rvalue->getBasicType() == EbtGVec4) - { - // imageLoad - insertBuiltIn(level, floatType, name, floatImage, ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, intType, name, intImage, ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, unsignedType, name, unsignedImage, ptype2, ptype3, ptype4, ptype5); - } - else if (rvalue->getBasicType() == EbtVoid) - { - // imageStore - insertBuiltIn(level, rvalue, name, floatImage, ptype2, floatType, ptype4, ptype5); - insertBuiltIn(level, rvalue, name, intImage, ptype2, intType, ptype4, ptype5); - insertBuiltIn(level, rvalue, name, unsignedImage, ptype2, unsignedType, ptype4, ptype5); - } - else - { - // imageSize - insertBuiltIn(level, rvalue, name, floatImage, ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, rvalue, name, intImage, ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, rvalue, name, unsignedImage, ptype2, ptype3, ptype4, ptype5); - } - } - else if (IsGenType(rvalue) || IsGenType(ptype1) || IsGenType(ptype2) || IsGenType(ptype3) || - IsGenType(ptype4)) - { - ASSERT(!ptype5); - insertUnmangledBuiltInName(name, level); - insertBuiltIn(level, op, ext, SpecificType(rvalue, 1), name, SpecificType(ptype1, 1), - SpecificType(ptype2, 1), SpecificType(ptype3, 1), SpecificType(ptype4, 1)); - insertBuiltIn(level, op, ext, SpecificType(rvalue, 2), name, SpecificType(ptype1, 2), - SpecificType(ptype2, 2), SpecificType(ptype3, 2), SpecificType(ptype4, 2)); - insertBuiltIn(level, op, ext, SpecificType(rvalue, 3), name, SpecificType(ptype1, 3), - SpecificType(ptype2, 3), SpecificType(ptype3, 3), SpecificType(ptype4, 3)); - insertBuiltIn(level, op, ext, SpecificType(rvalue, 4), name, SpecificType(ptype1, 4), - SpecificType(ptype2, 4), SpecificType(ptype3, 4), SpecificType(ptype4, 4)); - } - else if (IsVecType(rvalue) || IsVecType(ptype1) || IsVecType(ptype2) || IsVecType(ptype3)) - { - ASSERT(!ptype4 && !ptype5); - insertUnmangledBuiltInName(name, level); - insertBuiltIn(level, op, ext, VectorType(rvalue, 2), name, VectorType(ptype1, 2), - VectorType(ptype2, 2), VectorType(ptype3, 2)); - insertBuiltIn(level, op, ext, VectorType(rvalue, 3), name, VectorType(ptype1, 3), - VectorType(ptype2, 3), VectorType(ptype3, 3)); - insertBuiltIn(level, op, ext, VectorType(rvalue, 4), name, VectorType(ptype1, 4), - VectorType(ptype2, 4), VectorType(ptype3, 4)); - } - else - { - TFunction *function = new TFunction(this, NewPoolTString(name), rvalue, op, ext); - - function->addParameter(TConstParameter(ptype1)); - - if (ptype2) - { - function->addParameter(TConstParameter(ptype2)); - } - - if (ptype3) - { - function->addParameter(TConstParameter(ptype3)); - } - - if (ptype4) - { - function->addParameter(TConstParameter(ptype4)); - } - - if (ptype5) - { - function->addParameter(TConstParameter(ptype5)); - } - - ASSERT(hasUnmangledBuiltInAtLevel(name, level)); - insert(level, function); - } -} - -void TSymbolTable::insertBuiltInOp(ESymbolLevel level, - TOperator op, - const TType *rvalue, - const TType *ptype1, - const TType *ptype2, - const TType *ptype3, - const TType *ptype4, - const TType *ptype5) -{ - const char *name = GetOperatorString(op); - ASSERT(strlen(name) > 0); - insertUnmangledBuiltInName(name, level); - insertBuiltIn(level, op, TExtension::UNDEFINED, rvalue, name, ptype1, ptype2, ptype3, ptype4, - ptype5); -} - -void TSymbolTable::insertBuiltInOp(ESymbolLevel level, - TOperator op, - TExtension ext, - const TType *rvalue, - const TType *ptype1, - const TType *ptype2, - const TType *ptype3, - const TType *ptype4, - const TType *ptype5) -{ - const char *name = GetOperatorString(op); - insertUnmangledBuiltInName(name, level); - insertBuiltIn(level, op, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); -} - -void TSymbolTable::insertBuiltInFunctionNoParameters(ESymbolLevel level, - TOperator op, - const TType *rvalue, - const char *name) -{ - insertUnmangledBuiltInName(name, level); - insert(level, new TFunction(this, NewPoolTString(name), rvalue, op)); -} - -void TSymbolTable::insertBuiltInFunctionNoParametersExt(ESymbolLevel level, - TExtension ext, - TOperator op, - const TType *rvalue, - const char *name) -{ - insertUnmangledBuiltInName(name, level); - insert(level, new TFunction(this, NewPoolTString(name), rvalue, op, ext)); -} - -TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const -{ - if (!SupportsPrecision(type)) - return EbpUndefined; - - // unsigned integers use the same precision as signed - TBasicType baseType = (type == EbtUInt) ? EbtInt : type; - - int level = static_cast<int>(precisionStack.size()) - 1; - assert(level >= 0); // Just to be safe. Should not happen. - // If we dont find anything we return this. Some types don't have predefined default precision. - TPrecision prec = EbpUndefined; - while (level >= 0) - { - PrecisionStackLevel::iterator it = precisionStack[level]->find(baseType); - if (it != precisionStack[level]->end()) - { - prec = (*it).second; - break; - } - level--; - } - return prec; -} - -void TSymbolTable::insertUnmangledBuiltInName(const char *name, ESymbolLevel level) -{ - ASSERT(level >= 0 && level < static_cast<ESymbolLevel>(table.size())); - table[level]->insertUnmangledBuiltInName(std::string(name)); -} - -bool TSymbolTable::hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level) -{ - ASSERT(level >= 0 && level < static_cast<ESymbolLevel>(table.size())); - return table[level]->hasUnmangledBuiltIn(std::string(name)); -} - -bool TSymbolTable::hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion) -{ - ASSERT(static_cast<ESymbolLevel>(table.size()) > LAST_BUILTIN_LEVEL); - - for (int level = LAST_BUILTIN_LEVEL; level >= 0; --level) - { - if (level == ESSL3_1_BUILTINS && shaderVersion != 310) - { - --level; - } - if (level == ESSL3_BUILTINS && shaderVersion < 300) - { - --level; - } - if (level == ESSL1_BUILTINS && shaderVersion != 100) - { - --level; - } - - if (table[level]->hasUnmangledBuiltIn(name)) - { - return true; - } - } - return false; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h deleted file mode 100644 index 5d792ec188..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h +++ /dev/null @@ -1,545 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_H_ -#define COMPILER_TRANSLATOR_SYMBOLTABLE_H_ - -// -// Symbol table for parsing. Has these design characteristics: -// -// * Same symbol table can be used to compile many shaders, to preserve -// effort of creating and loading with the large numbers of built-in -// symbols. -// -// * Name mangling will be used to give each function a unique name -// so that symbol table lookups are never ambiguous. This allows -// a simpler symbol table structure. -// -// * Pushing and popping of scope, so symbol table will really be a stack -// of symbol tables. Searched from the top, with new inserts going into -// the top. -// -// * Constants: Compile time constant symbols will keep their values -// in the symbol table. The parser can substitute constants at parse -// time, including doing constant folding and constant propagation. -// -// * No temporaries: Temporaries made from operations (+, --, .xy, etc.) -// are tracked in the intermediate representation, not the symbol table. -// - -#include <array> -#include <assert.h> -#include <set> - -#include "common/angleutils.h" -#include "compiler/translator/ExtensionBehavior.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/SymbolUniqueId.h" - -namespace sh -{ - -// Symbol base class. (Can build functions or variables out of these...) -class TSymbol : angle::NonCopyable -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TSymbol(TSymbolTable *symbolTable, const TString *n); - - virtual ~TSymbol() - { - // don't delete name, it's from the pool - } - - const TString &getName() const { return *name; } - virtual const TString &getMangledName() const { return getName(); } - virtual bool isFunction() const { return false; } - virtual bool isVariable() const { return false; } - const TSymbolUniqueId &getUniqueId() const { return uniqueId; } - void relateToExtension(TExtension ext) { extension = ext; } - TExtension getExtension() const { return extension; } - - private: - const TSymbolUniqueId uniqueId; - const TString *name; - TExtension extension; -}; - -// Variable, meaning a symbol that's not a function. -// -// May store the value of a constant variable of any type (float, int, bool or struct). -class TVariable : public TSymbol -{ - public: - ~TVariable() override {} - bool isVariable() const override { return true; } - TType &getType() { return type; } - const TType &getType() const { return type; } - bool isUserType() const { return userType; } - void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); } - - const TConstantUnion *getConstPointer() const { return unionArray; } - - void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; } - - private: - friend class TSymbolTable; - - TVariable(TSymbolTable *symbolTable, - const TString *name, - const TType &t, - bool isUserTypeDefinition = false) - : TSymbol(symbolTable, name), type(t), userType(isUserTypeDefinition), unionArray(0) - { - } - - TType type; - - // Set to true if this represents a struct type, as opposed to a variable. - bool userType; - - // we are assuming that Pool Allocator will free the memory - // allocated to unionArray when this object is destroyed. - const TConstantUnion *unionArray; -}; - -// Immutable version of TParameter. -struct TConstParameter -{ - TConstParameter() : name(nullptr), type(nullptr) {} - explicit TConstParameter(const TString *n) : name(n), type(nullptr) {} - explicit TConstParameter(const TType *t) : name(nullptr), type(t) {} - TConstParameter(const TString *n, const TType *t) : name(n), type(t) {} - - // Both constructor arguments must be const. - TConstParameter(TString *n, TType *t) = delete; - TConstParameter(const TString *n, TType *t) = delete; - TConstParameter(TString *n, const TType *t) = delete; - - const TString *const name; - const TType *const type; -}; - -// The function sub-class of symbols and the parser will need to -// share this definition of a function parameter. -struct TParameter -{ - // Destructively converts to TConstParameter. - // This method resets name and type to nullptrs to make sure - // their content cannot be modified after the call. - TConstParameter turnToConst() - { - const TString *constName = name; - const TType *constType = type; - name = nullptr; - type = nullptr; - return TConstParameter(constName, constType); - } - - const TString *name; - TType *type; -}; - -// The function sub-class of a symbol. -class TFunction : public TSymbol -{ - public: - TFunction(TSymbolTable *symbolTable, - const TString *name, - const TType *retType, - TOperator tOp = EOpNull, - TExtension ext = TExtension::UNDEFINED) - : TSymbol(symbolTable, name), - returnType(retType), - mangledName(nullptr), - op(tOp), - defined(false), - mHasPrototypeDeclaration(false) - { - relateToExtension(ext); - } - ~TFunction() override; - bool isFunction() const override { return true; } - - void addParameter(const TConstParameter &p) - { - parameters.push_back(p); - mangledName = nullptr; - } - - void swapParameters(const TFunction ¶metersSource); - - const TString &getMangledName() const override - { - if (mangledName == nullptr) - { - mangledName = buildMangledName(); - } - return *mangledName; - } - - static const TString &GetMangledNameFromCall(const TString &functionName, - const TIntermSequence &arguments); - - const TType &getReturnType() const { return *returnType; } - - TOperator getBuiltInOp() const { return op; } - - void setDefined() { defined = true; } - bool isDefined() { return defined; } - void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; } - bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; } - - size_t getParamCount() const { return parameters.size(); } - const TConstParameter &getParam(size_t i) const { return parameters[i]; } - - private: - void clearParameters(); - - const TString *buildMangledName() const; - - typedef TVector<TConstParameter> TParamList; - TParamList parameters; - const TType *returnType; - mutable const TString *mangledName; - TOperator op; - bool defined; - bool mHasPrototypeDeclaration; -}; - -// Interface block name sub-symbol -class TInterfaceBlockName : public TSymbol -{ - public: - virtual ~TInterfaceBlockName() {} - - private: - friend class TSymbolTable; - TInterfaceBlockName(TSymbolTable *symbolTable, const TString *name) : TSymbol(symbolTable, name) - { - } -}; - -class TSymbolTableLevel -{ - public: - typedef TUnorderedMap<TString, TSymbol *> tLevel; - typedef tLevel::const_iterator const_iterator; - typedef const tLevel::value_type tLevelPair; - typedef std::pair<tLevel::iterator, bool> tInsertResult; - - TSymbolTableLevel() : mGlobalInvariant(false) {} - ~TSymbolTableLevel(); - - bool insert(TSymbol *symbol); - - // Insert a function using its unmangled name as the key. - bool insertUnmangled(TFunction *function); - - TSymbol *find(const TString &name) const; - - void addInvariantVarying(const std::string &name) { mInvariantVaryings.insert(name); } - - bool isVaryingInvariant(const std::string &name) - { - return (mGlobalInvariant || mInvariantVaryings.count(name) > 0); - } - - void setGlobalInvariant(bool invariant) { mGlobalInvariant = invariant; } - - void insertUnmangledBuiltInName(const std::string &name) - { - mUnmangledBuiltInNames.insert(name); - } - - bool hasUnmangledBuiltIn(const std::string &name) - { - return mUnmangledBuiltInNames.count(name) > 0; - } - - protected: - tLevel level; - std::set<std::string> mInvariantVaryings; - bool mGlobalInvariant; - - private: - std::set<std::string> mUnmangledBuiltInNames; -}; - -// Define ESymbolLevel as int rather than an enum since level can go -// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the -// compiler optimizes the >= of the last element to ==. -typedef int ESymbolLevel; -const int COMMON_BUILTINS = 0; -const int ESSL1_BUILTINS = 1; -const int ESSL3_BUILTINS = 2; -const int ESSL3_1_BUILTINS = 3; -// GLSL_BUILTINS are desktop GLSL builtins that don't exist in ESSL but are used to implement -// features in ANGLE's GLSL backend. They're not visible to the parser. -const int GLSL_BUILTINS = 4; -const int LAST_BUILTIN_LEVEL = GLSL_BUILTINS; -const int GLOBAL_LEVEL = 5; - -class TSymbolTable : angle::NonCopyable -{ - public: - TSymbolTable() : mUniqueIdCounter(0), mEmptySymbolId(this) - { - // The symbol table cannot be used until push() is called, but - // the lack of an initial call to push() can be used to detect - // that the symbol table has not been preloaded with built-ins. - } - - ~TSymbolTable(); - - // When the symbol table is initialized with the built-ins, there should - // 'push' calls, so that built-ins are at level 0 and the shader - // globals are at level 1. - bool isEmpty() const { return table.empty(); } - bool atBuiltInLevel() const { return currentLevel() <= LAST_BUILTIN_LEVEL; } - bool atGlobalLevel() const { return currentLevel() == GLOBAL_LEVEL; } - void push() - { - table.push_back(new TSymbolTableLevel); - precisionStack.push_back(new PrecisionStackLevel); - } - - void pop() - { - delete table.back(); - table.pop_back(); - - delete precisionStack.back(); - precisionStack.pop_back(); - } - - // The declare* entry points are used when parsing and declare symbols at the current scope. - // They return the created symbol in case the declaration was successful, and nullptr if the - // declaration failed due to redefinition. - TVariable *declareVariable(const TString *name, const TType &type); - TVariable *declareStructType(TStructure *str); - TInterfaceBlockName *declareInterfaceBlockName(const TString *name); - - // The insert* entry points are used when initializing the symbol table with built-ins. - // They return the created symbol in case the declaration was successful, and nullptr if the - // declaration failed due to redefinition. - TVariable *insertVariable(ESymbolLevel level, const char *name, const TType &type); - TVariable *insertVariableExt(ESymbolLevel level, - TExtension ext, - const char *name, - const TType &type); - TVariable *insertStructType(ESymbolLevel level, TStructure *str); - TInterfaceBlockName *insertInterfaceBlockNameExt(ESymbolLevel level, - TExtension ext, - const TString *name); - - bool insertConstInt(ESymbolLevel level, const char *name, int value, TPrecision precision) - { - TVariable *constant = - new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 1)); - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray[0].setIConst(value); - constant->shareConstPointer(unionArray); - return insert(level, constant); - } - - bool insertConstIntExt(ESymbolLevel level, - TExtension ext, - const char *name, - int value, - TPrecision precision) - { - TVariable *constant = - new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 1)); - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray[0].setIConst(value); - constant->shareConstPointer(unionArray); - return insert(level, ext, constant); - } - - bool insertConstIvec3(ESymbolLevel level, - const char *name, - const std::array<int, 3> &values, - TPrecision precision) - { - TVariable *constantIvec3 = - new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 3)); - - TConstantUnion *unionArray = new TConstantUnion[3]; - for (size_t index = 0u; index < 3u; ++index) - { - unionArray[index].setIConst(values[index]); - } - constantIvec3->shareConstPointer(unionArray); - - return insert(level, constantIvec3); - } - - void insertBuiltIn(ESymbolLevel level, - TOperator op, - TExtension ext, - const TType *rvalue, - const char *name, - const TType *ptype1, - const TType *ptype2 = 0, - const TType *ptype3 = 0, - const TType *ptype4 = 0, - const TType *ptype5 = 0); - - void insertBuiltIn(ESymbolLevel level, - const TType *rvalue, - const char *name, - const TType *ptype1, - const TType *ptype2 = 0, - const TType *ptype3 = 0, - const TType *ptype4 = 0, - const TType *ptype5 = 0) - { - insertUnmangledBuiltInName(name, level); - insertBuiltIn(level, EOpNull, TExtension::UNDEFINED, rvalue, name, ptype1, ptype2, ptype3, - ptype4, ptype5); - } - - void insertBuiltIn(ESymbolLevel level, - TExtension ext, - const TType *rvalue, - const char *name, - const TType *ptype1, - const TType *ptype2 = 0, - const TType *ptype3 = 0, - const TType *ptype4 = 0, - const TType *ptype5 = 0) - { - insertUnmangledBuiltInName(name, level); - insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); - } - - void insertBuiltInOp(ESymbolLevel level, - TOperator op, - const TType *rvalue, - const TType *ptype1, - const TType *ptype2 = 0, - const TType *ptype3 = 0, - const TType *ptype4 = 0, - const TType *ptype5 = 0); - - void insertBuiltInOp(ESymbolLevel level, - TOperator op, - TExtension ext, - const TType *rvalue, - const TType *ptype1, - const TType *ptype2 = 0, - const TType *ptype3 = 0, - const TType *ptype4 = 0, - const TType *ptype5 = 0); - - void insertBuiltInFunctionNoParameters(ESymbolLevel level, - TOperator op, - const TType *rvalue, - const char *name); - - void insertBuiltInFunctionNoParametersExt(ESymbolLevel level, - TExtension ext, - TOperator op, - const TType *rvalue, - const char *name); - - TSymbol *find(const TString &name, - int shaderVersion, - bool *builtIn = nullptr, - bool *sameScope = nullptr) const; - - TSymbol *findGlobal(const TString &name) const; - - TSymbol *findBuiltIn(const TString &name, int shaderVersion) const; - - TSymbol *findBuiltIn(const TString &name, int shaderVersion, bool includeGLSLBuiltins) const; - - TSymbolTableLevel *getOuterLevel() - { - assert(currentLevel() >= 1); - return table[currentLevel() - 1]; - } - - void setDefaultPrecision(TBasicType type, TPrecision prec) - { - int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1; - // Uses map operator [], overwrites the current value - (*precisionStack[indexOfLastElement])[type] = prec; - } - - // Searches down the precisionStack for a precision qualifier - // for the specified TBasicType - TPrecision getDefaultPrecision(TBasicType type) const; - - // This records invariant varyings declared through - // "invariant varying_name;". - void addInvariantVarying(const std::string &originalName) - { - ASSERT(atGlobalLevel()); - table[currentLevel()]->addInvariantVarying(originalName); - } - // If this returns false, the varying could still be invariant - // if it is set as invariant during the varying variable - // declaration - this piece of information is stored in the - // variable's type, not here. - bool isVaryingInvariant(const std::string &originalName) const - { - ASSERT(atGlobalLevel()); - return table[currentLevel()]->isVaryingInvariant(originalName); - } - - void setGlobalInvariant(bool invariant) - { - ASSERT(atGlobalLevel()); - table[currentLevel()]->setGlobalInvariant(invariant); - } - - const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); } - - // The empty symbol id is shared between all empty string ("") symbols. They are used in the - // AST for unused function parameters and struct type declarations that don't declare a - // variable, for example. - const TSymbolUniqueId &getEmptySymbolId() { return mEmptySymbolId; } - - // Checks whether there is a built-in accessible by a shader with the specified version. - bool hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion); - - private: - friend class TSymbolUniqueId; - int nextUniqueIdValue() { return ++mUniqueIdCounter; } - - ESymbolLevel currentLevel() const { return static_cast<ESymbolLevel>(table.size() - 1); } - - TVariable *insertVariable(ESymbolLevel level, const TString *name, const TType &type); - - bool insert(ESymbolLevel level, TSymbol *symbol) { return table[level]->insert(symbol); } - - bool insert(ESymbolLevel level, TExtension ext, TSymbol *symbol) - { - symbol->relateToExtension(ext); - return table[level]->insert(symbol); - } - - // Used to insert unmangled functions to check redeclaration of built-ins in ESSL 3.00 and - // above. - void insertUnmangledBuiltInName(const char *name, ESymbolLevel level); - - bool hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level); - - std::vector<TSymbolTableLevel *> table; - typedef TMap<TBasicType, TPrecision> PrecisionStackLevel; - std::vector<PrecisionStackLevel *> precisionStack; - - int mUniqueIdCounter; - - const TSymbolUniqueId mEmptySymbolId; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp deleted file mode 100644 index 2a68ae3e70..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SymbolUniqueId.cpp: Encapsulates a unique id for a symbol. - -#include "compiler/translator/SymbolUniqueId.h" - -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -TSymbolUniqueId::TSymbolUniqueId(TSymbolTable *symbolTable) : mId(symbolTable->nextUniqueIdValue()) -{ -} - -TSymbolUniqueId::TSymbolUniqueId(const TSymbol &symbol) : mId(symbol.getUniqueId().get()) -{ -} - -int TSymbolUniqueId::get() const -{ - return mId; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h b/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h deleted file mode 100644 index 4bd5604246..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// SymbolUniqueId.h: Encapsulates a unique id for a symbol. - -#ifndef COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_ -#define COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_ - -#include "compiler/translator/Common.h" - -namespace sh -{ - -class TSymbolTable; -class TSymbol; - -class TSymbolUniqueId -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - explicit TSymbolUniqueId(TSymbolTable *symbolTable); - explicit TSymbolUniqueId(const TSymbol &symbol); - TSymbolUniqueId(const TSymbolUniqueId &) = default; - TSymbolUniqueId &operator=(const TSymbolUniqueId &) = default; - - int get() const; - - private: - int mId; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp deleted file mode 100644 index d2b65a6c56..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp +++ /dev/null @@ -1,1322 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// TextureFunctionHLSL: Class for writing implementations of ESSL texture functions into HLSL -// output. Some of the implementations are straightforward and just call the HLSL equivalent of the -// ESSL texture function, others do more work to emulate ESSL texture sampling or size query -// behavior. -// - -#include "compiler/translator/TextureFunctionHLSL.h" - -#include "compiler/translator/UtilsHLSL.h" - -namespace sh -{ - -namespace -{ - -void OutputIntTexCoordWrap(TInfoSinkBase &out, - const char *wrapMode, - const char *size, - const TString &texCoord, - const TString &texCoordOffset, - const char *texCoordOutName) -{ - // GLES 3.0.4 table 3.22 specifies how the wrap modes work. We don't use the formulas verbatim - // but rather use equivalent formulas that map better to HLSL. - out << "int " << texCoordOutName << ";\n"; - out << "float " << texCoordOutName << "Offset = " << texCoord << " + float(" << texCoordOffset - << ") / " << size << ";\n"; - - // CLAMP_TO_EDGE - out << "if (" << wrapMode << " == 1)\n"; - out << "{\n"; - out << " " << texCoordOutName << " = clamp(int(floor(" << size << " * " << texCoordOutName - << "Offset)), 0, int(" << size << ") - 1);\n"; - out << "}\n"; - - // MIRRORED_REPEAT - out << "else if (" << wrapMode << " == 3)\n"; - out << "{\n"; - out << " float coordWrapped = 1.0 - abs(frac(abs(" << texCoordOutName - << "Offset) * 0.5) * 2.0 - 1.0);\n"; - out << " " << texCoordOutName << " = int(floor(" << size << " * coordWrapped));\n"; - out << "}\n"; - - // REPEAT - out << "else\n"; - out << "{\n"; - out << " " << texCoordOutName << " = int(floor(" << size << " * frac(" << texCoordOutName - << "Offset)));\n"; - out << "}\n"; -} - -void OutputIntTexCoordWraps(TInfoSinkBase &out, - const TextureFunctionHLSL::TextureFunction &textureFunction, - TString *texCoordX, - TString *texCoordY, - TString *texCoordZ) -{ - // Convert from normalized floating-point to integer - out << "int wrapS = samplerMetadata[samplerIndex].wrapModes & 0x3;\n"; - if (textureFunction.offset) - { - OutputIntTexCoordWrap(out, "wrapS", "width", *texCoordX, "offset.x", "tix"); - } - else - { - OutputIntTexCoordWrap(out, "wrapS", "width", *texCoordX, "0", "tix"); - } - *texCoordX = "tix"; - out << "int wrapT = (samplerMetadata[samplerIndex].wrapModes >> 2) & 0x3;\n"; - if (textureFunction.offset) - { - OutputIntTexCoordWrap(out, "wrapT", "height", *texCoordY, "offset.y", "tiy"); - } - else - { - OutputIntTexCoordWrap(out, "wrapT", "height", *texCoordY, "0", "tiy"); - } - *texCoordY = "tiy"; - - if (IsSamplerArray(textureFunction.sampler)) - { - *texCoordZ = "int(max(0, min(layers - 1, floor(0.5 + t.z))))"; - } - else if (!IsSamplerCube(textureFunction.sampler) && !IsSampler2D(textureFunction.sampler)) - { - out << "int wrapR = (samplerMetadata[samplerIndex].wrapModes >> 4) & 0x3;\n"; - if (textureFunction.offset) - { - OutputIntTexCoordWrap(out, "wrapR", "depth", *texCoordZ, "offset.z", "tiz"); - } - else - { - OutputIntTexCoordWrap(out, "wrapR", "depth", *texCoordZ, "0", "tiz"); - } - *texCoordZ = "tiz"; - } -} - -void OutputHLSL4SampleFunctionPrefix(TInfoSinkBase &out, - const TextureFunctionHLSL::TextureFunction &textureFunction, - const TString &textureReference, - const TString &samplerReference) -{ - out << textureReference; - if (IsIntegerSampler(textureFunction.sampler) || - textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH) - { - out << ".Load("; - return; - } - - if (IsShadowSampler(textureFunction.sampler)) - { - switch (textureFunction.method) - { - case TextureFunctionHLSL::TextureFunction::IMPLICIT: - case TextureFunctionHLSL::TextureFunction::BIAS: - case TextureFunctionHLSL::TextureFunction::LOD: - out << ".SampleCmp("; - break; - case TextureFunctionHLSL::TextureFunction::LOD0: - case TextureFunctionHLSL::TextureFunction::LOD0BIAS: - case TextureFunctionHLSL::TextureFunction::GRAD: - out << ".SampleCmpLevelZero("; - break; - default: - UNREACHABLE(); - } - } - else - { - switch (textureFunction.method) - { - case TextureFunctionHLSL::TextureFunction::IMPLICIT: - out << ".Sample("; - break; - case TextureFunctionHLSL::TextureFunction::BIAS: - out << ".SampleBias("; - break; - case TextureFunctionHLSL::TextureFunction::LOD: - case TextureFunctionHLSL::TextureFunction::LOD0: - case TextureFunctionHLSL::TextureFunction::LOD0BIAS: - out << ".SampleLevel("; - break; - case TextureFunctionHLSL::TextureFunction::GRAD: - out << ".SampleGrad("; - break; - default: - UNREACHABLE(); - } - } - out << samplerReference << ", "; -} - -const char *GetSamplerCoordinateTypeString( - const TextureFunctionHLSL::TextureFunction &textureFunction, - int hlslCoords) -{ - if (IsIntegerSampler(textureFunction.sampler) || - textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH) - { - switch (hlslCoords) - { - case 2: - if (textureFunction.sampler == EbtSampler2DMS || - textureFunction.sampler == EbtISampler2DMS || - textureFunction.sampler == EbtUSampler2DMS) - return "int2"; - else - return "int3"; - case 3: - return "int4"; - default: - UNREACHABLE(); - } - } - else - { - switch (hlslCoords) - { - case 2: - return "float2"; - case 3: - return "float3"; - case 4: - return "float4"; - default: - UNREACHABLE(); - } - } - return ""; -} - -int GetHLSLCoordCount(const TextureFunctionHLSL::TextureFunction &textureFunction, - ShShaderOutput outputType) -{ - if (outputType == SH_HLSL_3_0_OUTPUT) - { - int hlslCoords = 2; - switch (textureFunction.sampler) - { - case EbtSampler2D: - case EbtSamplerExternalOES: - case EbtSampler2DMS: - hlslCoords = 2; - break; - case EbtSamplerCube: - hlslCoords = 3; - break; - default: - UNREACHABLE(); - } - - switch (textureFunction.method) - { - case TextureFunctionHLSL::TextureFunction::IMPLICIT: - case TextureFunctionHLSL::TextureFunction::GRAD: - return hlslCoords; - case TextureFunctionHLSL::TextureFunction::BIAS: - case TextureFunctionHLSL::TextureFunction::LOD: - case TextureFunctionHLSL::TextureFunction::LOD0: - case TextureFunctionHLSL::TextureFunction::LOD0BIAS: - return 4; - default: - UNREACHABLE(); - } - } - else - { - switch (textureFunction.sampler) - { - case EbtSampler2D: - return 2; - case EbtSampler2DMS: - return 2; - case EbtSampler3D: - return 3; - case EbtSamplerCube: - return 3; - case EbtSampler2DArray: - return 3; - case EbtSamplerExternalOES: - return 2; - case EbtISampler2D: - return 2; - case EbtISampler2DMS: - return 2; - case EbtISampler3D: - return 3; - case EbtISamplerCube: - return 3; - case EbtISampler2DArray: - return 3; - case EbtUSampler2D: - return 2; - case EbtUSampler2DMS: - return 2; - case EbtUSampler3D: - return 3; - case EbtUSamplerCube: - return 3; - case EbtUSampler2DArray: - return 3; - case EbtSampler2DShadow: - return 2; - case EbtSamplerCubeShadow: - return 3; - case EbtSampler2DArrayShadow: - return 3; - default: - UNREACHABLE(); - } - } - return 0; -} - -void OutputTextureFunctionArgumentList(TInfoSinkBase &out, - const TextureFunctionHLSL::TextureFunction &textureFunction, - const ShShaderOutput outputType) -{ - if (outputType == SH_HLSL_3_0_OUTPUT) - { - switch (textureFunction.sampler) - { - case EbtSampler2D: - case EbtSamplerExternalOES: - out << "sampler2D s"; - break; - case EbtSamplerCube: - out << "samplerCUBE s"; - break; - default: - UNREACHABLE(); - } - } - else - { - if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - out << TextureString(textureFunction.sampler) << " x, " - << SamplerString(textureFunction.sampler) << " s"; - } - else - { - ASSERT(outputType == SH_HLSL_4_1_OUTPUT); - // A bug in the D3D compiler causes some nested sampling operations to fail. - // See http://anglebug.com/1923 - // TODO(jmadill): Reinstate the const keyword when possible. - out << /*"const"*/ "uint samplerIndex"; - } - } - - if (textureFunction.method == - TextureFunctionHLSL::TextureFunction::FETCH) // Integer coordinates - { - switch (textureFunction.coords) - { - case 2: - out << ", int2 t"; - break; - case 3: - out << ", int3 t"; - break; - default: - UNREACHABLE(); - } - } - else // Floating-point coordinates (except textureSize) - { - switch (textureFunction.coords) - { - case 0: - break; // textureSize(gSampler2DMS sampler) - case 1: - out << ", int lod"; - break; // textureSize() - case 2: - out << ", float2 t"; - break; - case 3: - out << ", float3 t"; - break; - case 4: - out << ", float4 t"; - break; - default: - UNREACHABLE(); - } - } - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) - { - switch (textureFunction.sampler) - { - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - case EbtSampler2DShadow: - case EbtSampler2DArrayShadow: - case EbtSamplerExternalOES: - out << ", float2 ddx, float2 ddy"; - break; - case EbtSampler3D: - case EbtISampler3D: - case EbtUSampler3D: - case EbtSamplerCube: - case EbtISamplerCube: - case EbtUSamplerCube: - case EbtSamplerCubeShadow: - out << ", float3 ddx, float3 ddy"; - break; - default: - UNREACHABLE(); - } - } - - switch (textureFunction.method) - { - case TextureFunctionHLSL::TextureFunction::IMPLICIT: - break; - case TextureFunctionHLSL::TextureFunction::BIAS: - break; // Comes after the offset parameter - case TextureFunctionHLSL::TextureFunction::LOD: - out << ", float lod"; - break; - case TextureFunctionHLSL::TextureFunction::LOD0: - break; - case TextureFunctionHLSL::TextureFunction::LOD0BIAS: - break; // Comes after the offset parameter - case TextureFunctionHLSL::TextureFunction::SIZE: - break; - case TextureFunctionHLSL::TextureFunction::FETCH: - if (textureFunction.sampler == EbtSampler2DMS || - textureFunction.sampler == EbtISampler2DMS || - textureFunction.sampler == EbtUSampler2DMS) - out << ", int index"; - else - out << ", int mip"; - break; - case TextureFunctionHLSL::TextureFunction::GRAD: - break; - default: - UNREACHABLE(); - } - - if (textureFunction.offset) - { - switch (textureFunction.sampler) - { - case EbtSampler3D: - case EbtISampler3D: - case EbtUSampler3D: - out << ", int3 offset"; - break; - case EbtSampler2D: - case EbtSampler2DArray: - case EbtISampler2D: - case EbtISampler2DArray: - case EbtUSampler2D: - case EbtUSampler2DArray: - case EbtSampler2DShadow: - case EbtSampler2DArrayShadow: - case EbtSampler2DMS: - case EbtISampler2DMS: - case EbtUSampler2DMS: - case EbtSamplerExternalOES: - out << ", int2 offset"; - break; - default: - UNREACHABLE(); - } - } - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS || - textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS) - { - out << ", float bias"; - } -} - -void GetTextureReference(TInfoSinkBase &out, - const TextureFunctionHLSL::TextureFunction &textureFunction, - const ShShaderOutput outputType, - TString *textureReference, - TString *samplerReference) -{ - if (outputType == SH_HLSL_4_1_OUTPUT) - { - TString suffix = TextureGroupSuffix(textureFunction.sampler); - if (TextureGroup(textureFunction.sampler) == HLSL_TEXTURE_2D) - { - *textureReference = TString("textures") + suffix + "[samplerIndex]"; - *samplerReference = TString("samplers") + suffix + "[samplerIndex]"; - } - else - { - out << " const uint textureIndex = samplerIndex - textureIndexOffset" << suffix - << ";\n"; - *textureReference = TString("textures") + suffix + "[textureIndex]"; - out << " const uint samplerArrayIndex = samplerIndex - samplerIndexOffset" << suffix - << ";\n"; - *samplerReference = TString("samplers") + suffix + "[samplerArrayIndex]"; - } - } - else - { - *textureReference = "x"; - *samplerReference = "s"; - } -} - -void OutputTextureSizeFunctionBody(TInfoSinkBase &out, - const TextureFunctionHLSL::TextureFunction &textureFunction, - const TString &textureReference, - bool getDimensionsIgnoresBaseLevel) -{ - if (IsSampler2DMS(textureFunction.sampler)) - { - out << " uint width; uint height; uint samples;\n" - << " " << textureReference << ".GetDimensions(width, height, samples);\n"; - } - else - { - if (getDimensionsIgnoresBaseLevel) - { - out << " int baseLevel = samplerMetadata[samplerIndex].baseLevel;\n"; - } - else - { - out << " int baseLevel = 0;\n"; - } - - if (IsSampler3D(textureFunction.sampler) || IsSamplerArray(textureFunction.sampler) || - (IsIntegerSampler(textureFunction.sampler) && IsSamplerCube(textureFunction.sampler))) - { - // "depth" stores either the number of layers in an array texture or 3D depth - out << " uint width; uint height; uint depth; uint numberOfLevels;\n" - << " " << textureReference - << ".GetDimensions(baseLevel, width, height, depth, numberOfLevels);\n" - << " width = max(width >> lod, 1);\n" - << " height = max(height >> lod, 1);\n"; - - if (!IsSamplerArray(textureFunction.sampler)) - { - out << " depth = max(depth >> lod, 1);\n"; - } - } - else if (IsSampler2D(textureFunction.sampler) || IsSamplerCube(textureFunction.sampler)) - { - out << " uint width; uint height; uint numberOfLevels;\n" - << " " << textureReference - << ".GetDimensions(baseLevel, width, height, numberOfLevels);\n" - << " width = max(width >> lod, 1);\n" - << " height = max(height >> lod, 1);\n"; - } - else - UNREACHABLE(); - } - - if (strcmp(textureFunction.getReturnType(), "int3") == 0) - { - out << " return int3(width, height, depth);\n"; - } - else - { - out << " return int2(width, height);\n"; - } -} - -void ProjectTextureCoordinates(const TextureFunctionHLSL::TextureFunction &textureFunction, - TString *texCoordX, - TString *texCoordY, - TString *texCoordZ) -{ - if (textureFunction.proj) - { - TString proj(""); - switch (textureFunction.coords) - { - case 3: - proj = " / t.z"; - break; - case 4: - proj = " / t.w"; - break; - default: - UNREACHABLE(); - } - *texCoordX = "(" + *texCoordX + proj + ")"; - *texCoordY = "(" + *texCoordY + proj + ")"; - *texCoordZ = "(" + *texCoordZ + proj + ")"; - } -} - -void OutputIntegerTextureSampleFunctionComputations( - TInfoSinkBase &out, - const TextureFunctionHLSL::TextureFunction &textureFunction, - const ShShaderOutput outputType, - const TString &textureReference, - TString *texCoordX, - TString *texCoordY, - TString *texCoordZ) -{ - if (!IsIntegerSampler(textureFunction.sampler)) - { - return; - } - if (IsSamplerCube(textureFunction.sampler)) - { - out << " float width; float height; float layers; float levels;\n"; - - out << " uint mip = 0;\n"; - - out << " " << textureReference - << ".GetDimensions(mip, width, height, layers, levels);\n"; - - out << " bool xMajor = abs(t.x) > abs(t.y) && abs(t.x) > abs(t.z);\n"; - out << " bool yMajor = abs(t.y) > abs(t.z) && abs(t.y) > abs(t.x);\n"; - out << " bool zMajor = abs(t.z) > abs(t.x) && abs(t.z) > abs(t.y);\n"; - out << " bool negative = (xMajor && t.x < 0.0f) || (yMajor && t.y < 0.0f) || " - "(zMajor && t.z < 0.0f);\n"; - - // FACE_POSITIVE_X = 000b - // FACE_NEGATIVE_X = 001b - // FACE_POSITIVE_Y = 010b - // FACE_NEGATIVE_Y = 011b - // FACE_POSITIVE_Z = 100b - // FACE_NEGATIVE_Z = 101b - out << " int face = (int)negative + (int)yMajor * 2 + (int)zMajor * 4;\n"; - - out << " float u = xMajor ? -t.z : (yMajor && t.y < 0.0f ? -t.x : t.x);\n"; - out << " float v = yMajor ? t.z : (negative ? t.y : -t.y);\n"; - out << " float m = xMajor ? t.x : (yMajor ? t.y : t.z);\n"; - - out << " t.x = (u * 0.5f / m) + 0.5f;\n"; - out << " t.y = (v * 0.5f / m) + 0.5f;\n"; - - // Mip level computation. - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT || - textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD || - textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) - { - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT) - { - out << " float2 tSized = float2(t.x * width, t.y * height);\n" - " float2 dx = ddx(tSized);\n" - " float2 dy = ddy(tSized);\n" - " float lod = 0.5f * log2(max(dot(dx, dx), dot(dy, dy)));\n"; - } - else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) - { - // ESSL 3.00.6 spec section 8.8: "For the cube version, the partial - // derivatives of P are assumed to be in the coordinate system used before - // texture coordinates are projected onto the appropriate cube face." - // ddx[0] and ddy[0] are the derivatives of t.x passed into the function - // ddx[1] and ddy[1] are the derivatives of t.y passed into the function - // ddx[2] and ddy[2] are the derivatives of t.z passed into the function - // Determine the derivatives of u, v and m - out << " float dudx = xMajor ? ddx[2] : (yMajor && t.y < 0.0f ? -ddx[0] " - ": ddx[0]);\n" - " float dudy = xMajor ? ddy[2] : (yMajor && t.y < 0.0f ? -ddy[0] " - ": ddy[0]);\n" - " float dvdx = yMajor ? ddx[2] : (negative ? ddx[1] : -ddx[1]);\n" - " float dvdy = yMajor ? ddy[2] : (negative ? ddy[1] : -ddy[1]);\n" - " float dmdx = xMajor ? ddx[0] : (yMajor ? ddx[1] : ddx[2]);\n" - " float dmdy = xMajor ? ddy[0] : (yMajor ? ddy[1] : ddy[2]);\n"; - // Now determine the derivatives of the face coordinates, using the - // derivatives calculated above. - // d / dx (u(x) * 0.5 / m(x) + 0.5) - // = 0.5 * (m(x) * u'(x) - u(x) * m'(x)) / m(x)^2 - out << " float dfacexdx = 0.5f * (m * dudx - u * dmdx) / (m * m);\n" - " float dfaceydx = 0.5f * (m * dvdx - v * dmdx) / (m * m);\n" - " float dfacexdy = 0.5f * (m * dudy - u * dmdy) / (m * m);\n" - " float dfaceydy = 0.5f * (m * dvdy - v * dmdy) / (m * m);\n" - " float2 sizeVec = float2(width, height);\n" - " float2 faceddx = float2(dfacexdx, dfaceydx) * sizeVec;\n" - " float2 faceddy = float2(dfacexdy, dfaceydy) * sizeVec;\n"; - // Optimization: instead of: log2(max(length(faceddx), length(faceddy))) - // we compute: log2(max(length(faceddx)^2, length(faceddy)^2)) / 2 - out << " float lengthfaceddx2 = dot(faceddx, faceddx);\n" - " float lengthfaceddy2 = dot(faceddy, faceddy);\n" - " float lod = log2(max(lengthfaceddx2, lengthfaceddy2)) * 0.5f;\n"; - } - out << " mip = uint(min(max(round(lod), 0), levels - 1));\n" - << " " << textureReference - << ".GetDimensions(mip, width, height, layers, levels);\n"; - } - - // Convert from normalized floating-point to integer - *texCoordX = "int(floor(width * frac(" + *texCoordX + ")))"; - *texCoordY = "int(floor(height * frac(" + *texCoordY + ")))"; - *texCoordZ = "face"; - } - else if (textureFunction.method != TextureFunctionHLSL::TextureFunction::FETCH) - { - if (IsSampler2D(textureFunction.sampler)) - { - if (IsSamplerArray(textureFunction.sampler)) - { - out << " float width; float height; float layers; float levels;\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0) - { - out << " uint mip = 0;\n"; - } - else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS) - { - out << " uint mip = bias;\n"; - } - else - { - - out << " " << textureReference - << ".GetDimensions(0, width, height, layers, levels);\n"; - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT || - textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) - { - out << " float2 tSized = float2(t.x * width, t.y * height);\n" - " float dx = length(ddx(tSized));\n" - " float dy = length(ddy(tSized));\n" - " float lod = log2(max(dx, dy));\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) - { - out << " lod += bias;\n"; - } - } - else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) - { - out << " float2 sizeVec = float2(width, height);\n" - " float2 sizeDdx = ddx * sizeVec;\n" - " float2 sizeDdy = ddy * sizeVec;\n" - " float lod = log2(max(dot(sizeDdx, sizeDdx), " - "dot(sizeDdy, sizeDdy))) * 0.5f;\n"; - } - - out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n"; - } - - out << " " << textureReference - << ".GetDimensions(mip, width, height, layers, levels);\n"; - } - else - { - out << " float width; float height; float levels;\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0) - { - out << " uint mip = 0;\n"; - } - else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS) - { - out << " uint mip = bias;\n"; - } - else - { - out << " " << textureReference - << ".GetDimensions(0, width, height, levels);\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT || - textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) - { - out << " float2 tSized = float2(t.x * width, t.y * height);\n" - " float dx = length(ddx(tSized));\n" - " float dy = length(ddy(tSized));\n" - " float lod = log2(max(dx, dy));\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) - { - out << " lod += bias;\n"; - } - } - else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) - { - out << " float2 sizeVec = float2(width, height);\n" - " float2 sizeDdx = ddx * sizeVec;\n" - " float2 sizeDdy = ddy * sizeVec;\n" - " float lod = log2(max(dot(sizeDdx, sizeDdx), " - "dot(sizeDdy, sizeDdy))) * 0.5f;\n"; - } - - out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n"; - } - - out << " " << textureReference - << ".GetDimensions(mip, width, height, levels);\n"; - } - } - else if (IsSampler3D(textureFunction.sampler)) - { - out << " float width; float height; float depth; float levels;\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0) - { - out << " uint mip = 0;\n"; - } - else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS) - { - out << " uint mip = bias;\n"; - } - else - { - out << " " << textureReference - << ".GetDimensions(0, width, height, depth, levels);\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT || - textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) - { - out << " float3 tSized = float3(t.x * width, t.y * height, t.z * depth);\n" - " float dx = length(ddx(tSized));\n" - " float dy = length(ddy(tSized));\n" - " float lod = log2(max(dx, dy));\n"; - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS) - { - out << " lod += bias;\n"; - } - } - else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) - { - out << " float3 sizeVec = float3(width, height, depth);\n" - " float3 sizeDdx = ddx * sizeVec;\n" - " float3 sizeDdy = ddy * sizeVec;\n" - " float lod = log2(max(dot(sizeDdx, sizeDdx), dot(sizeDdy, " - "sizeDdy))) * 0.5f;\n"; - } - - out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n"; - } - - out << " " << textureReference - << ".GetDimensions(mip, width, height, depth, levels);\n"; - } - else - UNREACHABLE(); - - OutputIntTexCoordWraps(out, textureFunction, texCoordX, texCoordY, texCoordZ); - } -} - -void OutputTextureSampleFunctionReturnStatement( - TInfoSinkBase &out, - const TextureFunctionHLSL::TextureFunction &textureFunction, - const ShShaderOutput outputType, - const TString &textureReference, - const TString &samplerReference, - const TString &texCoordX, - const TString &texCoordY, - const TString &texCoordZ) -{ - out << " return "; - - // HLSL intrinsic - if (outputType == SH_HLSL_3_0_OUTPUT) - { - switch (textureFunction.sampler) - { - case EbtSampler2D: - case EbtSamplerExternalOES: - out << "tex2D"; - break; - case EbtSamplerCube: - out << "texCUBE"; - break; - default: - UNREACHABLE(); - } - - switch (textureFunction.method) - { - case TextureFunctionHLSL::TextureFunction::IMPLICIT: - out << "(" << samplerReference << ", "; - break; - case TextureFunctionHLSL::TextureFunction::BIAS: - out << "bias(" << samplerReference << ", "; - break; - case TextureFunctionHLSL::TextureFunction::LOD: - out << "lod(" << samplerReference << ", "; - break; - case TextureFunctionHLSL::TextureFunction::LOD0: - out << "lod(" << samplerReference << ", "; - break; - case TextureFunctionHLSL::TextureFunction::LOD0BIAS: - out << "lod(" << samplerReference << ", "; - break; - case TextureFunctionHLSL::TextureFunction::GRAD: - out << "grad(" << samplerReference << ", "; - break; - default: - UNREACHABLE(); - } - } - else if (outputType == SH_HLSL_4_1_OUTPUT || outputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - OutputHLSL4SampleFunctionPrefix(out, textureFunction, textureReference, samplerReference); - } - else - UNREACHABLE(); - - const int hlslCoords = GetHLSLCoordCount(textureFunction, outputType); - - out << GetSamplerCoordinateTypeString(textureFunction, hlslCoords) << "(" << texCoordX << ", " - << texCoordY; - - if (outputType == SH_HLSL_3_0_OUTPUT) - { - if (hlslCoords >= 3) - { - if (textureFunction.coords < 3) - { - out << ", 0"; - } - else - { - out << ", " << texCoordZ; - } - } - - if (hlslCoords == 4) - { - switch (textureFunction.method) - { - case TextureFunctionHLSL::TextureFunction::BIAS: - out << ", bias"; - break; - case TextureFunctionHLSL::TextureFunction::LOD: - out << ", lod"; - break; - case TextureFunctionHLSL::TextureFunction::LOD0: - out << ", 0"; - break; - case TextureFunctionHLSL::TextureFunction::LOD0BIAS: - out << ", bias"; - break; - default: - UNREACHABLE(); - } - } - - out << ")"; - } - else if (outputType == SH_HLSL_4_1_OUTPUT || outputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - if (hlslCoords >= 3) - { - ASSERT(!IsIntegerSampler(textureFunction.sampler) || - !IsSamplerCube(textureFunction.sampler) || texCoordZ == "face"); - out << ", " << texCoordZ; - } - - if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD) - { - if (IsIntegerSampler(textureFunction.sampler)) - { - out << ", mip)"; - } - else if (IsShadowSampler(textureFunction.sampler)) - { - // Compare value - if (textureFunction.proj) - { - // According to ESSL 3.00.4 sec 8.8 p95 on textureProj: - // The resulting third component of P' in the shadow forms is used as - // Dref - out << "), " << texCoordZ; - } - else - { - switch (textureFunction.coords) - { - case 3: - out << "), t.z"; - break; - case 4: - out << "), t.w"; - break; - default: - UNREACHABLE(); - } - } - } - else - { - out << "), ddx, ddy"; - } - } - else if (IsIntegerSampler(textureFunction.sampler) || - textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH) - { - if (textureFunction.sampler == EbtSampler2DMS || - textureFunction.sampler == EbtISampler2DMS || - textureFunction.sampler == EbtUSampler2DMS) - out << "), index"; - else - out << ", mip)"; - } - else if (IsShadowSampler(textureFunction.sampler)) - { - // Compare value - if (textureFunction.proj) - { - // According to ESSL 3.00.4 sec 8.8 p95 on textureProj: - // The resulting third component of P' in the shadow forms is used as Dref - out << "), " << texCoordZ; - } - else - { - switch (textureFunction.coords) - { - case 3: - out << "), t.z"; - break; - case 4: - out << "), t.w"; - break; - default: - UNREACHABLE(); - } - } - } - else - { - switch (textureFunction.method) - { - case TextureFunctionHLSL::TextureFunction::IMPLICIT: - out << ")"; - break; - case TextureFunctionHLSL::TextureFunction::BIAS: - out << "), bias"; - break; - case TextureFunctionHLSL::TextureFunction::LOD: - out << "), lod"; - break; - case TextureFunctionHLSL::TextureFunction::LOD0: - out << "), 0"; - break; - case TextureFunctionHLSL::TextureFunction::LOD0BIAS: - out << "), bias"; - break; - default: - UNREACHABLE(); - } - } - - if (textureFunction.offset && - (!IsIntegerSampler(textureFunction.sampler) || - textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH)) - { - out << ", offset"; - } - } - else - UNREACHABLE(); - - out << ");\n"; // Close the sample function call and return statement -} - -} // Anonymous namespace - -TString TextureFunctionHLSL::TextureFunction::name() const -{ - TString name = "gl_texture"; - - // We need to include full the sampler type in the function name to make the signature unique - // on D3D11, where samplers are passed to texture functions as indices. - name += TextureTypeSuffix(this->sampler); - - if (proj) - { - name += "Proj"; - } - - if (offset) - { - name += "Offset"; - } - - switch (method) - { - case IMPLICIT: - break; - case BIAS: - break; // Extra parameter makes the signature unique - case LOD: - name += "Lod"; - break; - case LOD0: - name += "Lod0"; - break; - case LOD0BIAS: - name += "Lod0"; - break; // Extra parameter makes the signature unique - case SIZE: - name += "Size"; - break; - case FETCH: - name += "Fetch"; - break; - case GRAD: - name += "Grad"; - break; - default: - UNREACHABLE(); - } - - return name; -} - -const char *TextureFunctionHLSL::TextureFunction::getReturnType() const -{ - if (method == TextureFunction::SIZE) - { - switch (sampler) - { - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DShadow: - case EbtSamplerCube: - case EbtISamplerCube: - case EbtUSamplerCube: - case EbtSamplerCubeShadow: - case EbtSamplerExternalOES: - case EbtSampler2DMS: - case EbtISampler2DMS: - case EbtUSampler2DMS: - return "int2"; - case EbtSampler3D: - case EbtISampler3D: - case EbtUSampler3D: - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - case EbtSampler2DArrayShadow: - return "int3"; - default: - UNREACHABLE(); - } - } - else // Sampling function - { - switch (sampler) - { - case EbtSampler2D: - case EbtSampler2DMS: - case EbtSampler3D: - case EbtSamplerCube: - case EbtSampler2DArray: - case EbtSamplerExternalOES: - return "float4"; - case EbtISampler2D: - case EbtISampler2DMS: - case EbtISampler3D: - case EbtISamplerCube: - case EbtISampler2DArray: - return "int4"; - case EbtUSampler2D: - case EbtUSampler2DMS: - case EbtUSampler3D: - case EbtUSamplerCube: - case EbtUSampler2DArray: - return "uint4"; - case EbtSampler2DShadow: - case EbtSamplerCubeShadow: - case EbtSampler2DArrayShadow: - return "float"; - default: - UNREACHABLE(); - } - } - return ""; -} - -bool TextureFunctionHLSL::TextureFunction::operator<(const TextureFunction &rhs) const -{ - return std::tie(sampler, coords, proj, offset, method) < - std::tie(rhs.sampler, rhs.coords, rhs.proj, rhs.offset, rhs.method); -} - -TString TextureFunctionHLSL::useTextureFunction(const TString &name, - TBasicType samplerType, - int coords, - size_t argumentCount, - bool lod0, - sh::GLenum shaderType) -{ - TextureFunction textureFunction; - textureFunction.sampler = samplerType; - textureFunction.coords = coords; - textureFunction.method = TextureFunction::IMPLICIT; - textureFunction.proj = false; - textureFunction.offset = false; - - if (name == "texture2D" || name == "textureCube" || name == "texture") - { - textureFunction.method = TextureFunction::IMPLICIT; - } - else if (name == "texture2DProj" || name == "textureProj") - { - textureFunction.method = TextureFunction::IMPLICIT; - textureFunction.proj = true; - } - else if (name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod" || - name == "texture2DLodEXT" || name == "textureCubeLodEXT") - { - textureFunction.method = TextureFunction::LOD; - } - else if (name == "texture2DProjLod" || name == "textureProjLod" || - name == "texture2DProjLodEXT") - { - textureFunction.method = TextureFunction::LOD; - textureFunction.proj = true; - } - else if (name == "textureSize") - { - textureFunction.method = TextureFunction::SIZE; - } - else if (name == "textureOffset") - { - textureFunction.method = TextureFunction::IMPLICIT; - textureFunction.offset = true; - } - else if (name == "textureProjOffset") - { - textureFunction.method = TextureFunction::IMPLICIT; - textureFunction.offset = true; - textureFunction.proj = true; - } - else if (name == "textureLodOffset") - { - textureFunction.method = TextureFunction::LOD; - textureFunction.offset = true; - } - else if (name == "textureProjLodOffset") - { - textureFunction.method = TextureFunction::LOD; - textureFunction.proj = true; - textureFunction.offset = true; - } - else if (name == "texelFetch") - { - textureFunction.method = TextureFunction::FETCH; - } - else if (name == "texelFetchOffset") - { - textureFunction.method = TextureFunction::FETCH; - textureFunction.offset = true; - } - else if (name == "textureGrad" || name == "texture2DGradEXT") - { - textureFunction.method = TextureFunction::GRAD; - } - else if (name == "textureGradOffset") - { - textureFunction.method = TextureFunction::GRAD; - textureFunction.offset = true; - } - else if (name == "textureProjGrad" || name == "texture2DProjGradEXT" || - name == "textureCubeGradEXT") - { - textureFunction.method = TextureFunction::GRAD; - textureFunction.proj = true; - } - else if (name == "textureProjGradOffset") - { - textureFunction.method = TextureFunction::GRAD; - textureFunction.proj = true; - textureFunction.offset = true; - } - else - UNREACHABLE(); - - if (textureFunction.method == - TextureFunction::IMPLICIT) // Could require lod 0 or have a bias argument - { - size_t mandatoryArgumentCount = 2; // All functions have sampler and coordinate arguments - - if (textureFunction.offset) - { - mandatoryArgumentCount++; - } - - bool bias = (argumentCount > mandatoryArgumentCount); // Bias argument is optional - - if (lod0 || shaderType == GL_VERTEX_SHADER) - { - if (bias) - { - textureFunction.method = TextureFunction::LOD0BIAS; - } - else - { - textureFunction.method = TextureFunction::LOD0; - } - } - else if (bias) - { - textureFunction.method = TextureFunction::BIAS; - } - } - - mUsesTexture.insert(textureFunction); - return textureFunction.name(); -} - -void TextureFunctionHLSL::textureFunctionHeader(TInfoSinkBase &out, - const ShShaderOutput outputType, - bool getDimensionsIgnoresBaseLevel) -{ - for (const TextureFunction &textureFunction : mUsesTexture) - { - // Function header - out << textureFunction.getReturnType() << " " << textureFunction.name() << "("; - - OutputTextureFunctionArgumentList(out, textureFunction, outputType); - - out << ")\n" - "{\n"; - - // In some cases we use a variable to store the texture/sampler objects, but to work around - // a D3D11 compiler bug related to discard inside a loop that is conditional on texture - // sampling we need to call the function directly on references to the texture and sampler - // arrays. The bug was found using dEQP-GLES3.functional.shaders.discard*loop_texture* - // tests. - TString textureReference; - TString samplerReference; - GetTextureReference(out, textureFunction, outputType, &textureReference, &samplerReference); - - if (textureFunction.method == TextureFunction::SIZE) - { - OutputTextureSizeFunctionBody(out, textureFunction, textureReference, - getDimensionsIgnoresBaseLevel); - } - else - { - TString texCoordX("t.x"); - TString texCoordY("t.y"); - TString texCoordZ("t.z"); - ProjectTextureCoordinates(textureFunction, &texCoordX, &texCoordY, &texCoordZ); - OutputIntegerTextureSampleFunctionComputations(out, textureFunction, outputType, - textureReference, &texCoordX, &texCoordY, - &texCoordZ); - OutputTextureSampleFunctionReturnStatement(out, textureFunction, outputType, - textureReference, samplerReference, - texCoordX, texCoordY, texCoordZ); - } - - out << "}\n" - "\n"; - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h b/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h deleted file mode 100644 index 68bf8c0898..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// TextureFunctionHLSL: Class for writing implementations of ESSL texture functions into HLSL -// output. Some of the implementations are straightforward and just call the HLSL equivalent of the -// ESSL texture function, others do more work to emulate ESSL texture sampling or size query -// behavior. -// - -#ifndef COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_ -#define COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_ - -#include <set> - -#include "compiler/translator/BaseTypes.h" -#include "compiler/translator/Common.h" -#include "compiler/translator/InfoSink.h" -#include "GLSLANG/ShaderLang.h" - -namespace sh -{ - -class TextureFunctionHLSL final : angle::NonCopyable -{ - public: - struct TextureFunction - { - // See ESSL 3.00.6 section 8.8 for reference about what the different methods below do. - enum Method - { - IMPLICIT, // Mipmap LOD determined implicitly (standard lookup) - BIAS, - LOD, - LOD0, - LOD0BIAS, - SIZE, // textureSize() - FETCH, - GRAD - }; - - TString name() const; - - bool operator<(const TextureFunction &rhs) const; - - const char *getReturnType() const; - - TBasicType sampler; - int coords; - bool proj; - bool offset; - Method method; - }; - - // Returns the name of the texture function implementation to call. - // The name that's passed in is the name of the GLSL texture function that it should implement. - TString useTextureFunction(const TString &name, - TBasicType samplerType, - int coords, - size_t argumentCount, - bool lod0, - sh::GLenum shaderType); - - void textureFunctionHeader(TInfoSinkBase &out, - const ShShaderOutput outputType, - bool getDimensionsIgnoresBaseLevel); - - private: - typedef std::set<TextureFunction> TextureFunctionSet; - TextureFunctionSet mUsesTexture; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp deleted file mode 100644 index 23c967f944..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp +++ /dev/null @@ -1,184 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/TranslatorESSL.h" - -#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" -#include "compiler/translator/EmulatePrecision.h" -#include "compiler/translator/RecordConstantPrecision.h" -#include "compiler/translator/OutputESSL.h" -#include "angle_gl.h" - -namespace sh -{ - -TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec) - : TCompiler(type, spec, SH_ESSL_OUTPUT) -{ -} - -void TranslatorESSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, - ShCompileOptions compileOptions) -{ - if (compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION) - { - InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu); - } -} - -void TranslatorESSL::translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics * /*perfDiagnostics*/) -{ - TInfoSinkBase &sink = getInfoSink().obj; - - int shaderVer = getShaderVersion(); - if (shaderVer > 100) - { - sink << "#version " << shaderVer << " es\n"; - } - - // Write built-in extension behaviors. - writeExtensionBehavior(compileOptions); - - // Write pragmas after extensions because some drivers consider pragmas - // like non-preprocessor tokens. - writePragma(compileOptions); - - bool precisionEmulation = - getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; - - if (precisionEmulation) - { - EmulatePrecision emulatePrecision(&getSymbolTable(), shaderVer); - root->traverse(&emulatePrecision); - emulatePrecision.updateTree(); - emulatePrecision.writeEmulationHelpers(sink, shaderVer, SH_ESSL_OUTPUT); - } - - RecordConstantPrecision(root, &getSymbolTable()); - - // Write emulated built-in functions if needed. - if (!getBuiltInFunctionEmulator().isOutputEmpty()) - { - sink << "// BEGIN: Generated code for built-in function emulation\n\n"; - if (getShaderType() == GL_FRAGMENT_SHADER) - { - sink << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n" - << "#define emu_precision highp\n" - << "#else\n" - << "#define emu_precision mediump\n" - << "#endif\n\n"; - } - else - { - sink << "#define emu_precision highp\n"; - } - - getBuiltInFunctionEmulator().outputEmulatedFunctions(sink); - sink << "// END: Generated code for built-in function emulation\n\n"; - } - - // Write array bounds clamping emulation if needed. - getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); - - if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared()) - { - const sh::WorkGroupSize &localSize = getComputeShaderLocalSize(); - sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1] - << ", local_size_z=" << localSize[2] << ") in;\n"; - } - - if (getShaderType() == GL_GEOMETRY_SHADER_OES) - { - WriteGeometryShaderLayoutQualifiers( - sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(), - getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices()); - } - - // Write translated shader. - TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), - &getSymbolTable(), getShaderType(), shaderVer, precisionEmulation, - compileOptions); - - if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM) - { - TName uniformName(TString("ViewID_OVR")); - uniformName.setInternal(true); - sink << "highp uniform int " << outputESSL.hashName(uniformName) << ";\n"; - } - - root->traverse(&outputESSL); -} - -bool TranslatorESSL::shouldFlattenPragmaStdglInvariantAll() -{ - // Not necessary when translating to ESSL. - return false; -} - -void TranslatorESSL::writeExtensionBehavior(ShCompileOptions compileOptions) -{ - TInfoSinkBase &sink = getInfoSink().obj; - const TExtensionBehavior &extBehavior = getExtensionBehavior(); - const bool isMultiviewExtEmulated = - (compileOptions & - (SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM | SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW | - SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER)) != 0u; - for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); iter != extBehavior.end(); - ++iter) - { - if (iter->second != EBhUndefined) - { - const bool isMultiview = (iter->first == TExtension::OVR_multiview); - if (getResources().NV_shader_framebuffer_fetch && - iter->first == TExtension::EXT_shader_framebuffer_fetch) - { - sink << "#extension GL_NV_shader_framebuffer_fetch : " - << GetBehaviorString(iter->second) << "\n"; - } - else if (getResources().NV_draw_buffers && iter->first == TExtension::EXT_draw_buffers) - { - sink << "#extension GL_NV_draw_buffers : " << GetBehaviorString(iter->second) - << "\n"; - } - else if (isMultiview && isMultiviewExtEmulated) - { - if (getShaderType() == GL_VERTEX_SHADER && - (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u) - { - // Emit the NV_viewport_array2 extension in a vertex shader if the - // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set and the - // OVR_multiview(2) extension is requested. - sink << "#extension GL_NV_viewport_array2 : require\n"; - } - } - else if (iter->first == TExtension::OES_geometry_shader) - { - sink << "#ifdef GL_OES_geometry_shader\n" - << "#extension GL_OES_geometry_shader : " << GetBehaviorString(iter->second) - << "\n" - << "#elif defined GL_EXT_geometry_shader\n" - << "#extension GL_EXT_geometry_shader : " << GetBehaviorString(iter->second) - << "\n"; - if (iter->second == EBhRequire) - { - sink << "#else\n" - << "#error \"No geometry shader extensions available.\" // Only generate " - "this if the extension is \"required\"\n"; - } - sink << "#endif\n"; - } - else - { - sink << "#extension " << GetExtensionNameString(iter->first) << " : " - << GetBehaviorString(iter->second) << "\n"; - } - } - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h deleted file mode 100644 index 24dc738513..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_TRANSLATORESSL_H_ -#define COMPILER_TRANSLATOR_TRANSLATORESSL_H_ - -#include "compiler/translator/Compiler.h" - -namespace sh -{ - -class TranslatorESSL : public TCompiler -{ - public: - TranslatorESSL(sh::GLenum type, ShShaderSpec spec); - - protected: - void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, - ShCompileOptions compileOptions) override; - - void translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics *perfDiagnostics) override; - bool shouldFlattenPragmaStdglInvariantAll() override; - - private: - void writeExtensionBehavior(ShCompileOptions compileOptions); -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TRANSLATORESSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp deleted file mode 100644 index a14e69e5d5..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp +++ /dev/null @@ -1,339 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/TranslatorGLSL.h" - -#include "angle_gl.h" -#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" -#include "compiler/translator/EmulatePrecision.h" -#include "compiler/translator/ExtensionGLSL.h" -#include "compiler/translator/OutputGLSL.h" -#include "compiler/translator/RewriteTexelFetchOffset.h" -#include "compiler/translator/RewriteUnaryMinusOperatorFloat.h" -#include "compiler/translator/VersionGLSL.h" - -namespace sh -{ - -TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) - : TCompiler(type, spec, output) -{ -} - -void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, - ShCompileOptions compileOptions) -{ - if (compileOptions & SH_EMULATE_ABS_INT_FUNCTION) - { - InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(emu, getShaderType()); - } - - if (compileOptions & SH_EMULATE_ISNAN_FLOAT_FUNCTION) - { - InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(emu, getShaderVersion()); - } - - if (compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION) - { - InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu); - } - - int targetGLSLVersion = ShaderOutputTypeToGLSLVersion(getOutputType()); - InitBuiltInFunctionEmulatorForGLSLMissingFunctions(emu, getShaderType(), targetGLSLVersion); -} - -void TranslatorGLSL::translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics * /*perfDiagnostics*/) -{ - TInfoSinkBase &sink = getInfoSink().obj; - - // Write GLSL version. - writeVersion(root); - - // Write extension behaviour as needed - writeExtensionBehavior(root, compileOptions); - - // Write pragmas after extensions because some drivers consider pragmas - // like non-preprocessor tokens. - writePragma(compileOptions); - - // If flattening the global invariant pragma, write invariant declarations for built-in - // variables. It should be harmless to do this twice in the case that the shader also explicitly - // did this. However, it's important to emit invariant qualifiers only for those built-in - // variables that are actually used, to avoid affecting the behavior of the shader. - if ((compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) != 0 && - getPragma().stdgl.invariantAll && - !sh::RemoveInvariant(getShaderType(), getShaderVersion(), getOutputType(), compileOptions)) - { - ASSERT(wereVariablesCollected()); - - switch (getShaderType()) - { - case GL_VERTEX_SHADER: - sink << "invariant gl_Position;\n"; - - // gl_PointSize should be declared invariant in both ESSL 1.00 and 3.00 fragment - // shaders if it's statically referenced. - conditionallyOutputInvariantDeclaration("gl_PointSize"); - break; - case GL_FRAGMENT_SHADER: - // The preprocessor will reject this pragma if it's used in ESSL 3.00 fragment - // shaders, so we can use simple logic to determine whether to declare these - // variables invariant. - conditionallyOutputInvariantDeclaration("gl_FragCoord"); - conditionallyOutputInvariantDeclaration("gl_PointCoord"); - break; - default: - // Currently not reached, but leave this in for future expansion. - ASSERT(false); - break; - } - } - - if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0) - { - sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion()); - } - - if ((compileOptions & SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR) != 0) - { - sh::RewriteUnaryMinusOperatorFloat(root); - } - - bool precisionEmulation = - getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; - - if (precisionEmulation) - { - EmulatePrecision emulatePrecision(&getSymbolTable(), getShaderVersion()); - root->traverse(&emulatePrecision); - emulatePrecision.updateTree(); - emulatePrecision.writeEmulationHelpers(sink, getShaderVersion(), getOutputType()); - } - - // Write emulated built-in functions if needed. - if (!getBuiltInFunctionEmulator().isOutputEmpty()) - { - sink << "// BEGIN: Generated code for built-in function emulation\n\n"; - sink << "#define emu_precision\n\n"; - getBuiltInFunctionEmulator().outputEmulatedFunctions(sink); - sink << "// END: Generated code for built-in function emulation\n\n"; - } - - // Write array bounds clamping emulation if needed. - getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); - - // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData - // if it's core profile shaders and they are used. - if (getShaderType() == GL_FRAGMENT_SHADER) - { - const bool mayHaveESSL1SecondaryOutputs = - IsExtensionEnabled(getExtensionBehavior(), TExtension::EXT_blend_func_extended) && - getShaderVersion() == 100; - const bool declareGLFragmentOutputs = IsGLSL130OrNewer(getOutputType()); - - bool hasGLFragColor = false; - bool hasGLFragData = false; - bool hasGLSecondaryFragColor = false; - bool hasGLSecondaryFragData = false; - - for (const auto &outputVar : outputVariables) - { - if (declareGLFragmentOutputs) - { - if (outputVar.name == "gl_FragColor") - { - ASSERT(!hasGLFragColor); - hasGLFragColor = true; - continue; - } - else if (outputVar.name == "gl_FragData") - { - ASSERT(!hasGLFragData); - hasGLFragData = true; - continue; - } - } - if (mayHaveESSL1SecondaryOutputs) - { - if (outputVar.name == "gl_SecondaryFragColorEXT") - { - ASSERT(!hasGLSecondaryFragColor); - hasGLSecondaryFragColor = true; - continue; - } - else if (outputVar.name == "gl_SecondaryFragDataEXT") - { - ASSERT(!hasGLSecondaryFragData); - hasGLSecondaryFragData = true; - continue; - } - } - } - ASSERT(!((hasGLFragColor || hasGLSecondaryFragColor) && - (hasGLFragData || hasGLSecondaryFragData))); - if (hasGLFragColor) - { - sink << "out vec4 webgl_FragColor;\n"; - } - if (hasGLFragData) - { - sink << "out vec4 webgl_FragData[gl_MaxDrawBuffers];\n"; - } - if (hasGLSecondaryFragColor) - { - sink << "out vec4 angle_SecondaryFragColor;\n"; - } - if (hasGLSecondaryFragData) - { - sink << "out vec4 angle_SecondaryFragData[" << getResources().MaxDualSourceDrawBuffers - << "];\n"; - } - } - - if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared()) - { - const sh::WorkGroupSize &localSize = getComputeShaderLocalSize(); - sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1] - << ", local_size_z=" << localSize[2] << ") in;\n"; - } - - if (getShaderType() == GL_GEOMETRY_SHADER_OES) - { - WriteGeometryShaderLayoutQualifiers( - sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(), - getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices()); - } - - // Write translated shader. - TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), - &getSymbolTable(), getShaderType(), getShaderVersion(), getOutputType(), - compileOptions); - - if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM) - { - TName uniformName(TString("ViewID_OVR")); - uniformName.setInternal(true); - sink << "uniform int " << outputGLSL.hashName(uniformName) << ";\n"; - } - - root->traverse(&outputGLSL); -} - -bool TranslatorGLSL::shouldFlattenPragmaStdglInvariantAll() -{ - // Required when outputting to any GLSL version greater than 1.20, but since ANGLE doesn't - // translate to that version, return true for the next higher version. - return IsGLSL130OrNewer(getOutputType()); -} - -bool TranslatorGLSL::shouldCollectVariables(ShCompileOptions compileOptions) -{ - return (compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) || - TCompiler::shouldCollectVariables(compileOptions); -} - -void TranslatorGLSL::writeVersion(TIntermNode *root) -{ - TVersionGLSL versionGLSL(getShaderType(), getPragma(), getOutputType()); - root->traverse(&versionGLSL); - int version = versionGLSL.getVersion(); - // We need to write version directive only if it is greater than 110. - // If there is no version directive in the shader, 110 is implied. - if (version > 110) - { - TInfoSinkBase &sink = getInfoSink().obj; - sink << "#version " << version << "\n"; - } -} - -void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root, ShCompileOptions compileOptions) -{ - TInfoSinkBase &sink = getInfoSink().obj; - const TExtensionBehavior &extBehavior = getExtensionBehavior(); - for (const auto &iter : extBehavior) - { - if (iter.second == EBhUndefined) - { - continue; - } - - if (getOutputType() == SH_GLSL_COMPATIBILITY_OUTPUT) - { - // For GLSL output, we don't need to emit most extensions explicitly, - // but some we need to translate in GL compatibility profile. - if (iter.first == TExtension::EXT_shader_texture_lod) - { - sink << "#extension GL_ARB_shader_texture_lod : " << GetBehaviorString(iter.second) - << "\n"; - } - - if (iter.first == TExtension::EXT_draw_buffers) - { - sink << "#extension GL_ARB_draw_buffers : " << GetBehaviorString(iter.second) - << "\n"; - } - - if (iter.first == TExtension::OES_geometry_shader) - { - sink << "#extension GL_ARB_geometry_shader4 : " << GetBehaviorString(iter.second) - << "\n"; - } - } - - const bool isMultiview = (iter.first == TExtension::OVR_multiview); - if (isMultiview && getShaderType() == GL_VERTEX_SHADER && - (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u) - { - // Emit the NV_viewport_array2 extension in a vertex shader if the - // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set and the OVR_multiview(2) - // extension is requested. - sink << "#extension GL_NV_viewport_array2 : require\n"; - } - } - - // GLSL ES 3 explicit location qualifiers need to use an extension before GLSL 330 - if (getShaderVersion() >= 300 && getOutputType() < SH_GLSL_330_CORE_OUTPUT && - getShaderType() != GL_COMPUTE_SHADER) - { - sink << "#extension GL_ARB_explicit_attrib_location : require\n"; - } - - // Need to enable gpu_shader5 to have index constant sampler array indexing - if (getOutputType() != SH_ESSL_OUTPUT && getOutputType() < SH_GLSL_400_CORE_OUTPUT && - getShaderVersion() == 100) - { - // Don't use "require" on to avoid breaking WebGL 1 on drivers that silently - // support index constant sampler array indexing, but don't have the extension or - // on drivers that don't have the extension at all as it would break WebGL 1 for - // some users. - sink << "#extension GL_ARB_gpu_shader5 : enable\n"; - } - - TExtensionGLSL extensionGLSL(getOutputType()); - root->traverse(&extensionGLSL); - - for (const auto &ext : extensionGLSL.getEnabledExtensions()) - { - sink << "#extension " << ext << " : enable\n"; - } - for (const auto &ext : extensionGLSL.getRequiredExtensions()) - { - sink << "#extension " << ext << " : require\n"; - } -} - -void TranslatorGLSL::conditionallyOutputInvariantDeclaration(const char *builtinVaryingName) -{ - if (isVaryingDefined(builtinVaryingName)) - { - TInfoSinkBase &sink = getInfoSink().obj; - sink << "invariant " << builtinVaryingName << ";\n"; - } -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h deleted file mode 100644 index 982d0e5ddc..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ -#define COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ - -#include "compiler/translator/Compiler.h" - -namespace sh -{ - -class TranslatorGLSL : public TCompiler -{ - public: - TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); - - protected: - void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, - ShCompileOptions compileOptions) override; - - void translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics *perfDiagnostics) override; - bool shouldFlattenPragmaStdglInvariantAll() override; - bool shouldCollectVariables(ShCompileOptions compileOptions) override; - - private: - void writeVersion(TIntermNode *root); - void writeExtensionBehavior(TIntermNode *root, ShCompileOptions compileOptions); - void conditionallyOutputInvariantDeclaration(const char *builtinVaryingName); -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp deleted file mode 100644 index 091a649cfc..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/TranslatorHLSL.h" - -#include "compiler/translator/AddDefaultReturnStatements.h" -#include "compiler/translator/ArrayReturnValueToOutParameter.h" -#include "compiler/translator/BreakVariableAliasingInInnerLoops.h" -#include "compiler/translator/EmulatePrecision.h" -#include "compiler/translator/ExpandIntegerPowExpressions.h" -#include "compiler/translator/IntermNodePatternMatcher.h" -#include "compiler/translator/OutputHLSL.h" -#include "compiler/translator/RemoveDynamicIndexing.h" -#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h" -#include "compiler/translator/RewriteElseBlocks.h" -#include "compiler/translator/RewriteTexelFetchOffset.h" -#include "compiler/translator/RewriteUnaryMinusOperatorInt.h" -#include "compiler/translator/SeparateArrayInitialization.h" -#include "compiler/translator/SeparateDeclarations.h" -#include "compiler/translator/SeparateExpressionsReturningArrays.h" -#include "compiler/translator/SimplifyLoopConditions.h" -#include "compiler/translator/SplitSequenceOperator.h" -#include "compiler/translator/UnfoldShortCircuitToIf.h" -#include "compiler/translator/WrapSwitchStatementsInBlocks.h" - -namespace sh -{ - -TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) - : TCompiler(type, spec, output) -{ -} - -void TranslatorHLSL::translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics *perfDiagnostics) -{ - const ShBuiltInResources &resources = getResources(); - int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; - - sh::AddDefaultReturnStatements(root); - - // Note that SimplifyLoopConditions needs to be run before any other AST transformations that - // may need to generate new statements from loop conditions or loop expressions. - // Note that SeparateDeclarations has already been run in TCompiler::compileTreeImpl(). - SimplifyLoopConditions(root, - IntermNodePatternMatcher::kExpressionReturningArray | - IntermNodePatternMatcher::kUnfoldedShortCircuitExpression | - IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue, - &getSymbolTable(), getShaderVersion()); - - SplitSequenceOperator(root, - IntermNodePatternMatcher::kExpressionReturningArray | - IntermNodePatternMatcher::kUnfoldedShortCircuitExpression | - IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue, - &getSymbolTable(), getShaderVersion()); - - // Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf. - UnfoldShortCircuitToIf(root, &getSymbolTable()); - - SeparateExpressionsReturningArrays(root, &getSymbolTable()); - - // Note that SeparateDeclarations needs to be run before SeparateArrayInitialization. - SeparateArrayInitialization(root); - - // HLSL doesn't support arrays as return values, we'll need to make functions that have an array - // as a return value to use an out parameter to transfer the array data instead. - ArrayReturnValueToOutParameter(root, &getSymbolTable()); - - if (!shouldRunLoopAndIndexingValidation(compileOptions)) - { - // HLSL doesn't support dynamic indexing of vectors and matrices. - RemoveDynamicIndexing(root, &getSymbolTable(), getShaderVersion(), perfDiagnostics); - } - - // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which - // use a vertex attribute as a condition, and some related computation in the else block. - if (getOutputType() == SH_HLSL_3_0_OUTPUT && getShaderType() == GL_VERTEX_SHADER) - { - sh::RewriteElseBlocks(root, &getSymbolTable()); - } - - // Work around an HLSL compiler frontend aliasing optimization bug. - // TODO(cwallez) The date is 2016-08-25, Microsoft said the bug would be fixed - // in the next release of d3dcompiler.dll, it would be nice to detect the DLL - // version and only apply the workaround if it is too old. - sh::BreakVariableAliasingInInnerLoops(root); - - // WrapSwitchStatementsInBlocks should be called after any AST transformations that might - // introduce variable declarations inside the main scope of any switch statement. - if (WrapSwitchStatementsInBlocks(root)) - { - // The WrapSwitchStatementsInBlocks step might introduce new no-op cases to the end of - // switch statements, so make sure to clean up the AST. - RemoveNoOpCasesFromEndOfSwitchStatements(root, &getSymbolTable()); - } - - bool precisionEmulation = - getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; - - if (precisionEmulation) - { - EmulatePrecision emulatePrecision(&getSymbolTable(), getShaderVersion()); - root->traverse(&emulatePrecision); - emulatePrecision.updateTree(); - emulatePrecision.writeEmulationHelpers(getInfoSink().obj, getShaderVersion(), - getOutputType()); - } - - if ((compileOptions & SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS) != 0) - { - sh::ExpandIntegerPowExpressions(root, &getSymbolTable()); - } - - if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0) - { - sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion()); - } - - if (((compileOptions & SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR) != 0) && - getShaderType() == GL_VERTEX_SHADER) - { - sh::RewriteUnaryMinusOperatorInt(root); - } - - sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(), - getSourcePath(), getOutputType(), numRenderTargets, getUniforms(), - compileOptions, &getSymbolTable(), perfDiagnostics); - - outputHLSL.output(root, getInfoSink().obj); - - mUniformBlockRegisterMap = outputHLSL.getUniformBlockRegisterMap(); - mUniformRegisterMap = outputHLSL.getUniformRegisterMap(); -} - -bool TranslatorHLSL::shouldFlattenPragmaStdglInvariantAll() -{ - // Not necessary when translating to HLSL. - return false; -} - -bool TranslatorHLSL::hasUniformBlock(const std::string &uniformBlockName) const -{ - return (mUniformBlockRegisterMap.count(uniformBlockName) > 0); -} - -unsigned int TranslatorHLSL::getUniformBlockRegister(const std::string &uniformBlockName) const -{ - ASSERT(hasUniformBlock(uniformBlockName)); - return mUniformBlockRegisterMap.find(uniformBlockName)->second; -} - -const std::map<std::string, unsigned int> *TranslatorHLSL::getUniformRegisterMap() const -{ - return &mUniformRegisterMap; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h deleted file mode 100644 index d7005a603c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ -#define COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ - -#include "compiler/translator/Compiler.h" - -namespace sh -{ - -class TranslatorHLSL : public TCompiler -{ - public: - TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); - TranslatorHLSL *getAsTranslatorHLSL() override { return this; } - - bool hasUniformBlock(const std::string &interfaceBlockName) const; - unsigned int getUniformBlockRegister(const std::string &interfaceBlockName) const; - - const std::map<std::string, unsigned int> *getUniformRegisterMap() const; - - protected: - void translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics *perfDiagnostics) override; - bool shouldFlattenPragmaStdglInvariantAll() override; - - // collectVariables needs to be run always so registers can be assigned. - bool shouldCollectVariables(ShCompileOptions compileOptions) override { return true; } - - std::map<std::string, unsigned int> mUniformBlockRegisterMap; - std::map<std::string, unsigned int> mUniformRegisterMap; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp deleted file mode 100644 index 0fe2a21f90..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp +++ /dev/null @@ -1,173 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// TranslatorVulkan: -// A GLSL-based translator that outputs shaders that fit GL_KHR_vulkan_glsl. -// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side). -// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt -// - -#include "compiler/translator/TranslatorVulkan.h" - -#include "angle_gl.h" -#include "common/utilities.h" -#include "compiler/translator/OutputVulkanGLSL.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -class DeclareDefaultUniformsTraverser : public TIntermTraverser -{ - public: - DeclareDefaultUniformsTraverser(TInfoSinkBase *sink, - ShHashFunction64 hashFunction, - NameMap *nameMap) - : TIntermTraverser(true, true, true), - mSink(sink), - mHashFunction(hashFunction), - mNameMap(nameMap), - mInDefaultUniform(false) - { - } - - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override - { - const TIntermSequence &sequence = *(node->getSequence()); - - // TODO(jmadill): Compound declarations. - ASSERT(sequence.size() == 1); - - TIntermTyped *variable = sequence.front()->getAsTyped(); - const TType &type = variable->getType(); - bool isUniform = (type.getQualifier() == EvqUniform) && !IsOpaqueType(type.getBasicType()); - - if (visit == PreVisit) - { - if (isUniform) - { - (*mSink) << " " << GetTypeName(type, mHashFunction, mNameMap) << " "; - mInDefaultUniform = true; - } - } - else if (visit == InVisit) - { - mInDefaultUniform = isUniform; - } - else if (visit == PostVisit) - { - if (isUniform) - { - (*mSink) << ";\n"; - - // Remove the uniform declaration from the tree so it isn't parsed again. - TIntermSequence emptyReplacement; - mMultiReplacements.push_back(NodeReplaceWithMultipleEntry( - getParentNode()->getAsBlock(), node, emptyReplacement)); - } - - mInDefaultUniform = false; - } - return true; - } - - void visitSymbol(TIntermSymbol *symbol) override - { - if (mInDefaultUniform) - { - const TName &name = symbol->getName(); - ASSERT(name.getString().substr(0, 3) != "gl_"); - (*mSink) << HashName(name, mHashFunction, mNameMap); - } - } - - private: - TInfoSinkBase *mSink; - ShHashFunction64 mHashFunction; - NameMap *mNameMap; - bool mInDefaultUniform; -}; - -TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec) - : TCompiler(type, spec, SH_GLSL_450_CORE_OUTPUT) -{ -} - -void TranslatorVulkan::translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics * /*perfDiagnostics*/) -{ - TInfoSinkBase &sink = getInfoSink().obj; - - sink << "#version 450 core\n"; - - // Write out default uniforms into a uniform block assigned to a specific set/binding. - int defaultUniformCount = 0; - for (const auto &uniform : getUniforms()) - { - if (!uniform.isBuiltIn() && uniform.staticUse && !gl::IsOpaqueType(uniform.type)) - { - ++defaultUniformCount; - } - } - - if (defaultUniformCount > 0) - { - sink << "\nlayout(@@ DEFAULT-UNIFORMS-SET-BINDING @@) uniform defaultUniforms\n{\n"; - - DeclareDefaultUniformsTraverser defaultTraverser(&sink, getHashFunction(), &getNameMap()); - root->traverse(&defaultTraverser); - defaultTraverser.updateTree(); - - sink << "};\n"; - } - - // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData - // if it's core profile shaders and they are used. - if (getShaderType() == GL_FRAGMENT_SHADER) - { - bool hasGLFragColor = false; - bool hasGLFragData = false; - - for (const auto &outputVar : outputVariables) - { - if (outputVar.name == "gl_FragColor") - { - ASSERT(!hasGLFragColor); - hasGLFragColor = true; - continue; - } - else if (outputVar.name == "gl_FragData") - { - ASSERT(!hasGLFragData); - hasGLFragData = true; - continue; - } - } - ASSERT(!(hasGLFragColor && hasGLFragData)); - if (hasGLFragColor) - { - sink << "layout(location = 0) out vec4 webgl_FragColor;\n"; - } - if (hasGLFragData) - { - sink << "layout(location = 0) out vec4 webgl_FragData[gl_MaxDrawBuffers];\n"; - } - } - - // Write translated shader. - TOutputVulkanGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), - getNameMap(), &getSymbolTable(), getShaderType(), - getShaderVersion(), getOutputType(), compileOptions); - root->traverse(&outputGLSL); -} - -bool TranslatorVulkan::shouldFlattenPragmaStdglInvariantAll() -{ - // Not necessary. - return false; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h b/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h deleted file mode 100644 index ef67b15ae1..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// TranslatorVulkan: -// A GLSL-based translator that outputs shaders that fit GL_KHR_vulkan_glsl. -// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side). -// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt -// - -#ifndef COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_ -#define COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_ - -#include "compiler/translator/Compiler.h" - -namespace sh -{ - -class TranslatorVulkan : public TCompiler -{ - public: - TranslatorVulkan(sh::GLenum type, ShShaderSpec spec); - - protected: - void translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics *perfDiagnostics) override; - bool shouldFlattenPragmaStdglInvariantAll() override; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Types.cpp b/src/3rdparty/angle/src/compiler/translator/Types.cpp deleted file mode 100644 index 530ffe3aeb..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Types.cpp +++ /dev/null @@ -1,1072 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#if defined(_MSC_VER) -#pragma warning(disable : 4718) -#endif - -#include "compiler/translator/Types.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/SymbolTable.h" - -#include <algorithm> -#include <climits> - -namespace sh -{ - -const char *getBasicString(TBasicType t) -{ - switch (t) - { - case EbtVoid: - return "void"; - case EbtFloat: - return "float"; - case EbtInt: - return "int"; - case EbtUInt: - return "uint"; - case EbtBool: - return "bool"; - case EbtYuvCscStandardEXT: - return "yuvCscStandardEXT"; - case EbtSampler2D: - return "sampler2D"; - case EbtSampler3D: - return "sampler3D"; - case EbtSamplerCube: - return "samplerCube"; - case EbtSamplerExternalOES: - return "samplerExternalOES"; - case EbtSamplerExternal2DY2YEXT: - return "__samplerExternal2DY2YEXT"; - case EbtSampler2DRect: - return "sampler2DRect"; - case EbtSampler2DArray: - return "sampler2DArray"; - case EbtSampler2DMS: - return "sampler2DMS"; - case EbtISampler2D: - return "isampler2D"; - case EbtISampler3D: - return "isampler3D"; - case EbtISamplerCube: - return "isamplerCube"; - case EbtISampler2DArray: - return "isampler2DArray"; - case EbtISampler2DMS: - return "isampler2DMS"; - case EbtUSampler2D: - return "usampler2D"; - case EbtUSampler3D: - return "usampler3D"; - case EbtUSamplerCube: - return "usamplerCube"; - case EbtUSampler2DArray: - return "usampler2DArray"; - case EbtUSampler2DMS: - return "usampler2DMS"; - case EbtSampler2DShadow: - return "sampler2DShadow"; - case EbtSamplerCubeShadow: - return "samplerCubeShadow"; - case EbtSampler2DArrayShadow: - return "sampler2DArrayShadow"; - case EbtStruct: - return "structure"; - case EbtInterfaceBlock: - return "interface block"; - case EbtImage2D: - return "image2D"; - case EbtIImage2D: - return "iimage2D"; - case EbtUImage2D: - return "uimage2D"; - case EbtImage3D: - return "image3D"; - case EbtIImage3D: - return "iimage3D"; - case EbtUImage3D: - return "uimage3D"; - case EbtImage2DArray: - return "image2DArray"; - case EbtIImage2DArray: - return "iimage2DArray"; - case EbtUImage2DArray: - return "uimage2DArray"; - case EbtImageCube: - return "imageCube"; - case EbtIImageCube: - return "iimageCube"; - case EbtUImageCube: - return "uimageCube"; - case EbtAtomicCounter: - return "atomic_uint"; - default: - UNREACHABLE(); - return "unknown type"; - } -} - -// TType implementation. -TType::TType() - : type(EbtVoid), - precision(EbpUndefined), - qualifier(EvqGlobal), - invariant(false), - memoryQualifier(TMemoryQualifier::Create()), - layoutQualifier(TLayoutQualifier::Create()), - primarySize(0), - secondarySize(0), - mArraySizes(nullptr), - mInterfaceBlock(nullptr), - mStructure(nullptr), - mIsStructSpecifier(false), - mMangledName(nullptr) -{ -} - -TType::TType(TBasicType t, unsigned char ps, unsigned char ss) - : type(t), - precision(EbpUndefined), - qualifier(EvqGlobal), - invariant(false), - memoryQualifier(TMemoryQualifier::Create()), - layoutQualifier(TLayoutQualifier::Create()), - primarySize(ps), - secondarySize(ss), - mArraySizes(nullptr), - mInterfaceBlock(nullptr), - mStructure(nullptr), - mIsStructSpecifier(false), - mMangledName(nullptr) -{ -} - -TType::TType(TBasicType t, TPrecision p, TQualifier q, unsigned char ps, unsigned char ss) - : type(t), - precision(p), - qualifier(q), - invariant(false), - memoryQualifier(TMemoryQualifier::Create()), - layoutQualifier(TLayoutQualifier::Create()), - primarySize(ps), - secondarySize(ss), - mArraySizes(nullptr), - mInterfaceBlock(nullptr), - mStructure(nullptr), - mIsStructSpecifier(false), - mMangledName(nullptr) -{ -} - -TType::TType(const TPublicType &p) - : type(p.getBasicType()), - precision(p.precision), - qualifier(p.qualifier), - invariant(p.invariant), - memoryQualifier(p.memoryQualifier), - layoutQualifier(p.layoutQualifier), - primarySize(p.getPrimarySize()), - secondarySize(p.getSecondarySize()), - mArraySizes(nullptr), - mInterfaceBlock(nullptr), - mStructure(nullptr), - mIsStructSpecifier(false), - mMangledName(nullptr) -{ - ASSERT(primarySize <= 4); - ASSERT(secondarySize <= 4); - if (p.isArray()) - { - mArraySizes = new TVector<unsigned int>(*p.arraySizes); - } - if (p.getUserDef()) - { - mStructure = p.getUserDef(); - mIsStructSpecifier = p.isStructSpecifier(); - } -} - -TType::TType(TStructure *userDef) - : type(EbtStruct), - precision(EbpUndefined), - qualifier(EvqTemporary), - invariant(false), - memoryQualifier(TMemoryQualifier::Create()), - layoutQualifier(TLayoutQualifier::Create()), - primarySize(1), - secondarySize(1), - mArraySizes(nullptr), - mInterfaceBlock(nullptr), - mStructure(userDef), - mIsStructSpecifier(false), - mMangledName(nullptr) -{ -} - -TType::TType(TInterfaceBlock *interfaceBlockIn, - TQualifier qualifierIn, - TLayoutQualifier layoutQualifierIn) - : type(EbtInterfaceBlock), - precision(EbpUndefined), - qualifier(qualifierIn), - invariant(false), - memoryQualifier(TMemoryQualifier::Create()), - layoutQualifier(layoutQualifierIn), - primarySize(1), - secondarySize(1), - mArraySizes(nullptr), - mInterfaceBlock(interfaceBlockIn), - mStructure(0), - mIsStructSpecifier(false), - mMangledName(nullptr) -{ -} - -TType::TType(const TType &t) - : type(t.type), - precision(t.precision), - qualifier(t.qualifier), - invariant(t.invariant), - memoryQualifier(t.memoryQualifier), - layoutQualifier(t.layoutQualifier), - primarySize(t.primarySize), - secondarySize(t.secondarySize), - mArraySizes(t.mArraySizes ? new TVector<unsigned int>(*t.mArraySizes) : nullptr), - mInterfaceBlock(t.mInterfaceBlock), - mStructure(t.mStructure), - mIsStructSpecifier(t.mIsStructSpecifier), - mMangledName(t.mMangledName) -{ -} - -TType &TType::operator=(const TType &t) -{ - type = t.type; - precision = t.precision; - qualifier = t.qualifier; - invariant = t.invariant; - memoryQualifier = t.memoryQualifier; - layoutQualifier = t.layoutQualifier; - primarySize = t.primarySize; - secondarySize = t.secondarySize; - mArraySizes = t.mArraySizes ? new TVector<unsigned int>(*t.mArraySizes) : nullptr; - mInterfaceBlock = t.mInterfaceBlock; - mStructure = t.mStructure; - mIsStructSpecifier = t.mIsStructSpecifier; - mMangledName = t.mMangledName; - return *this; -} - -bool TType::canBeConstructed() const -{ - switch (type) - { - case EbtFloat: - case EbtInt: - case EbtUInt: - case EbtBool: - case EbtStruct: - return true; - default: - return false; - } -} - -const char *TType::getBuiltInTypeNameString() const -{ - if (isMatrix()) - { - switch (getCols()) - { - case 2: - switch (getRows()) - { - case 2: - return "mat2"; - case 3: - return "mat2x3"; - case 4: - return "mat2x4"; - default: - UNREACHABLE(); - return nullptr; - } - case 3: - switch (getRows()) - { - case 2: - return "mat3x2"; - case 3: - return "mat3"; - case 4: - return "mat3x4"; - default: - UNREACHABLE(); - return nullptr; - } - case 4: - switch (getRows()) - { - case 2: - return "mat4x2"; - case 3: - return "mat4x3"; - case 4: - return "mat4"; - default: - UNREACHABLE(); - return nullptr; - } - default: - UNREACHABLE(); - return nullptr; - } - } - if (isVector()) - { - switch (getBasicType()) - { - case EbtFloat: - switch (getNominalSize()) - { - case 2: - return "vec2"; - case 3: - return "vec3"; - case 4: - return "vec4"; - default: - UNREACHABLE(); - return nullptr; - } - case EbtInt: - switch (getNominalSize()) - { - case 2: - return "ivec2"; - case 3: - return "ivec3"; - case 4: - return "ivec4"; - default: - UNREACHABLE(); - return nullptr; - } - case EbtBool: - switch (getNominalSize()) - { - case 2: - return "bvec2"; - case 3: - return "bvec3"; - case 4: - return "bvec4"; - default: - UNREACHABLE(); - return nullptr; - } - case EbtUInt: - switch (getNominalSize()) - { - case 2: - return "uvec2"; - case 3: - return "uvec3"; - case 4: - return "uvec4"; - default: - UNREACHABLE(); - return nullptr; - } - default: - UNREACHABLE(); - return nullptr; - } - } - ASSERT(getBasicType() != EbtStruct); - ASSERT(getBasicType() != EbtInterfaceBlock); - return getBasicString(); -} - -TString TType::getCompleteString() const -{ - TStringStream stream; - - if (invariant) - stream << "invariant "; - if (qualifier != EvqTemporary && qualifier != EvqGlobal) - stream << getQualifierString() << " "; - if (precision != EbpUndefined) - stream << getPrecisionString() << " "; - if (mArraySizes) - { - for (auto arraySizeIter = mArraySizes->rbegin(); arraySizeIter != mArraySizes->rend(); - ++arraySizeIter) - { - stream << "array[" << (*arraySizeIter) << "] of "; - } - } - if (isMatrix()) - stream << getCols() << "X" << getRows() << " matrix of "; - else if (isVector()) - stream << getNominalSize() << "-component vector of "; - - stream << getBasicString(); - return stream.str(); -} - -// -// Recursively generate mangled names. -// -const char *TType::buildMangledName() const -{ - TString mangledName; - if (isMatrix()) - mangledName += 'm'; - else if (isVector()) - mangledName += 'v'; - - switch (type) - { - case EbtFloat: - mangledName += 'f'; - break; - case EbtInt: - mangledName += 'i'; - break; - case EbtUInt: - mangledName += 'u'; - break; - case EbtBool: - mangledName += 'b'; - break; - case EbtYuvCscStandardEXT: - mangledName += "ycs"; - break; - case EbtSampler2D: - mangledName += "s2"; - break; - case EbtSampler3D: - mangledName += "s3"; - break; - case EbtSamplerCube: - mangledName += "sC"; - break; - case EbtSampler2DArray: - mangledName += "s2a"; - break; - case EbtSamplerExternalOES: - mangledName += "sext"; - break; - case EbtSamplerExternal2DY2YEXT: - mangledName += "sext2y2y"; - break; - case EbtSampler2DRect: - mangledName += "s2r"; - break; - case EbtSampler2DMS: - mangledName += "s2ms"; - break; - case EbtISampler2D: - mangledName += "is2"; - break; - case EbtISampler3D: - mangledName += "is3"; - break; - case EbtISamplerCube: - mangledName += "isC"; - break; - case EbtISampler2DArray: - mangledName += "is2a"; - break; - case EbtISampler2DMS: - mangledName += "is2ms"; - break; - case EbtUSampler2D: - mangledName += "us2"; - break; - case EbtUSampler3D: - mangledName += "us3"; - break; - case EbtUSamplerCube: - mangledName += "usC"; - break; - case EbtUSampler2DArray: - mangledName += "us2a"; - break; - case EbtUSampler2DMS: - mangledName += "us2ms"; - break; - case EbtSampler2DShadow: - mangledName += "s2s"; - break; - case EbtSamplerCubeShadow: - mangledName += "sCs"; - break; - case EbtSampler2DArrayShadow: - mangledName += "s2as"; - break; - case EbtImage2D: - mangledName += "im2"; - break; - case EbtIImage2D: - mangledName += "iim2"; - break; - case EbtUImage2D: - mangledName += "uim2"; - break; - case EbtImage3D: - mangledName += "im3"; - break; - case EbtIImage3D: - mangledName += "iim3"; - break; - case EbtUImage3D: - mangledName += "uim3"; - break; - case EbtImage2DArray: - mangledName += "im2a"; - break; - case EbtIImage2DArray: - mangledName += "iim2a"; - break; - case EbtUImage2DArray: - mangledName += "uim2a"; - break; - case EbtImageCube: - mangledName += "imc"; - break; - case EbtIImageCube: - mangledName += "iimc"; - break; - case EbtUImageCube: - mangledName += "uimc"; - break; - case EbtAtomicCounter: - mangledName += "ac"; - break; - case EbtStruct: - mangledName += mStructure->mangledName(); - break; - case EbtInterfaceBlock: - mangledName += mInterfaceBlock->mangledName(); - break; - default: - // EbtVoid, EbtAddress and non types - break; - } - - if (isMatrix()) - { - mangledName += static_cast<char>('0' + getCols()); - mangledName += static_cast<char>('x'); - mangledName += static_cast<char>('0' + getRows()); - } - else - { - mangledName += static_cast<char>('0' + getNominalSize()); - } - - if (mArraySizes) - { - for (unsigned int arraySize : *mArraySizes) - { - char buf[20]; - snprintf(buf, sizeof(buf), "%d", arraySize); - mangledName += '['; - mangledName += buf; - mangledName += ']'; - } - } - - mangledName += ';'; - - // Copy string contents into a pool-allocated buffer, so we never need to call delete. - size_t requiredSize = mangledName.size() + 1; - char *buffer = reinterpret_cast<char *>(GetGlobalPoolAllocator()->allocate(requiredSize)); - memcpy(buffer, mangledName.c_str(), requiredSize); - return buffer; -} - -size_t TType::getObjectSize() const -{ - size_t totalSize; - - if (getBasicType() == EbtStruct) - totalSize = mStructure->objectSize(); - else - totalSize = primarySize * secondarySize; - - if (totalSize == 0) - return 0; - - if (mArraySizes) - { - for (size_t arraySize : *mArraySizes) - { - if (arraySize > INT_MAX / totalSize) - totalSize = INT_MAX; - else - totalSize *= arraySize; - } - } - - return totalSize; -} - -int TType::getLocationCount() const -{ - int count = 1; - - if (getBasicType() == EbtStruct) - { - count = mStructure->getLocationCount(); - } - - if (count == 0) - { - return 0; - } - - if (mArraySizes) - { - for (unsigned int arraySize : *mArraySizes) - { - if (arraySize > static_cast<unsigned int>(std::numeric_limits<int>::max() / count)) - { - count = std::numeric_limits<int>::max(); - } - else - { - count *= static_cast<int>(arraySize); - } - } - } - - return count; -} - -unsigned int TType::getArraySizeProduct() const -{ - if (!mArraySizes) - return 1u; - - unsigned int product = 1u; - - for (unsigned int arraySize : *mArraySizes) - { - product *= arraySize; - } - return product; -} - -bool TType::isUnsizedArray() const -{ - if (!mArraySizes) - return false; - - for (unsigned int arraySize : *mArraySizes) - { - if (arraySize == 0u) - { - return true; - } - } - return false; -} - -bool TType::sameNonArrayType(const TType &right) const -{ - return (type == right.type && primarySize == right.primarySize && - secondarySize == right.secondarySize && mStructure == right.mStructure); -} - -bool TType::isElementTypeOf(const TType &arrayType) const -{ - if (!sameNonArrayType(arrayType)) - { - return false; - } - if (arrayType.getNumArraySizes() != getNumArraySizes() + 1u) - { - return false; - } - if (isArray()) - { - for (size_t i = 0; i < mArraySizes->size(); ++i) - { - if ((*mArraySizes)[i] != (*arrayType.mArraySizes)[i]) - { - return false; - } - } - } - return true; -} - -void TType::sizeUnsizedArrays(const TVector<unsigned int> *newArraySizes) -{ - size_t newArraySizesSize = newArraySizes ? newArraySizes->size() : 0; - for (size_t i = 0u; i < getNumArraySizes(); ++i) - { - if ((*mArraySizes)[i] == 0) - { - if (i < newArraySizesSize) - { - ASSERT(newArraySizes != nullptr); - (*mArraySizes)[i] = (*newArraySizes)[i]; - } - else - { - (*mArraySizes)[i] = 1u; - } - } - } - invalidateMangledName(); -} - -void TType::sizeOutermostUnsizedArray(unsigned int arraySize) -{ - ASSERT(isArray()); - ASSERT(mArraySizes->back() == 0u); - mArraySizes->back() = arraySize; -} - -void TType::setBasicType(TBasicType t) -{ - if (type != t) - { - type = t; - invalidateMangledName(); - } -} - -void TType::setPrimarySize(unsigned char ps) -{ - if (primarySize != ps) - { - ASSERT(ps <= 4); - primarySize = ps; - invalidateMangledName(); - } -} - -void TType::setSecondarySize(unsigned char ss) -{ - if (secondarySize != ss) - { - ASSERT(ss <= 4); - secondarySize = ss; - invalidateMangledName(); - } -} - -void TType::makeArray(unsigned int s) -{ - if (!mArraySizes) - mArraySizes = new TVector<unsigned int>(); - - mArraySizes->push_back(s); - invalidateMangledName(); -} - -void TType::makeArrays(const TVector<unsigned int> &sizes) -{ - if (!mArraySizes) - mArraySizes = new TVector<unsigned int>(); - - mArraySizes->insert(mArraySizes->end(), sizes.begin(), sizes.end()); - invalidateMangledName(); -} - -void TType::setArraySize(size_t arrayDimension, unsigned int s) -{ - ASSERT(mArraySizes != nullptr); - ASSERT(arrayDimension < mArraySizes->size()); - if (mArraySizes->at(arrayDimension) != s) - { - (*mArraySizes)[arrayDimension] = s; - invalidateMangledName(); - } -} - -void TType::toArrayElementType() -{ - ASSERT(mArraySizes != nullptr); - if (mArraySizes->size() > 0) - { - mArraySizes->pop_back(); - invalidateMangledName(); - } -} - -void TType::setInterfaceBlock(TInterfaceBlock *interfaceBlockIn) -{ - if (mInterfaceBlock != interfaceBlockIn) - { - mInterfaceBlock = interfaceBlockIn; - invalidateMangledName(); - } -} - -void TType::setStruct(TStructure *s) -{ - if (mStructure != s) - { - mStructure = s; - invalidateMangledName(); - } -} - -const char *TType::getMangledName() const -{ - if (mMangledName == nullptr) - { - mMangledName = buildMangledName(); - } - - return mMangledName; -} - -void TType::realize() -{ - getMangledName(); -} - -void TType::invalidateMangledName() -{ - mMangledName = nullptr; -} - -// TStructure implementation. -TStructure::TStructure(TSymbolTable *symbolTable, const TString *name, TFieldList *fields) - : TFieldListCollection(name, fields), - mDeepestNesting(0), - mUniqueId(symbolTable->nextUniqueId()), - mAtGlobalScope(false) -{ -} - -bool TStructure::equals(const TStructure &other) const -{ - return (uniqueId() == other.uniqueId()); -} - -bool TStructure::containsArrays() const -{ - for (size_t i = 0; i < mFields->size(); ++i) - { - const TType *fieldType = (*mFields)[i]->type(); - if (fieldType->isArray() || fieldType->isStructureContainingArrays()) - return true; - } - return false; -} - -bool TStructure::containsType(TBasicType type) const -{ - for (size_t i = 0; i < mFields->size(); ++i) - { - const TType *fieldType = (*mFields)[i]->type(); - if (fieldType->getBasicType() == type || fieldType->isStructureContainingType(type)) - return true; - } - return false; -} - -bool TStructure::containsSamplers() const -{ - for (size_t i = 0; i < mFields->size(); ++i) - { - const TType *fieldType = (*mFields)[i]->type(); - if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers()) - return true; - } - return false; -} - -void TType::createSamplerSymbols(const TString &namePrefix, - const TString &apiNamePrefix, - TVector<TIntermSymbol *> *outputSymbols, - TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames, - TSymbolTable *symbolTable) const -{ - if (isStructureContainingSamplers()) - { - if (isArray()) - { - TType elementType(*this); - elementType.toArrayElementType(); - for (unsigned int arrayIndex = 0u; arrayIndex < getOutermostArraySize(); ++arrayIndex) - { - TStringStream elementName; - elementName << namePrefix << "_" << arrayIndex; - TStringStream elementApiName; - elementApiName << apiNamePrefix << "[" << arrayIndex << "]"; - elementType.createSamplerSymbols(elementName.str(), elementApiName.str(), - outputSymbols, outputSymbolsToAPINames, - symbolTable); - } - } - else - { - mStructure->createSamplerSymbols(namePrefix, apiNamePrefix, outputSymbols, - outputSymbolsToAPINames, symbolTable); - } - return; - } - - ASSERT(IsSampler(type)); - TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), namePrefix, *this); - outputSymbols->push_back(symbol); - if (outputSymbolsToAPINames) - { - (*outputSymbolsToAPINames)[symbol] = apiNamePrefix; - } -} - -void TStructure::createSamplerSymbols(const TString &namePrefix, - const TString &apiNamePrefix, - TVector<TIntermSymbol *> *outputSymbols, - TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames, - TSymbolTable *symbolTable) const -{ - ASSERT(containsSamplers()); - for (auto &field : *mFields) - { - const TType *fieldType = field->type(); - if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers()) - { - TString fieldName = namePrefix + "_" + field->name(); - TString fieldApiName = apiNamePrefix + "." + field->name(); - fieldType->createSamplerSymbols(fieldName, fieldApiName, outputSymbols, - outputSymbolsToAPINames, symbolTable); - } - } -} - -TString TFieldListCollection::buildMangledName(const TString &mangledNamePrefix) const -{ - TString mangledName(mangledNamePrefix); - mangledName += *mName; - for (size_t i = 0; i < mFields->size(); ++i) - { - mangledName += '-'; - mangledName += (*mFields)[i]->type()->getMangledName(); - } - return mangledName; -} - -size_t TFieldListCollection::calculateObjectSize() const -{ - size_t size = 0; - for (const TField *field : *mFields) - { - size_t fieldSize = field->type()->getObjectSize(); - if (fieldSize > INT_MAX - size) - size = INT_MAX; - else - size += fieldSize; - } - return size; -} - -int TFieldListCollection::getLocationCount() const -{ - int count = 0; - for (const TField *field : *mFields) - { - int fieldCount = field->type()->getLocationCount(); - if (fieldCount > std::numeric_limits<int>::max() - count) - { - count = std::numeric_limits<int>::max(); - } - else - { - count += fieldCount; - } - } - return count; -} - -int TStructure::calculateDeepestNesting() const -{ - int maxNesting = 0; - for (size_t i = 0; i < mFields->size(); ++i) - maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting()); - return 1 + maxNesting; -} - -// TPublicType implementation. -void TPublicType::initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q) -{ - typeSpecifierNonArray = typeSpecifier; - layoutQualifier = TLayoutQualifier::Create(); - memoryQualifier = TMemoryQualifier::Create(); - qualifier = q; - invariant = false; - precision = EbpUndefined; - arraySizes = nullptr; -} - -void TPublicType::initializeBasicType(TBasicType basicType) -{ - typeSpecifierNonArray.type = basicType; - typeSpecifierNonArray.primarySize = 1; - typeSpecifierNonArray.secondarySize = 1; - layoutQualifier = TLayoutQualifier::Create(); - memoryQualifier = TMemoryQualifier::Create(); - qualifier = EvqTemporary; - invariant = false; - precision = EbpUndefined; - arraySizes = nullptr; -} - -bool TPublicType::isStructureContainingArrays() const -{ - if (!typeSpecifierNonArray.userDef) - { - return false; - } - - return typeSpecifierNonArray.userDef->containsArrays(); -} - -bool TPublicType::isStructureContainingType(TBasicType t) const -{ - if (!typeSpecifierNonArray.userDef) - { - return false; - } - - return typeSpecifierNonArray.userDef->containsType(t); -} - -void TPublicType::setArraySizes(TVector<unsigned int> *sizes) -{ - arraySizes = sizes; -} - -bool TPublicType::isArray() const -{ - return arraySizes && !arraySizes->empty(); -} - -void TPublicType::clearArrayness() -{ - arraySizes = nullptr; -} - -bool TPublicType::isAggregate() const -{ - return isArray() || typeSpecifierNonArray.isMatrix() || typeSpecifierNonArray.isVector(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/Types.h b/src/3rdparty/angle/src/compiler/translator/Types.h deleted file mode 100644 index 7dc84c5b1c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Types.h +++ /dev/null @@ -1,509 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_TYPES_H_ -#define COMPILER_TRANSLATOR_TYPES_H_ - -#include "common/angleutils.h" -#include "common/debug.h" - -#include "compiler/translator/BaseTypes.h" -#include "compiler/translator/Common.h" -#include "compiler/translator/SymbolUniqueId.h" - -namespace sh -{ - -struct TPublicType; -class TType; -class TSymbol; -class TIntermSymbol; -class TSymbolTable; - -class TField : angle::NonCopyable -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TField(TType *type, TString *name, const TSourceLoc &line) - : mType(type), mName(name), mLine(line) - { - } - - // TODO(alokp): We should only return const type. - // Fix it by tweaking grammar. - TType *type() { return mType; } - const TType *type() const { return mType; } - - const TString &name() const { return *mName; } - const TSourceLoc &line() const { return mLine; } - - private: - TType *mType; - TString *mName; - TSourceLoc mLine; -}; - -typedef TVector<TField *> TFieldList; -inline TFieldList *NewPoolTFieldList() -{ - void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList)); - return new (memory) TFieldList; -} - -class TFieldListCollection : angle::NonCopyable -{ - public: - const TString &name() const { return *mName; } - const TFieldList &fields() const { return *mFields; } - - size_t objectSize() const - { - if (mObjectSize == 0) - mObjectSize = calculateObjectSize(); - return mObjectSize; - } - - // How many locations the field list consumes as a uniform. - int getLocationCount() const; - - protected: - TFieldListCollection(const TString *name, TFieldList *fields) - : mName(name), mFields(fields), mObjectSize(0) - { - } - TString buildMangledName(const TString &mangledNamePrefix) const; - size_t calculateObjectSize() const; - - const TString *mName; - TFieldList *mFields; - - mutable TString mMangledName; - mutable size_t mObjectSize; -}; - -// May also represent interface blocks -class TStructure : public TFieldListCollection -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TStructure(TSymbolTable *symbolTable, const TString *name, TFieldList *fields); - - int deepestNesting() const - { - if (mDeepestNesting == 0) - mDeepestNesting = calculateDeepestNesting(); - return mDeepestNesting; - } - bool containsArrays() const; - bool containsType(TBasicType t) const; - bool containsSamplers() const; - - void createSamplerSymbols(const TString &namePrefix, - const TString &apiNamePrefix, - TVector<TIntermSymbol *> *outputSymbols, - TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames, - TSymbolTable *symbolTable) const; - - bool equals(const TStructure &other) const; - - int uniqueId() const { return mUniqueId.get(); } - - void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; } - - bool atGlobalScope() const { return mAtGlobalScope; } - - const TString &mangledName() const - { - if (mMangledName.empty()) - mMangledName = buildMangledName("struct-"); - return mMangledName; - } - - private: - // TODO(zmo): Find a way to get rid of the const_cast in function - // setName(). At the moment keep this function private so only - // friend class RegenerateStructNames may call it. - friend class RegenerateStructNames; - void setName(const TString &name) - { - TString *mutableName = const_cast<TString *>(mName); - *mutableName = name; - } - - int calculateDeepestNesting() const; - - mutable int mDeepestNesting; - const TSymbolUniqueId mUniqueId; - bool mAtGlobalScope; -}; - -class TInterfaceBlock : public TFieldListCollection -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TInterfaceBlock(const TString *name, - TFieldList *fields, - const TString *instanceName, - const TLayoutQualifier &layoutQualifier) - : TFieldListCollection(name, fields), - mInstanceName(instanceName), - mBlockStorage(layoutQualifier.blockStorage), - mMatrixPacking(layoutQualifier.matrixPacking), - mBinding(layoutQualifier.binding) - { - } - - const TString &instanceName() const { return *mInstanceName; } - bool hasInstanceName() const { return mInstanceName != nullptr; } - TLayoutBlockStorage blockStorage() const { return mBlockStorage; } - TLayoutMatrixPacking matrixPacking() const { return mMatrixPacking; } - int blockBinding() const { return mBinding; } - const TString &mangledName() const - { - if (mMangledName.empty()) - mMangledName = buildMangledName("iblock-"); - return mMangledName; - } - - private: - const TString *mInstanceName; // for interface block instance names - TLayoutBlockStorage mBlockStorage; - TLayoutMatrixPacking mMatrixPacking; - int mBinding; -}; - -// -// Base class for things that have a type. -// -class TType -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TType(); - explicit TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1); - TType(TBasicType t, - TPrecision p, - TQualifier q = EvqTemporary, - unsigned char ps = 1, - unsigned char ss = 1); - explicit TType(const TPublicType &p); - explicit TType(TStructure *userDef); - TType(TInterfaceBlock *interfaceBlockIn, - TQualifier qualifierIn, - TLayoutQualifier layoutQualifierIn); - TType(const TType &t); - TType &operator=(const TType &t); - - TBasicType getBasicType() const { return type; } - void setBasicType(TBasicType t); - - TPrecision getPrecision() const { return precision; } - void setPrecision(TPrecision p) { precision = p; } - - TQualifier getQualifier() const { return qualifier; } - void setQualifier(TQualifier q) { qualifier = q; } - - bool isInvariant() const { return invariant; } - - void setInvariant(bool i) { invariant = i; } - - TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; } - void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; } - - TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; } - void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; } - - int getNominalSize() const { return primarySize; } - int getSecondarySize() const { return secondarySize; } - int getCols() const - { - ASSERT(isMatrix()); - return primarySize; - } - int getRows() const - { - ASSERT(isMatrix()); - return secondarySize; - } - void setPrimarySize(unsigned char ps); - void setSecondarySize(unsigned char ss); - - // Full size of single instance of type - size_t getObjectSize() const; - - // Get how many locations this type consumes as a uniform. - int getLocationCount() const; - - bool isMatrix() const { return primarySize > 1 && secondarySize > 1; } - bool isNonSquareMatrix() const { return isMatrix() && primarySize != secondarySize; } - bool isArray() const { return mArraySizes != nullptr && !mArraySizes->empty(); } - bool isArrayOfArrays() const { return isArray() && mArraySizes->size() > 1u; } - size_t getNumArraySizes() const { return isArray() ? mArraySizes->size() : 0; } - const TVector<unsigned int> *getArraySizes() const { return mArraySizes; } - unsigned int getArraySizeProduct() const; - bool isUnsizedArray() const; - unsigned int getOutermostArraySize() const { - ASSERT(isArray()); - return mArraySizes->back(); - } - void makeArray(unsigned int s); - - // sizes contain new outermost array sizes. - void makeArrays(const TVector<unsigned int> &sizes); - // Here, the array dimension value 0 corresponds to the innermost array. - void setArraySize(size_t arrayDimension, unsigned int s); - - // Will set unsized array sizes according to newArraySizes. In case there are more - // unsized arrays than there are sizes in newArraySizes, defaults to setting any - // remaining array sizes to 1. - void sizeUnsizedArrays(const TVector<unsigned int> *newArraySizes); - - // Will size the outermost array according to arraySize. - void sizeOutermostUnsizedArray(unsigned int arraySize); - - // Note that the array element type might still be an array type in GLSL ES version >= 3.10. - void toArrayElementType(); - - TInterfaceBlock *getInterfaceBlock() const { return mInterfaceBlock; } - void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn); - bool isInterfaceBlock() const { return type == EbtInterfaceBlock; } - - bool isVector() const { return primarySize > 1 && secondarySize == 1; } - bool isScalar() const - { - return primarySize == 1 && secondarySize == 1 && !mStructure && !isArray(); - } - bool isScalarFloat() const { return isScalar() && type == EbtFloat; } - bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); } - - bool canBeConstructed() const; - - TStructure *getStruct() { return mStructure; } - const TStructure *getStruct() const { return mStructure; } - void setStruct(TStructure *s); - - const char *getMangledName() const; - - bool sameNonArrayType(const TType &right) const; - - // Returns true if arrayType is an array made of this type. - bool isElementTypeOf(const TType &arrayType) const; - - bool operator==(const TType &right) const - { - size_t numArraySizesL = getNumArraySizes(); - size_t numArraySizesR = right.getNumArraySizes(); - bool arraySizesEqual = numArraySizesL == numArraySizesR && - (numArraySizesL == 0 || *mArraySizes == *right.mArraySizes); - return type == right.type && primarySize == right.primarySize && - secondarySize == right.secondarySize && arraySizesEqual && - mStructure == right.mStructure; - // don't check the qualifier, it's not ever what's being sought after - } - bool operator!=(const TType &right) const { return !operator==(right); } - bool operator<(const TType &right) const - { - if (type != right.type) - return type < right.type; - if (primarySize != right.primarySize) - return primarySize < right.primarySize; - if (secondarySize != right.secondarySize) - return secondarySize < right.secondarySize; - size_t numArraySizesL = getNumArraySizes(); - size_t numArraySizesR = right.getNumArraySizes(); - if (numArraySizesL != numArraySizesR) - return numArraySizesL < numArraySizesR; - for (size_t i = 0; i < numArraySizesL; ++i) - { - if ((*mArraySizes)[i] != (*right.mArraySizes)[i]) - return (*mArraySizes)[i] < (*right.mArraySizes)[i]; - } - if (mStructure != right.mStructure) - return mStructure < right.mStructure; - - return false; - } - - const char *getBasicString() const { return sh::getBasicString(type); } - - const char *getPrecisionString() const { return sh::getPrecisionString(precision); } - const char *getQualifierString() const { return sh::getQualifierString(qualifier); } - - const char *getBuiltInTypeNameString() const; - - TString getCompleteString() const; - - // If this type is a struct, returns the deepest struct nesting of - // any field in the struct. For example: - // struct nesting1 { - // vec4 position; - // }; - // struct nesting2 { - // nesting1 field1; - // vec4 field2; - // }; - // For type "nesting2", this method would return 2 -- the number - // of structures through which indirection must occur to reach the - // deepest field (nesting2.field1.position). - int getDeepestStructNesting() const { return mStructure ? mStructure->deepestNesting() : 0; } - - bool isNamelessStruct() const { return mStructure && mStructure->name() == ""; } - - bool isStructureContainingArrays() const - { - return mStructure ? mStructure->containsArrays() : false; - } - - bool isStructureContainingType(TBasicType t) const - { - return mStructure ? mStructure->containsType(t) : false; - } - - bool isStructureContainingSamplers() const - { - return mStructure ? mStructure->containsSamplers() : false; - } - - bool isStructSpecifier() const { return mIsStructSpecifier; } - - void createSamplerSymbols(const TString &namePrefix, - const TString &apiNamePrefix, - TVector<TIntermSymbol *> *outputSymbols, - TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames, - TSymbolTable *symbolTable) const; - - // Initializes all lazily-initialized members. - void realize(); - - private: - void invalidateMangledName(); - const char *buildMangledName() const; - - TBasicType type; - TPrecision precision; - TQualifier qualifier; - bool invariant; - TMemoryQualifier memoryQualifier; - TLayoutQualifier layoutQualifier; - unsigned char primarySize; // size of vector or cols matrix - unsigned char secondarySize; // rows of a matrix - - // Used to make an array type. Outermost array size is stored at the end of the vector. Having 0 - // in this vector means an unsized array. - TVector<unsigned int> *mArraySizes; - - // This is set only in the following two cases: - // 1) Represents an interface block. - // 2) Represents the member variable of an unnamed interface block. - // It's nullptr also for members of named interface blocks. - TInterfaceBlock *mInterfaceBlock; - - // 0 unless this is a struct - TStructure *mStructure; - bool mIsStructSpecifier; - - mutable const char *mMangledName; -}; - -// TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the -// grammar -struct TTypeSpecifierNonArray -{ - TBasicType type; - unsigned char primarySize; // size of vector or cols of matrix - unsigned char secondarySize; // rows of matrix - TStructure *userDef; - TSourceLoc line; - - // true if the type was defined by a struct specifier rather than a reference to a type name. - bool isStructSpecifier; - - void initialize(TBasicType aType, const TSourceLoc &aLine) - { - ASSERT(aType != EbtStruct); - type = aType; - primarySize = 1; - secondarySize = 1; - userDef = nullptr; - line = aLine; - isStructSpecifier = false; - } - - void initializeStruct(TStructure *aUserDef, bool aIsStructSpecifier, const TSourceLoc &aLine) - { - type = EbtStruct; - primarySize = 1; - secondarySize = 1; - userDef = aUserDef; - line = aLine; - isStructSpecifier = aIsStructSpecifier; - } - - void setAggregate(unsigned char size) { primarySize = size; } - - void setMatrix(unsigned char columns, unsigned char rows) - { - ASSERT(columns > 1 && rows > 1 && columns <= 4 && rows <= 4); - primarySize = columns; - secondarySize = rows; - } - - bool isMatrix() const { return primarySize > 1 && secondarySize > 1; } - - bool isVector() const { return primarySize > 1 && secondarySize == 1; } -}; - -// -// This is a workaround for a problem with the yacc stack, It can't have -// types that it thinks have non-trivial constructors. It should -// just be used while recognizing the grammar, not anything else. Pointers -// could be used, but also trying to avoid lots of memory management overhead. -// -// Not as bad as it looks, there is no actual assumption that the fields -// match up or are name the same or anything like that. -// -struct TPublicType -{ - // Must have a trivial default constructor since it is used in YYSTYPE. - TPublicType() = default; - - void initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q); - void initializeBasicType(TBasicType basicType); - - TBasicType getBasicType() const { return typeSpecifierNonArray.type; } - void setBasicType(TBasicType basicType) { typeSpecifierNonArray.type = basicType; } - - unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; } - unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; } - - TStructure *getUserDef() const { return typeSpecifierNonArray.userDef; } - const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; } - - bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; } - - bool isStructureContainingArrays() const; - bool isStructureContainingType(TBasicType t) const; - void setArraySizes(TVector<unsigned int> *sizes); - bool isArray() const; - void clearArrayness(); - bool isAggregate() const; - - TTypeSpecifierNonArray typeSpecifierNonArray; - TLayoutQualifier layoutQualifier; - TMemoryQualifier memoryQualifier; - TQualifier qualifier; - bool invariant; - TPrecision precision; - - // Either nullptr or empty in case the type is not an array. The last element is the outermost - // array size. Note that due to bison restrictions, copies of the public type created by the - // copy constructor share the same arraySizes pointer. - const TVector<unsigned int> *arraySizes; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_TYPES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp deleted file mode 100644 index 4e4653bbe5..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/UnfoldShortCircuitAST.h" - -namespace sh -{ - -namespace -{ - -// "x || y" is equivalent to "x ? true : y". -TIntermTernary *UnfoldOR(TIntermTyped *x, TIntermTyped *y) -{ - TConstantUnion *u = new TConstantUnion; - u->setBConst(true); - TIntermConstantUnion *trueNode = - new TIntermConstantUnion(u, TType(EbtBool, EbpUndefined, EvqConst, 1)); - return new TIntermTernary(x, trueNode, y); -} - -// "x && y" is equivalent to "x ? y : false". -TIntermTernary *UnfoldAND(TIntermTyped *x, TIntermTyped *y) -{ - TConstantUnion *u = new TConstantUnion; - u->setBConst(false); - TIntermConstantUnion *falseNode = - new TIntermConstantUnion(u, TType(EbtBool, EbpUndefined, EvqConst, 1)); - return new TIntermTernary(x, y, falseNode); -} - -} // namespace anonymous - -bool UnfoldShortCircuitAST::visitBinary(Visit visit, TIntermBinary *node) -{ - TIntermTernary *replacement = nullptr; - - switch (node->getOp()) - { - case EOpLogicalOr: - replacement = UnfoldOR(node->getLeft(), node->getRight()); - break; - case EOpLogicalAnd: - replacement = UnfoldAND(node->getLeft(), node->getRight()); - break; - default: - break; - } - if (replacement) - { - queueReplacement(replacement, OriginalNode::IS_DROPPED); - } - return true; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h deleted file mode 100644 index 7f377e6f15..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UnfoldShortCircuitAST is an AST traverser to replace short-circuiting -// operations with ternary operations. -// - -#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_ -#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_ - -#include "common/angleutils.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -// This traverser identifies all the short circuit binary nodes that need to -// be replaced, and creates the corresponding replacement nodes. However, -// the actual replacements happen after the traverse through updateTree(). - -class UnfoldShortCircuitAST : public TIntermTraverser -{ - public: - UnfoldShortCircuitAST() : TIntermTraverser(true, false, false) {} - - bool visitBinary(Visit visit, TIntermBinary *) override; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp deleted file mode 100644 index 774f1fc704..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp +++ /dev/null @@ -1,186 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UnfoldShortCircuitToIf is an AST traverser to convert short-circuiting operators to if-else -// statements. -// The results are assigned to s# temporaries, which are used by the main translator instead of -// the original expression. -// - -#include "compiler/translator/UnfoldShortCircuitToIf.h" - -#include "compiler/translator/IntermNodePatternMatcher.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -// Traverser that unfolds one short-circuiting operation at a time. -class UnfoldShortCircuitTraverser : public TIntermTraverser -{ - public: - UnfoldShortCircuitTraverser(TSymbolTable *symbolTable); - - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - - void nextIteration(); - bool foundShortCircuit() const { return mFoundShortCircuit; } - - protected: - // Marked to true once an operation that needs to be unfolded has been found. - // After that, no more unfolding is performed on that traversal. - bool mFoundShortCircuit; - - IntermNodePatternMatcher mPatternToUnfoldMatcher; -}; - -UnfoldShortCircuitTraverser::UnfoldShortCircuitTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, true, symbolTable), - mFoundShortCircuit(false), - mPatternToUnfoldMatcher(IntermNodePatternMatcher::kUnfoldedShortCircuitExpression) -{ -} - -bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - if (mFoundShortCircuit) - return false; - - if (visit != PreVisit) - return true; - - if (!mPatternToUnfoldMatcher.match(node, getParentNode())) - return true; - - // If our right node doesn't have side effects, we know we don't need to unfold this - // expression: there will be no short-circuiting side effects to avoid - // (note: unfolding doesn't depend on the left node -- it will always be evaluated) - ASSERT(node->getRight()->hasSideEffects()); - - mFoundShortCircuit = true; - - switch (node->getOp()) - { - case EOpLogicalOr: - { - // "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true; - // else s = y;", - // and then further simplifies down to "bool s = x; if(!s) s = y;". - - TIntermSequence insertions; - TType boolType(EbtBool, EbpUndefined, EvqTemporary); - - ASSERT(node->getLeft()->getType() == boolType); - insertions.push_back(createTempInitDeclaration(node->getLeft())); - - TIntermBlock *assignRightBlock = new TIntermBlock(); - ASSERT(node->getRight()->getType() == boolType); - assignRightBlock->getSequence()->push_back(createTempAssignment(node->getRight())); - - TIntermUnary *notTempSymbol = - new TIntermUnary(EOpLogicalNot, createTempSymbol(boolType)); - TIntermIfElse *ifNode = new TIntermIfElse(notTempSymbol, assignRightBlock, nullptr); - insertions.push_back(ifNode); - - insertStatementsInParentBlock(insertions); - - queueReplacement(createTempSymbol(boolType), OriginalNode::IS_DROPPED); - return false; - } - case EOpLogicalAnd: - { - // "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y; - // else s = false;", - // and then further simplifies down to "bool s = x; if(s) s = y;". - TIntermSequence insertions; - TType boolType(EbtBool, EbpUndefined, EvqTemporary); - - ASSERT(node->getLeft()->getType() == boolType); - insertions.push_back(createTempInitDeclaration(node->getLeft())); - - TIntermBlock *assignRightBlock = new TIntermBlock(); - ASSERT(node->getRight()->getType() == boolType); - assignRightBlock->getSequence()->push_back(createTempAssignment(node->getRight())); - - TIntermIfElse *ifNode = - new TIntermIfElse(createTempSymbol(boolType), assignRightBlock, nullptr); - insertions.push_back(ifNode); - - insertStatementsInParentBlock(insertions); - - queueReplacement(createTempSymbol(boolType), OriginalNode::IS_DROPPED); - return false; - } - default: - UNREACHABLE(); - return true; - } -} - -bool UnfoldShortCircuitTraverser::visitTernary(Visit visit, TIntermTernary *node) -{ - if (mFoundShortCircuit) - return false; - - if (visit != PreVisit) - return true; - - if (!mPatternToUnfoldMatcher.match(node)) - return true; - - mFoundShortCircuit = true; - - // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;" - TIntermSequence insertions; - - TIntermDeclaration *tempDeclaration = createTempDeclaration(node->getType()); - insertions.push_back(tempDeclaration); - - TIntermBlock *trueBlock = new TIntermBlock(); - TIntermBinary *trueAssignment = createTempAssignment(node->getTrueExpression()); - trueBlock->getSequence()->push_back(trueAssignment); - - TIntermBlock *falseBlock = new TIntermBlock(); - TIntermBinary *falseAssignment = createTempAssignment(node->getFalseExpression()); - falseBlock->getSequence()->push_back(falseAssignment); - - TIntermIfElse *ifNode = - new TIntermIfElse(node->getCondition()->getAsTyped(), trueBlock, falseBlock); - insertions.push_back(ifNode); - - insertStatementsInParentBlock(insertions); - - TIntermSymbol *ternaryResult = createTempSymbol(node->getType()); - queueReplacement(ternaryResult, OriginalNode::IS_DROPPED); - - return false; -} - -void UnfoldShortCircuitTraverser::nextIteration() -{ - mFoundShortCircuit = false; - nextTemporaryId(); -} - -} // namespace - -void UnfoldShortCircuitToIf(TIntermNode *root, TSymbolTable *symbolTable) -{ - UnfoldShortCircuitTraverser traverser(symbolTable); - // Unfold one operator at a time, and reset the traverser between iterations. - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.foundShortCircuit()) - traverser.updateTree(); - } while (traverser.foundShortCircuit()); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h deleted file mode 100644 index 37dd83a8cf..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UnfoldShortCircuitToIf is an AST traverser to convert short-circuiting operators to if-else -// statements. -// The results are assigned to s# temporaries, which are used by the main translator instead of -// the original expression. -// - -#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ -#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ - -namespace sh -{ - -class TIntermNode; -class TSymbolTable; - -void UnfoldShortCircuitToIf(TIntermNode *root, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp deleted file mode 100644 index 9f18509438..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp +++ /dev/null @@ -1,600 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UniformHLSL.cpp: -// Methods for GLSL to HLSL translation for uniforms and uniform blocks. -// - -#include "compiler/translator/UniformHLSL.h" - -#include "common/utilities.h" -#include "compiler/translator/StructureHLSL.h" -#include "compiler/translator/UtilsHLSL.h" -#include "compiler/translator/blocklayoutHLSL.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -static const char *UniformRegisterPrefix(const TType &type) -{ - if (IsSampler(type.getBasicType())) - { - return "s"; - } - else - { - return "c"; - } -} - -static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage) -{ - const TType &fieldType = *field.type(); - const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking; - ASSERT(matrixPacking != EmpUnspecified); - const TStructure *structure = fieldType.getStruct(); - - if (fieldType.isMatrix()) - { - // Use HLSL row-major packing for GLSL column-major matrices - const TString &matrixPackString = - (matrixPacking == EmpRowMajor ? "column_major" : "row_major"); - return matrixPackString + " " + TypeString(fieldType); - } - else if (structure) - { - // Use HLSL row-major packing for GLSL column-major matrices - return QualifiedStructNameString(*structure, matrixPacking == EmpColumnMajor, - blockStorage == EbsStd140); - } - else - { - return TypeString(fieldType); - } -} - -static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock) -{ - return DecoratePrivate(interfaceBlock.name()) + "_type"; -} - -void OutputSamplerIndexArrayInitializer(TInfoSinkBase &out, - const TType &type, - unsigned int startIndex) -{ - out << "{"; - TType elementType(type); - elementType.toArrayElementType(); - for (unsigned int i = 0u; i < type.getOutermostArraySize(); ++i) - { - if (i > 0u) - { - out << ", "; - } - if (elementType.isArray()) - { - OutputSamplerIndexArrayInitializer(out, elementType, - startIndex + i * elementType.getArraySizeProduct()); - } - else - { - out << (startIndex + i); - } - } - out << "}"; -} - -} // anonymous namespace - -UniformHLSL::UniformHLSL(sh::GLenum shaderType, - StructureHLSL *structureHLSL, - ShShaderOutput outputType, - const std::vector<Uniform> &uniforms) - : mUniformRegister(0), - mUniformBlockRegister(0), - mTextureRegister(0), - mRWTextureRegister(0), - mSamplerCount(0), - mShaderType(shaderType), - mStructureHLSL(structureHLSL), - mOutputType(outputType), - mUniforms(uniforms) -{ -} - -void UniformHLSL::reserveUniformRegisters(unsigned int registerCount) -{ - mUniformRegister = registerCount; -} - -void UniformHLSL::reserveUniformBlockRegisters(unsigned int registerCount) -{ - mUniformBlockRegister = registerCount; -} - -const Uniform *UniformHLSL::findUniformByName(const TString &name) const -{ - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex) - { - if (mUniforms[uniformIndex].name == name.c_str()) - { - return &mUniforms[uniformIndex]; - } - } - - return nullptr; -} - -unsigned int UniformHLSL::assignUniformRegister(const TType &type, - const TString &name, - unsigned int *outRegisterCount) -{ - unsigned int registerIndex; - const Uniform *uniform = findUniformByName(name); - ASSERT(uniform); - - if (IsSampler(type.getBasicType()) || - (IsImage(type.getBasicType()) && type.getMemoryQualifier().readonly)) - { - registerIndex = mTextureRegister; - } - else if (IsImage(type.getBasicType())) - { - registerIndex = mRWTextureRegister; - } - else - { - registerIndex = mUniformRegister; - } - - mUniformRegisterMap[uniform->name] = registerIndex; - - unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType); - - if (IsSampler(type.getBasicType()) || - (IsImage(type.getBasicType()) && type.getMemoryQualifier().readonly)) - { - mTextureRegister += registerCount; - } - else if (IsImage(type.getBasicType())) - { - mRWTextureRegister += registerCount; - } - else - { - mUniformRegister += registerCount; - } - if (outRegisterCount) - { - *outRegisterCount = registerCount; - } - return registerIndex; -} - -unsigned int UniformHLSL::assignSamplerInStructUniformRegister(const TType &type, - const TString &name, - unsigned int *outRegisterCount) -{ - // Sampler that is a field of a uniform structure. - ASSERT(IsSampler(type.getBasicType())); - unsigned int registerIndex = mTextureRegister; - mUniformRegisterMap[std::string(name.c_str())] = registerIndex; - unsigned int registerCount = type.isArray() ? type.getArraySizeProduct() : 1u; - mTextureRegister += registerCount; - if (outRegisterCount) - { - *outRegisterCount = registerCount; - } - return registerIndex; -} - -void UniformHLSL::outputHLSLSamplerUniformGroup( - TInfoSinkBase &out, - const HLSLTextureGroup textureGroup, - const TVector<const TIntermSymbol *> &group, - const TMap<const TIntermSymbol *, TString> &samplerInStructSymbolsToAPINames, - unsigned int *groupTextureRegisterIndex) -{ - if (group.empty()) - { - return; - } - unsigned int groupRegisterCount = 0; - for (const TIntermSymbol *uniform : group) - { - const TType &type = uniform->getType(); - const TString &name = uniform->getSymbol(); - unsigned int registerCount; - - // The uniform might be just a regular sampler or one extracted from a struct. - unsigned int samplerArrayIndex = 0u; - const Uniform *uniformByName = findUniformByName(name); - if (uniformByName) - { - samplerArrayIndex = assignUniformRegister(type, name, ®isterCount); - } - else - { - ASSERT(samplerInStructSymbolsToAPINames.find(uniform) != - samplerInStructSymbolsToAPINames.end()); - samplerArrayIndex = assignSamplerInStructUniformRegister( - type, samplerInStructSymbolsToAPINames.at(uniform), ®isterCount); - } - groupRegisterCount += registerCount; - - if (type.isArray()) - { - out << "static const uint " << DecorateVariableIfNeeded(uniform->getName()) - << ArrayString(type) << " = "; - OutputSamplerIndexArrayInitializer(out, type, samplerArrayIndex); - out << ";\n"; - } - else - { - out << "static const uint " << DecorateVariableIfNeeded(uniform->getName()) << " = " - << samplerArrayIndex << ";\n"; - } - } - TString suffix = TextureGroupSuffix(textureGroup); - // Since HLSL_TEXTURE_2D is the first group, it has a fixed offset of zero. - if (textureGroup != HLSL_TEXTURE_2D) - { - out << "static const uint textureIndexOffset" << suffix << " = " - << (*groupTextureRegisterIndex) << ";\n"; - out << "static const uint samplerIndexOffset" << suffix << " = " - << (*groupTextureRegisterIndex) << ";\n"; - } - out << "uniform " << TextureString(textureGroup) << " textures" << suffix << "[" - << groupRegisterCount << "]" - << " : register(t" << (*groupTextureRegisterIndex) << ");\n"; - out << "uniform " << SamplerString(textureGroup) << " samplers" << suffix << "[" - << groupRegisterCount << "]" - << " : register(s" << (*groupTextureRegisterIndex) << ");\n"; - *groupTextureRegisterIndex += groupRegisterCount; -} - -void UniformHLSL::outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex) -{ - out << "uniform " << SamplerString(type.getBasicType()) << " sampler_" - << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(s" - << str(registerIndex) << ");\n"; - out << "uniform " << TextureString(type.getBasicType()) << " texture_" - << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(t" - << str(registerIndex) << ");\n"; -} - -void UniformHLSL::outputHLSL4_1_FL11Texture(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex) -{ - // TODO(xinghua.cao@intel.com): if image2D variable is bound on one layer of Texture3D or - // Texture2DArray. Translate this variable to HLSL Texture3D object or HLSL Texture2DArray - // object, or create a temporary Texture2D to save content of the layer and bind the - // temporary Texture2D to image2D variable. - out << "uniform " - << TextureString(type.getBasicType(), type.getLayoutQualifier().imageInternalFormat) << " " - << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(t" - << str(registerIndex) << ");\n"; - return; -} - -void UniformHLSL::outputHLSL4_1_FL11RWTexture(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex) -{ - // TODO(xinghua.cao@intel.com): if image2D variable is bound on one layer of Texture3D or - // Texture2DArray. Translate this variable to HLSL RWTexture3D object or HLSL RWTexture2DArray - // object, or create a temporary Texture2D to save content of the layer and bind the - // temporary Texture2D to image2D variable. - if (mShaderType == GL_COMPUTE_SHADER) - { - out << "uniform " - << RWTextureString(type.getBasicType(), type.getLayoutQualifier().imageInternalFormat) - << " " << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(u" - << str(registerIndex) << ");\n"; - } - else - { - // TODO(xinghua.cao@intel.com): Support images in vertex shader and fragment shader, - // which are needed to sync binding value when linking program. - } - return; -} - -void UniformHLSL::outputUniform(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex) -{ - const TStructure *structure = type.getStruct(); - // If this is a nameless struct, we need to use its full definition, rather than its (empty) - // name. - // TypeString() will invoke defineNameless in this case; qualifier prefixes are unnecessary for - // nameless structs in ES, as nameless structs cannot be used anywhere that layout qualifiers - // are permitted. - const TString &typeName = ((structure && !structure->name().empty()) - ? QualifiedStructNameString(*structure, false, false) - : TypeString(type)); - - const TString ®isterString = - TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")"; - - out << "uniform " << typeName << " "; - - out << DecorateVariableIfNeeded(name); - - out << ArrayString(type) << " : " << registerString << ";\n"; -} - -void UniformHLSL::uniformsHeader(TInfoSinkBase &out, - ShShaderOutput outputType, - const ReferencedSymbols &referencedUniforms, - TSymbolTable *symbolTable) -{ - if (!referencedUniforms.empty()) - { - out << "// Uniforms\n\n"; - } - // In the case of HLSL 4, sampler uniforms need to be grouped by type before the code is - // written. They are grouped based on the combination of the HLSL texture type and - // HLSL sampler type, enumerated in HLSLTextureSamplerGroup. - TVector<TVector<const TIntermSymbol *>> groupedSamplerUniforms(HLSL_TEXTURE_MAX + 1); - TMap<const TIntermSymbol *, TString> samplerInStructSymbolsToAPINames; - TVector<const TIntermSymbol *> imageUniformsHLSL41Output; - for (auto &uniformIt : referencedUniforms) - { - // Output regular uniforms. Group sampler uniforms by type. - const TIntermSymbol &uniform = *uniformIt.second; - const TType &type = uniform.getType(); - const TName &name = uniform.getName(); - - if (outputType == SH_HLSL_4_1_OUTPUT && IsSampler(type.getBasicType())) - { - HLSLTextureGroup group = TextureGroup(type.getBasicType()); - groupedSamplerUniforms[group].push_back(&uniform); - } - else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(type.getBasicType())) - { - unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr); - outputHLSL4_0_FL9_3Sampler(out, type, name, registerIndex); - } - else if (outputType == SH_HLSL_4_1_OUTPUT && IsImage(type.getBasicType())) - { - imageUniformsHLSL41Output.push_back(&uniform); - } - else - { - if (type.isStructureContainingSamplers()) - { - TVector<TIntermSymbol *> samplerSymbols; - TMap<TIntermSymbol *, TString> symbolsToAPINames; - type.createSamplerSymbols("angle_" + name.getString(), name.getString(), - &samplerSymbols, &symbolsToAPINames, symbolTable); - for (TIntermSymbol *sampler : samplerSymbols) - { - const TType &samplerType = sampler->getType(); - - // Will use angle_ prefix instead of regular prefix. - sampler->setInternal(true); - const TName &samplerName = sampler->getName(); - - if (outputType == SH_HLSL_4_1_OUTPUT) - { - HLSLTextureGroup group = TextureGroup(samplerType.getBasicType()); - groupedSamplerUniforms[group].push_back(sampler); - samplerInStructSymbolsToAPINames[sampler] = symbolsToAPINames[sampler]; - } - else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT) - { - unsigned int registerIndex = assignSamplerInStructUniformRegister( - samplerType, symbolsToAPINames[sampler], nullptr); - outputHLSL4_0_FL9_3Sampler(out, samplerType, samplerName, registerIndex); - } - else - { - ASSERT(outputType == SH_HLSL_3_0_OUTPUT); - unsigned int registerIndex = assignSamplerInStructUniformRegister( - samplerType, symbolsToAPINames[sampler], nullptr); - outputUniform(out, samplerType, samplerName, registerIndex); - } - } - } - unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr); - outputUniform(out, type, name, registerIndex); - } - } - - if (outputType == SH_HLSL_4_1_OUTPUT) - { - unsigned int groupTextureRegisterIndex = 0; - // TEXTURE_2D is special, index offset is assumed to be 0 and omitted in that case. - ASSERT(HLSL_TEXTURE_MIN == HLSL_TEXTURE_2D); - for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId) - { - outputHLSLSamplerUniformGroup( - out, HLSLTextureGroup(groupId), groupedSamplerUniforms[groupId], - samplerInStructSymbolsToAPINames, &groupTextureRegisterIndex); - } - mSamplerCount = groupTextureRegisterIndex; - - for (const TIntermSymbol *image : imageUniformsHLSL41Output) - { - const TType &type = image->getType(); - const TName &name = image->getName(); - unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr); - if (type.getMemoryQualifier().readonly) - { - outputHLSL4_1_FL11Texture(out, type, name, registerIndex); - } - else - { - outputHLSL4_1_FL11RWTexture(out, type, name, registerIndex); - } - } - } -} - -void UniformHLSL::samplerMetadataUniforms(TInfoSinkBase &out, const char *reg) -{ - // If mSamplerCount is 0 the shader doesn't use any textures for samplers. - if (mSamplerCount > 0) - { - out << " struct SamplerMetadata\n" - " {\n" - " int baseLevel;\n" - " int internalFormatBits;\n" - " int wrapModes;\n" - " int padding;\n" - " };\n" - " SamplerMetadata samplerMetadata[" - << mSamplerCount << "] : packoffset(" << reg << ");\n"; - } -} - -TString UniformHLSL::uniformBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks) -{ - TString interfaceBlocks; - - for (ReferencedSymbols::const_iterator interfaceBlockIt = referencedInterfaceBlocks.begin(); - interfaceBlockIt != referencedInterfaceBlocks.end(); interfaceBlockIt++) - { - const TType &nodeType = interfaceBlockIt->second->getType(); - const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock(); - - // nodeType.isInterfaceBlock() == false means the node is a field of a uniform block which - // doesn't have instance name, so this block cannot be an array. - unsigned int interfaceBlockArraySize = 0u; - if (nodeType.isInterfaceBlock() && nodeType.isArray()) - { - interfaceBlockArraySize = nodeType.getOutermostArraySize(); - } - unsigned int activeRegister = mUniformBlockRegister; - - mUniformBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister; - mUniformBlockRegister += std::max(1u, interfaceBlockArraySize); - - // FIXME: interface block field names - - if (interfaceBlock.hasInstanceName()) - { - interfaceBlocks += uniformBlockStructString(interfaceBlock); - } - - if (interfaceBlockArraySize > 0) - { - for (unsigned int arrayIndex = 0; arrayIndex < interfaceBlockArraySize; arrayIndex++) - { - interfaceBlocks += - uniformBlockString(interfaceBlock, activeRegister + arrayIndex, arrayIndex); - } - } - else - { - interfaceBlocks += uniformBlockString(interfaceBlock, activeRegister, GL_INVALID_INDEX); - } - } - - return (interfaceBlocks.empty() ? "" : ("// Uniform Blocks\n\n" + interfaceBlocks)); -} - -TString UniformHLSL::uniformBlockString(const TInterfaceBlock &interfaceBlock, - unsigned int registerIndex, - unsigned int arrayIndex) -{ - const TString &arrayIndexString = - (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : ""); - const TString &blockName = interfaceBlock.name() + arrayIndexString; - TString hlsl; - - hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + - ")\n" - "{\n"; - - if (interfaceBlock.hasInstanceName()) - { - hlsl += " " + InterfaceBlockStructName(interfaceBlock) + " " + - uniformBlockInstanceString(interfaceBlock, arrayIndex) + ";\n"; - } - else - { - const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage(); - hlsl += uniformBlockMembersString(interfaceBlock, blockStorage); - } - - hlsl += "};\n\n"; - - return hlsl; -} - -TString UniformHLSL::uniformBlockInstanceString(const TInterfaceBlock &interfaceBlock, - unsigned int arrayIndex) -{ - if (!interfaceBlock.hasInstanceName()) - { - return ""; - } - else if (arrayIndex != GL_INVALID_INDEX) - { - return DecoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex); - } - else - { - return Decorate(interfaceBlock.instanceName()); - } -} - -TString UniformHLSL::uniformBlockMembersString(const TInterfaceBlock &interfaceBlock, - TLayoutBlockStorage blockStorage) -{ - TString hlsl; - - Std140PaddingHelper padHelper = mStructureHLSL->getPaddingHelper(); - - for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++) - { - const TField &field = *interfaceBlock.fields()[typeIndex]; - const TType &fieldType = *field.type(); - - if (blockStorage == EbsStd140) - { - // 2 and 3 component vector types in some cases need pre-padding - hlsl += padHelper.prePaddingString(fieldType); - } - - hlsl += " " + InterfaceBlockFieldTypeString(field, blockStorage) + " " + - Decorate(field.name()) + ArrayString(fieldType) + ";\n"; - - // must pad out after matrices and arrays, where HLSL usually allows itself room to pack - // stuff - if (blockStorage == EbsStd140) - { - const bool useHLSLRowMajorPacking = - (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor); - hlsl += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking); - } - } - - return hlsl; -} - -TString UniformHLSL::uniformBlockStructString(const TInterfaceBlock &interfaceBlock) -{ - const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage(); - - return "struct " + InterfaceBlockStructName(interfaceBlock) + - "\n" - "{\n" + - uniformBlockMembersString(interfaceBlock, blockStorage) + "};\n\n"; -} -} diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h deleted file mode 100644 index 8784e50533..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UniformHLSL.h: -// Methods for GLSL to HLSL translation for uniforms and uniform blocks. -// - -#ifndef COMPILER_TRANSLATOR_UNIFORMHLSL_H_ -#define COMPILER_TRANSLATOR_UNIFORMHLSL_H_ - -#include "compiler/translator/OutputHLSL.h" -#include "compiler/translator/UtilsHLSL.h" - -namespace sh -{ -class StructureHLSL; -class TSymbolTable; - -class UniformHLSL : angle::NonCopyable -{ - public: - UniformHLSL(sh::GLenum shaderType, - StructureHLSL *structureHLSL, - ShShaderOutput outputType, - const std::vector<Uniform> &uniforms); - - void reserveUniformRegisters(unsigned int registerCount); - void reserveUniformBlockRegisters(unsigned int registerCount); - void uniformsHeader(TInfoSinkBase &out, - ShShaderOutput outputType, - const ReferencedSymbols &referencedUniforms, - TSymbolTable *symbolTable); - - // Must be called after uniformsHeader - void samplerMetadataUniforms(TInfoSinkBase &out, const char *reg); - - TString uniformBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks); - - // Used for direct index references - static TString uniformBlockInstanceString(const TInterfaceBlock &interfaceBlock, - unsigned int arrayIndex); - - const std::map<std::string, unsigned int> &getUniformBlockRegisterMap() const - { - return mUniformBlockRegisterMap; - } - const std::map<std::string, unsigned int> &getUniformRegisterMap() const - { - return mUniformRegisterMap; - } - - private: - TString uniformBlockString(const TInterfaceBlock &interfaceBlock, - unsigned int registerIndex, - unsigned int arrayIndex); - TString uniformBlockMembersString(const TInterfaceBlock &interfaceBlock, - TLayoutBlockStorage blockStorage); - TString uniformBlockStructString(const TInterfaceBlock &interfaceBlock); - const Uniform *findUniformByName(const TString &name) const; - - void outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex); - void outputHLSL4_1_FL11Texture(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex); - void outputHLSL4_1_FL11RWTexture(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex); - void outputUniform(TInfoSinkBase &out, - const TType &type, - const TName &name, - const unsigned int registerIndex); - - // Returns the uniform's register index - unsigned int assignUniformRegister(const TType &type, - const TString &name, - unsigned int *outRegisterCount); - unsigned int assignSamplerInStructUniformRegister(const TType &type, - const TString &name, - unsigned int *outRegisterCount); - - void outputHLSLSamplerUniformGroup( - TInfoSinkBase &out, - const HLSLTextureGroup textureGroup, - const TVector<const TIntermSymbol *> &group, - const TMap<const TIntermSymbol *, TString> &samplerInStructSymbolsToAPINames, - unsigned int *groupTextureRegisterIndex); - - unsigned int mUniformRegister; - unsigned int mUniformBlockRegister; - unsigned int mTextureRegister; - unsigned int mRWTextureRegister; - unsigned int mSamplerCount; - sh::GLenum mShaderType; - StructureHLSL *mStructureHLSL; - ShShaderOutput mOutputType; - - const std::vector<Uniform> &mUniforms; - std::map<std::string, unsigned int> mUniformBlockRegisterMap; - std::map<std::string, unsigned int> mUniformRegisterMap; -}; -} - -#endif // COMPILER_TRANSLATOR_UNIFORMHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp b/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp deleted file mode 100644 index 40bd42afad..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// Copyright 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// UseInterfaceBlockFields.cpp: insert statements to reference all members in InterfaceBlock list at -// the beginning of main. This is to work around a Mac driver that treats unused standard/shared -// uniform blocks as inactive. - -#include "compiler/translator/UseInterfaceBlockFields.h" - -#include "compiler/translator/FindMain.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermNode_util.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -void AddNodeUseStatements(TIntermTyped *node, TIntermSequence *sequence) -{ - if (node->isArray()) - { - for (unsigned int i = 0u; i < node->getOutermostArraySize(); ++i) - { - TIntermBinary *element = - new TIntermBinary(EOpIndexDirect, node->deepCopy(), CreateIndexNode(i)); - AddNodeUseStatements(element, sequence); - } - } - else - { - sequence->insert(sequence->begin(), node); - } -} - -void AddFieldUseStatements(const ShaderVariable &var, - TIntermSequence *sequence, - const TSymbolTable &symbolTable) -{ - TString name = TString(var.name.c_str()); - ASSERT(name.find_last_of('[') == TString::npos); - TIntermSymbol *symbol = ReferenceGlobalVariable(name, symbolTable); - AddNodeUseStatements(symbol, sequence); -} - -void InsertUseCode(const InterfaceBlock &block, TIntermTyped *blockNode, TIntermSequence *sequence) -{ - for (unsigned int i = 0; i < block.fields.size(); ++i) - { - TIntermBinary *element = new TIntermBinary(EOpIndexDirectInterfaceBlock, - blockNode->deepCopy(), CreateIndexNode(i)); - sequence->insert(sequence->begin(), element); - } -} - -void InsertUseCode(TIntermSequence *sequence, - const InterfaceBlockList &blocks, - const TSymbolTable &symbolTable) -{ - for (const auto &block : blocks) - { - if (block.instanceName.empty()) - { - for (const auto &var : block.fields) - { - AddFieldUseStatements(var, sequence, symbolTable); - } - } - else if (block.arraySize > 0u) - { - TString name(block.instanceName.c_str()); - TIntermSymbol *arraySymbol = ReferenceGlobalVariable(name, symbolTable); - for (unsigned int i = 0u; i < block.arraySize; ++i) - { - TIntermBinary *elementSymbol = - new TIntermBinary(EOpIndexDirect, arraySymbol->deepCopy(), CreateIndexNode(i)); - InsertUseCode(block, elementSymbol, sequence); - } - } - else - { - TString name(block.instanceName.c_str()); - TIntermSymbol *blockSymbol = ReferenceGlobalVariable(name, symbolTable); - InsertUseCode(block, blockSymbol, sequence); - } - } -} - -} // namespace anonymous - -void UseInterfaceBlockFields(TIntermBlock *root, - const InterfaceBlockList &blocks, - const TSymbolTable &symbolTable) -{ - TIntermBlock *mainBody = FindMainBody(root); - InsertUseCode(mainBody->getSequence(), blocks, symbolTable); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h b/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h deleted file mode 100644 index 3e2a4815d4..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// UseInterfaceBlockFields.h: insert statements to reference all members in InterfaceBlock list at -// the beginning of main. This is to work around a Mac driver that treats unused standard/shared -// uniform blocks as inactive. - -#ifndef COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_ -#define COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_ - -#include <GLSLANG/ShaderLang.h> - -namespace sh -{ - -class TIntermBlock; -class TSymbolTable; - -using InterfaceBlockList = std::vector<sh::InterfaceBlock>; - -void UseInterfaceBlockFields(TIntermBlock *root, - const InterfaceBlockList &blocks, - const TSymbolTable &symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp deleted file mode 100644 index 8a77f0049a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp +++ /dev/null @@ -1,970 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UtilsHLSL.cpp: -// Utility methods for GLSL to HLSL translation. -// - -#include "compiler/translator/UtilsHLSL.h" -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/StructureHLSL.h" -#include "compiler/translator/SymbolTable.h" - -namespace sh -{ - -TString SamplerString(const TBasicType type) -{ - if (IsShadowSampler(type)) - { - return "SamplerComparisonState"; - } - else - { - return "SamplerState"; - } -} - -TString SamplerString(HLSLTextureGroup type) -{ - if (type >= HLSL_COMPARISON_SAMPLER_GROUP_BEGIN && type <= HLSL_COMPARISON_SAMPLER_GROUP_END) - { - return "SamplerComparisonState"; - } - else - { - return "SamplerState"; - } -} - -HLSLTextureGroup TextureGroup(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) - -{ - switch (type) - { - case EbtSampler2D: - return HLSL_TEXTURE_2D; - case EbtSamplerCube: - return HLSL_TEXTURE_CUBE; - case EbtSamplerExternalOES: - return HLSL_TEXTURE_2D; - case EbtSampler2DArray: - return HLSL_TEXTURE_2D_ARRAY; - case EbtSampler3D: - return HLSL_TEXTURE_3D; - case EbtSampler2DMS: - return HLSL_TEXTURE_2D_MS; - case EbtISampler2D: - return HLSL_TEXTURE_2D_INT4; - case EbtISampler3D: - return HLSL_TEXTURE_3D_INT4; - case EbtISamplerCube: - return HLSL_TEXTURE_2D_ARRAY_INT4; - case EbtISampler2DArray: - return HLSL_TEXTURE_2D_ARRAY_INT4; - case EbtISampler2DMS: - return HLSL_TEXTURE_2D_MS_INT4; - case EbtUSampler2D: - return HLSL_TEXTURE_2D_UINT4; - case EbtUSampler3D: - return HLSL_TEXTURE_3D_UINT4; - case EbtUSamplerCube: - return HLSL_TEXTURE_2D_ARRAY_UINT4; - case EbtUSampler2DArray: - return HLSL_TEXTURE_2D_ARRAY_UINT4; - case EbtUSampler2DMS: - return HLSL_TEXTURE_2D_MS_UINT4; - case EbtSampler2DShadow: - return HLSL_TEXTURE_2D_COMPARISON; - case EbtSamplerCubeShadow: - return HLSL_TEXTURE_CUBE_COMPARISON; - case EbtSampler2DArrayShadow: - return HLSL_TEXTURE_2D_ARRAY_COMPARISON; - case EbtImage2D: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return HLSL_TEXTURE_2D; - case EiifRGBA8: - return HLSL_TEXTURE_2D_UNORM; - case EiifRGBA8_SNORM: - return HLSL_TEXTURE_2D_SNORM; - default: - UNREACHABLE(); - } - } - case EbtIImage2D: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return HLSL_TEXTURE_2D_INT4; - default: - UNREACHABLE(); - } - } - case EbtUImage2D: - { - switch (imageInternalFormat) - { - - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return HLSL_TEXTURE_2D_UINT4; - default: - UNREACHABLE(); - } - } - case EbtImage3D: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return HLSL_TEXTURE_3D; - case EiifRGBA8: - return HLSL_TEXTURE_3D_UNORM; - case EiifRGBA8_SNORM: - return HLSL_TEXTURE_3D_SNORM; - default: - UNREACHABLE(); - } - } - case EbtIImage3D: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return HLSL_TEXTURE_3D_INT4; - default: - UNREACHABLE(); - } - } - case EbtUImage3D: - { - switch (imageInternalFormat) - { - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return HLSL_TEXTURE_3D_UINT4; - default: - UNREACHABLE(); - } - } - case EbtImage2DArray: - case EbtImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return HLSL_TEXTURE_2D_ARRAY; - case EiifRGBA8: - return HLSL_TEXTURE_2D_ARRAY_UNORN; - case EiifRGBA8_SNORM: - return HLSL_TEXTURE_2D_ARRAY_SNORM; - default: - UNREACHABLE(); - } - } - case EbtIImage2DArray: - case EbtIImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return HLSL_TEXTURE_2D_ARRAY_INT4; - default: - UNREACHABLE(); - } - } - case EbtUImage2DArray: - case EbtUImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return HLSL_TEXTURE_2D_ARRAY_UINT4; - default: - UNREACHABLE(); - } - } - default: - UNREACHABLE(); - } - return HLSL_TEXTURE_UNKNOWN; -} - -TString TextureString(const HLSLTextureGroup textureGroup) -{ - switch (textureGroup) - { - case HLSL_TEXTURE_2D: - return "Texture2D<float4>"; - case HLSL_TEXTURE_CUBE: - return "TextureCube<float4>"; - case HLSL_TEXTURE_2D_ARRAY: - return "Texture2DArray<float4>"; - case HLSL_TEXTURE_3D: - return "Texture3D<float4>"; - case HLSL_TEXTURE_2D_UNORM: - return "Texture2D<unorm float4>"; - case HLSL_TEXTURE_CUBE_UNORM: - return "TextureCube<unorm float4>"; - case HLSL_TEXTURE_2D_ARRAY_UNORN: - return "Texture2DArray<unorm float4>"; - case HLSL_TEXTURE_3D_UNORM: - return "Texture3D<unorm float4>"; - case HLSL_TEXTURE_2D_SNORM: - return "Texture2D<snorm float4>"; - case HLSL_TEXTURE_CUBE_SNORM: - return "TextureCube<snorm float4>"; - case HLSL_TEXTURE_2D_ARRAY_SNORM: - return "Texture2DArray<snorm float4>"; - case HLSL_TEXTURE_3D_SNORM: - return "Texture3D<snorm float4>"; - case HLSL_TEXTURE_2D_MS: - return "Texture2DMS<float4>"; - case HLSL_TEXTURE_2D_INT4: - return "Texture2D<int4>"; - case HLSL_TEXTURE_3D_INT4: - return "Texture3D<int4>"; - case HLSL_TEXTURE_2D_ARRAY_INT4: - return "Texture2DArray<int4>"; - case HLSL_TEXTURE_2D_MS_INT4: - return "Texture2DMS<int4>"; - case HLSL_TEXTURE_2D_UINT4: - return "Texture2D<uint4>"; - case HLSL_TEXTURE_3D_UINT4: - return "Texture3D<uint4>"; - case HLSL_TEXTURE_2D_ARRAY_UINT4: - return "Texture2DArray<uint4>"; - case HLSL_TEXTURE_2D_MS_UINT4: - return "Texture2DMS<uint4>"; - case HLSL_TEXTURE_2D_COMPARISON: - return "Texture2D"; - case HLSL_TEXTURE_CUBE_COMPARISON: - return "TextureCube"; - case HLSL_TEXTURE_2D_ARRAY_COMPARISON: - return "Texture2DArray"; - default: - UNREACHABLE(); - } - - return "<unknown read texture type>"; -} - -TString TextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) -{ - return TextureString(TextureGroup(type, imageInternalFormat)); -} - -TString TextureGroupSuffix(const HLSLTextureGroup type) -{ - switch (type) - { - case HLSL_TEXTURE_2D: - return "2D"; - case HLSL_TEXTURE_CUBE: - return "Cube"; - case HLSL_TEXTURE_2D_ARRAY: - return "2DArray"; - case HLSL_TEXTURE_3D: - return "3D"; - case HLSL_TEXTURE_2D_UNORM: - return "2D_unorm_float4_"; - case HLSL_TEXTURE_CUBE_UNORM: - return "Cube_unorm_float4_"; - case HLSL_TEXTURE_2D_ARRAY_UNORN: - return "2DArray_unorm_float4_"; - case HLSL_TEXTURE_3D_UNORM: - return "3D_unorm_float4_"; - case HLSL_TEXTURE_2D_SNORM: - return "2D_snorm_float4_"; - case HLSL_TEXTURE_CUBE_SNORM: - return "Cube_snorm_float4_"; - case HLSL_TEXTURE_2D_ARRAY_SNORM: - return "2DArray_snorm_float4_"; - case HLSL_TEXTURE_3D_SNORM: - return "3D_snorm_float4_"; - case HLSL_TEXTURE_2D_MS: - return "2DMS"; - case HLSL_TEXTURE_2D_INT4: - return "2D_int4_"; - case HLSL_TEXTURE_3D_INT4: - return "3D_int4_"; - case HLSL_TEXTURE_2D_ARRAY_INT4: - return "2DArray_int4_"; - case HLSL_TEXTURE_2D_MS_INT4: - return "2DMS_int4_"; - case HLSL_TEXTURE_2D_UINT4: - return "2D_uint4_"; - case HLSL_TEXTURE_3D_UINT4: - return "3D_uint4_"; - case HLSL_TEXTURE_2D_ARRAY_UINT4: - return "2DArray_uint4_"; - case HLSL_TEXTURE_2D_MS_UINT4: - return "2DMS_uint4_"; - case HLSL_TEXTURE_2D_COMPARISON: - return "2D_comparison"; - case HLSL_TEXTURE_CUBE_COMPARISON: - return "Cube_comparison"; - case HLSL_TEXTURE_2D_ARRAY_COMPARISON: - return "2DArray_comparison"; - default: - UNREACHABLE(); - } - - return "<unknown texture type>"; -} - -TString TextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) -{ - return TextureGroupSuffix(TextureGroup(type, imageInternalFormat)); -} - -TString TextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) -{ - switch (type) - { - case EbtISamplerCube: - return "Cube_int4_"; - case EbtUSamplerCube: - return "Cube_uint4_"; - case EbtSamplerExternalOES: - return "_External"; - case EbtImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return "Cube_float4_"; - case EiifRGBA8: - return "Cube_unorm_float4_"; - case EiifRGBA8_SNORM: - return "Cube_snorm_float4_"; - default: - UNREACHABLE(); - } - } - case EbtIImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return "Cube_int4_"; - default: - UNREACHABLE(); - } - } - case EbtUImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return "Cube_uint4_"; - default: - UNREACHABLE(); - } - } - default: - // All other types are identified by their group suffix - return TextureGroupSuffix(type, imageInternalFormat); - } -} - -HLSLRWTextureGroup RWTextureGroup(const TBasicType type, - TLayoutImageInternalFormat imageInternalFormat) - -{ - switch (type) - { - case EbtImage2D: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return HLSL_RWTEXTURE_2D_FLOAT4; - case EiifRGBA8: - return HLSL_RWTEXTURE_2D_UNORM; - case EiifRGBA8_SNORM: - return HLSL_RWTEXTURE_2D_SNORM; - default: - UNREACHABLE(); - } - } - case EbtIImage2D: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return HLSL_RWTEXTURE_2D_INT4; - default: - UNREACHABLE(); - } - } - case EbtUImage2D: - { - switch (imageInternalFormat) - { - - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return HLSL_RWTEXTURE_2D_UINT4; - default: - UNREACHABLE(); - } - } - case EbtImage3D: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return HLSL_RWTEXTURE_3D_FLOAT4; - case EiifRGBA8: - return HLSL_RWTEXTURE_3D_UNORM; - case EiifRGBA8_SNORM: - return HLSL_RWTEXTURE_3D_SNORM; - default: - UNREACHABLE(); - } - } - case EbtIImage3D: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return HLSL_RWTEXTURE_3D_INT4; - default: - UNREACHABLE(); - } - } - case EbtUImage3D: - { - switch (imageInternalFormat) - { - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return HLSL_RWTEXTURE_3D_UINT4; - default: - UNREACHABLE(); - } - } - case EbtImage2DArray: - case EbtImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return HLSL_RWTEXTURE_2D_ARRAY_FLOAT4; - case EiifRGBA8: - return HLSL_RWTEXTURE_2D_ARRAY_UNORN; - case EiifRGBA8_SNORM: - return HLSL_RWTEXTURE_2D_ARRAY_SNORM; - default: - UNREACHABLE(); - } - } - case EbtIImage2DArray: - case EbtIImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return HLSL_RWTEXTURE_2D_ARRAY_INT4; - default: - UNREACHABLE(); - } - } - case EbtUImage2DArray: - case EbtUImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return HLSL_RWTEXTURE_2D_ARRAY_UINT4; - default: - UNREACHABLE(); - } - } - default: - UNREACHABLE(); - } - return HLSL_RWTEXTURE_UNKNOWN; -} - -TString RWTextureString(const HLSLRWTextureGroup RWTextureGroup) -{ - switch (RWTextureGroup) - { - case HLSL_RWTEXTURE_2D_FLOAT4: - return "RWTexture2D<float4>"; - case HLSL_RWTEXTURE_2D_ARRAY_FLOAT4: - return "RWTexture2DArray<float4>"; - case HLSL_RWTEXTURE_3D_FLOAT4: - return "RWTexture3D<float4>"; - case HLSL_RWTEXTURE_2D_UNORM: - return "RWTexture2D<unorm float4>"; - case HLSL_RWTEXTURE_2D_ARRAY_UNORN: - return "RWTexture2DArray<unorm float4>"; - case HLSL_RWTEXTURE_3D_UNORM: - return "RWTexture3D<unorm float4>"; - case HLSL_RWTEXTURE_2D_SNORM: - return "RWTexture2D<snorm float4>"; - case HLSL_RWTEXTURE_2D_ARRAY_SNORM: - return "RWTexture2DArray<snorm float4>"; - case HLSL_RWTEXTURE_3D_SNORM: - return "RWTexture3D<snorm float4>"; - case HLSL_RWTEXTURE_2D_UINT4: - return "RWTexture2D<uint4>"; - case HLSL_RWTEXTURE_2D_ARRAY_UINT4: - return "RWTexture2DArray<uint4>"; - case HLSL_RWTEXTURE_3D_UINT4: - return "RWTexture3D<uint4>"; - case HLSL_RWTEXTURE_2D_INT4: - return "RWTexture2D<int4>"; - case HLSL_RWTEXTURE_2D_ARRAY_INT4: - return "RWTexture2DArray<int4>"; - case HLSL_RWTEXTURE_3D_INT4: - return "RWTexture3D<int4>"; - default: - UNREACHABLE(); - } - - return "<unknown read and write texture type>"; -} - -TString RWTextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) -{ - return RWTextureString(RWTextureGroup(type, imageInternalFormat)); -} - -TString RWTextureGroupSuffix(const HLSLRWTextureGroup type) -{ - switch (type) - { - case HLSL_RWTEXTURE_2D_FLOAT4: - return "RW2D_float4_"; - case HLSL_RWTEXTURE_2D_ARRAY_FLOAT4: - return "RW2DArray_float4_"; - case HLSL_RWTEXTURE_3D_FLOAT4: - return "RW3D_float4_"; - case HLSL_RWTEXTURE_2D_UNORM: - return "RW2D_unorm_float4_"; - case HLSL_RWTEXTURE_2D_ARRAY_UNORN: - return "RW2DArray_unorm_float4_"; - case HLSL_RWTEXTURE_3D_UNORM: - return "RW3D_unorm_float4_"; - case HLSL_RWTEXTURE_2D_SNORM: - return "RW2D_snorm_float4_"; - case HLSL_RWTEXTURE_2D_ARRAY_SNORM: - return "RW2DArray_snorm_float4_"; - case HLSL_RWTEXTURE_3D_SNORM: - return "RW3D_snorm_float4_"; - case HLSL_RWTEXTURE_2D_UINT4: - return "RW2D_uint4_"; - case HLSL_RWTEXTURE_2D_ARRAY_UINT4: - return "RW2DArray_uint4_"; - case HLSL_RWTEXTURE_3D_UINT4: - return "RW3D_uint4_"; - case HLSL_RWTEXTURE_2D_INT4: - return "RW2D_int4_"; - case HLSL_RWTEXTURE_2D_ARRAY_INT4: - return "RW2DArray_int4_"; - case HLSL_RWTEXTURE_3D_INT4: - return "RW3D_int4_"; - default: - UNREACHABLE(); - } - - return "<unknown read and write resource>"; -} - -TString RWTextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) -{ - return RWTextureGroupSuffix(RWTextureGroup(type, imageInternalFormat)); -} - -TString RWTextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat) -{ - switch (type) - { - case EbtImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - return "RWCube_float4_"; - case EiifRGBA8: - return "RWCube_unorm_float4_"; - case EiifRGBA8_SNORM: - return "RWCube_unorm_float4_"; - default: - UNREACHABLE(); - } - } - case EbtIImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - return "RWCube_int4_"; - default: - UNREACHABLE(); - } - } - case EbtUImageCube: - { - switch (imageInternalFormat) - { - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - return "RWCube_uint4_"; - default: - UNREACHABLE(); - } - } - default: - // All other types are identified by their group suffix - return TextureGroupSuffix(type, imageInternalFormat); - } -} - -TString DecorateField(const TString &string, const TStructure &structure) -{ - if (structure.name().compare(0, 3, "gl_") != 0) - { - return Decorate(string); - } - - return string; -} - -TString DecoratePrivate(const TString &privateText) -{ - return "dx_" + privateText; -} - -TString Decorate(const TString &string) -{ - if (string.compare(0, 3, "gl_") != 0) - { - return "_" + string; - } - - return string; -} - -TString DecorateVariableIfNeeded(const TName &name) -{ - if (name.isInternal()) - { - // The name should not have a prefix reserved for user-defined variables or functions. - ASSERT(name.getString().compare(0, 2, "f_") != 0); - ASSERT(name.getString().compare(0, 1, "_") != 0); - return name.getString(); - } - else - { - return Decorate(name.getString()); - } -} - -TString DecorateFunctionIfNeeded(const TName &name) -{ - if (name.isInternal()) - { - // The name should not have a prefix reserved for user-defined variables or functions. - ASSERT(name.getString().compare(0, 2, "f_") != 0); - ASSERT(name.getString().compare(0, 1, "_") != 0); - return name.getString(); - } - ASSERT(name.getString().compare(0, 3, "gl_") != 0); - // Add an additional f prefix to functions so that they're always disambiguated from variables. - // This is necessary in the corner case where a variable declaration hides a function that it - // uses in its initializer. - return "f_" + name.getString(); -} - -TString TypeString(const TType &type) -{ - const TStructure *structure = type.getStruct(); - if (structure) - { - const TString &typeName = structure->name(); - if (typeName != "") - { - return StructNameString(*structure); - } - else // Nameless structure, define in place - { - return StructureHLSL::defineNameless(*structure); - } - } - else if (type.isMatrix()) - { - int cols = type.getCols(); - int rows = type.getRows(); - return "float" + str(cols) + "x" + str(rows); - } - else - { - switch (type.getBasicType()) - { - case EbtFloat: - switch (type.getNominalSize()) - { - case 1: - return "float"; - case 2: - return "float2"; - case 3: - return "float3"; - case 4: - return "float4"; - } - case EbtInt: - switch (type.getNominalSize()) - { - case 1: - return "int"; - case 2: - return "int2"; - case 3: - return "int3"; - case 4: - return "int4"; - } - case EbtUInt: - switch (type.getNominalSize()) - { - case 1: - return "uint"; - case 2: - return "uint2"; - case 3: - return "uint3"; - case 4: - return "uint4"; - } - case EbtBool: - switch (type.getNominalSize()) - { - case 1: - return "bool"; - case 2: - return "bool2"; - case 3: - return "bool3"; - case 4: - return "bool4"; - } - case EbtVoid: - return "void"; - case EbtSampler2D: - case EbtISampler2D: - case EbtUSampler2D: - case EbtSampler2DArray: - case EbtISampler2DArray: - case EbtUSampler2DArray: - return "sampler2D"; - case EbtSamplerCube: - case EbtISamplerCube: - case EbtUSamplerCube: - return "samplerCUBE"; - case EbtSamplerExternalOES: - return "sampler2D"; - case EbtAtomicCounter: - return "atomic_uint"; - default: - break; - } - } - - UNREACHABLE(); - return "<unknown type>"; -} - -TString StructNameString(const TStructure &structure) -{ - if (structure.name().empty()) - { - return ""; - } - - // For structures at global scope we use a consistent - // translation so that we can link between shader stages. - if (structure.atGlobalScope()) - { - return Decorate(structure.name()); - } - - return "ss" + str(structure.uniqueId()) + "_" + structure.name(); -} - -TString QualifiedStructNameString(const TStructure &structure, - bool useHLSLRowMajorPacking, - bool useStd140Packing) -{ - if (structure.name() == "") - { - return ""; - } - - TString prefix = ""; - - // Structs packed with row-major matrices in HLSL are prefixed with "rm" - // GLSL column-major maps to HLSL row-major, and the converse is true - - if (useStd140Packing) - { - prefix += "std_"; - } - - if (useHLSLRowMajorPacking) - { - prefix += "rm_"; - } - - return prefix + StructNameString(structure); -} - -TString InterpolationString(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqVaryingIn: - return ""; - case EvqFragmentIn: - return ""; - case EvqSmoothIn: - return "linear"; - case EvqFlatIn: - return "nointerpolation"; - case EvqCentroidIn: - return "centroid"; - case EvqVaryingOut: - return ""; - case EvqVertexOut: - return ""; - case EvqSmoothOut: - return "linear"; - case EvqFlatOut: - return "nointerpolation"; - case EvqCentroidOut: - return "centroid"; - default: - UNREACHABLE(); - } - - return ""; -} - -TString QualifierString(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqIn: - return "in"; - case EvqOut: - return "inout"; // 'out' results in an HLSL error if not all fields are written, for - // GLSL it's undefined - case EvqInOut: - return "inout"; - case EvqConstReadOnly: - return "const"; - default: - UNREACHABLE(); - } - - return ""; -} - -TString DisambiguateFunctionName(const TIntermSequence *parameters) -{ - TString disambiguatingString; - for (auto parameter : *parameters) - { - const TType ¶mType = parameter->getAsTyped()->getType(); - // Parameter types are only added to function names if they are ambiguous according to the - // native HLSL compiler. Other parameter types are not added to function names to avoid - // making function names longer. - if (paramType.getObjectSize() == 4 && paramType.getBasicType() == EbtFloat) - { - // Disambiguation is needed for float2x2 and float4 parameters. These are the only - // built-in types that HLSL thinks are identical. float2x3 and float3x2 are different - // types, for example. - disambiguatingString += "_" + TypeString(paramType); - } - else if (paramType.getBasicType() == EbtStruct) - { - // Disambiguation is needed for struct parameters, since HLSL thinks that structs with - // the same fields but a different name are identical. - ASSERT(paramType.getStruct()->name() != ""); - disambiguatingString += "_" + TypeString(paramType); - } - } - return disambiguatingString; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h deleted file mode 100644 index daeec8de41..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h +++ /dev/null @@ -1,129 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UtilsHLSL.h: -// Utility methods for GLSL to HLSL translation. -// - -#ifndef COMPILER_TRANSLATOR_UTILSHLSL_H_ -#define COMPILER_TRANSLATOR_UTILSHLSL_H_ - -#include <vector> -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/Types.h" - -#include "angle_gl.h" - -class TName; - -namespace sh -{ - -// HLSL Texture type for GLSL sampler type and readonly image type. -enum HLSLTextureGroup -{ - // read resources - HLSL_TEXTURE_2D, - HLSL_TEXTURE_MIN = HLSL_TEXTURE_2D, - - HLSL_TEXTURE_CUBE, - HLSL_TEXTURE_2D_ARRAY, - HLSL_TEXTURE_3D, - HLSL_TEXTURE_2D_UNORM, - HLSL_TEXTURE_CUBE_UNORM, - HLSL_TEXTURE_2D_ARRAY_UNORN, - HLSL_TEXTURE_3D_UNORM, - HLSL_TEXTURE_2D_SNORM, - HLSL_TEXTURE_CUBE_SNORM, - HLSL_TEXTURE_2D_ARRAY_SNORM, - HLSL_TEXTURE_3D_SNORM, - HLSL_TEXTURE_2D_MS, - HLSL_TEXTURE_2D_INT4, - HLSL_TEXTURE_3D_INT4, - HLSL_TEXTURE_2D_ARRAY_INT4, - HLSL_TEXTURE_2D_MS_INT4, - HLSL_TEXTURE_2D_UINT4, - HLSL_TEXTURE_3D_UINT4, - HLSL_TEXTURE_2D_ARRAY_UINT4, - HLSL_TEXTURE_2D_MS_UINT4, - - // Comparison samplers - - HLSL_TEXTURE_2D_COMPARISON, - HLSL_TEXTURE_CUBE_COMPARISON, - HLSL_TEXTURE_2D_ARRAY_COMPARISON, - - HLSL_COMPARISON_SAMPLER_GROUP_BEGIN = HLSL_TEXTURE_2D_COMPARISON, - HLSL_COMPARISON_SAMPLER_GROUP_END = HLSL_TEXTURE_2D_ARRAY_COMPARISON, - - HLSL_TEXTURE_UNKNOWN, - HLSL_TEXTURE_MAX = HLSL_TEXTURE_UNKNOWN -}; - -// HLSL RWTexture type for GLSL read and write image type. -enum HLSLRWTextureGroup -{ - // read/write resource - HLSL_RWTEXTURE_2D_FLOAT4, - HLSL_RWTEXTURE_MIN = HLSL_RWTEXTURE_2D_FLOAT4, - HLSL_RWTEXTURE_2D_ARRAY_FLOAT4, - HLSL_RWTEXTURE_3D_FLOAT4, - HLSL_RWTEXTURE_2D_UNORM, - HLSL_RWTEXTURE_2D_ARRAY_UNORN, - HLSL_RWTEXTURE_3D_UNORM, - HLSL_RWTEXTURE_2D_SNORM, - HLSL_RWTEXTURE_2D_ARRAY_SNORM, - HLSL_RWTEXTURE_3D_SNORM, - HLSL_RWTEXTURE_2D_UINT4, - HLSL_RWTEXTURE_2D_ARRAY_UINT4, - HLSL_RWTEXTURE_3D_UINT4, - HLSL_RWTEXTURE_2D_INT4, - HLSL_RWTEXTURE_2D_ARRAY_INT4, - HLSL_RWTEXTURE_3D_INT4, - - HLSL_RWTEXTURE_UNKNOWN, - HLSL_RWTEXTURE_MAX = HLSL_RWTEXTURE_UNKNOWN -}; - -HLSLTextureGroup TextureGroup(const TBasicType type, - TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified); -TString TextureString(const HLSLTextureGroup textureGroup); -TString TextureString(const TBasicType type, - TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified); -TString TextureGroupSuffix(const HLSLTextureGroup type); -TString TextureGroupSuffix(const TBasicType type, - TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified); -TString TextureTypeSuffix(const TBasicType type, - TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified); -HLSLRWTextureGroup RWTextureGroup(const TBasicType type, - TLayoutImageInternalFormat imageInternalFormat); -TString RWTextureString(const HLSLRWTextureGroup textureGroup); -TString RWTextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat); -TString RWTextureGroupSuffix(const HLSLRWTextureGroup type); -TString RWTextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat); -TString RWTextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat); - -TString SamplerString(const TBasicType type); -TString SamplerString(HLSLTextureGroup type); - -// Adds a prefix to user-defined names to avoid naming clashes. -TString Decorate(const TString &string); -TString DecorateVariableIfNeeded(const TName &name); -TString DecorateFunctionIfNeeded(const TName &name); -TString DecorateField(const TString &string, const TStructure &structure); -TString DecoratePrivate(const TString &privateText); -TString TypeString(const TType &type); -TString StructNameString(const TStructure &structure); -TString QualifiedStructNameString(const TStructure &structure, - bool useHLSLRowMajorPacking, - bool useStd140Packing); -TString InterpolationString(TQualifier qualifier); -TString QualifierString(TQualifier qualifier); -// Parameters may need to be included in function names to disambiguate between overloaded -// functions. -TString DisambiguateFunctionName(const TIntermSequence *parameters); -} - -#endif // COMPILER_TRANSLATOR_UTILSHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp deleted file mode 100644 index 492972b60d..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/ValidateGlobalInitializer.h" - -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/ParseContext.h" - -namespace sh -{ - -namespace -{ - -class ValidateGlobalInitializerTraverser : public TIntermTraverser -{ - public: - ValidateGlobalInitializerTraverser(const TParseContext *context); - - void visitSymbol(TIntermSymbol *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitUnary(Visit visit, TIntermUnary *node) override; - - bool isValid() const { return mIsValid; } - bool issueWarning() const { return mIssueWarning; } - - private: - const TParseContext *mContext; - bool mIsValid; - bool mIssueWarning; -}; - -void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node) -{ - const TSymbol *sym = - mContext->symbolTable.find(node->getSymbol(), mContext->getShaderVersion()); - if (sym->isVariable()) - { - // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3): - // Global initializers must be constant expressions. - const TVariable *var = static_cast<const TVariable *>(sym); - switch (var->getType().getQualifier()) - { - case EvqConst: - break; - case EvqGlobal: - case EvqTemporary: - case EvqUniform: - // We allow these cases to be compatible with legacy ESSL 1.00 content. - // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal - // with. - if (mContext->getShaderVersion() >= 300) - { - mIsValid = false; - } - else - { - mIssueWarning = true; - } - break; - default: - mIsValid = false; - } - } -} - -bool ValidateGlobalInitializerTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - // Disallow calls to user-defined functions and texture lookup functions in global variable - // initializers. - // This is done simply by disabling all function calls - built-in math functions don't use - // the function call ops. - if (node->isFunctionCall()) - { - mIsValid = false; - } - return true; -} - -bool ValidateGlobalInitializerTraverser::visitBinary(Visit visit, TIntermBinary *node) -{ - if (node->isAssignment()) - { - mIsValid = false; - } - return true; -} - -bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *node) -{ - if (node->isAssignment()) - { - mIsValid = false; - } - return true; -} - -ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(const TParseContext *context) - : TIntermTraverser(true, false, false), mContext(context), mIsValid(true), mIssueWarning(false) -{ -} - -} // namespace - -bool ValidateGlobalInitializer(TIntermTyped *initializer, - const TParseContext *context, - bool *warning) -{ - ValidateGlobalInitializerTraverser validate(context); - initializer->traverse(&validate); - ASSERT(warning != nullptr); - *warning = validate.issueWarning(); - return validate.isValid(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h b/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h deleted file mode 100644 index 2e7570667a..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ -#define COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ - -namespace sh -{ - -class TIntermTyped; -class TParseContext; - -// Returns true if the initializer is valid. -bool ValidateGlobalInitializer(TIntermTyped *initializer, - const TParseContext *context, - bool *warning); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp deleted file mode 100644 index 941f79ae51..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp +++ /dev/null @@ -1,444 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/ValidateLimitations.h" - -#include "angle_gl.h" -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/ParseContext.h" - -namespace sh -{ - -namespace -{ - -int GetLoopSymbolId(TIntermLoop *loop) -{ - // Here we assume all the operations are valid, because the loop node is - // already validated before this call. - TIntermSequence *declSeq = loop->getInit()->getAsDeclarationNode()->getSequence(); - TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); - TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); - - return symbol->getId(); -} - -// Traverses a node to check if it represents a constant index expression. -// Definition: -// constant-index-expressions are a superset of constant-expressions. -// Constant-index-expressions can include loop indices as defined in -// GLSL ES 1.0 spec, Appendix A, section 4. -// The following are constant-index-expressions: -// - Constant expressions -// - Loop indices as defined in section 4 -// - Expressions composed of both of the above -class ValidateConstIndexExpr : public TIntermTraverser -{ - public: - ValidateConstIndexExpr(const std::vector<int> &loopSymbols) - : TIntermTraverser(true, false, false), mValid(true), mLoopSymbolIds(loopSymbols) - { - } - - // Returns true if the parsed node represents a constant index expression. - bool isValid() const { return mValid; } - - void visitSymbol(TIntermSymbol *symbol) override - { - // Only constants and loop indices are allowed in a - // constant index expression. - if (mValid) - { - bool isLoopSymbol = std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(), - symbol->getId()) != mLoopSymbolIds.end(); - mValid = (symbol->getQualifier() == EvqConst) || isLoopSymbol; - } - } - - private: - bool mValid; - const std::vector<int> mLoopSymbolIds; -}; - -// Traverses intermediate tree to ensure that the shader does not exceed the -// minimum functionality mandated in GLSL 1.0 spec, Appendix A. -class ValidateLimitationsTraverser : public TLValueTrackingTraverser -{ - public: - ValidateLimitationsTraverser(sh::GLenum shaderType, - TSymbolTable *symbolTable, - int shaderVersion, - TDiagnostics *diagnostics); - - void visitSymbol(TIntermSymbol *node) override; - bool visitBinary(Visit, TIntermBinary *) override; - bool visitLoop(Visit, TIntermLoop *) override; - - private: - void error(TSourceLoc loc, const char *reason, const char *token); - - bool withinLoopBody() const; - bool isLoopIndex(TIntermSymbol *symbol); - bool validateLoopType(TIntermLoop *node); - - bool validateForLoopHeader(TIntermLoop *node); - // If valid, return the index symbol id; Otherwise, return -1. - int validateForLoopInit(TIntermLoop *node); - bool validateForLoopCond(TIntermLoop *node, int indexSymbolId); - bool validateForLoopExpr(TIntermLoop *node, int indexSymbolId); - - // Returns true if indexing does not exceed the minimum functionality - // mandated in GLSL 1.0 spec, Appendix A, Section 5. - bool isConstExpr(TIntermNode *node); - bool isConstIndexExpr(TIntermNode *node); - bool validateIndexing(TIntermBinary *node); - - sh::GLenum mShaderType; - TDiagnostics *mDiagnostics; - std::vector<int> mLoopSymbolIds; -}; - -ValidateLimitationsTraverser::ValidateLimitationsTraverser(sh::GLenum shaderType, - TSymbolTable *symbolTable, - int shaderVersion, - TDiagnostics *diagnostics) - : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion), - mShaderType(shaderType), - mDiagnostics(diagnostics) -{ - ASSERT(diagnostics); -} - -void ValidateLimitationsTraverser::visitSymbol(TIntermSymbol *node) -{ - if (isLoopIndex(node) && isLValueRequiredHere()) - { - error(node->getLine(), - "Loop index cannot be statically assigned to within the body of the loop", - node->getSymbol().c_str()); - } -} - -bool ValidateLimitationsTraverser::visitBinary(Visit, TIntermBinary *node) -{ - // Check indexing. - switch (node->getOp()) - { - case EOpIndexDirect: - case EOpIndexIndirect: - validateIndexing(node); - break; - default: - break; - } - return true; -} - -bool ValidateLimitationsTraverser::visitLoop(Visit, TIntermLoop *node) -{ - if (!validateLoopType(node)) - return false; - - if (!validateForLoopHeader(node)) - return false; - - TIntermNode *body = node->getBody(); - if (body != nullptr) - { - mLoopSymbolIds.push_back(GetLoopSymbolId(node)); - body->traverse(this); - mLoopSymbolIds.pop_back(); - } - - // The loop is fully processed - no need to visit children. - return false; -} - -void ValidateLimitationsTraverser::error(TSourceLoc loc, const char *reason, const char *token) -{ - mDiagnostics->error(loc, reason, token); -} - -bool ValidateLimitationsTraverser::withinLoopBody() const -{ - return !mLoopSymbolIds.empty(); -} - -bool ValidateLimitationsTraverser::isLoopIndex(TIntermSymbol *symbol) -{ - return std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(), symbol->getId()) != - mLoopSymbolIds.end(); -} - -bool ValidateLimitationsTraverser::validateLoopType(TIntermLoop *node) -{ - TLoopType type = node->getType(); - if (type == ELoopFor) - return true; - - // Reject while and do-while loops. - error(node->getLine(), "This type of loop is not allowed", type == ELoopWhile ? "while" : "do"); - return false; -} - -bool ValidateLimitationsTraverser::validateForLoopHeader(TIntermLoop *node) -{ - ASSERT(node->getType() == ELoopFor); - - // - // The for statement has the form: - // for ( init-declaration ; condition ; expression ) statement - // - int indexSymbolId = validateForLoopInit(node); - if (indexSymbolId < 0) - return false; - if (!validateForLoopCond(node, indexSymbolId)) - return false; - if (!validateForLoopExpr(node, indexSymbolId)) - return false; - - return true; -} - -int ValidateLimitationsTraverser::validateForLoopInit(TIntermLoop *node) -{ - TIntermNode *init = node->getInit(); - if (init == nullptr) - { - error(node->getLine(), "Missing init declaration", "for"); - return -1; - } - - // - // init-declaration has the form: - // type-specifier identifier = constant-expression - // - TIntermDeclaration *decl = init->getAsDeclarationNode(); - if (decl == nullptr) - { - error(init->getLine(), "Invalid init declaration", "for"); - return -1; - } - // To keep things simple do not allow declaration list. - TIntermSequence *declSeq = decl->getSequence(); - if (declSeq->size() != 1) - { - error(decl->getLine(), "Invalid init declaration", "for"); - return -1; - } - TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); - if ((declInit == nullptr) || (declInit->getOp() != EOpInitialize)) - { - error(decl->getLine(), "Invalid init declaration", "for"); - return -1; - } - TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); - if (symbol == nullptr) - { - error(declInit->getLine(), "Invalid init declaration", "for"); - return -1; - } - // The loop index has type int or float. - TBasicType type = symbol->getBasicType(); - if ((type != EbtInt) && (type != EbtUInt) && (type != EbtFloat)) - { - error(symbol->getLine(), "Invalid type for loop index", getBasicString(type)); - return -1; - } - // The loop index is initialized with constant expression. - if (!isConstExpr(declInit->getRight())) - { - error(declInit->getLine(), "Loop index cannot be initialized with non-constant expression", - symbol->getSymbol().c_str()); - return -1; - } - - return symbol->getId(); -} - -bool ValidateLimitationsTraverser::validateForLoopCond(TIntermLoop *node, int indexSymbolId) -{ - TIntermNode *cond = node->getCondition(); - if (cond == nullptr) - { - error(node->getLine(), "Missing condition", "for"); - return false; - } - // - // condition has the form: - // loop_index relational_operator constant_expression - // - TIntermBinary *binOp = cond->getAsBinaryNode(); - if (binOp == nullptr) - { - error(node->getLine(), "Invalid condition", "for"); - return false; - } - // Loop index should be to the left of relational operator. - TIntermSymbol *symbol = binOp->getLeft()->getAsSymbolNode(); - if (symbol == nullptr) - { - error(binOp->getLine(), "Invalid condition", "for"); - return false; - } - if (symbol->getId() != indexSymbolId) - { - error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str()); - return false; - } - // Relational operator is one of: > >= < <= == or !=. - switch (binOp->getOp()) - { - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - break; - default: - error(binOp->getLine(), "Invalid relational operator", - GetOperatorString(binOp->getOp())); - break; - } - // Loop index must be compared with a constant. - if (!isConstExpr(binOp->getRight())) - { - error(binOp->getLine(), "Loop index cannot be compared with non-constant expression", - symbol->getSymbol().c_str()); - return false; - } - - return true; -} - -bool ValidateLimitationsTraverser::validateForLoopExpr(TIntermLoop *node, int indexSymbolId) -{ - TIntermNode *expr = node->getExpression(); - if (expr == nullptr) - { - error(node->getLine(), "Missing expression", "for"); - return false; - } - - // for expression has one of the following forms: - // loop_index++ - // loop_index-- - // loop_index += constant_expression - // loop_index -= constant_expression - // ++loop_index - // --loop_index - // The last two forms are not specified in the spec, but I am assuming - // its an oversight. - TIntermUnary *unOp = expr->getAsUnaryNode(); - TIntermBinary *binOp = unOp ? nullptr : expr->getAsBinaryNode(); - - TOperator op = EOpNull; - TIntermSymbol *symbol = nullptr; - if (unOp != nullptr) - { - op = unOp->getOp(); - symbol = unOp->getOperand()->getAsSymbolNode(); - } - else if (binOp != nullptr) - { - op = binOp->getOp(); - symbol = binOp->getLeft()->getAsSymbolNode(); - } - - // The operand must be loop index. - if (symbol == nullptr) - { - error(expr->getLine(), "Invalid expression", "for"); - return false; - } - if (symbol->getId() != indexSymbolId) - { - error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str()); - return false; - } - - // The operator is one of: ++ -- += -=. - switch (op) - { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - ASSERT((unOp != nullptr) && (binOp == nullptr)); - break; - case EOpAddAssign: - case EOpSubAssign: - ASSERT((unOp == nullptr) && (binOp != nullptr)); - break; - default: - error(expr->getLine(), "Invalid operator", GetOperatorString(op)); - return false; - } - - // Loop index must be incremented/decremented with a constant. - if (binOp != nullptr) - { - if (!isConstExpr(binOp->getRight())) - { - error(binOp->getLine(), "Loop index cannot be modified by non-constant expression", - symbol->getSymbol().c_str()); - return false; - } - } - - return true; -} - -bool ValidateLimitationsTraverser::isConstExpr(TIntermNode *node) -{ - ASSERT(node != nullptr); - return node->getAsConstantUnion() != nullptr && node->getAsTyped()->getQualifier() == EvqConst; -} - -bool ValidateLimitationsTraverser::isConstIndexExpr(TIntermNode *node) -{ - ASSERT(node != nullptr); - - ValidateConstIndexExpr validate(mLoopSymbolIds); - node->traverse(&validate); - return validate.isValid(); -} - -bool ValidateLimitationsTraverser::validateIndexing(TIntermBinary *node) -{ - ASSERT((node->getOp() == EOpIndexDirect) || (node->getOp() == EOpIndexIndirect)); - - bool valid = true; - TIntermTyped *index = node->getRight(); - // The index expession must be a constant-index-expression unless - // the operand is a uniform in a vertex shader. - TIntermTyped *operand = node->getLeft(); - bool skip = (mShaderType == GL_VERTEX_SHADER) && (operand->getQualifier() == EvqUniform); - if (!skip && !isConstIndexExpr(index)) - { - error(index->getLine(), "Index expression must be constant", "[]"); - valid = false; - } - return valid; -} - -} // namespace anonymous - -bool ValidateLimitations(TIntermNode *root, - GLenum shaderType, - TSymbolTable *symbolTable, - int shaderVersion, - TDiagnostics *diagnostics) -{ - ValidateLimitationsTraverser validate(shaderType, symbolTable, shaderVersion, diagnostics); - root->traverse(&validate); - return diagnostics->numErrors() == 0; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h deleted file mode 100644 index 9149b8c216..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ -#define COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -class TDiagnostics; - -// Returns true if the given shader does not exceed the minimum functionality mandated in GLSL ES -// 1.00 spec Appendix A. -bool ValidateLimitations(TIntermNode *root, - GLenum shaderType, - TSymbolTable *symbolTable, - int shaderVersion, - TDiagnostics *diagnostics); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp deleted file mode 100644 index 9dccbf413f..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ValidateMaxParameters checks if function definitions have more than a set number of parameters. - -#include "compiler/translator/ValidateMaxParameters.h" - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -bool ValidateMaxParameters(TIntermBlock *root, unsigned int maxParameters) -{ - for (TIntermNode *node : *root->getSequence()) - { - TIntermFunctionDefinition *definition = node->getAsFunctionDefinition(); - if (definition != nullptr && - definition->getFunctionPrototype()->getSequence()->size() > maxParameters) - { - return false; - } - } - return true; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h b/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h deleted file mode 100644 index dec7597da4..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ValidateMaxParameters checks if function definitions have more than a set number of parameters. - -#ifndef COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_ -#define COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_ - -namespace sh -{ - -class TIntermBlock; - -// Return true if valid. -bool ValidateMaxParameters(TIntermBlock *root, unsigned int maxParameters); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp deleted file mode 100644 index 26f0e81ba7..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ValidateOutputs validates fragment shader outputs. It checks for conflicting locations, -// out-of-range locations, that locations are specified when using multiple outputs, and YUV output -// validity. - -#include "compiler/translator/ValidateOutputs.h" - -#include <set> - -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/ParseContext.h" - -namespace sh -{ - -namespace -{ -void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics) -{ - diagnostics->error(symbol.getLine(), reason, symbol.getSymbol().c_str()); -} - -class ValidateOutputsTraverser : public TIntermTraverser -{ - public: - ValidateOutputsTraverser(const TExtensionBehavior &extBehavior, int maxDrawBuffers); - - void validate(TDiagnostics *diagnostics) const; - - void visitSymbol(TIntermSymbol *) override; - - private: - int mMaxDrawBuffers; - bool mAllowUnspecifiedOutputLocationResolution; - bool mUsesFragDepth; - - typedef std::vector<TIntermSymbol *> OutputVector; - OutputVector mOutputs; - OutputVector mUnspecifiedLocationOutputs; - OutputVector mYuvOutputs; - std::set<std::string> mVisitedSymbols; -}; - -ValidateOutputsTraverser::ValidateOutputsTraverser(const TExtensionBehavior &extBehavior, - int maxDrawBuffers) - : TIntermTraverser(true, false, false), - mMaxDrawBuffers(maxDrawBuffers), - mAllowUnspecifiedOutputLocationResolution( - IsExtensionEnabled(extBehavior, TExtension::EXT_blend_func_extended)), - mUsesFragDepth(false) -{ -} - -void ValidateOutputsTraverser::visitSymbol(TIntermSymbol *symbol) -{ - TString name = symbol->getSymbol(); - TQualifier qualifier = symbol->getQualifier(); - - if (mVisitedSymbols.count(name.c_str()) == 1) - return; - - mVisitedSymbols.insert(name.c_str()); - - if (qualifier == EvqFragmentOut) - { - if (symbol->getType().getLayoutQualifier().location != -1) - { - mOutputs.push_back(symbol); - } - else if (symbol->getType().getLayoutQualifier().yuv == true) - { - mYuvOutputs.push_back(symbol); - } - else - { - mUnspecifiedLocationOutputs.push_back(symbol); - } - } - else if (qualifier == EvqFragDepth || qualifier == EvqFragDepthEXT) - { - mUsesFragDepth = true; - } -} - -void ValidateOutputsTraverser::validate(TDiagnostics *diagnostics) const -{ - ASSERT(diagnostics); - OutputVector validOutputs(mMaxDrawBuffers); - - for (const auto &symbol : mOutputs) - { - const TType &type = symbol->getType(); - ASSERT(!type.isArrayOfArrays()); // Disallowed in GLSL ES 3.10 section 4.3.6. - const size_t elementCount = - static_cast<size_t>(type.isArray() ? type.getOutermostArraySize() : 1u); - const size_t location = static_cast<size_t>(type.getLayoutQualifier().location); - - ASSERT(type.getLayoutQualifier().location != -1); - - if (location + elementCount <= validOutputs.size()) - { - for (size_t elementIndex = 0; elementIndex < elementCount; elementIndex++) - { - const size_t offsetLocation = location + elementIndex; - if (validOutputs[offsetLocation]) - { - std::stringstream strstr; - strstr << "conflicting output locations with previously defined output '" - << validOutputs[offsetLocation]->getSymbol() << "'"; - error(*symbol, strstr.str().c_str(), diagnostics); - } - else - { - validOutputs[offsetLocation] = symbol; - } - } - } - else - { - if (elementCount > 0) - { - error(*symbol, - elementCount > 1 ? "output array locations would exceed MAX_DRAW_BUFFERS" - : "output location must be < MAX_DRAW_BUFFERS", - diagnostics); - } - } - } - - if (!mAllowUnspecifiedOutputLocationResolution && - ((!mOutputs.empty() && !mUnspecifiedLocationOutputs.empty()) || - mUnspecifiedLocationOutputs.size() > 1)) - { - for (const auto &symbol : mUnspecifiedLocationOutputs) - { - error(*symbol, - "must explicitly specify all locations when using multiple fragment outputs", - diagnostics); - } - } - - if (!mYuvOutputs.empty() && (mYuvOutputs.size() > 1 || mUsesFragDepth || !mOutputs.empty() || - !mUnspecifiedLocationOutputs.empty())) - { - for (const auto &symbol : mYuvOutputs) - { - error(*symbol, - "not allowed to specify yuv qualifier when using depth or multiple color " - "fragment outputs", - diagnostics); - } - } -} - -} // anonymous namespace - -bool ValidateOutputs(TIntermBlock *root, - const TExtensionBehavior &extBehavior, - int maxDrawBuffers, - TDiagnostics *diagnostics) -{ - ValidateOutputsTraverser validateOutputs(extBehavior, maxDrawBuffers); - root->traverse(&validateOutputs); - int numErrorsBefore = diagnostics->numErrors(); - validateOutputs.validate(diagnostics); - return (diagnostics->numErrors() == numErrorsBefore); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h deleted file mode 100644 index e41ccd990c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ValidateOutputs validates fragment shader outputs. It checks for conflicting locations, -// out-of-range locations, that locations are specified when using multiple outputs, and YUV output -// validity. -// - -#ifndef COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ -#define COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ - -#include "compiler/translator/ExtensionBehavior.h" - -namespace sh -{ - -class TIntermBlock; -class TDiagnostics; - -// Returns true if the shader has no conflicting or otherwise erroneous fragment outputs. -bool ValidateOutputs(TIntermBlock *root, - const TExtensionBehavior &extBehavior, - int maxDrawBuffers, - TDiagnostics *diagnostics); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp deleted file mode 100644 index 9f7a264e58..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp +++ /dev/null @@ -1,319 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/ValidateSwitch.h" - -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class ValidateSwitch : public TIntermTraverser -{ - public: - static bool validate(TBasicType switchType, - int shaderVersion, - TDiagnostics *diagnostics, - TIntermBlock *statementList, - const TSourceLoc &loc); - - void visitSymbol(TIntermSymbol *) override; - void visitConstantUnion(TIntermConstantUnion *) override; - bool visitDeclaration(Visit, TIntermDeclaration *) override; - bool visitBlock(Visit, TIntermBlock *) override; - bool visitBinary(Visit, TIntermBinary *) override; - bool visitUnary(Visit, TIntermUnary *) override; - bool visitTernary(Visit, TIntermTernary *) override; - bool visitSwizzle(Visit, TIntermSwizzle *) override; - bool visitIfElse(Visit visit, TIntermIfElse *) override; - bool visitSwitch(Visit, TIntermSwitch *) override; - bool visitCase(Visit, TIntermCase *node) override; - bool visitAggregate(Visit, TIntermAggregate *) override; - bool visitLoop(Visit visit, TIntermLoop *) override; - bool visitBranch(Visit, TIntermBranch *) override; - - private: - ValidateSwitch(TBasicType switchType, int shaderVersion, TDiagnostics *context); - - bool validateInternal(const TSourceLoc &loc); - - TBasicType mSwitchType; - int mShaderVersion; - TDiagnostics *mDiagnostics; - bool mCaseTypeMismatch; - bool mFirstCaseFound; - bool mStatementBeforeCase; - bool mLastStatementWasCase; - int mControlFlowDepth; - bool mCaseInsideControlFlow; - int mDefaultCount; - std::set<int> mCasesSigned; - std::set<unsigned int> mCasesUnsigned; - bool mDuplicateCases; -}; - -bool ValidateSwitch::validate(TBasicType switchType, - int shaderVersion, - TDiagnostics *diagnostics, - TIntermBlock *statementList, - const TSourceLoc &loc) -{ - ValidateSwitch validate(switchType, shaderVersion, diagnostics); - ASSERT(statementList); - statementList->traverse(&validate); - return validate.validateInternal(loc); -} - -ValidateSwitch::ValidateSwitch(TBasicType switchType, int shaderVersion, TDiagnostics *diagnostics) - : TIntermTraverser(true, false, true), - mSwitchType(switchType), - mShaderVersion(shaderVersion), - mDiagnostics(diagnostics), - mCaseTypeMismatch(false), - mFirstCaseFound(false), - mStatementBeforeCase(false), - mLastStatementWasCase(false), - mControlFlowDepth(0), - mCaseInsideControlFlow(false), - mDefaultCount(0), - mDuplicateCases(false) -{ -} - -void ValidateSwitch::visitSymbol(TIntermSymbol *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; -} - -void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *) -{ - // Conditions of case labels are not traversed, so this is some other constant - // Could be just a statement like "0;" - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; -} - -bool ValidateSwitch::visitDeclaration(Visit, TIntermDeclaration *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitBlock(Visit, TIntermBlock *) -{ - if (getParentNode() != nullptr) - { - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - } - return true; -} - -bool ValidateSwitch::visitBinary(Visit, TIntermBinary *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitUnary(Visit, TIntermUnary *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitTernary(Visit, TIntermTernary *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitSwizzle(Visit, TIntermSwizzle *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitIfElse(Visit visit, TIntermIfElse *) -{ - if (visit == PreVisit) - ++mControlFlowDepth; - if (visit == PostVisit) - --mControlFlowDepth; - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitSwitch(Visit, TIntermSwitch *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - // Don't go into nested switch statements - return false; -} - -bool ValidateSwitch::visitCase(Visit, TIntermCase *node) -{ - const char *nodeStr = node->hasCondition() ? "case" : "default"; - if (mControlFlowDepth > 0) - { - mDiagnostics->error(node->getLine(), "label statement nested inside control flow", nodeStr); - mCaseInsideControlFlow = true; - } - mFirstCaseFound = true; - mLastStatementWasCase = true; - if (!node->hasCondition()) - { - ++mDefaultCount; - if (mDefaultCount > 1) - { - mDiagnostics->error(node->getLine(), "duplicate default label", nodeStr); - } - } - else - { - TIntermConstantUnion *condition = node->getCondition()->getAsConstantUnion(); - if (condition == nullptr) - { - // This can happen in error cases. - return false; - } - TBasicType conditionType = condition->getBasicType(); - if (conditionType != mSwitchType) - { - mDiagnostics->error(condition->getLine(), - "case label type does not match switch init-expression type", - nodeStr); - mCaseTypeMismatch = true; - } - - if (conditionType == EbtInt) - { - int iConst = condition->getIConst(0); - if (mCasesSigned.find(iConst) != mCasesSigned.end()) - { - mDiagnostics->error(condition->getLine(), "duplicate case label", nodeStr); - mDuplicateCases = true; - } - else - { - mCasesSigned.insert(iConst); - } - } - else if (conditionType == EbtUInt) - { - unsigned int uConst = condition->getUConst(0); - if (mCasesUnsigned.find(uConst) != mCasesUnsigned.end()) - { - mDiagnostics->error(condition->getLine(), "duplicate case label", nodeStr); - mDuplicateCases = true; - } - else - { - mCasesUnsigned.insert(uConst); - } - } - // Other types are possible only in error cases, where the error has already been generated - // when parsing the case statement. - } - // Don't traverse the condition of the case statement - return false; -} - -bool ValidateSwitch::visitAggregate(Visit visit, TIntermAggregate *) -{ - if (getParentNode() != nullptr) - { - // This is not the statementList node, but some other node. - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - } - return true; -} - -bool ValidateSwitch::visitLoop(Visit visit, TIntermLoop *) -{ - if (visit == PreVisit) - ++mControlFlowDepth; - if (visit == PostVisit) - --mControlFlowDepth; - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitBranch(Visit, TIntermBranch *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::validateInternal(const TSourceLoc &loc) -{ - if (mStatementBeforeCase) - { - mDiagnostics->error(loc, "statement before the first label", "switch"); - } - bool lastStatementWasCaseError = false; - if (mLastStatementWasCase) - { - if (mShaderVersion == 300) - { - lastStatementWasCaseError = true; - // This error has been proposed to be made optional in GLSL ES 3.00, but dEQP tests - // still require it. - mDiagnostics->error( - loc, "no statement between the last label and the end of the switch statement", - "switch"); - } - else - { - // The error has been removed from GLSL ES 3.10. - mDiagnostics->warning( - loc, "no statement between the last label and the end of the switch statement", - "switch"); - } - } - return !mStatementBeforeCase && !lastStatementWasCaseError && !mCaseInsideControlFlow && - !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases; -} - -} // anonymous namespace - -bool ValidateSwitchStatementList(TBasicType switchType, - int shaderVersion, - TDiagnostics *diagnostics, - TIntermBlock *statementList, - const TSourceLoc &loc) -{ - return ValidateSwitch::validate(switchType, shaderVersion, diagnostics, statementList, loc); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h deleted file mode 100644 index 2d2dd70f78..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_VALIDATESWITCH_H_ -#define COMPILER_TRANSLATOR_VALIDATESWITCH_H_ - -#include "compiler/translator/BaseTypes.h" -#include "compiler/translator/Common.h" - -namespace sh -{ -class TDiagnostics; -class TIntermBlock; - -// Check for errors and output error messages on the context. -// Returns true if there are no errors. -bool ValidateSwitchStatementList(TBasicType switchType, - int shaderVersion, - TDiagnostics *diagnostics, - TIntermBlock *statementList, - const TSourceLoc &loc); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VALIDATESWITCH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp deleted file mode 100644 index 9c36fcea78..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// -// Copyright (c) 2002-2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The ValidateVaryingLocations function checks if there exists location conflicts on shader -// varyings. -// - -#include "ValidateVaryingLocations.h" - -#include "compiler/translator/Diagnostics.h" -#include "compiler/translator/IntermTraverse.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics) -{ - diagnostics->error(symbol.getLine(), reason, symbol.getSymbol().c_str()); -} - -int GetLocationCount(const TIntermSymbol *varying, bool ignoreVaryingArraySize) -{ - const auto &varyingType = varying->getType(); - if (varyingType.getStruct() != nullptr) - { - ASSERT(!varyingType.isArray()); - int totalLocation = 0; - for (const auto *field : varyingType.getStruct()->fields()) - { - const auto *fieldType = field->type(); - ASSERT(fieldType->getStruct() == nullptr && !fieldType->isArray()); - - totalLocation += fieldType->getSecondarySize(); - } - return totalLocation; - } - // [GL_OES_shader_io_blocks SPEC Chapter 4.4.1] - // Geometry shader inputs, tessellation control shader inputs and outputs, and tessellation - // evaluation inputs all have an additional level of arrayness relative to other shader inputs - // and outputs. This outer array level is removed from the type before considering how many - // locations the type consumes. - else if (ignoreVaryingArraySize) - { - // Array-of-arrays cannot be inputs or outputs of a geometry shader. - // (GL_OES_geometry_shader SPEC issues(5)) - ASSERT(!varyingType.isArrayOfArrays()); - return varyingType.getSecondarySize(); - } - else - { - return varyingType.getSecondarySize() * static_cast<int>(varyingType.getArraySizeProduct()); - } -} - -using VaryingVector = std::vector<const TIntermSymbol *>; - -void ValidateShaderInterface(TDiagnostics *diagnostics, - VaryingVector &varyingVector, - bool ignoreVaryingArraySize) -{ - // Location conflicts can only happen when there are two or more varyings in varyingVector. - if (varyingVector.size() <= 1) - { - return; - } - - std::map<int, const TIntermSymbol *> locationMap; - for (const TIntermSymbol *varying : varyingVector) - { - const int location = varying->getType().getLayoutQualifier().location; - ASSERT(location >= 0); - - const int elementCount = GetLocationCount(varying, ignoreVaryingArraySize); - for (int elementIndex = 0; elementIndex < elementCount; ++elementIndex) - { - const int offsetLocation = location + elementIndex; - if (locationMap.find(offsetLocation) != locationMap.end()) - { - std::stringstream strstr; - strstr << "'" << varying->getSymbol() - << "' conflicting location with previously defined '" - << locationMap[offsetLocation]->getSymbol() << "'"; - error(*varying, strstr.str().c_str(), diagnostics); - } - else - { - locationMap[offsetLocation] = varying; - } - } - } -} - -class ValidateVaryingLocationsTraverser : public TIntermTraverser -{ - public: - ValidateVaryingLocationsTraverser(GLenum shaderType); - void validate(TDiagnostics *diagnostics); - - private: - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; - - VaryingVector mInputVaryingsWithLocation; - VaryingVector mOutputVaryingsWithLocation; - GLenum mShaderType; -}; - -ValidateVaryingLocationsTraverser::ValidateVaryingLocationsTraverser(GLenum shaderType) - : TIntermTraverser(true, false, false), mShaderType(shaderType) -{ -} - -bool ValidateVaryingLocationsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - const TIntermSequence &sequence = *(node->getSequence()); - ASSERT(!sequence.empty()); - - const TIntermSymbol *symbol = sequence.front()->getAsSymbolNode(); - if (symbol == nullptr) - { - return false; - } - - // Collect varyings that have explicit 'location' qualifiers. - const TQualifier qualifier = symbol->getQualifier(); - if (symbol->getType().getLayoutQualifier().location != -1) - { - if (IsVaryingIn(qualifier)) - { - mInputVaryingsWithLocation.push_back(symbol); - } - else if (IsVaryingOut(qualifier)) - { - mOutputVaryingsWithLocation.push_back(symbol); - } - } - - return false; -} - -bool ValidateVaryingLocationsTraverser::visitFunctionDefinition(Visit visit, - TIntermFunctionDefinition *node) -{ - // We stop traversing function definitions because varyings cannot be defined in a function. - return false; -} - -void ValidateVaryingLocationsTraverser::validate(TDiagnostics *diagnostics) -{ - ASSERT(diagnostics); - - ValidateShaderInterface(diagnostics, mInputVaryingsWithLocation, - mShaderType == GL_GEOMETRY_SHADER_OES); - ValidateShaderInterface(diagnostics, mOutputVaryingsWithLocation, false); -} - -} // anonymous namespace - -bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType) -{ - ValidateVaryingLocationsTraverser varyingValidator(shaderType); - root->traverse(&varyingValidator); - int numErrorsBefore = diagnostics->numErrors(); - varyingValidator.validate(diagnostics); - return (diagnostics->numErrors() == numErrorsBefore); -} - -} // namespace sh
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h b/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h deleted file mode 100644 index 1e53977c68..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) 2002-2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The ValidateVaryingLocations function checks if there exists location conflicts on shader -// varyings. -// - -#ifndef COMPILER_TRANSLATOR_VALIDATEVARYINGLOCATIONS_H_ -#define COMPILER_TRANSLATOR_VALIDATEVARYINGLOCATIONS_H_ - -#include "GLSLANG/ShaderVars.h" - -namespace sh -{ - -class TIntermBlock; -class TDiagnostics; - -bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType); - -} // namespace sh - -#endif
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp deleted file mode 100644 index 6dd396ff02..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp +++ /dev/null @@ -1,413 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Check whether variables fit within packing limits according to the packing rules from the GLSL ES -// 1.00.17 spec, Appendix A, section 7. - -#include <algorithm> - -#include "angle_gl.h" - -#include "compiler/translator/VariablePacker.h" -#include "common/utilities.h" - -namespace sh -{ - -namespace -{ - -// Expand the variable so that struct variables are split into their individual fields. -// Will not set the mappedName or staticUse fields on the expanded variables. -void ExpandVariable(const ShaderVariable &variable, - const std::string &name, - std::vector<ShaderVariable> *expanded); - -void ExpandStructVariable(const ShaderVariable &variable, - const std::string &name, - std::vector<ShaderVariable> *expanded) -{ - ASSERT(variable.isStruct()); - - const std::vector<ShaderVariable> &fields = variable.fields; - - for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) - { - const ShaderVariable &field = fields[fieldIndex]; - ExpandVariable(field, name + "." + field.name, expanded); - } -} - -void ExpandStructArrayVariable(const ShaderVariable &variable, - unsigned int arrayNestingIndex, - const std::string &name, - std::vector<ShaderVariable> *expanded) -{ - // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the - // innermost. - const unsigned int currentArraySize = variable.getNestedArraySize(arrayNestingIndex); - for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement) - { - const std::string elementName = name + ArrayString(arrayElement); - if (arrayNestingIndex + 1u < variable.arraySizes.size()) - { - ExpandStructArrayVariable(variable, arrayNestingIndex + 1u, elementName, expanded); - } - else - { - ExpandStructVariable(variable, elementName, expanded); - } - } -} - -void ExpandVariable(const ShaderVariable &variable, - const std::string &name, - std::vector<ShaderVariable> *expanded) -{ - if (variable.isStruct()) - { - if (variable.isArray()) - { - ExpandStructArrayVariable(variable, 0u, name, expanded); - } - else - { - ExpandStructVariable(variable, name, expanded); - } - } - else - { - ShaderVariable expandedVar = variable; - expandedVar.name = name; - - expanded->push_back(expandedVar); - } -} - -int GetVariablePackingRows(const ShaderVariable &variable) -{ - return GetTypePackingRows(variable.type) * variable.getArraySizeProduct(); -} - -class VariablePacker -{ - public: - bool checkExpandedVariablesWithinPackingLimits(unsigned int maxVectors, - std::vector<sh::ShaderVariable> *variables); - - private: - static const int kNumColumns = 4; - static const unsigned kColumnMask = (1 << kNumColumns) - 1; - - unsigned makeColumnFlags(int column, int numComponentsPerRow); - void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow); - bool searchColumn(int column, int numRows, int *destRow, int *destSize); - - int topNonFullRow_; - int bottomNonFullRow_; - int maxRows_; - std::vector<unsigned> rows_; -}; - -struct TVariableInfoComparer -{ - bool operator()(const sh::ShaderVariable &lhs, const sh::ShaderVariable &rhs) const - { - int lhsSortOrder = gl::VariableSortOrder(lhs.type); - int rhsSortOrder = gl::VariableSortOrder(rhs.type); - if (lhsSortOrder != rhsSortOrder) - { - return lhsSortOrder < rhsSortOrder; - } - // Sort by largest first. - return lhs.getArraySizeProduct() > rhs.getArraySizeProduct(); - } -}; - -unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow) -{ - return ((kColumnMask << (kNumColumns - numComponentsPerRow)) & kColumnMask) >> column; -} - -void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow) -{ - unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow); - for (int r = 0; r < numRows; ++r) - { - int row = topRow + r; - ASSERT((rows_[row] & columnFlags) == 0); - rows_[row] |= columnFlags; - } -} - -bool VariablePacker::searchColumn(int column, int numRows, int *destRow, int *destSize) -{ - ASSERT(destRow); - - for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask; ++topNonFullRow_) - { - } - - for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask; --bottomNonFullRow_) - { - } - - if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) - { - return false; - } - - unsigned columnFlags = makeColumnFlags(column, 1); - int topGoodRow = 0; - int smallestGoodTop = -1; - int smallestGoodSize = maxRows_ + 1; - int bottomRow = bottomNonFullRow_ + 1; - bool found = false; - for (int row = topNonFullRow_; row <= bottomRow; ++row) - { - bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false; - if (rowEmpty) - { - if (!found) - { - topGoodRow = row; - found = true; - } - } - else - { - if (found) - { - int size = row - topGoodRow; - if (size >= numRows && size < smallestGoodSize) - { - smallestGoodSize = size; - smallestGoodTop = topGoodRow; - } - } - found = false; - } - } - if (smallestGoodTop < 0) - { - return false; - } - - *destRow = smallestGoodTop; - if (destSize) - { - *destSize = smallestGoodSize; - } - return true; -} - -bool VariablePacker::checkExpandedVariablesWithinPackingLimits( - unsigned int maxVectors, - std::vector<sh::ShaderVariable> *variables) -{ - ASSERT(maxVectors > 0); - maxRows_ = maxVectors; - topNonFullRow_ = 0; - bottomNonFullRow_ = maxRows_ - 1; - - // Check whether each variable fits in the available vectors. - for (const sh::ShaderVariable &variable : *variables) - { - // Structs should have been expanded before reaching here. - ASSERT(!variable.isStruct()); - if (variable.getArraySizeProduct() > maxVectors / GetTypePackingRows(variable.type)) - { - return false; - } - } - - // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific - // order by type, then by size of array, largest first. - std::sort(variables->begin(), variables->end(), TVariableInfoComparer()); - rows_.clear(); - rows_.resize(maxVectors, 0); - - // Packs the 4 column variables. - size_t ii = 0; - for (; ii < variables->size(); ++ii) - { - const sh::ShaderVariable &variable = (*variables)[ii]; - if (GetTypePackingComponentsPerRow(variable.type) != 4) - { - break; - } - topNonFullRow_ += GetVariablePackingRows(variable); - } - - if (topNonFullRow_ > maxRows_) - { - return false; - } - - // Packs the 3 column variables. - int num3ColumnRows = 0; - for (; ii < variables->size(); ++ii) - { - const sh::ShaderVariable &variable = (*variables)[ii]; - if (GetTypePackingComponentsPerRow(variable.type) != 3) - { - break; - } - num3ColumnRows += GetVariablePackingRows(variable); - } - - if (topNonFullRow_ + num3ColumnRows > maxRows_) - { - return false; - } - - fillColumns(topNonFullRow_, num3ColumnRows, 0, 3); - - // Packs the 2 column variables. - int top2ColumnRow = topNonFullRow_ + num3ColumnRows; - int twoColumnRowsAvailable = maxRows_ - top2ColumnRow; - int rowsAvailableInColumns01 = twoColumnRowsAvailable; - int rowsAvailableInColumns23 = twoColumnRowsAvailable; - for (; ii < variables->size(); ++ii) - { - const sh::ShaderVariable &variable = (*variables)[ii]; - if (GetTypePackingComponentsPerRow(variable.type) != 2) - { - break; - } - int numRows = GetVariablePackingRows(variable); - if (numRows <= rowsAvailableInColumns01) - { - rowsAvailableInColumns01 -= numRows; - } - else if (numRows <= rowsAvailableInColumns23) - { - rowsAvailableInColumns23 -= numRows; - } - else - { - return false; - } - } - - int numRowsUsedInColumns01 = twoColumnRowsAvailable - rowsAvailableInColumns01; - int numRowsUsedInColumns23 = twoColumnRowsAvailable - rowsAvailableInColumns23; - fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2); - fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23, 2, 2); - - // Packs the 1 column variables. - for (; ii < variables->size(); ++ii) - { - const sh::ShaderVariable &variable = (*variables)[ii]; - ASSERT(1 == GetTypePackingComponentsPerRow(variable.type)); - int numRows = GetVariablePackingRows(variable); - int smallestColumn = -1; - int smallestSize = maxRows_ + 1; - int topRow = -1; - for (int column = 0; column < kNumColumns; ++column) - { - int row = 0; - int size = 0; - if (searchColumn(column, numRows, &row, &size)) - { - if (size < smallestSize) - { - smallestSize = size; - smallestColumn = column; - topRow = row; - } - } - } - - if (smallestColumn < 0) - { - return false; - } - - fillColumns(topRow, numRows, smallestColumn, 1); - } - - ASSERT(variables->size() == ii); - - return true; -} - -} // anonymous namespace - -int GetTypePackingComponentsPerRow(sh::GLenum type) -{ - switch (type) - { - case GL_FLOAT_MAT4: - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x2: - case GL_FLOAT_MAT4x3: - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_BOOL_VEC4: - case GL_UNSIGNED_INT_VEC4: - return 4; - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT3x2: - case GL_FLOAT_VEC3: - case GL_INT_VEC3: - case GL_BOOL_VEC3: - case GL_UNSIGNED_INT_VEC3: - return 3; - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_BOOL_VEC2: - case GL_UNSIGNED_INT_VEC2: - return 2; - default: - ASSERT(gl::VariableComponentCount(type) == 1); - return 1; - } -} - -int GetTypePackingRows(sh::GLenum type) -{ - switch (type) - { - case GL_FLOAT_MAT4: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x3: - case GL_FLOAT_MAT4x2: - return 4; - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT3x2: - return 3; - case GL_FLOAT_MAT2: - return 2; - default: - ASSERT(gl::VariableRowCount(type) == 1); - return 1; - } -} - -template <typename T> -bool CheckVariablesInPackingLimits(unsigned int maxVectors, const std::vector<T> &variables) -{ - VariablePacker packer; - std::vector<sh::ShaderVariable> expandedVariables; - for (const ShaderVariable &variable : variables) - { - ExpandVariable(variable, variable.name, &expandedVariables); - } - return packer.checkExpandedVariablesWithinPackingLimits(maxVectors, &expandedVariables); -} - -template bool CheckVariablesInPackingLimits<ShaderVariable>( - unsigned int maxVectors, - const std::vector<ShaderVariable> &variables); -template bool CheckVariablesInPackingLimits<Uniform>(unsigned int maxVectors, - const std::vector<Uniform> &variables); - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h deleted file mode 100644 index 36b2104cd0..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Check whether variables fit within packing limits according to the packing rules from the GLSL ES -// 1.00.17 spec, Appendix A, section 7. - -#ifndef COMPILER_TRANSLATOR_VARIABLEPACKER_H_ -#define COMPILER_TRANSLATOR_VARIABLEPACKER_H_ - -#include <vector> - -#include <GLSLANG/ShaderLang.h> - -namespace sh -{ - -// Gets how many components in a row a data type takes. -int GetTypePackingComponentsPerRow(sh::GLenum type); - -// Gets how many rows a data type takes. -int GetTypePackingRows(sh::GLenum type); - -// Returns true if the passed in variables pack in maxVectors. -// T should be ShaderVariable or one of the subclasses of ShaderVariable. -template <typename T> -bool CheckVariablesInPackingLimits(unsigned int maxVectors, const std::vector<T> &variables); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VARIABLEPACKER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp b/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp deleted file mode 100644 index 1e79a60991..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// VectorizeVectorScalarArithmetic.cpp: Turn some arithmetic operations that operate on a float -// vector-scalar pair into vector-vector operations. This is done recursively. Some scalar binary -// operations inside vector constructors are also turned into vector operations. -// -// This is targeted to work around a bug in NVIDIA OpenGL drivers that was reproducible on NVIDIA -// driver version 387.92. It works around the most common occurrences of the bug. - -#include "compiler/translator/VectorizeVectorScalarArithmetic.h" - -#include <set> - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class VectorizeVectorScalarArithmeticTraverser : public TIntermTraverser -{ - public: - VectorizeVectorScalarArithmeticTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, false, symbolTable), mReplaced(false) - { - } - - bool didReplaceScalarsWithVectors() { return mReplaced; } - void nextIteration() - { - mReplaced = false; - mModifiedBlocks.clear(); - } - - protected: - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - - private: - // These helpers should only be called from visitAggregate when visiting a constructor. - // argBinary is the only argument of the constructor. - void replaceMathInsideConstructor(TIntermAggregate *node, TIntermBinary *argBinary); - void replaceAssignInsideConstructor(const TIntermAggregate *node, - const TIntermBinary *argBinary); - - static TIntermTyped *Vectorize(TIntermTyped *node, - TType vectorType, - TIntermTraverser::OriginalNode *originalNodeFate); - - bool mReplaced; - std::set<const TIntermBlock *> mModifiedBlocks; -}; - -TIntermTyped *VectorizeVectorScalarArithmeticTraverser::Vectorize( - TIntermTyped *node, - TType vectorType, - TIntermTraverser::OriginalNode *originalNodeFate) -{ - ASSERT(node->isScalar()); - vectorType.setQualifier(EvqTemporary); - TIntermSequence vectorConstructorArgs; - vectorConstructorArgs.push_back(node); - TIntermAggregate *vectorized = - TIntermAggregate::CreateConstructor(vectorType, &vectorConstructorArgs); - TIntermTyped *vectorizedFolded = vectorized->fold(nullptr); - if (originalNodeFate != nullptr) - { - if (vectorizedFolded != vectorized) - { - *originalNodeFate = OriginalNode::IS_DROPPED; - } - else - { - *originalNodeFate = OriginalNode::BECOMES_CHILD; - } - } - return vectorizedFolded; -} - -bool VectorizeVectorScalarArithmeticTraverser::visitBinary(Visit /*visit*/, TIntermBinary *node) -{ - TIntermTyped *left = node->getLeft(); - TIntermTyped *right = node->getRight(); - ASSERT(left); - ASSERT(right); - switch (node->getOp()) - { - case EOpAdd: - case EOpAddAssign: - // Only these specific ops are necessary to turn into vector ops. - break; - default: - return true; - } - if (node->getBasicType() != EbtFloat) - { - // Only float ops have reproduced the bug. - return true; - } - if (left->isScalar() && right->isVector()) - { - ASSERT(!node->isAssignment()); - ASSERT(!right->isArray()); - OriginalNode originalNodeFate; - TIntermTyped *leftVectorized = Vectorize(left, right->getType(), &originalNodeFate); - queueReplacementWithParent(node, left, leftVectorized, originalNodeFate); - mReplaced = true; - // Don't replace more nodes in the same subtree on this traversal. However, nodes elsewhere - // in the tree may still be replaced. - return false; - } - else if (left->isVector() && right->isScalar()) - { - OriginalNode originalNodeFate; - TIntermTyped *rightVectorized = Vectorize(right, left->getType(), &originalNodeFate); - queueReplacementWithParent(node, right, rightVectorized, originalNodeFate); - mReplaced = true; - // Don't replace more nodes in the same subtree on this traversal. However, nodes elsewhere - // in the tree may still be replaced. - return false; - } - return true; -} - -void VectorizeVectorScalarArithmeticTraverser::replaceMathInsideConstructor( - TIntermAggregate *node, - TIntermBinary *argBinary) -{ - // Turn: - // a * b - // into: - // gvec(a) * gvec(b) - - TIntermTyped *left = argBinary->getLeft(); - TIntermTyped *right = argBinary->getRight(); - ASSERT(left->isScalar() && right->isScalar()); - - TType leftVectorizedType = left->getType(); - leftVectorizedType.setPrimarySize(static_cast<unsigned char>(node->getType().getNominalSize())); - TIntermTyped *leftVectorized = Vectorize(left, leftVectorizedType, nullptr); - TType rightVectorizedType = right->getType(); - rightVectorizedType.setPrimarySize( - static_cast<unsigned char>(node->getType().getNominalSize())); - TIntermTyped *rightVectorized = Vectorize(right, rightVectorizedType, nullptr); - - TIntermBinary *newArg = new TIntermBinary(argBinary->getOp(), leftVectorized, rightVectorized); - queueReplacementWithParent(node, argBinary, newArg, OriginalNode::IS_DROPPED); -} - -void VectorizeVectorScalarArithmeticTraverser::replaceAssignInsideConstructor( - const TIntermAggregate *node, - const TIntermBinary *argBinary) -{ - // Turn: - // gvec(a *= b); - // into: - // // This is inserted into the parent block: - // gvec s0 = gvec(a); - // - // // This goes where the gvec constructor used to be: - // ((s0 *= b, a = s0.x), s0); - - TIntermTyped *left = argBinary->getLeft(); - TIntermTyped *right = argBinary->getRight(); - ASSERT(left->isScalar() && right->isScalar()); - ASSERT(!left->hasSideEffects()); - - TType vecType = node->getType(); - vecType.setQualifier(EvqTemporary); - - nextTemporaryId(); - // gvec s0 = gvec(a); - // s0 is called "tempAssignmentTarget" below. - TIntermTyped *tempAssignmentTargetInitializer = Vectorize(left->deepCopy(), vecType, nullptr); - TIntermDeclaration *tempAssignmentTargetDeclaration = - createTempInitDeclaration(tempAssignmentTargetInitializer); - - // s0 *= b - TOperator compoundAssignmentOp = argBinary->getOp(); - if (compoundAssignmentOp == EOpMulAssign) - { - compoundAssignmentOp = EOpVectorTimesScalarAssign; - } - TIntermBinary *replacementCompoundAssignment = - new TIntermBinary(compoundAssignmentOp, createTempSymbol(vecType), right->deepCopy()); - - // s0.x - TVector<int> swizzleXOffset; - swizzleXOffset.push_back(0); - TIntermSwizzle *tempAssignmentTargetX = - new TIntermSwizzle(createTempSymbol(vecType), swizzleXOffset); - // a = s0.x - TIntermBinary *replacementAssignBackToTarget = - new TIntermBinary(EOpAssign, left->deepCopy(), tempAssignmentTargetX); - - // s0 *= b, a = s0.x - TIntermBinary *replacementSequenceLeft = - new TIntermBinary(EOpComma, replacementCompoundAssignment, replacementAssignBackToTarget); - // (s0 *= b, a = s0.x), s0 - TIntermBinary *replacementSequence = - new TIntermBinary(EOpComma, replacementSequenceLeft, createTempSymbol(vecType)); - - insertStatementInParentBlock(tempAssignmentTargetDeclaration); - queueReplacement(replacementSequence, OriginalNode::IS_DROPPED); -} - -bool VectorizeVectorScalarArithmeticTraverser::visitAggregate(Visit /*visit*/, - TIntermAggregate *node) -{ - // Transform scalar binary expressions inside vector constructors. - if (!node->isConstructor() || !node->isVector() || node->getSequence()->size() != 1) - { - return true; - } - TIntermTyped *argument = node->getSequence()->back()->getAsTyped(); - ASSERT(argument); - if (!argument->isScalar() || argument->getBasicType() != EbtFloat) - { - return true; - } - TIntermBinary *argBinary = argument->getAsBinaryNode(); - if (!argBinary) - { - return true; - } - - // Only specific ops are necessary to change. - switch (argBinary->getOp()) - { - case EOpMul: - case EOpDiv: - { - replaceMathInsideConstructor(node, argBinary); - mReplaced = true; - // Don't replace more nodes in the same subtree on this traversal. However, nodes - // elsewhere in the tree may still be replaced. - return false; - } - case EOpMulAssign: - case EOpDivAssign: - { - // The case where the left side has side effects is too complicated to deal with, so we - // leave that be. - if (!argBinary->getLeft()->hasSideEffects()) - { - const TIntermBlock *parentBlock = getParentBlock(); - // We can't do more than one insertion to the same block on the same traversal. - if (mModifiedBlocks.find(parentBlock) == mModifiedBlocks.end()) - { - replaceAssignInsideConstructor(node, argBinary); - mModifiedBlocks.insert(parentBlock); - mReplaced = true; - // Don't replace more nodes in the same subtree on this traversal. - // However, nodes elsewhere in the tree may still be replaced. - return false; - } - } - break; - } - default: - return true; - } - return true; -} - -} // anonymous namespace - -void VectorizeVectorScalarArithmetic(TIntermBlock *root, TSymbolTable *symbolTable) -{ - VectorizeVectorScalarArithmeticTraverser traverser(symbolTable); - do - { - traverser.nextIteration(); - root->traverse(&traverser); - traverser.updateTree(); - } while (traverser.didReplaceScalarsWithVectors()); -} - -} // namespace sh
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h b/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h deleted file mode 100644 index 69f092e039..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// VectorizeVectorScalarArithmetic.h: Turn some arithmetic operations that operate on a float -// vector-scalar pair into vector-vector operations. This is done recursively. Some scalar binary -// operations inside vector constructors are also turned into vector operations. -// -// This is targeted to work around a bug in NVIDIA OpenGL drivers that was reproducible on NVIDIA -// driver version 387.92. It works around the most common occurrences of the bug. - -#ifndef COMPILER_TRANSLATOR_VECTORIZEVECTORSCALARARITHMETIC_H_ -#define COMPILER_TRANSLATOR_VECTORIZEVECTORSCALARARITHMETIC_H_ - -namespace sh -{ - -class TIntermBlock; -class TSymbolTable; - -void VectorizeVectorScalarArithmetic(TIntermBlock *root, TSymbolTable *symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VECTORIZEVECTORSCALARARITHMETIC_H_
\ No newline at end of file diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp deleted file mode 100644 index 81688765b8..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/VersionGLSL.h" - -#include "angle_gl.h" - -namespace sh -{ - -int ShaderOutputTypeToGLSLVersion(ShShaderOutput output) -{ - switch (output) - { - case SH_GLSL_130_OUTPUT: - return GLSL_VERSION_130; - case SH_GLSL_140_OUTPUT: - return GLSL_VERSION_140; - case SH_GLSL_150_CORE_OUTPUT: - return GLSL_VERSION_150; - case SH_GLSL_330_CORE_OUTPUT: - return GLSL_VERSION_330; - case SH_GLSL_400_CORE_OUTPUT: - return GLSL_VERSION_400; - case SH_GLSL_410_CORE_OUTPUT: - return GLSL_VERSION_410; - case SH_GLSL_420_CORE_OUTPUT: - return GLSL_VERSION_420; - case SH_GLSL_430_CORE_OUTPUT: - return GLSL_VERSION_430; - case SH_GLSL_440_CORE_OUTPUT: - return GLSL_VERSION_440; - case SH_GLSL_450_CORE_OUTPUT: - return GLSL_VERSION_450; - case SH_GLSL_COMPATIBILITY_OUTPUT: - return GLSL_VERSION_110; - default: - UNREACHABLE(); - return 0; - } -} - -// We need to scan for the following: -// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders -// but only at the global scope. -// 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader -// but inside any scope. -// 3. Call to a matrix constructor with another matrix as argument. -// (These constructors were reserved in GLSL version 1.10.) -// 4. Arrays as "out" function parameters. -// GLSL spec section 6.1.1: "When calling a function, expressions that do -// not evaluate to l-values cannot be passed to parameters declared as -// out or inout." -// GLSL 1.1 section 5.8: "Other binary or unary expressions, -// non-dereferenced arrays, function names, swizzles with repeated fields, -// and constants cannot be l-values." -// GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that -// are built-in types, entire structures or arrays... are all l-values." -// -TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutput output) - : TIntermTraverser(true, false, false) -{ - mVersion = ShaderOutputTypeToGLSLVersion(output); - if (pragma.stdgl.invariantAll) - { - ensureVersionIsAtLeast(GLSL_VERSION_120); - } - if (type == GL_COMPUTE_SHADER) - { - ensureVersionIsAtLeast(GLSL_VERSION_430); - } -} - -void TVersionGLSL::visitSymbol(TIntermSymbol *node) -{ - if (node->getSymbol() == "gl_PointCoord") - { - ensureVersionIsAtLeast(GLSL_VERSION_120); - } -} - -bool TVersionGLSL::visitDeclaration(Visit, TIntermDeclaration *node) -{ - const TIntermSequence &sequence = *(node->getSequence()); - if (sequence.front()->getAsTyped()->getType().isInvariant()) - { - ensureVersionIsAtLeast(GLSL_VERSION_120); - } - return true; -} - -bool TVersionGLSL::visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node) -{ - ensureVersionIsAtLeast(GLSL_VERSION_120); - return true; -} - -bool TVersionGLSL::visitFunctionPrototype(Visit, TIntermFunctionPrototype *node) -{ - const TIntermSequence ¶ms = *(node->getSequence()); - for (TIntermSequence::const_iterator iter = params.begin(); iter != params.end(); ++iter) - { - const TIntermTyped *param = (*iter)->getAsTyped(); - if (param->isArray()) - { - TQualifier qualifier = param->getQualifier(); - if ((qualifier == EvqOut) || (qualifier == EvqInOut)) - { - ensureVersionIsAtLeast(GLSL_VERSION_120); - break; - } - } - } - // Fully processed. No need to visit children. - return false; -} - -bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node) -{ - if (node->getOp() == EOpConstruct && node->getType().isMatrix()) - { - const TIntermSequence &sequence = *(node->getSequence()); - if (sequence.size() == 1) - { - TIntermTyped *typed = sequence.front()->getAsTyped(); - if (typed && typed->isMatrix()) - { - ensureVersionIsAtLeast(GLSL_VERSION_120); - } - } - } - return true; -} - -void TVersionGLSL::ensureVersionIsAtLeast(int version) -{ - mVersion = std::max(version, mVersion); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h deleted file mode 100644 index 8b82eb9615..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_VERSIONGLSL_H_ -#define COMPILER_TRANSLATOR_VERSIONGLSL_H_ - -#include "compiler/translator/IntermTraverse.h" - -#include "compiler/translator/Pragma.h" - -namespace sh -{ - -static const int GLSL_VERSION_110 = 110; -static const int GLSL_VERSION_120 = 120; -static const int GLSL_VERSION_130 = 130; -static const int GLSL_VERSION_140 = 140; -static const int GLSL_VERSION_150 = 150; -static const int GLSL_VERSION_330 = 330; -static const int GLSL_VERSION_400 = 400; -static const int GLSL_VERSION_410 = 410; -static const int GLSL_VERSION_420 = 420; -static const int GLSL_VERSION_430 = 430; -static const int GLSL_VERSION_440 = 440; -static const int GLSL_VERSION_450 = 450; - -int ShaderOutputTypeToGLSLVersion(ShShaderOutput output); - -// Traverses the intermediate tree to return the minimum GLSL version -// required to legally access all built-in features used in the shader. -// GLSL 1.1 which is mandated by OpenGL 2.0 provides: -// - #version and #extension to declare version and extensions. -// - built-in functions refract, exp, and log. -// - updated step() to compare x < edge instead of x <= edge. -// GLSL 1.2 which is mandated by OpenGL 2.1 provides: -// - many changes to reduce differences when compared to the ES specification. -// - invariant keyword and its support. -// - c++ style name hiding rules. -// - built-in variable gl_PointCoord for fragment shaders. -// - matrix constructors taking matrix as argument. -// - array as "out" function parameters -// -// TODO: ES3 equivalent versions of GLSL -class TVersionGLSL : public TIntermTraverser -{ - public: - TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutput output); - - // If output is core profile, returns 150. - // If output is legacy profile, - // Returns 120 if the following is used the shader: - // - "invariant", - // - "gl_PointCoord", - // - matrix/matrix constructors - // - array "out" parameters - // Else 110 is returned. - int getVersion() const { return mVersion; } - - void visitSymbol(TIntermSymbol *node) override; - bool visitAggregate(Visit, TIntermAggregate *node) override; - bool visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node) override; - bool visitFunctionPrototype(Visit, TIntermFunctionPrototype *node) override; - bool visitDeclaration(Visit, TIntermDeclaration *node) override; - - private: - void ensureVersionIsAtLeast(int version); - - int mVersion; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_VERSIONGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp b/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp deleted file mode 100644 index 85a11c998d..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// WrapSwitchStatementsInBlocks.cpp: Wrap switch statements in blocks and declare all switch-scoped -// variables there to make the AST compatible with HLSL output. -// -// switch (init) -// { -// case 0: -// float f; -// default: -// f = 1.0; -// } -// -// becomes -// -// { -// float f; -// switch (init) -// { -// case 0: -// default: -// f = 1.0; -// } -// } - -#include "compiler/translator/WrapSwitchStatementsInBlocks.h" - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class WrapSwitchStatementsInBlocksTraverser : public TIntermTraverser -{ - public: - WrapSwitchStatementsInBlocksTraverser() : TIntermTraverser(true, false, false), mDidWrap(false) - { - } - - bool visitSwitch(Visit visit, TIntermSwitch *node) override; - - bool didWrap() const { return mDidWrap; } - - private: - bool mDidWrap; -}; - -bool WrapSwitchStatementsInBlocksTraverser::visitSwitch(Visit, TIntermSwitch *node) -{ - std::vector<TIntermDeclaration *> declarations; - TIntermSequence *statementList = node->getStatementList()->getSequence(); - for (TIntermNode *statement : *statementList) - { - TIntermDeclaration *asDeclaration = statement->getAsDeclarationNode(); - if (asDeclaration) - { - declarations.push_back(asDeclaration); - } - } - if (declarations.empty()) - { - // We don't need to wrap the switch if it doesn't contain declarations as its direct - // descendants. - return true; - } - - TIntermBlock *wrapperBlock = new TIntermBlock(); - for (TIntermDeclaration *declaration : declarations) - { - // SeparateDeclarations should have already been run. - ASSERT(declaration->getSequence()->size() == 1); - - TIntermDeclaration *declarationInBlock = new TIntermDeclaration(); - TIntermSymbol *declaratorAsSymbol = declaration->getSequence()->at(0)->getAsSymbolNode(); - if (declaratorAsSymbol) - { - // This is a simple declaration like: "float f;" - // Remove the declaration from inside the switch and put it in the wrapping block. - TIntermSequence emptyReplacement; - mMultiReplacements.push_back(NodeReplaceWithMultipleEntry( - node->getStatementList(), declaration, emptyReplacement)); - - declarationInBlock->appendDeclarator(declaratorAsSymbol->deepCopy()); - } - else - { - // This is an init declaration like: "float f = 0.0;" - // Change the init declaration inside the switch into an assignment and put a plain - // declaration in the wrapping block. - TIntermBinary *declaratorAsBinary = - declaration->getSequence()->at(0)->getAsBinaryNode(); - ASSERT(declaratorAsBinary); - - TIntermBinary *initAssignment = new TIntermBinary( - EOpAssign, declaratorAsBinary->getLeft(), declaratorAsBinary->getRight()); - - queueReplacementWithParent(node->getStatementList(), declaration, initAssignment, - OriginalNode::IS_DROPPED); - - declarationInBlock->appendDeclarator(declaratorAsBinary->getLeft()->deepCopy()); - } - wrapperBlock->appendStatement(declarationInBlock); - } - - wrapperBlock->appendStatement(node); - queueReplacement(wrapperBlock, OriginalNode::BECOMES_CHILD); - mDidWrap = true; - - // Should be fine to process multiple switch statements, even nesting ones in the same - // traversal. - return true; -} - -} // anonymous namespace - -// Wrap switch statements in the AST into blocks when needed. -bool WrapSwitchStatementsInBlocks(TIntermBlock *root) -{ - WrapSwitchStatementsInBlocksTraverser traverser; - root->traverse(&traverser); - traverser.updateTree(); - return traverser.didWrap(); -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h b/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h deleted file mode 100644 index bc0179926d..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// WrapSwitchStatementsInBlocks.h: Wrap switch statements in blocks and declare all switch-scoped -// variables there to make the AST compatible with HLSL output. - -#ifndef COMPILER_TRANSLATOR_WRAPSWITCHSTATEMENTSINBLOCKS_H_ -#define COMPILER_TRANSLATOR_WRAPSWITCHSTATEMENTSINBLOCKS_H_ - -namespace sh -{ - -class TIntermBlock; - -// Wrap switch statements in the AST into blocks when needed. Returns true if the AST was changed. -bool WrapSwitchStatementsInBlocks(TIntermBlock *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_WRAPSWITCHSTATEMENTSINBLOCKS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp b/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp deleted file mode 100644 index fd8c450c20..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp +++ /dev/null @@ -1,281 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// blocklayout.cpp: -// Implementation for block layout classes and methods. -// - -#include "compiler/translator/blocklayout.h" - -#include "common/mathutil.h" -#include "common/utilities.h" - -namespace sh -{ - -namespace -{ -bool IsRowMajorLayout(const InterfaceBlockField &var) -{ - return var.isRowMajorLayout; -} - -bool IsRowMajorLayout(const ShaderVariable &var) -{ - return false; -} - -template <typename VarT> -void GetUniformBlockStructMemberInfo(const std::vector<VarT> &fields, - const std::string &fieldName, - sh::BlockLayoutEncoder *encoder, - bool inRowMajorLayout, - BlockLayoutMap *blockInfoOut) -{ - encoder->enterAggregateType(); - GetUniformBlockInfo(fields, fieldName, encoder, inRowMajorLayout, blockInfoOut); - encoder->exitAggregateType(); -} - -template <typename VarT> -void GetUniformBlockStructArrayMemberInfo(const VarT &field, - unsigned int arrayNestingIndex, - const std::string &arrayName, - sh::BlockLayoutEncoder *encoder, - bool inRowMajorLayout, - BlockLayoutMap *blockInfoOut) -{ - // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the - // innermost. - const unsigned int currentArraySize = field.getNestedArraySize(arrayNestingIndex); - for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement) - { - const std::string elementName = arrayName + ArrayString(arrayElement); - if (arrayNestingIndex + 1u < field.arraySizes.size()) - { - GetUniformBlockStructArrayMemberInfo(field, arrayNestingIndex + 1u, elementName, - encoder, inRowMajorLayout, blockInfoOut); - } - else - { - GetUniformBlockStructMemberInfo(field.fields, elementName, encoder, inRowMajorLayout, - blockInfoOut); - } - } -} - -template <typename VarT> -void GetUniformBlockArrayOfArraysMemberInfo(const VarT &field, - unsigned int arrayNestingIndex, - const std::string &arrayName, - sh::BlockLayoutEncoder *encoder, - bool inRowMajorLayout, - BlockLayoutMap *blockInfoOut) -{ - const unsigned int currentArraySize = field.getNestedArraySize(arrayNestingIndex); - for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement) - { - const std::string elementName = arrayName + ArrayString(arrayElement); - if (arrayNestingIndex + 2u < field.arraySizes.size()) - { - GetUniformBlockArrayOfArraysMemberInfo(field, arrayNestingIndex + 1u, elementName, - encoder, inRowMajorLayout, blockInfoOut); - } - else - { - std::vector<unsigned int> innermostArraySize( - 1u, field.getNestedArraySize(arrayNestingIndex + 1u)); - (*blockInfoOut)[elementName] = - encoder->encodeType(field.type, innermostArraySize, inRowMajorLayout); - } - } -} - -} // anonymous namespace - -BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0) -{ -} - -BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, - const std::vector<unsigned int> &arraySizes, - bool isRowMajorMatrix) -{ - int arrayStride; - int matrixStride; - - getBlockLayoutInfo(type, arraySizes, isRowMajorMatrix, &arrayStride, &matrixStride); - - const BlockMemberInfo memberInfo(static_cast<int>(mCurrentOffset * BytesPerComponent), - static_cast<int>(arrayStride * BytesPerComponent), - static_cast<int>(matrixStride * BytesPerComponent), - isRowMajorMatrix); - - advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride, matrixStride); - - return memberInfo; -} - -// static -size_t BlockLayoutEncoder::getBlockRegister(const BlockMemberInfo &info) -{ - return (info.offset / BytesPerComponent) / ComponentsPerRegister; -} - -// static -size_t BlockLayoutEncoder::getBlockRegisterElement(const BlockMemberInfo &info) -{ - return (info.offset / BytesPerComponent) % ComponentsPerRegister; -} - -void BlockLayoutEncoder::nextRegister() -{ - mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, ComponentsPerRegister); -} - -Std140BlockEncoder::Std140BlockEncoder() -{ -} - -void Std140BlockEncoder::enterAggregateType() -{ - nextRegister(); -} - -void Std140BlockEncoder::exitAggregateType() -{ - nextRegister(); -} - -void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, - const std::vector<unsigned int> &arraySizes, - bool isRowMajorMatrix, - int *arrayStrideOut, - int *matrixStrideOut) -{ - // We assume we are only dealing with 4 byte components (no doubles or half-words currently) - ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); - - size_t baseAlignment = 0; - int matrixStride = 0; - int arrayStride = 0; - - if (gl::IsMatrixType(type)) - { - baseAlignment = ComponentsPerRegister; - matrixStride = ComponentsPerRegister; - - if (!arraySizes.empty()) - { - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - arrayStride = ComponentsPerRegister * numRegisters; - } - } - else if (!arraySizes.empty()) - { - baseAlignment = ComponentsPerRegister; - arrayStride = ComponentsPerRegister; - } - else - { - const int numComponents = gl::VariableComponentCount(type); - baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents)); - } - - mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment); - - *matrixStrideOut = matrixStride; - *arrayStrideOut = arrayStride; -} - -void Std140BlockEncoder::advanceOffset(GLenum type, - const std::vector<unsigned int> &arraySizes, - bool isRowMajorMatrix, - int arrayStride, - int matrixStride) -{ - if (!arraySizes.empty()) - { - mCurrentOffset += arrayStride * gl::ArraySizeProduct(arraySizes); - } - else if (gl::IsMatrixType(type)) - { - ASSERT(matrixStride == ComponentsPerRegister); - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - mCurrentOffset += ComponentsPerRegister * numRegisters; - } - else - { - mCurrentOffset += gl::VariableComponentCount(type); - } -} - -template <typename VarT> -void GetUniformBlockInfo(const std::vector<VarT> &fields, - const std::string &prefix, - sh::BlockLayoutEncoder *encoder, - bool inRowMajorLayout, - BlockLayoutMap *blockInfoOut) -{ - for (const VarT &field : fields) - { - // Skip samplers. On Vulkan we use this for the default uniform block, so samplers may be - // included. - if (gl::IsSamplerType(field.type)) - { - continue; - } - - const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); - - if (field.isStruct()) - { - bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); - - if (field.isArray()) - { - GetUniformBlockStructArrayMemberInfo(field, 0u, fieldName, encoder, rowMajorLayout, - blockInfoOut); - } - else - { - GetUniformBlockStructMemberInfo(field.fields, fieldName, encoder, rowMajorLayout, - blockInfoOut); - } - } - else if (field.isArrayOfArrays()) - { - bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout); - GetUniformBlockArrayOfArraysMemberInfo(field, 0u, fieldName, encoder, isRowMajorMatrix, - blockInfoOut); - } - else - { - bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout); - (*blockInfoOut)[fieldName] = - encoder->encodeType(field.type, field.arraySizes, isRowMajorMatrix); - } - } -} - -template void GetUniformBlockInfo(const std::vector<InterfaceBlockField> &, - const std::string &, - sh::BlockLayoutEncoder *, - bool, - BlockLayoutMap *); - -template void GetUniformBlockInfo(const std::vector<Uniform> &, - const std::string &, - sh::BlockLayoutEncoder *, - bool, - BlockLayoutMap *); - -template void GetUniformBlockInfo(const std::vector<ShaderVariable> &, - const std::string &, - sh::BlockLayoutEncoder *, - bool, - BlockLayoutMap *); - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayout.h b/src/3rdparty/angle/src/compiler/translator/blocklayout.h deleted file mode 100644 index 2b7acf4e60..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/blocklayout.h +++ /dev/null @@ -1,144 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// blocklayout.h: -// Methods and classes related to uniform layout and packing in GLSL and HLSL. -// - -#ifndef COMMON_BLOCKLAYOUT_H_ -#define COMMON_BLOCKLAYOUT_H_ - -#include <cstddef> -#include <map> -#include <vector> - -#include "angle_gl.h" -#include <GLSLANG/ShaderLang.h> - -namespace sh -{ -struct ShaderVariable; -struct InterfaceBlockField; -struct Uniform; -struct Varying; -struct InterfaceBlock; - -struct BlockMemberInfo -{ - BlockMemberInfo() - : offset(-1), - arrayStride(-1), - matrixStride(-1), - isRowMajorMatrix(false), - topLevelArrayStride(-1) - { - } - - BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix) - : offset(offset), - arrayStride(arrayStride), - matrixStride(matrixStride), - isRowMajorMatrix(isRowMajorMatrix), - topLevelArrayStride(-1) - { - } - - BlockMemberInfo(int offset, - int arrayStride, - int matrixStride, - bool isRowMajorMatrix, - int topLevelArrayStride) - : offset(offset), - arrayStride(arrayStride), - matrixStride(matrixStride), - isRowMajorMatrix(isRowMajorMatrix), - topLevelArrayStride(topLevelArrayStride) - { - } - - static BlockMemberInfo getDefaultBlockInfo() { return BlockMemberInfo(-1, -1, -1, false, -1); } - - int offset; - int arrayStride; - int matrixStride; - bool isRowMajorMatrix; - int topLevelArrayStride; // Only used for shader storage block members. -}; - -class BlockLayoutEncoder -{ - public: - BlockLayoutEncoder(); - virtual ~BlockLayoutEncoder() {} - - BlockMemberInfo encodeType(GLenum type, - const std::vector<unsigned int> &arraySizes, - bool isRowMajorMatrix); - - size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; } - - virtual void enterAggregateType() = 0; - virtual void exitAggregateType() = 0; - - static const size_t BytesPerComponent = 4u; - static const unsigned int ComponentsPerRegister = 4u; - - static size_t getBlockRegister(const BlockMemberInfo &info); - static size_t getBlockRegisterElement(const BlockMemberInfo &info); - - protected: - size_t mCurrentOffset; - - void nextRegister(); - - virtual void getBlockLayoutInfo(GLenum type, - const std::vector<unsigned int> &arraySizes, - bool isRowMajorMatrix, - int *arrayStrideOut, - int *matrixStrideOut) = 0; - virtual void advanceOffset(GLenum type, - const std::vector<unsigned int> &arraySizes, - bool isRowMajorMatrix, - int arrayStride, - int matrixStride) = 0; -}; - -// Block layout according to the std140 block layout -// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification - -class Std140BlockEncoder : public BlockLayoutEncoder -{ - public: - Std140BlockEncoder(); - - void enterAggregateType() override; - void exitAggregateType() override; - - protected: - void getBlockLayoutInfo(GLenum type, - const std::vector<unsigned int> &arraySizes, - bool isRowMajorMatrix, - int *arrayStrideOut, - int *matrixStrideOut) override; - void advanceOffset(GLenum type, - const std::vector<unsigned int> &arraySizes, - bool isRowMajorMatrix, - int arrayStride, - int matrixStride) override; -}; - -using BlockLayoutMap = std::map<std::string, BlockMemberInfo>; - -// Only valid to call with ShaderVariable, InterfaceBlockField and Uniform. -template <typename VarT> -void GetUniformBlockInfo(const std::vector<VarT> &fields, - const std::string &prefix, - sh::BlockLayoutEncoder *encoder, - bool inRowMajorLayout, - BlockLayoutMap *blockLayoutMap); - -} // namespace sh - -#endif // COMMON_BLOCKLAYOUT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp deleted file mode 100644 index 867821f1ea..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// blocklayout.cpp: -// Implementation for block layout classes and methods. -// - -#include "compiler/translator/blocklayoutHLSL.h" - -#include "common/mathutil.h" -#include "common/utilities.h" - -namespace sh -{ - -HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices) - : mEncoderStrategy(strategy), mTransposeMatrices(transposeMatrices) -{ -} - -void HLSLBlockEncoder::enterAggregateType() -{ - nextRegister(); -} - -void HLSLBlockEncoder::exitAggregateType() -{ -} - -void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, - const std::vector<unsigned int> &arraySizes, - bool isRowMajorMatrix, - int *arrayStrideOut, - int *matrixStrideOut) -{ - GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn); - - // We assume we are only dealing with 4 byte components (no doubles or half-words currently) - ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); - - int matrixStride = 0; - int arrayStride = 0; - - // if variables are not to be packed, or we're about to - // pack a matrix or array, skip to the start of the next - // register - if (!isPacked() || gl::IsMatrixType(type) || !arraySizes.empty()) - { - nextRegister(); - } - - if (gl::IsMatrixType(type)) - { - matrixStride = ComponentsPerRegister; - - if (!arraySizes.empty()) - { - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - arrayStride = ComponentsPerRegister * numRegisters; - } - } - else if (!arraySizes.empty()) - { - arrayStride = ComponentsPerRegister; - } - else if (isPacked()) - { - int numComponents = gl::VariableComponentCount(type); - if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister) - { - nextRegister(); - } - } - - *matrixStrideOut = matrixStride; - *arrayStrideOut = arrayStride; -} - -void HLSLBlockEncoder::advanceOffset(GLenum typeIn, - const std::vector<unsigned int> &arraySizes, - bool isRowMajorMatrix, - int arrayStride, - int matrixStride) -{ - GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn); - - if (!arraySizes.empty()) - { - mCurrentOffset += arrayStride * (gl::ArraySizeProduct(arraySizes) - 1); - } - - if (gl::IsMatrixType(type)) - { - ASSERT(matrixStride == ComponentsPerRegister); - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix); - mCurrentOffset += ComponentsPerRegister * (numRegisters - 1); - mCurrentOffset += numComponents; - } - else if (isPacked()) - { - mCurrentOffset += gl::VariableComponentCount(type); - } - else - { - mCurrentOffset += ComponentsPerRegister; - } -} - -void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters) -{ - mCurrentOffset += (numRegisters * ComponentsPerRegister); -} - -HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor( - ShShaderOutput outputType) -{ - switch (outputType) - { - case SH_HLSL_3_0_OUTPUT: - return ENCODE_LOOSE; - case SH_HLSL_4_1_OUTPUT: - case SH_HLSL_4_0_FL9_3_OUTPUT: - return ENCODE_PACKED; - default: - UNREACHABLE(); - return ENCODE_PACKED; - } -} - -template <class ShaderVarType> -void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder) -{ - if (variable.isStruct()) - { - for (size_t arrayElement = 0; arrayElement < variable.getArraySizeProduct(); arrayElement++) - { - encoder->enterAggregateType(); - - for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++) - { - HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder); - } - - encoder->exitAggregateType(); - } - } - else - { - // We operate only on varyings and uniforms, which do not have matrix layout qualifiers - encoder->encodeType(variable.type, variable.arraySizes, false); - } -} - -unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType) -{ - HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType), true); - HLSLVariableRegisterCount(variable, &encoder); - - const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister); - return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / - registerBytes); -} -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h deleted file mode 100644 index 8f4a51a906..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// blocklayout.h: -// Methods and classes related to uniform layout and packing in GLSL and HLSL. -// - -#ifndef COMMON_BLOCKLAYOUTHLSL_H_ -#define COMMON_BLOCKLAYOUTHLSL_H_ - -#include <cstddef> -#include <vector> - -#include "angle_gl.h" -#include "blocklayout.h" -#include <GLSLANG/ShaderLang.h> - -namespace sh -{ -// Block layout packed according to the D3D9 or default D3D10+ register packing rules -// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx -// The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED -// for everything else (D3D10+ constant blocks and all attributes/varyings). - -class HLSLBlockEncoder : public BlockLayoutEncoder -{ - public: - enum HLSLBlockEncoderStrategy - { - ENCODE_PACKED, - ENCODE_LOOSE - }; - - HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices); - - void enterAggregateType() override; - void exitAggregateType() override; - void skipRegisters(unsigned int numRegisters); - - bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; } - - static HLSLBlockEncoderStrategy GetStrategyFor(ShShaderOutput outputType); - - protected: - void getBlockLayoutInfo(GLenum type, - const std::vector<unsigned int> &arraySizes, - bool isRowMajorMatrix, - int *arrayStrideOut, - int *matrixStrideOut) override; - void advanceOffset(GLenum type, - const std::vector<unsigned int> &arraySizes, - bool isRowMajorMatrix, - int arrayStride, - int matrixStride) override; - - HLSLBlockEncoderStrategy mEncoderStrategy; - bool mTransposeMatrices; -}; - -// This method returns the number of used registers for a ShaderVariable. It is dependent on the -// HLSLBlockEncoder class to count the number of used registers in a struct (which are individually -// packed according to the same rules). -unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType); -} - -#endif // COMMON_BLOCKLAYOUTHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json b/src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json deleted file mode 100644 index 32e500fe67..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json +++ /dev/null @@ -1,1382 +0,0 @@ -[ - { - "op":"mod", - "return_type":"float", - "args":[ - "float x", - "float y" - ], - "body":[ - "return x - y * floor(x / y);" - ] - }, - { - "op":"mod", - "return_type":"float2", - "args":[ - "float2 x", - "float2 y" - ], - "body":[ - "return x - y * floor(x / y);" - ] - }, - { - "op":"mod", - "return_type":"float2", - "args":[ - "float2 x", - "float y" - ], - "body":[ - "return x - y * floor(x / y);" - ] - }, - { - "op":"mod", - "return_type":"float3", - "args":[ - "float3 x", - "float3 y" - ], - "body":[ - "return x - y * floor(x / y);" - ] - }, - { - "op":"mod", - "return_type":"float3", - "args":[ - "float3 x", - "float y" - ], - "body":[ - "return x - y * floor(x / y);" - ] - }, - { - "op":"mod", - "return_type":"float4", - "args":[ - "float4 x", - "float4 y" - ], - "body":[ - "return x - y * floor(x / y);" - ] - }, - { - "op":"mod", - "return_type":"float4", - "args":[ - "float4 x", - "float y" - ], - "body":[ - "return x - y * floor(x / y);" - ] - }, - { - "op":"frexp", - "return_type":"float", - "args":[ - "float x", - "out int exp" - ], - "body":[ - "float fexp;", - "float mantissa = frexp(abs(x), fexp) * sign(x);", - "exp = int(fexp);", - "return mantissa;" - ] - }, - { - "op":"frexp", - "return_type":"float2", - "args":[ - "float2 x", - "out int2 exp" - ], - "body":[ - "float2 fexp;", - "float2 mantissa = frexp(abs(x), fexp) * sign(x);", - "exp = int2(fexp);", - "return mantissa;" - ] - }, - { - "op":"frexp", - "return_type":"float3", - "args":[ - "float3 x", - "out int3 exp" - ], - "body":[ - "float3 fexp;", - "float3 mantissa = frexp(abs(x), fexp) * sign(x);", - "exp = int3(fexp);", - "return mantissa;" - ] - }, - { - "op":"frexp", - "return_type":"float4", - "args":[ - "float4 x", - "out int4 exp" - ], - "body":[ - "float4 fexp;", - "float4 mantissa = frexp(abs(x), fexp) * sign(x);", - "exp = int4(fexp);", - "return mantissa;" - ] - }, - { - "op":"ldexp", - "return_type":"float", - "args":[ - "float x", - "int exp" - ], - "body":[ - "return ldexp(x, float(exp));" - ] - }, - { - "op":"ldexp", - "return_type":"float2", - "args":[ - "float2 x", - "int2 exp" - ], - "body":[ - "return ldexp(x, float2(exp));" - ] - }, - { - "op":"ldexp", - "return_type":"float3", - "args":[ - "float3 x", - "int3 exp" - ], - "body":[ - "return ldexp(x, float3(exp));" - ] - }, - { - "op":"ldexp", - "return_type":"float4", - "args":[ - "float4 x", - "int4 exp" - ], - "body":[ - "return ldexp(x, float4(exp));" - ] - }, - { - "op":"faceforward", - "return_type":"float", - "args":[ - "float N", - "float I", - "float Nref" - ], - "body":[ - "if(dot(Nref, I) >= 0)", - "{", - " return -N;", - "}", - "else", - "{", - " return N;", - "}" - ] - }, - { - "op":"faceforward", - "return_type":"float2", - "args":[ - "float2 N", - "float2 I", - "float2 Nref" - ], - "body":[ - "if(dot(Nref, I) >= 0)", - "{", - " return -N;", - "}", - "else", - "{", - " return N;", - "}" - ] - }, - { - "op":"faceforward", - "return_type":"float3", - "args":[ - "float3 N", - "float3 I", - "float3 Nref" - ], - "body":[ - "if(dot(Nref, I) >= 0)", - "{", - " return -N;", - "}", - "else", - "{", - " return N;", - "}" - ] - }, - { - "op":"faceforward", - "return_type":"float4", - "args":[ - "float4 N", - "float4 I", - "float4 Nref" - ], - "body":[ - "if(dot(Nref, I) >= 0)", - "{", - " return -N;", - "}", - "else", - "{", - " return N;", - "}" - ] - }, - { - "op":"atan", - "return_type":"float", - "args":[ - "float y", - "float x" - ], - "body":[ - "if(x == 0 && y == 0) x = 1;", - "return atan2(y, x);" - ] - }, - { - "op":"atan", - "return_type":"float2", - "args":[ - "float2 y", - "float2 x" - ], - "body":[ - "if(x[0] == 0 && y[0] == 0) x[0] = 1;", - "if(x[1] == 0 && y[1] == 0) x[1] = 1;", - "return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));" - ] - }, - { - "op":"atan", - "return_type":"float3", - "args":[ - "float3 y", - "float3 x" - ], - "body":[ - "if(x[0] == 0 && y[0] == 0) x[0] = 1;", - "if(x[1] == 0 && y[1] == 0) x[1] = 1;", - "if(x[2] == 0 && y[2] == 0) x[2] = 1;", - "return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));" - ] - }, - { - "op":"atan", - "return_type":"float4", - "args":[ - "float4 y", - "float4 x" - ], - "body":[ - "if(x[0] == 0 && y[0] == 0) x[0] = 1;", - "if(x[1] == 0 && y[1] == 0) x[1] = 1;", - "if(x[2] == 0 && y[2] == 0) x[2] = 1;", - "if(x[3] == 0 && y[3] == 0) x[3] = 1;", - "return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], ", - "x[2]), atan2(y[3], x[3]));" - ] - }, - { - "op":"asinh", - "return_type":"float", - "args":[ - "in float x" - ], - "body":[ - "return log(x + sqrt(pow(x, 2.0) + 1.0));" - ] - }, - { - "op":"asinh", - "return_type":"float2", - "args":[ - "in float2 x" - ], - "body":[ - "return log(x + sqrt(pow(x, 2.0) + 1.0));" - ] - }, - { - "op":"asinh", - "return_type":"float3", - "args":[ - "in float3 x" - ], - "body":[ - "return log(x + sqrt(pow(x, 2.0) + 1.0));" - ] - }, - { - "op":"asinh", - "return_type":"float4", - "args":[ - "in float4 x" - ], - "body":[ - "return log(x + sqrt(pow(x, 2.0) + 1.0));" - ] - }, - { - "op":"acosh", - "return_type":"float", - "args":[ - "in float x" - ], - "body":[ - "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));" - ] - }, - { - "op":"acosh", - "return_type":"float2", - "args":[ - "in float2 x" - ], - "body":[ - "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));" - ] - }, - { - "op":"acosh", - "return_type":"float3", - "args":[ - "in float3 x" - ], - "body":[ - "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));" - ] - }, - { - "op":"acosh", - "return_type":"float4", - "args":[ - "in float4 x" - ], - "body":[ - "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));" - ] - }, - { - "op":"atanh", - "return_type":"float", - "args":[ - "in float x" - ], - "body":[ - "return 0.5 * log((1.0 + x) / (1.0 - x));" - ] - }, - { - "op":"atanh", - "return_type":"float2", - "args":[ - "in float2 x" - ], - "body":[ - "return 0.5 * log((1.0 + x) / (1.0 - x));" - ] - }, - { - "op":"atanh", - "return_type":"float3", - "args":[ - "in float3 x" - ], - "body":[ - "return 0.5 * log((1.0 + x) / (1.0 - x));" - ] - }, - { - "op":"atanh", - "return_type":"float4", - "args":[ - "in float4 x" - ], - "body":[ - "return 0.5 * log((1.0 + x) / (1.0 - x));" - ] - }, - { - "op":"roundEven", - "return_type":"float", - "args":[ - "in float x" - ], - "body":[ - "return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);" - ] - }, - { - "op":"roundEven", - "return_type":"float2", - "args":[ - "in float2 x" - ], - "body":[ - "float2 v;", - "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);", - "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);", - "return v;" - ] - }, - { - "op":"roundEven", - "return_type":"float3", - "args":[ - "in float3 x" - ], - "body":[ - "float3 v;", - "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);", - "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);", - "v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);", - "return v;" - ] - }, - { - "op":"roundEven", - "return_type":"float4", - "args":[ - "in float4 x" - ], - "body":[ - "float4 v;", - "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);", - "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);", - "v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);", - "v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);", - "return v;" - ] - }, - { - "op":"packSnorm2x16", - "return_type":"uint", - "args":[ - "in float2 v" - ], - "helper":[ - "int webgl_toSnorm16(in float x) {", - " return int(round(clamp(x, -1.0, 1.0) * 32767.0));", - "}" - ], - "body":[ - "int x = webgl_toSnorm16(v.x);", - "int y = webgl_toSnorm16(v.y);", - "return (asuint(y) << 16) | (asuint(x) & 0xffffu);" - ] - }, - { - "op":"packUnorm2x16", - "return_type":"uint", - "args":[ - "in float2 v" - ], - "helper":[ - "uint webgl_toUnorm16(in float x) {", - " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));", - "}" - ], - "body":[ - "uint x = webgl_toUnorm16(v.x);", - "uint y = webgl_toUnorm16(v.y);", - "return (y << 16) | x;" - ] - }, - { - "op":"packHalf2x16", - "return_type":"uint", - "args":[ - "in float2 v" - ], - "body":[ - "uint x = f32tof16(v.x);", - "uint y = f32tof16(v.y);", - "return (y << 16) | x;" - ] - }, - { - "op":"unpackSnorm2x16", - "return_type":"float2", - "args":[ - "in uint u" - ], - "helper":[ - "float webgl_fromSnorm16(in uint x) {", - " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);", - " return clamp(float(xi) / 32767.0, -1.0, 1.0);", - "}" - ], - "body":[ - "uint y = (u >> 16);", - "uint x = u;", - "return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));" - ] - }, - { - "op":"unpackUnorm2x16", - "return_type":"float2", - "args":[ - "in uint u" - ], - "helper":[ - "float webgl_fromUnorm16(in uint x) {", - " return float(x) / 65535.0;", - "}" - ], - "body":[ - "uint y = (u >> 16);", - "uint x = u & 0xffffu;", - "return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));" - ] - }, - { - "op":"unpackHalf2x16", - "return_type":"float2", - "args":[ - "in uint u" - ], - "body":[ - "uint y = (u >> 16);", - "uint x = u & 0xffffu;", - "return float2(f16tof32(x), f16tof32(y));" - ] - }, - { - "op":"packSnorm4x8", - "return_type":"uint", - "args":[ - "in float4 v" - ], - "helper":[ - "int webgl_toSnorm8(in float x) {", - " return int(round(clamp(x, -1.0, 1.0) * 127.0));", - "}" - ], - "body":[ - "int x = webgl_toSnorm8(v.x);", - "int y = webgl_toSnorm8(v.y);", - "int z = webgl_toSnorm8(v.z);", - "int w = webgl_toSnorm8(v.w);", - "return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) ", - "| ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);" - ] - }, - { - "op":"packUnorm4x8", - "return_type":"uint", - "args":[ - "in float4 v" - ], - "helper":[ - "uint webgl_toUnorm8(in float x) {", - " return uint(round(clamp(x, 0.0, 1.0) * 255.0));", - "}" - ], - "body":[ - "uint x = webgl_toUnorm8(v.x);", - "uint y = webgl_toUnorm8(v.y);", - "uint z = webgl_toUnorm8(v.z);", - "uint w = webgl_toUnorm8(v.w);", - "return (w << 24) | (z << 16) | (y << 8) | x;" - ] - }, - { - "op":"unpackSnorm4x8", - "return_type":"float4", - "args":[ - "in uint u" - ], - "helper":[ - "float webgl_fromSnorm8(in uint x) {", - " int xi = asint(x & 0x7fu) - asint(x & 0x80u);", - " return clamp(float(xi) / 127.0, -1.0, 1.0);", - "}" - ], - "body":[ - "uint w = (u >> 24);", - "uint z = (u >> 16);", - "uint y = (u >> 8);", - "uint x = u;", - "return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), ", - "webgl_fromSnorm8(z), webgl_fromSnorm8(w));" - ] - }, - { - "op":"unpackUnorm4x8", - "return_type":"float4", - "args":[ - "in uint u" - ], - "helper":[ - "float webgl_fromUnorm8(in uint x) {", - " return float(x) / 255.0;", - "}" - ], - "body":[ - "uint w = (u >> 24) & 0xffu;", - "uint z = (u >> 16) & 0xffu;", - "uint y = (u >> 8) & 0xffu;", - "uint x = u & 0xffu;", - "return float4(webgl_fromUnorm8(x), webgl_fromUnorm8(y), ", - "webgl_fromUnorm8(z), webgl_fromUnorm8(w));" - ] - }, - { - "comment":[ - "The matrix resulting from outer product needs to be transposed", - "(matrices are stored as transposed to simplify element access in HLSL).", - "So the function should return transpose(c * r) where c is a column vector", - "and r is a row vector. This can be simplified by using the following", - "formula:", - "transpose(c * r) = transpose(r) * transpose(c)", - "transpose(r) and transpose(c) are in a sense free, since to get the", - "transpose of r, we simply can build a column matrix out of the original", - "vector instead of a row matrix." - ], - "op":"outerProduct", - "return_type":"float2x2", - "args":[ - "in float2 c", - "in float2 r" - ], - "body":[ - "return mul(float2x1(r), float1x2(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float3x3", - "args":[ - "in float3 c", - "in float3 r" - ], - "body":[ - "return mul(float3x1(r), float1x3(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float4x4", - "args":[ - "in float4 c", - "in float4 r" - ], - "body":[ - "return mul(float4x1(r), float1x4(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float2x3", - "args":[ - "in float3 c", - "in float2 r" - ], - "body":[ - "return mul(float2x1(r), float1x3(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float3x2", - "args":[ - "in float2 c", - "in float3 r" - ], - "body":[ - "return mul(float3x1(r), float1x2(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float2x4", - "args":[ - "in float4 c", - "in float2 r" - ], - "body":[ - "return mul(float2x1(r), float1x4(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float4x2", - "args":[ - "in float2 c", - "in float4 r" - ], - "body":[ - "return mul(float4x1(r), float1x2(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float3x4", - "args":[ - "in float4 c", - "in float3 r" - ], - "body":[ - "return mul(float3x1(r), float1x4(c));" - ] - }, - { - "op":"outerProduct", - "return_type":"float4x3", - "args":[ - "in float3 c", - "in float4 r" - ], - "body":[ - "return mul(float4x1(r), float1x3(c));" - ] - }, - { - "comment":[ - "Remember here that the parameter matrix is actually the transpose", - "of the matrix that we're trying to invert, and the resulting matrix", - "should also be the transpose of the inverse.", - "When accessing the parameter matrix with m[a][b] it can be thought of so", - "that a is the column and b is the row of the matrix that we're inverting.", - "We calculate the inverse as the adjugate matrix divided by the", - "determinant of the matrix being inverted. However, as the result needs", - "to be transposed, we actually use of the transpose of the adjugate matrix", - "which happens to be the cofactor matrix. That's stored in 'cof'.", - "We don't need to care about divide-by-zero since results are undefined", - "for singular or poorly-conditioned matrices." - ], - "op":"inverse", - "return_type":"float2x2", - "args":[ - "in float2x2 m" - ], - "body":[ - "float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };", - "return cof / determinant(transpose(m));" - ] - }, - { - "comment":[ - "cofAB is the cofactor for column A and row B." - ], - "op":"inverse", - "return_type":"float3x3", - "args":[ - "in float3x3 m" - ], - "body":[ - "float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];", - "float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);", - "float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];", - "float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);", - "float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];", - "float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);", - "float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];", - "float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);", - "float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];", - "float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };", - "return cof / determinant(transpose(m));" - ] - }, - { - "op":"inverse", - "return_type":"float4x4", - "args":[ - "in float4x4 m" - ], - "body":[ - "float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * ", - "m[1][2] * m[2][3]", - " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * ", - "m[1][3];", - "float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * ", - "m[1][2] * m[2][3]", - " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * ", - "m[1][3]);", - "float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * ", - "m[1][1] * m[2][3]", - " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * ", - "m[1][3];", - "float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * ", - "m[1][1] * m[2][2]", - " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * ", - "m[1][2]);", - "float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * ", - "m[0][2] * m[2][3]", - " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * ", - "m[0][3]);", - "float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * ", - "m[0][2] * m[2][3]", - " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * ", - "m[0][3];", - "float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * ", - "m[0][1] * m[2][3]", - " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * ", - "m[0][3]);", - "float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * ", - "m[0][1] * m[2][2]", - " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * ", - "m[0][2];", - "float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * ", - "m[0][2] * m[1][3]", - " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * ", - "m[0][3];", - "float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * ", - "m[0][2] * m[1][3]", - " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * ", - "m[0][3]);", - "float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * ", - "m[0][1] * m[1][3]", - " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * ", - "m[0][3];", - "float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * ", - "m[0][1] * m[1][2]", - " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * ", - "m[0][2]);", - "float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * ", - "m[0][2] * m[1][3]", - " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * ", - "m[0][3]);", - "float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * ", - "m[0][2] * m[1][3]", - " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * ", - "m[0][3];", - "float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * ", - "m[0][1] * m[1][3]", - " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * ", - "m[0][3]);", - "float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * ", - "m[0][1] * m[1][2]", - " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * ", - "m[0][2];", - "float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,", - " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };", - "return cof / determinant(transpose(m));" - ] - }, - { - "comment":[ - "Emulate ESSL3 variant of mix that takes last argument as boolean vector.", - "genType mix(genType x, genType y, genBType a): Selects which vector each returned component", - "comes from. For a component of 'a' that is false, the corresponding component of 'x' is", - "returned. For a component of 'a' that is true, the corresponding component of 'y' is returned." - ], - "op":"mix", - "return_type":"float", - "args":[ - "float x", - "float y", - "bool a" - ], - "body":[ - "return a ? y : x;" - ] - }, - { - "op":"mix", - "return_type":"float2", - "args":[ - "float2 x", - "float2 y", - "bool2 a" - ], - "body":[ - "return a ? y : x;" - ] - }, - { - "op":"mix", - "return_type":"float3", - "args":[ - "float3 x", - "float3 y", - "bool3 a" - ], - "body":[ - "return a ? y : x;" - ] - }, - { - "op":"mix", - "return_type":"float4", - "args":[ - "float4 x", - "float4 y", - "bool4 a" - ], - "body":[ - "return a ? y : x;" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"uint", - "args":[ - "uint value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return 0u;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "return (value & mask) >> offset;" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"uint2", - "args":[ - "uint2 value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return uint2(0u, 0u);", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "return (value & mask) >> offset;" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"uint3", - "args":[ - "uint3 value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return uint3(0u, 0u, 0u);", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "return (value & mask) >> offset;" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"uint4", - "args":[ - "uint4 value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return uint4(0u, 0u, 0u, 0u);", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "return (value & mask) >> offset;" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"int", - "args":[ - "int value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return 0;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint resultUnsigned = (asuint(value) & mask) >> offset;", - "if (bits != 32 && (resultUnsigned & maskMsb) != 0)", - "{", - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;", - " resultUnsigned |= higherBitsMask;", - "}", - "return asint(resultUnsigned);" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"int2", - "args":[ - "int2 value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return int2(0, 0);", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint2 resultUnsigned = (asuint(value) & mask) >> offset;", - "if (bits != 32)", - "{", - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;", - " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;", - "}", - "return asint(resultUnsigned);" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"int3", - "args":[ - "int3 value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return int3(0, 0, 0);", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint3 resultUnsigned = (asuint(value) & mask) >> offset;", - "if (bits != 32)", - "{", - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;", - " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;", - "}", - "return asint(resultUnsigned);" - ] - }, - { - "op":"bitfieldExtract", - "return_type":"int4", - "args":[ - "int4 value", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return int4(0, 0, 0, 0);", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint4 resultUnsigned = (asuint(value) & mask) >> offset;", - "if (bits != 32)", - "{", - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;", - " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;", - "}", - "return asint(resultUnsigned);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"uint", - "args":[ - "uint base", - "uint insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "return (base & baseMask) | ((insert << offset) & insertMask);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"uint2", - "args":[ - "uint2 base", - "uint2 insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "return (base & baseMask) | ((insert << offset) & insertMask);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"uint3", - "args":[ - "uint3 base", - "uint3 insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "return (base & baseMask) | ((insert << offset) & insertMask);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"uint4", - "args":[ - "uint4 base", - "uint4 insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "return (base & baseMask) | ((insert << offset) & insertMask);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"int", - "args":[ - "int base", - "int insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "uint resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ", - " insertMask);", - "return asint(resultUnsigned);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"int2", - "args":[ - "int2 base", - "int2 insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "uint2 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ", - " insertMask);", - "return asint(resultUnsigned);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"int3", - "args":[ - "int3 base", - "int3 insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "uint3 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ", - " insertMask);", - "return asint(resultUnsigned);" - ] - }, - { - "op":"bitfieldInsert", - "return_type":"int4", - "args":[ - "int4 base", - "int4 insert", - "int offset", - "int bits" - ], - "body":[ - "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", - "{", - " return base;", - "}", - "uint maskMsb = (1u << (bits - 1));", - "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", - "uint baseMask = ~insertMask;", - "uint4 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ", - "insertMask);", - "return asint(resultUnsigned);" - ] - }, - { - "op":"uaddCarry", - "return_type":"uint", - "args":[ - "uint x", - "uint y", - "out uint carry" - ], - "body":[ - "carry = uint(x > (0xffffffffu - y));", - "return x + y;" - ] - }, - { - "op":"uaddCarry", - "return_type":"uint2", - "args":[ - "uint2 x", - "uint2 y", - "out uint2 carry" - ], - "body":[ - "carry = uint2(x > (0xffffffffu - y));", - "return x + y;" - ] - }, - { - "op":"uaddCarry", - "return_type":"uint3", - "args":[ - "uint3 x", - "uint3 y", - "out uint3 carry" - ], - "body":[ - "carry = uint3(x > (0xffffffffu - y));", - "return x + y;" - ] - }, - { - "op":"uaddCarry", - "return_type":"uint4", - "args":[ - "uint4 x", - "uint4 y", - "out uint4 carry" - ], - "body":[ - "carry = uint4(x > (0xffffffffu - y));", - "return x + y;" - ] - }, - { - "op":"usubBorrow", - "return_type":"uint", - "args":[ - "uint x", - "uint y", - "out uint borrow" - ], - "body":[ - "borrow = uint(x < y);", - "return x - y;" - ] - }, - { - "op":"usubBorrow", - "return_type":"uint2", - "args":[ - "uint2 x", - "uint2 y", - "out uint2 borrow" - ], - "body":[ - "borrow = uint2(x < y);", - "return x - y;" - ] - }, - { - "op":"usubBorrow", - "return_type":"uint3", - "args":[ - "uint3 x", - "uint3 y", - "out uint3 borrow" - ], - "body":[ - "borrow = uint3(x < y);", - "return x - y;" - ] - }, - { - "op":"usubBorrow", - "return_type":"uint4", - "args":[ - "uint4 x", - "uint4 y", - "out uint4 borrow" - ], - "body":[ - "borrow = uint4(x < y);", - "return x - y;" - ] - } -] diff --git a/src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp b/src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp deleted file mode 100644 index 288da5e0f5..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp +++ /dev/null @@ -1,859 +0,0 @@ -// GENERATED FILE - DO NOT EDIT. -// Generated by gen_emulated_builtin_function_tables.py using data from -// emulated_builtin_function_data_hlsl.json. -// -// Copyright 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// emulated_builtin_functions_hlsl: -// HLSL code for emulating GLSL builtin functions not present in HLSL. - -#include "compiler/translator/BuiltInFunctionEmulator.h" - -namespace sh -{ - -namespace -{ - -struct FunctionPair -{ - constexpr FunctionPair(const MiniFunctionId &idIn, const char *bodyIn) : id(idIn), body(bodyIn) - { - } - - MiniFunctionId id; - const char *body; -}; - -constexpr FunctionPair g_hlslFunctions[] = { - {{EOpMod, ParamType::Float1, ParamType::Float1}, - "float mod_emu(float x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n"}, - {{EOpMod, ParamType::Float2, ParamType::Float2}, - "float2 mod_emu(float2 x, float2 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n"}, - {{EOpMod, ParamType::Float2, ParamType::Float1}, - "float2 mod_emu(float2 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n"}, - {{EOpMod, ParamType::Float3, ParamType::Float3}, - "float3 mod_emu(float3 x, float3 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n"}, - {{EOpMod, ParamType::Float3, ParamType::Float1}, - "float3 mod_emu(float3 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n"}, - {{EOpMod, ParamType::Float4, ParamType::Float4}, - "float4 mod_emu(float4 x, float4 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n"}, - {{EOpMod, ParamType::Float4, ParamType::Float1}, - "float4 mod_emu(float4 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n"}, - {{EOpFrexp, ParamType::Float1, ParamType::Int1}, - "float frexp_emu(float x, out int exp)\n" - "{\n" - " float fexp;\n" - " float mantissa = frexp(abs(x), fexp) * sign(x);\n" - " exp = int(fexp);\n" - " return mantissa;\n" - "}\n"}, - {{EOpFrexp, ParamType::Float2, ParamType::Int2}, - "float2 frexp_emu(float2 x, out int2 exp)\n" - "{\n" - " float2 fexp;\n" - " float2 mantissa = frexp(abs(x), fexp) * sign(x);\n" - " exp = int2(fexp);\n" - " return mantissa;\n" - "}\n"}, - {{EOpFrexp, ParamType::Float3, ParamType::Int3}, - "float3 frexp_emu(float3 x, out int3 exp)\n" - "{\n" - " float3 fexp;\n" - " float3 mantissa = frexp(abs(x), fexp) * sign(x);\n" - " exp = int3(fexp);\n" - " return mantissa;\n" - "}\n"}, - {{EOpFrexp, ParamType::Float4, ParamType::Int4}, - "float4 frexp_emu(float4 x, out int4 exp)\n" - "{\n" - " float4 fexp;\n" - " float4 mantissa = frexp(abs(x), fexp) * sign(x);\n" - " exp = int4(fexp);\n" - " return mantissa;\n" - "}\n"}, - {{EOpLdexp, ParamType::Float1, ParamType::Int1}, - "float ldexp_emu(float x, int exp)\n" - "{\n" - " return ldexp(x, float(exp));\n" - "}\n"}, - {{EOpLdexp, ParamType::Float2, ParamType::Int2}, - "float2 ldexp_emu(float2 x, int2 exp)\n" - "{\n" - " return ldexp(x, float2(exp));\n" - "}\n"}, - {{EOpLdexp, ParamType::Float3, ParamType::Int3}, - "float3 ldexp_emu(float3 x, int3 exp)\n" - "{\n" - " return ldexp(x, float3(exp));\n" - "}\n"}, - {{EOpLdexp, ParamType::Float4, ParamType::Int4}, - "float4 ldexp_emu(float4 x, int4 exp)\n" - "{\n" - " return ldexp(x, float4(exp));\n" - "}\n"}, - {{EOpFaceforward, ParamType::Float1, ParamType::Float1, ParamType::Float1}, - "float faceforward_emu(float N, float I, float Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n"}, - {{EOpFaceforward, ParamType::Float2, ParamType::Float2, ParamType::Float2}, - "float2 faceforward_emu(float2 N, float2 I, float2 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n"}, - {{EOpFaceforward, ParamType::Float3, ParamType::Float3, ParamType::Float3}, - "float3 faceforward_emu(float3 N, float3 I, float3 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n"}, - {{EOpFaceforward, ParamType::Float4, ParamType::Float4, ParamType::Float4}, - "float4 faceforward_emu(float4 N, float4 I, float4 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n"}, - {{EOpAtan, ParamType::Float1, ParamType::Float1}, - "float atan_emu(float y, float x)\n" - "{\n" - " if(x == 0 && y == 0) x = 1;\n" - " return atan2(y, x);\n" - "}\n"}, - {{EOpAtan, ParamType::Float2, ParamType::Float2}, - "float2 atan_emu(float2 y, float2 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n" - "}\n"}, - {{EOpAtan, ParamType::Float3, ParamType::Float3}, - "float3 atan_emu(float3 y, float3 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" - " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n" - "}\n"}, - {{EOpAtan, ParamType::Float4, ParamType::Float4}, - "float4 atan_emu(float4 y, float4 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" - " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n" - " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], \n" - " x[2]), atan2(y[3], x[3]));\n" - "}\n"}, - {{EOpAsinh, ParamType::Float1}, - "float asinh_emu(in float x)\n" - "{\n" - " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" - "}\n"}, - {{EOpAsinh, ParamType::Float2}, - "float2 asinh_emu(in float2 x)\n" - "{\n" - " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" - "}\n"}, - {{EOpAsinh, ParamType::Float3}, - "float3 asinh_emu(in float3 x)\n" - "{\n" - " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" - "}\n"}, - {{EOpAsinh, ParamType::Float4}, - "float4 asinh_emu(in float4 x)\n" - "{\n" - " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" - "}\n"}, - {{EOpAcosh, ParamType::Float1}, - "float acosh_emu(in float x)\n" - "{\n" - " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" - "}\n"}, - {{EOpAcosh, ParamType::Float2}, - "float2 acosh_emu(in float2 x)\n" - "{\n" - " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" - "}\n"}, - {{EOpAcosh, ParamType::Float3}, - "float3 acosh_emu(in float3 x)\n" - "{\n" - " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" - "}\n"}, - {{EOpAcosh, ParamType::Float4}, - "float4 acosh_emu(in float4 x)\n" - "{\n" - " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" - "}\n"}, - {{EOpAtanh, ParamType::Float1}, - "float atanh_emu(in float x)\n" - "{\n" - " return 0.5 * log((1.0 + x) / (1.0 - x));\n" - "}\n"}, - {{EOpAtanh, ParamType::Float2}, - "float2 atanh_emu(in float2 x)\n" - "{\n" - " return 0.5 * log((1.0 + x) / (1.0 - x));\n" - "}\n"}, - {{EOpAtanh, ParamType::Float3}, - "float3 atanh_emu(in float3 x)\n" - "{\n" - " return 0.5 * log((1.0 + x) / (1.0 - x));\n" - "}\n"}, - {{EOpAtanh, ParamType::Float4}, - "float4 atanh_emu(in float4 x)\n" - "{\n" - " return 0.5 * log((1.0 + x) / (1.0 - x));\n" - "}\n"}, - {{EOpRoundEven, ParamType::Float1}, - "float roundEven_emu(in float x)\n" - "{\n" - " return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n" - "}\n"}, - {{EOpRoundEven, ParamType::Float2}, - "float2 roundEven_emu(in float2 x)\n" - "{\n" - " float2 v;\n" - " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" - " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" - " return v;\n" - "}\n"}, - {{EOpRoundEven, ParamType::Float3}, - "float3 roundEven_emu(in float3 x)\n" - "{\n" - " float3 v;\n" - " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" - " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" - " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n" - " return v;\n" - "}\n"}, - {{EOpRoundEven, ParamType::Float4}, - "float4 roundEven_emu(in float4 x)\n" - "{\n" - " float4 v;\n" - " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" - " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" - " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n" - " v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n" - " return v;\n" - "}\n"}, - {{EOpPackSnorm2x16, ParamType::Float2}, - "int webgl_toSnorm16(in float x) {\n" - " return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n" - "}\n" - "uint packSnorm2x16_emu(in float2 v)\n" - "{\n" - " int x = webgl_toSnorm16(v.x);\n" - " int y = webgl_toSnorm16(v.y);\n" - " return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n" - "}\n"}, - {{EOpPackUnorm2x16, ParamType::Float2}, - "uint webgl_toUnorm16(in float x) {\n" - " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n" - "}\n" - "uint packUnorm2x16_emu(in float2 v)\n" - "{\n" - " uint x = webgl_toUnorm16(v.x);\n" - " uint y = webgl_toUnorm16(v.y);\n" - " return (y << 16) | x;\n" - "}\n"}, - {{EOpPackHalf2x16, ParamType::Float2}, - "uint packHalf2x16_emu(in float2 v)\n" - "{\n" - " uint x = f32tof16(v.x);\n" - " uint y = f32tof16(v.y);\n" - " return (y << 16) | x;\n" - "}\n"}, - {{EOpUnpackSnorm2x16, ParamType::Uint1}, - "float webgl_fromSnorm16(in uint x) {\n" - " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n" - " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n" - "}\n" - "float2 unpackSnorm2x16_emu(in uint u)\n" - "{\n" - " uint y = (u >> 16);\n" - " uint x = u;\n" - " return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));\n" - "}\n"}, - {{EOpUnpackUnorm2x16, ParamType::Uint1}, - "float webgl_fromUnorm16(in uint x) {\n" - " return float(x) / 65535.0;\n" - "}\n" - "float2 unpackUnorm2x16_emu(in uint u)\n" - "{\n" - " uint y = (u >> 16);\n" - " uint x = u & 0xffffu;\n" - " return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));\n" - "}\n"}, - {{EOpUnpackHalf2x16, ParamType::Uint1}, - "float2 unpackHalf2x16_emu(in uint u)\n" - "{\n" - " uint y = (u >> 16);\n" - " uint x = u & 0xffffu;\n" - " return float2(f16tof32(x), f16tof32(y));\n" - "}\n"}, - {{EOpPackSnorm4x8, ParamType::Float4}, - "int webgl_toSnorm8(in float x) {\n" - " return int(round(clamp(x, -1.0, 1.0) * 127.0));\n" - "}\n" - "uint packSnorm4x8_emu(in float4 v)\n" - "{\n" - " int x = webgl_toSnorm8(v.x);\n" - " int y = webgl_toSnorm8(v.y);\n" - " int z = webgl_toSnorm8(v.z);\n" - " int w = webgl_toSnorm8(v.w);\n" - " return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) \n" - " | ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);\n" - "}\n"}, - {{EOpPackUnorm4x8, ParamType::Float4}, - "uint webgl_toUnorm8(in float x) {\n" - " return uint(round(clamp(x, 0.0, 1.0) * 255.0));\n" - "}\n" - "uint packUnorm4x8_emu(in float4 v)\n" - "{\n" - " uint x = webgl_toUnorm8(v.x);\n" - " uint y = webgl_toUnorm8(v.y);\n" - " uint z = webgl_toUnorm8(v.z);\n" - " uint w = webgl_toUnorm8(v.w);\n" - " return (w << 24) | (z << 16) | (y << 8) | x;\n" - "}\n"}, - {{EOpUnpackSnorm4x8, ParamType::Uint1}, - "float webgl_fromSnorm8(in uint x) {\n" - " int xi = asint(x & 0x7fu) - asint(x & 0x80u);\n" - " return clamp(float(xi) / 127.0, -1.0, 1.0);\n" - "}\n" - "float4 unpackSnorm4x8_emu(in uint u)\n" - "{\n" - " uint w = (u >> 24);\n" - " uint z = (u >> 16);\n" - " uint y = (u >> 8);\n" - " uint x = u;\n" - " return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), \n" - " webgl_fromSnorm8(z), webgl_fromSnorm8(w));\n" - "}\n"}, - {{EOpUnpackUnorm4x8, ParamType::Uint1}, - "float webgl_fromUnorm8(in uint x) {\n" - " return float(x) / 255.0;\n" - "}\n" - "float4 unpackUnorm4x8_emu(in uint u)\n" - "{\n" - " uint w = (u >> 24) & 0xffu;\n" - " uint z = (u >> 16) & 0xffu;\n" - " uint y = (u >> 8) & 0xffu;\n" - " uint x = u & 0xffu;\n" - " return float4(webgl_fromUnorm8(x), webgl_fromUnorm8(y), \n" - " webgl_fromUnorm8(z), webgl_fromUnorm8(w));\n" - "}\n"}, - // The matrix resulting from outer product needs to be transposed - // (matrices are stored as transposed to simplify element access in HLSL). - // So the function should return transpose(c * r) where c is a column vector - // and r is a row vector. This can be simplified by using the following - // formula: - // transpose(c * r) = transpose(r) * transpose(c) - // transpose(r) and transpose(c) are in a sense free, since to get the - // transpose of r, we simply can build a column matrix out of the original - // vector instead of a row matrix. - {{EOpOuterProduct, ParamType::Float2, ParamType::Float2}, - "float2x2 outerProduct_emu(in float2 c, in float2 r)\n" - "{\n" - " return mul(float2x1(r), float1x2(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float3, ParamType::Float3}, - "float3x3 outerProduct_emu(in float3 c, in float3 r)\n" - "{\n" - " return mul(float3x1(r), float1x3(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float4, ParamType::Float4}, - "float4x4 outerProduct_emu(in float4 c, in float4 r)\n" - "{\n" - " return mul(float4x1(r), float1x4(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float3, ParamType::Float2}, - "float2x3 outerProduct_emu(in float3 c, in float2 r)\n" - "{\n" - " return mul(float2x1(r), float1x3(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float2, ParamType::Float3}, - "float3x2 outerProduct_emu(in float2 c, in float3 r)\n" - "{\n" - " return mul(float3x1(r), float1x2(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float4, ParamType::Float2}, - "float2x4 outerProduct_emu(in float4 c, in float2 r)\n" - "{\n" - " return mul(float2x1(r), float1x4(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float2, ParamType::Float4}, - "float4x2 outerProduct_emu(in float2 c, in float4 r)\n" - "{\n" - " return mul(float4x1(r), float1x2(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float4, ParamType::Float3}, - "float3x4 outerProduct_emu(in float4 c, in float3 r)\n" - "{\n" - " return mul(float3x1(r), float1x4(c));\n" - "}\n"}, - {{EOpOuterProduct, ParamType::Float3, ParamType::Float4}, - "float4x3 outerProduct_emu(in float3 c, in float4 r)\n" - "{\n" - " return mul(float4x1(r), float1x3(c));\n" - "}\n"}, - // Remember here that the parameter matrix is actually the transpose - // of the matrix that we're trying to invert, and the resulting matrix - // should also be the transpose of the inverse. - // When accessing the parameter matrix with m[a][b] it can be thought of so - // that a is the column and b is the row of the matrix that we're inverting. - // We calculate the inverse as the adjugate matrix divided by the - // determinant of the matrix being inverted. However, as the result needs - // to be transposed, we actually use of the transpose of the adjugate matrix - // which happens to be the cofactor matrix. That's stored in 'cof'. - // We don't need to care about divide-by-zero since results are undefined - // for singular or poorly-conditioned matrices. - {{EOpInverse, ParamType::Mat2}, - "float2x2 inverse_emu(in float2x2 m)\n" - "{\n" - " float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n" - " return cof / determinant(transpose(m));\n" - "}\n"}, - // cofAB is the cofactor for column A and row B. - {{EOpInverse, ParamType::Mat3}, - "float3x3 inverse_emu(in float3x3 m)\n" - "{\n" - " float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n" - " float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n" - " float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];\n" - " float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n" - " float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];\n" - " float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n" - " float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];\n" - " float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n" - " float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];\n" - " float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n" - " return cof / determinant(transpose(m));\n" - "}\n"}, - {{EOpInverse, ParamType::Mat4}, - "float4x4 inverse_emu(in float4x4 m)\n" - "{\n" - " float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * \n" - " m[1][2] * m[2][3]\n" - " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * \n" - " m[1][3];\n" - " float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * \n" - " m[1][2] * m[2][3]\n" - " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * \n" - " m[1][3]);\n" - " float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * \n" - " m[1][1] * m[2][3]\n" - " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * \n" - " m[1][3];\n" - " float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * \n" - " m[1][1] * m[2][2]\n" - " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * \n" - " m[1][2]);\n" - " float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * \n" - " m[0][2] * m[2][3]\n" - " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * \n" - " m[0][3]);\n" - " float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * \n" - " m[0][2] * m[2][3]\n" - " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * \n" - " m[0][3];\n" - " float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * \n" - " m[0][1] * m[2][3]\n" - " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * \n" - " m[0][3]);\n" - " float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * \n" - " m[0][1] * m[2][2]\n" - " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * \n" - " m[0][2];\n" - " float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * \n" - " m[0][2] * m[1][3]\n" - " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * \n" - " m[0][3];\n" - " float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * \n" - " m[0][2] * m[1][3]\n" - " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * \n" - " m[0][3]);\n" - " float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * \n" - " m[0][1] * m[1][3]\n" - " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * \n" - " m[0][3];\n" - " float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * \n" - " m[0][1] * m[1][2]\n" - " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * \n" - " m[0][2]);\n" - " float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * \n" - " m[0][2] * m[1][3]\n" - " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * \n" - " m[0][3]);\n" - " float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * \n" - " m[0][2] * m[1][3]\n" - " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * \n" - " m[0][3];\n" - " float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * \n" - " m[0][1] * m[1][3]\n" - " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * \n" - " m[0][3]);\n" - " float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * \n" - " m[0][1] * m[1][2]\n" - " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * \n" - " m[0][2];\n" - " float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,\n" - " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n" - " return cof / determinant(transpose(m));\n" - "}\n"}, - // Emulate ESSL3 variant of mix that takes last argument as boolean vector. - // genType mix(genType x, genType y, genBType a): Selects which vector each returned component - // comes from. For a component of 'a' that is false, the corresponding component of 'x' is - // returned. For a component of 'a' that is true, the corresponding component of 'y' is - // returned. - {{EOpMix, ParamType::Float1, ParamType::Float1, ParamType::Bool1}, - "float mix_emu(float x, float y, bool a)\n" - "{\n" - " return a ? y : x;\n" - "}\n"}, - {{EOpMix, ParamType::Float2, ParamType::Float2, ParamType::Bool2}, - "float2 mix_emu(float2 x, float2 y, bool2 a)\n" - "{\n" - " return a ? y : x;\n" - "}\n"}, - {{EOpMix, ParamType::Float3, ParamType::Float3, ParamType::Bool3}, - "float3 mix_emu(float3 x, float3 y, bool3 a)\n" - "{\n" - " return a ? y : x;\n" - "}\n"}, - {{EOpMix, ParamType::Float4, ParamType::Float4, ParamType::Bool4}, - "float4 mix_emu(float4 x, float4 y, bool4 a)\n" - "{\n" - " return a ? y : x;\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Uint1, ParamType::Int1, ParamType::Int1}, - "uint bitfieldExtract_emu(uint value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return 0u;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " return (value & mask) >> offset;\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Uint2, ParamType::Int1, ParamType::Int1}, - "uint2 bitfieldExtract_emu(uint2 value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return uint2(0u, 0u);\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " return (value & mask) >> offset;\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Uint3, ParamType::Int1, ParamType::Int1}, - "uint3 bitfieldExtract_emu(uint3 value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return uint3(0u, 0u, 0u);\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " return (value & mask) >> offset;\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Uint4, ParamType::Int1, ParamType::Int1}, - "uint4 bitfieldExtract_emu(uint4 value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return uint4(0u, 0u, 0u, 0u);\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " return (value & mask) >> offset;\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Int1, ParamType::Int1, ParamType::Int1}, - "int bitfieldExtract_emu(int value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return 0;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint resultUnsigned = (asuint(value) & mask) >> offset;\n" - " if (bits != 32 && (resultUnsigned & maskMsb) != 0)\n" - " {\n" - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n" - " resultUnsigned |= higherBitsMask;\n" - " }\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Int2, ParamType::Int1, ParamType::Int1}, - "int2 bitfieldExtract_emu(int2 value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return int2(0, 0);\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint2 resultUnsigned = (asuint(value) & mask) >> offset;\n" - " if (bits != 32)\n" - " {\n" - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n" - " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n" - " }\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Int3, ParamType::Int1, ParamType::Int1}, - "int3 bitfieldExtract_emu(int3 value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return int3(0, 0, 0);\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint3 resultUnsigned = (asuint(value) & mask) >> offset;\n" - " if (bits != 32)\n" - " {\n" - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n" - " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n" - " }\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpBitfieldExtract, ParamType::Int4, ParamType::Int1, ParamType::Int1}, - "int4 bitfieldExtract_emu(int4 value, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return int4(0, 0, 0, 0);\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint4 resultUnsigned = (asuint(value) & mask) >> offset;\n" - " if (bits != 32)\n" - " {\n" - " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n" - " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n" - " }\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Uint1, ParamType::Uint1, ParamType::Int1, ParamType::Int1}, - "uint bitfieldInsert_emu(uint base, uint insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " return (base & baseMask) | ((insert << offset) & insertMask);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Uint2, ParamType::Uint2, ParamType::Int1, ParamType::Int1}, - "uint2 bitfieldInsert_emu(uint2 base, uint2 insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " return (base & baseMask) | ((insert << offset) & insertMask);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Uint3, ParamType::Uint3, ParamType::Int1, ParamType::Int1}, - "uint3 bitfieldInsert_emu(uint3 base, uint3 insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " return (base & baseMask) | ((insert << offset) & insertMask);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Uint4, ParamType::Uint4, ParamType::Int1, ParamType::Int1}, - "uint4 bitfieldInsert_emu(uint4 base, uint4 insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " return (base & baseMask) | ((insert << offset) & insertMask);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Int1, ParamType::Int1, ParamType::Int1, ParamType::Int1}, - "int bitfieldInsert_emu(int base, int insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " uint resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n" - " insertMask);\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Int2, ParamType::Int2, ParamType::Int1, ParamType::Int1}, - "int2 bitfieldInsert_emu(int2 base, int2 insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " uint2 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n" - " insertMask);\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Int3, ParamType::Int3, ParamType::Int1, ParamType::Int1}, - "int3 bitfieldInsert_emu(int3 base, int3 insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " uint3 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n" - " insertMask);\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpBitfieldInsert, ParamType::Int4, ParamType::Int4, ParamType::Int1, ParamType::Int1}, - "int4 bitfieldInsert_emu(int4 base, int4 insert, int offset, int bits)\n" - "{\n" - " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" - " {\n" - " return base;\n" - " }\n" - " uint maskMsb = (1u << (bits - 1));\n" - " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n" - " uint baseMask = ~insertMask;\n" - " uint4 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n" - " insertMask);\n" - " return asint(resultUnsigned);\n" - "}\n"}, - {{EOpUaddCarry, ParamType::Uint1, ParamType::Uint1, ParamType::Uint1}, - "uint uaddCarry_emu(uint x, uint y, out uint carry)\n" - "{\n" - " carry = uint(x > (0xffffffffu - y));\n" - " return x + y;\n" - "}\n"}, - {{EOpUaddCarry, ParamType::Uint2, ParamType::Uint2, ParamType::Uint2}, - "uint2 uaddCarry_emu(uint2 x, uint2 y, out uint2 carry)\n" - "{\n" - " carry = uint2(x > (0xffffffffu - y));\n" - " return x + y;\n" - "}\n"}, - {{EOpUaddCarry, ParamType::Uint3, ParamType::Uint3, ParamType::Uint3}, - "uint3 uaddCarry_emu(uint3 x, uint3 y, out uint3 carry)\n" - "{\n" - " carry = uint3(x > (0xffffffffu - y));\n" - " return x + y;\n" - "}\n"}, - {{EOpUaddCarry, ParamType::Uint4, ParamType::Uint4, ParamType::Uint4}, - "uint4 uaddCarry_emu(uint4 x, uint4 y, out uint4 carry)\n" - "{\n" - " carry = uint4(x > (0xffffffffu - y));\n" - " return x + y;\n" - "}\n"}, - {{EOpUsubBorrow, ParamType::Uint1, ParamType::Uint1, ParamType::Uint1}, - "uint usubBorrow_emu(uint x, uint y, out uint borrow)\n" - "{\n" - " borrow = uint(x < y);\n" - " return x - y;\n" - "}\n"}, - {{EOpUsubBorrow, ParamType::Uint2, ParamType::Uint2, ParamType::Uint2}, - "uint2 usubBorrow_emu(uint2 x, uint2 y, out uint2 borrow)\n" - "{\n" - " borrow = uint2(x < y);\n" - " return x - y;\n" - "}\n"}, - {{EOpUsubBorrow, ParamType::Uint3, ParamType::Uint3, ParamType::Uint3}, - "uint3 usubBorrow_emu(uint3 x, uint3 y, out uint3 borrow)\n" - "{\n" - " borrow = uint3(x < y);\n" - " return x - y;\n" - "}\n"}, - {{EOpUsubBorrow, ParamType::Uint4, ParamType::Uint4, ParamType::Uint4}, - "uint4 usubBorrow_emu(uint4 x, uint4 y, out uint4 borrow)\n" - "{\n" - " borrow = uint4(x < y);\n" - " return x - y;\n" - "}\n"}, -}; -} // anonymous namespace - -const char *FindHLSLFunction(const FunctionId &functionID) -{ - for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index) - { - const auto &function = g_hlslFunctions[index]; - if (function.id == functionID) - { - return function.body; - } - } - - return nullptr; -} -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.h b/src/3rdparty/angle/src/compiler/translator/glslang.h deleted file mode 100644 index e54c31ba3e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/glslang.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_GLSLANG_H_ -#define COMPILER_TRANSLATOR_GLSLANG_H_ - -namespace sh -{ -class TParseContext; -} - -extern int glslang_initialize(sh::TParseContext *context); -extern int glslang_finalize(sh::TParseContext *context); - -extern int glslang_scan(size_t count, - const char *const string[], - const int length[], - sh::TParseContext *context); -extern int glslang_parse(sh::TParseContext *context); - -#endif // COMPILER_TRANSLATOR_GLSLANG_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.l b/src/3rdparty/angle/src/compiler/translator/glslang.l deleted file mode 100644 index 858ffd96bb..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/glslang.l +++ /dev/null @@ -1,697 +0,0 @@ -/* -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -This file contains the Lex specification for GLSL ES. -Based on ANSI C grammar, Lex specification: -http://www.lysator.liu.se/c/ANSI-C-grammar-l.html - -IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh, -WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). -*/ - -%top{ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// This file is auto-generated by generate_parser.sh. DO NOT EDIT! - -/* clang-format off */ - -// Ignore errors in auto-generated code. -#if defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wswitch-enum" -#elif defined(_MSC_VER) -#pragma warning(disable: 4005) -#pragma warning(disable: 4065) -#pragma warning(disable: 4189) -#pragma warning(disable: 4244) -#pragma warning(disable: 4505) -#pragma warning(disable: 4701) -#pragma warning(disable: 4702) -#endif -} - -%{ -#include "compiler/translator/glslang.h" -#include "compiler/translator/ParseContext.h" -#include "compiler/preprocessor/Token.h" -#include "compiler/translator/util.h" -#include "compiler/translator/length_limits.h" - -using namespace sh; - -#include "glslang_tab.h" - -/* windows only pragma */ -#ifdef _MSC_VER -#pragma warning(disable : 4102) -#endif - -// Workaround for flex using the register keyword, deprecated in C++11. -#ifdef __cplusplus -#if __cplusplus > 199711L -#define register -#endif -#endif - -#define YY_USER_ACTION \ - yylloc->first_file = yylloc->last_file = yycolumn; \ - yylloc->first_line = yylloc->last_line = yylineno; - -#define YY_INPUT(buf, result, max_size) \ - result = string_input(buf, max_size, yyscanner); - -static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner); -static int check_type(yyscan_t yyscanner); -static int reserved_word(yyscan_t yyscanner); -static int ES2_reserved_ES3_keyword(TParseContext *context, int token); -static int ES2_keyword_ES3_reserved(TParseContext *context, int token); -static int ES2_ident_ES3_keyword(TParseContext *context, int token); -static int ES2_ident_ES3_keyword_multiview_keyword(TParseContext *context, int token); -static int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token); -static int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token); -static int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token); -static int ES3_extension_keyword_else_ident(TParseContext *context, TExtension extension, int token); -static int uint_constant(TParseContext *context); -static int int_constant(TParseContext *context); -static int float_constant(yyscan_t yyscanner); -static int floatsuffix_check(TParseContext* context); -static int yuvcscstandardext_constant(TParseContext *context); -%} - -%option noyywrap nounput never-interactive -%option yylineno reentrant bison-bridge bison-locations -%option extra-type="TParseContext*" -%x FIELDS - -D [0-9] -L [a-zA-Z_] -H [a-fA-F0-9] -E [Ee][+-]?{D}+ -O [0-7] - -%% - -%{ - TParseContext* context = yyextra; -%} - -"invariant" { return INVARIANT; } -"highp" { return HIGH_PRECISION; } -"mediump" { return MEDIUM_PRECISION; } -"lowp" { return LOW_PRECISION; } -"precision" { return PRECISION; } - -"attribute" { return ES2_keyword_ES3_reserved(context, ATTRIBUTE); } -"const" { return CONST_QUAL; } -"uniform" { return UNIFORM; } -"buffer" { return ES2_and_ES3_ident_ES3_1_keyword(context, BUFFER); } -"varying" { return ES2_keyword_ES3_reserved(context, VARYING); } - -"break" { return BREAK; } -"continue" { return CONTINUE; } -"do" { return DO; } -"for" { return FOR; } -"while" { return WHILE; } - -"if" { return IF; } -"else" { return ELSE; } -"switch" { return ES2_reserved_ES3_keyword(context, SWITCH); } -"case" { return ES2_ident_ES3_keyword(context, CASE); } -"default" { return ES2_reserved_ES3_keyword(context, DEFAULT); } - -"centroid" { return ES2_ident_ES3_keyword(context, CENTROID); } -"flat" { return ES2_reserved_ES3_keyword(context, FLAT); } -"smooth" { return ES2_ident_ES3_keyword(context, SMOOTH); } - -"in" { return IN_QUAL; } -"out" { return OUT_QUAL; } -"inout" { return INOUT_QUAL; } -"shared" { return ES2_and_ES3_ident_ES3_1_keyword(context, SHARED); } - -"float" { return FLOAT_TYPE; } -"int" { return INT_TYPE; } -"uint" { return ES2_ident_ES3_keyword(context, UINT_TYPE); } -"void" { return VOID_TYPE; } -"bool" { return BOOL_TYPE; } -"true" { yylval->lex.b = true; return BOOLCONSTANT; } -"false" { yylval->lex.b = false; return BOOLCONSTANT; } - -"discard" { return DISCARD; } -"return" { return RETURN; } - -"mat2" { return MATRIX2; } -"mat3" { return MATRIX3; } -"mat4" { return MATRIX4; } - -"mat2x2" { return ES2_ident_ES3_keyword(context, MATRIX2); } -"mat3x3" { return ES2_ident_ES3_keyword(context, MATRIX3); } -"mat4x4" { return ES2_ident_ES3_keyword(context, MATRIX4); } - -"mat2x3" { return ES2_ident_ES3_keyword(context, MATRIX2x3); } -"mat3x2" { return ES2_ident_ES3_keyword(context, MATRIX3x2); } -"mat2x4" { return ES2_ident_ES3_keyword(context, MATRIX2x4); } -"mat4x2" { return ES2_ident_ES3_keyword(context, MATRIX4x2); } -"mat3x4" { return ES2_ident_ES3_keyword(context, MATRIX3x4); } -"mat4x3" { return ES2_ident_ES3_keyword(context, MATRIX4x3); } - -"vec2" { return VEC2; } -"vec3" { return VEC3; } -"vec4" { return VEC4; } -"ivec2" { return IVEC2; } -"ivec3" { return IVEC3; } -"ivec4" { return IVEC4; } -"bvec2" { return BVEC2; } -"bvec3" { return BVEC3; } -"bvec4" { return BVEC4; } -"uvec2" { return ES2_ident_ES3_keyword(context, UVEC2); } -"uvec3" { return ES2_ident_ES3_keyword(context, UVEC3); } -"uvec4" { return ES2_ident_ES3_keyword(context, UVEC4); } - -"sampler2D" { return SAMPLER2D; } -"samplerCube" { return SAMPLERCUBE; } -"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; } -"sampler3D" { return ES2_reserved_ES3_keyword(context, SAMPLER3D); } -"sampler3DRect" { return ES2_reserved_ES3_keyword(context, SAMPLER3DRECT); } -"sampler2DRect" { return SAMPLER2DRECT; } -"sampler2DArray" { return ES2_ident_ES3_keyword(context, SAMPLER2DARRAY); } -"sampler2DMS" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, SAMPLER2DMS); } -"isampler2D" { return ES2_ident_ES3_keyword(context, ISAMPLER2D); } -"isampler3D" { return ES2_ident_ES3_keyword(context, ISAMPLER3D); } -"isamplerCube" { return ES2_ident_ES3_keyword(context, ISAMPLERCUBE); } -"isampler2DArray" { return ES2_ident_ES3_keyword(context, ISAMPLER2DARRAY); } -"isampler2DMS" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, ISAMPLER2DMS); } -"usampler2D" { return ES2_ident_ES3_keyword(context, USAMPLER2D); } -"usampler3D" { return ES2_ident_ES3_keyword(context, USAMPLER3D); } -"usamplerCube" { return ES2_ident_ES3_keyword(context, USAMPLERCUBE); } -"usampler2DArray" { return ES2_ident_ES3_keyword(context, USAMPLER2DARRAY); } -"usampler2DMS" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, USAMPLER2DMS); } -"sampler2DShadow" { return ES2_reserved_ES3_keyword(context, SAMPLER2DSHADOW); } -"samplerCubeShadow" { return ES2_ident_ES3_keyword(context, SAMPLERCUBESHADOW); } -"sampler2DArrayShadow" { return ES2_ident_ES3_keyword(context, SAMPLER2DARRAYSHADOW); } -"__samplerExternal2DY2YEXT" { return ES3_extension_keyword_else_ident(context, TExtension::EXT_YUV_target, SAMPLEREXTERNAL2DY2YEXT); } - -"struct" { return STRUCT; } - -"layout" { return ES2_ident_ES3_keyword_multiview_keyword(context, LAYOUT); } - -"yuvCscStandardEXT" { return ES3_extension_keyword_else_ident(context, TExtension::EXT_YUV_target, YUVCSCSTANDARDEXT); } -"itu_601" { return yuvcscstandardext_constant(context); } -"itu_601_full_range" { return yuvcscstandardext_constant(context); } -"itu_709" { return yuvcscstandardext_constant(context); } - -"image2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2D); } -"iimage2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2D); } -"uimage2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2D); } -"image2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2DARRAY); } -"iimage2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2DARRAY); } -"uimage2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2DARRAY); } -"image3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE3D); } -"uimage3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE3D); } -"iimage3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE3D); } -"iimageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGECUBE); } -"uimageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGECUBE); } -"imageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGECUBE); } -"readonly" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, READONLY); } -"writeonly" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, WRITEONLY); } -"coherent" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, COHERENT); } -"restrict" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, RESTRICT); } -"volatile" { return ES2_and_ES3_reserved_ES3_1_keyword(context, VOLATILE); } -"atomic_uint" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, ATOMICUINT); } - - /* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */ -"resource" | -"noperspective" | -"patch" | -"sample" | -"subroutine" | -"common" | -"partition" | -"active" | - -"filter" | -"image1D" | -"iimage1D" | -"uimage1D" | -"image1DArray" | -"iimage1DArray" | -"uimage1DArray" | -"image1DShadow" | -"image2DShadow" | -"image1DArrayShadow" | -"image2DArrayShadow" | -"imageBuffer" | -"iimageBuffer" | -"uimageBuffer" | - -"sampler1DArray" | -"sampler1DArrayShadow" | -"isampler1D" | -"isampler1DArray" | -"usampler1D" | -"usampler1DArray" | -"isampler2DRect" | -"usampler2DRect" | -"samplerBuffer" | -"isamplerBuffer" | -"usamplerBuffer" | -"sampler2DMSArray" | -"isampler2DMSArray" | -"usampler2DMSArray" { - if (context->getShaderVersion() < 300) { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); - } - return reserved_word(yyscanner); -} - - /* Reserved keywords in GLSL ES 1.00 that are not reserved in GLSL ES 3.00 */ -"packed" { - if (context->getShaderVersion() >= 300) - { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); - } - - return reserved_word(yyscanner); -} - - /* Reserved keywords */ -"asm" | - -"class" | -"union" | -"enum" | -"typedef" | -"template" | -"this" | - -"goto" | - -"inline" | -"noinline" | -"public" | -"static" | -"extern" | -"external" | -"interface" | - -"long" | -"short" | -"double" | -"half" | -"fixed" | -"unsigned" | -"superp" | - -"input" | -"output" | - -"hvec2" | -"hvec3" | -"hvec4" | -"dvec2" | -"dvec3" | -"dvec4" | -"fvec2" | -"fvec3" | -"fvec4" | - -"sampler1D" | -"sampler1DShadow" | -"sampler2DRectShadow" | - -"sizeof" | -"cast" | - -"namespace" | -"using" { return reserved_word(yyscanner); } - -{L}({L}|{D})* { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); -} - -0[xX]{H}+ { return int_constant(context); } -0{O}+ { return int_constant(context); } -{D}+ { return int_constant(context); } - -0[xX]{H}+[uU] { return uint_constant(context); } -0{O}+[uU] { return uint_constant(context); } -{D}+[uU] { return uint_constant(context); } - -{D}+{E} { return float_constant(yyscanner); } -{D}+"."{D}*({E})? { return float_constant(yyscanner); } -"."{D}+({E})? { return float_constant(yyscanner); } - -{D}+{E}[fF] { return floatsuffix_check(context); } -{D}+"."{D}*({E})?[fF] { return floatsuffix_check(context); } -"."{D}+({E})?[fF] { return floatsuffix_check(context); } - -"+=" { return ADD_ASSIGN; } -"-=" { return SUB_ASSIGN; } -"*=" { return MUL_ASSIGN; } -"/=" { return DIV_ASSIGN; } -"%=" { return MOD_ASSIGN; } -"<<=" { return LEFT_ASSIGN; } -">>=" { return RIGHT_ASSIGN; } -"&=" { return AND_ASSIGN; } -"^=" { return XOR_ASSIGN; } -"|=" { return OR_ASSIGN; } - -"++" { return INC_OP; } -"--" { return DEC_OP; } -"&&" { return AND_OP; } -"||" { return OR_OP; } -"^^" { return XOR_OP; } -"<=" { return LE_OP; } -">=" { return GE_OP; } -"==" { return EQ_OP; } -"!=" { return NE_OP; } -"<<" { return LEFT_OP; } -">>" { return RIGHT_OP; } -";" { return SEMICOLON; } -("{"|"<%") { return LEFT_BRACE; } -("}"|"%>") { return RIGHT_BRACE; } -"," { return COMMA; } -":" { return COLON; } -"=" { return EQUAL; } -"(" { return LEFT_PAREN; } -")" { return RIGHT_PAREN; } -("["|"<:") { return LEFT_BRACKET; } -("]"|":>") { return RIGHT_BRACKET; } -"." { BEGIN(FIELDS); return DOT; } -"!" { return BANG; } -"-" { return DASH; } -"~" { return TILDE; } -"+" { return PLUS; } -"*" { return STAR; } -"/" { return SLASH; } -"%" { return PERCENT; } -"<" { return LEFT_ANGLE; } -">" { return RIGHT_ANGLE; } -"|" { return VERTICAL_BAR; } -"^" { return CARET; } -"&" { return AMPERSAND; } -"?" { return QUESTION; } - -<FIELDS>{L}({L}|{D})* { - BEGIN(INITIAL); - yylval->lex.string = NewPoolTString(yytext); - return FIELD_SELECTION; -} -<FIELDS>[ \t\v\f\r] {} -<FIELDS>. { - yyextra->error(*yylloc, "Illegal character at fieldname start", yytext); - return 0; -} - -[ \t\v\n\f\r] { } -<*><<EOF>> { yyterminate(); } -<*>. { assert(false); return 0; } - -%% - -yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) { - pp::Token token; - yyget_extra(yyscanner)->getPreprocessor().lex(&token); - yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size(); - if (len < max_size) - memcpy(buf, token.text.c_str(), len); - yyset_column(token.location.file, yyscanner); - yyset_lineno(token.location.line, yyscanner); - - if (len >= max_size) - YY_FATAL_ERROR("Input buffer overflow"); - else if (len > 0) - buf[len++] = ' '; - return len; -} - -int check_type(yyscan_t yyscanner) { - struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; - - int token = IDENTIFIER; - TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->getShaderVersion()); - if (symbol && symbol->isVariable()) { - TVariable* variable = static_cast<TVariable*>(symbol); - if (variable->isUserType()) { - token = TYPE_NAME; - } - } - yylval->lex.symbol = symbol; - return token; -} - -int reserved_word(yyscan_t yyscanner) { - struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; - - yyextra->error(*yylloc, "Illegal use of reserved word", yytext); - return 0; -} - -int ES2_reserved_ES3_keyword(TParseContext *context, int token) -{ - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - if (context->getShaderVersion() < 300) - { - return reserved_word(yyscanner); - } - - return token; -} - -int ES2_keyword_ES3_reserved(TParseContext *context, int token) -{ - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - if (context->getShaderVersion() >= 300) - { - return reserved_word(yyscanner); - } - - return token; -} - -int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - if (context->getShaderVersion() < 300) - { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); - } - else if (context->getShaderVersion() == 300) - { - return reserved_word(yyscanner); - } - - return token; -} - -int ES2_ident_ES3_keyword(TParseContext *context, int token) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name - if (context->getShaderVersion() < 300) - { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); - } - - return token; -} - -int ES2_ident_ES3_keyword_multiview_keyword(TParseContext *context, int token) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name - // except when multiview extension is enabled - if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview)) - { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); - } - - return token; -} - -int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token) -{ - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - if (context->getShaderVersion() < 310) - { - return reserved_word(yyscanner); - } - - return token; -} - -int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - // not a reserved word in GLSL ES 1.00 and GLSL ES 3.00, so could be used as an identifier/type name - if (context->getShaderVersion() < 310) - { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); - } - - return token; -} - -int ES3_extension_keyword_else_ident(TParseContext *context, TExtension extension, int token) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - // a reserved word in GLSL ES 3.00 with enabled extension, otherwise could be used as an identifier/type name - if (context->getShaderVersion() >= 300 && context->isExtensionEnabled(extension)) - { - return token; - } - - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); -} - -int uint_constant(TParseContext *context) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - - if (context->getShaderVersion() < 300) - { - context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext); - return 0; - } - - if (!atoi_clamp(yytext, &(yylval->lex.u))) - yyextra->error(*yylloc, "Integer overflow", yytext); - - return UINTCONSTANT; -} - -int floatsuffix_check(TParseContext* context) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - - if (context->getShaderVersion() < 300) - { - context->error(*yylloc, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext); - return 0; - } - - std::string text = yytext; - text.resize(text.size() - 1); - if (!strtof_clamp(text, &(yylval->lex.f))) - yyextra->warning(*yylloc, "Float overflow", yytext); - - return(FLOATCONSTANT); -} - -void yyerror(YYLTYPE* lloc, TParseContext* context, void *scanner, const char* reason) { - context->error(*lloc, reason, yyget_text(scanner)); -} - -int int_constant(TParseContext *context) { - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - - unsigned int u; - if (!atoi_clamp(yytext, &u)) - { - if (context->getShaderVersion() >= 300) - yyextra->error(*yylloc, "Integer overflow", yytext); - else - yyextra->warning(*yylloc, "Integer overflow", yytext); - } - yylval->lex.i = static_cast<int>(u); - return INTCONSTANT; -} - -int float_constant(yyscan_t yyscanner) { - struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; - - if (!strtof_clamp(yytext, &(yylval->lex.f))) - yyextra->warning(*yylloc, "Float overflow", yytext); - return FLOATCONSTANT; -} - -int yuvcscstandardext_constant(TParseContext *context) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - // a reserved word in GLSL ES 3.00 with enabled extension, otherwise could be used as an identifier/type name - if (context->getShaderVersion() >= 300 && context->isExtensionEnabled(TExtension::EXT_YUV_target)) - { - yylval->lex.string = NewPoolTString(yytext); - return YUVCSCSTANDARDEXTCONSTANT; - } - - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); -} - -int glslang_initialize(TParseContext* context) { - yyscan_t scanner = NULL; - if (yylex_init_extra(context, &scanner)) - return 1; - - context->setScanner(scanner); - return 0; -} - -int glslang_finalize(TParseContext* context) { - yyscan_t scanner = context->getScanner(); - if (scanner == NULL) return 0; - - context->setScanner(NULL); - yylex_destroy(scanner); - - return 0; -} - -int glslang_scan(size_t count, const char* const string[], const int length[], - TParseContext* context) { - yyrestart(NULL, context->getScanner()); - yyset_column(0, context->getScanner()); - yyset_lineno(1, context->getScanner()); - - // Initialize preprocessor. - pp::Preprocessor *preprocessor = &context->getPreprocessor(); - - if (!preprocessor->init(count, string, length)) - return 1; - - // Define extension macros. - const TExtensionBehavior& extBehavior = context->extensionBehavior(); - for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); - iter != extBehavior.end(); ++iter) { - preprocessor->predefineMacro(GetExtensionNameString(iter->first), 1); - } - if (context->getFragmentPrecisionHigh()) - preprocessor->predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1); - - preprocessor->setMaxTokenSize(sh::GetGlobalMaxTokenSize(context->getShaderSpec())); - - return 0; -} diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y deleted file mode 100644 index 3e506caac8..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/glslang.y +++ /dev/null @@ -1,1468 +0,0 @@ -/* -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -This file contains the Yacc grammar for GLSL ES. -Based on ANSI C Yacc grammar: -http://www.lysator.liu.se/c/ANSI-C-grammar-y.html - -IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh, -WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). -*/ - -%{ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// This file is auto-generated by generate_parser.sh. DO NOT EDIT! - -// clang-format off - -// Ignore errors in auto-generated code. -#if defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wswitch-enum" -#elif defined(_MSC_VER) -#pragma warning(disable: 4065) -#pragma warning(disable: 4189) -#pragma warning(disable: 4244) -#pragma warning(disable: 4505) -#pragma warning(disable: 4701) -#pragma warning(disable: 4702) -#endif - -#include "angle_gl.h" -#include "compiler/translator/Cache.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/ParseContext.h" -#include "GLSLANG/ShaderLang.h" - -#define YYENABLE_NLS 0 - -using namespace sh; - -%} -%expect 1 /* One shift reduce conflict because of if | else */ -%parse-param {TParseContext* context} -%param {void *scanner} -%define api.pure full -%locations - -%code requires { -#define YYLTYPE TSourceLoc -#define YYLTYPE_IS_DECLARED 1 -} - -%union { - struct { - union { - TString *string; - float f; - int i; - unsigned int u; - bool b; - }; - TSymbol* symbol; - } lex; - struct { - TOperator op; - union { - TIntermNode *intermNode; - TIntermNodePair nodePair; - TIntermFunctionCallOrMethod callOrMethodPair; - TIntermTyped *intermTypedNode; - TIntermAggregate *intermAggregate; - TIntermBlock *intermBlock; - TIntermDeclaration *intermDeclaration; - TIntermFunctionPrototype *intermFunctionPrototype; - TIntermSwitch *intermSwitch; - TIntermCase *intermCase; - }; - union { - TVector<unsigned int> *arraySizes; - TTypeSpecifierNonArray typeSpecifierNonArray; - TPublicType type; - TPrecision precision; - TLayoutQualifier layoutQualifier; - TQualifier qualifier; - TFunction *function; - TParameter param; - TField *field; - TFieldList *fieldList; - TQualifierWrapperBase *qualifierWrapper; - TTypeQualifierBuilder *typeQualifierBuilder; - }; - } interm; -} - -%{ -extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner); -extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, const char* reason); - -#define YYLLOC_DEFAULT(Current, Rhs, N) \ - do { \ - if (N) { \ - (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \ - (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ - (Current).last_file = YYRHSLOC(Rhs, N).last_file; \ - (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ - } \ - else { \ - (Current).first_file = YYRHSLOC(Rhs, 0).last_file; \ - (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \ - (Current).last_file = YYRHSLOC(Rhs, 0).last_file; \ - (Current).last_line = YYRHSLOC(Rhs, 0).last_line; \ - } \ - } while (0) - -#define VERTEX_ONLY(S, L) { \ - if (context->getShaderType() != GL_VERTEX_SHADER) { \ - context->error(L, " supported in vertex shaders only", S); \ - } \ -} - -#define COMPUTE_ONLY(S, L) { \ - if (context->getShaderType() != GL_COMPUTE_SHADER) { \ - context->error(L, " supported in compute shaders only", S); \ - } \ -} - -#define ES2_ONLY(S, L) { \ - if (context->getShaderVersion() != 100) { \ - context->error(L, " supported in GLSL ES 1.00 only", S); \ - } \ -} - -#define ES3_OR_NEWER(TOKEN, LINE, REASON) { \ - if (context->getShaderVersion() < 300) { \ - context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN); \ - } \ -} - -#define ES3_OR_NEWER_OR_MULTIVIEW(TOKEN, LINE, REASON) { \ - if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview)) { \ - context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN); \ - } \ -} - -#define ES3_1_ONLY(TOKEN, LINE, REASON) { \ - if (context->getShaderVersion() != 310) { \ - context->error(LINE, REASON " supported in GLSL ES 3.10 only", TOKEN); \ - } \ -} -%} - -%token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION -%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE UINT_TYPE -%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT -%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 UVEC2 UVEC3 UVEC4 -%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM BUFFER VARYING -%token <lex> MATRIX2x3 MATRIX3x2 MATRIX2x4 MATRIX4x2 MATRIX3x4 MATRIX4x3 -%token <lex> CENTROID FLAT SMOOTH -%token <lex> READONLY WRITEONLY COHERENT RESTRICT VOLATILE SHARED -%token <lex> STRUCT VOID_TYPE WHILE -%token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT SAMPLER2DARRAY -%token <lex> ISAMPLER2D ISAMPLER3D ISAMPLERCUBE ISAMPLER2DARRAY -%token <lex> USAMPLER2D USAMPLER3D USAMPLERCUBE USAMPLER2DARRAY -%token <lex> SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS -%token <lex> SAMPLER3D SAMPLER3DRECT SAMPLER2DSHADOW SAMPLERCUBESHADOW SAMPLER2DARRAYSHADOW -%token <lex> SAMPLEREXTERNAL2DY2YEXT -%token <lex> IMAGE2D IIMAGE2D UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY -%token <lex> IMAGECUBE IIMAGECUBE UIMAGECUBE -%token <lex> ATOMICUINT -%token <lex> LAYOUT -%token <lex> YUVCSCSTANDARDEXT YUVCSCSTANDARDEXTCONSTANT - -%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT -%token <lex> FIELD_SELECTION -%token <lex> LEFT_OP RIGHT_OP -%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP -%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN -%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN -%token <lex> SUB_ASSIGN - -%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT -%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT -%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION - -%type <lex> identifier -%type <interm.op> assignment_operator unary_operator -%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression -%type <interm.intermTypedNode> expression integer_expression assignment_expression -%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression -%type <interm.intermTypedNode> relational_expression equality_expression -%type <interm.intermTypedNode> conditional_expression constant_expression -%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression -%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression -%type <interm.intermTypedNode> function_call initializer - -%type <interm.intermNode> condition conditionopt -%type <interm.intermBlock> translation_unit -%type <interm.intermNode> function_definition statement simple_statement -%type <interm.intermBlock> statement_list compound_statement_with_scope compound_statement_no_new_scope -%type <interm.intermNode> declaration_statement selection_statement expression_statement -%type <interm.intermNode> declaration external_declaration -%type <interm.intermNode> for_init_statement -%type <interm.nodePair> selection_rest_statement for_rest_statement -%type <interm.intermSwitch> switch_statement -%type <interm.intermCase> case_label -%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope -%type <interm> single_declaration init_declarator_list - -%type <interm.param> parameter_declaration parameter_declarator parameter_type_specifier -%type <interm.layoutQualifier> layout_qualifier_id_list layout_qualifier_id - -// Note: array_specifier guaranteed to be non-null. -%type <interm.arraySizes> array_specifier - -%type <interm.type> fully_specified_type type_specifier - -%type <interm.precision> precision_qualifier -%type <interm.layoutQualifier> layout_qualifier -%type <interm.qualifier> interpolation_qualifier -%type <interm.qualifierWrapper> storage_qualifier single_type_qualifier invariant_qualifier -%type <interm.typeQualifierBuilder> type_qualifier - -%type <interm.typeSpecifierNonArray> type_specifier_nonarray struct_specifier -%type <interm.type> type_specifier_no_prec -%type <interm.field> struct_declarator -%type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list -%type <interm.function> function_header function_declarator function_identifier -%type <interm.function> function_header_with_parameters function_call_header -%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype -%type <interm> function_call_or_method - -%type <lex> enter_struct - -%start translation_unit -%% - -identifier - : IDENTIFIER - | TYPE_NAME - -variable_identifier - : IDENTIFIER { - // The symbol table search was done in the lexical phase - $$ = context->parseVariableIdentifier(@1, $1.string, $1.symbol); - - // don't delete $1.string, it's used by error recovery, and the pool - // pop will reclaim the memory - } - ; - -primary_expression - : variable_identifier { - $$ = $1; - } - | INTCONSTANT { - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray->setIConst($1.i); - $$ = context->addScalarLiteral(unionArray, @1); - } - | UINTCONSTANT { - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray->setUConst($1.u); - $$ = context->addScalarLiteral(unionArray, @1); - } - | FLOATCONSTANT { - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray->setFConst($1.f); - $$ = context->addScalarLiteral(unionArray, @1); - } - | BOOLCONSTANT { - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray->setBConst($1.b); - $$ = context->addScalarLiteral(unionArray, @1); - } - | YUVCSCSTANDARDEXTCONSTANT { - if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target)) - { - context->error(@1, "unsupported value", $1.string->c_str()); - } - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray->setYuvCscStandardEXTConst(getYuvCscStandardEXT($1.string->c_str())); - $$ = context->addScalarLiteral(unionArray, @1); - } - | LEFT_PAREN expression RIGHT_PAREN { - $$ = $2; - } - ; - -postfix_expression - : primary_expression { - $$ = $1; - } - | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET { - $$ = context->addIndexExpression($1, @2, $3); - } - | function_call { - $$ = $1; - } - | postfix_expression DOT FIELD_SELECTION { - $$ = context->addFieldSelectionExpression($1, @2, *$3.string, @3); - } - | postfix_expression INC_OP { - $$ = context->addUnaryMathLValue(EOpPostIncrement, $1, @2); - } - | postfix_expression DEC_OP { - $$ = context->addUnaryMathLValue(EOpPostDecrement, $1, @2); - } - ; - -integer_expression - : expression { - context->checkIsScalarInteger($1, "[]"); - $$ = $1; - } - ; - -function_call - : function_call_or_method { - $$ = context->addFunctionCallOrMethod($1.function, $1.callOrMethodPair.arguments, $1.callOrMethodPair.thisNode, @1); - } - ; - -function_call_or_method - : function_call_generic { - $$ = $1; - $$.callOrMethodPair.thisNode = nullptr; - } - | postfix_expression DOT function_call_generic { - ES3_OR_NEWER("", @3, "methods"); - $$ = $3; - $$.callOrMethodPair.thisNode = $1; - } - ; - -function_call_generic - : function_call_header_with_parameters RIGHT_PAREN { - $$ = $1; - } - | function_call_header_no_parameters RIGHT_PAREN { - $$ = $1; - } - ; - -function_call_header_no_parameters - : function_call_header VOID_TYPE { - $$.function = $1; - $$.callOrMethodPair.arguments = context->createEmptyArgumentsList(); - } - | function_call_header { - $$.function = $1; - $$.callOrMethodPair.arguments = context->createEmptyArgumentsList(); - } - ; - -function_call_header_with_parameters - : function_call_header assignment_expression { - $$.callOrMethodPair.arguments = context->createEmptyArgumentsList(); - $$.function = $1; - $$.callOrMethodPair.arguments->push_back($2); - } - | function_call_header_with_parameters COMMA assignment_expression { - $$.function = $1.function; - $$.callOrMethodPair.arguments->push_back($3); - } - ; - -function_call_header - : function_identifier LEFT_PAREN { - $$ = $1; - } - ; - -// Grammar Note: Constructors look like functions, but are recognized as types. - -function_identifier - : type_specifier_no_prec { - $$ = context->addConstructorFunc($1); - } - | IDENTIFIER { - $$ = context->addNonConstructorFunc($1.string, @1); - } - | FIELD_SELECTION { - $$ = context->addNonConstructorFunc($1.string, @1); - } - ; - -unary_expression - : postfix_expression { - $$ = $1; - } - | INC_OP unary_expression { - $$ = context->addUnaryMathLValue(EOpPreIncrement, $2, @1); - } - | DEC_OP unary_expression { - $$ = context->addUnaryMathLValue(EOpPreDecrement, $2, @1); - } - | unary_operator unary_expression { - $$ = context->addUnaryMath($1, $2, @1); - } - ; -// Grammar Note: No traditional style type casts. - -unary_operator - : PLUS { $$ = EOpPositive; } - | DASH { $$ = EOpNegative; } - | BANG { $$ = EOpLogicalNot; } - | TILDE { - ES3_OR_NEWER("~", @$, "bit-wise operator"); - $$ = EOpBitwiseNot; - } - ; -// Grammar Note: No '*' or '&' unary ops. Pointers are not supported. - -multiplicative_expression - : unary_expression { $$ = $1; } - | multiplicative_expression STAR unary_expression { - $$ = context->addBinaryMath(EOpMul, $1, $3, @2); - } - | multiplicative_expression SLASH unary_expression { - $$ = context->addBinaryMath(EOpDiv, $1, $3, @2); - } - | multiplicative_expression PERCENT unary_expression { - ES3_OR_NEWER("%", @2, "integer modulus operator"); - $$ = context->addBinaryMath(EOpIMod, $1, $3, @2); - } - ; - -additive_expression - : multiplicative_expression { $$ = $1; } - | additive_expression PLUS multiplicative_expression { - $$ = context->addBinaryMath(EOpAdd, $1, $3, @2); - } - | additive_expression DASH multiplicative_expression { - $$ = context->addBinaryMath(EOpSub, $1, $3, @2); - } - ; - -shift_expression - : additive_expression { $$ = $1; } - | shift_expression LEFT_OP additive_expression { - ES3_OR_NEWER("<<", @2, "bit-wise operator"); - $$ = context->addBinaryMath(EOpBitShiftLeft, $1, $3, @2); - } - | shift_expression RIGHT_OP additive_expression { - ES3_OR_NEWER(">>", @2, "bit-wise operator"); - $$ = context->addBinaryMath(EOpBitShiftRight, $1, $3, @2); - } - ; - -relational_expression - : shift_expression { $$ = $1; } - | relational_expression LEFT_ANGLE shift_expression { - $$ = context->addBinaryMathBooleanResult(EOpLessThan, $1, $3, @2); - } - | relational_expression RIGHT_ANGLE shift_expression { - $$ = context->addBinaryMathBooleanResult(EOpGreaterThan, $1, $3, @2); - } - | relational_expression LE_OP shift_expression { - $$ = context->addBinaryMathBooleanResult(EOpLessThanEqual, $1, $3, @2); - } - | relational_expression GE_OP shift_expression { - $$ = context->addBinaryMathBooleanResult(EOpGreaterThanEqual, $1, $3, @2); - } - ; - -equality_expression - : relational_expression { $$ = $1; } - | equality_expression EQ_OP relational_expression { - $$ = context->addBinaryMathBooleanResult(EOpEqual, $1, $3, @2); - } - | equality_expression NE_OP relational_expression { - $$ = context->addBinaryMathBooleanResult(EOpNotEqual, $1, $3, @2); - } - ; - -and_expression - : equality_expression { $$ = $1; } - | and_expression AMPERSAND equality_expression { - ES3_OR_NEWER("&", @2, "bit-wise operator"); - $$ = context->addBinaryMath(EOpBitwiseAnd, $1, $3, @2); - } - ; - -exclusive_or_expression - : and_expression { $$ = $1; } - | exclusive_or_expression CARET and_expression { - ES3_OR_NEWER("^", @2, "bit-wise operator"); - $$ = context->addBinaryMath(EOpBitwiseXor, $1, $3, @2); - } - ; - -inclusive_or_expression - : exclusive_or_expression { $$ = $1; } - | inclusive_or_expression VERTICAL_BAR exclusive_or_expression { - ES3_OR_NEWER("|", @2, "bit-wise operator"); - $$ = context->addBinaryMath(EOpBitwiseOr, $1, $3, @2); - } - ; - -logical_and_expression - : inclusive_or_expression { $$ = $1; } - | logical_and_expression AND_OP inclusive_or_expression { - $$ = context->addBinaryMathBooleanResult(EOpLogicalAnd, $1, $3, @2); - } - ; - -logical_xor_expression - : logical_and_expression { $$ = $1; } - | logical_xor_expression XOR_OP logical_and_expression { - $$ = context->addBinaryMathBooleanResult(EOpLogicalXor, $1, $3, @2); - } - ; - -logical_or_expression - : logical_xor_expression { $$ = $1; } - | logical_or_expression OR_OP logical_xor_expression { - $$ = context->addBinaryMathBooleanResult(EOpLogicalOr, $1, $3, @2); - } - ; - -conditional_expression - : logical_or_expression { $$ = $1; } - | logical_or_expression QUESTION expression COLON assignment_expression { - $$ = context->addTernarySelection($1, $3, $5, @2); - } - ; - -assignment_expression - : conditional_expression { $$ = $1; } - | unary_expression assignment_operator assignment_expression { - $$ = context->addAssign($2, $1, $3, @2); - } - ; - -assignment_operator - : EQUAL { $$ = EOpAssign; } - | MUL_ASSIGN { $$ = EOpMulAssign; } - | DIV_ASSIGN { $$ = EOpDivAssign; } - | MOD_ASSIGN { - ES3_OR_NEWER("%=", @$, "integer modulus operator"); - $$ = EOpIModAssign; - } - | ADD_ASSIGN { $$ = EOpAddAssign; } - | SUB_ASSIGN { $$ = EOpSubAssign; } - | LEFT_ASSIGN { - ES3_OR_NEWER("<<=", @$, "bit-wise operator"); - $$ = EOpBitShiftLeftAssign; - } - | RIGHT_ASSIGN { - ES3_OR_NEWER(">>=", @$, "bit-wise operator"); - $$ = EOpBitShiftRightAssign; - } - | AND_ASSIGN { - ES3_OR_NEWER("&=", @$, "bit-wise operator"); - $$ = EOpBitwiseAndAssign; - } - | XOR_ASSIGN { - ES3_OR_NEWER("^=", @$, "bit-wise operator"); - $$ = EOpBitwiseXorAssign; - } - | OR_ASSIGN { - ES3_OR_NEWER("|=", @$, "bit-wise operator"); - $$ = EOpBitwiseOrAssign; - } - ; - -expression - : assignment_expression { - $$ = $1; - } - | expression COMMA assignment_expression { - $$ = context->addComma($1, $3, @2); - } - ; - -constant_expression - : conditional_expression { - context->checkIsConst($1); - $$ = $1; - } - ; - -enter_struct - : IDENTIFIER LEFT_BRACE { - context->enterStructDeclaration(@1, *$1.string); - $$ = $1; - } - ; - -declaration - : function_prototype SEMICOLON { - $$ = context->addFunctionPrototypeDeclaration(*($1.function), @1); - } - | init_declarator_list SEMICOLON { - $$ = $1.intermDeclaration; - } - | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { - context->parseDefaultPrecisionQualifier($2, $3, @1); - $$ = nullptr; - } - | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE SEMICOLON { - ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks"); - $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, NULL, @$, NULL, @$); - } - | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON { - ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks"); - $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, $5.string, @5, NULL, @$); - } - | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET SEMICOLON { - ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks"); - $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, $5.string, @5, $7, @6); - } - | type_qualifier SEMICOLON { - context->parseGlobalLayoutQualifier(*$1); - $$ = nullptr; - } - | type_qualifier IDENTIFIER SEMICOLON // e.g. to qualify an existing variable as invariant - { - $$ = context->parseInvariantDeclaration(*$1, @2, $2.string, $2.symbol); - } - ; - -function_prototype - : function_declarator RIGHT_PAREN { - $$.function = context->parseFunctionDeclarator(@2, $1); - context->exitFunctionDeclaration(); - } - ; - -function_declarator - : function_header { - $$ = $1; - } - | function_header_with_parameters { - $$ = $1; - } - ; - - -function_header_with_parameters - : function_header parameter_declaration { - // Add the parameter - $$ = $1; - if ($2.type->getBasicType() != EbtVoid) - { - $1->addParameter($2.turnToConst()); - } - } - | function_header_with_parameters COMMA parameter_declaration { - $$ = $1; - // Only first parameter of one-parameter functions can be void - // The check for named parameters not being void is done in parameter_declarator - if ($3.type->getBasicType() == EbtVoid) - { - // This parameter > first is void - context->error(@2, "cannot be a parameter type except for '(void)'", "void"); - } - else - { - $1->addParameter($3.turnToConst()); - } - } - ; - -function_header - : fully_specified_type IDENTIFIER LEFT_PAREN { - $$ = context->parseFunctionHeader($1, $2.string, @2); - - context->symbolTable.push(); - context->enterFunctionDeclaration(); - } - ; - -parameter_declarator - // Type + name - : type_specifier identifier { - $$ = context->parseParameterDeclarator($1, $2.string, @2); - } - | type_specifier identifier array_specifier { - $$ = context->parseParameterArrayDeclarator($2.string, @2, *($3), @3, &$1); - } - ; - -parameter_declaration - : type_qualifier parameter_declarator { - $$ = $2; - context->checkIsParameterQualifierValid(@2, *$1, $2.type); - } - | parameter_declarator { - $$ = $1; - $$.type->setQualifier(EvqIn); - } - | type_qualifier parameter_type_specifier { - $$ = $2; - context->checkIsParameterQualifierValid(@2, *$1, $2.type); - } - | parameter_type_specifier { - $$ = $1; - $$.type->setQualifier(EvqIn); - } - ; - -parameter_type_specifier - : type_specifier { - TParameter param = { 0, new TType($1) }; - $$ = param; - } - ; - -init_declarator_list - : single_declaration { - $$ = $1; - } - | init_declarator_list COMMA identifier { - $$ = $1; - context->parseDeclarator($$.type, @3, *$3.string, $$.intermDeclaration); - } - | init_declarator_list COMMA identifier array_specifier { - $$ = $1; - context->parseArrayDeclarator($$.type, @3, *$3.string, @4, *($4), $$.intermDeclaration); - } - | init_declarator_list COMMA identifier array_specifier EQUAL initializer { - ES3_OR_NEWER("=", @5, "first-class arrays (array initializer)"); - $$ = $1; - context->parseArrayInitDeclarator($$.type, @3, *$3.string, @4, *($4), @5, $6, $$.intermDeclaration); - } - | init_declarator_list COMMA identifier EQUAL initializer { - $$ = $1; - context->parseInitDeclarator($$.type, @3, *$3.string, @4, $5, $$.intermDeclaration); - } - ; - -single_declaration - : fully_specified_type { - $$.type = $1; - $$.intermDeclaration = context->parseSingleDeclaration($$.type, @1, ""); - } - | fully_specified_type identifier { - $$.type = $1; - $$.intermDeclaration = context->parseSingleDeclaration($$.type, @2, *$2.string); - } - | fully_specified_type identifier array_specifier { - $$.type = $1; - $$.intermDeclaration = context->parseSingleArrayDeclaration($$.type, @2, *$2.string, @3, *($3)); - } - | fully_specified_type identifier array_specifier EQUAL initializer { - ES3_OR_NEWER("[]", @3, "first-class arrays (array initializer)"); - $$.type = $1; - $$.intermDeclaration = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, *($3), @4, $5); - } - | fully_specified_type identifier EQUAL initializer { - $$.type = $1; - $$.intermDeclaration = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4); - } - ; - -fully_specified_type - : type_specifier { - context->addFullySpecifiedType(&$1); - $$ = $1; - } - | type_qualifier type_specifier { - $$ = context->addFullySpecifiedType(*$1, $2); - } - ; - -interpolation_qualifier - : SMOOTH { - $$ = EvqSmooth; - } - | FLAT { - $$ = EvqFlat; - } - ; - -type_qualifier - : single_type_qualifier { - $$ = context->createTypeQualifierBuilder(@1); - $$->appendQualifier($1); - } - | type_qualifier single_type_qualifier { - $$ = $1; - $$->appendQualifier($2); - } - ; - -invariant_qualifier - : INVARIANT { - // empty - } - ; - -single_type_qualifier - : storage_qualifier { - context->checkLocalVariableConstStorageQualifier(*$1); - $$ = $1; - } - | layout_qualifier { - context->checkIsAtGlobalLevel(@1, "layout"); - $$ = new TLayoutQualifierWrapper($1, @1); - } - | precision_qualifier { - $$ = new TPrecisionQualifierWrapper($1, @1); - } - | interpolation_qualifier { - $$ = new TInterpolationQualifierWrapper($1, @1); - } - | invariant_qualifier { - context->checkIsAtGlobalLevel(@1, "invariant"); - $$ = new TInvariantQualifierWrapper(@1); - } - ; - - -storage_qualifier - : - ATTRIBUTE { - VERTEX_ONLY("attribute", @1); - ES2_ONLY("attribute", @1); - $$ = context->parseGlobalStorageQualifier(EvqAttribute, @1); - } - | VARYING { - ES2_ONLY("varying", @1); - $$ = context->parseVaryingQualifier(@1); - } - | CONST_QUAL { - $$ = new TStorageQualifierWrapper(EvqConst, @1); - } - | IN_QUAL { - $$ = context->parseInQualifier(@1); - } - | OUT_QUAL { - $$ = context->parseOutQualifier(@1); - } - | INOUT_QUAL { - $$ = context->parseInOutQualifier(@1); - } - | CENTROID { - ES3_OR_NEWER("centroid", @1, "storage qualifier"); - $$ = new TStorageQualifierWrapper(EvqCentroid, @1); - } - | UNIFORM { - $$ = context->parseGlobalStorageQualifier(EvqUniform, @1); - } - | BUFFER { - ES3_1_ONLY("buffer", @1, "storage qualifier"); - $$ = context->parseGlobalStorageQualifier(EvqBuffer, @1); - } - | READONLY { - $$ = new TMemoryQualifierWrapper(EvqReadOnly, @1); - } - | WRITEONLY { - $$ = new TMemoryQualifierWrapper(EvqWriteOnly, @1); - } - | COHERENT { - $$ = new TMemoryQualifierWrapper(EvqCoherent, @1); - } - | RESTRICT { - $$ = new TMemoryQualifierWrapper(EvqRestrict, @1); - } - | VOLATILE { - $$ = new TMemoryQualifierWrapper(EvqVolatile, @1); - } - | SHARED { - COMPUTE_ONLY("shared", @1); - $$ = context->parseGlobalStorageQualifier(EvqShared, @1); - } - ; - -type_specifier - : type_specifier_no_prec { - $$ = $1; - $$.precision = context->symbolTable.getDefaultPrecision($1.getBasicType()); - } - ; - -precision_qualifier - : HIGH_PRECISION { - $$ = EbpHigh; - } - | MEDIUM_PRECISION { - $$ = EbpMedium; - } - | LOW_PRECISION { - $$ = EbpLow; - } - ; - -layout_qualifier - : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN { - ES3_OR_NEWER_OR_MULTIVIEW("layout", @1, "qualifier"); - $$ = $3; - } - ; - -layout_qualifier_id_list - : layout_qualifier_id { - $$ = $1; - } - | layout_qualifier_id_list COMMA layout_qualifier_id { - $$ = context->joinLayoutQualifiers($1, $3, @3); - } - ; - -layout_qualifier_id - : IDENTIFIER { - $$ = context->parseLayoutQualifier(*$1.string, @1); - } - | IDENTIFIER EQUAL INTCONSTANT { - $$ = context->parseLayoutQualifier(*$1.string, @1, $3.i, @3); - } - | IDENTIFIER EQUAL UINTCONSTANT { - $$ = context->parseLayoutQualifier(*$1.string, @1, $3.i, @3); - } - | SHARED { - $$ = context->parseLayoutQualifier("shared", @1); - } - ; - -type_specifier_no_prec - : type_specifier_nonarray { - $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary)); - } - | type_specifier_nonarray array_specifier { - $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary)); - $$.setArraySizes($2); - } - ; - -array_specifier - : LEFT_BRACKET RIGHT_BRACKET { - ES3_OR_NEWER("[]", @1, "implicitly sized array"); - $$ = new TVector<unsigned int>(); - $$->push_back(0u); - } - | LEFT_BRACKET constant_expression RIGHT_BRACKET { - $$ = new TVector<unsigned int>(); - unsigned int size = context->checkIsValidArraySize(@1, $2); - // Make the type an array even if size check failed. - // This ensures useless error messages regarding a variable's non-arrayness won't follow. - $$->push_back(size); - } - | array_specifier LEFT_BRACKET RIGHT_BRACKET { - ES3_1_ONLY("[]", @2, "arrays of arrays"); - $$ = $1; - $$->insert($$->begin(), 0u); - } - | array_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET { - ES3_1_ONLY("[]", @2, "arrays of arrays"); - $$ = $1; - unsigned int size = context->checkIsValidArraySize(@2, $3); - // Make the type an array even if size check failed. - // This ensures useless error messages regarding a variable's non-arrayness won't follow. - $$->insert($$->begin(), size); - } - ; - -type_specifier_nonarray - : VOID_TYPE { - $$.initialize(EbtVoid, @1); - } - | FLOAT_TYPE { - $$.initialize(EbtFloat, @1); - } - | INT_TYPE { - $$.initialize(EbtInt, @1); - } - | UINT_TYPE { - $$.initialize(EbtUInt, @1); - } - | BOOL_TYPE { - $$.initialize(EbtBool, @1); - } - | VEC2 { - $$.initialize(EbtFloat, @1); - $$.setAggregate(2); - } - | VEC3 { - $$.initialize(EbtFloat, @1); - $$.setAggregate(3); - } - | VEC4 { - $$.initialize(EbtFloat, @1); - $$.setAggregate(4); - } - | BVEC2 { - $$.initialize(EbtBool, @1); - $$.setAggregate(2); - } - | BVEC3 { - $$.initialize(EbtBool, @1); - $$.setAggregate(3); - } - | BVEC4 { - $$.initialize(EbtBool, @1); - $$.setAggregate(4); - } - | IVEC2 { - $$.initialize(EbtInt, @1); - $$.setAggregate(2); - } - | IVEC3 { - $$.initialize(EbtInt, @1); - $$.setAggregate(3); - } - | IVEC4 { - $$.initialize(EbtInt, @1); - $$.setAggregate(4); - } - | UVEC2 { - $$.initialize(EbtUInt, @1); - $$.setAggregate(2); - } - | UVEC3 { - $$.initialize(EbtUInt, @1); - $$.setAggregate(3); - } - | UVEC4 { - $$.initialize(EbtUInt, @1); - $$.setAggregate(4); - } - | MATRIX2 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(2, 2); - } - | MATRIX3 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(3, 3); - } - | MATRIX4 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(4, 4); - } - | MATRIX2x3 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(2, 3); - } - | MATRIX3x2 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(3, 2); - } - | MATRIX2x4 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(2, 4); - } - | MATRIX4x2 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(4, 2); - } - | MATRIX3x4 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(3, 4); - } - | MATRIX4x3 { - $$.initialize(EbtFloat, @1); - $$.setMatrix(4, 3); - } - | YUVCSCSTANDARDEXT { - if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target)) - { - context->error(@1, "unsupported type", "yuvCscStandardEXT"); - } - $$.initialize(EbtYuvCscStandardEXT, @1); - } - | SAMPLER2D { - $$.initialize(EbtSampler2D, @1); - } - | SAMPLER3D { - $$.initialize(EbtSampler3D, @1); - } - | SAMPLERCUBE { - $$.initialize(EbtSamplerCube, @1); - } - | SAMPLER2DARRAY { - $$.initialize(EbtSampler2DArray, @1); - } - | SAMPLER2DMS { - $$.initialize(EbtSampler2DMS, @1); - } - | ISAMPLER2D { - $$.initialize(EbtISampler2D, @1); - } - | ISAMPLER3D { - $$.initialize(EbtISampler3D, @1); - } - | ISAMPLERCUBE { - $$.initialize(EbtISamplerCube, @1); - } - | ISAMPLER2DARRAY { - $$.initialize(EbtISampler2DArray, @1); - } - | ISAMPLER2DMS { - $$.initialize(EbtISampler2DMS, @1); - } - | USAMPLER2D { - $$.initialize(EbtUSampler2D, @1); - } - | USAMPLER3D { - $$.initialize(EbtUSampler3D, @1); - } - | USAMPLERCUBE { - $$.initialize(EbtUSamplerCube, @1); - } - | USAMPLER2DARRAY { - $$.initialize(EbtUSampler2DArray, @1); - } - | USAMPLER2DMS { - $$.initialize(EbtUSampler2DMS, @1); - } - | SAMPLER2DSHADOW { - $$.initialize(EbtSampler2DShadow, @1); - } - | SAMPLERCUBESHADOW { - $$.initialize(EbtSamplerCubeShadow, @1); - } - | SAMPLER2DARRAYSHADOW { - $$.initialize(EbtSampler2DArrayShadow, @1); - } - | SAMPLER_EXTERNAL_OES { - constexpr std::array<TExtension, 3u> extensions{ { TExtension::NV_EGL_stream_consumer_external, - TExtension::OES_EGL_image_external_essl3, - TExtension::OES_EGL_image_external } }; - if (!context->checkCanUseOneOfExtensions(@1, extensions)) - { - context->error(@1, "unsupported type", "samplerExternalOES"); - } - $$.initialize(EbtSamplerExternalOES, @1); - } - | SAMPLEREXTERNAL2DY2YEXT { - if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target)) - { - context->error(@1, "unsupported type", "__samplerExternal2DY2YEXT"); - } - $$.initialize(EbtSamplerExternal2DY2YEXT, @1); - } - | SAMPLER2DRECT { - if (!context->checkCanUseExtension(@1, TExtension::ARB_texture_rectangle)) - { - context->error(@1, "unsupported type", "sampler2DRect"); - } - $$.initialize(EbtSampler2DRect, @1); - } - | struct_specifier { - $$ = $1; - } - | IMAGE2D { - $$.initialize(EbtImage2D, @1); - } - | IIMAGE2D { - $$.initialize(EbtIImage2D, @1); - } - | UIMAGE2D { - $$.initialize(EbtUImage2D, @1); - } - | IMAGE3D { - $$.initialize(EbtImage3D, @1); - } - | IIMAGE3D { - $$.initialize(EbtIImage3D, @1); - } - | UIMAGE3D { - $$.initialize(EbtUImage3D, @1); - } - | IMAGE2DARRAY { - $$.initialize(EbtImage2DArray, @1); - } - | IIMAGE2DARRAY { - $$.initialize(EbtIImage2DArray, @1); - } - | UIMAGE2DARRAY { - $$.initialize(EbtUImage2DArray, @1); - } - | IMAGECUBE { - $$.initialize(EbtImageCube, @1); - } - | IIMAGECUBE { - $$.initialize(EbtIImageCube, @1); - } - | UIMAGECUBE { - $$.initialize(EbtUImageCube, @1); - } - | ATOMICUINT { - $$.initialize(EbtAtomicCounter, @1); - } - | TYPE_NAME { - // This is for user defined type names. The lexical phase looked up the type. - TType& structure = static_cast<TVariable*>($1.symbol)->getType(); - $$.initializeStruct(structure.getStruct(), false, @1); - } - ; - -struct_specifier - : STRUCT identifier LEFT_BRACE { context->enterStructDeclaration(@2, *$2.string); } struct_declaration_list RIGHT_BRACE { - $$ = context->addStructure(@1, @2, $2.string, $5); - } - | STRUCT LEFT_BRACE { context->enterStructDeclaration(@2, *$2.string); } struct_declaration_list RIGHT_BRACE { - $$ = context->addStructure(@1, @$, NewPoolTString(""), $4); - } - ; - -struct_declaration_list - : struct_declaration { - $$ = context->addStructFieldList($1, @1); - } - | struct_declaration_list struct_declaration { - $$ = context->combineStructFieldLists($1, $2, @2); - } - ; - -struct_declaration - : type_specifier struct_declarator_list SEMICOLON { - $$ = context->addStructDeclaratorList($1, $2); - } - | type_qualifier type_specifier struct_declarator_list SEMICOLON { - // ES3 Only, but errors should be handled elsewhere - $$ = context->addStructDeclaratorListWithQualifiers(*$1, &$2, $3); - } - ; - -struct_declarator_list - : struct_declarator { - $$ = NewPoolTFieldList(); - $$->push_back($1); - } - | struct_declarator_list COMMA struct_declarator { - $$->push_back($3); - } - ; - -struct_declarator - : identifier { - $$ = context->parseStructDeclarator($1.string, @1); - } - | identifier array_specifier { - $$ = context->parseStructArrayDeclarator($1.string, @1, *($2), @2); - } - ; - -initializer - : assignment_expression { $$ = $1; } - ; - -declaration_statement - : declaration { $$ = $1; } - ; - -statement - : compound_statement_with_scope { $$ = $1; } - | simple_statement { $$ = $1; } - ; - -// Grammar Note: Labeled statements for SWITCH only; 'goto' is not supported. - -simple_statement - : declaration_statement { $$ = $1; } - | expression_statement { $$ = $1; } - | selection_statement { $$ = $1; } - | switch_statement { $$ = $1; } - | case_label { $$ = $1; } - | iteration_statement { $$ = $1; } - | jump_statement { $$ = $1; } - ; - -compound_statement_with_scope - : LEFT_BRACE RIGHT_BRACE { - $$ = new TIntermBlock(); - $$->setLine(@$); - } - | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE { - $3->setLine(@$); - $$ = $3; - } - ; - -statement_no_new_scope - : compound_statement_no_new_scope { $$ = $1; } - | simple_statement { $$ = $1; } - ; - -statement_with_scope - : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; } - | { context->symbolTable.push(); } simple_statement { context->symbolTable.pop(); $$ = $2; } - ; - -compound_statement_no_new_scope - // Statement that doesn't create a new scope for iteration_statement, function definition (scope is created for parameters) - : LEFT_BRACE RIGHT_BRACE { - $$ = new TIntermBlock(); - $$->setLine(@$); - } - | LEFT_BRACE statement_list RIGHT_BRACE { - $2->setLine(@$); - $$ = $2; - } - ; - -statement_list - : statement { - $$ = new TIntermBlock(); - $$->appendStatement($1); - } - | statement_list statement { - $$ = $1; - $$->appendStatement($2); - } - ; - -expression_statement - : SEMICOLON { $$ = context->addEmptyStatement(@$); } - | expression SEMICOLON { $$ = $1; } - ; - -selection_statement - : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { - $$ = context->addIfElse($3, $5, @1); - } - ; - -selection_rest_statement - : statement_with_scope ELSE statement_with_scope { - $$.node1 = $1; - $$.node2 = $3; - } - | statement_with_scope { - $$.node1 = $1; - $$.node2 = nullptr; - } - ; - -// Note that we've diverged from the spec grammar here a bit for the sake of simplicity. -// We're reusing compound_statement_with_scope instead of having separate rules for switch. -switch_statement - : SWITCH LEFT_PAREN expression RIGHT_PAREN { context->incrSwitchNestingLevel(); } compound_statement_with_scope { - $$ = context->addSwitch($3, $6, @1); - context->decrSwitchNestingLevel(); - } - ; - -case_label - : CASE constant_expression COLON { - $$ = context->addCase($2, @1); - } - | DEFAULT COLON { - $$ = context->addDefault(@1); - } - ; - -condition - : expression { - $$ = $1; - context->checkIsScalarBool($1->getLine(), $1); - } - | fully_specified_type identifier EQUAL initializer { - $$ = context->addConditionInitializer($1, *$2.string, $4, @2); - } - ; - -iteration_statement - : WHILE LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(); } condition RIGHT_PAREN statement_no_new_scope { - context->symbolTable.pop(); - $$ = context->addLoop(ELoopWhile, 0, $4, 0, $6, @1); - context->decrLoopNestingLevel(); - } - | DO { context->incrLoopNestingLevel(); } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { - $$ = context->addLoop(ELoopDoWhile, 0, $6, 0, $3, @4); - context->decrLoopNestingLevel(); - } - | FOR LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(); } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { - context->symbolTable.pop(); - $$ = context->addLoop(ELoopFor, $4, $5.node1, reinterpret_cast<TIntermTyped*>($5.node2), $7, @1); - context->decrLoopNestingLevel(); - } - ; - -for_init_statement - : expression_statement { - $$ = $1; - } - | declaration_statement { - $$ = $1; - } - ; - -conditionopt - : condition { - $$ = $1; - } - | /* May be null */ { - $$ = nullptr; - } - ; - -for_rest_statement - : conditionopt SEMICOLON { - $$.node1 = $1; - $$.node2 = 0; - } - | conditionopt SEMICOLON expression { - $$.node1 = $1; - $$.node2 = $3; - } - ; - -jump_statement - : CONTINUE SEMICOLON { - $$ = context->addBranch(EOpContinue, @1); - } - | BREAK SEMICOLON { - $$ = context->addBranch(EOpBreak, @1); - } - | RETURN SEMICOLON { - $$ = context->addBranch(EOpReturn, @1); - } - | RETURN expression SEMICOLON { - $$ = context->addBranch(EOpReturn, $2, @1); - } - | DISCARD SEMICOLON { - $$ = context->addBranch(EOpKill, @1); - } - ; - -// Grammar Note: No 'goto'. Gotos are not supported. - -translation_unit - : external_declaration { - $$ = new TIntermBlock(); - $$->setLine(@$); - $$->appendStatement($1); - context->setTreeRoot($$); - } - | translation_unit external_declaration { - $$->appendStatement($2); - } - ; - -external_declaration - : function_definition { - $$ = $1; - } - | declaration { - $$ = $1; - } - ; - -function_definition - : function_prototype { - context->parseFunctionDefinitionHeader(@1, &($1.function), &($1.intermFunctionPrototype)); - } - compound_statement_no_new_scope { - $$ = context->addFunctionDefinition($1.intermFunctionPrototype, $3, @1); - } - ; - -%% - -int glslang_parse(TParseContext* context) { - return yyparse(context, context->getScanner()); -} diff --git a/src/3rdparty/angle/src/compiler/translator/length_limits.h b/src/3rdparty/angle/src/compiler/translator/length_limits.h deleted file mode 100644 index fcda639d71..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/length_limits.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2011-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// length_limits.h -// - -#ifndef COMPILER_TRANSLATOR_LENGTHLIMITS_H_ -#define COMPILER_TRANSLATOR_LENGTHLIMITS_H_ - -#include "GLSLANG/ShaderLang.h" - -// These constants are factored out from the rest of the headers to -// make it easier to reference them from the compiler sources. - -namespace sh -{ - -size_t GetGlobalMaxTokenSize(ShShaderSpec spec); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_LENGTHLIMITS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp deleted file mode 100644 index 9738370c47..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/util.cpp +++ /dev/null @@ -1,714 +0,0 @@ -// -// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/util.h" - -#include <limits> - -#include "common/utilities.h" -#include "compiler/preprocessor/numeric_lex.h" -#include "compiler/translator/SymbolTable.h" - -bool atoi_clamp(const char *str, unsigned int *value) -{ - bool success = pp::numeric_lex_int(str, value); - if (!success) - *value = std::numeric_limits<unsigned int>::max(); - return success; -} - -namespace sh -{ - -namespace -{ - -bool IsInterpolationIn(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqSmoothIn: - case EvqFlatIn: - case EvqCentroidIn: - return true; - default: - return false; - } -} - -} // anonymous namespace - -float NumericLexFloat32OutOfRangeToInfinity(const std::string &str) -{ - // Parses a decimal string using scientific notation into a floating point number. - // Out-of-range values are converted to infinity. Values that are too small to be - // represented are converted to zero. - - // The mantissa in decimal scientific notation. The magnitude of the mantissa integer does not - // matter. - unsigned int decimalMantissa = 0; - size_t i = 0; - bool decimalPointSeen = false; - bool nonZeroSeenInMantissa = false; - - // The exponent offset reflects the position of the decimal point. - int exponentOffset = -1; - while (i < str.length()) - { - const char c = str[i]; - if (c == 'e' || c == 'E') - { - break; - } - if (c == '.') - { - decimalPointSeen = true; - ++i; - continue; - } - - unsigned int digit = static_cast<unsigned int>(c - '0'); - ASSERT(digit < 10u); - if (digit != 0u) - { - nonZeroSeenInMantissa = true; - } - if (nonZeroSeenInMantissa) - { - // Add bits to the mantissa until space runs out in 32-bit int. This should be - // enough precision to make the resulting binary mantissa accurate to 1 ULP. - if (decimalMantissa <= (std::numeric_limits<unsigned int>::max() - 9u) / 10u) - { - decimalMantissa = decimalMantissa * 10u + digit; - } - if (!decimalPointSeen) - { - ++exponentOffset; - } - } - else if (decimalPointSeen) - { - --exponentOffset; - } - ++i; - } - if (decimalMantissa == 0) - { - return 0.0f; - } - int exponent = 0; - if (i < str.length()) - { - ASSERT(str[i] == 'e' || str[i] == 'E'); - ++i; - bool exponentOutOfRange = false; - bool negativeExponent = false; - if (str[i] == '-') - { - negativeExponent = true; - ++i; - } - else if (str[i] == '+') - { - ++i; - } - while (i < str.length()) - { - const char c = str[i]; - unsigned int digit = static_cast<unsigned int>(c - '0'); - ASSERT(digit < 10u); - if (exponent <= (std::numeric_limits<int>::max() - 9) / 10) - { - exponent = exponent * 10 + digit; - } - else - { - exponentOutOfRange = true; - } - ++i; - } - if (negativeExponent) - { - exponent = -exponent; - } - if (exponentOutOfRange) - { - if (negativeExponent) - { - return 0.0f; - } - else - { - return std::numeric_limits<float>::infinity(); - } - } - } - // Do the calculation in 64-bit to avoid overflow. - long long exponentLong = - static_cast<long long>(exponent) + static_cast<long long>(exponentOffset); - if (exponentLong > std::numeric_limits<float>::max_exponent10) - { - return std::numeric_limits<float>::infinity(); - } - else if (exponentLong < std::numeric_limits<float>::min_exponent10) - { - return 0.0f; - } - // The exponent is in range, so we need to actually evaluate the float. - exponent = static_cast<int>(exponentLong); - double value = decimalMantissa; - - // Calculate the exponent offset to normalize the mantissa. - int normalizationExponentOffset = 0; - while (decimalMantissa >= 10u) - { - --normalizationExponentOffset; - decimalMantissa /= 10u; - } - // Apply the exponent. - value *= std::pow(10.0, static_cast<double>(exponent + normalizationExponentOffset)); - if (value > static_cast<double>(std::numeric_limits<float>::max())) - { - return std::numeric_limits<float>::infinity(); - } - if (value < static_cast<double>(std::numeric_limits<float>::min())) - { - return 0.0f; - } - return static_cast<float>(value); -} - -bool strtof_clamp(const std::string &str, float *value) -{ - // Try the standard float parsing path first. - bool success = pp::numeric_lex_float(str, value); - - // If the standard path doesn't succeed, take the path that can handle the following corner - // cases: - // 1. The decimal mantissa is very small but the exponent is very large, putting the resulting - // number inside the float range. - // 2. The decimal mantissa is very large but the exponent is very small, putting the resulting - // number inside the float range. - // 3. The value is out-of-range and should be evaluated as infinity. - // 4. The value is too small and should be evaluated as zero. - // See ESSL 3.00.6 section 4.1.4 for the relevant specification. - if (!success) - *value = NumericLexFloat32OutOfRangeToInfinity(str); - return !gl::isInf(*value); -} - -GLenum GLVariableType(const TType &type) -{ - if (type.getBasicType() == EbtFloat) - { - if (type.isVector()) - { - switch (type.getNominalSize()) - { - case 2: - return GL_FLOAT_VEC2; - case 3: - return GL_FLOAT_VEC3; - case 4: - return GL_FLOAT_VEC4; - default: - UNREACHABLE(); - } - } - else if (type.isMatrix()) - { - switch (type.getCols()) - { - case 2: - switch (type.getRows()) - { - case 2: - return GL_FLOAT_MAT2; - case 3: - return GL_FLOAT_MAT2x3; - case 4: - return GL_FLOAT_MAT2x4; - default: - UNREACHABLE(); - } - - case 3: - switch (type.getRows()) - { - case 2: - return GL_FLOAT_MAT3x2; - case 3: - return GL_FLOAT_MAT3; - case 4: - return GL_FLOAT_MAT3x4; - default: - UNREACHABLE(); - } - - case 4: - switch (type.getRows()) - { - case 2: - return GL_FLOAT_MAT4x2; - case 3: - return GL_FLOAT_MAT4x3; - case 4: - return GL_FLOAT_MAT4; - default: - UNREACHABLE(); - } - - default: - UNREACHABLE(); - } - } - else - { - return GL_FLOAT; - } - } - else if (type.getBasicType() == EbtInt) - { - if (type.isVector()) - { - switch (type.getNominalSize()) - { - case 2: - return GL_INT_VEC2; - case 3: - return GL_INT_VEC3; - case 4: - return GL_INT_VEC4; - default: - UNREACHABLE(); - } - } - else - { - ASSERT(!type.isMatrix()); - return GL_INT; - } - } - else if (type.getBasicType() == EbtUInt) - { - if (type.isVector()) - { - switch (type.getNominalSize()) - { - case 2: - return GL_UNSIGNED_INT_VEC2; - case 3: - return GL_UNSIGNED_INT_VEC3; - case 4: - return GL_UNSIGNED_INT_VEC4; - default: - UNREACHABLE(); - } - } - else - { - ASSERT(!type.isMatrix()); - return GL_UNSIGNED_INT; - } - } - else if (type.getBasicType() == EbtBool) - { - if (type.isVector()) - { - switch (type.getNominalSize()) - { - case 2: - return GL_BOOL_VEC2; - case 3: - return GL_BOOL_VEC3; - case 4: - return GL_BOOL_VEC4; - default: - UNREACHABLE(); - } - } - else - { - ASSERT(!type.isMatrix()); - return GL_BOOL; - } - } - - switch (type.getBasicType()) - { - case EbtSampler2D: - return GL_SAMPLER_2D; - case EbtSampler3D: - return GL_SAMPLER_3D; - case EbtSamplerCube: - return GL_SAMPLER_CUBE; - case EbtSamplerExternalOES: - return GL_SAMPLER_EXTERNAL_OES; - case EbtSamplerExternal2DY2YEXT: - return GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT; - case EbtSampler2DRect: - return GL_SAMPLER_2D_RECT_ANGLE; - case EbtSampler2DArray: - return GL_SAMPLER_2D_ARRAY; - case EbtSampler2DMS: - return GL_SAMPLER_2D_MULTISAMPLE; - case EbtISampler2D: - return GL_INT_SAMPLER_2D; - case EbtISampler3D: - return GL_INT_SAMPLER_3D; - case EbtISamplerCube: - return GL_INT_SAMPLER_CUBE; - case EbtISampler2DArray: - return GL_INT_SAMPLER_2D_ARRAY; - case EbtISampler2DMS: - return GL_INT_SAMPLER_2D_MULTISAMPLE; - case EbtUSampler2D: - return GL_UNSIGNED_INT_SAMPLER_2D; - case EbtUSampler3D: - return GL_UNSIGNED_INT_SAMPLER_3D; - case EbtUSamplerCube: - return GL_UNSIGNED_INT_SAMPLER_CUBE; - case EbtUSampler2DArray: - return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY; - case EbtUSampler2DMS: - return GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE; - case EbtSampler2DShadow: - return GL_SAMPLER_2D_SHADOW; - case EbtSamplerCubeShadow: - return GL_SAMPLER_CUBE_SHADOW; - case EbtSampler2DArrayShadow: - return GL_SAMPLER_2D_ARRAY_SHADOW; - case EbtImage2D: - return GL_IMAGE_2D; - case EbtIImage2D: - return GL_INT_IMAGE_2D; - case EbtUImage2D: - return GL_UNSIGNED_INT_IMAGE_2D; - case EbtImage2DArray: - return GL_IMAGE_2D_ARRAY; - case EbtIImage2DArray: - return GL_INT_IMAGE_2D_ARRAY; - case EbtUImage2DArray: - return GL_UNSIGNED_INT_IMAGE_2D_ARRAY; - case EbtImage3D: - return GL_IMAGE_3D; - case EbtIImage3D: - return GL_INT_IMAGE_3D; - case EbtUImage3D: - return GL_UNSIGNED_INT_IMAGE_3D; - case EbtImageCube: - return GL_IMAGE_CUBE; - case EbtIImageCube: - return GL_INT_IMAGE_CUBE; - case EbtUImageCube: - return GL_UNSIGNED_INT_IMAGE_CUBE; - case EbtAtomicCounter: - return GL_UNSIGNED_INT_ATOMIC_COUNTER; - default: - UNREACHABLE(); - } - - return GL_NONE; -} - -GLenum GLVariablePrecision(const TType &type) -{ - if (type.getBasicType() == EbtFloat) - { - switch (type.getPrecision()) - { - case EbpHigh: - return GL_HIGH_FLOAT; - case EbpMedium: - return GL_MEDIUM_FLOAT; - case EbpLow: - return GL_LOW_FLOAT; - case EbpUndefined: - // Should be defined as the default precision by the parser - default: - UNREACHABLE(); - } - } - else if (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt) - { - switch (type.getPrecision()) - { - case EbpHigh: - return GL_HIGH_INT; - case EbpMedium: - return GL_MEDIUM_INT; - case EbpLow: - return GL_LOW_INT; - case EbpUndefined: - // Should be defined as the default precision by the parser - default: - UNREACHABLE(); - } - } - - // Other types (boolean, sampler) don't have a precision - return GL_NONE; -} - -TString ArrayString(const TType &type) -{ - TStringStream arrayString; - if (!type.isArray()) - return arrayString.str(); - - const TVector<unsigned int> &arraySizes = *type.getArraySizes(); - for (auto arraySizeIter = arraySizes.rbegin(); arraySizeIter != arraySizes.rend(); - ++arraySizeIter) - { - arrayString << "["; - if (*arraySizeIter > 0) - { - arrayString << (*arraySizeIter); - } - arrayString << "]"; - } - return arrayString.str(); -} - -TString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap) -{ - if (type.getBasicType() == EbtStruct) - return HashName(TName(type.getStruct()->name()), hashFunction, nameMap); - else - return type.getBuiltInTypeNameString(); -} - -bool IsVaryingOut(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqVaryingOut: - case EvqSmoothOut: - case EvqFlatOut: - case EvqCentroidOut: - case EvqVertexOut: - case EvqGeometryOut: - return true; - - default: - break; - } - - return false; -} - -bool IsVaryingIn(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqVaryingIn: - case EvqSmoothIn: - case EvqFlatIn: - case EvqCentroidIn: - case EvqFragmentIn: - case EvqGeometryIn: - return true; - - default: - break; - } - - return false; -} - -bool IsVarying(TQualifier qualifier) -{ - return IsVaryingIn(qualifier) || IsVaryingOut(qualifier); -} - -bool IsGeometryShaderInput(GLenum shaderType, TQualifier qualifier) -{ - return (qualifier == EvqGeometryIn) || - ((shaderType == GL_GEOMETRY_SHADER_OES) && IsInterpolationIn(qualifier)); -} - -InterpolationType GetInterpolationType(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqFlatIn: - case EvqFlatOut: - return INTERPOLATION_FLAT; - - case EvqSmoothIn: - case EvqSmoothOut: - case EvqVertexOut: - case EvqFragmentIn: - case EvqVaryingIn: - case EvqVaryingOut: - case EvqGeometryIn: - case EvqGeometryOut: - return INTERPOLATION_SMOOTH; - - case EvqCentroidIn: - case EvqCentroidOut: - return INTERPOLATION_CENTROID; - - default: - UNREACHABLE(); - return INTERPOLATION_SMOOTH; - } -} - -TType GetShaderVariableBasicType(const sh::ShaderVariable &var) -{ - switch (var.type) - { - case GL_BOOL: - return TType(EbtBool); - case GL_BOOL_VEC2: - return TType(EbtBool, 2); - case GL_BOOL_VEC3: - return TType(EbtBool, 3); - case GL_BOOL_VEC4: - return TType(EbtBool, 4); - case GL_FLOAT: - return TType(EbtFloat); - case GL_FLOAT_VEC2: - return TType(EbtFloat, 2); - case GL_FLOAT_VEC3: - return TType(EbtFloat, 3); - case GL_FLOAT_VEC4: - return TType(EbtFloat, 4); - case GL_FLOAT_MAT2: - return TType(EbtFloat, 2, 2); - case GL_FLOAT_MAT3: - return TType(EbtFloat, 3, 3); - case GL_FLOAT_MAT4: - return TType(EbtFloat, 4, 4); - case GL_FLOAT_MAT2x3: - return TType(EbtFloat, 2, 3); - case GL_FLOAT_MAT2x4: - return TType(EbtFloat, 2, 4); - case GL_FLOAT_MAT3x2: - return TType(EbtFloat, 3, 2); - case GL_FLOAT_MAT3x4: - return TType(EbtFloat, 3, 4); - case GL_FLOAT_MAT4x2: - return TType(EbtFloat, 4, 2); - case GL_FLOAT_MAT4x3: - return TType(EbtFloat, 4, 3); - case GL_INT: - return TType(EbtInt); - case GL_INT_VEC2: - return TType(EbtInt, 2); - case GL_INT_VEC3: - return TType(EbtInt, 3); - case GL_INT_VEC4: - return TType(EbtInt, 4); - case GL_UNSIGNED_INT: - return TType(EbtUInt); - case GL_UNSIGNED_INT_VEC2: - return TType(EbtUInt, 2); - case GL_UNSIGNED_INT_VEC3: - return TType(EbtUInt, 3); - case GL_UNSIGNED_INT_VEC4: - return TType(EbtUInt, 4); - default: - UNREACHABLE(); - return TType(); - } -} - -// GLSL ES 1.0.17 4.6.1 The Invariant Qualifier -bool CanBeInvariantESSL1(TQualifier qualifier) -{ - return IsVaryingIn(qualifier) || IsVaryingOut(qualifier) || - IsBuiltinOutputVariable(qualifier) || - (IsBuiltinFragmentInputVariable(qualifier) && qualifier != EvqFrontFacing); -} - -// GLSL ES 3.00 Revision 6, 4.6.1 The Invariant Qualifier -// GLSL ES 3.10 Revision 4, 4.8.1 The Invariant Qualifier -bool CanBeInvariantESSL3OrGreater(TQualifier qualifier) -{ - return IsVaryingOut(qualifier) || qualifier == EvqFragmentOut || - IsBuiltinOutputVariable(qualifier); -} - -bool IsBuiltinOutputVariable(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqPosition: - case EvqPointSize: - case EvqFragDepth: - case EvqFragDepthEXT: - case EvqFragColor: - case EvqSecondaryFragColorEXT: - case EvqFragData: - case EvqSecondaryFragDataEXT: - return true; - default: - break; - } - return false; -} - -bool IsBuiltinFragmentInputVariable(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqFragCoord: - case EvqPointCoord: - case EvqFrontFacing: - return true; - default: - break; - } - return false; -} - -bool IsOutputESSL(ShShaderOutput output) -{ - return output == SH_ESSL_OUTPUT; -} - -bool IsOutputGLSL(ShShaderOutput output) -{ - switch (output) - { - case SH_GLSL_130_OUTPUT: - case SH_GLSL_140_OUTPUT: - case SH_GLSL_150_CORE_OUTPUT: - case SH_GLSL_330_CORE_OUTPUT: - case SH_GLSL_400_CORE_OUTPUT: - case SH_GLSL_410_CORE_OUTPUT: - case SH_GLSL_420_CORE_OUTPUT: - case SH_GLSL_430_CORE_OUTPUT: - case SH_GLSL_440_CORE_OUTPUT: - case SH_GLSL_450_CORE_OUTPUT: - case SH_GLSL_COMPATIBILITY_OUTPUT: - return true; - default: - break; - } - return false; -} -bool IsOutputHLSL(ShShaderOutput output) -{ - switch (output) - { - case SH_HLSL_3_0_OUTPUT: - case SH_HLSL_4_1_OUTPUT: - case SH_HLSL_4_0_FL9_3_OUTPUT: - return true; - default: - break; - } - return false; -} -bool IsOutputVulkan(ShShaderOutput output) -{ - return output == SH_GLSL_VULKAN_OUTPUT; -} - -} // namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h deleted file mode 100644 index 6d6dc95b3b..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/util.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_UTIL_H_ -#define COMPILER_TRANSLATOR_UTIL_H_ - -#include <stack> - -#include "angle_gl.h" -#include <GLSLANG/ShaderLang.h> - -#include "compiler/translator/HashNames.h" -#include "compiler/translator/Operator.h" -#include "compiler/translator/Types.h" - -// If overflow happens, clamp the value to UINT_MIN or UINT_MAX. -// Return false if overflow happens. -bool atoi_clamp(const char *str, unsigned int *value); - -namespace sh -{ -class TSymbolTable; - -float NumericLexFloat32OutOfRangeToInfinity(const std::string &str); - -// strtof_clamp is like strtof but -// 1. it forces C locale, i.e. forcing '.' as decimal point. -// 2. it sets the value to infinity if overflow happens. -// 3. str should be guaranteed to be in the valid format for a floating point number as defined -// by the grammar in the ESSL 3.00.6 spec section 4.1.4. -// Return false if overflow happens. -bool strtof_clamp(const std::string &str, float *value); - -GLenum GLVariableType(const TType &type); -GLenum GLVariablePrecision(const TType &type); -bool IsVaryingIn(TQualifier qualifier); -bool IsVaryingOut(TQualifier qualifier); -bool IsVarying(TQualifier qualifier); -bool IsGeometryShaderInput(GLenum shaderType, TQualifier qualifier); -InterpolationType GetInterpolationType(TQualifier qualifier); - -// Returns array brackets including size with outermost array size first, as specified in GLSL ES -// 3.10 section 4.1.9. -TString ArrayString(const TType &type); - -TString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap); - -TType GetShaderVariableBasicType(const sh::ShaderVariable &var); - -bool IsBuiltinOutputVariable(TQualifier qualifier); -bool IsBuiltinFragmentInputVariable(TQualifier qualifier); -bool CanBeInvariantESSL1(TQualifier qualifier); -bool CanBeInvariantESSL3OrGreater(TQualifier qualifier); -bool IsOutputESSL(ShShaderOutput output); -bool IsOutputGLSL(ShShaderOutput output); -bool IsOutputHLSL(ShShaderOutput output); -bool IsOutputVulkan(ShShaderOutput output); -} // namespace sh - -#endif // COMPILER_TRANSLATOR_UTIL_H_ |