From 7f9a04fd59627c0ce6c6b3c9887c22def834c10c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 6 Jul 2022 12:42:47 +0200 Subject: [PATCH] [dxvk] Don't keep pipeline locked when building optimized variant Only lock when creating base variant, otherwise we'll have stutter. --- src/dxvk/dxvk_graphics.cpp | 35 ++++++++++++++++++++++++++--------- src/dxvk/dxvk_graphics.h | 2 +- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 86a9de93..888498c3 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -566,22 +566,39 @@ namespace dxvk { void DxvkGraphicsPipeline::compilePipeline( const DxvkGraphicsPipelineStateInfo& state) { - // Exit early if the state vector is invalid - if (!this->validatePipelineState(state, false)) + if (m_device->config().enableGraphicsPipelineLibrary == Tristate::True) return; - // Keep the object locked while compiling a pipeline since compiling - // similar pipelines concurrently is fragile on some drivers - std::lock_guard lock(m_mutex); + // Try to find an existing instance that contains a base pipeline + DxvkGraphicsPipelineInstance* instance = this->findInstance(state); - if (!this->findInstance(state)) - this->createInstance(state); + if (!instance) { + // Exit early if the state vector is invalid + if (!this->validatePipelineState(state, false)) + return; + + // Prevent other threads from adding new instances and check again + std::lock_guard lock(m_mutex); + instance = this->findInstance(state); + + if (!instance) + instance = this->createInstance(state); + } + + // Exit if another thread is already compiling + // an optimized version of this pipeline + if (instance->isCompiling.load() + || instance->isCompiling.exchange(VK_TRUE, std::memory_order_acquire)) + return; + + VkPipeline pipeline = this->createOptimizedPipeline(state); + instance->fastHandle.store(pipeline, std::memory_order_release); } DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::createInstance( const DxvkGraphicsPipelineStateInfo& state) { - VkPipeline pipeline = this->createPipeline(state); + VkPipeline pipeline = this->createOptimizedPipeline(state); m_stats->numGraphicsPipelines += 1; return &(*m_pipelines.emplace(state, VK_NULL_HANDLE, pipeline)); @@ -599,7 +616,7 @@ namespace dxvk { } - VkPipeline DxvkGraphicsPipeline::createPipeline( + VkPipeline DxvkGraphicsPipeline::createOptimizedPipeline( const DxvkGraphicsPipelineStateInfo& state) const { auto vk = m_device->vkd(); diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index c4b25721..268e4ac8 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -388,7 +388,7 @@ namespace dxvk { DxvkGraphicsPipelineInstance* findInstance( const DxvkGraphicsPipelineStateInfo& state); - VkPipeline createPipeline( + VkPipeline createOptimizedPipeline( const DxvkGraphicsPipelineStateInfo& state) const; void destroyPipeline(