Commit 666f65a1 by Jamie Madill Committed by Commit Bot

Revert "Revert "Cover vector dynamic indexing case in SplitSequenceOperator""

This reverts commit d2f59bb6. Change-Id: If2842bce17a0c085e2bc913ff120083fbe90497c Reviewed-on: https://chromium-review.googlesource.com/376189Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent b3925a3f
...@@ -27,7 +27,14 @@ IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mM ...@@ -27,7 +27,14 @@ IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mM
{ {
} }
bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode) // 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 ((mMask & kExpressionReturningArray) != 0)
{ {
...@@ -49,6 +56,33 @@ bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNod ...@@ -49,6 +56,33 @@ bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNod
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,22 +19,35 @@ class TIntermSelection; ...@@ -19,22 +19,35 @@ 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,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#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
...@@ -405,10 +406,18 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod ...@@ -405,10 +406,18 @@ 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 (!node->getLeft()->isArray() && node->getLeft()->getBasicType() != EbtStruct) else if (IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(node))
{ {
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()); mFoundLoopToChange = mConditionsToSimplify.match(node, getParentNode(), isLValueRequiredHere());
return !mFoundLoopToChange; return !mFoundLoopToChange;
} }
......
...@@ -17,10 +17,12 @@ ...@@ -17,10 +17,12 @@
namespace namespace
{ {
class SplitSequenceOperatorTraverser : public TIntermTraverser class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser
{ {
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;
...@@ -38,8 +40,10 @@ class SplitSequenceOperatorTraverser : public TIntermTraverser ...@@ -38,8 +40,10 @@ class SplitSequenceOperatorTraverser : public TIntermTraverser
IntermNodePatternMatcher mPatternToSplitMatcher; IntermNodePatternMatcher mPatternToSplitMatcher;
}; };
SplitSequenceOperatorTraverser::SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask) SplitSequenceOperatorTraverser::SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask,
: TIntermTraverser(true, false, true), const TSymbolTable &symbolTable,
int shaderVersion)
: TLValueTrackingTraverser(true, false, true, symbolTable, shaderVersion),
mFoundExpressionToSplit(false), mFoundExpressionToSplit(false),
mInsideSequenceOperator(0), mInsideSequenceOperator(0),
mPatternToSplitMatcher(patternsToSplitMask) mPatternToSplitMatcher(patternsToSplitMask)
...@@ -61,7 +65,8 @@ bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *nod ...@@ -61,7 +65,8 @@ 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 = mPatternToSplitMatcher.match(node, getParentNode()); mFoundExpressionToSplit =
mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere());
return !mFoundExpressionToSplit; return !mFoundExpressionToSplit;
} }
...@@ -133,9 +138,13 @@ bool SplitSequenceOperatorTraverser::visitSelection(Visit visit, TIntermSelectio ...@@ -133,9 +138,13 @@ bool SplitSequenceOperatorTraverser::visitSelection(Visit visit, TIntermSelectio
} // namespace } // namespace
void SplitSequenceOperator(TIntermNode *root, int patternsToSplitMask, unsigned int *temporaryIndex) void SplitSequenceOperator(TIntermNode *root,
int patternsToSplitMask,
unsigned int *temporaryIndex,
const TSymbolTable &symbolTable,
int shaderVersion)
{ {
SplitSequenceOperatorTraverser traverser(patternsToSplitMask); SplitSequenceOperatorTraverser traverser(patternsToSplitMask, symbolTable, shaderVersion);
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,9 +13,12 @@ ...@@ -13,9 +13,12 @@
#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,16 +37,17 @@ void TranslatorHLSL::translate(TIntermNode *root, int compileOptions) ...@@ -37,16 +37,17 @@ 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, IntermNodePatternMatcher::kExpressionReturningArray | SimplifyLoopConditions(root,
IntermNodePatternMatcher::kUnfoldedShortCircuitExpression, IntermNodePatternMatcher::kExpressionReturningArray |
IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue,
getTemporaryIndex(), getSymbolTable(), getShaderVersion()); getTemporaryIndex(), getSymbolTable(), getShaderVersion());
// TODO (oetuaho): Sequence operators should also be split in case there is dynamic indexing of SplitSequenceOperator(root,
// a vector or matrix as an l-value inside (RemoveDynamicIndexing transformation step generates IntermNodePatternMatcher::kExpressionReturningArray |
// statements in this case). IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
SplitSequenceOperator(root, IntermNodePatternMatcher::kExpressionReturningArray | IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue,
IntermNodePatternMatcher::kUnfoldedShortCircuitExpression, getTemporaryIndex(), getSymbolTable(), getShaderVersion());
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,6 +2130,35 @@ TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit) ...@@ -2130,6 +2130,35 @@ 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