Skip to content

Commit 1843752

Browse files
yoyofrkblaschke
authored andcommitted
Apply possible HLSL compiler optimization for pow() function with literal 1 as exponent
Signed-off-by: Kai Blaschke <kai.blaschke@kb-dev.net>
1 parent 2ed1df6 commit 1843752

File tree

1 file changed

+56
-12
lines changed

1 file changed

+56
-12
lines changed

vendor/hlslparser/src/GLSLGenerator.cpp

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ GLSLGenerator::GLSLGenerator() :
119119
#else
120120
m_version = Version_330;
121121
#endif
122-
122+
123123
m_versionLegacy = false;
124124
m_inAttribPrefix = NULL;
125125
m_outAttribPrefix = NULL;
@@ -244,7 +244,7 @@ bool GLSLGenerator::Generate(HLSLTree* tree, Target target, Version version, con
244244
m_writer.WriteLine(0, "precision highp float;");
245245
}
246246
else if (m_version == Version_300_ES)
247-
{
247+
{
248248
m_writer.WriteLine(0, "#version 300 es");
249249
m_writer.WriteLine(0, "precision highp float;");
250250
m_writer.WriteLine(0, "precision highp sampler3D;");
@@ -420,7 +420,7 @@ bool GLSLGenerator::Generate(HLSLTree* tree, Target target, Version version, con
420420
* domain. To do this, we bail out to a separate function that piecewise-defines
421421
* a polynomial that qualitatively matches what we see under DX9. The DX9
422422
* implementation itself is unknown, so this is only a rough match.
423-
*
423+
*
424424
* We also implement this as a separate function because we need to evaluate the
425425
* argument multiple times. If the argument expression involves side-effects
426426
* (such as post-increment or -decrement) the result would not be what we expect
@@ -547,7 +547,7 @@ void GLSLGenerator::OutputExpressionList(HLSLExpression* expression, HLSLArgumen
547547
{
548548
m_writer.Write(", ");
549549
}
550-
550+
551551
HLSLType* expectedType = NULL;
552552
if (argument != NULL)
553553
{
@@ -1028,16 +1028,60 @@ void GLSLGenerator::OutputExpression(HLSLExpression* expression, const HLSLType*
10281028
Error("%s expects 2 arguments", functionName);
10291029
return;
10301030
}
1031+
10311032
/* See rsqrt above regarding abs(). Note that this behaves
10321033
* as expected on some drivers but not others, so we add
10331034
* the abs() call for compatibility across drivers.
1035+
*
1036+
* There's one special case though: if the exponent is a literal "1" (or "1.0"),
1037+
* don't use pow() at all, just return the base (arg 1) unchanged, even if negative.
1038+
* This is probably due to an HLSL compiler optimization which does the same thing.
1039+
* When not optimized, pow(x, 1) with a negative value of x would return NaN instead.
10341040
*/
1035-
m_writer.Write("pow(abs(");
1036-
OutputExpression(argument[0], &functionCall->function->returnType);
1037-
m_writer.Write("),");
1038-
OutputExpression(argument[1], &functionCall->function->returnType);
1039-
m_writer.Write(")");
1040-
handled = true;
1041+
if (argument[1]->nodeType == HLSLNodeType_LiteralExpression)
1042+
{
1043+
HLSLLiteralExpression* literalExpression = static_cast<HLSLLiteralExpression*>(argument[1]);
1044+
float value = 0.0;
1045+
bool found = false;
1046+
switch (literalExpression->type)
1047+
{
1048+
case HLSLBaseType_Float:
1049+
value = literalExpression->fValue;
1050+
found = true;
1051+
break;
1052+
case HLSLBaseType_Int:
1053+
case HLSLBaseType_Uint:
1054+
value = literalExpression->iValue;
1055+
found = true;
1056+
break;
1057+
case HLSLBaseType_Bool:
1058+
value = literalExpression->bValue;
1059+
found = true;
1060+
break;
1061+
default:
1062+
break;
1063+
}
1064+
1065+
// Replace the function call with just arg 1.
1066+
if (found && value == 1.0)
1067+
{
1068+
m_writer.Write("(");
1069+
OutputExpression(argument[0], &functionCall->function->returnType);
1070+
m_writer.Write(")");
1071+
handled = true;
1072+
}
1073+
}
1074+
1075+
// Other cases, including variable exponent arguments, will still call pow().
1076+
if (!handled)
1077+
{
1078+
m_writer.Write("pow(abs(");
1079+
OutputExpression(argument[0], &functionCall->function->returnType);
1080+
m_writer.Write("),");
1081+
OutputExpression(argument[1], &functionCall->function->returnType);
1082+
m_writer.Write(")");
1083+
handled = true;
1084+
}
10411085
}
10421086
else if (String_Equal(functionName, "ldexp"))
10431087
{
@@ -1173,7 +1217,7 @@ void GLSLGenerator::OutputIdentifier(const char* name)
11731217
{
11741218
name = m_asinFunction;
11751219
}
1176-
else
1220+
else
11771221
{
11781222
// The identifier could be a GLSL reserved word (if it's not also a HLSL reserved word).
11791223
name = GetSafeIdentifierName(name);
@@ -2155,7 +2199,7 @@ void GLSLGenerator::Error(const char* format, ...)
21552199
va_start(arg, format);
21562200
Log_ErrorArgList(format, arg);
21572201
va_end(arg);
2158-
}
2202+
}
21592203

21602204
const char* GLSLGenerator::GetSafeIdentifierName(const char* name) const
21612205
{

0 commit comments

Comments
 (0)