summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2021-10-29 10:50:55 -0700
committerEric Engestrom <eric@engestrom.ch>2022-02-23 17:55:55 +0000
commit72e5c056ae86630829dbb23594c07257819ec395 (patch)
tree7f812ed8c3477be4a4ccd7c7a52b7f8af26ce62f
parentbbfcf5b3aa97a24731c92fe0b0a4ba6d8a6db102 (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.json2
-rw-r--r--src/compiler/nir/nir_builtin_builder.c23
2 files changed, 23 insertions, 2 deletions
diff --git a/.pick_status.json b/.pick_status.json
index 11a9e423ee8..dc4c84544b2 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -3793,7 +3793,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 *