Commit 7854d861 by Olli Etuaho Committed by Commit Bot

EmulatePrecision: Round constructor args only when needed

Constructor arguments don't need to be rounded if the constructor result will be rounded to the same precision. This will make precision emulated shaders slightly faster to execute in some cases. BUG=angleproject:874 TEST=angle_unittests Change-Id: I4220cd2289c97dcf5b7a25a4cbdd18487947c2d2 Reviewed-on: https://chromium-review.googlesource.com/500288Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 9cbc07c3
...@@ -467,7 +467,7 @@ TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left, ...@@ -467,7 +467,7 @@ TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left,
return createInternalFunctionCallNode(TType(EbtVoid), functionName, arguments); return createInternalFunctionCallNode(TType(EbtVoid), functionName, arguments);
} }
bool parentUsesResult(TIntermNode *parent, TIntermNode *node) bool ParentUsesResult(TIntermNode *parent, TIntermTyped *node)
{ {
if (!parent) if (!parent)
{ {
...@@ -490,6 +490,24 @@ bool parentUsesResult(TIntermNode *parent, TIntermNode *node) ...@@ -490,6 +490,24 @@ bool parentUsesResult(TIntermNode *parent, TIntermNode *node)
return true; 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 } // namespace anonymous
EmulatePrecision::EmulatePrecision(const TSymbolTable &symbolTable, int shaderVersion) EmulatePrecision::EmulatePrecision(const TSymbolTable &symbolTable, int shaderVersion)
...@@ -500,7 +518,10 @@ EmulatePrecision::EmulatePrecision(const TSymbolTable &symbolTable, int shaderVe ...@@ -500,7 +518,10 @@ EmulatePrecision::EmulatePrecision(const TSymbolTable &symbolTable, int shaderVe
void EmulatePrecision::visitSymbol(TIntermSymbol *node) void EmulatePrecision::visitSymbol(TIntermSymbol *node)
{ {
if (canRoundFloat(node->getType()) && !mDeclaringVariables && !isLValueRequiredHere()) TIntermNode *parent = getParentNode();
if (canRoundFloat(node->getType()) && ParentUsesResult(parent, node) &&
!ParentConstructorTakesCareOfRounding(parent, node) && !mDeclaringVariables &&
!isLValueRequiredHere())
{ {
TIntermNode *replacement = createRoundingFunctionCallNode(node); TIntermNode *replacement = createRoundingFunctionCallNode(node);
queueReplacement(node, replacement, OriginalNode::BECOMES_CHILD); queueReplacement(node, replacement, OriginalNode::BECOMES_CHILD);
...@@ -545,7 +566,8 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node) ...@@ -545,7 +566,8 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
case EOpMatrixTimesMatrix: case EOpMatrixTimesMatrix:
{ {
TIntermNode *parent = getParentNode(); TIntermNode *parent = getParentNode();
if (!parentUsesResult(parent, node)) if (!ParentUsesResult(parent, node) ||
ParentConstructorTakesCareOfRounding(parent, node))
{ {
break; break;
} }
...@@ -637,7 +659,8 @@ bool EmulatePrecision::visitFunctionPrototype(Visit visit, TIntermFunctionProtot ...@@ -637,7 +659,8 @@ bool EmulatePrecision::visitFunctionPrototype(Visit visit, TIntermFunctionProtot
bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node) bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
{ {
bool visitChildren = true; if (visit != PreVisit)
return true;
switch (node->getOp()) switch (node->getOp())
{ {
case EOpCallInternalRawFunction: case EOpCallInternalRawFunction:
...@@ -652,15 +675,15 @@ bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -652,15 +675,15 @@ bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
} }
default: default:
TIntermNode *parent = getParentNode(); TIntermNode *parent = getParentNode();
if (canRoundFloat(node->getType()) && visit == PreVisit && if (canRoundFloat(node->getType()) && ParentUsesResult(parent, node) &&
parentUsesResult(parent, node)) !ParentConstructorTakesCareOfRounding(parent, node))
{ {
TIntermNode *replacement = createRoundingFunctionCallNode(node); TIntermNode *replacement = createRoundingFunctionCallNode(node);
queueReplacement(node, replacement, OriginalNode::BECOMES_CHILD); queueReplacement(node, replacement, OriginalNode::BECOMES_CHILD);
} }
break; break;
} }
return visitChildren; return true;
} }
bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node) bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node)
......
...@@ -798,7 +798,7 @@ TEST_F(DebugShaderPrecisionTest, ConstructorRounding) ...@@ -798,7 +798,7 @@ TEST_F(DebugShaderPrecisionTest, ConstructorRounding)
"precision mediump int;\n" "precision mediump int;\n"
"uniform float u1;\n" "uniform float u1;\n"
"uniform float u2;\n" "uniform float u2;\n"
"uniform float u3;\n" "uniform lowp float u3;\n"
"uniform float u4;\n" "uniform float u4;\n"
"uniform ivec4 uiv;\n" "uniform ivec4 uiv;\n"
"void main() {\n" "void main() {\n"
...@@ -807,13 +807,10 @@ TEST_F(DebugShaderPrecisionTest, ConstructorRounding) ...@@ -807,13 +807,10 @@ TEST_F(DebugShaderPrecisionTest, ConstructorRounding)
" gl_FragColor = v1 + v2;\n" " gl_FragColor = v1 + v2;\n"
"}\n"; "}\n";
compile(shaderString); compile(shaderString);
// Note: this is suboptimal for the case taking four floats, but optimizing would be tricky. ASSERT_TRUE(foundInAllGLSLCode("v1 = angle_frm(vec4(u1, u2, angle_frl(u3), u4))"));
ASSERT_TRUE(foundInAllGLSLCode(
"v1 = angle_frm(vec4(angle_frm(u1), angle_frm(u2), angle_frm(u3), angle_frm(u4)))"));
ASSERT_TRUE(foundInAllGLSLCode("v2 = angle_frm(vec4(uiv))")); ASSERT_TRUE(foundInAllGLSLCode("v2 = angle_frm(vec4(uiv))"));
ASSERT_TRUE(foundInHLSLCode( ASSERT_TRUE(foundInHLSLCode("v1 = angle_frm(vec4(_u1, _u2, angle_frl(_u3), _u4))"));
"v1 = angle_frm(vec4(angle_frm(_u1), angle_frm(_u2), angle_frm(_u3), angle_frm(_u4)))"));
ASSERT_TRUE(foundInHLSLCode("v2 = angle_frm(vec4(_uiv))")); ASSERT_TRUE(foundInHLSLCode("v2 = angle_frm(vec4(_uiv))"));
} }
......
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