diff options
author | Jamie Madill <jmadill@chromium.org> | 2013-11-04 11:09:26 -0500 |
---|---|---|
committer | Jamie Madill <jmadill@chromium.org> | 2013-11-04 11:09:26 -0500 |
commit | d1ffb561a2773f9675641abd5e7d408ae93c5846 (patch) | |
tree | 8e7ae2708e49f2e614383054dde2ee9eec23cec6 | |
parent | 9c318342233f68b915d39c8f1f181b9ef545c4db (diff) | |
download | angle_dx11-d1ffb561a2773f9675641abd5e7d408ae93c5846.tar.gz |
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
-rw-r--r-- | src/common/version.h | 2 | ||||
-rw-r--r-- | src/compiler/Intermediate.cpp | 2 | ||||
-rw-r--r-- | src/compiler/NodeSearch.h | 78 | ||||
-rw-r--r-- | src/compiler/OutputHLSL.cpp | 53 | ||||
-rw-r--r-- | src/compiler/OutputHLSL.h | 1 | ||||
-rw-r--r-- | src/compiler/UnfoldShortCircuit.cpp | 14 | ||||
-rw-r--r-- | src/compiler/ValidateLimitations.cpp | 2 | ||||
-rw-r--r-- | src/compiler/depgraph/DependencyGraphBuilder.cpp | 2 | ||||
-rw-r--r-- | src/compiler/intermediate.h | 18 | ||||
-rw-r--r-- | src/compiler/translator.vcxproj | 1 | ||||
-rw-r--r-- | src/compiler/translator.vcxproj.filters | 3 | ||||
-rw-r--r-- | src/libGLESv2/ProgramBinary.cpp | 11 | ||||
-rw-r--r-- | src/libGLESv2/Shader.cpp | 2 | ||||
-rw-r--r-- | src/libGLESv2/Shader.h | 1 | ||||
-rw-r--r-- | src/libGLESv2/renderer/Renderer.h | 8 | ||||
-rw-r--r-- | src/libGLESv2/renderer/Renderer11.cpp | 2 | ||||
-rw-r--r-- | src/libGLESv2/renderer/Renderer11.h | 2 | ||||
-rw-r--r-- | src/libGLESv2/renderer/Renderer9.cpp | 8 | ||||
-rw-r--r-- | src/libGLESv2/renderer/Renderer9.h | 2 |
19 files changed, 188 insertions, 24 deletions
diff --git a/src/common/version.h b/src/common/version.h index d917aa29..9f221f3a 100644 --- a/src/common/version.h +++ b/src/common/version.h @@ -1,7 +1,7 @@ #define MAJOR_VERSION 1 #define MINOR_VERSION 2 #define BUILD_VERSION 0 -#define BUILD_REVISION 2449 +#define BUILD_REVISION 2450 #define STRINGIFY(x) #x #define MACRO_STRINGIFY(x) STRINGIFY(x) diff --git a/src/compiler/Intermediate.cpp b/src/compiler/Intermediate.cpp index 5bab2161..b3cb3ddb 100644 --- a/src/compiler/Intermediate.cpp +++ b/src/compiler/Intermediate.cpp @@ -806,7 +806,7 @@ bool TIntermSelection::replaceChildNode( // // Returns true if state is modified. // -bool TIntermOperator::modifiesState() const +bool TIntermOperator::hasSideEffects() const { switch (op) { case EOpPostIncrement: diff --git a/src/compiler/NodeSearch.h b/src/compiler/NodeSearch.h new file mode 100644 index 00000000..27e471db --- /dev/null +++ b/src/compiler/NodeSearch.h @@ -0,0 +1,78 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// NodeSearch.h: Utilities for searching translator node graphs +// + +#ifndef TRANSLATOR_NODESEARCH_H_ +#define TRANSLATOR_NODESEARCH_H_ + +namespace sh +{ + +template <class Parent> +class NodeSearchTraverser : public TIntermTraverser +{ + public: + NodeSearchTraverser() + : mFound(false) + {} + + bool found() const { return mFound; } + + static bool search(TIntermNode *node) + { + Parent searchTraverser; + node->traverse(&searchTraverser); + return searchTraverser.found(); + } + + protected: + bool mFound; +}; + +class FindDiscard : public NodeSearchTraverser<FindDiscard> +{ + public: + virtual bool visitBranch(Visit visit, TIntermBranch *node) + { + switch (node->getFlowOp()) + { + case EOpKill: + mFound = true; + break; + + default: break; + } + + return !mFound; + } +}; + +class FindSideEffectRewriting : public NodeSearchTraverser<FindSideEffectRewriting> +{ + public: + virtual bool visitBinary(Visit visit, TIntermBinary *node) + { + switch (node->getOp()) + { + case EOpLogicalOr: + case EOpLogicalAnd: + if (node->getRight()->hasSideEffects()) + { + mFound = true; + } + break; + + default: break; + } + + return !mFound; + } +}; + +} + +#endif // TRANSLATOR_NODESEARCH_H_ diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp index 79a373eb..53799dff 100644 --- a/src/compiler/OutputHLSL.cpp +++ b/src/compiler/OutputHLSL.cpp @@ -12,6 +12,7 @@ #include "compiler/InfoSink.h" #include "compiler/SearchSymbol.h" #include "compiler/UnfoldShortCircuit.h" +#include "compiler/NodeSearch.h" #include <algorithm> #include <cfloat> @@ -72,6 +73,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc mUsesAtan2_2 = false; mUsesAtan2_3 = false; mUsesAtan2_4 = false; + mUsesDiscardRewriting = false; mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; @@ -196,6 +198,11 @@ void OutputHLSL::header() attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; } + if (mUsesDiscardRewriting) + { + out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n"; + } + if (shaderType == SH_FRAGMENT_SHADER) { TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers"); @@ -1299,15 +1306,31 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) 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(); } @@ -1944,7 +1967,7 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) { mUnfoldShortCircuit->traverse(node->getCondition()); - out << "if("; + out << "if ("; node->getCondition()->traverse(this); @@ -1953,9 +1976,14 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) 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); @@ -1973,6 +2001,15 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) 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; } } @@ -2070,7 +2107,9 @@ bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) switch (node->getFlowOp()) { - case EOpKill: outputTriplet(visit, "discard;\n", "", ""); break; + case EOpKill: + outputTriplet(visit, "discard;\n", "", ""); + break; case EOpBreak: if (visit == PreVisit) { @@ -2293,7 +2332,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) if (!firstLoopFragment) { - out << "if(!Break"; + out << "if (!Break"; index->traverse(this); out << ") {\n"; } diff --git a/src/compiler/OutputHLSL.h b/src/compiler/OutputHLSL.h index 49bc1376..586a76fb 100644 --- a/src/compiler/OutputHLSL.h +++ b/src/compiler/OutputHLSL.h @@ -125,6 +125,7 @@ class OutputHLSL : public TIntermTraverser bool mUsesAtan2_2; bool mUsesAtan2_3; bool mUsesAtan2_4; + bool mUsesDiscardRewriting; int mNumRenderTargets; diff --git a/src/compiler/UnfoldShortCircuit.cpp b/src/compiler/UnfoldShortCircuit.cpp index 47f0afca..5cfdd323 100644 --- a/src/compiler/UnfoldShortCircuit.cpp +++ b/src/compiler/UnfoldShortCircuit.cpp @@ -31,6 +31,14 @@ bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node) { TInfoSinkBase &out = mOutputHLSL->getBodyStream(); + // If our right node doesn't have side effects, we know we don't need to unfold this + // expression: there will be no short-circuiting side effects to avoid + // (note: unfolding doesn't depend on the left node -- it will always be evaluated) + if (!node->getRight()->hasSideEffects()) + { + return true; + } + switch (node->getOp()) { case EOpLogicalOr: @@ -49,7 +57,7 @@ bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node) mTemporaryIndex = i + 1; node->getLeft()->traverse(mOutputHLSL); out << ";\n"; - out << "if(!s" << i << ")\n" + out << "if (!s" << i << ")\n" "{\n"; mTemporaryIndex = i + 1; node->getRight()->traverse(this); @@ -80,7 +88,7 @@ bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node) mTemporaryIndex = i + 1; node->getLeft()->traverse(mOutputHLSL); out << ";\n"; - out << "if(s" << i << ")\n" + out << "if (s" << i << ")\n" "{\n"; mTemporaryIndex = i + 1; node->getRight()->traverse(this); @@ -115,7 +123,7 @@ bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node) mTemporaryIndex = i + 1; node->getCondition()->traverse(this); - out << "if("; + out << "if ("; mTemporaryIndex = i + 1; node->getCondition()->traverse(mOutputHLSL); out << ")\n" diff --git a/src/compiler/ValidateLimitations.cpp b/src/compiler/ValidateLimitations.cpp index 7b8b1c87..3f3260b0 100644 --- a/src/compiler/ValidateLimitations.cpp +++ b/src/compiler/ValidateLimitations.cpp @@ -457,7 +457,7 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) bool ValidateLimitations::validateOperation(TIntermOperator* node, TIntermNode* operand) { // Check if loop index is modified in the loop body. - if (!withinLoopBody() || !node->modifiesState()) + if (!withinLoopBody() || !node->hasSideEffects()) return true; const TIntermSymbol* symbol = operand->getAsSymbolNode(); diff --git a/src/compiler/depgraph/DependencyGraphBuilder.cpp b/src/compiler/depgraph/DependencyGraphBuilder.cpp index d586cfd0..069e9633 100644 --- a/src/compiler/depgraph/DependencyGraphBuilder.cpp +++ b/src/compiler/depgraph/DependencyGraphBuilder.cpp @@ -94,7 +94,7 @@ void TDependencyGraphBuilder::visitSymbol(TIntermSymbol* intermSymbol) bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary* intermBinary) { TOperator op = intermBinary->getOp(); - if (op == EOpInitialize || intermBinary->modifiesState()) + if (op == EOpInitialize || intermBinary->hasSideEffects()) visitAssignment(intermBinary); else if (op == EOpLogicalAnd || op == EOpLogicalOr) visitLogicalOp(intermBinary); diff --git a/src/compiler/intermediate.h b/src/compiler/intermediate.h index 69e3f07a..4ddfdabd 100644 --- a/src/compiler/intermediate.h +++ b/src/compiler/intermediate.h @@ -252,6 +252,8 @@ public: TIntermTyped(const TType& t) : type(t) { } virtual TIntermTyped* getAsTyped() { return this; } + virtual bool hasSideEffects() const = 0; + void setType(const TType& t) { type = t; } const TType& getType() const { return type; } TType* getTypePointer() { return &type; } @@ -354,6 +356,8 @@ public: TIntermSymbol(int i, const TString& sym, const TType& t) : TIntermTyped(t), id(i) { symbol = sym; originalSymbol = sym; } + virtual bool hasSideEffects() const { return false; } + int getId() const { return id; } const TString& getSymbol() const { return symbol; } @@ -376,6 +380,8 @@ class TIntermConstantUnion : public TIntermTyped { public: TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { } + virtual bool hasSideEffects() const { return false; } + ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; } int getIConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; } @@ -400,7 +406,7 @@ public: TOperator getOp() const { return op; } void setOp(TOperator o) { op = o; } - bool modifiesState() const; + virtual bool hasSideEffects() const; bool isConstructor() const; protected: @@ -421,6 +427,8 @@ public: virtual bool replaceChildNode( TIntermNode *original, TIntermNode *replacement); + virtual bool hasSideEffects() const { return (TIntermOperator::hasSideEffects() || left->hasSideEffects() || right->hasSideEffects()); } + void setLeft(TIntermTyped* n) { left = n; } void setRight(TIntermTyped* n) { right = n; } TIntermTyped* getLeft() const { return left; } @@ -451,6 +459,8 @@ public: virtual bool replaceChildNode( TIntermNode *original, TIntermNode *replacement); + virtual bool hasSideEffects() const { return (TIntermOperator::hasSideEffects() || operand->hasSideEffects()); } + void setOperand(TIntermTyped* o) { operand = o; } TIntermTyped* getOperand() { return operand; } bool promote(TInfoSink&); @@ -483,6 +493,9 @@ public: virtual bool replaceChildNode( TIntermNode *original, TIntermNode *replacement); + // Conservatively assume function calls and other aggregate operators have side-effects + virtual bool hasSideEffects() const { return true; } + TIntermSequence& getSequence() { return sequence; } void setName(const TString& n) { name = n; } @@ -528,6 +541,9 @@ public: virtual bool replaceChildNode( TIntermNode *original, TIntermNode *replacement); + // Conservatively assume selections have side-effects + virtual bool hasSideEffects() const { return true; } + bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } TIntermNode* getCondition() const { return condition; } TIntermNode* getTrueBlock() const { return trueBlock; } diff --git a/src/compiler/translator.vcxproj b/src/compiler/translator.vcxproj index 7325172a..54d71a1d 100644 --- a/src/compiler/translator.vcxproj +++ b/src/compiler/translator.vcxproj @@ -263,6 +263,7 @@ <ClInclude Include="localintermediate.h" /> <ClInclude Include="MapLongVariableNames.h" /> <ClInclude Include="MMap.h" /> + <ClInclude Include="NodeSearch.h" /> <ClInclude Include="osinclude.h" /> <ClInclude Include="OutputESSL.h" /> <ClInclude Include="OutputGLSL.h" /> diff --git a/src/compiler/translator.vcxproj.filters b/src/compiler/translator.vcxproj.filters index b8cd7304..1df6c7c2 100644 --- a/src/compiler/translator.vcxproj.filters +++ b/src/compiler/translator.vcxproj.filters @@ -346,6 +346,9 @@ <ClInclude Include="ParseContext.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="NodeSearch.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <CustomBuild Include="glslang.l"> diff --git a/src/libGLESv2/ProgramBinary.cpp b/src/libGLESv2/ProgramBinary.cpp index 922cd3de..ee0ec8e0 100644 --- a/src/libGLESv2/ProgramBinary.cpp +++ b/src/libGLESv2/ProgramBinary.cpp @@ -34,6 +34,11 @@ std::string str(int i) return buffer; } +static rx::D3DWorkaroundType DiscardWorkaround(bool usesDiscard) +{ + return (usesDiscard ? rx::ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER : rx::ANGLE_D3D_WORKAROUND_NONE); +} + UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) : name(name), element(element), index(index) { @@ -1962,13 +1967,13 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin if (success) { - mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX); - mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL); + mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX, DiscardWorkaround(vertexShader->mUsesDiscardRewriting)); + mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL, DiscardWorkaround(fragmentShader->mUsesDiscardRewriting)); if (usesGeometryShader()) { std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader); - mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY); + mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY, rx::ANGLE_D3D_WORKAROUND_NONE); } if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) diff --git a/src/libGLESv2/Shader.cpp b/src/libGLESv2/Shader.cpp index 7dfdd0ba..f6a2f03d 100644 --- a/src/libGLESv2/Shader.cpp +++ b/src/libGLESv2/Shader.cpp @@ -307,6 +307,7 @@ void Shader::parseVaryings() mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL; mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL; mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL; + mUsesDiscardRewriting = strstr(mHlsl, "ANGLE_USES_DISCARD_REWRITING") != NULL; } } @@ -340,6 +341,7 @@ void Shader::uncompile() mUsesPointCoord = false; mUsesDepthRange = false; mUsesFragDepth = false; + mUsesDiscardRewriting = false; mActiveUniforms.clear(); } diff --git a/src/libGLESv2/Shader.h b/src/libGLESv2/Shader.h index 2afe2976..848d4c99 100644 --- a/src/libGLESv2/Shader.h +++ b/src/libGLESv2/Shader.h @@ -107,6 +107,7 @@ class Shader bool mUsesPointCoord; bool mUsesDepthRange; bool mUsesFragDepth; + bool mUsesDiscardRewriting; static void *mFragmentCompiler; static void *mVertexCompiler; diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h index 04e877ba..e1861f01 100644 --- a/src/libGLESv2/renderer/Renderer.h +++ b/src/libGLESv2/renderer/Renderer.h @@ -93,6 +93,12 @@ enum ShaderType SHADER_GEOMETRY }; +enum D3DWorkaroundType +{ + ANGLE_D3D_WORKAROUND_NONE, + ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER +}; + class Renderer { public: @@ -207,7 +213,7 @@ class Renderer // Shader operations virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type) = 0; - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) = 0; + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) = 0; // Image operations virtual Image *createImage() = 0; diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp index 150e14c2..13ba355d 100644 --- a/src/libGLESv2/renderer/Renderer11.cpp +++ b/src/libGLESv2/renderer/Renderer11.cpp @@ -2830,7 +2830,7 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length return executable; } -ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) +ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) { const char *profile = NULL; diff --git a/src/libGLESv2/renderer/Renderer11.h b/src/libGLESv2/renderer/Renderer11.h index 90ef04db..b86f485f 100644 --- a/src/libGLESv2/renderer/Renderer11.h +++ b/src/libGLESv2/renderer/Renderer11.h @@ -155,7 +155,7 @@ class Renderer11 : public Renderer // Shader operations virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type); - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type); + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround); // Image operations virtual Image *createImage(); diff --git a/src/libGLESv2/renderer/Renderer9.cpp b/src/libGLESv2/renderer/Renderer9.cpp index d3f3814a..e89f8bdd 100644 --- a/src/libGLESv2/renderer/Renderer9.cpp +++ b/src/libGLESv2/renderer/Renderer9.cpp @@ -3129,7 +3129,7 @@ ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, return executable; } -ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) +ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) { const char *profile = NULL; @@ -3146,7 +3146,11 @@ ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const cha return NULL; } - ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, ANGLE_COMPILE_OPTIMIZATION_LEVEL, true); + // ANGLE issue 486: + // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization + UINT optimizationFlags = (workaround == ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER ? D3DCOMPILE_SKIP_OPTIMIZATION : ANGLE_COMPILE_OPTIMIZATION_LEVEL); + + ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, optimizationFlags, true); if (!binary) return NULL; diff --git a/src/libGLESv2/renderer/Renderer9.h b/src/libGLESv2/renderer/Renderer9.h index f8932c4f..afc2dc1d 100644 --- a/src/libGLESv2/renderer/Renderer9.h +++ b/src/libGLESv2/renderer/Renderer9.h @@ -170,7 +170,7 @@ class Renderer9 : public Renderer // Shader operations virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type); - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type); + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround); // Image operations virtual Image *createImage(); |