zink: add more locking for compute pipelines

if multiple contexts are accessing this all at once then this needs
more locking to avoid unsynchronized cache access

cc: mesa-stable

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25929>
(cherry picked from commit f8909e7d55)
This commit is contained in:
Mike Blumenkrantz 2023-10-26 16:22:27 -04:00 committed by Eric Engestrom
parent 423202cae4
commit e8e6ad5692
3 changed files with 21 additions and 5 deletions

View file

@ -654,7 +654,7 @@
"description": "zink: add more locking for compute pipelines",
"nominated": true,
"nomination_type": 0,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": null,
"notes": null

View file

@ -1367,6 +1367,7 @@ create_compute_program(struct zink_context *ctx, nir_shader *nir)
struct zink_compute_program *comp = create_program(ctx, true);
if (!comp)
return NULL;
simple_mtx_init(&comp->cache_lock, mtx_plain);
comp->scratch_size = nir->scratch_size;
comp->nir = nir;
comp->num_inlinable_uniforms = nir->info.num_inlinable_uniforms;
@ -1595,6 +1596,7 @@ zink_get_compute_pipeline(struct zink_screen *screen,
struct zink_compute_pipeline_state *state)
{
struct hash_entry *entry = NULL;
struct compute_pipeline_cache_entry *cache_entry;
if (!state->dirty && !state->module_changed)
return state->pipeline;
@ -1617,30 +1619,42 @@ zink_get_compute_pipeline(struct zink_screen *screen,
entry = _mesa_hash_table_search_pre_hashed(&comp->pipelines, state->final_hash, state);
if (!entry) {
simple_mtx_lock(&comp->cache_lock);
entry = _mesa_hash_table_search_pre_hashed(&comp->pipelines, state->final_hash, state);
if (entry) {
simple_mtx_unlock(&comp->cache_lock);
goto out;
}
VkPipeline pipeline = zink_create_compute_pipeline(screen, comp, state);
if (pipeline == VK_NULL_HANDLE)
if (pipeline == VK_NULL_HANDLE) {
simple_mtx_unlock(&comp->cache_lock);
return VK_NULL_HANDLE;
}
zink_screen_update_pipeline_cache(screen, &comp->base, false);
if (compute_can_shortcut(comp)) {
simple_mtx_unlock(&comp->cache_lock);
/* don't add base pipeline to cache */
state->pipeline = comp->base_pipeline = pipeline;
return state->pipeline;
}
struct compute_pipeline_cache_entry *pc_entry = CALLOC_STRUCT(compute_pipeline_cache_entry);
if (!pc_entry)
if (!pc_entry) {
simple_mtx_unlock(&comp->cache_lock);
return VK_NULL_HANDLE;
}
memcpy(&pc_entry->state, state, sizeof(*state));
pc_entry->pipeline = pipeline;
entry = _mesa_hash_table_insert_pre_hashed(&comp->pipelines, state->final_hash, pc_entry, pc_entry);
assert(entry);
simple_mtx_unlock(&comp->cache_lock);
}
struct compute_pipeline_cache_entry *cache_entry = entry->data;
out:
cache_entry = entry->data;
state->pipeline = cache_entry->pipeline;
return state->pipeline;
}

View file

@ -1148,6 +1148,8 @@ struct zink_compute_program {
struct zink_shader *shader;
struct hash_table pipelines;
simple_mtx_t cache_lock; //extra lock because threads are insane and sand was not meant to think
VkPipeline base_pipeline;
};