freedreno: add batch debugging
authorRob Clark <robdclark@chromium.org>
Sat, 23 May 2020 18:00:40 +0000 (11:00 -0700)
committerMarge Bot <eric+marge@anholt.net>
Tue, 26 May 2020 19:14:22 +0000 (19:14 +0000)
Something I cooked up in the process of debugging the issue fixed in the
next commit.  Might come in useful again in the future.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5188>

src/gallium/drivers/freedreno/freedreno_batch.c
src/gallium/drivers/freedreno/freedreno_batch.h
src/gallium/drivers/freedreno/freedreno_batch_cache.c
src/gallium/drivers/freedreno/freedreno_batch_cache.h
src/gallium/drivers/freedreno/freedreno_context.c
src/gallium/drivers/freedreno/freedreno_screen.c
src/gallium/drivers/freedreno/freedreno_screen.h

index b31dd2c02c8240a04eff24b38df822d4201ccf3e..4ad10aeb35ac7deb31f83cf20c75944b9520532c 100644 (file)
@@ -128,6 +128,11 @@ fd_batch_create(struct fd_context *ctx, bool nondraw)
 
        batch_init(batch);
 
+       fd_screen_assert_locked(ctx->screen);
+       if (BATCH_DEBUG) {
+               _mesa_set_add(ctx->screen->live_batches, batch);
+       }
+
        return batch;
 }
 
@@ -271,6 +276,10 @@ __fd_batch_destroy(struct fd_batch *batch)
 
        fd_context_assert_locked(batch->ctx);
 
+       if (BATCH_DEBUG) {
+               _mesa_set_remove_key(ctx->screen->live_batches, batch);
+       }
+
        fd_bc_invalidate_batch(batch, true);
 
        batch_reset_resources_locked(batch);
index e64d9061b6b854c1d0c7374ac77587ab5a664646..b7b970359a357d13040c199e2b1584042f1f3832 100644 (file)
 
 #include "freedreno_util.h"
 
+#ifdef DEBUG
+#  define BATCH_DEBUG (fd_mesa_debug & FD_DBG_MSGS)
+#else
+#  define BATCH_DEBUG 0
+#endif
+
 struct fd_context;
 struct fd_resource;
 enum fd_resource_status;
index 329ed41fba363e34b9e9cdb7393cd234c10ebad7..448e701bbc6276c81d2edd155c466ad0b2f60c6a 100644 (file)
@@ -187,6 +187,45 @@ fd_bc_flush_deferred(struct fd_batch_cache *cache, struct fd_context *ctx)
        bc_flush(cache, ctx, true);
 }
 
+static bool
+batch_in_cache(struct fd_batch_cache *cache, struct fd_batch *batch)
+{
+       struct fd_batch *b;
+
+       foreach_batch (b, cache, cache->batch_mask)
+               if (b == batch)
+                       return true;
+
+       return false;
+}
+
+void
+fd_bc_dump(struct fd_screen *screen, const char *fmt, ...)
+{
+       struct fd_batch_cache *cache = &screen->batch_cache;
+
+       if (!BATCH_DEBUG)
+               return;
+
+       fd_screen_lock(screen);
+
+       va_list ap;
+       va_start(ap, fmt);
+       vprintf(fmt, ap);
+       va_end(ap);
+
+       set_foreach (screen->live_batches, entry) {
+               struct fd_batch *batch = (struct fd_batch *)entry->key;
+               printf("  %p<%u>%s%s\n", batch, batch->seqno,
+                               batch->needs_flush ? ", NEEDS FLUSH" : "",
+                               batch_in_cache(cache, batch) ? "" : ", ORPHAN");
+       }
+
+       printf("----\n");
+
+       fd_screen_unlock(screen);
+}
+
 void
 fd_bc_invalidate_context(struct fd_context *ctx)
 {
index 0f2c40ba8d818806bfecbc5de9d4d331bac251d7..59e9d44253e347d0baad164af3ef6cf1a4124bb1 100644 (file)
@@ -32,6 +32,7 @@
 struct fd_resource;
 struct fd_batch;
 struct fd_context;
+struct fd_screen;
 
 struct hash_table;
 
@@ -64,6 +65,7 @@ void fd_bc_fini(struct fd_batch_cache *cache);
 
 void fd_bc_flush(struct fd_batch_cache *cache, struct fd_context *ctx);
 void fd_bc_flush_deferred(struct fd_batch_cache *cache, struct fd_context *ctx);
+void fd_bc_dump(struct fd_screen *screen, const char *fmt, ...)  _util_printf_format(2, 3);
 
 void fd_bc_invalidate_context(struct fd_context *ctx);
 void fd_bc_invalidate_batch(struct fd_batch *batch, bool destroy);
index c45a1583eac3c2d9f0436c6de311f4f675f40caf..4572147c4e72e4471f596436f5044471f8fb2dd1 100644 (file)
@@ -59,7 +59,6 @@ fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fencep,
        /* In some sequence of events, we can end up with a last_fence that is
         * not an "fd" fence, which results in eglDupNativeFenceFDANDROID()
         * errors.
-        *
         */
        if (flags & PIPE_FLUSH_FENCE_FD)
                fd_fence_ref(&ctx->last_fence, NULL);
@@ -69,11 +68,14 @@ fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fencep,
         */
        if (ctx->last_fence) {
                fd_fence_ref(&fence, ctx->last_fence);
+               fd_bc_dump(ctx->screen, "%p: reuse last_fence, remaining:\n", ctx);
                goto out;
        }
 
-       if (!batch)
+       if (!batch) {
+               fd_bc_dump(ctx->screen, "%p: NULL batch, remaining:\n", ctx);
                return;
+       }
 
        /* Take a ref to the batch's fence (batch can be unref'd when flushed: */
        fd_fence_ref(&fence, batch->fence);
@@ -81,6 +83,9 @@ fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fencep,
        if (flags & PIPE_FLUSH_FENCE_FD)
                batch->needs_out_fence_fd = true;
 
+       fd_bc_dump(ctx->screen, "%p: flushing %p<%u>, flags=0x%x, pending:\n",
+                       ctx, batch, batch->seqno, flags);
+
        if (!ctx->screen->reorder) {
                fd_batch_flush(batch);
        } else if (flags & PIPE_FLUSH_DEFERRED) {
@@ -89,6 +94,8 @@ fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fencep,
                fd_bc_flush(&ctx->screen->batch_cache, ctx);
        }
 
+       fd_bc_dump(ctx->screen, "%p: remaining:\n", ctx);
+
 out:
        if (fencep)
                fd_fence_ref(fencep, fence);
index e1c5b81cb32811de8d3730545deba39880190a45..0d8584c2d2e482498d262b2774498217fc479b9f 100644 (file)
@@ -160,6 +160,7 @@ fd_screen_destroy(struct pipe_screen *pscreen)
        simple_mtx_destroy(&screen->lock);
 
        ralloc_free(screen->compiler);
+       ralloc_free(screen->live_batches);
 
        free(screen->perfcntr_queries);
        free(screen);
@@ -972,6 +973,9 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro)
        if (fd_device_version(dev) >= FD_VERSION_UNLIMITED_CMDS)
                screen->reorder = !(fd_mesa_debug & FD_DBG_INORDER);
 
+       if (BATCH_DEBUG)
+               screen->live_batches = _mesa_pointer_set_create(NULL);
+
        fd_bc_init(&screen->batch_cache);
 
        list_inithead(&screen->context_list);
index 0337866fd9b81d05b738bb454ef689073188d6a0..c2a13f51f8c3e338e9b84b22350526886e4e2266 100644 (file)
@@ -119,6 +119,11 @@ struct fd_screen {
        const uint64_t *supported_modifiers;
 
        struct renderonly *ro;
+
+       /* when BATCH_DEBUG is enabled, tracking for fd_batch's which are not yet
+        * freed:
+        */
+       struct set *live_batches;
 };
 
 static inline struct fd_screen *