summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp462
1 files changed, 0 insertions, 462 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