From 3b132196d353bcfa20b4d6338056af9c070b6d91 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 10 May 2018 14:15:47 +0200 Subject: [PATCH] [dxvk] Add ability to hold two pipeline handles to pipeline instances --- src/dxvk/dxvk_graphics.cpp | 32 ++++++++++++++++++------ src/dxvk/dxvk_graphics.h | 50 ++++++++++++++++++++++++++++---------- 2 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 8d7575261..5aa1519e0 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -37,16 +37,20 @@ namespace dxvk { DxvkGraphicsPipelineInstance::DxvkGraphicsPipelineInstance( const Rc& vkd, const DxvkGraphicsPipelineStateInfo& stateVector, - VkRenderPass renderPass) + VkRenderPass renderPass, + VkPipeline basePipeline) : m_vkd (vkd), m_stateVector (stateVector), - m_renderPass (renderPass) { + m_renderPass (renderPass), + m_basePipeline(basePipeline), + m_fastPipeline(VK_NULL_HANDLE) { } DxvkGraphicsPipelineInstance::~DxvkGraphicsPipelineInstance() { - m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipeline, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_basePipeline, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_fastPipeline, nullptr); } @@ -113,11 +117,12 @@ namespace dxvk { // If no pipeline instance exists with the given state // vector, create a new one and add it to the list. - Rc newPipeline = - new DxvkGraphicsPipelineInstance(m_device->vkd(), state, renderPassHandle); + VkPipeline newPipelineHandle = this->compilePipeline( + state, renderPassHandle, VK_NULL_HANDLE); - newPipeline->setPipeline(this->compilePipeline( - state, renderPassHandle, VK_NULL_HANDLE)); + Rc newPipeline = + new DxvkGraphicsPipelineInstance(m_device->vkd(), state, + renderPassHandle, newPipelineHandle); { std::lock_guard lock(m_mutex); @@ -138,6 +143,19 @@ namespace dxvk { } + void DxvkGraphicsPipeline::compilePipelineInstance( + const Rc& instance) { + // Compile an optimized version of the pipeline + VkPipeline newPipelineHandle = this->compilePipeline( + instance->m_stateVector, instance->m_renderPass, VK_NULL_HANDLE); + + // If an optimized version has been compiled + // in the meantime, discard the new pipeline + if (!instance->setFastPipeline(newPipelineHandle)) + m_vkd->vkDestroyPipeline(m_vkd->device(), newPipelineHandle, nullptr); + } + + DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::findInstance( const DxvkGraphicsPipelineStateInfo& state, VkRenderPass renderPass) const { diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index 0a02675eb..ec4a776ee 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -94,16 +94,17 @@ namespace dxvk { * \brief Graphics pipeline instance * * Stores a state vector and the corresponding - * pipeline handles. + * unoptimized and optimized pipeline handles. */ class DxvkGraphicsPipelineInstance : public RcObject { - + friend class DxvkGraphicsPipeline; public: DxvkGraphicsPipelineInstance( const Rc& vkd, const DxvkGraphicsPipelineStateInfo& stateVector, - VkRenderPass renderPass); + VkRenderPass renderPass, + VkPipeline basePipeline); ~DxvkGraphicsPipelineInstance(); @@ -122,19 +123,31 @@ namespace dxvk { } /** - * \brief Sets the pipeline handle - * \param [in] pipeline The pipeline + * \brief Sets the optimized pipeline handle + * + * If an optimized pipeline handle has already been + * set up, this method will fail and the new pipeline + * handle should be destroyed. + * \param [in] pipeline The optimized pipeline */ - void setPipeline(VkPipeline pipeline) { - m_pipeline = pipeline; + bool setFastPipeline(VkPipeline pipeline) { + VkPipeline expected = VK_NULL_HANDLE; + return m_fastPipeline.compare_exchange_strong(expected, pipeline); } /** * \brief Retrieves pipeline - * \returns The pipeline + * + * Returns the optimized version of the pipeline if + * if has been set, or the base pipeline if not. + * \returns The pipeline handle */ VkPipeline getPipeline() const { - return m_pipeline; + VkPipeline basePipeline = m_basePipeline.load(); + VkPipeline fastPipeline = m_fastPipeline.load(); + + return fastPipeline != VK_NULL_HANDLE + ? fastPipeline : basePipeline; } private: @@ -144,7 +157,8 @@ namespace dxvk { DxvkGraphicsPipelineStateInfo m_stateVector; VkRenderPass m_renderPass; - VkPipeline m_pipeline = VK_NULL_HANDLE; + std::atomic m_basePipeline; + std::atomic m_fastPipeline; }; @@ -193,9 +207,19 @@ namespace dxvk { * \returns Pipeline handle */ VkPipeline getPipelineHandle( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPass& renderPass, - DxvkStatCounters& stats); + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass& renderPass, + DxvkStatCounters& stats); + + /** + * \brief Compiles optimized pipeline + * + * Compiles an optimized version of a pipeline + * and makes it available to the system. + * \param [in] instance The pipeline instance + */ + void compilePipelineInstance( + const Rc& instance); private: