Commit d2f59bb6 by Jamie Madill

Revert "Cover vector dynamic indexing case in SplitSequenceOperator"

This CL was causing inverted rendering in a WebGL application. This reverts commit 7da98506. Vectors or matrices that are dynamically indexed as a part of an l-value generate new statements in the RemoveDynamicIndexing AST transformation step. SplitSequenceOperator needs to detect this case and split the sequence operator before statements are generated from its operands to ensure the correct order of execution. BUG=angleproject:1341 TEST=angle_end2end_tests Change-Id: I854f8cce2d46107afa62f48edf3d32c6d5c97eda Reviewed-on: https://chromium-review.googlesource.com/371643Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 6c9503ec
...@@ -27,14 +27,7 @@ IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mM ...@@ -27,14 +27,7 @@ IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mM
{ {
} }
// static bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode)
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 ((mMask & kExpressionReturningArray) != 0)
{ {
...@@ -56,33 +49,6 @@ bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *p ...@@ -56,33 +49,6 @@ bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *p
return false; 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) bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode)
{ {
if ((mMask & kExpressionReturningArray) != 0) if ((mMask & kExpressionReturningArray) != 0)
......
...@@ -19,35 +19,22 @@ class TIntermSelection; ...@@ -19,35 +19,22 @@ class TIntermSelection;
class IntermNodePatternMatcher class IntermNodePatternMatcher
{ {
public: public:
static bool IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node);
enum PatternType enum PatternType
{ {
// Matches expressions that are unfolded to if statements by UnfoldShortCircuitToIf
kUnfoldedShortCircuitExpression = 0x0001, kUnfoldedShortCircuitExpression = 0x0001,
// Matches expressions that return arrays with the exception of simple statements where a // Matches expressions that return arrays with the exception of simple statements where a
// constructor or function call result is assigned. // constructor or function call result is assigned.
kExpressionReturningArray = 0x0002, kExpressionReturningArray = 0x0002
// Matches dynamic indexing of vectors or matrices in l-values.
kDynamicIndexingOfVectorOrMatrixInLValue = 0x0004
}; };
IntermNodePatternMatcher(const unsigned int mask); IntermNodePatternMatcher(const unsigned int mask);
bool match(TIntermBinary *node, TIntermNode *parentNode); 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(TIntermAggregate *node, TIntermNode *parentNode);
bool match(TIntermSelection *node); bool match(TIntermSelection *node);
private: private:
const unsigned int mMask; const unsigned int mMask;
bool matchInternal(TIntermBinary *node, TIntermNode *parentNode);
}; };
#endif #endif
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h" #include "compiler/translator/IntermNode.h"
#include "compiler/translator/IntermNodePatternMatcher.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
namespace namespace
...@@ -406,18 +405,10 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod ...@@ -406,18 +405,10 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod
TIntermSymbol *tempIndex = createTempSymbol(node->getRight()->getType()); TIntermSymbol *tempIndex = createTempSymbol(node->getRight()->getType());
queueReplacementWithParent(node, node->getRight(), tempIndex, OriginalNode::IS_DROPPED); queueReplacementWithParent(node, node->getRight(), tempIndex, OriginalNode::IS_DROPPED);
} }
else if (IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(node)) else if (!node->getLeft()->isArray() && node->getLeft()->getBasicType() != EbtStruct)
{ {
bool write = isLValueRequiredHere(); 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
TType type = node->getLeft()->getType(); TType type = node->getLeft()->getType();
mIndexedVecAndMatrixTypes.insert(type); mIndexedVecAndMatrixTypes.insert(type);
......
...@@ -83,7 +83,7 @@ bool SimplifyLoopConditionsTraverser::visitBinary(Visit visit, TIntermBinary *no ...@@ -83,7 +83,7 @@ bool SimplifyLoopConditionsTraverser::visitBinary(Visit visit, TIntermBinary *no
if (!mInsideLoopConditionOrExpression) if (!mInsideLoopConditionOrExpression)
return false; return false;
mFoundLoopToChange = mConditionsToSimplify.match(node, getParentNode(), isLValueRequiredHere()); mFoundLoopToChange = mConditionsToSimplify.match(node, getParentNode());
return !mFoundLoopToChange; return !mFoundLoopToChange;
} }
......
...@@ -17,12 +17,10 @@ ...@@ -17,12 +17,10 @@
namespace namespace
{ {
class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser class SplitSequenceOperatorTraverser : public TIntermTraverser
{ {
public: public:
SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask, SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask);
const TSymbolTable &symbolTable,
int shaderVersion);
bool visitBinary(Visit visit, TIntermBinary *node) override; bool visitBinary(Visit visit, TIntermBinary *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override; bool visitAggregate(Visit visit, TIntermAggregate *node) override;
...@@ -40,10 +38,8 @@ class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser ...@@ -40,10 +38,8 @@ class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser
IntermNodePatternMatcher mPatternToSplitMatcher; IntermNodePatternMatcher mPatternToSplitMatcher;
}; };
SplitSequenceOperatorTraverser::SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask, SplitSequenceOperatorTraverser::SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask)
const TSymbolTable &symbolTable, : TIntermTraverser(true, false, true),
int shaderVersion)
: TLValueTrackingTraverser(true, false, true, symbolTable, shaderVersion),
mFoundExpressionToSplit(false), mFoundExpressionToSplit(false),
mInsideSequenceOperator(0), mInsideSequenceOperator(0),
mPatternToSplitMatcher(patternsToSplitMask) mPatternToSplitMatcher(patternsToSplitMask)
...@@ -65,8 +61,7 @@ bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *nod ...@@ -65,8 +61,7 @@ bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *nod
if (mInsideSequenceOperator > 0 && visit == PreVisit) if (mInsideSequenceOperator > 0 && visit == PreVisit)
{ {
// Detect expressions that need to be simplified // Detect expressions that need to be simplified
mFoundExpressionToSplit = mFoundExpressionToSplit = mPatternToSplitMatcher.match(node, getParentNode());
mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere());
return !mFoundExpressionToSplit; return !mFoundExpressionToSplit;
} }
...@@ -138,13 +133,9 @@ bool SplitSequenceOperatorTraverser::visitSelection(Visit visit, TIntermSelectio ...@@ -138,13 +133,9 @@ bool SplitSequenceOperatorTraverser::visitSelection(Visit visit, TIntermSelectio
} // namespace } // namespace
void SplitSequenceOperator(TIntermNode *root, void SplitSequenceOperator(TIntermNode *root, int patternsToSplitMask, unsigned int *temporaryIndex)
int patternsToSplitMask,
unsigned int *temporaryIndex,
const TSymbolTable &symbolTable,
int shaderVersion)
{ {
SplitSequenceOperatorTraverser traverser(patternsToSplitMask, symbolTable, shaderVersion); SplitSequenceOperatorTraverser traverser(patternsToSplitMask);
ASSERT(temporaryIndex != nullptr); ASSERT(temporaryIndex != nullptr);
traverser.useTemporaryIndex(temporaryIndex); traverser.useTemporaryIndex(temporaryIndex);
// Separate one expression at a time, and reset the traverser between iterations. // Separate one expression at a time, and reset the traverser between iterations.
......
...@@ -13,12 +13,9 @@ ...@@ -13,12 +13,9 @@
#define COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_ #define COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_
class TIntermNode; class TIntermNode;
class TSymbolTable;
void SplitSequenceOperator(TIntermNode *root, void SplitSequenceOperator(TIntermNode *root,
int patternsToSplitMask, int patternsToSplitMask,
unsigned int *temporaryIndex, unsigned int *temporaryIndex);
const TSymbolTable &symbolTable,
int shaderVersion);
#endif // COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_ #endif // COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_
...@@ -37,17 +37,16 @@ void TranslatorHLSL::translate(TIntermNode *root, int compileOptions) ...@@ -37,17 +37,16 @@ void TranslatorHLSL::translate(TIntermNode *root, int compileOptions)
// Note that SimplifyLoopConditions needs to be run before any other AST transformations that // 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. // may need to generate new statements from loop conditions or loop expressions.
SimplifyLoopConditions(root, SimplifyLoopConditions(root, IntermNodePatternMatcher::kExpressionReturningArray |
IntermNodePatternMatcher::kExpressionReturningArray | IntermNodePatternMatcher::kUnfoldedShortCircuitExpression,
IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue,
getTemporaryIndex(), getSymbolTable(), getShaderVersion()); getTemporaryIndex(), getSymbolTable(), getShaderVersion());
SplitSequenceOperator(root, // TODO (oetuaho): Sequence operators should also be split in case there is dynamic indexing of
IntermNodePatternMatcher::kExpressionReturningArray | // a vector or matrix as an l-value inside (RemoveDynamicIndexing transformation step generates
IntermNodePatternMatcher::kUnfoldedShortCircuitExpression | // statements in this case).
IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue, SplitSequenceOperator(root, IntermNodePatternMatcher::kExpressionReturningArray |
getTemporaryIndex(), getSymbolTable(), getShaderVersion()); IntermNodePatternMatcher::kUnfoldedShortCircuitExpression,
getTemporaryIndex());
// Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf. // Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf.
UnfoldShortCircuitToIf(root, getTemporaryIndex()); UnfoldShortCircuitToIf(root, getTemporaryIndex());
......
...@@ -2130,35 +2130,6 @@ TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit) ...@@ -2130,35 +2130,6 @@ TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
} }
// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
// Indexing the vector needs to be evaluated after func() for the right result.
TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
{
const std::string &fragmentShaderSource =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"uniform int u_zero;\n"
"int sideEffectCount = 0;\n"
"float func() {\n"
" ++sideEffectCount;\n"
" return -1.0;\n"
"}\n"
"void main() {\n"
" vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
" float f = (func(), (++v[u_zero + sideEffectCount]));\n"
" bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
" my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
"}\n";
GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
ASSERT_NE(0u, program);
drawQuad(program, "inputAttribute", 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error. // Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
// From WebGL test conformance/rendering/point-specific-shader-variables.html // From WebGL test conformance/rendering/point-specific-shader-variables.html
// See http://anglebug.com/1380 // See http://anglebug.com/1380
......
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