From d9e56d8a695304a0f2fb109cea6fc46991f98007 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 24 Apr 2020 15:00:20 -0700 Subject: [PATCH] freedreno: rebind resource in all contexts If the resource is rebound, we need to invalidate in all contexts. Signed-off-by: Rob Clark Part-of: --- .../drivers/freedreno/freedreno_context.c | 8 ++++++ .../drivers/freedreno/freedreno_context.h | 2 ++ .../drivers/freedreno/freedreno_resource.c | 28 +++++++++---------- .../drivers/freedreno/freedreno_screen.c | 2 ++ .../drivers/freedreno/freedreno_screen.h | 2 ++ 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c index 4969172e449..529b58e8b54 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.c +++ b/src/gallium/drivers/freedreno/freedreno_context.c @@ -178,6 +178,10 @@ fd_context_destroy(struct pipe_context *pctx) DBG(""); + mtx_lock(&ctx->screen->lock); + list_del(&ctx->node); + mtx_unlock(&ctx->screen->lock); + fd_log_process(ctx, true); assert(list_is_empty(&ctx->log_chunks)); @@ -419,6 +423,10 @@ fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen, list_inithead(&ctx->acc_active_queries); list_inithead(&ctx->log_chunks); + mtx_lock(&ctx->screen->lock); + list_add(&ctx->node, &ctx->screen->context_list); + mtx_unlock(&ctx->screen->lock); + ctx->log_out = stdout; if ((fd_mesa_debug & FD_DBG_LOG) && diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index faaade508fa..57a172eede8 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -162,6 +162,8 @@ enum fd_dirty_shader_state { struct fd_context { struct pipe_context base; + struct list_head node; /* node in screen->context_list */ + /* We currently need to serialize emitting GMEM batches, because of * VSC state access in the context. * diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 0f846c7b255..a4933acdf3b 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -146,11 +146,19 @@ rebind_resource_in_ctx(struct fd_context *ctx, struct fd_resource *rsc) } static void -rebind_resource(struct fd_context *ctx, struct fd_resource *rsc) +rebind_resource(struct fd_resource *rsc) { + struct fd_screen *screen = fd_screen(rsc->base.screen); + + mtx_lock(&screen->lock); fd_resource_lock(rsc); - rebind_resource_in_ctx(ctx, rsc); + + if (rsc->dirty) + list_for_each_entry (struct fd_context, ctx, &screen->context_list, node) + rebind_resource_in_ctx(ctx, rsc); + fd_resource_unlock(rsc); + mtx_unlock(&screen->lock); } static void @@ -379,17 +387,7 @@ fd_resource_uncompress(struct fd_context *ctx, struct fd_resource *rsc) /* shadow should not fail in any cases where we need to uncompress: */ debug_assert(success); - /* - * TODO what if rsc is used in other contexts, we don't currently - * have a good way to rebind_resource() in other contexts. And an - * app that is reading one resource in multiple contexts, isn't - * going to expect that the resource is modified. - * - * Hopefully the edge cases where we need to uncompress are rare - * enough that they mostly only show up in deqp. - */ - - rebind_resource(ctx, rsc); + rebind_resource(rsc); } static struct fd_resource * @@ -638,7 +636,7 @@ fd_resource_transfer_map(struct pipe_context *pctx, if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { if (needs_flush || fd_resource_busy(rsc, op)) { realloc_bo(rsc, fd_bo_size(rsc->bo)); - rebind_resource(ctx, rsc); + rebind_resource(rsc); } } else if ((usage & PIPE_TRANSFER_WRITE) && prsc->target == PIPE_BUFFER && @@ -681,7 +679,7 @@ fd_resource_transfer_map(struct pipe_context *pctx, if (needs_flush && fd_try_shadow_resource(ctx, rsc, level, box, DRM_FORMAT_MOD_LINEAR)) { needs_flush = busy = false; - rebind_resource(ctx, rsc); + rebind_resource(rsc); ctx->stats.shadow_uploads++; } else { struct fd_resource *staging_rsc; diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 0838412138f..143b601f3b7 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -961,6 +961,8 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro) fd_bc_init(&screen->batch_cache); + list_inithead(&screen->context_list); + (void) mtx_init(&screen->lock, mtx_plain); pscreen->destroy = fd_screen_destroy; diff --git a/src/gallium/drivers/freedreno/freedreno_screen.h b/src/gallium/drivers/freedreno/freedreno_screen.h index 534d0a2f859..c46d1c8793d 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.h +++ b/src/gallium/drivers/freedreno/freedreno_screen.h @@ -46,6 +46,8 @@ struct fd_bo; struct fd_screen { struct pipe_screen base; + struct list_head context_list; + mtx_t lock; /* it would be tempting to use pipe_reference here, but that -- 2.30.2