From 62fc70d62b2909a991a67805bd7059ea8e851fee Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Oct 2021 10:51:25 -0700 Subject: [PATCH] spirv: Produce correct result for GLSLstd450Tanh with NaN No shader-db or fossil-db changes on any Intel platform. Reviewed-by: Caio Oliveira Fixes: 9f9432d56c0 ("Revert "spirv: Use a simpler and more correct implementaiton of tanh()"") Part-of: (cherry picked from commit 93ed87af28e7f5b7db7bae095e5a37b63b7bd2c7) --- .pick_status.json | 2 +- src/compiler/spirv/vtn_glsl450.c | 34 +++++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 3cc6f7baf19..a77e2c205ba 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -3811,7 +3811,7 @@ "description": "spirv: Produce correct result for GLSLstd450Tanh with NaN", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "9f9432d56c055b9704a76cad44da88d5e12f825c" }, diff --git a/src/compiler/spirv/vtn_glsl450.c b/src/compiler/spirv/vtn_glsl450.c index 21f5fa80973..045ffb41832 100644 --- a/src/compiler/spirv/vtn_glsl450.c +++ b/src/compiler/spirv/vtn_glsl450.c @@ -520,11 +520,35 @@ handle_glsl450_alu(struct vtn_builder *b, enum GLSLstd450 entrypoint, nir_ssa_def *x = nir_fclamp(nb, src[0], nir_imm_floatN_t(nb, -clamped_x, bit_size), nir_imm_floatN_t(nb, clamped_x, bit_size)); - dest->def = - nir_fdiv(nb, nir_fsub(nb, nir_fexp(nb, x), - nir_fexp(nb, nir_fneg(nb, x))), - nir_fadd(nb, nir_fexp(nb, x), - nir_fexp(nb, nir_fneg(nb, x)))); + + /* The clamping will filter out NaN values causing an incorrect result. + * The comparison is carefully structured to get NaN result for NaN and + * get -0 for -0. + * + * result = abs(s) > 0.0 ? ... : s; + */ + const bool exact = nb->exact; + + nb->exact = true; + nir_ssa_def *is_regular = nir_flt(nb, + nir_imm_floatN_t(nb, 0, bit_size), + nir_fabs(nb, src[0])); + + /* The extra 1.0*s ensures that subnormal inputs are flushed to zero + * when that is selected by the shader. + */ + nir_ssa_def *flushed = nir_fmul(nb, + src[0], + nir_imm_floatN_t(nb, 1.0, bit_size)); + nb->exact = exact; + + dest->def = nir_bcsel(nb, + is_regular, + nir_fdiv(nb, nir_fsub(nb, nir_fexp(nb, x), + nir_fexp(nb, nir_fneg(nb, x))), + nir_fadd(nb, nir_fexp(nb, x), + nir_fexp(nb, nir_fneg(nb, x)))), + flushed); break; }