Prevent atan2 from generating a NaN

TRAC #12184 This is necessary because a NaN generated in flattened conditional code fails to get discarded on certain devices. Signed-off-by: Shannon Woods Signed-off-by: Daniel Koch Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@248 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent adf02846
...@@ -50,6 +50,7 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr ...@@ -50,6 +50,7 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr
mUsesEqualBVec2 = false; mUsesEqualBVec2 = false;
mUsesEqualBVec3 = false; mUsesEqualBVec3 = false;
mUsesEqualBVec4 = false; mUsesEqualBVec4 = false;
mUsesAtan2 = false;
mArgumentIndex = 0; mArgumentIndex = 0;
} }
...@@ -675,6 +676,15 @@ void OutputHLSL::header() ...@@ -675,6 +676,15 @@ void OutputHLSL::header()
" return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n" " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
"}\n"; "}\n";
} }
if (mUsesAtan2)
{
out << "float atanyx(float y, float x)\n"
"{\n"
" if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN
" return atan2(y, x);\n"
"}\n";
}
} }
void OutputHLSL::footer() void OutputHLSL::footer()
...@@ -1450,15 +1460,9 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -1450,15 +1460,9 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpMod: outputTriplet(visit, "mod(", ", ", ")"); break; case EOpMod: outputTriplet(visit, "mod(", ", ", ")"); break;
case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break; case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break;
case EOpAtan: case EOpAtan:
if (node->getSequence().size() == 1) ASSERT(node->getSequence().size() == 2); // atan(x) is a unary operator
{ mUsesAtan2 = true;
outputTriplet(visit, "atan(", ", ", ")"); outputTriplet(visit, "atanyx(", ", ", ")");
}
else if (node->getSequence().size() == 2)
{
outputTriplet(visit, "atan2(", ", ", ")");
}
else UNREACHABLE();
break; break;
case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break; case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break;
case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break; case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break;
......
...@@ -89,6 +89,7 @@ class OutputHLSL : public TIntermTraverser ...@@ -89,6 +89,7 @@ class OutputHLSL : public TIntermTraverser
bool mUsesEqualBVec2; bool mUsesEqualBVec2;
bool mUsesEqualBVec3; bool mUsesEqualBVec3;
bool mUsesEqualBVec4; bool mUsesEqualBVec4;
bool mUsesAtan2;
struct Constructor // Describes a constructor signature struct Constructor // Describes a constructor signature
{ {
......
...@@ -895,7 +895,7 @@ ID3DXBuffer *Program::compileToBinary(const char *hlsl, const char *profile, ID3 ...@@ -895,7 +895,7 @@ ID3DXBuffer *Program::compileToBinary(const char *hlsl, const char *profile, ID3
ID3DXBuffer *binary = NULL; ID3DXBuffer *binary = NULL;
ID3DXBuffer *errorMessage = NULL; ID3DXBuffer *errorMessage = NULL;
HRESULT result = D3DXCompileShader(hlsl, (UINT)strlen(hlsl), NULL, 0, "main", profile, 0, &binary, &errorMessage, constantTable); HRESULT result = D3DXCompileShader(hlsl, (UINT)strlen(hlsl), NULL, NULL, "main", profile, 0, &binary, &errorMessage, constantTable);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
......
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