diff options
author | Haixia Shi <hshi@chromium.org> | 2016-12-08 17:41:02 -0800 |
---|---|---|
committer | Emil Velikov <emil.l.velikov@gmail.com> | 2016-12-15 16:46:11 +0000 |
commit | 41c688a6c31ac5b985a3318e082f78103f061977 (patch) | |
tree | a4cb0ad3580b4de34820e36300fc55c97eab0632 | |
parent | 0c2a66c5b6be5457b9aa8411804fdee32394cdd8 (diff) | |
download | external_mesa3d-41c688a6c31ac5b985a3318e082f78103f061977.zip external_mesa3d-41c688a6c31ac5b985a3318e082f78103f061977.tar.gz external_mesa3d-41c688a6c31ac5b985a3318e082f78103f061977.tar.bz2 |
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 <hshi@chromium.org>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Cc: "13.0" <mesa-dev@lists.freedesktop.org>
(cherry picked from commit d4983390a869c3051929858a8b783be53d46b722)
-rw-r--r-- | src/compiler/glsl/builtin_functions.cpp | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp index 3e4bcbb..3dead1a 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; } |