panfrost: Overhaul tilebuffer allocations
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Thu, 9 Jul 2020 21:35:24 +0000 (17:35 -0400)
committerMarge Bot <eric+marge@anholt.net>
Thu, 16 Jul 2020 19:59:43 +0000 (19:59 +0000)
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>

src/gallium/drivers/panfrost/pan_mfbd.c

index 4d48f2dcac312b12e647ca63200316b539503f63..ac890b5c56f47d57be1ac1bfa24a3134519b2df7 100644 (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);
         }