Mesa (master): etnaviv: Rework resource status tracking

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Oct 18 17:04:13 UTC 2019


Module: Mesa
Branch: master
Commit: 1456aa61cc51f6e7727944d58a662d00158cf111
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=1456aa61cc51f6e7727944d58a662d00158cf111

Author: Marek Vasut <marex at denx.de>
Date:   Thu Sep  5 01:23:52 2019 +0200

etnaviv: Rework resource status tracking

Have each context track which resources it marked as pending read and
pending write. Have each resource track in which context it is pending.
This way, it is possible to identify when a resource is both pending
read and pending write at the same time. Moreover, the status field
can be correctly calculated and updated when necessary.

Signed-off-by: Marek Vasut <marex at denx.de>

---

 src/gallium/drivers/etnaviv/etnaviv_context.c  | 48 +++++++++++++----
 src/gallium/drivers/etnaviv/etnaviv_context.h  |  3 +-
 src/gallium/drivers/etnaviv/etnaviv_resource.c | 71 ++++++++++++++++++--------
 src/gallium/drivers/etnaviv/etnaviv_resource.h |  3 ++
 4 files changed, 93 insertions(+), 32 deletions(-)

diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c
index ff03650ffa5..4a33b7a9229 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_context.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_context.c
@@ -63,23 +63,38 @@ etna_context_destroy(struct pipe_context *pctx)
    struct etna_context *ctx = etna_context(pctx);
    struct etna_screen *screen = ctx->screen;
 
-   if (ctx->used_resources) {
-      mtx_lock(&screen->lock);
+   mtx_lock(&screen->lock);
+   if (ctx->used_resources_read) {
+
+      /*
+       * There should be no resources tracked in the context when it's being
+       * destroyed. Be sure there are none to avoid memory leaks on buggy
+       * programs.
+       */
+      set_foreach(ctx->used_resources_read, entry) {
+         struct etna_resource *rsc = (struct etna_resource *)entry->key;
+
+         _mesa_set_remove_key(rsc->pending_ctx, ctx);
+      }
+      _mesa_set_destroy(ctx->used_resources_read, NULL);
+
+   }
+   if (ctx->used_resources_write) {
 
       /*
        * There should be no resources tracked in the context when it's being
        * destroyed. Be sure there are none to avoid memory leaks on buggy
        * programs.
        */
-      set_foreach(ctx->used_resources, entry) {
+      set_foreach(ctx->used_resources_write, entry) {
          struct etna_resource *rsc = (struct etna_resource *)entry->key;
 
          _mesa_set_remove_key(rsc->pending_ctx, ctx);
       }
-      _mesa_set_destroy(ctx->used_resources, NULL);
+      _mesa_set_destroy(ctx->used_resources_write, NULL);
 
-      mtx_unlock(&screen->lock);
    }
+   mtx_unlock(&screen->lock);
 
    if (ctx->dummy_rt)
       etna_bo_del(ctx->dummy_rt);
@@ -417,17 +432,25 @@ etna_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence,
    * Go through all _resources_ pending in this _context_ and mark them as
    * not pending in this _context_ anymore, since they were just flushed.
    */
-   set_foreach(ctx->used_resources, entry) {
+   set_foreach(ctx->used_resources_read, entry) {
       struct etna_resource *rsc = (struct etna_resource *)entry->key;
       struct pipe_resource *referenced = &rsc->base;
 
-      rsc->status = 0;
+      _mesa_set_remove_key(rsc->pending_ctx, ctx);
+
+      pipe_resource_reference(&referenced, NULL);
+   }
+   _mesa_set_clear(ctx->used_resources_read, NULL);
+
+   set_foreach(ctx->used_resources_write, entry) {
+      struct etna_resource *rsc = (struct etna_resource *)entry->key;
+      struct pipe_resource *referenced = &rsc->base;
 
       _mesa_set_remove_key(rsc->pending_ctx, ctx);
 
       pipe_resource_reference(&referenced, NULL);
    }
-   _mesa_set_clear(ctx->used_resources, NULL);
+   _mesa_set_clear(ctx->used_resources_write, NULL);
 
    mtx_unlock(&screen->lock);
 
@@ -479,9 +502,14 @@ etna_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
    if (ctx->stream == NULL)
       goto fail;
 
-   ctx->used_resources = _mesa_set_create(NULL, _mesa_hash_pointer,
+   ctx->used_resources_read = _mesa_set_create(NULL, _mesa_hash_pointer,
+                                          _mesa_key_pointer_equal);
+   if (!ctx->used_resources_read)
+      goto fail;
+
+   ctx->used_resources_write = _mesa_set_create(NULL, _mesa_hash_pointer,
                                           _mesa_key_pointer_equal);
-   if (!ctx->used_resources)
+   if (!ctx->used_resources_write)
       goto fail;
 
    /* context ctxate setup */
diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.h b/src/gallium/drivers/etnaviv/etnaviv_context.h
index 9fa6396dbb5..25169abd71d 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_context.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_context.h
@@ -192,7 +192,8 @@ struct etna_context {
    struct etna_reloc dummy_rt_reloc;
 
    /* set of resources used by currently-unsubmitted renders */
-   struct set *used_resources;
+   struct set *used_resources_read;
+   struct set *used_resources_write;
 };
 
 static inline struct etna_context *
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c
index 4ccf887f600..1d1a0587f2a 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
@@ -605,6 +605,35 @@ etna_resource_get_handle(struct pipe_screen *pscreen,
    }
 }
 
+enum etna_resource_status
+etna_resource_get_status(struct etna_context *ctx, struct etna_resource *rsc)
+{
+   enum etna_resource_status newstatus = 0;
+
+   set_foreach(rsc->pending_ctx, entry) {
+      struct etna_context *extctx = (struct etna_context *)entry->key;
+      struct pipe_context *pctx = &extctx->base;
+
+      set_foreach(extctx->used_resources_read, entry2) {
+         struct etna_resource *rsc2 = (struct etna_resource *)entry2->key;
+         if (ctx == extctx || rsc2 != rsc)
+            continue;
+
+         newstatus |= ETNA_PENDING_READ;
+      }
+
+      set_foreach(extctx->used_resources_write, entry2) {
+         struct etna_resource *rsc2 = (struct etna_resource *)entry2->key;
+         if (ctx == extctx || rsc2 != rsc)
+            continue;
+
+         newstatus |= ETNA_PENDING_WRITE;
+      }
+   }
+
+   return newstatus;
+}
+
 void
 etna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc,
                    enum etna_resource_status status)
@@ -616,40 +645,40 @@ etna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc,
    if (!prsc)
       return;
 
+   mtx_lock(&screen->lock);
+
    rsc = etna_resource(prsc);
 
-   mtx_lock(&screen->lock);
+   enum etna_resource_status newstatus = 0;
 
-   /*
-    * if we are pending read or write by any other context or
-    * if reading a resource pending a write, then
-    * flush all the contexts to maintain coherency
-    */
-   if (((status & ETNA_PENDING_WRITE) && rsc->status) ||
-       ((status & ETNA_PENDING_READ) && (rsc->status & ETNA_PENDING_WRITE))) {
-      set_foreach(rsc->pending_ctx, entry) {
-         struct etna_context *extctx = (struct etna_context *)entry->key;
-         struct pipe_context *pctx = &extctx->base;
+   set_foreach(rsc->pending_ctx, entry) {
+      struct etna_context *extctx = (struct etna_context *)entry->key;
+      struct pipe_context *pctx = &extctx->base;
+
+      set_foreach(extctx->used_resources_read, entry2) {
+         struct etna_resource *rsc2 = (struct etna_resource *)entry2->key;
+         if (ctx == extctx || rsc2 != rsc)
+            continue;
+
+         if (status & ETNA_PENDING_WRITE)
+            pctx->flush(pctx, NULL, 0);
+      }
 
-         if (extctx == ctx)
+      set_foreach(extctx->used_resources_write, entry2) {
+         struct etna_resource *rsc2 = (struct etna_resource *)entry2->key;
+         if (ctx == extctx || rsc2 != rsc)
             continue;
 
          pctx->flush(pctx, NULL, 0);
-         /* It's safe to clear the status here. If we need to flush it means
-          * either another context had the resource in exclusive (write) use,
-          * or we transition the resource to exclusive use in our context.
-          * In both cases the new status accurately reflects the resource use
-          * after the flush.
-          */
-         rsc->status = 0;
       }
    }
 
-   rsc->status |= status;
+   rsc->status = status;
 
    if (!_mesa_set_search(rsc->pending_ctx, ctx)) {
       pipe_resource_reference(&referenced, prsc);
-      _mesa_set_add(ctx->used_resources, rsc);
+      _mesa_set_add((status & ETNA_PENDING_READ) ?
+                    ctx->used_resources_read : ctx->used_resources_write, rsc);
       _mesa_set_add(rsc->pending_ctx, ctx);
    }
 
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h b/src/gallium/drivers/etnaviv/etnaviv_resource.h
index 1c253006471..64aef18a016 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h
@@ -134,6 +134,9 @@ etna_resource(struct pipe_resource *p)
    return (struct etna_resource *)p;
 }
 
+enum etna_resource_status
+etna_resource_get_status(struct etna_context *ctx, struct etna_resource *rsc);
+
 void
 etna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc,
                    enum etna_resource_status status);




More information about the mesa-commit mailing list