@@ -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
21602204const char * GLSLGenerator::GetSafeIdentifierName (const char * name) const
21612205{
0 commit comments