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 <alyssa@rosenzweig.io>
This commit is contained in:
parent
041451b655
commit
8a48af4f8f
4 changed files with 46 additions and 19 deletions
|
|
@ -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});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -214,6 +222,23 @@ agx_internal_layer_id(nir_builder *b)
|
|||
return nir_channel(b, nir_load_workgroup_id(b), 2);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue