panfrost: Overhaul tilebuffer allocations

Based on the colour buffers in use, we need to select a tile size
allowing either 128-bits of storage per pixel or 512-bits. Based on the
size chosen, we scale the offsets into the tilebuffer. Likewise, we need
to calculate offsets based on bpp (with special cases) rather than
picking an average case.

Fixes regressions that otherwise would be caused by the next commit.

v2: Fix colour clears (Icecream95).

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5858>
This commit is contained in:
Alyssa Rosenzweig 2020-07-09 17:35:24 -04:00 committed by Marge Bot
parent 3d13870ee2
commit a0003c329a

View file

@ -428,6 +428,23 @@ panfrost_mfbd_upload(struct panfrost_batch *batch,
#undef UPLOAD
/* Determines the # of bytes per pixel we need to reserve for a given format in
* the tilebuffer (compared to 128-bit budget, etc). Usually the same as the
* bytes per pixel of the format itself, but there are some special cases I
* don't understand. */
static unsigned
pan_bytes_per_pixel_tib(enum pipe_format format)
{
const struct util_format_description *desc =
util_format_description(format);
if (util_format_is_unorm8(desc) || format == PIPE_FORMAT_B5G6R5_UNORM)
return 4;
return desc->block.bits / 8;
}
/* Determines whether a framebuffer uses too much tilebuffer space (requiring
* us to scale up the tile at a performance penalty). This is conservative but
* afaict you get 128-bits per pixel normally */
@ -440,8 +457,7 @@ pan_is_large_tib(struct panfrost_batch *batch)
for (int cb = 0; cb < batch->key.nr_cbufs; ++cb) {
struct pipe_surface *surf = batch->key.cbufs[cb];
assert(surf);
unsigned bpp = util_format_get_blocksize(surf->format);
size += ALIGN_POT(bpp, 4);
size += pan_bytes_per_pixel_tib(surf->format);
}
return (size > 16);
@ -515,17 +531,18 @@ panfrost_mfbd_fragment(struct panfrost_batch *batch, bool has_draws)
unsigned rt_descriptors = MAX2(batch->key.nr_cbufs, 1);
fb.rt_count_1 = MALI_POSITIVE(rt_descriptors);
fb.rt_count_2 = rt_descriptors;
fb.mfbd_flags = 0x100;
/* TODO: MRT clear */
panfrost_mfbd_clear(batch, &fb, &fbx, rts, fb.rt_count_2);
panfrost_mfbd_clear(batch, &fb, &fbx, rts, rt_descriptors);
/* Upload either the render target or a dummy GL_NONE target */
unsigned offset = 0;
bool is_large = pan_is_large_tib(batch);
for (int cb = 0; cb < rt_descriptors; ++cb) {
struct pipe_surface *surf = batch->key.cbufs[cb];
unsigned rt_offset = offset * 0x100;
if (surf && ((batch->clear | batch->draws) & (PIPE_CLEAR_COLOR0 << cb))) {
unsigned nr_samples = surf->nr_samples;
@ -538,12 +555,7 @@ panfrost_mfbd_fragment(struct panfrost_batch *batch, bool has_draws)
panfrost_mfbd_set_cbuf(&rts[cb], surf);
/* What is this? Looks like some extension of the bpp
* field. Maybe it establishes how much internal
* tilebuffer space is reserved? */
unsigned bpp = util_format_get_blocksize(surf->format);
fb.rt_count_2 = MAX2(fb.rt_count_2, ALIGN_POT(bpp, 4) / 4);
offset += pan_bytes_per_pixel_tib(surf->format);
} else {
struct mali_rt_format null_rt = {
.unk1 = 0x4000000,
@ -561,9 +573,11 @@ panfrost_mfbd_fragment(struct panfrost_batch *batch, bool has_draws)
}
/* TODO: Break out the field */
rts[cb].format.unk1 |= (cb * 0x400);
rts[cb].format.unk1 |= is_large ? (rt_offset / 4) : rt_offset;
}
fb.rt_count_2 = MAX2(DIV_ROUND_UP(offset, is_large ? 16 : 4), 1);
if (batch->key.zsbuf && ((batch->clear | batch->draws) & PIPE_CLEAR_DEPTHSTENCIL)) {
panfrost_mfbd_set_zsbuf(&fb, &fbx, batch->key.zsbuf);
}