diff --git a/.pick_status.json b/.pick_status.json index e09364274cf..c440906a0d5 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -796,7 +796,7 @@ "description": "zink: add more locking for pipeline cache", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null }, diff --git a/src/gallium/drivers/zink/zink_pipeline.c b/src/gallium/drivers/zink/zink_pipeline.c index f49b902e920..b6ee4bb41b4 100644 --- a/src/gallium/drivers/zink/zink_pipeline.c +++ b/src/gallium/drivers/zink/zink_pipeline.c @@ -392,8 +392,10 @@ zink_create_gfx_pipeline(struct zink_screen *screen, pci.stageCount = num_stages; VkPipeline pipeline; + u_rwlock_wrlock(&prog->base.pipeline_cache_lock); VkResult result = VKSCR(CreateGraphicsPipelines)(screen->dev, prog->base.pipeline_cache, 1, &pci, NULL, &pipeline); + u_rwlock_wrunlock(&prog->base.pipeline_cache_lock); if (result != VK_SUCCESS) { mesa_loge("ZINK: vkCreateGraphicsPipelines failed (%s)", vk_Result_to_str(result)); return VK_NULL_HANDLE; @@ -436,8 +438,10 @@ zink_create_compute_pipeline(struct zink_screen *screen, struct zink_compute_pro pci.stage = stage; VkPipeline pipeline; + u_rwlock_wrlock(&comp->base.pipeline_cache_lock); VkResult result = VKSCR(CreateComputePipelines)(screen->dev, comp->base.pipeline_cache, 1, &pci, NULL, &pipeline); + u_rwlock_wrunlock(&comp->base.pipeline_cache_lock); if (result != VK_SUCCESS) { mesa_loge("ZINK: vkCreateComputePipelines failed (%s)", vk_Result_to_str(result)); return VK_NULL_HANDLE; @@ -773,7 +777,10 @@ create_gfx_pipeline_library(struct zink_screen *screen, VkShaderModule *modules, VkPipeline zink_create_gfx_pipeline_library(struct zink_screen *screen, struct zink_gfx_program *prog) { - return create_gfx_pipeline_library(screen, prog->modules, prog->base.layout, prog->base.pipeline_cache); + u_rwlock_wrlock(&prog->base.pipeline_cache_lock); + VkPipeline pipeline = create_gfx_pipeline_library(screen, prog->modules, prog->base.layout, prog->base.pipeline_cache); + u_rwlock_wrunlock(&prog->base.pipeline_cache_lock); + return pipeline; } VkPipeline @@ -811,11 +818,14 @@ zink_create_gfx_pipeline_combined(struct zink_screen *screen, struct zink_gfx_pr pci.flags |= VK_PIPELINE_CREATE_LIBRARY_BIT_KHR; VkPipeline pipeline; + u_rwlock_wrlock(&prog->base.pipeline_cache_lock); if (VKSCR(CreateGraphicsPipelines)(screen->dev, prog->base.pipeline_cache, 1, &pci, NULL, &pipeline) != VK_SUCCESS) { mesa_loge("ZINK: vkCreateGraphicsPipelines failed"); + u_rwlock_wrunlock(&prog->base.pipeline_cache_lock); return VK_NULL_HANDLE; } + u_rwlock_wrunlock(&prog->base.pipeline_cache_lock); return pipeline; } diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c index 815c5371414..14a04a305d8 100644 --- a/src/gallium/drivers/zink/zink_program.c +++ b/src/gallium/drivers/zink/zink_program.c @@ -920,6 +920,7 @@ create_program(struct zink_context *ctx, bool is_compute) return NULL; pipe_reference_init(&pg->reference, 1); + u_rwlock_init(&pg->pipeline_cache_lock); util_queue_fence_init(&pg->cache_fence); pg->is_compute = is_compute; pg->ctx = ctx; @@ -1422,6 +1423,7 @@ deinit_program(struct zink_screen *screen, struct zink_program *pg) if (pg->pipeline_cache) VKSCR(DestroyPipelineCache)(screen->dev, pg->pipeline_cache, NULL); + u_rwlock_destroy(&pg->pipeline_cache_lock); zink_descriptor_program_deinit(screen, pg); } diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index 8328138f46e..3009b53f02f 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -313,17 +313,24 @@ cache_put_job(void *data, void *gdata, int thread_index) struct zink_program *pg = data; struct zink_screen *screen = gdata; size_t size = 0; + u_rwlock_rdlock(&pg->pipeline_cache_lock); VkResult result = VKSCR(GetPipelineCacheData)(screen->dev, pg->pipeline_cache, &size, NULL); if (result != VK_SUCCESS) { + u_rwlock_rdunlock(&pg->pipeline_cache_lock); mesa_loge("ZINK: vkGetPipelineCacheData failed (%s)", vk_Result_to_str(result)); return; } - if (pg->pipeline_cache_size == size) + if (pg->pipeline_cache_size == size) { + u_rwlock_rdunlock(&pg->pipeline_cache_lock); return; + } void *pipeline_data = malloc(size); - if (!pipeline_data) + if (!pipeline_data) { + u_rwlock_rdunlock(&pg->pipeline_cache_lock); return; + } result = VKSCR(GetPipelineCacheData)(screen->dev, pg->pipeline_cache, &size, pipeline_data); + u_rwlock_rdunlock(&pg->pipeline_cache_lock); if (result == VK_SUCCESS) { pg->pipeline_cache_size = size; diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h index 490fd45c245..1049f8e0e78 100644 --- a/src/gallium/drivers/zink/zink_types.h +++ b/src/gallium/drivers/zink/zink_types.h @@ -42,6 +42,7 @@ #include "util/hash_table.h" #include "util/list.h" #include "util/log.h" +#include "util/rwlock.h" #include "util/set.h" #include "util/simple_mtx.h" #include "util/slab.h" @@ -939,6 +940,7 @@ struct zink_program { struct zink_context *ctx; unsigned char sha1[20]; struct util_queue_fence cache_fence; + struct u_rwlock pipeline_cache_lock; VkPipelineCache pipeline_cache; size_t pipeline_cache_size; struct zink_batch_usage *batch_uses;