Implement hyperbolic function support for ESSL 3.00
Emulating arc hyperbolic functions is required on HLSL, where they do
not exist natively. For this, BuiltInFunctionEmulator is split into GLSL
and HLSL subclasses. The GLSL subclass handles the pre-existing built-in
emulation implemented for working around OSX bugs, and the HLSL subclass
handles emulating asinh, acosh and atanh on HLSL.
BUG=angle:855
Change-Id: I0dfeffb862ac27ba7f9ecf5492ec31d9d952b273
Reviewed-on: https://chromium-review.googlesource.com/236861
Reviewed-by: Nicolas Capens <capn@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 0df2343..bd391a9 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -9,6 +9,7 @@
#include "common/angleutils.h"
#include "common/utilities.h"
#include "common/blocklayout.h"
+#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "compiler/translator/compilerdebug.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/DetectDiscontinuity.h"
@@ -184,11 +185,17 @@
RewriteElseBlocks(mContext.treeRoot);
}
+ BuiltInFunctionEmulatorHLSL builtInFunctionEmulator;
+ builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(mContext.treeRoot);
mContext.treeRoot->traverse(this); // Output the body first to determine what has to go in the header
header();
+ TInfoSinkBase& sink = mContext.infoSink().obj;
+ // Write emulated built-in functions if needed.
+ builtInFunctionEmulator.OutputEmulatedFunctionDefinition(sink, false);
+ builtInFunctionEmulator.Cleanup();
- mContext.infoSink().obj << mHeader.c_str();
- mContext.infoSink().obj << mBody.c_str();
+ sink << mHeader.c_str();
+ sink << mBody.c_str();
}
void OutputHLSL::makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs)
@@ -1781,6 +1788,21 @@
case EOpAsin: outputTriplet(visit, "asin(", "", ")"); break;
case EOpAcos: outputTriplet(visit, "acos(", "", ")"); break;
case EOpAtan: outputTriplet(visit, "atan(", "", ")"); break;
+ case EOpSinh: outputTriplet(visit, "sinh(", "", ")"); break;
+ case EOpCosh: outputTriplet(visit, "cosh(", "", ")"); break;
+ case EOpTanh: outputTriplet(visit, "tanh(", "", ")"); break;
+ case EOpAsinh:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "asinh(");
+ break;
+ case EOpAcosh:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "acosh(");
+ break;
+ case EOpAtanh:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "atanh(");
+ break;
case EOpExp: outputTriplet(visit, "exp(", "", ")"); break;
case EOpLog: outputTriplet(visit, "log(", "", ")"); break;
case EOpExp2: outputTriplet(visit, "exp2(", "", ")"); break;
@@ -2925,4 +2947,10 @@
return constUnion;
}
+void OutputHLSL::writeEmulatedFunctionTriplet(Visit visit, const char *preStr)
+{
+ TString preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr);
+ outputTriplet(visit, preString.c_str(), ", ", ")");
+}
+
}