[RFC,2/2] etnaviv: try to use CPU to tile/untile when the region is small enough

Submitted by Boris Brezillon on Feb. 20, 2019, 5:01 p.m.

Details

Message ID 20190220170137.23115-3-boris.brezillon@collabora.com
State New
Headers show
Series "etnaviv: use CPU-based tiling/untiling for small regions" ( rev: 1 ) in Mesa

Not browsing as part of any series.

Commit Message

Boris Brezillon Feb. 20, 2019, 5:01 p.m.
Using the GPU has a cost, it implies preparing the RS/BLT request and
then possibly requires extra GPU -> CPU syncs, so let's only use
GPU-based tiling/untiling for rather big regions.

While at it, move the "should we use the GPU to tile/untile" logic to
its own function to make things more readable.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 .../drivers/etnaviv/etnaviv_transfer.c        | 67 +++++++++++++++++--
 1 file changed, 61 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/gallium/drivers/etnaviv/etnaviv_transfer.c b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
index 38648564b701..a3013e624ead 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
@@ -132,6 +132,66 @@  etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans)
    slab_free(&ctx->transfer_pool, trans);
 }
 
+#define GPU_TILING_MIN_SURFACE_SIZE		1024
+#define GPU_TILING_MIN_UNALIGNED_SURFACE_SIZE	8192
+
+static bool
+etna_transfer_use_gpu(struct etna_context *ctx, struct etna_resource *rsc,
+                      const struct pipe_box *box)
+{
+   unsigned w_align, h_align;
+
+   /* Always use the GPU to tile/untile when the resource has a Tile Status
+    * buffer attached. */
+   if (rsc->ts_bo)
+      return true;
+
+   /* Nothing to tile/untile if the resource is using a linear format. */
+   if (rsc->layout == ETNA_LAYOUT_LINEAR)
+      return false;
+
+   /* Do not use the GPU when the resource is using a 1byte/pixel format. */
+   if (util_format_get_blocksize(rsc->base.format) == 1)
+      return false;
+
+   /* HALIGN 4 resources are incompatible with the resolve engine, so fall back
+    * to using software to detile this resource. */
+   if (rsc->halign == TEXTURE_HALIGN_FOUR)
+      return false;
+
+   /* Using the GPU has a cost, it implies preparing the RS/BLT request and
+    * then possibly requires extra GPU -> CPU syncs, so let's only use
+    * GPU-based tiling for rather big regions. Right now the minimum surface
+    * surface size is arbitrarily set to 1024 pixels. */
+   if (box->width * box->height < GPU_TILING_MIN_SURFACE_SIZE)
+      return false;
+
+   /* No alignment constraints when using BLT. */
+   if (ctx->specs.use_blt)
+      return true;
+
+   if (rsc->layout & ETNA_LAYOUT_BIT_SUPER) {
+      w_align = h_align = 64;
+   } else {
+      w_align = ETNA_RS_WIDTH_MASK + 1;
+      h_align = ETNA_RS_HEIGHT_MASK + 1;
+   }
+   h_align *= ctx->screen->specs.pixel_pipes;
+
+   /* Everything is properly aligned, let's use the RS engine to
+    * tile/untile. */
+   if (!((box->x | box->width) & (w_align - 1)) &&
+       !((box->y | box->height) & (h_align - 1)))
+      return true;
+
+   /* We want the minimum surface size to be even bigger for unaligned
+    * requests. */
+   if (box->width * box->height < GPU_TILING_MIN_UNALIGNED_SURFACE_SIZE)
+      return false;
+
+   return true;
+}
+
 static void *
 etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc,
                   unsigned level,
@@ -179,12 +239,7 @@  etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc,
        * render resource. Use the texture resource, which avoids bouncing
        * pixels between the two resources, and we can de-tile it in s/w. */
       rsc = etna_resource(rsc->texture);
-   } else if (rsc->ts_bo ||
-              (rsc->layout != ETNA_LAYOUT_LINEAR &&
-               util_format_get_blocksize(format) > 1 &&
-               /* HALIGN 4 resources are incompatible with the resolve engine,
-                * so fall back to using software to detile this resource. */
-               rsc->halign != TEXTURE_HALIGN_FOUR)) {
+   } else if (etna_transfer_use_gpu(ctx, rsc, box)) {
       /* If the surface has tile status, we need to resolve it first.
        * The strategy we implement here is to use the RS to copy the
        * depth buffer, filling in the "holes" where the tile status