From d01b6baf38897238bcf8d6b692a57c4291759537 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 30 Jul 2019 12:14:52 +0200 Subject: [PATCH] [dxvk] Introduce compilePipeline method to Dxvk*Pipeline classes Decouples the act of synchronously retrieving a handle from asynchronously compiling the pipeline. --- src/dxvk/dxvk_compute.cpp | 43 +++++++++++++++-------- src/dxvk/dxvk_compute.h | 19 ++++++++-- src/dxvk/dxvk_graphics.cpp | 65 +++++++++++++++++++++-------------- src/dxvk/dxvk_graphics.h | 20 +++++++++-- src/dxvk/dxvk_state_cache.cpp | 4 +-- 5 files changed, 105 insertions(+), 46 deletions(-) diff --git a/src/dxvk/dxvk_compute.cpp b/src/dxvk/dxvk_compute.cpp index 0baee54c..9ad2cf34 100644 --- a/src/dxvk/dxvk_compute.cpp +++ b/src/dxvk/dxvk_compute.cpp @@ -43,34 +43,49 @@ namespace dxvk { VkPipeline DxvkComputePipeline::getPipelineHandle( const DxvkComputePipelineStateInfo& state) { - VkPipeline newPipelineHandle = VK_NULL_HANDLE; + DxvkComputePipelineInstance* instance = nullptr; { std::lock_guard lock(m_mutex); - auto instance = this->findInstance(state); + instance = this->findInstance(state); if (instance) return instance->pipeline(); // If no pipeline instance exists with the given state // vector, create a new one and add it to the list. - newPipelineHandle = this->createPipeline(state); - - // Add new pipeline to the set - m_pipelines.emplace_back(state, newPipelineHandle); - m_pipeMgr->m_numComputePipelines += 1; + instance = this->createInstance(state); } - if (newPipelineHandle != VK_NULL_HANDLE) - this->writePipelineStateToCache(state); - - return newPipelineHandle; + if (!instance) + return VK_NULL_HANDLE; + + this->writePipelineStateToCache(state); + return instance->pipeline(); + } + + + void DxvkComputePipeline::compilePipeline( + const DxvkComputePipelineStateInfo& state) { + std::lock_guard lock(m_mutex); + + if (!this->findInstance(state)) + this->createInstance(state); } - const DxvkComputePipelineInstance* DxvkComputePipeline::findInstance( - const DxvkComputePipelineStateInfo& state) const { - for (const auto& instance : m_pipelines) { + DxvkComputePipelineInstance* DxvkComputePipeline::createInstance( + const DxvkComputePipelineStateInfo& state) { + VkPipeline newPipelineHandle = this->createPipeline(state); + + m_pipeMgr->m_numComputePipelines += 1; + return &m_pipelines.emplace_back(state, newPipelineHandle); + } + + + DxvkComputePipelineInstance* DxvkComputePipeline::findInstance( + const DxvkComputePipelineStateInfo& state) { + for (auto& instance : m_pipelines) { if (instance.isCompatible(state)) return &instance; } diff --git a/src/dxvk/dxvk_compute.h b/src/dxvk/dxvk_compute.h index 9cd7bd13..5f7f6d2f 100644 --- a/src/dxvk/dxvk_compute.h +++ b/src/dxvk/dxvk_compute.h @@ -109,7 +109,7 @@ namespace dxvk { } /** - * \brief Pipeline handle + * \brief Retrieves pipeline handle * * \param [in] state Pipeline state * \returns Pipeline handle @@ -117,6 +117,16 @@ namespace dxvk { VkPipeline getPipelineHandle( const DxvkComputePipelineStateInfo& state); + /** + * \brief Compiles a pipeline + * + * Asynchronously compiles the given pipeline + * and stores the result for future use. + * \param [in] state Pipeline state + */ + void compilePipeline( + const DxvkComputePipelineStateInfo& state); + private: Rc m_vkd; @@ -130,8 +140,11 @@ namespace dxvk { sync::Spinlock m_mutex; std::vector m_pipelines; - const DxvkComputePipelineInstance* findInstance( - const DxvkComputePipelineStateInfo& state) const; + DxvkComputePipelineInstance* createInstance( + const DxvkComputePipelineStateInfo& state); + + DxvkComputePipelineInstance* findInstance( + const DxvkComputePipelineStateInfo& state); VkPipeline createPipeline( const DxvkComputePipelineStateInfo& state) const; diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 4dbfbf61..9045fdba 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -97,43 +97,58 @@ namespace dxvk { VkPipeline DxvkGraphicsPipeline::getPipelineHandle( const DxvkGraphicsPipelineStateInfo& state, const DxvkRenderPass& renderPass) { - VkRenderPass renderPassHandle = renderPass.getDefaultHandle(); - - VkPipeline newPipelineHandle = VK_NULL_HANDLE; + DxvkGraphicsPipelineInstance* instance = nullptr; { std::lock_guard lock(m_mutex); - auto instance = this->findInstance(state, renderPassHandle); + instance = this->findInstance(state, renderPass); - if (instance != nullptr) + if (instance) return instance->pipeline(); - - // If the pipeline state vector is invalid, don't try - // to create a new pipeline, it won't work anyway. - if (!this->validatePipelineState(state)) - return VK_NULL_HANDLE; - // If no pipeline instance exists with the given state - // vector, create a new one and add it to the list. - newPipelineHandle = this->createPipeline(state, renderPass); - - // Add new pipeline to the set - m_pipelines.emplace_back(state, renderPassHandle, newPipelineHandle); - m_pipeMgr->m_numGraphicsPipelines += 1; + instance = this->createInstance(state, renderPass); } - if (newPipelineHandle != VK_NULL_HANDLE) - this->writePipelineStateToCache(state, renderPass.format()); - - return newPipelineHandle; + if (!instance) + return VK_NULL_HANDLE; + + this->writePipelineStateToCache(state, renderPass.format()); + return instance->pipeline(); + } + + + void DxvkGraphicsPipeline::compilePipeline( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass& renderPass) { + std::lock_guard lock(m_mutex); + + if (!this->findInstance(state, renderPass)) + this->createInstance(state, renderPass); + } + + + DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::createInstance( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass& renderPass) { + // If the pipeline state vector is invalid, don't try + // to create a new pipeline, it won't work anyway. + if (!this->validatePipelineState(state)) + return nullptr; + + VkPipeline newPipelineHandle = this->createPipeline(state, renderPass); + + m_pipeMgr->m_numGraphicsPipelines += 1; + return &m_pipelines.emplace_back(state, renderPass.getDefaultHandle(), newPipelineHandle); } - const DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::findInstance( + DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::findInstance( const DxvkGraphicsPipelineStateInfo& state, - VkRenderPass renderPass) const { - for (const auto& instance : m_pipelines) { - if (instance.isCompatible(state, renderPass)) + const DxvkRenderPass& renderPass) { + VkRenderPass renderPassHandle = renderPass.getDefaultHandle(); + + for (auto& instance : m_pipelines) { + if (instance.isCompatible(state, renderPassHandle)) return &instance; } diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index c696b1ce..7750f523 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -253,6 +253,18 @@ namespace dxvk { const DxvkGraphicsPipelineStateInfo& state, const DxvkRenderPass& renderPass); + /** + * \brief Compiles a pipeline + * + * Asynchronously compiles the given pipeline + * and stores the result for future use. + * \param [in] state Pipeline state vector + * \param [in] renderPass The render pass + */ + void compilePipeline( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass& renderPass); + private: Rc m_vkd; @@ -273,9 +285,13 @@ namespace dxvk { alignas(CACHE_LINE_SIZE) sync::Spinlock m_mutex; std::vector m_pipelines; - const DxvkGraphicsPipelineInstance* findInstance( + DxvkGraphicsPipelineInstance* createInstance( const DxvkGraphicsPipelineStateInfo& state, - VkRenderPass renderPass) const; + const DxvkRenderPass& renderPass); + + DxvkGraphicsPipelineInstance* findInstance( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass& renderPass); VkPipeline createPipeline( const DxvkGraphicsPipelineStateInfo& state, diff --git a/src/dxvk/dxvk_state_cache.cpp b/src/dxvk/dxvk_state_cache.cpp index 0b310062..36d1ef85 100644 --- a/src/dxvk/dxvk_state_cache.cpp +++ b/src/dxvk/dxvk_state_cache.cpp @@ -262,7 +262,7 @@ namespace dxvk { const auto& entry = m_entries[e->second]; auto rp = m_passManager->getRenderPass(entry.format); - pipeline->getPipelineHandle(entry.gpState, *rp); + pipeline->compilePipeline(entry.gpState, *rp); } } else { auto pipeline = m_pipeManager->createComputePipeline(item.cp); @@ -270,7 +270,7 @@ namespace dxvk { for (auto e = entries.first; e != entries.second; e++) { const auto& entry = m_entries[e->second]; - pipeline->getPipelineHandle(entry.cpState); + pipeline->compilePipeline(entry.cpState); } } }