Commit 44efa0b8 by Arun Patole Committed by Jamie Madill

Conditionally enable IEEE strictness for isnan()

ANGLE's ESSL3 built-in function isnan() implementation just uses HLSL intrinsic function isnan(). For HLSL intrinsic function isnan() to work properly, IEEE strictness needs to be enabled for D3D compiler. This change detects use of isnan() in shaders and passes compiler flag D3DCOMPILE_IEEE_STRICTNESS whenever isnan is used in shaders. This change also moves existing workarounds in D3DWorkaroundType to D3DCompilerWorkarounds. BUG=angle:927 TEST= dEQP tests dEQP-GLES3.functional.shaders.builtin_functions.common.isnan.* Change-Id: I1ce5b1a7a825fdd720a37dc9aeb71320e55162d9 Reviewed-on: https://chromium-review.googlesource.com/255834Reviewed-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 56d1003e
......@@ -126,6 +126,7 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType, int shaderVersion,
mUsesXor = false;
mUsesDiscardRewriting = false;
mUsesNestedBreak = false;
mRequiresIEEEStrictCompiling = false;
mUniqueIndex = 0;
......@@ -353,6 +354,11 @@ void OutputHLSL::header(const BuiltInFunctionEmulator *builtInFunctionEmulator)
out << "#define ANGLE_USES_NESTED_BREAK\n";
}
if (mRequiresIEEEStrictCompiling)
{
out << "#define ANGLE_REQUIRES_IEEE_STRICT_COMPILING\n";
}
out << "#ifdef ANGLE_ENABLE_LOOP_FLATTEN\n"
"#define LOOP [loop]\n"
"#define FLATTEN [flatten]\n"
......@@ -1690,7 +1696,10 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
break;
case EOpCeil: outputTriplet(visit, "ceil(", "", ")"); break;
case EOpFract: outputTriplet(visit, "frac(", "", ")"); break;
case EOpIsNan: outputTriplet(visit, "isnan(", "", ")"); break;
case EOpIsNan:
outputTriplet(visit, "isnan(", "", ")");
mRequiresIEEEStrictCompiling = true;
break;
case EOpIsInf: outputTriplet(visit, "isinf(", "", ")"); break;
case EOpFloatBitsToInt: outputTriplet(visit, "asint(", "", ")"); break;
case EOpFloatBitsToUint: outputTriplet(visit, "asuint(", "", ")"); break;
......
......@@ -155,6 +155,8 @@ class OutputHLSL : public TIntermTraverser
bool mUsesXor;
bool mUsesDiscardRewriting;
bool mUsesNestedBreak;
bool mRequiresIEEEStrictCompiling;
int mNumRenderTargets;
......
......@@ -16,11 +16,28 @@
namespace rx
{
enum D3DWorkaroundType
struct D3DCompilerWorkarounds
{
ANGLE_D3D_WORKAROUND_NONE,
ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION,
ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION
D3DCompilerWorkarounds()
: skipOptimization(false),
useMaxOptimization(false),
enableIEEEStrictness(false)
{}
void reset()
{
skipOptimization = false;
useMaxOptimization = false;
enableIEEEStrictness = false;
}
bool skipOptimization;
bool useMaxOptimization;
// IEEE strictness needs to be enabled for NANs to work.
bool enableIEEEStrictness;
DISALLOW_COPY_AND_ASSIGN(D3DCompilerWorkarounds)
};
struct Workarounds
......
......@@ -178,8 +178,6 @@ ProgramD3D::ProgramD3D(RendererD3D *renderer)
mRenderer(renderer),
mDynamicHLSL(NULL),
mGeometryExecutable(NULL),
mVertexWorkarounds(ANGLE_D3D_WORKAROUND_NONE),
mPixelWorkarounds(ANGLE_D3D_WORKAROUND_NONE),
mUsesPointSize(false),
mVertexUniformStorage(NULL),
mFragmentUniformStorage(NULL),
......@@ -543,9 +541,9 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
}
stream->readString(&mVertexHLSL);
stream->readInt(&mVertexWorkarounds);
stream->readBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds));
stream->readString(&mPixelHLSL);
stream->readInt(&mPixelWorkarounds);
stream->readBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds));
stream->readBool(&mUsesFragDepth);
stream->readBool(&mUsesPointSize);
......@@ -766,9 +764,9 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
}
stream->writeString(mVertexHLSL);
stream->writeInt(mVertexWorkarounds);
stream->writeBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds));
stream->writeString(mPixelHLSL);
stream->writeInt(mPixelWorkarounds);
stream->writeBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds));
stream->writeInt(mUsesFragDepth);
stream->writeInt(mUsesPointSize);
......@@ -987,7 +985,7 @@ LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shade
error = mRenderer->compileToExecutable(infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
ANGLE_D3D_WORKAROUND_NONE, &mGeometryExecutable);
D3DCompilerWorkarounds(), &mGeometryExecutable);
if (error.isError())
{
return LinkResult(false, error);
......@@ -1035,10 +1033,10 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog,
mTransformFeedbackBufferMode = transformFeedbackBufferMode;
mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds();
fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
mVertexHLSL = vertexShaderD3D->getTranslatedSource();
mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds();
vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
mShaderVersion = vertexShaderD3D->getShaderVersion();
// Map the varyings to the register file
......@@ -1941,11 +1939,11 @@ void ProgramD3D::reset()
mTransformFeedbackBufferMode = GL_NONE;
mVertexHLSL.clear();
mVertexWorkarounds = ANGLE_D3D_WORKAROUND_NONE;
mVertexWorkarounds.reset();
mShaderVersion = 100;
mPixelHLSL.clear();
mPixelWorkarounds = ANGLE_D3D_WORKAROUND_NONE;
mPixelWorkarounds.reset();
mUsesFragDepth = false;
mPixelShaderKey.clear();
mUsesPointSize = false;
......
......@@ -205,10 +205,10 @@ class ProgramD3D : public ProgramImpl
ShaderExecutableD3D *mGeometryExecutable;
std::string mVertexHLSL;
D3DWorkaroundType mVertexWorkarounds;
D3DCompilerWorkarounds mVertexWorkarounds;
std::string mPixelHLSL;
D3DWorkaroundType mPixelWorkarounds;
D3DCompilerWorkarounds mPixelWorkarounds;
bool mUsesFragDepth;
std::vector<PixelShaderOutputVariable> mPixelShaderKey;
......
......@@ -141,7 +141,7 @@ class RendererD3D : public Renderer
bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) = 0;
virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround,
bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable) = 0;
virtual UniformStorageD3D *createUniformStorage(size_t storageSize) = 0;
......
......@@ -106,18 +106,19 @@ void ShaderD3D::parseVaryings(ShHandle compiler)
mVaryings.push_back(gl::PackedVarying((*varyings)[varyingIndex]));
}
mUsesMultipleRenderTargets = mTranslatedSource.find("GL_USES_MRT") != std::string::npos;
mUsesFragColor = mTranslatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos;
mUsesFragData = mTranslatedSource.find("GL_USES_FRAG_DATA") != std::string::npos;
mUsesFragCoord = mTranslatedSource.find("GL_USES_FRAG_COORD") != std::string::npos;
mUsesFrontFacing = mTranslatedSource.find("GL_USES_FRONT_FACING") != std::string::npos;
mUsesPointSize = mTranslatedSource.find("GL_USES_POINT_SIZE") != std::string::npos;
mUsesPointCoord = mTranslatedSource.find("GL_USES_POINT_COORD") != std::string::npos;
mUsesDepthRange = mTranslatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos;
mUsesFragDepth = mTranslatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos;
mUsesDiscardRewriting = mTranslatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
mUsesNestedBreak = mTranslatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
mUsesDeferredInit = mTranslatedSource.find("ANGLE_USES_DEFERRED_INIT") != std::string::npos;
mUsesMultipleRenderTargets = mTranslatedSource.find("GL_USES_MRT") != std::string::npos;
mUsesFragColor = mTranslatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos;
mUsesFragData = mTranslatedSource.find("GL_USES_FRAG_DATA") != std::string::npos;
mUsesFragCoord = mTranslatedSource.find("GL_USES_FRAG_COORD") != std::string::npos;
mUsesFrontFacing = mTranslatedSource.find("GL_USES_FRONT_FACING") != std::string::npos;
mUsesPointSize = mTranslatedSource.find("GL_USES_POINT_SIZE") != std::string::npos;
mUsesPointCoord = mTranslatedSource.find("GL_USES_POINT_COORD") != std::string::npos;
mUsesDepthRange = mTranslatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos;
mUsesFragDepth = mTranslatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos;
mUsesDiscardRewriting = mTranslatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
mUsesNestedBreak = mTranslatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
mUsesDeferredInit = mTranslatedSource.find("ANGLE_USES_DEFERRED_INIT") != std::string::npos;
mRequiresIEEEStrictCompiling = mTranslatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos;
}
}
......@@ -150,6 +151,7 @@ void ShaderD3D::uncompile()
mUsesDiscardRewriting = false;
mUsesNestedBreak = false;
mUsesDeferredInit = false;
mRequiresIEEEStrictCompiling = false;
mVaryings.clear();
mUniforms.clear();
......@@ -264,24 +266,27 @@ void ShaderD3D::compileToHLSL(ShHandle compiler, const std::string &source)
}
}
D3DWorkaroundType ShaderD3D::getD3DWorkarounds() const
void ShaderD3D::generateWorkarounds(D3DCompilerWorkarounds *workarounds) const
{
if (mUsesDiscardRewriting)
{
// ANGLE issue 486:
// Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
return ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION;
workarounds->skipOptimization = true;
}
if (mUsesNestedBreak)
else if (mUsesNestedBreak)
{
// ANGLE issue 603:
// Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization
// We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence
return ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION;
workarounds->useMaxOptimization = true;
}
return ANGLE_D3D_WORKAROUND_NONE;
if (mRequiresIEEEStrictCompiling)
{
// IEEE Strictness for D3D compiler needs to be enabled for NaNs to work.
workarounds->enableIEEEStrictness = true;
}
}
// true if varying x has a higher priority in packing than y
......
......@@ -41,7 +41,7 @@ class ShaderD3D : public ShaderImpl
unsigned int getInterfaceBlockRegister(const std::string &blockName) const;
void appendDebugInfo(const std::string &info) { mDebugInfo += info; }
D3DWorkaroundType getD3DWorkarounds() const;
void generateWorkarounds(D3DCompilerWorkarounds *workarounds) const;
int getShaderVersion() const { return mShaderVersion; }
bool usesDepthRange() const { return mUsesDepthRange; }
bool usesPointSize() const { return mUsesPointSize; }
......@@ -78,6 +78,7 @@ class ShaderD3D : public ShaderImpl
bool mUsesDiscardRewriting;
bool mUsesNestedBreak;
bool mUsesDeferredInit;
bool mRequiresIEEEStrictCompiling;
ShShaderOutput mCompilerOutputType;
std::string mDebugInfo;
......
......@@ -2742,7 +2742,7 @@ gl::Error Renderer11::loadExecutable(const void *function, size_t length, Shader
gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround,
bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable)
{
const char *profileType = NULL;
......@@ -2775,6 +2775,9 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin
flags |= D3DCOMPILE_DEBUG;
}
if (workarounds.enableIEEEStrictness)
flags |= D3DCOMPILE_IEEE_STRICTNESS;
// Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
// Try the default flags first and if compilation fails, try some alternatives.
std::vector<CompileConfig> configs;
......
......@@ -163,7 +163,7 @@ class Renderer11 : public RendererD3D
bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable);
virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround,
bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable);
virtual UniformStorageD3D *createUniformStorage(size_t storageSize);
......
......@@ -2711,7 +2711,7 @@ gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderT
gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround,
bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable)
{
// Transform feedback is not supported in ES2 or D3D9
......@@ -2736,15 +2736,14 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string
UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL;
if (workaround == ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION)
if (workarounds.skipOptimization)
{
flags = D3DCOMPILE_SKIP_OPTIMIZATION;
}
else if (workaround == ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION)
else if (workarounds.useMaxOptimization)
{
flags = D3DCOMPILE_OPTIMIZATION_LEVEL3;
}
else ASSERT(workaround == ANGLE_D3D_WORKAROUND_NONE);
if (gl::perfActive())
{
......
......@@ -172,7 +172,7 @@ class Renderer9 : public RendererD3D
bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable);
virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround,
bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable);
virtual UniformStorageD3D *createUniformStorage(size_t storageSize);
......
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