lima: Implement lima_texture_subdata
authorVasily Khoruzhick <anarsoul@gmail.com>
Mon, 23 Mar 2020 06:12:06 +0000 (23:12 -0700)
committerMarge Bot <eric+marge@anholt.net>
Sat, 28 Mar 2020 00:17:40 +0000 (00:17 +0000)
We can avoid intermediate copy if we implement it ourselves.
Improves x11perf -shmput500 from 199.0/s to 283.0/s

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

src/gallium/drivers/lima/lima_resource.c

index e60a46b7ae8e80155f4dbffc9ae127e39557dc41..bd3549db44866e297c8e7d14268672e3751ecf91 100644 (file)
@@ -626,22 +626,22 @@ lima_transfer_flush_region(struct pipe_context *pctx,
 }
 
 static void
-lima_transfer_unmap(struct pipe_context *pctx,
-                    struct pipe_transfer *ptrans)
+lima_transfer_unmap_inner(struct lima_context *ctx,
+                          struct pipe_transfer *ptrans)
 {
-   struct lima_context *ctx = lima_context(pctx);
-   struct lima_transfer *trans = lima_transfer(ptrans);
+
    struct lima_resource *res = lima_resource(ptrans->resource);
+   struct lima_transfer *trans = lima_transfer(ptrans);
    struct lima_bo *bo = res->bo;
    struct pipe_resource *pres;
 
    if (trans->staging) {
       pres = &res->base;
-      if (ptrans->usage & PIPE_TRANSFER_WRITE) {
+      if (trans->base.usage & PIPE_TRANSFER_WRITE) {
          unsigned i;
-         for (i = 0; i < ptrans->box.depth; i++)
+         for (i = 0; i < trans->base.box.depth; i++)
             panfrost_store_tiled_image(
-               bo->map + res->levels[ptrans->level].offset + (i + ptrans->box.z) * res->levels[ptrans->level].layer_stride,
+               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,
@@ -649,9 +649,20 @@ lima_transfer_unmap(struct pipe_context *pctx,
                ptrans->stride,
                pres->format);
       }
-      free(trans->staging);
    }
+}
 
+static void
+lima_transfer_unmap(struct pipe_context *pctx,
+                    struct pipe_transfer *ptrans)
+{
+   struct lima_context *ctx = lima_context(pctx);
+   struct lima_transfer *trans = lima_transfer(ptrans);
+   struct lima_resource *res = lima_resource(ptrans->resource);
+
+   lima_transfer_unmap_inner(ctx, ptrans);
+   if (trans->staging)
+      free(trans->staging);
    panfrost_minmax_cache_invalidate(res->index_cache, ptrans);
 
    pipe_resource_reference(&ptrans->resource, NULL);
@@ -718,18 +729,59 @@ lima_flush_resource(struct pipe_context *pctx, struct pipe_resource *resource)
 
 }
 
+static void
+lima_texture_subdata(struct pipe_context *pctx,
+                     struct pipe_resource *prsc,
+                     unsigned level,
+                     unsigned usage,
+                     const struct pipe_box *box,
+                     const void *data,
+                     unsigned stride,
+                     unsigned layer_stride)
+{
+   struct lima_context *ctx = lima_context(pctx);
+   struct lima_resource *res = lima_resource(prsc);
+
+   if (!res->tiled) {
+      u_default_texture_subdata(pctx, prsc, level, usage, box,
+                                data, stride, layer_stride);
+      return;
+   }
+
+   assert(!(usage & PIPE_TRANSFER_READ));
+
+   struct lima_transfer t = {
+      .base = {
+         .resource = prsc,
+         .usage = PIPE_TRANSFER_WRITE,
+         .level = level,
+         .box = *box,
+         .stride = stride,
+         .layer_stride = layer_stride,
+      },
+      .staging = (void *)data,
+   };
+
+   lima_flush_job_accessing_bo(ctx, res->bo, true);
+   lima_bo_wait(res->bo, LIMA_GEM_WAIT_WRITE, PIPE_TIMEOUT_INFINITE);
+   if (!lima_bo_map(res->bo))
+      return;
+
+   lima_transfer_unmap_inner(ctx, &t.base);
+}
+
 void
 lima_resource_context_init(struct lima_context *ctx)
 {
    ctx->base.create_surface = lima_surface_create;
    ctx->base.surface_destroy = lima_surface_destroy;
 
-   /* TODO: optimize these functions to read/write data directly
-    * from/to target instead of creating a staging memory for tiled
-    * buffer indirectly
-    */
    ctx->base.buffer_subdata = u_default_buffer_subdata;
-   ctx->base.texture_subdata = u_default_texture_subdata;
+   ctx->base.texture_subdata = lima_texture_subdata;
+   /* TODO: optimize resource_copy_region to do copy directly
+    * between 2 tiled or tiled and linear resources instead of
+    * using staging buffer.
+    */
    ctx->base.resource_copy_region = util_resource_copy_region;
 
    ctx->base.blit = lima_blit;