From 35d849025ba99227e2528e56b74538fc22f83ac9 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 29 May 2023 19:51:21 -0400 Subject: [PATCH] asahi: Decompress with format reinterpretation The internal layout used with compression partially depends on the pixel format. Some limited reinterpretation is definitely allowed (linear vs sRGB views of the same physical format are documented by Apple as allowed). Some reinterpretations are definitely forbidden (R8G8B8A8 vs R32, I think). At some point we'll need to work out the exact rule. I suspect the answer is that "you can reinterpret iff the Channels field matches". Meaning that R8G8B8A8_UNORM and B8G8R8A8_SINT would be compatible, but not R16G16_UNORM. But I haven't tested that. Fixes all fails in: dEQP-GLES31.functional.image_load_store.*.format_reinterpret.* Signed-off-by: Alyssa Rosenzweig Part-of: --- src/gallium/drivers/asahi/agx_state.c | 43 +++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c index 394b01aa0a8..528e0f071d2 100644 --- a/src/gallium/drivers/asahi/agx_state.c +++ b/src/gallium/drivers/asahi/agx_state.c @@ -38,6 +38,39 @@ #include "util/u_transfer.h" #include "agx_disk_cache.h" +static void +agx_legalize_compression(struct agx_context *ctx, struct agx_resource *rsrc, + enum pipe_format format) +{ + /* If the resource isn't compressed, we can reinterpret */ + if (rsrc->layout.tiling != AIL_TILING_TWIDDLED_COMPRESSED) + return; + + /* Normalize due to Gallium shenanigans */ + if (format == PIPE_FORMAT_Z24_UNORM_S8_UINT || + format == PIPE_FORMAT_Z24X8_UNORM) + format = PIPE_FORMAT_Z32_FLOAT; + + /* The physical format */ + enum pipe_format storage = rsrc->layout.format; + + /* sRGB vs linear are always compatible */ + storage = util_format_linear(storage); + format = util_format_linear(format); + + /* If no reinterpretation happens, we don't have to decompress */ + if (storage == format) + return; + + /* Otherwise, decompress. TODO: Reverse-engineer which formats are compatible + * and don't need decompression. There are some vague hints in the Metal + * documentation: + * + * https://developer.apple.com/documentation/metal/mtltextureusage/mtltextureusagepixelformatview?language=objc + */ + agx_decompress(ctx, rsrc, "Incompatible formats"); +} + static void agx_set_shader_images(struct pipe_context *pctx, enum pipe_shader_type shader, unsigned start_slot, unsigned count, @@ -82,6 +115,11 @@ agx_set_shader_images(struct pipe_context *pctx, enum pipe_shader_type shader, agx_decompress(ctx, rsrc, "Shader image"); } + /* Readable images may be compressed but are still subject to format + * reinterpretation rules. + */ + agx_legalize_compression(ctx, rsrc, image->format); + /* FIXME: Decompress here once we have texture compression */ util_copy_image_view(&ctx->stage[shader].images[start_slot + i], image); } @@ -768,6 +806,8 @@ agx_create_sampler_view(struct pipe_context *pctx, } } + agx_legalize_compression(agx_context(pctx), rsrc, format); + /* Save off the resource that we actually use, with the stencil fixed up */ so->rsrc = rsrc; agx_pack_texture(&so->desc, rsrc, format, state, false); @@ -831,6 +871,9 @@ static struct pipe_surface * agx_create_surface(struct pipe_context *ctx, struct pipe_resource *texture, const struct pipe_surface *surf_tmpl) { + agx_legalize_compression(agx_context(ctx), agx_resource(texture), + surf_tmpl->format); + struct pipe_surface *surface = CALLOC_STRUCT(pipe_surface); if (!surface)