From d826f82ffe62a8fb53f3b59df07b83d0c7c1093f Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Wed, 12 Mar 2025 18:00:26 -0500 Subject: [PATCH] nak: Implement nir_intrinsic_convert_alu_types We can't support every single form of this instruction but at least it's plumbed through now. Before this will be OpenCL-ready, we'll need to call the NIR lowering pass with an appropriate predicate function. However, for now it lets us use it in NAK-specific NIR lowerings. Reviewed-by: Mel Henning Reviewed-by: Benjamin Lee Part-of: --- src/nouveau/compiler/nak/from_nir.rs | 104 +++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/src/nouveau/compiler/nak/from_nir.rs b/src/nouveau/compiler/nak/from_nir.rs index c308e7b273d..d568e07a679 100644 --- a/src/nouveau/compiler/nak/from_nir.rs +++ b/src/nouveau/compiler/nak/from_nir.rs @@ -283,6 +283,18 @@ impl ShaderFloatControls { } } +fn f_rnd_mode_from_nir(mode: nir_rounding_mode) -> FRndMode { + match mode { + nir_rounding_mode_undef | nir_rounding_mode_rtne => { + FRndMode::NearestEven + } + nir_rounding_mode_ru => FRndMode::PosInf, + nir_rounding_mode_rd => FRndMode::NegInf, + nir_rounding_mode_rtz => FRndMode::Zero, + _ => panic!("Invalid NIR rounding mode"), + } +} + impl Index for ShaderFloatControls { type Output = PerSizeFloatControls; @@ -2161,6 +2173,98 @@ impl<'a> ShaderFromNir<'a> { } self.set_ssa(&intrin.def, dst); } + nir_intrinsic_convert_alu_types => { + let src_base_type = intrin.src_type().base_type(); + let src_bit_size = intrin.src_type().bit_size(); + let dst_base_type = intrin.dest_type().base_type(); + let dst_bit_size = intrin.dest_type().bit_size(); + let rnd_mode = f_rnd_mode_from_nir(intrin.rounding_mode()); + + assert!(srcs[0].as_def().bit_size() == src_bit_size); + assert!(intrin.def.bit_size() == dst_bit_size); + + let def_bits = + intrin.def.bit_size() * intrin.def.num_components(); + let dst = b.alloc_ssa(RegFile::GPR, def_bits.div_ceil(32)); + + match dst_base_type { + ALUType::INT | ALUType::UINT => { + let dst_type = IntType::from_bits( + dst_bit_size.into(), + dst_base_type == ALUType::INT, + ); + match src_base_type { + ALUType::INT | ALUType::UINT => { + let src_type = IntType::from_bits( + src_bit_size.into(), + src_base_type == ALUType::INT, + ); + b.push_op(OpI2I { + dst: dst.into(), + src: self.get_src(&srcs[0]), + src_type, + dst_type, + abs: false, + neg: false, + saturate: intrin.saturate(), + }); + } + ALUType::FLOAT => { + let src_type = + FloatType::from_bits(src_bit_size.into()); + // F2I doesn't support 8-bit destinations + // pre-Volta + assert!(b.sm() >= 70 || dst_bit_size > 8); + b.push_op(OpF2I { + dst: dst.into(), + src: self.get_src(&srcs[0]), + src_type, + dst_type, + rnd_mode, + ftz: self.float_ctl[src_type].ftz, + }); + } + _ => panic!("Unknown src_type"), + } + } + ALUType::FLOAT => { + let dst_type = + FloatType::from_bits(dst_bit_size.into()); + match src_base_type { + ALUType::INT | ALUType::UINT => { + let src_type = IntType::from_bits( + src_bit_size.into(), + src_base_type == ALUType::INT, + ); + b.push_op(OpI2F { + dst: dst.into(), + src: self.get_src(&srcs[0]), + src_type, + dst_type, + rnd_mode, + }); + } + ALUType::FLOAT => { + let src_type = + FloatType::from_bits(src_bit_size.into()); + b.push_op(OpF2F { + dst: dst.into(), + src: self.get_src(&srcs[0]), + src_type, + dst_type, + rnd_mode, + ftz: self.float_ctl[src_type].ftz, + high: false, + integer_rnd: false, + }); + } + _ => panic!("Unknown src_type"), + } + } + _ => panic!("Unknown dest_type"), + } + self.set_dst(&intrin.def, dst); + } nir_intrinsic_ddx | nir_intrinsic_ddx_coarse | nir_intrinsic_ddx_fine => {