Disable optimizations for shaders with conditional discard in D3D9, and
only use expanded short-circuiting conditionals for expressions with
potential side-effects.
Conservatively assume aggreate and selection operators have side effects for now.
BUG=
ANGLEBUG=486
R=geofflang@chromium.org, kbr@chromium.org, nicolas@transgaming.com, shannonwoods@chromium.org
Review URL: https://codereview.appspot.com/14441075
Conflicts:
src/common/version.h
src/compiler/translator.vcxproj
src/compiler/translator.vcxproj.filters
src/compiler/translator/OutputHLSL.cpp
src/libGLESv2/ProgramBinary.cpp
src/libGLESv2/Shader.cpp
src/libGLESv2/Shader.h
Change-Id: Iaf9f10b5de7b33c927ef032f3c4fe9d5095f64dd
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index c410ba2..7009390 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -15,6 +15,7 @@
#include "compiler/translator/UnfoldShortCircuit.h"
#include "compiler/translator/HLSLLayoutEncoder.h"
#include "compiler/translator/FlagStd140Structs.h"
+#include "compiler/translator/NodeSearch.h"
#include <algorithm>
#include <cfloat>
@@ -121,6 +122,7 @@
mUsesAtan2_2 = false;
mUsesAtan2_3 = false;
mUsesAtan2_4 = false;
+ mUsesDiscardRewriting = false;
mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
@@ -663,6 +665,11 @@
out << *constructor;
}
+ if (mUsesDiscardRewriting)
+ {
+ out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n";
+ }
+
if (mContext.shaderType == SH_FRAGMENT_SHADER)
{
TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
@@ -1883,15 +1890,31 @@
case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break;
case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break;
case EOpLogicalOr:
- out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
- return false;
+ if (node->getRight()->hasSideEffects())
+ {
+ out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
+ return false;
+ }
+ else
+ {
+ outputTriplet(visit, "(", " || ", ")");
+ return true;
+ }
case EOpLogicalXor:
mUsesXor = true;
outputTriplet(visit, "xor(", ", ", ")");
break;
case EOpLogicalAnd:
- out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
- return false;
+ if (node->getRight()->hasSideEffects())
+ {
+ out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
+ return false;
+ }
+ else
+ {
+ outputTriplet(visit, "(", " && ", ")");
+ return true;
+ }
default: UNREACHABLE();
}
@@ -2483,7 +2506,7 @@
{
mUnfoldShortCircuit->traverse(node->getCondition());
- out << "if(";
+ out << "if (";
node->getCondition()->traverse(this);
@@ -2492,9 +2515,14 @@
outputLineDirective(node->getLine().first_line);
out << "{\n";
+ bool discard = false;
+
if (node->getTrueBlock())
{
traverseStatements(node->getTrueBlock());
+
+ // Detect true discard
+ discard = (discard || FindDiscard::search(node->getTrueBlock()));
}
outputLineDirective(node->getLine().first_line);
@@ -2512,6 +2540,15 @@
outputLineDirective(node->getFalseBlock()->getLine().first_line);
out << ";\n}\n";
+
+ // Detect false discard
+ discard = (discard || FindDiscard::search(node->getFalseBlock()));
+ }
+
+ // ANGLE issue 486: Detect problematic conditional discard
+ if (discard && FindSideEffectRewriting::search(node))
+ {
+ mUsesDiscardRewriting = true;
}
}
@@ -2609,7 +2646,9 @@
switch (node->getFlowOp())
{
- case EOpKill: outputTriplet(visit, "discard;\n", "", ""); break;
+ case EOpKill:
+ outputTriplet(visit, "discard;\n", "", "");
+ break;
case EOpBreak:
if (visit == PreVisit)
{
@@ -2832,7 +2871,7 @@
if (!firstLoopFragment)
{
- out << "if(!Break";
+ out << "if (!Break";
index->traverse(this);
out << ") {\n";
}