Added a traverser for detecting gradient operations.

TRAC #20737 Signed-off-by: Daniel Koch Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@1121 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent e2095642
...@@ -10,29 +10,110 @@ ...@@ -10,29 +10,110 @@
#include "compiler/DetectDiscontinuity.h" #include "compiler/DetectDiscontinuity.h"
#include "compiler/ParseHelper.h"
namespace sh namespace sh
{ {
bool DetectDiscontinuity::traverse(TIntermNode *node) bool DetectLoopDiscontinuity::traverse(TIntermNode *node)
{ {
mDiscontinuity = false; mLoopDiscontinuity = false;
node->traverse(this); node->traverse(this);
return mDiscontinuity; return mLoopDiscontinuity;
} }
bool DetectDiscontinuity::visitBranch(Visit visit, TIntermBranch *node) bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node)
{ {
if (mLoopDiscontinuity)
{
return false;
}
switch (node->getFlowOp()) switch (node->getFlowOp())
{ {
case EOpKill: case EOpKill:
break; break;
case EOpBreak: case EOpBreak:
case EOpContinue: case EOpContinue:
mDiscontinuity = true; mLoopDiscontinuity = true;
case EOpReturn: case EOpReturn:
break; break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
return !mDiscontinuity; return !mLoopDiscontinuity;
}
bool DetectLoopDiscontinuity::visitAggregate(Visit visit, TIntermAggregate *node)
{
return !mLoopDiscontinuity;
}
bool containsLoopDiscontinuity(TIntermNode *node)
{
DetectLoopDiscontinuity detectLoopDiscontinuity;
return detectLoopDiscontinuity.traverse(node);
}
bool DetectGradientOperation::traverse(TIntermNode *node)
{
mGradientOperation = false;
node->traverse(this);
return mGradientOperation;
}
bool DetectGradientOperation::visitUnary(Visit visit, TIntermUnary *node)
{
if (mGradientOperation)
{
return false;
}
switch (node->getOp())
{
case EOpDFdx:
case EOpDFdy:
mGradientOperation = true;
default:
break;
}
return !mGradientOperation;
}
bool DetectGradientOperation::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (mGradientOperation)
{
return false;
}
if (node->getOp() == EOpFunctionCall)
{
if (!node->isUserDefined())
{
TString name = TFunction::unmangleName(node->getName());
if (name == "texture2D" ||
name == "texture2DProj" ||
name == "textureCube")
{
mGradientOperation = true;
}
}
else
{
// When a user defined function is called, we have to
// conservatively assume it to contain gradient operations
mGradientOperation = true;
}
}
return !mGradientOperation;
}
bool containsGradientOperation(TIntermNode *node)
{
DetectGradientOperation detectGradientOperation;
return detectGradientOperation.traverse(node);
} }
} }
...@@ -15,22 +15,36 @@ ...@@ -15,22 +15,36 @@
namespace sh namespace sh
{ {
class DetectDiscontinuity : public TIntermTraverser // Checks whether a loop can run for a variable number of iterations
class DetectLoopDiscontinuity : public TIntermTraverser
{ {
public: public:
bool traverse(TIntermNode *node); bool traverse(TIntermNode *node);
protected: protected:
bool visitBranch(Visit visit, TIntermBranch *node); bool visitBranch(Visit visit, TIntermBranch *node);
bool visitAggregate(Visit visit, TIntermAggregate *node);
bool mDiscontinuity; bool mLoopDiscontinuity;
}; };
bool containsDiscontinuity(TIntermNode *node) bool containsLoopDiscontinuity(TIntermNode *node);
// Checks for intrinsic functions which compute gradients
class DetectGradientOperation : public TIntermTraverser
{ {
DetectDiscontinuity detectDiscontinuity; public:
return detectDiscontinuity.traverse(node); bool traverse(TIntermNode *node);
}
protected:
bool visitUnary(Visit visit, TIntermUnary *node);
bool visitAggregate(Visit visit, TIntermAggregate *node);
bool mGradientOperation;
};
bool containsGradientOperation(TIntermNode *node);
} }
#endif // COMPILER_DETECTDISCONTINUITY_H_ #endif // COMPILER_DETECTDISCONTINUITY_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment