From 3d9185f17e38ef21d40f768d185c1614e63646b8 Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Tue, 1 Apr 2025 20:11:07 -0500 Subject: [PATCH] nak: Add a ChannelMask type We use this for tex and image ops instead of a u8. This lets us assert some variants up-front as well as pretty print them. Part-of: --- src/nouveau/compiler/nak/from_nir.rs | 21 ++++----- src/nouveau/compiler/nak/ir.rs | 59 ++++++++++++++++++++----- src/nouveau/compiler/nak/sm50.rs | 39 +++++++++++----- src/nouveau/compiler/nak/sm70_encode.rs | 41 ++++++++++++----- 4 files changed, 118 insertions(+), 42 deletions(-) diff --git a/src/nouveau/compiler/nak/from_nir.rs b/src/nouveau/compiler/nak/from_nir.rs index d568e07a679..6a72297b2f9 100644 --- a/src/nouveau/compiler/nak/from_nir.rs +++ b/src/nouveau/compiler/nak/from_nir.rs @@ -1804,6 +1804,7 @@ impl<'a> ShaderFromNir<'a> { } else { debug_assert!(mask != 0); } + let channel_mask = ChannelMask::new(mask); let dst_comps = u8::try_from(mask.count_ones()).unwrap(); let dst = b.alloc_ssa(RegFile::GPR, dst_comps); @@ -1832,7 +1833,7 @@ impl<'a> ShaderFromNir<'a> { src: src, query: TexQuery::Dimension, nodep: flags.nodep(), - mask: mask, + channel_mask, }); } else if tex.op == nir_texop_tex_type_nv { let src = self.get_src(&srcs[0].src); @@ -1843,7 +1844,7 @@ impl<'a> ShaderFromNir<'a> { src: src, query: TexQuery::TextureType, nodep: flags.nodep(), - mask: mask, + channel_mask, }); } else { let lod_mode = match flags.lod_mode() { @@ -1884,7 +1885,7 @@ impl<'a> ShaderFromNir<'a> { offset: offset_mode == Tld4OffsetMode::AddOffI, mem_eviction_priority: MemEvictionPriority::Normal, nodep: flags.nodep(), - mask: mask, + channel_mask, }); } else if tex.op == nir_texop_lod { assert!(offset_mode == Tld4OffsetMode::None); @@ -1894,7 +1895,7 @@ impl<'a> ShaderFromNir<'a> { srcs: srcs, dim: dim, nodep: flags.nodep(), - mask: mask, + channel_mask, }); } else if tex.op == nir_texop_txf || tex.op == nir_texop_txf_ms { assert!(offset_mode != Tld4OffsetMode::PerPx); @@ -1909,7 +1910,7 @@ impl<'a> ShaderFromNir<'a> { offset: offset_mode == Tld4OffsetMode::AddOffI, mem_eviction_priority: MemEvictionPriority::Normal, nodep: flags.nodep(), - mask: mask, + channel_mask, }); } else if tex.op == nir_texop_tg4 { b.push_op(OpTld4 { @@ -1923,7 +1924,7 @@ impl<'a> ShaderFromNir<'a> { z_cmpr: flags.has_z_cmpr(), mem_eviction_priority: MemEvictionPriority::Normal, nodep: flags.nodep(), - mask: mask, + channel_mask, }); } else { assert!(offset_mode != Tld4OffsetMode::PerPx); @@ -1938,7 +1939,7 @@ impl<'a> ShaderFromNir<'a> { offset: offset_mode == Tld4OffsetMode::AddOffI, mem_eviction_priority: MemEvictionPriority::Normal, nodep: flags.nodep(), - mask: mask, + channel_mask, }); } } @@ -2488,7 +2489,7 @@ impl<'a> ShaderFromNir<'a> { mem_order, mem_eviction_priority: self .get_eviction_priority(intrin.access()), - mask: (1 << comps) - 1, + channel_mask: ChannelMask::for_comps(comps), handle: handle, coord: coord, }); @@ -2524,7 +2525,7 @@ impl<'a> ShaderFromNir<'a> { mem_order, mem_eviction_priority: self .get_eviction_priority(intrin.access()), - mask: (1 << (comps - 1)) - 1, + channel_mask: ChannelMask::for_comps(comps - 1), handle: handle, coord: coord, }); @@ -2553,7 +2554,7 @@ impl<'a> ShaderFromNir<'a> { mem_order: MemOrder::Strong(MemScope::GPU), mem_eviction_priority: self .get_eviction_priority(intrin.access()), - mask: (1 << comps) - 1, + channel_mask: ChannelMask::for_comps(comps), handle: handle, coord: coord, data: data, diff --git a/src/nouveau/compiler/nak/ir.rs b/src/nouveau/compiler/nak/ir.rs index 5722433f91d..b6deda8424b 100644 --- a/src/nouveau/compiler/nak/ir.rs +++ b/src/nouveau/compiler/nak/ir.rs @@ -2126,6 +2126,37 @@ impl fmt::Display for TexLodMode { } } +#[derive(Clone, Copy, Eq, PartialEq)] +pub struct ChannelMask(u8); + +impl ChannelMask { + pub fn new(mask: u8) -> Self { + assert!(mask != 0 && (mask & !0xf) == 0); + ChannelMask(mask) + } + + pub fn for_comps(comps: u8) -> Self { + assert!(comps > 0 && comps <= 4); + ChannelMask((1 << comps) - 1) + } + + pub fn to_bits(self) -> u8 { + self.0 + } +} + +impl fmt::Display for ChannelMask { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, ".")?; + for (i, c) in ['r', 'g', 'b', 'a'].into_iter().enumerate() { + if self.0 & (1 << i) != 0 { + write!(f, "{c}")?; + } + } + Ok(()) + } +} + #[derive(Clone, Copy, Eq, PartialEq)] pub enum Tld4OffsetMode { None, @@ -4843,7 +4874,7 @@ pub struct OpTex { pub offset: bool, pub mem_eviction_priority: MemEvictionPriority, pub nodep: bool, - pub mask: u8, + pub channel_mask: ChannelMask, } impl DisplayOp for OpTex { @@ -4862,6 +4893,7 @@ impl DisplayOp for OpTex { if self.nodep { write!(f, ".nodep")?; } + write!(f, "{}", self.channel_mask)?; write!(f, " {} {} {}", self.tex, self.srcs[0], self.srcs[1]) } } @@ -4884,7 +4916,7 @@ pub struct OpTld { pub offset: bool, pub mem_eviction_priority: MemEvictionPriority, pub nodep: bool, - pub mask: u8, + pub channel_mask: ChannelMask, } impl DisplayOp for OpTld { @@ -4903,6 +4935,7 @@ impl DisplayOp for OpTld { if self.nodep { write!(f, ".nodep")?; } + write!(f, "{}", self.channel_mask)?; write!(f, " {} {} {}", self.tex, self.srcs[0], self.srcs[1]) } } @@ -4925,7 +4958,7 @@ pub struct OpTld4 { pub z_cmpr: bool, pub mem_eviction_priority: MemEvictionPriority, pub nodep: bool, - pub mask: u8, + pub channel_mask: ChannelMask, } impl DisplayOp for OpTld4 { @@ -4941,6 +4974,7 @@ impl DisplayOp for OpTld4 { if self.nodep { write!(f, ".nodep")?; } + write!(f, "{}", self.channel_mask)?; write!(f, " {} {} {}", self.tex, self.srcs[0], self.srcs[1]) } } @@ -4958,7 +4992,7 @@ pub struct OpTmml { pub dim: TexDim, pub nodep: bool, - pub mask: u8, + pub channel_mask: ChannelMask, } impl DisplayOp for OpTmml { @@ -4967,6 +5001,7 @@ impl DisplayOp for OpTmml { if self.nodep { write!(f, ".nodep")?; } + write!(f, "{}", self.channel_mask)?; write!(f, " {} {} {}", self.tex, self.srcs[0], self.srcs[1]) } } @@ -4987,7 +5022,7 @@ pub struct OpTxd { pub offset: bool, pub mem_eviction_priority: MemEvictionPriority, pub nodep: bool, - pub mask: u8, + pub channel_mask: ChannelMask, } impl DisplayOp for OpTxd { @@ -5000,6 +5035,7 @@ impl DisplayOp for OpTxd { if self.nodep { write!(f, ".nodep")?; } + write!(f, "{}", self.channel_mask)?; write!(f, " {} {} {}", self.tex, self.srcs[0], self.srcs[1]) } } @@ -5017,7 +5053,7 @@ pub struct OpTxq { pub query: TexQuery, pub nodep: bool, - pub mask: u8, + pub channel_mask: ChannelMask, } impl DisplayOp for OpTxq { @@ -5026,6 +5062,7 @@ impl DisplayOp for OpTxq { if self.nodep { write!(f, ".nodep")?; } + write!(f, "{}", self.channel_mask)?; write!(f, " {} {} {}", self.tex, self.src, self.query) } } @@ -5040,7 +5077,7 @@ pub struct OpSuLd { pub image_dim: ImageDim, pub mem_order: MemOrder, pub mem_eviction_priority: MemEvictionPriority, - pub mask: u8, + pub channel_mask: ChannelMask, #[src_type(GPR)] pub handle: Src, @@ -5053,10 +5090,11 @@ impl DisplayOp for OpSuLd { fn fmt_op(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "suld.p{}{}{} [{}] {}", + "suld.p{}{}{}{} [{}] {}", self.image_dim, self.mem_order, self.mem_eviction_priority, + self.channel_mask, self.coord, self.handle, ) @@ -5070,7 +5108,7 @@ pub struct OpSuSt { pub image_dim: ImageDim, pub mem_order: MemOrder, pub mem_eviction_priority: MemEvictionPriority, - pub mask: u8, + pub channel_mask: ChannelMask, #[src_type(GPR)] pub handle: Src, @@ -5086,10 +5124,11 @@ impl DisplayOp for OpSuSt { fn fmt_op(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "sust.p{}{}{} [{}] {} {}", + "sust.p{}{}{}{} [{}] {} {}", self.image_dim, self.mem_order, self.mem_eviction_priority, + self.channel_mask, self.coord, self.data, self.handle, diff --git a/src/nouveau/compiler/nak/sm50.rs b/src/nouveau/compiler/nak/sm50.rs index 528e1aed0b6..a5d9ba2636c 100644 --- a/src/nouveau/compiler/nak/sm50.rs +++ b/src/nouveau/compiler/nak/sm50.rs @@ -2164,6 +2164,14 @@ impl SM50Encoder<'_> { }, ); } + + fn set_tex_channel_mask( + &mut self, + range: Range, + channel_mask: ChannelMask, + ) { + self.set_field(range, channel_mask.to_bits()); + } } fn legalize_tex_instr(op: &mut impl SrcsAsSlice, _b: &mut LegalizeBuilder) { @@ -2207,7 +2215,7 @@ impl SM50Op for OpTex { e.set_reg_src(20..28, self.srcs[1]); e.set_tex_dim(28..31, self.dim); - e.set_field(31..35, self.mask); + e.set_tex_channel_mask(31..35, self.channel_mask); e.set_bit(35, false); // ToDo: NDV e.set_bit(49, self.nodep); e.set_bit(50, self.z_cmpr); @@ -2240,7 +2248,7 @@ impl SM50Op for OpTld { e.set_reg_src(20..28, self.srcs[1]); e.set_tex_dim(28..31, self.dim); - e.set_field(31..35, self.mask); + e.set_tex_channel_mask(31..35, self.channel_mask); e.set_bit(35, self.offset); e.set_bit(49, self.nodep); e.set_bit(50, self.is_ms); @@ -2288,7 +2296,7 @@ impl SM50Op for OpTld4 { e.set_reg_src(20..28, self.srcs[1]); e.set_tex_dim(28..31, self.dim); - e.set_field(31..35, self.mask); + e.set_tex_channel_mask(31..35, self.channel_mask); e.set_bit(35, false); // ToDo: NDV e.set_bit(49, self.nodep); e.set_bit(50, self.z_cmpr); @@ -2320,7 +2328,7 @@ impl SM50Op for OpTmml { e.set_reg_src(20..28, self.srcs[1]); e.set_tex_dim(28..31, self.dim); - e.set_field(31..35, self.mask); + e.set_tex_channel_mask(31..35, self.channel_mask); e.set_bit(35, false); // ToDo: NDV e.set_bit(49, self.nodep); } @@ -2352,7 +2360,7 @@ impl SM50Op for OpTxd { e.set_reg_src(20..28, self.srcs[1]); e.set_tex_dim(28..31, self.dim); - e.set_field(31..35, self.mask); + e.set_tex_channel_mask(31..35, self.channel_mask); e.set_bit(35, self.offset); e.set_bit(49, self.nodep); } @@ -2393,7 +2401,7 @@ impl SM50Op for OpTxq { // TexQuery::BorderColour => 0x16, }, ); - e.set_field(31..35, self.mask); + e.set_tex_channel_mask(31..35, self.channel_mask); e.set_bit(49, self.nodep); } } @@ -2445,6 +2453,19 @@ impl SM50Encoder<'_> { }, ); } + + fn set_image_channel_mask( + &mut self, + range: Range, + channel_mask: ChannelMask, + ) { + assert!( + channel_mask.to_bits() == 0x1 + || channel_mask.to_bits() == 0x3 + || channel_mask.to_bits() == 0xf + ); + self.set_field(range, channel_mask.to_bits()); + } } impl SM50Op for OpSuLd { @@ -2455,8 +2476,7 @@ impl SM50Op for OpSuLd { fn encode(&self, e: &mut SM50Encoder<'_>) { e.set_opcode(0xeb00); - assert!(self.mask == 0x1 || self.mask == 0x3 || self.mask == 0xf); - e.set_field(20..24, self.mask); + e.set_image_channel_mask(20..24, self.channel_mask); e.set_image_dim(33..36, self.image_dim); // mem_eviction_policy not a thing for sm < 70 @@ -2499,8 +2519,7 @@ impl SM50Op for OpSuSt { e.set_image_dim(33..36, self.image_dim); e.set_mem_order(&self.mem_order); - assert!(self.mask == 0x1 || self.mask == 0x3 || self.mask == 0xf); - e.set_field(20..24, self.mask); + e.set_image_channel_mask(20..24, self.channel_mask); } } diff --git a/src/nouveau/compiler/nak/sm70_encode.rs b/src/nouveau/compiler/nak/sm70_encode.rs index 2a4aea7d601..c8ad9e7f24a 100644 --- a/src/nouveau/compiler/nak/sm70_encode.rs +++ b/src/nouveau/compiler/nak/sm70_encode.rs @@ -2325,6 +2325,27 @@ impl SM70Encoder<'_> { }, ); } + + fn set_tex_channel_mask( + &mut self, + range: Range, + channel_mask: ChannelMask, + ) { + self.set_field(range, channel_mask.to_bits()); + } + + fn set_image_channel_mask( + &mut self, + range: Range, + channel_mask: ChannelMask, + ) { + assert!( + channel_mask.to_bits() == 0x1 + || channel_mask.to_bits() == 0x3 + || channel_mask.to_bits() == 0xf + ); + self.set_field(range, channel_mask.to_bits()); + } } fn legalize_tex_instr(op: &mut impl SrcsAsSlice, b: &mut LegalizeBuilder) { @@ -2376,7 +2397,7 @@ impl SM70Op for OpTex { e.set_reg_src(32..40, self.srcs[1]); e.set_tex_dim(61..64, self.dim); - e.set_field(72..76, self.mask); + e.set_tex_channel_mask(72..76, self.channel_mask); e.set_bit(76, self.offset); e.set_bit(77, false); // ToDo: NDV e.set_bit(78, self.z_cmpr); @@ -2418,7 +2439,7 @@ impl SM70Op for OpTld { e.set_reg_src(32..40, self.srcs[1]); e.set_tex_dim(61..64, self.dim); - e.set_field(72..76, self.mask); + 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); @@ -2465,7 +2486,7 @@ impl SM70Op for OpTld4 { e.set_reg_src(32..40, self.srcs[1]); e.set_tex_dim(61..64, self.dim); - e.set_field(72..76, self.mask); + e.set_tex_channel_mask(72..76, self.channel_mask); e.set_field( 76..78, match self.offset_mode { @@ -2513,7 +2534,7 @@ impl SM70Op for OpTmml { e.set_reg_src(32..40, self.srcs[1]); e.set_tex_dim(61..64, self.dim); - e.set_field(72..76, self.mask); + e.set_tex_channel_mask(72..76, self.channel_mask); e.set_bit(77, false); // ToDo: NDV e.set_bit(90, self.nodep); } @@ -2551,7 +2572,7 @@ impl SM70Op for OpTxd { e.set_reg_src(32..40, self.srcs[1]); e.set_tex_dim(61..64, self.dim); - e.set_field(72..76, self.mask); + e.set_tex_channel_mask(72..76, self.channel_mask); e.set_bit(76, self.offset); e.set_bit(77, false); // ToDo: NDV e.set_eviction_priority(&self.mem_eviction_priority); @@ -2595,7 +2616,7 @@ impl SM70Op for OpTxq { TexQuery::SamplerPos => 2_u8, }, ); - e.set_field(72..76, self.mask); + e.set_tex_channel_mask(72..76, self.channel_mask); e.set_bit(90, self.nodep); } } @@ -2700,9 +2721,7 @@ impl SM70Op for OpSuLd { e.set_image_dim(61..64, self.image_dim); e.set_mem_order(&self.mem_order); e.set_eviction_priority(&self.mem_eviction_priority); - - assert!(self.mask == 0x1 || self.mask == 0x3 || self.mask == 0xf); - e.set_field(72..76, self.mask); + e.set_image_channel_mask(72..76, self.channel_mask); } } @@ -2721,9 +2740,7 @@ impl SM70Op for OpSuSt { e.set_image_dim(61..64, self.image_dim); e.set_mem_order(&self.mem_order); e.set_eviction_priority(&self.mem_eviction_priority); - - assert!(self.mask == 0x1 || self.mask == 0x3 || self.mask == 0xf); - e.set_field(72..76, self.mask); + e.set_image_channel_mask(72..76, self.channel_mask); } }