lima: switch resource to linear layout if there's to many full updates
authorVasily Khoruzhick <anarsoul@gmail.com>
Sun, 2 May 2021 05:45:30 +0000 (22:45 -0700)
committerMarge Bot <eric+marge@anholt.net>
Sun, 2 May 2021 14:55:13 +0000 (14:55 +0000)
Overwriting entire resource multiple times indicates streaming and in this
case it's more efficient to use linear layout to avoid expensive linear->tiled
conversions.

Reviewed-by: Erico Nunes <nunes.erico@gmail.com>
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10572>

src/gallium/drivers/lima/lima_resource.c
src/gallium/drivers/lima/lima_resource.h

index d16a0b0..4e0c8d3 100644 (file)
@@ -322,6 +322,8 @@ lima_resource_from_handle(struct pipe_screen *pscreen,
       return NULL;
    }
 
+   res->modifier_constant = true;
+
    switch (handle->modifier) {
    case DRM_FORMAT_MOD_LINEAR:
       res->tiled = false;
@@ -412,6 +414,8 @@ lima_resource_get_handle(struct pipe_screen *pscreen,
    else
       handle->modifier = DRM_FORMAT_MOD_LINEAR;
 
+   res->modifier_constant = true;
+
    if (handle->type == WINSYS_HANDLE_TYPE_KMS && screen->ro &&
        renderonly_get_handle(res->scanout, handle))
       return true;
@@ -686,6 +690,38 @@ lima_transfer_flush_region(struct pipe_context *pctx,
 
 }
 
+static bool
+lima_should_convert_linear(struct lima_resource *res,
+                           struct pipe_transfer *ptrans)
+{
+   if (res->modifier_constant)
+          return false;
+
+   /* Overwriting the entire resource indicates streaming, for which
+    * linear layout is most efficient due to the lack of expensive
+    * conversion.
+    *
+    * For now we just switch to linear after a number of complete
+    * overwrites to keep things simple, but we could do better.
+    */
+
+   unsigned depth = res->base.target == PIPE_TEXTURE_3D ?
+                    res->base.depth0 : res->base.array_size;
+   bool entire_overwrite =
+          res->base.last_level == 0 &&
+          ptrans->box.width == res->base.width0 &&
+          ptrans->box.height == res->base.height0 &&
+          ptrans->box.depth == depth &&
+          ptrans->box.x == 0 &&
+          ptrans->box.y == 0 &&
+          ptrans->box.z == 0;
+
+   if (entire_overwrite)
+          ++res->full_updates;
+
+   return res->full_updates >= LAYOUT_CONVERT_THRESHOLD;
+}
+
 static void
 lima_transfer_unmap_inner(struct lima_context *ctx,
                           struct pipe_transfer *ptrans)
@@ -699,15 +735,36 @@ lima_transfer_unmap_inner(struct lima_context *ctx,
       pres = &res->base;
       if (trans->base.usage & PIPE_MAP_WRITE) {
          unsigned i;
-         for (i = 0; i < trans->base.box.depth; i++)
-            panfrost_store_tiled_image(
-               bo->map + res->levels[trans->base.level].offset + (i + trans->base.box.z) * res->levels[trans->base.level].layer_stride,
-               trans->staging + i * ptrans->stride * ptrans->box.height,
-               ptrans->box.x, ptrans->box.y,
-               ptrans->box.width, ptrans->box.height,
-               res->levels[ptrans->level].stride,
-               ptrans->stride,
-               pres->format);
+         if (lima_should_convert_linear(res, ptrans)) {
+            /* It's safe to re-use the same BO since tiled BO always has
+             * aligned dimensions */
+            for (i = 0; i < trans->base.box.depth; i++) {
+               util_copy_rect(bo->map + res->levels[0].offset +
+                                 (i + trans->base.box.z) * res->levels[0].stride,
+                              res->base.format,
+                              res->levels[0].stride,
+                              0, 0,
+                              ptrans->box.width,
+                              ptrans->box.height,
+                              trans->staging + i * ptrans->stride * ptrans->box.height,
+                              ptrans->stride,
+                              0, 0);
+            }
+            res->tiled = false;
+            res->modifier_constant = true;
+            /* Update texture descriptor */
+            ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES;
+         } else {
+            for (i = 0; i < trans->base.box.depth; i++)
+               panfrost_store_tiled_image(
+                  bo->map + res->levels[trans->base.level].offset + (i + trans->base.box.z) * res->levels[trans->base.level].layer_stride,
+                  trans->staging + i * ptrans->stride * ptrans->box.height,
+                  ptrans->box.x, ptrans->box.y,
+                  ptrans->box.width, ptrans->box.height,
+                  res->levels[ptrans->level].stride,
+                  ptrans->stride,
+                  pres->format);
+         }
       }
    }
 }
index 36ea605..91443e5 100644 (file)
@@ -29,6 +29,7 @@
 
 /* max texture size is 4096x4096 */
 #define LIMA_MAX_MIP_LEVELS 13
+#define LAYOUT_CONVERT_THRESHOLD 8
 
 struct lima_screen;
 struct panfrost_minmax_cache;
@@ -55,6 +56,8 @@ struct lima_resource {
    struct lima_bo *bo;
    struct panfrost_minmax_cache *index_cache;
    bool tiled;
+   bool modifier_constant;
+   unsigned full_updates;
 
    struct lima_resource_level levels[LIMA_MAX_MIP_LEVELS];
 };