panfrost: Tiled to linear layout conversion
authorIcecream95 <ixn@keemail.me>
Sun, 19 Apr 2020 03:44:17 +0000 (15:44 +1200)
committerMarge Bot <eric+marge@anholt.net>
Fri, 12 Jun 2020 19:15:47 +0000 (19:15 +0000)
Tiling is expensive, so this patch converts textures that appear to be
used for streaming to a linear layout.

Performance of mpv is significantly improved, with software-decoded
1080p mp4 playback on RK3288 going from 30fps to 50fps when testing
with `--untimed --no-audio`.

To keep things simple, conversion only happens when updating the whole
texture and no mipmapping is used.

v2: Make it clear that the heuristic doesn't rely on a texture being
uninitialized, since layout switching code can get confusing (Alyssa).

Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4628>

src/gallium/drivers/panfrost/pan_resource.c
src/gallium/drivers/panfrost/pan_resource.h

index 84f82ab76891f8312b010c0d5dd118d6e6384e57..8c1cda9513df3b52a400f0770f72d3bdc8e100aa 100644 (file)
@@ -427,6 +427,7 @@ panfrost_resource_create_bo(struct panfrost_device *dev, struct panfrost_resourc
         /* Set the layout appropriately */
         assert(!(must_tile && !can_tile)); /* must_tile => can_tile */
         pres->layout = ((can_tile && should_tile) || must_tile) ? MALI_TEXTURE_TILED : MALI_TEXTURE_LINEAR;
+        pres->layout_constant = must_tile || !can_tile;
 
         size_t bo_size;
 
@@ -725,14 +726,48 @@ panfrost_transfer_unmap(struct pipe_context *pctx,
                         } else if (prsrc->layout == MALI_TEXTURE_TILED) {
                                 assert(transfer->box.depth == 1);
 
-                                panfrost_store_tiled_image(
-                                        bo->cpu + prsrc->slices[transfer->level].offset,
-                                        trans->map,
-                                        transfer->box.x, transfer->box.y,
-                                        transfer->box.width, transfer->box.height,
-                                        prsrc->slices[transfer->level].stride,
-                                        transfer->stride,
-                                        prsrc->internal_format);
+                                /* Do we overwrite the entire resource? If so,
+                                 * we don't need an intermediate blit so it's a
+                                 * good time to switch the layout. */
+
+                                bool discards_content = prsrc->base.last_level == 0
+                                    && transfer->box.width == prsrc->base.width0
+                                    && transfer->box.height == prsrc->base.height0
+                                    && transfer->box.x == 0
+                                    && transfer->box.y == 0
+                                    && !prsrc->layout_constant;
+
+                                /* It also serves as a good heuristic for
+                                 * streaming textures (e.g. in video players),
+                                 * but we could do better */
+
+                                if (discards_content)
+                                        ++prsrc->layout_updates;
+
+                                if (prsrc->layout_updates >= LAYOUT_CONVERT_THRESHOLD)
+                                {
+                                        prsrc->layout = MALI_TEXTURE_LINEAR;
+
+                                        util_copy_rect(
+                                                bo->cpu + prsrc->slices[0].offset,
+                                                prsrc->base.format,
+                                                prsrc->slices[0].stride,
+                                                0, 0,
+                                                transfer->box.width,
+                                                transfer->box.height,
+                                                trans->map,
+                                                transfer->stride,
+                                                0, 0);
+                                } else {
+                                        panfrost_store_tiled_image(
+                                                bo->cpu + prsrc->slices[transfer->level].offset,
+                                                trans->map,
+                                                transfer->box.x, transfer->box.y,
+                                                transfer->box.width, transfer->box.height,
+                                                prsrc->slices[transfer->level].stride,
+                                                transfer->stride,
+                                                prsrc->internal_format);
+                                }
                         }
                 }
         }
index 0a25e305de02461770fa3160579638d1306d0bb4..c6226cbe272d47744a3b88401c0ae7f3073216a7 100644 (file)
@@ -34,6 +34,8 @@
 #include "drm-uapi/drm.h"
 #include "util/u_range.h"
 
+#define LAYOUT_CONVERT_THRESHOLD 8
+
 struct panfrost_resource {
         struct pipe_resource base;
         struct {
@@ -57,9 +59,15 @@ struct panfrost_resource {
         /* Internal layout (tiled?) */
         enum mali_texture_layout layout;
 
+        /* Whether the layout can be changed */
+        bool layout_constant;
+
         /* Is transaciton elimination enabled? */
         bool checksummed;
 
+        /* Used to decide when to convert to another layout */
+        uint16_t layout_updates;
+
         enum pipe_format internal_format;
 
         /* Cached min/max values for index buffers */