diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_context.h b/src/gallium/drivers/freedreno/a6xx/fd6_context.h index 3bfccc800f8..cb264ca1c0c 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_context.h +++ b/src/gallium/drivers/freedreno/a6xx/fd6_context.h @@ -121,6 +121,7 @@ struct fd6_context { uint16_t tex_seqno; struct hash_table *tex_cache; + bool tex_cache_needs_invalidate; /** * Descriptor sets for 3d shader stages diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_texture.c b/src/gallium/drivers/freedreno/a6xx/fd6_texture.c index dd5cbf55a17..8c132bda095 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_texture.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_texture.c @@ -661,6 +661,31 @@ build_texture_state(struct fd_context *ctx, struct fd_ringbuffer *ring, OUT_RING(ring, num_textures); } +/** + * Handle invalidates potentially coming from other contexts. By + * flagging the invalidate rather than handling it immediately, we + * avoid needing to refcnt (with it's associated atomics) the tex + * state. And furthermore, this avoids cross-ctx (thread) sharing + * of fd_ringbuffer's, avoiding their need for atomic refcnts. + */ +static void +handle_invalidates(struct fd_context *ctx) + assert_dt +{ + struct fd6_context *fd6_ctx = fd6_context(ctx); + + fd_screen_assert_locked(ctx->screen); + + hash_table_foreach (fd6_ctx->tex_cache, entry) { + struct fd6_texture_state *state = entry->data; + + if (state->invalidate) + remove_tex_entry(fd6_ctx, entry); + } + + fd6_ctx->tex_cache_needs_invalidate = false; +} + struct fd6_texture_state * fd6_texture_state(struct fd_context *ctx, enum pipe_shader_type type, struct fd_texture_stateobj *tex) @@ -701,6 +726,10 @@ fd6_texture_state(struct fd_context *ctx, enum pipe_shader_type type, uint32_t hash = tex_key_hash(&key); fd_screen_lock(ctx->screen); + + if (unlikely(fd6_ctx->tex_cache_needs_invalidate)) + handle_invalidates(ctx); + struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(fd6_ctx->tex_cache, hash, &key); @@ -757,8 +786,9 @@ fd6_rebind_resource(struct fd_context *ctx, struct fd_resource *rsc) assert_dt for (unsigned i = 0; i < ARRAY_SIZE(state->key.view); i++) { if (rsc->seqno == state->key.view[i].rsc_seqno) { - remove_tex_entry(fd6_ctx, entry); - break; + struct fd6_texture_state *tex = entry->data; + tex->invalidate = true; + fd6_ctx->tex_cache_needs_invalidate = true; } } } diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_texture.h b/src/gallium/drivers/freedreno/a6xx/fd6_texture.h index 095fe9b1721..17d81da67d9 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_texture.h +++ b/src/gallium/drivers/freedreno/a6xx/fd6_texture.h @@ -131,6 +131,7 @@ struct fd6_texture_state { struct pipe_reference reference; struct fd6_texture_key key; struct fd_ringbuffer *stateobj; + bool invalidate; }; struct fd6_texture_state *