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: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34336>
This commit is contained in:
Faith Ekstrand 2025-04-01 20:11:07 -05:00 committed by Marge Bot
parent c2570055d5
commit 3d9185f17e
4 changed files with 118 additions and 42 deletions

View file

@ -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,

View file

@ -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,

View file

@ -2164,6 +2164,14 @@ impl SM50Encoder<'_> {
},
);
}
fn set_tex_channel_mask(
&mut self,
range: Range<usize>,
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<usize>,
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);
}
}

View file

@ -2325,6 +2325,27 @@ impl SM70Encoder<'_> {
},
);
}
fn set_tex_channel_mask(
&mut self,
range: Range<usize>,
channel_mask: ChannelMask,
) {
self.set_field(range, channel_mask.to_bits());
}
fn set_image_channel_mask(
&mut self,
range: Range<usize>,
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);
}
}