diff --git a/src/nouveau/compiler/nak_encode_sm75.rs b/src/nouveau/compiler/nak_encode_sm75.rs index 75f5e3ec6ee..6e38ecc8114 100644 --- a/src/nouveau/compiler/nak_encode_sm75.rs +++ b/src/nouveau/compiler/nak_encode_sm75.rs @@ -618,6 +618,23 @@ impl SM75Instr { self.set_bit(80, false /* HI */); } + fn encode_f2i(&mut self, op: &OpF2I) { + self.encode_alu( + 0x105, + Some(op.dst), + ALUSrc::None, + ALUSrc::from_src(&op.src.into()), + ALUSrc::None, + ); + self.set_bit(72, op.dst_type.is_signed()); + self.set_field(75..77, op.dst_type.bytes().ilog2()); + self.set_bit(77, false); /* NTZ */ + self.set_rnd_mode(78..80, op.rnd_mode); + self.set_bit(80, false); /* FTZ */ + self.set_bit(81, false); /* DNZ */ + self.set_field(84..86, op.src_type.bytes().ilog2()); + } + fn encode_i2f(&mut self, op: &OpI2F) { self.encode_alu( 0x106, @@ -860,6 +877,7 @@ impl SM75Instr { Op::ISetP(op) => si.encode_isetp(&op), Op::Lop3(op) => si.encode_lop3(&op), Op::Shl(op) => si.encode_shl(&op), + Op::F2I(op) => si.encode_f2i(&op), Op::I2F(op) => si.encode_i2f(&op), Op::Mov(op) => si.encode_mov(&op), Op::Sel(op) => si.encode_sel(&op), diff --git a/src/nouveau/compiler/nak_from_nir.rs b/src/nouveau/compiler/nak_from_nir.rs index 326435228e5..f41612caa80 100644 --- a/src/nouveau/compiler/nak_from_nir.rs +++ b/src/nouveau/compiler/nak_from_nir.rs @@ -156,6 +156,18 @@ impl<'a> ShaderFromNir<'a> { self.instrs .push(Instr::new_sel(dst, srcs[0], srcs[1], srcs[2])); } + nir_op_f2i32 | nir_op_f2u32 => { + let src_bits = usize::from(alu.get_src(0).bit_size()); + let dst_bits = usize::from(alu.def.bit_size()); + let dst_is_signed = alu.info().output_type & 2 != 0; + self.instrs.push(Instr::new(Op::F2I(OpF2I { + dst: dst, + src: srcs[0], + src_type: FloatType::from_bytes(src_bits / 8), + dst_type: IntType::from_bytes(dst_bits / 8, dst_is_signed), + rnd_mode: FRndMode::Zero, + }))); + } nir_op_fabs => { self.instrs.push(Instr::new(Op::FMov(OpFMov { dst: dst, diff --git a/src/nouveau/compiler/nak_ir.rs b/src/nouveau/compiler/nak_ir.rs index d30f735ffd2..705641e4250 100644 --- a/src/nouveau/compiler/nak_ir.rs +++ b/src/nouveau/compiler/nak_ir.rs @@ -812,6 +812,15 @@ pub enum FloatType { } impl FloatType { + pub fn from_bytes(bytes: usize) -> FloatType { + match bytes { + 2 => FloatType::F16, + 4 => FloatType::F32, + 8 => FloatType::F64, + _ => panic!("Invalid float type size"), + } + } + pub fn bytes(&self) -> usize { match self { FloatType::F16 => 2, @@ -862,6 +871,40 @@ pub enum IntType { } impl IntType { + pub fn from_bytes(bytes: usize, is_signed: bool) -> IntType { + match bytes { + 1 => { + if is_signed { + IntType::I8 + } else { + IntType::U8 + } + } + 2 => { + if is_signed { + IntType::I16 + } else { + IntType::U16 + } + } + 4 => { + if is_signed { + IntType::I32 + } else { + IntType::U32 + } + } + 8 => { + if is_signed { + IntType::I64 + } else { + IntType::U64 + } + } + _ => panic!("Invalid integer type size"), + } + } + pub fn is_signed(&self) -> bool { match self { IntType::U8 | IntType::U16 | IntType::U32 | IntType::U64 => false, @@ -1277,6 +1320,26 @@ impl fmt::Display for OpShl { } } +#[repr(C)] +#[derive(SrcsAsSlice, DstsAsSlice)] +pub struct OpF2I { + pub dst: Dst, + pub src: Src, + pub src_type: FloatType, + pub dst_type: IntType, + pub rnd_mode: FRndMode, +} + +impl fmt::Display for OpF2I { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "F2I.{}.{}.{} {} {}", + self.dst_type, self.src_type, self.rnd_mode, self.dst, self.src, + ) + } +} + #[repr(C)] #[derive(SrcsAsSlice, DstsAsSlice)] pub struct OpI2F { @@ -1801,6 +1864,7 @@ pub enum Op { ISetP(OpISetP), Lop3(OpLop3), Shl(OpShl), + F2I(OpF2I), I2F(OpI2F), Mov(OpMov), Sel(OpSel), @@ -2269,7 +2333,7 @@ impl Instr { | Op::PLop3(_) | Op::ISetP(_) | Op::Shl(_) => Some(6), - Op::I2F(_) | Op::Mov(_) => Some(15), + Op::F2I(_) | Op::I2F(_) | Op::Mov(_) => Some(15), Op::MuFu(_) => None, Op::Sel(_) => Some(15), Op::S2R(_) => None,