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: 2098ae16c8 ("nir/builder: Move nir_atan and nir_atan2 from SPIR-V translator")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13999>
This commit is contained in:
Ian Romanick 2021-10-29 10:50:55 -07:00 committed by Marge Bot
parent 7d0d9b9fbc
commit 1cb3d1a6ae
1 changed files with 22 additions and 1 deletions

View File

@ -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 *