asahi: use flat tile size encoding

this is way more convenient.

(some cosmetic stuff squashed in).

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Mary Guillemard <mary@mary.zone>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39111>
This commit is contained in:
Alyssa Rosenzweig 2025-12-29 22:12:52 -05:00
parent 16627035ef
commit 130c1b0bd5
7 changed files with 38 additions and 54 deletions

View file

@ -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 = {

View file

@ -5,9 +5,7 @@
#include "agx_tilebuffer.h"
#include <assert.h>
#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

View file

@ -8,6 +8,7 @@
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#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.

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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.