From 4c97a716a64a0d4990a2cc2f8185713459576ca4 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 23 May 2020 11:00:40 -0700 Subject: [PATCH] freedreno: add batch debugging 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 Part-of: --- .../drivers/freedreno/freedreno_batch.c | 9 +++++ .../drivers/freedreno/freedreno_batch.h | 6 +++ .../drivers/freedreno/freedreno_batch_cache.c | 39 +++++++++++++++++++ .../drivers/freedreno/freedreno_batch_cache.h | 2 + .../drivers/freedreno/freedreno_context.c | 11 +++++- .../drivers/freedreno/freedreno_screen.c | 4 ++ .../drivers/freedreno/freedreno_screen.h | 5 +++ 7 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/freedreno/freedreno_batch.c b/src/gallium/drivers/freedreno/freedreno_batch.c index b31dd2c02c8..4ad10aeb35a 100644 --- a/src/gallium/drivers/freedreno/freedreno_batch.c +++ b/src/gallium/drivers/freedreno/freedreno_batch.c @@ -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); diff --git a/src/gallium/drivers/freedreno/freedreno_batch.h b/src/gallium/drivers/freedreno/freedreno_batch.h index e64d9061b6b..b7b970359a3 100644 --- a/src/gallium/drivers/freedreno/freedreno_batch.h +++ b/src/gallium/drivers/freedreno/freedreno_batch.h @@ -33,6 +33,12 @@ #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; diff --git a/src/gallium/drivers/freedreno/freedreno_batch_cache.c b/src/gallium/drivers/freedreno/freedreno_batch_cache.c index 329ed41fba3..448e701bbc6 100644 --- a/src/gallium/drivers/freedreno/freedreno_batch_cache.c +++ b/src/gallium/drivers/freedreno/freedreno_batch_cache.c @@ -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) { diff --git a/src/gallium/drivers/freedreno/freedreno_batch_cache.h b/src/gallium/drivers/freedreno/freedreno_batch_cache.h index 0f2c40ba8d8..59e9d44253e 100644 --- a/src/gallium/drivers/freedreno/freedreno_batch_cache.h +++ b/src/gallium/drivers/freedreno/freedreno_batch_cache.h @@ -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); diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c index c45a1583eac..4572147c4e7 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.c +++ b/src/gallium/drivers/freedreno/freedreno_context.c @@ -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); diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index e1c5b81cb32..0d8584c2d2e 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -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); diff --git a/src/gallium/drivers/freedreno/freedreno_screen.h b/src/gallium/drivers/freedreno/freedreno_screen.h index 0337866fd9b..c2a13f51f8c 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.h +++ b/src/gallium/drivers/freedreno/freedreno_screen.h @@ -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 * -- 2.30.2