nak: Wire up texture ops

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24998>
This commit is contained in:
Faith Ekstrand 2023-04-10 17:23:33 -05:00 committed by Marge Bot
parent 9d7e1d515f
commit a70423944b
3 changed files with 648 additions and 2 deletions

View file

@ -735,6 +735,187 @@ impl SM75Instr {
self.set_pred_src(87..90, 90, op.srcs[0]);
}
fn set_tex_dim(&mut self, range: Range<usize>, dim: TexDim) {
assert!(range.len() == 3);
self.set_field(
range,
match dim {
TexDim::_1D => 0_u8,
TexDim::Array1D => 4_u8,
TexDim::_2D => 1_u8,
TexDim::Array2D => 5_u8,
TexDim::_3D => 2_u8,
TexDim::Cube => 3_u8,
TexDim::ArrayCube => 7_u8,
},
);
}
fn set_tex_lod_mode(&mut self, range: Range<usize>, 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,
},
);
}
fn encode_tex(&mut self, op: &OpTex) {
self.set_opcode(0x361);
self.set_bit(59, true); /* .B */
self.set_dst(op.dsts[0]);
if let Dst::Reg(reg) = op.dsts[1] {
self.set_reg(64..72, reg);
} else {
self.set_field(64..72, 255_u8);
}
self.set_pred_dst(81..84, op.resident);
self.set_reg_src(24..32, op.srcs[0]);
self.set_reg_src(32..40, op.srcs[1]);
self.set_tex_dim(61..64, op.dim);
self.set_field(72..76, op.mask);
self.set_bit(76, op.offset);
self.set_bit(77, false); /* ToDo: NDV */
self.set_bit(78, op.z_cmpr);
self.set_field(84..87, 1);
self.set_tex_lod_mode(87..90, op.lod_mode);
self.set_bit(90, false); /* TODO: .NODEP */
}
fn encode_tld(&mut self, op: &OpTld) {
self.set_opcode(0x367);
self.set_bit(59, true); /* .B */
self.set_dst(op.dsts[0]);
if let Dst::Reg(reg) = op.dsts[1] {
self.set_reg(64..72, reg);
} else {
self.set_field(64..72, 255_u8);
}
self.set_pred_dst(81..84, op.resident);
self.set_reg_src(24..32, op.srcs[0]);
self.set_reg_src(32..40, op.srcs[1]);
self.set_tex_dim(61..64, op.dim);
self.set_field(72..76, op.mask);
self.set_bit(76, op.offset);
/* bit 77: .CL */
self.set_bit(78, op.is_ms);
/* bits 79..81: .F16 */
assert!(
op.lod_mode == TexLodMode::Zero || op.lod_mode == TexLodMode::Lod
);
self.set_tex_lod_mode(87..90, op.lod_mode);
self.set_bit(90, false); /* TODO: .NODEP */
}
fn encode_tld4(&mut self, op: &OpTld4) {
self.set_opcode(0x364);
self.set_bit(59, true); /* .B */
self.set_dst(op.dsts[0]);
if let Dst::Reg(reg) = op.dsts[1] {
self.set_reg(64..72, reg);
} else {
self.set_field(64..72, 255_u8);
}
self.set_pred_dst(81..84, op.resident);
self.set_reg_src(24..32, op.srcs[0]);
self.set_reg_src(32..40, op.srcs[1]);
self.set_tex_dim(61..64, op.dim);
self.set_field(72..76, op.mask);
self.set_field(
76..78,
match op.offset_mode {
Tld4OffsetMode::None => 0_u8,
Tld4OffsetMode::AddOffI => 1_u8,
Tld4OffsetMode::PerPx => 2_u8,
},
);
/* bit 77: .CL */
self.set_bit(78, op.z_cmpr);
self.set_bit(84, true); /* !.EF */
self.set_field(87..89, op.comp);
self.set_bit(90, false); /* TODO: .NODEP */
}
fn encode_tmml(&mut self, op: &OpTmml) {
self.set_opcode(0x36a);
self.set_bit(59, true); /* .B */
self.set_dst(op.dsts[0]);
if let Dst::Reg(reg) = op.dsts[1] {
self.set_reg(64..72, reg);
} else {
self.set_field(64..72, 255_u8);
}
self.set_reg_src(24..32, op.srcs[0]);
self.set_reg_src(32..40, op.srcs[1]);
self.set_tex_dim(61..64, op.dim);
self.set_field(72..76, op.mask);
self.set_bit(77, false); /* ToDo: NDV */
self.set_bit(90, false); /* TODO: .NODEP */
}
fn encode_txd(&mut self, op: &OpTxd) {
self.set_opcode(0x36d);
self.set_bit(59, true); /* .B */
self.set_dst(op.dsts[0]);
if let Dst::Reg(reg) = op.dsts[1] {
self.set_reg(64..72, reg);
} else {
self.set_field(64..72, 255_u8);
}
self.set_pred_dst(81..84, op.resident);
self.set_reg_src(24..32, op.srcs[0]);
self.set_reg_src(32..40, op.srcs[1]);
self.set_tex_dim(61..64, op.dim);
self.set_field(72..76, op.mask);
self.set_bit(76, op.offset);
self.set_bit(77, false); /* ToDo: NDV */
self.set_bit(90, false); /* TODO: .NODEP */
}
fn encode_txq(&mut self, op: &OpTxq) {
self.set_opcode(0x370);
self.set_bit(59, true); /* .B */
self.set_dst(op.dsts[0]);
if let Dst::Reg(reg) = op.dsts[1] {
self.set_reg(64..72, reg);
} else {
self.set_field(64..72, 255_u8);
}
self.set_reg_src(24..32, op.src);
self.set_field(
62..64,
match op.query {
TexQuery::Dimension => 0_u8,
TexQuery::TextureType => 1_u8,
TexQuery::SamplerPos => 2_u8,
},
);
self.set_field(72..76, op.mask);
}
fn set_mem_access(&mut self, access: &MemAccess) {
self.set_field(
72..73,
@ -931,6 +1112,12 @@ impl SM75Instr {
Op::Mov(op) => si.encode_mov(&op),
Op::Sel(op) => si.encode_sel(&op),
Op::PLop3(op) => si.encode_plop3(&op),
Op::Tex(op) => si.encode_tex(&op),
Op::Tld(op) => si.encode_tld(&op),
Op::Tld4(op) => si.encode_tld4(&op),
Op::Tmml(op) => si.encode_tmml(&op),
Op::Txd(op) => si.encode_txd(&op),
Op::Txq(op) => si.encode_txq(&op),
Op::Ld(op) => si.encode_ld(&op),
Op::St(op) => si.encode_st(&op),
Op::ALd(op) => si.encode_ald(&op),

View file

@ -4,12 +4,15 @@
*/
#![allow(non_upper_case_globals)]
#![allow(unstable_name_collisions)]
use crate::nak_ir::*;
use crate::nir::*;
use crate::util::DivCeil;
use nak_bindings::*;
use std::cmp::min;
use std::collections::HashMap;
struct ShaderFromNir<'a> {
@ -128,6 +131,29 @@ impl<'a> ShaderFromNir<'a> {
split
}
fn split(&mut self, ssa: SSAValue) -> Vec<SSAValue> {
if ssa.comps() == 1 {
return vec![ssa];
}
let mut split_ssa = Vec::new();
let mut dsts = Vec::new();
for c in 0..ssa.comps() {
let dst_ssa = self.alloc_ssa(ssa.file(), 1);
split_ssa.push(dst_ssa);
dsts.push(Dst::from(dst_ssa));
}
self.instrs.push(Instr::new_split(&dsts, ssa.into()));
split_ssa
}
fn vec(&mut self, ssa: &[SSAValue]) -> SSAValue {
let dst = self.alloc_ssa(ssa[0].file(), ssa.len().try_into().unwrap());
let srcs: Vec<Src> = ssa.iter().map(|s| (*s).into()).collect();
self.instrs.push(Instr::new_vec(dst.into(), &srcs));
dst
}
fn parse_alu(&mut self, alu: &nir_alu_instr) {
let mut srcs = Vec::new();
for alu_src in alu.srcs_as_slice() {
@ -567,8 +593,171 @@ impl<'a> ShaderFromNir<'a> {
/* Nothing to do */
}
fn parse_tex(&mut self, _tex: &nir_tex_instr) {
panic!("Texture instructions unimplemented");
fn parse_tex(&mut self, tex: &nir_tex_instr) {
let dim = match tex.sampler_dim {
GLSL_SAMPLER_DIM_1D => {
if tex.is_array {
TexDim::Array1D
} else {
TexDim::_1D
}
}
GLSL_SAMPLER_DIM_2D => {
if tex.is_array {
TexDim::Array2D
} else {
TexDim::_2D
}
}
GLSL_SAMPLER_DIM_3D => {
assert!(!tex.is_array);
TexDim::_3D
}
GLSL_SAMPLER_DIM_CUBE => {
if tex.is_array {
TexDim::ArrayCube
} else {
TexDim::Cube
}
}
GLSL_SAMPLER_DIM_BUF => TexDim::_1D,
GLSL_SAMPLER_DIM_MS => {
if tex.is_array {
TexDim::Array2D
} else {
TexDim::_2D
}
}
_ => panic!("Unsupported texture dimension: {}", tex.sampler_dim),
};
let srcs = tex.srcs_as_slice();
assert!(srcs[0].src_type == nir_tex_src_backend1);
if srcs.len() > 1 {
assert!(srcs.len() == 2);
assert!(srcs[1].src_type == nir_tex_src_backend2);
}
let flags: nak_nir_tex_flags =
unsafe { std::mem::transmute_copy(&tex.backend_flags) };
let mask = tex.def.components_read();
let mask = u8::try_from(mask).unwrap();
let dst_comps = u8::try_from(mask.count_ones()).unwrap();
let mut dsts = [Dst::None; 2];
dsts[0] = self.alloc_ssa(RegFile::GPR, min(dst_comps, 2)).into();
if dst_comps > 2 {
dsts[1] = self.alloc_ssa(RegFile::GPR, dst_comps - 2).into();
}
if tex.op == nir_texop_hdr_dim_nv {
self.instrs.push(Instr::new(Op::Txq(OpTxq {
dsts: dsts,
src: self.get_src(&srcs[0].src),
query: TexQuery::Dimension,
mask: mask,
})));
} else if tex.op == nir_texop_tex_type_nv {
self.instrs.push(Instr::new(Op::Txq(OpTxq {
dsts: dsts,
src: self.get_src(&srcs[0].src),
query: TexQuery::TextureType,
mask: mask,
})));
} else {
let lod_mode = match flags.lod_mode() {
NAK_NIR_LOD_MODE_AUTO => TexLodMode::Auto,
NAK_NIR_LOD_MODE_ZERO => TexLodMode::Zero,
NAK_NIR_LOD_MODE_BIAS => TexLodMode::Bias,
NAK_NIR_LOD_MODE_LOD => TexLodMode::Lod,
NAK_NIR_LOD_MODE_CLAMP => TexLodMode::Clamp,
NAK_NIR_LOD_MODE_BIAS_CLAMP => TexLodMode::BiasClamp,
_ => panic!("Invalid LOD mode"),
};
let offset_mode = match flags.offset_mode() {
NAK_NIR_OFFSET_MODE_NONE => Tld4OffsetMode::None,
NAK_NIR_OFFSET_MODE_AOFFI => Tld4OffsetMode::AddOffI,
NAK_NIR_OFFSET_MODE_PER_PX => Tld4OffsetMode::PerPx,
_ => panic!("Invalid offset mode"),
};
let srcs = [self.get_src(&srcs[0].src), self.get_src(&srcs[1].src)];
if tex.op == nir_texop_txd {
assert!(lod_mode == TexLodMode::Auto);
assert!(offset_mode != Tld4OffsetMode::PerPx);
assert!(!flags.has_z_cmpr());
self.instrs.push(Instr::new(Op::Txd(OpTxd {
dsts: dsts,
resident: Dst::None,
srcs: srcs,
dim: dim,
offset: offset_mode == Tld4OffsetMode::AddOffI,
mask: mask,
})));
} else if tex.op == nir_texop_lod {
assert!(offset_mode == Tld4OffsetMode::None);
self.instrs.push(Instr::new(Op::Tmml(OpTmml {
dsts: dsts,
srcs: srcs,
dim: dim,
mask: mask,
})));
} else if tex.op == nir_texop_txf {
assert!(offset_mode != Tld4OffsetMode::PerPx);
self.instrs.push(Instr::new(Op::Tld(OpTld {
dsts: dsts,
resident: Dst::None,
srcs: srcs,
dim: dim,
lod_mode: lod_mode,
is_ms: false,
offset: offset_mode == Tld4OffsetMode::AddOffI,
mask: mask,
})));
} else if tex.op == nir_texop_tg4 {
self.instrs.push(Instr::new(Op::Tld4(OpTld4 {
dsts: dsts,
resident: Dst::None,
srcs: srcs,
dim: dim,
comp: tex.component().try_into().unwrap(),
offset_mode: offset_mode,
z_cmpr: flags.has_z_cmpr(),
mask: mask,
})));
} else {
assert!(offset_mode != Tld4OffsetMode::PerPx);
self.instrs.push(Instr::new(Op::Tex(OpTex {
dsts: dsts,
resident: Dst::None,
srcs: srcs,
dim: dim,
lod_mode: lod_mode,
z_cmpr: flags.has_z_cmpr(),
offset: offset_mode == Tld4OffsetMode::AddOffI,
mask: mask,
})));
}
}
let mut dst_comps = Vec::new();
for dst in dsts {
if let Dst::SSA(dst) = dst {
for comp in self.split(dst) {
dst_comps.push(comp.into());
}
}
}
for c in 0..tex.def.num_components() {
if mask & (1 << c) == 0 {
dst_comps.insert(c.into(), SrcRef::Zero.into());
}
}
self.instrs
.push(Instr::new_vec(self.get_dst(&tex.def), &dst_comps));
}
fn parse_intrinsic(&mut self, intrin: &nir_intrinsic_instr) {

View file

@ -859,6 +859,88 @@ impl fmt::Display for FRndMode {
}
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum TexDim {
_1D,
Array1D,
_2D,
Array2D,
_3D,
Cube,
ArrayCube,
}
impl fmt::Display for TexDim {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TexDim::_1D => write!(f, "1D"),
TexDim::Array1D => write!(f, "ARRAY_1D"),
TexDim::_2D => write!(f, "2D"),
TexDim::Array2D => write!(f, "ARRAY_2D"),
TexDim::_3D => write!(f, "3D"),
TexDim::Cube => write!(f, "CUBE"),
TexDim::ArrayCube => write!(f, "ARRAY_CUBE"),
}
}
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum TexLodMode {
Auto,
Zero,
Bias,
Lod,
Clamp,
BiasClamp,
}
impl fmt::Display for TexLodMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TexLodMode::Auto => write!(f, "LA"),
TexLodMode::Zero => write!(f, "LZ"),
TexLodMode::Bias => write!(f, "LB"),
TexLodMode::Lod => write!(f, "LL"),
TexLodMode::Clamp => write!(f, "LC"),
TexLodMode::BiasClamp => write!(f, "LB.LC"),
}
}
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum Tld4OffsetMode {
None,
AddOffI,
PerPx,
}
impl fmt::Display for Tld4OffsetMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Tld4OffsetMode::None => write!(f, "NO_OFF"),
Tld4OffsetMode::AddOffI => write!(f, "AOFFI"),
Tld4OffsetMode::PerPx => write!(f, "PTP"),
}
}
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum TexQuery {
Dimension,
TextureType,
SamplerPos,
}
impl fmt::Display for TexQuery {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TexQuery::Dimension => write!(f, "DIMENSION"),
TexQuery::TextureType => write!(f, "TEXTURE_TYPE"),
TexQuery::SamplerPos => write!(f, "SAMPLER_POS"),
}
}
}
pub enum IntType {
U8,
I8,
@ -1501,6 +1583,182 @@ impl fmt::Display for OpPLop3 {
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpTex {
pub dsts: [Dst; 2],
pub resident: Dst,
pub srcs: [Src; 2],
pub dim: TexDim,
pub lod_mode: TexLodMode,
pub z_cmpr: bool,
pub offset: bool,
pub mask: u8,
}
impl fmt::Display for OpTex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "TEX.B")?;
if self.lod_mode != TexLodMode::Auto {
write!(f, ".{}", self.lod_mode)?;
}
if self.offset {
write!(f, ".AOFFI")?;
}
if self.z_cmpr {
write!(f, ".DC")?;
}
write!(
f,
" {{ {}, {}, {} }} {{ {}, {} }} {}",
self.dsts[0],
self.dsts[1],
self.resident,
self.srcs[0],
self.srcs[1],
self.dim,
)
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpTld {
pub dsts: [Dst; 2],
pub resident: Dst,
pub srcs: [Src; 2],
pub dim: TexDim,
pub is_ms: bool,
pub lod_mode: TexLodMode,
pub offset: bool,
pub mask: u8,
}
impl fmt::Display for OpTld {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "TLD.B")?;
if self.lod_mode != TexLodMode::Auto {
write!(f, ".{}", self.lod_mode)?;
}
if self.offset {
write!(f, ".AOFFI")?;
}
if self.is_ms {
write!(f, ".MS")?;
}
write!(
f,
" {{ {}, {}, {} }} {{ {}, {} }} {}",
self.dsts[0],
self.dsts[1],
self.resident,
self.srcs[0],
self.srcs[1],
self.dim,
)
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpTld4 {
pub dsts: [Dst; 2],
pub resident: Dst,
pub srcs: [Src; 2],
pub dim: TexDim,
pub comp: u8,
pub offset_mode: Tld4OffsetMode,
pub z_cmpr: bool,
pub mask: u8,
}
impl fmt::Display for OpTld4 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "TLD4.G.B")?;
if self.offset_mode != Tld4OffsetMode::None {
write!(f, ".{}", self.offset_mode)?;
}
write!(
f,
" {{ {}, {}, {} }} {{ {}, {} }} {}",
self.dsts[0],
self.dsts[1],
self.resident,
self.srcs[0],
self.srcs[1],
self.dim,
)
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpTmml {
pub dsts: [Dst; 2],
pub srcs: [Src; 2],
pub dim: TexDim,
pub mask: u8,
}
impl fmt::Display for OpTmml {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"TMML.B.LOD {{ {}, {} }} {{ {}, {} }} {}",
self.dsts[0], self.dsts[1], self.srcs[0], self.srcs[1], self.dim
)
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpTxd {
pub dsts: [Dst; 2],
pub resident: Dst,
pub srcs: [Src; 2],
pub dim: TexDim,
pub offset: bool,
pub mask: u8,
}
impl fmt::Display for OpTxd {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "TXD.B")?;
if self.offset {
write!(f, ".AOFFI")?;
}
write!(
f,
" {{ {}, {}, {} }} {{ {}, {} }} {}",
self.dsts[0],
self.dsts[1],
self.resident,
self.srcs[0],
self.srcs[1],
self.dim,
)
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpTxq {
pub dsts: [Dst; 2],
pub src: Src,
pub query: TexQuery,
pub mask: u8,
}
impl fmt::Display for OpTxq {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"TXQ.B {{ {}, {} }} {} {}",
self.dsts[0], self.dsts[1], self.src, self.query
)
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpLd {
@ -1953,6 +2211,12 @@ pub enum Op {
Mov(OpMov),
Sel(OpSel),
PLop3(OpPLop3),
Tex(OpTex),
Tld(OpTld),
Tld4(OpTld4),
Tmml(OpTmml),
Txd(OpTxd),
Txq(OpTxq),
Ld(OpLd),
St(OpSt),
ALd(OpALd),
@ -2420,6 +2684,12 @@ impl Instr {
Op::ALd(_) => None,
Op::ASt(_) => Some(15),
Op::Ipa(_) => None,
Op::Tex(_) => None,
Op::Tld(_) => None,
Op::Tld4(_) => None,
Op::Tmml(_) => None,
Op::Txd(_) => None,
Op::Txq(_) => None,
Op::Ld(_) => None,
Op::St(_) => None,
Op::Bra(_) | Op::Exit(_) => Some(15),