Mesa (master): panfrost: Fix the DISCARD_WHOLE_RES case in transfer_map()

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Oct 21 13:39:35 UTC 2019


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

Author: Boris Brezillon <boris.brezillon at collabora.com>
Date:   Thu Oct 10 15:12:30 2019 +0200

panfrost: Fix the DISCARD_WHOLE_RES case in transfer_map()

The current implementation does not synchronize on BO readiness when
DISCARD_WHOLE_RES flag is set, which can lead to misbehaviours when the
resource being updated is being used by one of the pending or already
flushed batches.

Adding unconditional BO synchronization would do the trick, but we can
sometimes optimize this path by re-allocating a new BO instead of
waiting for the existing one to be ready.

Reported-by: Daniel Stone <daniels at collabora.com>
Reported-by: Heinrich Fink <heinrich.fink at daqri.com>
Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: Daniel Stone <daniels at collabora.com>
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig at collabora.com>

---

 src/gallium/drivers/panfrost/pan_job.c      | 24 +++++++++++++++++++
 src/gallium/drivers/panfrost/pan_job.h      |  4 ++++
 src/gallium/drivers/panfrost/pan_resource.c | 37 +++++++++++++++++++++++++++--
 3 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c
index a10d4a37528..9cff5232519 100644
--- a/src/gallium/drivers/panfrost/pan_job.c
+++ b/src/gallium/drivers/panfrost/pan_job.c
@@ -984,6 +984,30 @@ panfrost_flush_all_batches(struct panfrost_context *ctx, bool wait)
         util_dynarray_fini(&syncobjs);
 }
 
+bool
+panfrost_pending_batches_access_bo(struct panfrost_context *ctx,
+                                   const struct panfrost_bo *bo)
+{
+        struct panfrost_bo_access *access;
+        struct hash_entry *hentry;
+
+        hentry = _mesa_hash_table_search(ctx->accessed_bos, bo);
+        access = hentry ? hentry->data : NULL;
+        if (!access)
+                return false;
+
+        if (access->writer && access->writer->batch)
+                return true;
+
+        util_dynarray_foreach(&access->readers, struct panfrost_batch_fence *,
+                              reader) {
+                if (*reader && (*reader)->batch)
+                        return true;
+        }
+
+        return false;
+}
+
 void
 panfrost_flush_batches_accessing_bo(struct panfrost_context *ctx,
                                     struct panfrost_bo *bo,
diff --git a/src/gallium/drivers/panfrost/pan_job.h b/src/gallium/drivers/panfrost/pan_job.h
index 1da5d57aec1..2a810421caa 100644
--- a/src/gallium/drivers/panfrost/pan_job.h
+++ b/src/gallium/drivers/panfrost/pan_job.h
@@ -188,6 +188,10 @@ panfrost_batch_create_bo(struct panfrost_batch *batch, size_t size,
 void
 panfrost_flush_all_batches(struct panfrost_context *ctx, bool wait);
 
+bool
+panfrost_pending_batches_access_bo(struct panfrost_context *ctx,
+                                   const struct panfrost_bo *bo);
+
 void
 panfrost_flush_batches_accessing_bo(struct panfrost_context *ctx,
                                     struct panfrost_bo *bo, uint32_t flags);
diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c
index db0643c7305..d0619a89882 100644
--- a/src/gallium/drivers/panfrost/pan_resource.c
+++ b/src/gallium/drivers/panfrost/pan_resource.c
@@ -587,8 +587,41 @@ panfrost_transfer_map(struct pipe_context *pctx,
         /* TODO: Respect usage flags */
 
         if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
-                /* TODO: reallocate */
-                //printf("debug: Missed reallocate\n");
+                /* If the BO is used by one of the pending batches or if it's
+                 * not ready yet (still accessed by one of the already flushed
+                 * batches), we try to allocate a new one to avoid waiting.
+                 */
+                if (panfrost_pending_batches_access_bo(ctx, bo) ||
+                    !panfrost_bo_wait(bo, 0, PAN_BO_ACCESS_RW)) {
+                        struct panfrost_screen *screen = pan_screen(pctx->screen);
+                        /* We want the BO to be MMAPed. */
+                        uint32_t flags = bo->flags & ~PAN_BO_DELAY_MMAP;
+                        struct panfrost_bo *newbo = NULL;
+
+                        /* When the BO has been imported/exported, we can't
+                         * replace it by another one, otherwise the
+                         * importer/exporter wouldn't see the change we're
+                         * doing to it.
+                         */
+                        if (!(bo->flags & (PAN_BO_IMPORTED | PAN_BO_EXPORTED)))
+                                newbo = panfrost_bo_create(screen, bo->size,
+                                                           flags);
+
+                        if (newbo) {
+                                panfrost_bo_unreference(bo);
+                                rsrc->bo = newbo;
+                                bo = newbo;
+                        } else {
+                                uint32_t access = PAN_BO_ACCESS_RW;
+
+                                /* Allocation failed or was impossible, let's
+                                 * fall back on a flush+wait.
+                                 */
+                                panfrost_flush_batches_accessing_bo(ctx, bo,
+                                                                    access);
+                                panfrost_bo_wait(bo, INT64_MAX, access);
+                        }
+                }
         } else if ((usage & PIPE_TRANSFER_WRITE)
                    && resource->target == PIPE_BUFFER
                    && !util_ranges_intersect(&rsrc->valid_buffer_range, box->x, box->x + box->width)) {




More information about the mesa-commit mailing list