diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 1b99aefaf..08f25517d 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -35,24 +35,6 @@ namespace dxvk { } - DxvkGraphicsPipelineInstance::DxvkGraphicsPipelineInstance( - const Rc& vkd, - const DxvkGraphicsPipelineStateInfo& stateVector, - VkRenderPass renderPass, - VkPipeline pipeline) - : m_vkd (vkd), - m_stateVector (stateVector), - m_renderPass (renderPass), - m_pipeline (pipeline) { - - } - - - DxvkGraphicsPipelineInstance::~DxvkGraphicsPipelineInstance() { - m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipeline, nullptr); - } - - DxvkGraphicsPipeline::DxvkGraphicsPipeline( const DxvkDevice* device, const Rc& cache, @@ -93,7 +75,8 @@ namespace dxvk { DxvkGraphicsPipeline::~DxvkGraphicsPipeline() { - + for (const auto& instance : m_pipelines) + this->destroyPipeline(instance.pipeline()); } @@ -105,11 +88,11 @@ namespace dxvk { { std::lock_guard lock(m_mutex); - DxvkGraphicsPipelineInstance* pipeline = + const DxvkGraphicsPipelineInstance* instance = this->findInstance(state, renderPassHandle); - if (pipeline != nullptr) - return pipeline->getPipeline(); + if (instance != nullptr) + return instance->pipeline(); } // If the pipeline state vector is invalid, don't try @@ -123,22 +106,20 @@ namespace dxvk { VkPipeline newPipelineHandle = this->compilePipeline( state, renderPassHandle, newPipelineBase); - Rc newPipeline = - new DxvkGraphicsPipelineInstance(m_device->vkd(), - state, renderPassHandle, newPipelineHandle); - { std::lock_guard lock(m_mutex); // Discard the pipeline if another thread // was faster compiling the same pipeline - DxvkGraphicsPipelineInstance* pipeline = + const DxvkGraphicsPipelineInstance* instance = this->findInstance(state, renderPassHandle); - if (pipeline != nullptr) - return pipeline->getPipeline(); + if (instance != nullptr) { + this->destroyPipeline(newPipelineHandle); + return instance->pipeline(); + } // Add new pipeline to the set - m_pipelines.push_back(newPipeline); + m_pipelines.emplace_back(state, renderPassHandle, newPipelineHandle); stats.addCtr(DxvkStatCounter::PipeCountGraphics, 1); } @@ -151,12 +132,12 @@ namespace dxvk { } - DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::findInstance( + const DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::findInstance( const DxvkGraphicsPipelineStateInfo& state, VkRenderPass renderPass) const { - for (const auto& pipeline : m_pipelines) { - if (pipeline->isCompatible(state, renderPass)) - return pipeline.ptr(); + for (const auto& instance : m_pipelines) { + if (instance.isCompatible(state, renderPass)) + return &instance; } return nullptr; @@ -377,6 +358,11 @@ namespace dxvk { } + void DxvkGraphicsPipeline::destroyPipeline(VkPipeline pipeline) const { + m_vkd->vkDestroyPipeline(m_vkd->device(), pipeline, nullptr); + } + + bool DxvkGraphicsPipeline::validatePipelineState( const DxvkGraphicsPipelineStateInfo& state) const { // Validate vertex input - each input slot consumed by the diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index 217e7f178..03155bf17 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -90,18 +90,19 @@ namespace dxvk { * Stores a state vector and the * corresponding pipeline handle. */ - class DxvkGraphicsPipelineInstance : public RcObject { - friend class DxvkGraphicsPipeline; + class DxvkGraphicsPipelineInstance { + public: - + + DxvkGraphicsPipelineInstance() { } DxvkGraphicsPipelineInstance( - const Rc& vkd, - const DxvkGraphicsPipelineStateInfo& stateVector, - VkRenderPass renderPass, - VkPipeline pipeline); - - ~DxvkGraphicsPipelineInstance(); - + const DxvkGraphicsPipelineStateInfo& state, + VkRenderPass rp, + VkPipeline pipe) + : m_stateVector (state), + m_renderPass (rp), + m_pipeline (pipe) { } + /** * \brief Checks for matching pipeline state * @@ -110,47 +111,28 @@ namespace dxvk { * \returns \c true if the specialization is compatible */ bool isCompatible( - const DxvkGraphicsPipelineStateInfo& stateVector, - VkRenderPass renderPass) const { - return m_renderPass == renderPass - && m_stateVector == stateVector; + const DxvkGraphicsPipelineStateInfo& state, + VkRenderPass rp) const { + return m_stateVector == state + && m_renderPass == rp; } - - /** - * \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 - */ - bool setPipeline(VkPipeline pipeline) { - VkPipeline expected = VK_NULL_HANDLE; - return m_pipeline.compare_exchange_strong(expected, pipeline); - } - + /** * \brief Retrieves 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.load(); + VkPipeline pipeline() const { + return m_pipeline; } - + private: - - const Rc m_vkd; - + DxvkGraphicsPipelineStateInfo m_stateVector; VkRenderPass m_renderPass; + VkPipeline m_pipeline; - std::atomic m_pipeline; - }; - + /** * \brief Graphics pipeline @@ -226,13 +208,13 @@ namespace dxvk { DxvkGraphicsCommonPipelineStateInfo m_common; // List of pipeline instances, shared between threads - alignas(CACHE_LINE_SIZE) sync::Spinlock m_mutex; - std::vector> m_pipelines; + alignas(CACHE_LINE_SIZE) sync::Spinlock m_mutex; + std::vector m_pipelines; // Pipeline handles used for derivative pipelines std::atomic m_basePipeline = { VK_NULL_HANDLE }; - DxvkGraphicsPipelineInstance* findInstance( + const DxvkGraphicsPipelineInstance* findInstance( const DxvkGraphicsPipelineStateInfo& state, VkRenderPass renderPass) const; @@ -241,6 +223,9 @@ namespace dxvk { VkRenderPass renderPass, VkPipeline baseHandle) const; + void destroyPipeline( + VkPipeline pipeline) const; + bool validatePipelineState( const DxvkGraphicsPipelineStateInfo& state) const;