From 8a48af4f8f98418b35e4dc4bf57b26ad80b65a30 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 28 Aug 2023 08:36:40 -0400 Subject: [PATCH] agx/lower_tilebuffer: Support spilled layered RTs If we spill render targets with a layered framebuffer, our spilled targets are assumed to be 2D Arrays (in general). We need to use arrayed image operations to load/store from these. The layer is given by the layer as read in the fragemnt shader. This handles the eMRT portion of layered rendering. Signed-off-by: Alyssa Rosenzweig --- src/asahi/lib/agx_meta.c | 2 +- src/asahi/lib/agx_nir_lower_tilebuffer.c | 59 +++++++++++++++++++++++--------- src/asahi/lib/agx_tilebuffer.h | 2 +- src/gallium/drivers/asahi/agx_state.c | 2 +- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/asahi/lib/agx_meta.c b/src/asahi/lib/agx_meta.c index 12e828c..5f49025 100644 --- a/src/asahi/lib/agx_meta.c +++ b/src/asahi/lib/agx_meta.c @@ -20,7 +20,7 @@ agx_compile_meta_shader(struct agx_meta_cache *cache, nir_shader *shader, agx_preprocess_nir(shader, false, false, NULL); if (tib) { unsigned bindless_base = 0; - agx_nir_lower_tilebuffer(shader, tib, NULL, &bindless_base, NULL); + agx_nir_lower_tilebuffer(shader, tib, NULL, &bindless_base, NULL, true); agx_nir_lower_monolithic_msaa( shader, &(struct agx_msaa_state){.nr_samples = tib->nr_samples}); } diff --git a/src/asahi/lib/agx_nir_lower_tilebuffer.c b/src/asahi/lib/agx_nir_lower_tilebuffer.c index 4bb6b05..763b3cf 100644 --- a/src/asahi/lib/agx_nir_lower_tilebuffer.c +++ b/src/asahi/lib/agx_nir_lower_tilebuffer.c @@ -22,6 +22,7 @@ struct ctx { bool *translucent; unsigned bindless_base; bool any_memory_stores; + bool layer_id_sr; uint8_t outputs_written; }; @@ -131,14 +132,21 @@ dim_for_rt(nir_builder *b, unsigned nr_samples, nir_def **sample) } static nir_def * -image_coords(nir_builder *b) +image_coords(nir_builder *b, nir_def *layer_id) { - return nir_pad_vector(b, nir_u2u32(b, nir_load_pixel_coord(b)), 4); + nir_def *xy = nir_u2u32(b, nir_load_pixel_coord(b)); + nir_def *vec = nir_pad_vector(b, xy, 4); + + if (layer_id) + vec = nir_vector_insert_imm(b, vec, layer_id, 2); + + return vec; } static void store_memory(nir_builder *b, unsigned bindless_base, unsigned nr_samples, - enum pipe_format format, unsigned rt, nir_def *value) + nir_def *layer_id, enum pipe_format format, unsigned rt, + nir_def *value) { /* Force bindless for multisampled image writes since they will be lowered * with a descriptor crawl later. @@ -150,7 +158,7 @@ store_memory(nir_builder *b, unsigned bindless_base, unsigned nr_samples, nir_def *sample; enum glsl_sampler_dim dim = dim_for_rt(b, nr_samples, &sample); - nir_def *coords = image_coords(b); + nir_def *coords = image_coords(b, layer_id); nir_begin_invocation_interlock(b); @@ -163,12 +171,12 @@ store_memory(nir_builder *b, unsigned bindless_base, unsigned nr_samples, } if (bindless) { - nir_bindless_image_store( - b, image, coords, sample, value, lod, .image_dim = dim, - .image_array = false /* TODO */, .format = format); + nir_bindless_image_store(b, image, coords, sample, value, lod, + .image_dim = dim, .image_array = !!layer_id, + .format = format); } else { nir_image_store(b, image, coords, sample, value, lod, .image_dim = dim, - .image_array = false /* TODO */, .format = format); + .image_array = !!layer_id, .format = format); } if (nr_samples > 1) @@ -179,7 +187,7 @@ store_memory(nir_builder *b, unsigned bindless_base, unsigned nr_samples, static nir_def * load_memory(nir_builder *b, unsigned bindless_base, unsigned nr_samples, - uint8_t comps, uint8_t bit_size, unsigned rt, + nir_def *layer_id, uint8_t comps, uint8_t bit_size, unsigned rt, enum pipe_format format) { bool bindless = false; @@ -189,7 +197,7 @@ load_memory(nir_builder *b, unsigned bindless_base, unsigned nr_samples, nir_def *sample; enum glsl_sampler_dim dim = dim_for_rt(b, nr_samples, &sample); - nir_def *coords = image_coords(b); + nir_def *coords = image_coords(b, layer_id); /* Ensure pixels below this one have written out their results */ nir_begin_invocation_interlock(b); @@ -197,10 +205,10 @@ load_memory(nir_builder *b, unsigned bindless_base, unsigned nr_samples, if (bindless) { return nir_bindless_image_load( b, comps, bit_size, image, coords, sample, lod, .image_dim = dim, - .image_array = false /* TODO */, .format = format); + .image_array = !!layer_id, .format = format); } else { return nir_image_load(b, comps, bit_size, image, coords, sample, lod, - .image_dim = dim, .image_array = false /* TODO */, + .image_dim = dim, .image_array = !!layer_id, .format = format); } } @@ -215,6 +223,23 @@ agx_internal_layer_id(nir_builder *b) } static nir_def * +tib_layer_id(nir_builder *b, struct ctx *ctx) +{ + if (!ctx->tib->layered) { + /* If we're not layered, there's no explicit layer ID */ + return NULL; + } else if (ctx->layer_id_sr) { + return agx_internal_layer_id(b); + } else { + /* Otherwise, the layer ID is loaded as a flat varying. */ + b->shader->info.inputs_read |= VARYING_BIT_LAYER; + + return nir_load_input(b, 1, 32, nir_imm_int(b, 0), + .io_semantics.location = VARYING_SLOT_LAYER); + } +} + +static nir_def * tib_impl(nir_builder *b, nir_instr *instr, void *data) { struct ctx *ctx = data; @@ -268,8 +293,8 @@ tib_impl(nir_builder *b, nir_instr *instr, void *data) value = nir_trim_vector(b, intr->src[0].ssa, comps); if (tib->spilled[rt]) { - store_memory(b, ctx->bindless_base, tib->nr_samples, logical_format, - rt, value); + store_memory(b, ctx->bindless_base, tib->nr_samples, + tib_layer_id(b, ctx), logical_format, rt, value); ctx->any_memory_stores = true; } else { store_tilebuffer(b, tib, format, logical_format, rt, value, @@ -289,7 +314,8 @@ tib_impl(nir_builder *b, nir_instr *instr, void *data) *(ctx->translucent) = true; return load_memory(b, ctx->bindless_base, tib->nr_samples, - intr->num_components, bit_size, rt, logical_format); + tib_layer_id(b, ctx), intr->num_components, + bit_size, rt, logical_format); } else { return load_tilebuffer(b, tib, intr->num_components, bit_size, rt, format, logical_format); @@ -300,7 +326,7 @@ tib_impl(nir_builder *b, nir_instr *instr, void *data) bool agx_nir_lower_tilebuffer(nir_shader *shader, struct agx_tilebuffer_layout *tib, uint8_t *colormasks, unsigned *bindless_base, - bool *translucent) + bool *translucent, bool layer_id_sr) { assert(shader->info.stage == MESA_SHADER_FRAGMENT); @@ -308,6 +334,7 @@ agx_nir_lower_tilebuffer(nir_shader *shader, struct agx_tilebuffer_layout *tib, .tib = tib, .colormasks = colormasks, .translucent = translucent, + .layer_id_sr = layer_id_sr, }; /* Allocate 1 texture + 1 PBE descriptor for each spilled descriptor */ diff --git a/src/asahi/lib/agx_tilebuffer.h b/src/asahi/lib/agx_tilebuffer.h index 6092c70..3ad3dea 100644 --- a/src/asahi/lib/agx_tilebuffer.h +++ b/src/asahi/lib/agx_tilebuffer.h @@ -91,7 +91,7 @@ agx_build_tilebuffer_layout(enum pipe_format *formats, uint8_t nr_cbufs, bool agx_nir_lower_tilebuffer(struct nir_shader *shader, struct agx_tilebuffer_layout *tib, uint8_t *colormasks, unsigned *bindless_base, - bool *translucent); + bool *translucent, bool layer_id_sr); struct nir_def *agx_internal_layer_id(struct nir_builder *b); diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c index 67426c0..7868940 100644 --- a/src/gallium/drivers/asahi/agx_state.c +++ b/src/gallium/drivers/asahi/agx_state.c @@ -1620,7 +1620,7 @@ agx_compile_variant(struct agx_device *dev, struct agx_uncompiled_shader *so, (2 * BITSET_LAST_BIT(nir->info.images_used)); unsigned rt_spill = rt_spill_base; NIR_PASS_V(nir, agx_nir_lower_tilebuffer, &tib, colormasks, &rt_spill, - &force_translucent); + &force_translucent, false); /* If anything spilled, we have bindless texture */ so->internal_bindless |= (rt_spill != rt_spill_base); -- 2.7.4