diff --git a/src/nouveau/compiler/nak/ir.rs b/src/nouveau/compiler/nak/ir.rs index a4ab1deb114..ae05ff6345f 100644 --- a/src/nouveau/compiler/nak/ir.rs +++ b/src/nouveau/compiler/nak/ir.rs @@ -2104,6 +2104,18 @@ pub enum TexLodMode { BiasClamp, } +impl TexLodMode { + pub fn is_explicit_lod(&self) -> bool { + match self { + TexLodMode::Auto + | TexLodMode::Bias + | TexLodMode::Clamp + | TexLodMode::BiasClamp => false, + TexLodMode::Zero | TexLodMode::Lod => true, + } + } +} + impl fmt::Display for TexLodMode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { diff --git a/src/nouveau/compiler/nak/nvdisasm_tests.rs b/src/nouveau/compiler/nak/nvdisasm_tests.rs index f1c120c83b8..b3b2877c8c4 100644 --- a/src/nouveau/compiler/nak/nvdisasm_tests.rs +++ b/src/nouveau/compiler/nak/nvdisasm_tests.rs @@ -305,3 +305,174 @@ pub fn test_ld_st_atom() { c.check(sm); } } + +#[test] +pub fn test_texture() { + let r0 = RegRef::new(RegFile::GPR, 0, 1); + let r1 = RegRef::new(RegFile::GPR, 1, 1); + let r2 = RegRef::new(RegFile::GPR, 2, 1); + let r3 = RegRef::new(RegFile::GPR, 3, 1); + let p0 = RegRef::new(RegFile::Pred, 0, 1); + + let lod_modes = [ + TexLodMode::Auto, + TexLodMode::Zero, + TexLodMode::Lod, + TexLodMode::Bias, + TexLodMode::Clamp, + TexLodMode::BiasClamp, + ]; + + let tld4_offset_modes = [ + Tld4OffsetMode::None, + Tld4OffsetMode::AddOffI, + Tld4OffsetMode::PerPx, + ]; + + let tex_queries = [ + TexQuery::Dimension, + TexQuery::TextureType, + TexQuery::SamplerPos, + ]; + + for sm in SM_LIST { + let mut c = DisasmCheck::new(); + for lod_mode in lod_modes { + let lod_mode_str = if lod_mode == TexLodMode::Auto { + String::new() + } else { + format!(".{lod_mode}") + }; + if lod_mode == TexLodMode::BiasClamp && sm >= 100 { + continue; + } + + let instr = OpTex { + dsts: [Dst::Reg(r0), Dst::Reg(r2)], + fault: Dst::Reg(p0), + + tex: TexRef::Bindless, + + srcs: [SrcRef::Reg(r1).into(), SrcRef::Reg(r3).into()], + + dim: TexDim::_2D, + lod_mode, + z_cmpr: false, + offset: false, + mem_eviction_priority: MemEvictionPriority::First, + nodep: true, + channel_mask: ChannelMask::for_comps(3), + }; + c.push( + instr, + format!( + "tex.b{lod_mode_str}.ef.nodep p0, r2, r0, r1, r3, 2d, 0x7;" + ), + ); + + if lod_mode.is_explicit_lod() { + let instr = OpTld { + dsts: [Dst::Reg(r0), Dst::Reg(r2)], + fault: Dst::Reg(p0), + + tex: TexRef::Bindless, + + srcs: [SrcRef::Reg(r1).into(), SrcRef::Reg(r3).into()], + + dim: TexDim::_2D, + is_ms: false, + lod_mode, + offset: false, + mem_eviction_priority: MemEvictionPriority::First, + nodep: true, + channel_mask: ChannelMask::for_comps(3), + }; + c.push( + instr, + format!("tld.b{lod_mode_str}.ef.nodep p0, r2, r0, r1, r3, 2d, 0x7;"), + ); + } + } + + for offset_mode in tld4_offset_modes { + let offset_mode_str = if offset_mode == Tld4OffsetMode::None { + String::new() + } else { + format!(".{offset_mode}") + }; + + let instr = OpTld4 { + dsts: [Dst::Reg(r0), Dst::Reg(r2)], + fault: Dst::Reg(p0), + + tex: TexRef::Bindless, + + srcs: [SrcRef::Reg(r1).into(), SrcRef::Reg(r3).into()], + + dim: TexDim::_2D, + comp: 1, + offset_mode, + z_cmpr: false, + mem_eviction_priority: MemEvictionPriority::First, + nodep: true, + channel_mask: ChannelMask::for_comps(3), + }; + c.push( + instr, + format!("tld4.g.b{offset_mode_str}.ef.nodep p0, r2, r0, r1, r3, 2d, 0x7;"), + ); + } + + let instr = OpTmml { + dsts: [Dst::Reg(r0), Dst::Reg(r2)], + + tex: TexRef::Bindless, + + srcs: [SrcRef::Reg(r1).into(), SrcRef::Reg(r3).into()], + + dim: TexDim::_2D, + nodep: true, + channel_mask: ChannelMask::for_comps(3), + }; + c.push(instr, format!("tmml.b.lod.nodep r2, r0, r1, r3, 2d, 0x7;")); + + let instr = OpTxd { + dsts: [Dst::Reg(r0), Dst::Reg(r2)], + fault: Dst::Reg(p0), + + tex: TexRef::Bindless, + + srcs: [SrcRef::Reg(r1).into(), SrcRef::Reg(r3).into()], + + dim: TexDim::_2D, + offset: false, + mem_eviction_priority: MemEvictionPriority::First, + nodep: true, + channel_mask: ChannelMask::for_comps(3), + }; + c.push( + instr, + format!("txd.b.ef.nodep p0, r2, r0, r1, r3, 2d, 0x7;"), + ); + + for tex_query in tex_queries { + let instr = OpTxq { + dsts: [Dst::Reg(r0), Dst::Reg(r2)], + + tex: TexRef::Bindless, + + src: SrcRef::Reg(r1).into(), + + query: tex_query, + nodep: true, + channel_mask: ChannelMask::for_comps(3), + }; + c.push( + instr, + format!("txq.b.nodep r2, r0, r1, tex_header_{tex_query}, 0x7;"), + ); + } + + c.check(sm); + } +} diff --git a/src/nouveau/compiler/nak/sm70_encode.rs b/src/nouveau/compiler/nak/sm70_encode.rs index 57de2130ee5..7728b352525 100644 --- a/src/nouveau/compiler/nak/sm70_encode.rs +++ b/src/nouveau/compiler/nak/sm70_encode.rs @@ -2306,17 +2306,36 @@ impl SM70Encoder<'_> { fn set_tex_lod_mode(&mut self, range: Range, lod_mode: TexLodMode) { assert!(range.len() == 3); - self.set_field( - range, - match lod_mode { - TexLodMode::Auto => 0_u8, - TexLodMode::Zero => 1_u8, - TexLodMode::Bias => 2_u8, - TexLodMode::Lod => 3_u8, - TexLodMode::Clamp => 4_u8, - TexLodMode::BiasClamp => 5_u8, - }, - ); + if self.sm >= 100 { + self.set_field( + range, + match lod_mode { + TexLodMode::Auto => 0_u8, + TexLodMode::Bias => 1_u8, + TexLodMode::Clamp => 2_u8, + // ulb => 0x3 + // ulc => 0x4 + // lb.ulc => 0x5 + TexLodMode::BiasClamp => todo!(), + + TexLodMode::Zero => 0_u8, + TexLodMode::Lod => 1_u8, + // ull => 3 + }, + ); + } else { + self.set_field( + range, + match lod_mode { + TexLodMode::Auto => 0_u8, + TexLodMode::Zero => 1_u8, + TexLodMode::Bias => 2_u8, + TexLodMode::Lod => 3_u8, + TexLodMode::Clamp => 4_u8, + TexLodMode::BiasClamp => 5_u8, + }, + ); + } } fn set_image_dim(&mut self, range: Range, dim: ImageDim) { @@ -2384,12 +2403,18 @@ impl SM70Op for OpTex { panic!("SM70+ doesn't have legacy bound textures"); } TexRef::CBuf(cb) => { + assert!(e.sm < 100); e.set_opcode(0xb60); e.set_tex_cb_ref(40..59, cb); } TexRef::Bindless => { - e.set_opcode(0x361); - e.set_bit(59, true); // .B + if e.sm >= 100 { + e.set_opcode(0xd61); + e.set_bit(91, true); + } else { + e.set_opcode(0x361); + e.set_bit(59, true); // .B + } } } @@ -2404,6 +2429,11 @@ impl SM70Op for OpTex { e.set_reg_src(24..32, self.srcs[0]); e.set_reg_src(32..40, self.srcs[1]); + if e.sm >= 100 { + e.set_field(48..56, 0xff_u8); // ureg + e.set_bit(59, self.lod_mode.is_explicit_lod()); + } + e.set_tex_dim(61..64, self.dim); e.set_tex_channel_mask(72..76, self.channel_mask); e.set_bit(76, self.offset); @@ -2426,12 +2456,18 @@ impl SM70Op for OpTld { panic!("SM70+ doesn't have legacy bound textures"); } TexRef::CBuf(cb) => { + assert!(e.sm < 100); e.set_opcode(0xb66); e.set_tex_cb_ref(40..59, cb); } TexRef::Bindless => { - e.set_opcode(0x367); - e.set_bit(59, true); // .B + if e.sm >= 100 { + e.set_opcode(0xd67); + e.set_bit(91, true); + } else { + e.set_opcode(0x367); + e.set_bit(59, true); // .B + } } } @@ -2446,17 +2482,18 @@ impl SM70Op for OpTld { e.set_reg_src(24..32, self.srcs[0]); e.set_reg_src(32..40, self.srcs[1]); + if e.sm >= 100 { + e.set_field(48..56, 0xff_u8); // ureg + } + e.set_tex_dim(61..64, self.dim); e.set_tex_channel_mask(72..76, self.channel_mask); e.set_bit(76, self.offset); // bit 77: .CL e.set_bit(78, self.is_ms); // bits 79..81: .F16 - assert!( - self.lod_mode == TexLodMode::Zero - || self.lod_mode == TexLodMode::Lod - ); e.set_eviction_priority(&self.mem_eviction_priority); + assert!(self.lod_mode.is_explicit_lod()); e.set_tex_lod_mode(87..90, self.lod_mode); e.set_bit(90, self.nodep); } @@ -2473,12 +2510,18 @@ impl SM70Op for OpTld4 { panic!("SM70+ doesn't have legacy bound textures"); } TexRef::CBuf(cb) => { + assert!(e.sm < 100); e.set_opcode(0xb63); e.set_tex_cb_ref(40..59, cb); } TexRef::Bindless => { - e.set_opcode(0x364); - e.set_bit(59, true); // .B + if e.sm >= 100 { + e.set_opcode(0xd64); + e.set_bit(91, true); + } else { + e.set_opcode(0x364); + e.set_bit(59, true); // .B + } } } @@ -2493,6 +2536,10 @@ impl SM70Op for OpTld4 { e.set_reg_src(24..32, self.srcs[0]); e.set_reg_src(32..40, self.srcs[1]); + if e.sm >= 100 { + e.set_field(48..56, 0xff_u8); // ureg + } + e.set_tex_dim(61..64, self.dim); e.set_tex_channel_mask(72..76, self.channel_mask); e.set_field( @@ -2522,6 +2569,7 @@ impl SM70Op for OpTmml { panic!("SM70+ doesn't have legacy bound textures"); } TexRef::CBuf(cb) => { + assert!(e.sm < 100); e.set_opcode(0xb69); e.set_tex_cb_ref(40..59, cb); } @@ -2559,12 +2607,18 @@ impl SM70Op for OpTxd { panic!("SM70+ doesn't have legacy bound textures"); } TexRef::CBuf(cb) => { + assert!(e.sm < 100); e.set_opcode(0xb6c); e.set_tex_cb_ref(40..59, cb); } TexRef::Bindless => { - e.set_opcode(0x36d); - e.set_bit(59, true); // .B + if e.sm >= 100 { + e.set_opcode(0xd6d); + e.set_bit(91, true); + } else { + e.set_opcode(0x36d); + e.set_bit(59, true); // .B + } } } @@ -2579,6 +2633,10 @@ impl SM70Op for OpTxd { e.set_reg_src(24..32, self.srcs[0]); e.set_reg_src(32..40, self.srcs[1]); + if e.sm >= 100 { + e.set_field(48..56, 0xff_u8); // ureg + } + e.set_tex_dim(61..64, self.dim); e.set_tex_channel_mask(72..76, self.channel_mask); e.set_bit(76, self.offset); @@ -2599,6 +2657,7 @@ impl SM70Op for OpTxq { panic!("SM70+ doesn't have legacy bound textures"); } TexRef::CBuf(cb) => { + assert!(e.sm < 100); e.set_opcode(0xb6f); e.set_tex_cb_ref(40..59, cb); }