From d934b5293fbc21c43affdcca4ad9754d5d24bb72 Mon Sep 17 00:00:00 2001 From: Danylo Piliaiev Date: Fri, 23 Jan 2026 22:28:27 +0100 Subject: [PATCH] ir3: Add resbase_ir3 intrinsic Signed-off-by: Danylo Piliaiev --- src/compiler/nir/nir_divergence_analysis.c | 1 + src/compiler/nir/nir_intrinsics.py | 2 ++ src/freedreno/ir3/ir3.c | 1 + src/freedreno/ir3/ir3.h | 1 + src/freedreno/ir3/ir3_compiler_nir.c | 14 ++++++++++++++ src/freedreno/ir3/ir3_legalize.c | 2 +- src/freedreno/ir3/ir3_validate.c | 1 + src/freedreno/isa/ir3-cat6.xml | 3 ++- 8 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/compiler/nir/nir_divergence_analysis.c b/src/compiler/nir/nir_divergence_analysis.c index 9d8ea263c6b..7b6b58bb160 100644 --- a/src/compiler/nir/nir_divergence_analysis.c +++ b/src/compiler/nir/nir_divergence_analysis.c @@ -802,6 +802,7 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state) case nir_intrinsic_load_gmem_frag_offset_ir3: case nir_intrinsic_bindless_resource_ir3: case nir_intrinsic_ray_intersection_ir3: + case nir_intrinsic_resbase_ir3: case nir_intrinsic_load_attribute_payload_intel: case nir_intrinsic_load_urb_vec4_intel: case nir_intrinsic_load_urb_lsc_intel: diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index 8426c0c0140..2ffd0270b7a 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -1675,6 +1675,8 @@ intrinsic("prefetch_sam_ir3", [1, 1], flags=[CAN_REORDER]) intrinsic("prefetch_tex_ir3", [1], flags=[CAN_REORDER]) intrinsic("prefetch_ubo_ir3", [1], flags=[CAN_REORDER]) +intrinsic("resbase_ir3", src_comp=[1], dest_comp=2, flags=[CAN_ELIMINATE, CAN_REORDER]) + # Panfrost-specific intrinsic for loading vertex attributes. Takes explicit # vertex and instance IDs which we need in order to implement vertex attribute # divisor with non-zero base instance on v9+. diff --git a/src/freedreno/ir3/ir3.c b/src/freedreno/ir3/ir3.c index bc493a9dc76..dfdfb38da0f 100644 --- a/src/freedreno/ir3/ir3.c +++ b/src/freedreno/ir3/ir3.c @@ -1907,6 +1907,7 @@ ir3_valid_flags(struct ir3_instruction *instr, unsigned n, unsigned flags) return false; break; case OPC_RESINFO: + case OPC_RESBASE: if (n != 0) return false; break; diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index fafa51f1842..24c196e4992 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -3119,6 +3119,7 @@ INSTR3NODST(STLW) INSTR3NODST(STP) INSTR1(RESINFO) INSTR1(RESFMT) +INSTR1(RESBASE) INSTR2(ATOMIC_ADD) INSTR2(ATOMIC_SUB) INSTR2(ATOMIC_XCHG) diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index 38d9db43782..5a936b680dc 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -3522,6 +3522,20 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr) array_insert(ctx->block, ctx->block->keeps, ldc); break; } + case nir_intrinsic_resbase_ir3: { + struct ir3_instruction *ibo = ir3_ssbo_to_ibo(ctx, intr->src[0]); + struct ir3_instruction *resbase = ir3_RESBASE(b, ibo, 0); + resbase->cat6.iim_val = 1; + resbase->cat6.d = 1; + resbase->cat6.type = TYPE_U32; + resbase->cat6.typed = false; + /* resbase has no writemask and always writes out 2 components */ + resbase->dsts[0]->wrmask = MASK(2); + ir3_handle_bindless_cat6(resbase, intr->src[0]); + ir3_handle_nonuniform(resbase, intr); + ir3_split_dest(b, dst, resbase, 0, 2); + break; + } case nir_intrinsic_rotate: case nir_intrinsic_shuffle_up_uniform_ir3: case nir_intrinsic_shuffle_down_uniform_ir3: diff --git a/src/freedreno/ir3/ir3_legalize.c b/src/freedreno/ir3/ir3_legalize.c index 635af257b1a..02c3812264a 100644 --- a/src/freedreno/ir3/ir3_legalize.c +++ b/src/freedreno/ir3/ir3_legalize.c @@ -254,7 +254,7 @@ sync_update(struct ir3_legalize_state *state, struct ir3_compiler *compiler, if (is_tex_or_prefetch(n) && !has_dummy_dst(n)) { regmask_set(&state->needs_sy, n->dsts[0]); - } else if (n->opc == OPC_RESINFO && !has_dummy_dst(n)) { + } else if ((n->opc == OPC_RESINFO || n->opc == OPC_RESBASE) && !has_dummy_dst(n)) { regmask_set(&state->needs_ss, n->dsts[0]); } else if (is_load(n)) { if (is_local_mem_load(n)) diff --git a/src/freedreno/ir3/ir3_validate.c b/src/freedreno/ir3/ir3_validate.c index f047c8bdb69..8a29d767b60 100644 --- a/src/freedreno/ir3/ir3_validate.c +++ b/src/freedreno/ir3/ir3_validate.c @@ -464,6 +464,7 @@ validate_instr(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr) switch (instr->opc) { case OPC_RESINFO: case OPC_RESFMT: + case OPC_RESBASE: if (instr->dsts_count > 0) validate_reg_size(ctx, instr->dsts[0], instr->cat6.type); validate_reg_size(ctx, instr->srcs[0], instr->cat6.type); diff --git a/src/freedreno/isa/ir3-cat6.xml b/src/freedreno/isa/ir3-cat6.xml index 300633a6647..de97f571209 100644 --- a/src/freedreno/isa/ir3-cat6.xml +++ b/src/freedreno/isa/ir3-cat6.xml @@ -1311,7 +1311,8 @@ TODO rename UAV src to "UAV" so disasm_field_cb can find it easily? - RESourceBASE - returns the address of the bindless descriptor + RESourceBASE - returns the value encoded into TEX_CONST_7_FLAG_LO/HI + of the given descriptor. 001100