ir3: Implement sparse residency check

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32671>
This commit is contained in:
Connor Abbott
2024-12-03 15:56:23 -05:00
committed by Marge Bot
parent 120f755bdb
commit 70cf40086c
7 changed files with 91 additions and 5 deletions
+24 -3
View File
@@ -290,15 +290,19 @@ emit_intrinsic_load_image(struct ir3_context *ctx, nir_intrinsic_instr *intr,
struct ir3_instruction **dst)
{
struct ir3_builder *b = &ctx->build;
struct ir3_instruction *ldib;
struct ir3_instruction *ldib, *rck;
struct ir3_instruction *const *coords = ir3_get_src(ctx, &intr->src[1]);
unsigned ncoords = ir3_get_image_coords(intr, NULL);
unsigned num_components = intr->num_components;
if (intr->intrinsic == nir_intrinsic_image_sparse_load ||
intr->intrinsic == nir_intrinsic_bindless_image_sparse_load)
num_components--;
ldib = ir3_LDIB(b, ir3_image_to_ibo(ctx, intr->src[0]), 0,
ir3_create_collect(b, coords, ncoords), 0,
create_immed(b, 0), 0);
ldib->dsts[0]->wrmask = MASK(intr->num_components);
ldib->cat6.iim_val = intr->num_components;
ldib->dsts[0]->wrmask = MASK(num_components);
ldib->cat6.iim_val = num_components;
ldib->cat6.d = ncoords;
ldib->cat6.type = ir3_get_type_for_image_intrinsic(intr);
ldib->cat6.typed = true;
@@ -307,6 +311,23 @@ emit_intrinsic_load_image(struct ir3_context *ctx, nir_intrinsic_instr *intr,
ir3_handle_bindless_cat6(ldib, intr->src[0]);
ir3_handle_nonuniform(ldib, intr);
if (intr->intrinsic == nir_intrinsic_image_sparse_load ||
intr->intrinsic == nir_intrinsic_bindless_image_sparse_load) {
rck = ir3_LDIB(b, ir3_image_to_ibo(ctx, intr->src[0]), 0,
ir3_create_collect(b, coords, ncoords), 0,
create_immed(b, 0), 0);
rck->dsts[0]->wrmask = 0b1;
rck->cat6.iim_val = 1;
rck->cat6.d = ncoords;
rck->cat6.type = TYPE_U32;
rck->cat6.typed = true;
rck->flags |= IR3_INSTR_RCK;
ir3_handle_bindless_cat6(rck, intr->src[0]);
ir3_handle_nonuniform(rck, intr);
dst[num_components] = rck;
}
ir3_split_dest(b, dst, ldib, 0, intr->num_components);
}
+28 -1
View File
@@ -1767,7 +1767,7 @@ emit_intrinsic_load_image(struct ir3_context *ctx, nir_intrinsic_instr *intr,
struct ir3_builder *b = &ctx->build;
struct tex_src_info info = get_image_ssbo_samp_tex_src(ctx, &intr->src[0], true);
struct ir3_instruction *sam;
struct ir3_instruction *sam, *rck;
struct ir3_instruction *const *src0 = ir3_get_src(ctx, &intr->src[1]);
struct ir3_instruction *coords[4];
unsigned flags, ncoords = ir3_get_image_coords(intr, &flags);
@@ -1799,6 +1799,17 @@ emit_intrinsic_load_image(struct ir3_context *ctx, nir_intrinsic_instr *intr,
sam->barrier_conflict = IR3_BARRIER_IMAGE_W;
ir3_split_dest(b, dst, sam, 0, 4);
if (intr->intrinsic == nir_intrinsic_image_sparse_load ||
intr->intrinsic == nir_intrinsic_bindless_image_sparse_load) {
/* The results of the residency check cannot change within the shader, so
* it doesn't need any barriers.
*/
rck = emit_sam(ctx, OPC_ISAM, info, type, 0b1,
ir3_create_collect(b, coords, ncoords), NULL);
rck->flags |= IR3_INSTR_RCK;
dst[4] = rck;
}
}
/* A4xx version of image_size, see ir3_a6xx.c for newer resinfo version. */
@@ -2901,6 +2912,8 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr)
break;
case nir_intrinsic_image_load:
case nir_intrinsic_bindless_image_load:
case nir_intrinsic_image_sparse_load:
case nir_intrinsic_bindless_image_sparse_load:
emit_intrinsic_load_image(ctx, intr, dst);
break;
case nir_intrinsic_image_store:
@@ -3604,6 +3617,12 @@ emit_tex(struct ir3_context *ctx, nir_tex_instr *tex)
dst = ir3_get_def(ctx, &tex->def, ncomp);
/* For sparse residency check, the last component is a residency code that is
* emitted separately.
*/
if (tex->is_sparse)
ncomp--;
for (unsigned i = 0; i < tex->num_srcs; i++) {
switch (tex->src[i].src_type) {
case nir_tex_src_coord:
@@ -3921,6 +3940,14 @@ emit_tex(struct ir3_context *ctx, nir_tex_instr *tex)
sam = emit_sam(ctx, opc, info, type, MASK(ncomp), col0, col1);
}
if (tex->is_sparse) {
info.flags |= flags;
struct ir3_instruction *rck =
emit_sam(ctx, opc, info, TYPE_U32, MASK(1), col0, col1);
rck->flags |= IR3_INSTR_RCK;
dst[ncomp] = rck;
}
if (tg4_swizzle_fixup) {
/* TODO: fix-up for ASTC when alpha is selected? */
array_insert(ctx->ir, ctx->ir->tg4, sam);
+2
View File
@@ -102,7 +102,9 @@ ir3_get_type_for_image_intrinsic(const nir_intrinsic_instr *instr)
nir_alu_type type = nir_type_uint;
switch (instr->intrinsic) {
case nir_intrinsic_image_load:
case nir_intrinsic_image_sparse_load:
case nir_intrinsic_bindless_image_load:
case nir_intrinsic_bindless_image_sparse_load:
type = nir_alu_type_get_base_type(nir_intrinsic_dest_type(instr));
/* SpvOpAtomicLoad doesn't have dest type */
if (type == nir_type_invalid)
+32
View File
@@ -596,6 +596,36 @@ ir3_nir_lower_shader_clock(nir_shader *shader, uint64_t uche_trap_base)
nir_metadata_none, &uche_trap_base);
}
static bool
ir3_nir_lower_sparse_residency_cb(nir_builder *b, nir_intrinsic_instr *instr,
void *data)
{
b->cursor = nir_before_instr(&instr->instr);
nir_def *def;
switch (instr->intrinsic) {
case nir_intrinsic_is_sparse_texels_resident:
def = nir_ieq_imm(b, instr->src[0].ssa, 0);
break;
case nir_intrinsic_sparse_residency_code_and:
def = nir_ior(b, instr->src[0].ssa, instr->src[1].ssa);
break;
default:
return false;
}
nir_def_rewrite_uses(&instr->def, def);
return true;
}
static bool
ir3_nir_lower_sparse_residency(nir_shader *shader)
{
return nir_shader_intrinsics_pass(
shader, ir3_nir_lower_sparse_residency_cb,
nir_metadata_control_flow, NULL);
}
void
ir3_finalize_nir(struct ir3_compiler *compiler,
const struct ir3_shader_nir_options *options,
@@ -635,6 +665,8 @@ ir3_finalize_nir(struct ir3_compiler *compiler,
OPT(s, nir_lower_tex, &tex_options);
OPT(s, nir_lower_load_const_to_scalar);
NIR_PASS(_, s, ir3_nir_lower_sparse_residency);
if (compiler->array_index_add_half)
OPT(s, ir3_nir_lower_array_sampler);
@@ -178,7 +178,8 @@ lower_tex_prefetch_block(nir_block *block, ir3_prefetch_state *state)
continue;
/* only prefetch for simple 2d tex fetch case */
if (tex->sampler_dim != GLSL_SAMPLER_DIM_2D || tex->is_array)
if (tex->sampler_dim != GLSL_SAMPLER_DIM_2D || tex->is_array ||
tex->is_sparse)
continue;
if (!ok_tex_samp(tex))
+2
View File
@@ -192,6 +192,8 @@ print_instr_name(struct log_stream *stream, struct ir3_instruction *instr,
mesa_log_stream_printf(stream, ".a1en");
if (instr->flags & IR3_INSTR_U)
mesa_log_stream_printf(stream, ".u");
if (instr->flags & IR3_INSTR_RCK)
mesa_log_stream_printf(stream, ".rck");
if (instr->opc == OPC_LDC)
mesa_log_stream_printf(stream, ".offset%d", instr->cat6.d);
if (instr->opc == OPC_LDC_K)
+1
View File
@@ -502,6 +502,7 @@ lower_intrinsic(nir_builder *b, nir_intrinsic_instr *instr,
return lower_ssbo_ubo_intrinsic(dev, b, instr);
case nir_intrinsic_image_deref_load:
case nir_intrinsic_image_deref_sparse_load:
case nir_intrinsic_image_deref_store:
case nir_intrinsic_image_deref_atomic:
case nir_intrinsic_image_deref_atomic_swap: