asahi: handle cross-process eMRT

decompress in place, just in time.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30981>
This commit is contained in:
Alyssa Rosenzweig 2024-08-31 08:49:00 -04:00 committed by Marge Bot
parent 591bf066ba
commit a6c5f7dc20

View file

@ -15,6 +15,7 @@
#include "asahi/lib/agx_nir_passes.h"
#include "asahi/lib/agx_ppp.h"
#include "asahi/lib/agx_usc.h"
#include "asahi/lib/shaders/compression.h"
#include "asahi/lib/shaders/tessellator.h"
#include "compiler/nir/nir.h"
#include "compiler/nir/nir_serialize.h"
@ -1180,7 +1181,7 @@ target_is_array(enum pipe_texture_target target)
static void
agx_batch_upload_pbe(struct agx_batch *batch, struct agx_pbe_packed *out,
struct pipe_image_view *view, bool block_access,
bool arrays_as_2d, bool force_2d_array)
bool arrays_as_2d, bool force_2d_array, bool emrt)
{
struct agx_resource *tex = agx_resource(view->resource);
const struct util_format_description *desc =
@ -1296,7 +1297,7 @@ agx_batch_upload_pbe(struct agx_batch *batch, struct agx_pbe_packed *out,
cfg.samples = agx_translate_sample_count(tex->base.nr_samples);
}
if (ail_is_compressed(&tex->layout)) {
if (ail_is_compressed(&tex->layout) && !emrt) {
cfg.compressed_1 = true;
cfg.extended = true;
@ -1308,7 +1309,7 @@ agx_batch_upload_pbe(struct agx_batch *batch, struct agx_pbe_packed *out,
/* When the descriptor isn't extended architecturally, we can use the last
* 8 bytes as a sideband. We use it to provide metadata for image atomics.
*/
if (!cfg.extended && tex->layout.writeable_image &&
if (!cfg.extended && (tex->layout.writeable_image || emrt) &&
tex->base.target != PIPE_BUFFER) {
if (util_res_sample_count(&tex->base) > 1) {
@ -1322,7 +1323,7 @@ agx_batch_upload_pbe(struct agx_batch *batch, struct agx_pbe_packed *out,
cfg.sample_count_log2_sw = util_logbase2(tex->base.nr_samples);
if (tex->layout.tiling == AIL_TILING_TWIDDLED) {
if (tex->layout.tiling == AIL_TILING_TWIDDLED || emrt) {
struct ail_tile tile_size = tex->layout.tilesize_el[level];
cfg.tile_width_sw = tile_size.width_el;
cfg.tile_height_sw = tile_size.height_el;
@ -2588,6 +2589,8 @@ agx_build_meta_shader_internal(struct agx_context *ctx,
nir_address_format_62bit_generic);
agx_preprocess_nir(b.shader, NULL);
NIR_PASS(_, b.shader, agx_nir_lower_texture);
NIR_PASS(_, b.shader, agx_nir_lower_multisampled_image_store);
}
struct agx_compiled_shader *shader = agx_compile_nir(
@ -2681,7 +2684,7 @@ agx_upload_spilled_rt_descriptors(struct agx_texture_packed *out,
sampler_view.target = PIPE_TEXTURE_2D_ARRAY;
agx_pack_texture(texture, rsrc, surf->format, &sampler_view);
agx_batch_upload_pbe(batch, pbe, &view, false, false, true);
agx_batch_upload_pbe(batch, pbe, &view, false, false, true, true);
}
}
@ -2761,7 +2764,7 @@ agx_upload_textures(struct agx_batch *batch, struct agx_compiled_shader *cs,
agx_pack_texture(texture, agx_resource(view->resource), view->format,
&sampler_view);
agx_batch_upload_pbe(batch, pbe, view, false, false, false);
agx_batch_upload_pbe(batch, pbe, view, false, false, false, false);
}
if (stage == PIPE_SHADER_FRAGMENT &&
@ -3031,7 +3034,8 @@ agx_build_internal_usc(struct agx_batch *batch, struct agx_compiled_shader *cs,
uint64_t data)
{
struct agx_device *dev = agx_device(batch->ctx->base.screen);
size_t usc_size = agx_usc_size(12);
bool needs_sampler = cs->b.info.uses_txf;
size_t usc_size = agx_usc_size(12 + (needs_sampler ? 1 : 0));
struct agx_ptr t =
agx_pool_alloc_aligned(&batch->pipeline_pool, usc_size, 64);
@ -3041,6 +3045,20 @@ agx_build_internal_usc(struct agx_batch *batch, struct agx_compiled_shader *cs,
agx_usc_uniform(&b, 0, 4, agx_pool_upload(&batch->pool, &data, 8));
agx_usc_immediates(&b, batch, cs);
if (needs_sampler) {
/* TODO: deduplicate */
struct agx_ptr t = agx_pool_alloc_aligned(
&batch->pool, sizeof(struct agx_sampler_packed), 64);
agx_pack_txf_sampler((struct agx_sampler_packed *)t.cpu);
agx_usc_pack(&b, SAMPLER, cfg) {
cfg.start = 0;
cfg.count = 1;
cfg.buffer = t.gpu;
}
}
assert(cs->b.info.scratch_size == 0 && "internal kernels don't spill");
assert(cs->b.info.preamble_scratch_size == 0 && "internal doesn't spill");
@ -3193,7 +3211,7 @@ agx_build_bg_eot(struct agx_batch *batch, bool store, bool partial_render)
/* The tilebuffer is already in sRGB space if needed. Do not convert */
view.format = util_format_linear(view.format);
agx_batch_upload_pbe(batch, pbe.cpu, &view, true, true, false);
agx_batch_upload_pbe(batch, pbe.cpu, &view, true, true, false, false);
agx_usc_pack(&b, TEXTURE, cfg) {
cfg.start = rt;
@ -3410,14 +3428,50 @@ agx_batch_init_state(struct agx_batch *batch)
continue;
struct agx_resource *rsrc = agx_resource(surf->texture);
if (rsrc->layout.writeable_image)
struct ail_layout *layout = &rsrc->layout;
unsigned level = surf->u.tex.level;
if (!ail_is_level_compressed(layout, level))
continue;
/* Decompress if we can and shadow if we can't. */
if (rsrc->base.bind & PIPE_BIND_SHARED)
unreachable("TODO");
else
if (true || (rsrc->base.bind & PIPE_BIND_SHARED)) {
struct agx_context *ctx = batch->ctx;
struct agx_device *dev = agx_device(ctx->base.screen);
perf_debug(dev, "Decompressing in-place");
if (!batch->cdm.bo)
batch->cdm = agx_encoder_allocate(batch, dev);
struct agx_ptr data = agx_pool_alloc_aligned(
&batch->pool, sizeof(struct libagx_decompress_push), 64);
struct libagx_decompress_push *push = data.cpu;
agx_fill_decompress_push(push, layout, surf->u.tex.first_layer,
level, agx_map_texture_gpu(rsrc, 0));
struct pipe_sampler_view sampler_view =
sampler_view_for_surface(surf);
sampler_view.target = PIPE_TEXTURE_2D_ARRAY;
struct pipe_image_view view = image_view_for_surface(surf);
agx_pack_texture(&push->compressed, rsrc, surf->format,
&sampler_view);
agx_batch_upload_pbe(batch, &push->uncompressed, &view, false, true,
true, true);
struct agx_grid grid = agx_grid_direct(
ail_metadata_width_tl(layout, level) * 32,
ail_metadata_height_tl(layout, level),
surf->u.tex.last_layer - surf->u.tex.first_layer + 1, 32, 1, 1);
struct agx_decompress_key key = {
.nr_samples = layout->sample_count_sa,
};
agx_launch_with_uploaded_data(batch, &grid, agx_nir_decompress,
&key, sizeof(key), data.gpu);
} else {
agx_decompress(batch->ctx, rsrc, "Render target spilled");
}
}
}