From ee4cff760304d08a1edfa238e3a0b80827222f0e Mon Sep 17 00:00:00 2001 From: Lorenzo Rossi Date: Wed, 7 May 2025 17:31:11 +0200 Subject: [PATCH] nvk: nak: Add OpViLd support Kepler and earlier GPUs do not support the ISBERD instruction but have a different VILD (Vertex Indirect Load) instruction that provides less functionality. This commit adds support for the op in nak and nir, needed for the upcoming encoder commit. Signed-off-by: Lorenzo Rossi Reviewed-by: Faith Ekstrand Part-of: --- src/compiler/nir/nir_divergence_analysis.c | 1 + src/compiler/nir/nir_intrinsics.py | 2 + src/nouveau/compiler/nak/from_nir.rs | 11 ++++++ src/nouveau/compiler/nak/ir.rs | 37 +++++++++++++++++++ .../compiler/nak/opt_instr_sched_common.rs | 2 + src/nouveau/compiler/nak_nir_lower_vtg_io.c | 18 +++++---- 6 files changed, 64 insertions(+), 7 deletions(-) diff --git a/src/compiler/nir/nir_divergence_analysis.c b/src/compiler/nir/nir_divergence_analysis.c index ed1a78e194f..3e8015267a5 100644 --- a/src/compiler/nir/nir_divergence_analysis.c +++ b/src/compiler/nir/nir_divergence_analysis.c @@ -904,6 +904,7 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state) case nir_intrinsic_cmat_muladd_amd: case nir_intrinsic_dpas_intel: case nir_intrinsic_isberd_nv: + case nir_intrinsic_vild_nv: case nir_intrinsic_al2p_nv: case nir_intrinsic_ald_nv: case nir_intrinsic_ipa_nv: diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index fa1c71ae62b..0e0373b03ab 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -2459,6 +2459,8 @@ intrinsic("load_sysval_nv", dest_comp=1, src_comp=[], bit_sizes=[32, 64], indices=[ACCESS, BASE], flags=[CAN_ELIMINATE]) intrinsic("isberd_nv", dest_comp=1, src_comp=[1], bit_sizes=[32], flags=[CAN_ELIMINATE, CAN_REORDER]) +intrinsic("vild_nv", dest_comp=1, src_comp=[1], bit_sizes=[32], + flags=[CAN_ELIMINATE, CAN_REORDER]) intrinsic("al2p_nv", dest_comp=1, src_comp=[1], bit_sizes=[32], indices=[BASE, FLAGS], flags=[CAN_ELIMINATE, CAN_REORDER]) # src[] = { vtx, offset }. diff --git a/src/nouveau/compiler/nak/from_nir.rs b/src/nouveau/compiler/nak/from_nir.rs index 6609f340c51..e50026a881a 100644 --- a/src/nouveau/compiler/nak/from_nir.rs +++ b/src/nouveau/compiler/nak/from_nir.rs @@ -2835,6 +2835,17 @@ impl<'a> ShaderFromNir<'a> { }); self.set_dst(&intrin.def, dst.into()); } + nir_intrinsic_vild_nv => { + let dst = b.alloc_ssa(RegFile::GPR); + + let (idx, off) = self.get_io_addr_offset(&srcs[0], 8); + b.push_op(OpViLd { + dst: dst.into(), + idx, + off: off.try_into().unwrap(), + }); + self.set_dst(&intrin.def, dst.into()); + } nir_intrinsic_load_barycentric_at_offset_nv => (), nir_intrinsic_load_barycentric_centroid => (), nir_intrinsic_load_barycentric_pixel => (), diff --git a/src/nouveau/compiler/nak/ir.rs b/src/nouveau/compiler/nak/ir.rs index fec544ef871..1df9b4c6fa2 100644 --- a/src/nouveau/compiler/nak/ir.rs +++ b/src/nouveau/compiler/nak/ir.rs @@ -5741,6 +5741,41 @@ impl DisplayOp for OpIsberd { } impl_display_for_op!(OpIsberd); +/// Vertex Index Load +/// (Only available in Kepler) +/// +/// Takes as input the vertex index and loads the vertex address in +/// attribute space. +#[repr(C)] +#[derive(SrcsAsSlice, DstsAsSlice)] +pub struct OpViLd { + #[dst_type(GPR)] + pub dst: Dst, + + #[src_type(SSA)] + pub idx: Src, + + pub off: i8, +} + +impl DisplayOp for OpViLd { + fn fmt_op(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "vild v[")?; + + if !self.idx.is_zero() { + write!(f, "{}", self.idx)?; + if self.off != 0 { + write!(f, "{:+}", self.off)?; + } + } else { + write!(f, "{}", self.off)?; + } + + write!(f, "]") + } +} +impl_display_for_op!(OpViLd); + #[repr(C)] #[derive(SrcsAsSlice, DstsAsSlice)] pub struct OpKill {} @@ -6433,6 +6468,7 @@ pub enum Op { TexDepBar(OpTexDepBar), CS2R(OpCS2R), Isberd(OpIsberd), + ViLd(OpViLd), Kill(OpKill), Nop(OpNop), PixLd(OpPixLd), @@ -6602,6 +6638,7 @@ impl Op { | Op::TexDepBar(_) | Op::CS2R(_) | Op::Isberd(_) + | Op::ViLd(_) | Op::Kill(_) | Op::PixLd(_) | Op::S2R(_) => false, diff --git a/src/nouveau/compiler/nak/opt_instr_sched_common.rs b/src/nouveau/compiler/nak/opt_instr_sched_common.rs index 83513930516..149e5eb7a7f 100644 --- a/src/nouveau/compiler/nak/opt_instr_sched_common.rs +++ b/src/nouveau/compiler/nak/opt_instr_sched_common.rs @@ -198,6 +198,7 @@ pub fn side_effect_type(op: &Op) -> SideEffect { | Op::TexDepBar(_) | Op::CS2R(_) | Op::Isberd(_) + | Op::ViLd(_) | Op::Kill(_) | Op::S2R(_) => SideEffect::Barrier, Op::PixLd(_) | Op::Nop(_) | Op::Vote(_) => SideEffect::None, @@ -289,6 +290,7 @@ pub fn estimate_variable_latency(sm: u8, op: &Op) -> u32 { | Op::TexDepBar(_) | Op::CS2R(_) | Op::Isberd(_) + | Op::ViLd(_) | Op::Kill(_) | Op::PixLd(_) | Op::S2R(_) => 16, diff --git a/src/nouveau/compiler/nak_nir_lower_vtg_io.c b/src/nouveau/compiler/nak_nir_lower_vtg_io.c index 98dfdba3698..f1701b20d2c 100644 --- a/src/nouveau/compiler/nak_nir_lower_vtg_io.c +++ b/src/nouveau/compiler/nak_nir_lower_vtg_io.c @@ -138,13 +138,17 @@ lower_vtg_io_intrin(nir_builder *b, mask = nir_component_mask(intrin->num_components); if (vtx != NULL && !is_output) { - nir_def *info = nir_load_sysval_nv(b, 32, - .base = NAK_SV_INVOCATION_INFO, - .access = ACCESS_CAN_REORDER); - nir_def *lo = nir_extract_u8_imm(b, info, 0); - nir_def *hi = nir_extract_u8_imm(b, info, 2); - nir_def *idx = nir_iadd(b, nir_imul(b, lo, hi), vtx); - vtx = nir_isberd_nv(b, idx); + if (nak->sm >= 50) { + nir_def *info = nir_load_sysval_nv(b, 32, + .base = NAK_SV_INVOCATION_INFO, + .access = ACCESS_CAN_REORDER); + nir_def *lo = nir_extract_u8_imm(b, info, 0); + nir_def *hi = nir_extract_u8_imm(b, info, 2); + nir_def *idx = nir_iadd(b, nir_imul(b, lo, hi), vtx); + vtx = nir_isberd_nv(b, idx); + } else { + vtx = nir_vild_nv(b, vtx); + } } if (vtx == NULL)