summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHaixia Shi <[email protected]>2016-12-08 17:41:02 -0800
committerJason Ekstrand <[email protected]>2016-12-09 09:14:20 -0800
commitd4983390a869c3051929858a8b783be53d46b722 (patch)
treec7c959e6a37183dc448915ad3a949d0fec4a9a0b /src
parent7aea08667c673713e1f419539e788eedeea047cb (diff)
compiler/glsl: fix precision problem of tanh
Clamp input scalar value to range [-10, +10] to avoid precision problems when the absolute value of input is too large. Fixes dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.* test failures. v2: added more explanation in the comment. v3: fixed a typo in the comment. Signed-off-by: Haixia Shi <[email protected]> Reviewed-by: Jason Ekstrand <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]> Cc: "13.0" <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/compiler/glsl/builtin_functions.cpp12
1 files changed, 10 insertions, 2 deletions
diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp
index 3e4bcbbd239..3dead1af00f 100644
--- a/src/compiler/glsl/builtin_functions.cpp
+++ b/src/compiler/glsl/builtin_functions.cpp
@@ -3563,9 +3563,17 @@ builtin_builder::_tanh(const glsl_type *type)
ir_variable *x = in_var(type, "x");
MAKE_SIG(type, v130, 1, x);
+ /* Clamp x to [-10, +10] to avoid precision problems.
+ * When x > 10, e^(-x) is so small relative to e^x that it gets flushed to
+ * zero in the computation e^x + e^(-x). The same happens in the other
+ * direction when x < -10.
+ */
+ ir_variable *t = body.make_temp(type, "tmp");
+ body.emit(assign(t, min2(max2(x, imm(-10.0f)), imm(10.0f))));
+
/* (e^x - e^(-x)) / (e^x + e^(-x)) */
- body.emit(ret(div(sub(exp(x), exp(neg(x))),
- add(exp(x), exp(neg(x))))));
+ body.emit(ret(div(sub(exp(t), exp(neg(t))),
+ add(exp(t), exp(neg(t))))));
return sig;
}