From 8cb51ba30e0078111ccaf15f9c76bab443072228 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 13 Mar 2021 09:02:49 -0800 Subject: [PATCH] freedreno: Add dirty bit for state that needs rsc tracking aa1ddb6fe3c364c4f10df29bb42a0cf09d4cdabe skipped the tracking for the !dirty case, but we can do a bit better and track at bind time whether the state change is one that requires resource tracking. Signed-off-by: Rob Clark Part-of: --- .../drivers/freedreno/freedreno_context.h | 34 ++++++++++++++++++- .../drivers/freedreno/freedreno_draw.c | 2 +- .../drivers/freedreno/freedreno_resource.c | 2 +- .../drivers/freedreno/freedreno_state.c | 5 +++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index 6d667ae913d..1650b8f6c7d 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -159,6 +159,9 @@ enum fd_dirty_3d_state { FD_DIRTY_RASTERIZER_DISCARD = BIT(24), FD_DIRTY_BLEND_DUAL = BIT(25), #define NUM_DIRTY_BITS 26 + + /* additional flag for state requires updated resource tracking: */ + FD_DIRTY_RESOURCE = BIT(31), }; /* per shader-stage dirty state: */ @@ -506,6 +509,31 @@ fd_stream_output_target(struct pipe_stream_output_target *target) return (struct fd_stream_output_target *)target; } +/** + * Does the dirty state require resource tracking, ie. in general + * does it reference some resource. There are some special cases: + * + * - FD_DIRTY_CONST can reference a resource, but cb0 is handled + * specially as if it is not a user-buffer, we expect it to be + * coming from const_uploader, so we can make some assumptions + * that future transfer_map will be UNSYNCRONIZED + * - FD_DIRTY_ZSA controls how the framebuffer is accessed + * - FD_DIRTY_BLEND needs to update GMEM reason + * + * TODO if we can make assumptions that framebuffer state is bound + * first, before blend/zsa/etc state we can move some of the ZSA/ + * BLEND state handling from draw time to bind time. I think this + * is true of mesa/st, perhaps we can just document it to be a + * frontend requirement? + */ +static inline bool +fd_context_dirty_resource(enum fd_dirty_3d_state dirty) +{ + return dirty & (FD_DIRTY_FRAMEBUFFER | FD_DIRTY_ZSA | + FD_DIRTY_BLEND | FD_DIRTY_SSBO | FD_DIRTY_IMAGE | + FD_DIRTY_VTXBUF | FD_DIRTY_TEX | FD_DIRTY_STREAMOUT); +} + /* Mark specified non-shader-stage related state as dirty: */ static inline void fd_context_dirty(struct fd_context *ctx, enum fd_dirty_3d_state dirty) @@ -514,8 +542,12 @@ fd_context_dirty(struct fd_context *ctx, enum fd_dirty_3d_state dirty) assert(util_is_power_of_two_nonzero(dirty)); STATIC_ASSERT(ffs(dirty) <= ARRAY_SIZE(ctx->gen_dirty_map)); - ctx->dirty |= dirty; ctx->gen_dirty |= ctx->gen_dirty_map[ffs(dirty) - 1]; + + if (fd_context_dirty_resource(dirty)) + dirty |= FD_DIRTY_RESOURCE; + + ctx->dirty |= dirty; } static inline void diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c index 98488e472b8..d0ccfa6c1eb 100644 --- a/src/gallium/drivers/freedreno/freedreno_draw.c +++ b/src/gallium/drivers/freedreno/freedreno_draw.c @@ -209,7 +209,7 @@ batch_draw_tracking(struct fd_batch *batch, const struct pipe_draw_info *info, fd_screen_lock(ctx->screen); - if (ctx->dirty) + if (ctx->dirty & FD_DIRTY_RESOURCE) batch_draw_tracking_for_dirty_bits(batch); /* Mark index buffer as being read */ diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index b6265f84d76..28c7fb273eb 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -99,7 +99,7 @@ rebind_resource_in_ctx(struct fd_context *ctx, struct fd_resource *rsc) !(ctx->dirty_shader[stage] & FD_DIRTY_CONST)) { struct fd_constbuf_stateobj *cb = &ctx->constbuf[stage]; const unsigned num_ubos = util_last_bit(cb->enabled_mask); - for (unsigned i = 0; i < num_ubos; i++) { + for (unsigned i = 1; i < num_ubos; i++) { if (cb->cb[i].buffer == prsc) { fd_context_dirty_shader(ctx, stage, FD_DIRTY_SHADER_CONST); break; diff --git a/src/gallium/drivers/freedreno/freedreno_state.c b/src/gallium/drivers/freedreno/freedreno_state.c index a865994d4e5..8ca5a1c43a0 100644 --- a/src/gallium/drivers/freedreno/freedreno_state.c +++ b/src/gallium/drivers/freedreno/freedreno_state.c @@ -123,6 +123,11 @@ fd_set_constant_buffer(struct pipe_context *pctx, fd_context_dirty_shader(ctx, shader, FD_DIRTY_SHADER_CONST); fd_resource_set_usage(cb->buffer, FD_DIRTY_CONST); + + if (index > 0) { + assert(!cb->user_buffer); + ctx->dirty |= FD_DIRTY_RESOURCE; + } } static void