nir: Add saturating float to integer conversion opcodes

v2: Add a comment around has_f2[ui]_sat explaining which opcodes it
enables. Suggested by Georg. Cast u_uintN_max and friends to double in
nir_opcodes.py. This ensures that an exact conversion is made.
Eliminate duplicate conversions from half float to double. Both noticed
by Georg.

v3: Apply "NaN should be zero" fix suggested by Georg.

Co-authored-by: Georg Lehmann <dadschoorse@gmail.com>
Reviewed-by: Georg Lehmann <dadschoorse@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37186>
This commit is contained in:
Ian Romanick 2025-09-08 09:45:55 -07:00 committed by Marge Bot
parent 5ce8b34a10
commit 986086c846
2 changed files with 26 additions and 0 deletions

View file

@ -339,6 +339,19 @@ unop_numeric_convert_mp("u2f", tfloat16, tuint32)
unop_numeric_convert("f2i32_rtne", tint32, tfloat32, "(int32_t)_mesa_roundevenf(src0)")
# Note: 64-bit integers are intentionally not supported. Casting u_uintN_max
# (and related signed values) to double is precisely representable for upto
# 32-bit integers. To support these opcodes for 64-bit integers would require
# a more complex implementation.
for bits in (8, 16, 32):
unop_numeric_convert(f"f2u{bits}_sat", f"uint{bits}", tfloat,
f"(uint{bits}_t)fmin(fmax(src0, 0.0), (double)u_uintN_max({bits}))",
"Convert float to uint with clamping to uint range. NaN becomes zero.")
unop_numeric_convert(f"f2i{bits}_sat", f"int{bits}", tfloat,
f"(int{bits}_t) isnan(src0) ? 0.0 : fmin(fmax(src0, (double)u_intN_min({bits})), (double)u_intN_max({bits}))",
"Convert float to int with clamping to int range. NaN becomes zero.")
# Unary floating-point rounding operations.

View file

@ -486,6 +486,19 @@ typedef struct nir_shader_compiler_options {
*/
bool lower_bfloat16_conversions;
/**
* Set if f2u_sat (or f2i_sat) is supported for converting from 16-, 32-,
* or 64-bit float types to 8-, 16-, or 32-bit integer types (with small
* exceptions).
*
* Due to the prevalence of drivers using \c nir_split_conversion for
* conversions from 64-bit float to 8-bit integer, these flags will not
* enable generation of f2u_sat from 64-bit float types to 8-bit integer
* types.
*/
bool has_f2u_sat;
bool has_f2i_sat;
bool vectorize_tess_levels;
bool lower_to_scalar;
nir_instr_filter_cb lower_to_scalar_filter;