From 130c1b0bd5692257d4aec9ac3d90242b941426e1 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 29 Dec 2025 22:12:52 -0500 Subject: [PATCH] asahi: use flat tile size encoding this is way more convenient. (some cosmetic stuff squashed in). Signed-off-by: Alyssa Rosenzweig Reviewed-by: Mary Guillemard Part-of: --- src/asahi/lib/agx_nir_prolog_epilog.c | 2 +- src/asahi/lib/agx_tilebuffer.c | 39 ++++++++----------------- src/asahi/lib/agx_tilebuffer.h | 18 +++++++----- src/asahi/lib/tests/test-tilebuffer.cpp | 23 +++++++-------- src/asahi/vulkan/hk_queue.c | 3 +- src/gallium/drivers/asahi/agx_pipe.c | 3 +- src/gallium/drivers/asahi/agx_state.c | 4 +-- 7 files changed, 38 insertions(+), 54 deletions(-) diff --git a/src/asahi/lib/agx_nir_prolog_epilog.c b/src/asahi/lib/agx_nir_prolog_epilog.c index 34d13f35a9b..93efce59154 100644 --- a/src/asahi/lib/agx_nir_prolog_epilog.c +++ b/src/asahi/lib/agx_nir_prolog_epilog.c @@ -420,7 +420,7 @@ agx_nir_fs_epilog(nir_builder *b, const void *key_) key->rt_formats, ARRAY_SIZE(key->rt_formats), key->nr_samples, true); if (key->force_small_tile) - tib.tile_size = (struct agx_tile_size){16, 16}; + tib.tile_size = 16 * 16; bool force_translucent = false; nir_lower_blend_options opts = { diff --git a/src/asahi/lib/agx_tilebuffer.c b/src/asahi/lib/agx_tilebuffer.c index 535cab35984..d00cfaa1160 100644 --- a/src/asahi/lib/agx_tilebuffer.c +++ b/src/asahi/lib/agx_tilebuffer.c @@ -5,9 +5,7 @@ #include "agx_tilebuffer.h" #include -#include "util/bitscan.h" #include "util/format/u_format.h" -#include "agx_usc.h" #include "layout.h" /* Maximum number of bytes per tile on G13G. This may change in future versions @@ -24,35 +22,24 @@ #define MIN_TILE_SIZE_PX (16 * 16) /* Select the largest tile size that fits */ -static struct agx_tile_size -agx_select_tile_size(unsigned bytes_per_pixel) +static uint16_t +agx_select_tile_size(unsigned px_size_B) { - /* clang-format off */ - struct agx_tile_size sizes[] = { - { 32, 32 }, - { 32, 16 }, - { 16, 16 } - }; - /* clang-format on */ + assert(px_size_B <= (MAX_BYTES_PER_TILE / MIN_TILE_SIZE_PX)); - for (unsigned i = 0; i < ARRAY_SIZE(sizes); ++i) { - struct agx_tile_size size = sizes[i]; - - if ((bytes_per_pixel * size.width * size.height) <= MAX_BYTES_PER_TILE) - return size; - } - - UNREACHABLE("No supported tile size meets the bytes per pixel requirement"); + return ((px_size_B * 32 * 32) <= MAX_BYTES_PER_TILE) ? (32 * 32) + : ((px_size_B * 32 * 16) <= MAX_BYTES_PER_TILE) ? (32 * 16) + : MIN_TILE_SIZE_PX; } static unsigned -agx_shared_layout_from_tile_size(struct agx_tile_size t) +agx_shared_layout_from_tile_size(uint16_t t) { - if (t.width == 32 && t.height == 32) + if (t == 32 * 32) return AGX_SHARED_LAYOUT_32X32; - else if (t.width == 32 && t.height == 16) + else if (t == 32 * 16) return AGX_SHARED_LAYOUT_32X16; - else if (t.width == 16 && t.height == 16) + else if (t == 16 * 16) return AGX_SHARED_LAYOUT_16X16; else UNREACHABLE("Invalid tile size"); @@ -127,8 +114,7 @@ agx_build_tilebuffer_layout(const enum pipe_format *formats, uint8_t nr_cbufs, if (nr_samples > 1) offset_B = MAX2(offset_B, 1); - tib.sample_size_B = ALIGN_POT(offset_B, 8); - + tib.sample_size_B = align(offset_B, 8); tib.tile_size = agx_select_tile_size(tib.sample_size_B * nr_samples); agx_tilebuffer_pack_usc(&tib); @@ -176,8 +162,7 @@ agx_tilebuffer_supports_mask(struct agx_tilebuffer_layout *tib, unsigned rt) uint32_t agx_tilebuffer_total_size(struct agx_tilebuffer_layout *tib) { - return tib->sample_size_B * tib->nr_samples * tib->tile_size.width * - tib->tile_size.height; + return tib->sample_size_B * tib->nr_samples * tib->tile_size; } void diff --git a/src/asahi/lib/agx_tilebuffer.h b/src/asahi/lib/agx_tilebuffer.h index da0acf58cea..49017f51309 100644 --- a/src/asahi/lib/agx_tilebuffer.h +++ b/src/asahi/lib/agx_tilebuffer.h @@ -8,6 +8,7 @@ #include #include #include +#include "drm-uapi/asahi_drm.h" #include "util/format/u_formats.h" #include "agx_pack.h" @@ -25,11 +26,6 @@ struct nir_shader; struct nir_def; struct nir_builder; -struct agx_tile_size { - uint8_t width; - uint8_t height; -}; - struct agx_tilebuffer_layout { /* Logical format of each render target. Use agx_tilebuffer_physical_format * to get the physical format. @@ -55,13 +51,21 @@ struct agx_tilebuffer_layout { /* If layered rendering is used */ bool layered; - /* Selected tile size */ - struct agx_tile_size tile_size; + /* Selected tile size in pixels. Either 32*32, 32*16, or 16*16. */ + uint16_t tile_size; /* USC word corresponding to this configuration of the tilebuffer */ struct agx_usc_shared_packed usc; }; +static inline void +agx_tilebuffer_set_drm_cmd(struct drm_asahi_cmd_render *c, + const struct agx_tilebuffer_layout *layout) +{ + c->utile_width_px = layout->tile_size >= 32 * 16 ? 32 : 16; + c->utile_height_px = layout->tile_size <= 32 * 16 ? 16 : 32; +} + /* * _offset_B is undefined for non-spilled render targets. This safe accessor * asserts that render targets are not spilled rather than returning garbage. diff --git a/src/asahi/lib/tests/test-tilebuffer.cpp b/src/asahi/lib/tests/test-tilebuffer.cpp index 609058854f5..f36d70cda29 100644 --- a/src/asahi/lib/tests/test-tilebuffer.cpp +++ b/src/asahi/lib/tests/test-tilebuffer.cpp @@ -26,7 +26,7 @@ struct test tests[] = { ._offset_B = { 0 }, .sample_size_B = 8, .nr_samples = 1, - .tile_size = { 32, 32 }, + .tile_size = 32 * 32, }, 8192 }, @@ -38,7 +38,7 @@ struct test tests[] = { ._offset_B = { 0 }, .sample_size_B = 8, .nr_samples = 2, - .tile_size = { 32, 32 }, + .tile_size = 32 * 32, }, 16384 }, @@ -50,7 +50,7 @@ struct test tests[] = { ._offset_B = { 0 }, .sample_size_B = 8, .nr_samples = 4, - .tile_size = { 32, 16 }, + .tile_size = 32 * 16, }, 16384 }, @@ -67,7 +67,7 @@ struct test tests[] = { ._offset_B = { 16, 0, 18, 8 }, .sample_size_B = 24, .nr_samples = 1, - .tile_size = { 32, 32 }, + .tile_size = 32 * 32, }, 24576 }, @@ -84,7 +84,7 @@ struct test tests[] = { ._offset_B = { 16, 0, 18, 8 }, .sample_size_B = 24, .nr_samples = 2, - .tile_size = { 32, 16 }, + .tile_size = 32 * 16, }, 24576 }, @@ -101,7 +101,7 @@ struct test tests[] = { ._offset_B = { 16, 0, 18, 8 }, .sample_size_B = 24, .nr_samples = 4, - .tile_size = { 16, 16 }, + .tile_size = 16 * 16, }, 24576 }, @@ -113,7 +113,7 @@ struct test tests[] = { ._offset_B = { 4, 0 }, .sample_size_B = 8, .nr_samples = 1, - .tile_size = { 32, 32 }, + .tile_size = 32 * 32, }, 8192 }, @@ -125,7 +125,7 @@ struct test tests[] = { ._offset_B = { 4, 0 }, .sample_size_B = 8, .nr_samples = 1, - .tile_size = { 32, 32 }, + .tile_size = 32 * 32, }, 8192 }, @@ -147,7 +147,7 @@ struct test tests[] = { ._offset_B = { 0, 4, 8, 12, 16, 20, 0, 0}, .sample_size_B = 24, .nr_samples = 4, - .tile_size = { 16, 16 }, + .tile_size = 16 * 16, }, 24576 }, @@ -171,10 +171,7 @@ TEST(Tilebuffer, Layouts) ASSERT_EQ(tests[i].layout.sample_size_B, actual.sample_size_B) << tests[i].name; ASSERT_EQ(tests[i].layout.nr_samples, actual.nr_samples) << tests[i].name; - ASSERT_EQ(tests[i].layout.tile_size.width, actual.tile_size.width) - << tests[i].name; - ASSERT_EQ(tests[i].layout.tile_size.height, actual.tile_size.height) - << tests[i].name; + ASSERT_EQ(tests[i].layout.tile_size, actual.tile_size) << tests[i].name; ASSERT_EQ(tests[i].total_size, agx_tilebuffer_total_size(&tests[i].layout)) << tests[i].name; diff --git a/src/asahi/vulkan/hk_queue.c b/src/asahi/vulkan/hk_queue.c index d69deaab8e8..e7e6aec2e51 100644 --- a/src/asahi/vulkan/hk_queue.c +++ b/src/asahi/vulkan/hk_queue.c @@ -146,8 +146,7 @@ asahi_fill_vdm_command(struct hk_device *dev, struct hk_cs *cs, c->flags |= DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING; } - c->utile_width_px = cs->tib.tile_size.width; - c->utile_height_px = cs->tib.tile_size.height; + agx_tilebuffer_set_drm_cmd(c, &cs->tib); /* Can be 0 for attachmentless rendering with no draws */ c->samples = MAX2(cs->tib.nr_samples, 1); diff --git a/src/gallium/drivers/asahi/agx_pipe.c b/src/gallium/drivers/asahi/agx_pipe.c index 1534f6d443c..ddafd23a5a2 100644 --- a/src/gallium/drivers/asahi/agx_pipe.c +++ b/src/gallium/drivers/asahi/agx_pipe.c @@ -1374,8 +1374,7 @@ agx_cmdbuf(struct agx_device *dev, struct drm_asahi_cmd_render *c, c->partial_bg.usc = pipeline_load.usc | 4; c->partial_eot.usc = pipeline_store.usc | 4; - c->utile_width_px = tib->tile_size.width; - c->utile_height_px = tib->tile_size.height; + agx_tilebuffer_set_drm_cmd(c, tib); c->samples = tib->nr_samples; c->layers = MAX2(util_framebuffer_get_num_layers(framebuffer), 1); diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c index 29eeb49de1a..6269ed55bc7 100644 --- a/src/gallium/drivers/asahi/agx_state.c +++ b/src/gallium/drivers/asahi/agx_state.c @@ -1608,7 +1608,7 @@ agx_compile_variant(struct agx_device *dev, struct pipe_context *pctx, true); if (dev->debug & AGX_DBG_SMALLTILE) - tib.tile_size = (struct agx_tile_size){16, 16}; + tib.tile_size = 16 * 16; /* XXX: don't replicate this all over the driver */ unsigned rt_spill_base = BITSET_LAST_BIT(nir->info.textures_used) + @@ -3365,7 +3365,7 @@ agx_batch_init_state(struct agx_batch *batch) util_framebuffer_get_num_layers(&batch->key) > 1); if (agx_device(batch->ctx->base.screen)->debug & AGX_DBG_SMALLTILE) - batch->tilebuffer_layout.tile_size = (struct agx_tile_size){16, 16}; + batch->tilebuffer_layout.tile_size = 16 * 16; /* If the layout spilled render targets, we need to decompress those render * targets to ensure we can write to them.