mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 11:18:08 +02:00
nir: add lower_fminmax_signed_zero
This implements IEEE-754-2019 signed zero semantics for fmin/fmax, as now required by NIR, for hardware that has busted signed zero behaviour for fmin/fmax. Ian expressed interest in this for Intel. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Ian Romanick <ian.d.romanick@intel.com> Reviewed-by: Konstantin Seurer <konstantin.seurer@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30075>
This commit is contained in:
parent
0e46f7b39a
commit
d238d766c6
2 changed files with 32 additions and 1 deletions
|
|
@ -3807,6 +3807,12 @@ typedef struct nir_shader_compiler_options {
|
||||||
/** enable rules that avoid generating umin from signed integer ops */
|
/** enable rules that avoid generating umin from signed integer ops */
|
||||||
bool lower_umin;
|
bool lower_umin;
|
||||||
|
|
||||||
|
/* lower fmin/fmax with signed zero preserve to fmin/fmax with
|
||||||
|
* no_signed_zero, for backends whose fmin/fmax implementations do not
|
||||||
|
* implement IEEE-754-2019 semantics for signed zero.
|
||||||
|
*/
|
||||||
|
bool lower_fminmax_signed_zero;
|
||||||
|
|
||||||
/* lower fdph to fdot4 */
|
/* lower fdph to fdot4 */
|
||||||
bool lower_fdph;
|
bool lower_fdph;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,30 @@ lower_alu_instr(nir_builder *b, nir_instr *instr_, UNUSED void *cb_data)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case nir_op_fmin:
|
||||||
|
case nir_op_fmax: {
|
||||||
|
if (!b->shader->options->lower_fminmax_signed_zero ||
|
||||||
|
!nir_alu_instr_is_signed_zero_preserve(instr))
|
||||||
|
break;
|
||||||
|
|
||||||
|
nir_def *s0 = nir_ssa_for_alu_src(b, instr, 0);
|
||||||
|
nir_def *s1 = nir_ssa_for_alu_src(b, instr, 1);
|
||||||
|
|
||||||
|
bool max = instr->op == nir_op_fmax;
|
||||||
|
nir_def *iminmax = max ? nir_imax(b, s0, s1) : nir_imin(b, s0, s1);
|
||||||
|
|
||||||
|
/* Lower the fmin/fmax to a no_signed_zero fmin/fmax. This ensures that
|
||||||
|
* nir_lower_alu is idempotent, and allows the backend to implement
|
||||||
|
* soundly the no_signed_zero subset of fmin/fmax.
|
||||||
|
*/
|
||||||
|
b->fp_fast_math &= ~FLOAT_CONTROLS_SIGNED_ZERO_PRESERVE;
|
||||||
|
nir_def *fminmax = max ? nir_fmax(b, s0, s1) : nir_fmin(b, s0, s1);
|
||||||
|
b->fp_fast_math = instr->fp_fast_math;
|
||||||
|
|
||||||
|
lowered = nir_bcsel(b, nir_feq(b, s0, s1), iminmax, fminmax);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -229,7 +253,8 @@ nir_lower_alu(nir_shader *shader)
|
||||||
{
|
{
|
||||||
if (!shader->options->lower_bitfield_reverse &&
|
if (!shader->options->lower_bitfield_reverse &&
|
||||||
!shader->options->lower_bit_count &&
|
!shader->options->lower_bit_count &&
|
||||||
!shader->options->lower_mul_high)
|
!shader->options->lower_mul_high &&
|
||||||
|
!shader->options->lower_fminmax_signed_zero)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return nir_shader_instructions_pass(shader, lower_alu_instr,
|
return nir_shader_instructions_pass(shader, lower_alu_instr,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue