freedreno/a6xx: Texture cache locking

Originally the tex cache was never touched from other contexts, but
rebind_resource() changed that.  Add some locking to protect tex cache
against multi-threaded access.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7342>
This commit is contained in:
Rob Clark 2020-10-23 14:56:09 -07:00 committed by Marge Bot
parent 51665dee8c
commit 1783a156c8
3 changed files with 68 additions and 15 deletions

View File

@ -519,6 +519,8 @@ fd6_emit_combined_textures(struct fd_ringbuffer *ring, struct fd6_emit *emit,
fd6_emit_add_group(emit, tex->stateobj, s[type].state_id,
s[type].enable_mask);
fd6_texture_state_reference(&tex, NULL);
}
} else {
/* In the slow-path, create a one-shot texture state object

View File

@ -37,7 +37,13 @@
#include "fd6_format.h"
#include "fd6_emit.h"
static void fd6_texture_state_destroy(struct fd6_texture_state *state);
static void
remove_tex_entry(struct fd6_context *fd6_ctx, struct hash_entry *entry)
{
struct fd6_texture_state *tex = entry->data;
_mesa_hash_table_remove(fd6_ctx->tex_cache, entry);
fd6_texture_state_reference(&tex, NULL);
}
static enum a6xx_tex_clamp
tex_clamp(unsigned wrap, bool clamp_to_edge, bool *needs_border)
@ -149,21 +155,25 @@ fd6_sampler_state_create(struct pipe_context *pctx,
static void
fd6_sampler_state_delete(struct pipe_context *pctx, void *hwcso)
{
struct fd6_context *fd6_ctx = fd6_context(fd_context(pctx));
struct fd_context *ctx = fd_context(pctx);
struct fd6_context *fd6_ctx = fd6_context(ctx);
struct fd6_sampler_stateobj *samp = hwcso;
fd_screen_lock(ctx->screen);
hash_table_foreach(fd6_ctx->tex_cache, entry) {
struct fd6_texture_state *state = entry->data;
for (unsigned i = 0; i < ARRAY_SIZE(state->key.samp); i++) {
if (samp->seqno == state->key.samp[i].seqno) {
fd6_texture_state_destroy(entry->data);
_mesa_hash_table_remove(fd6_ctx->tex_cache, entry);
remove_tex_entry(fd6_ctx, entry);
break;
}
}
}
fd_screen_unlock(ctx->screen);
free(hwcso);
}
@ -364,21 +374,25 @@ static void
fd6_sampler_view_destroy(struct pipe_context *pctx,
struct pipe_sampler_view *_view)
{
struct fd6_context *fd6_ctx = fd6_context(fd_context(pctx));
struct fd_context *ctx = fd_context(pctx);
struct fd6_context *fd6_ctx = fd6_context(ctx);
struct fd6_pipe_sampler_view *view = fd6_pipe_sampler_view(_view);
fd_screen_lock(ctx->screen);
hash_table_foreach(fd6_ctx->tex_cache, entry) {
struct fd6_texture_state *state = entry->data;
for (unsigned i = 0; i < ARRAY_SIZE(state->key.view); i++) {
if (view->seqno == state->key.view[i].seqno) {
fd6_texture_state_destroy(entry->data);
_mesa_hash_table_remove(fd6_ctx->tex_cache, entry);
remove_tex_entry(fd6_ctx, entry);
break;
}
}
}
fd_screen_unlock(ctx->screen);
pipe_resource_reference(&view->base.texture, NULL);
free(view);
@ -405,6 +419,7 @@ fd6_texture_state(struct fd_context *ctx, enum pipe_shader_type type,
struct fd_texture_stateobj *tex)
{
struct fd6_context *fd6_ctx = fd6_context(ctx);
struct fd6_texture_state *state = NULL;
struct fd6_texture_key key;
bool needs_border = false;
@ -437,15 +452,19 @@ fd6_texture_state(struct fd_context *ctx, enum pipe_shader_type type,
key.bcolor_offset = fd6_border_color_offset(ctx, type, tex);
uint32_t hash = key_hash(&key);
fd_screen_lock(ctx->screen);
struct hash_entry *entry =
_mesa_hash_table_search_pre_hashed(fd6_ctx->tex_cache, hash, &key);
if (entry) {
return entry->data;
fd6_texture_state_reference(&state, entry->data);
goto out_unlock;
}
struct fd6_texture_state *state = CALLOC_STRUCT(fd6_texture_state);
state = CALLOC_STRUCT(fd6_texture_state);
/* NOTE: one ref for tex_cache, and second ref for returned state: */
pipe_reference_init(&state->reference, 2);
state->key = key;
state->stateobj = fd_ringbuffer_new_object(ctx->pipe, 0x1000);
state->needs_border = needs_border;
@ -459,11 +478,19 @@ fd6_texture_state(struct fd_context *ctx, enum pipe_shader_type type,
_mesa_hash_table_insert_pre_hashed(fd6_ctx->tex_cache, hash,
&state->key, state);
out_unlock:
fd_screen_unlock(ctx->screen);
return state;
}
static void
fd6_texture_state_destroy(struct fd6_texture_state *state)
void
__fd6_texture_state_describe(char* buf, const struct fd6_texture_state *tex)
{
sprintf(buf, "fd6_texture_state<%p>", tex);
}
void
__fd6_texture_state_destroy(struct fd6_texture_state *state)
{
fd_ringbuffer_del(state->stateobj);
free(state);
@ -472,6 +499,8 @@ fd6_texture_state_destroy(struct fd6_texture_state *state)
static void
fd6_rebind_resource(struct fd_context *ctx, struct fd_resource *rsc)
{
fd_screen_assert_locked(ctx->screen);
if (!(rsc->dirty & FD_DIRTY_TEX))
return;
@ -482,8 +511,7 @@ fd6_rebind_resource(struct fd_context *ctx, struct fd_resource *rsc)
for (unsigned i = 0; i < ARRAY_SIZE(state->key.view); i++) {
if (rsc->seqno == state->key.view[i].rsc_seqno) {
fd6_texture_state_destroy(entry->data);
_mesa_hash_table_remove(fd6_ctx->tex_cache, entry);
remove_tex_entry(fd6_ctx, entry);
}
}
}
@ -511,10 +539,16 @@ fd6_texture_init(struct pipe_context *pctx)
void
fd6_texture_fini(struct pipe_context *pctx)
{
struct fd6_context *fd6_ctx = fd6_context(fd_context(pctx));
struct fd_context *ctx = fd_context(pctx);
struct fd6_context *fd6_ctx = fd6_context(ctx);
fd_screen_lock(ctx->screen);
hash_table_foreach(fd6_ctx->tex_cache, entry) {
fd6_texture_state_destroy(entry->data);
remove_tex_entry(fd6_ctx, entry);
}
fd_screen_unlock(ctx->screen);
ralloc_free(fd6_ctx->tex_cache);
}

View File

@ -147,6 +147,7 @@ struct fd6_texture_key {
};
struct fd6_texture_state {
struct pipe_reference reference;
struct fd6_texture_key key;
struct fd_ringbuffer *stateobj;
bool needs_border;
@ -155,4 +156,20 @@ struct fd6_texture_state {
struct fd6_texture_state * fd6_texture_state(struct fd_context *ctx,
enum pipe_shader_type type, struct fd_texture_stateobj *tex);
/* not called directly: */
void __fd6_texture_state_describe(char* buf, const struct fd6_texture_state *tex);
void __fd6_texture_state_destroy(struct fd6_texture_state *tex);
static inline void
fd6_texture_state_reference(struct fd6_texture_state **ptr, struct fd6_texture_state *tex)
{
struct fd6_texture_state *old_tex = *ptr;
if (pipe_reference_described(&(*ptr)->reference, &tex->reference,
(debug_reference_descriptor)__fd6_texture_state_describe))
__fd6_texture_state_destroy(old_tex);
*ptr = tex;
}
#endif /* FD6_TEXTURE_H_ */