diff options
author | Ian Romanick <ian.d.romanick@intel.com> | 2021-10-29 10:50:55 -0700 |
---|---|---|
committer | Dylan Baker <dylan.c.baker@intel.com> | 2022-02-24 14:56:50 -0800 |
commit | 21dfddc2f6cd093dd9cfe986c120bb2133da724c (patch) | |
tree | b10a07dda4943a2c7eb96e1ff5a72e060f6fc54a | |
parent | 1830da60e8d2eb753538e0ec733f02857e607450 (diff) |
nir: Produce correct results for atan with NaN
Properly handling NaN adversely affects several hundred shaders in
shader-db (lots of Skia and a few others from various synthetic
benchmarks) and fossil-db (mostly Talos and some Doom 2016). Only apply
the NaN handling work-around when the shader demands it.
v2: Add comment explaining the 1.0*y_over_x. Suggested by Caio.
Reviewed-by: Caio Oliveira <caio.oliveira@intel.com>
Fixes: 2098ae16c8b ("nir/builder: Move nir_atan and nir_atan2 from SPIR-V translator")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13999>
(cherry picked from commit 1cb3d1a6ae027b5045e47ccf7e551bd81fc3cab2)
-rw-r--r-- | .pick_status.json | 2 | ||||
-rw-r--r-- | src/compiler/nir/nir_builtin_builder.c | 23 |
2 files changed, 23 insertions, 2 deletions
diff --git a/.pick_status.json b/.pick_status.json index 86036c1f6e0..176d8d3c667 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -76,7 +76,7 @@ "description": "nir: Produce correct results for atan with NaN", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "2098ae16c8b4e64d0694a28f74a461b69b98a336" }, diff --git a/src/compiler/nir/nir_builtin_builder.c b/src/compiler/nir/nir_builtin_builder.c index da332e72de9..b975157cfb1 100644 --- a/src/compiler/nir/nir_builtin_builder.c +++ b/src/compiler/nir/nir_builtin_builder.c @@ -223,7 +223,28 @@ nir_atan(nir_builder *b, nir_ssa_def *y_over_x) tmp); /* sign fixup */ - return nir_fmul(b, tmp, nir_fsign(b, y_over_x)); + nir_ssa_def *result = nir_fmul(b, tmp, nir_fsign(b, y_over_x)); + + /* The fmin and fmax above will filter out NaN values. This leads to + * non-NaN results for NaN inputs. Work around this by doing + * + * !isnan(y_over_x) ? ... : y_over_x; + */ + if (b->exact || + nir_is_float_control_signed_zero_inf_nan_preserve(b->shader->info.float_controls_execution_mode, bit_size)) { + const bool exact = b->exact; + + b->exact = true; + nir_ssa_def *is_not_nan = nir_feq(b, y_over_x, y_over_x); + b->exact = exact; + + /* The extra 1.0*y_over_x ensures that subnormal results are flushed to + * zero. + */ + result = nir_bcsel(b, is_not_nan, result, nir_fmul_imm(b, y_over_x, 1.0)); + } + + return result; } nir_ssa_def * |