From 3a3b1eda5992218c9da6f7d282ce9d8c059b45e7 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 3 May 2018 19:33:41 +0200 Subject: [PATCH] [dxvk] Move render pass out of pipeline state vector --- src/dxvk/dxvk_context.cpp | 6 +++--- src/dxvk/dxvk_framebuffer.h | 8 ++++++++ src/dxvk/dxvk_graphics.cpp | 21 +++++++++++---------- src/dxvk/dxvk_graphics.h | 7 ++++++- src/dxvk/dxvk_renderpass.cpp | 30 +++++++++++++++++------------- src/dxvk/dxvk_renderpass.h | 10 ++++++++++ 6 files changed, 55 insertions(+), 27 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 89eb4733..7ff4b378 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1712,8 +1712,9 @@ namespace dxvk { for (uint32_t i = m_state.gp.state.ilBindingCount; i < MaxNumVertexBindings; i++) m_state.gp.state.ilBindings[i].stride = 0; - m_gpActivePipeline = m_state.gp.pipeline != nullptr - ? m_state.gp.pipeline->getPipelineHandle(m_state.gp.state, m_cmd->statCounters()) + m_gpActivePipeline = m_state.gp.pipeline != nullptr && m_state.om.framebuffer != nullptr + ? m_state.gp.pipeline->getPipelineHandle(m_state.gp.state, + m_state.om.framebuffer->getRenderPass(), m_cmd->statCounters()) : VK_NULL_HANDLE; if (m_gpActivePipeline != VK_NULL_HANDLE) { @@ -1911,7 +1912,6 @@ namespace dxvk { auto fb = m_device->createFramebuffer(m_state.om.renderTargets); m_state.gp.state.msSampleCount = fb->getSampleCount(); - m_state.gp.state.omRenderPass = fb->getDefaultRenderPassHandle(); m_state.om.framebuffer = fb; m_flags.set(DxvkContextFlag::GpDirtyPipelineState); diff --git a/src/dxvk/dxvk_framebuffer.h b/src/dxvk/dxvk_framebuffer.h index 592b6d96..40499239 100644 --- a/src/dxvk/dxvk_framebuffer.h +++ b/src/dxvk/dxvk_framebuffer.h @@ -110,6 +110,14 @@ namespace dxvk { return m_renderPass->getHandle(ops); } + /** + * \brief Retrieves render pass + * \returns Render pass reference + */ + const DxvkRenderPass& getRenderPass() const { + return *m_renderPass; + } + /** * \brief Depth-stencil target * \returns Depth-stencil target diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 32c8db24..cc707beb 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -77,32 +77,34 @@ namespace dxvk { VkPipeline DxvkGraphicsPipeline::getPipelineHandle( const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass& renderPass, DxvkStatCounters& stats) { VkPipeline pipeline = VK_NULL_HANDLE; + VkRenderPass renderPassHandle = renderPass.getDefaultHandle(); { std::lock_guard lock(m_mutex); - if (this->findPipeline(state, pipeline)) + if (this->findPipeline(state, renderPassHandle, pipeline)) return pipeline; } // If no pipeline exists with the given state vector, // create a new one and add it to the pipeline set. VkPipeline newPipeline = this->validatePipelineState(state) - ? this->compilePipeline(state, m_basePipeline) + ? this->compilePipeline(state, renderPassHandle, m_basePipeline) : VK_NULL_HANDLE; { std::lock_guard lock(m_mutex); // Discard the pipeline if another thread // was faster compiling the same pipeline - if (this->findPipeline(state, pipeline)) { + if (this->findPipeline(state, renderPassHandle, pipeline)) { m_vkd->vkDestroyPipeline(m_vkd->device(), newPipeline, nullptr); return pipeline; } // Add new pipeline to the set - m_pipelines.push_back({ state, newPipeline }); + m_pipelines.push_back({ state, renderPassHandle, newPipeline }); if (m_basePipeline == VK_NULL_HANDLE) m_basePipeline = newPipeline; @@ -115,9 +117,11 @@ namespace dxvk { bool DxvkGraphicsPipeline::findPipeline( const DxvkGraphicsPipelineStateInfo& state, + VkRenderPass renderPass, VkPipeline& pipeline) const { for (const PipelineStruct& pair : m_pipelines) { - if (pair.stateVector == state) { + if (pair.stateVector == state + && pair.renderPass == renderPass) { pipeline = pair.pipeline; return true; } @@ -129,6 +133,7 @@ namespace dxvk { VkPipeline DxvkGraphicsPipeline::compilePipeline( const DxvkGraphicsPipelineStateInfo& state, + VkRenderPass renderPass, VkPipeline baseHandle) const { if (Logger::logLevel() <= LogLevel::Debug) { Logger::debug("Compiling graphics pipeline..."); @@ -297,7 +302,7 @@ namespace dxvk { info.pColorBlendState = &cbInfo; info.pDynamicState = &dyInfo; info.layout = m_layout->pipelineLayout(); - info.renderPass = state.omRenderPass; + info.renderPass = renderPass; info.subpass = 0; info.basePipelineHandle = baseHandle; info.basePipelineIndex = -1; @@ -331,10 +336,6 @@ namespace dxvk { bool DxvkGraphicsPipeline::validatePipelineState( const DxvkGraphicsPipelineStateInfo& state) const { - // Make sure that we have an active render pass - if (state.omRenderPass == VK_NULL_HANDLE) - return false; - // Validate vertex input - each input slot consumed by the // vertex shader must be provided by the input layout. uint32_t providedVertexInputs = 0; diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index 5c40928e..cee384d9 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -6,6 +6,7 @@ #include "dxvk_constant_state.h" #include "dxvk_pipecache.h" #include "dxvk_pipelayout.h" +#include "dxvk_renderpass.h" #include "dxvk_resource.h" #include "dxvk_shader.h" #include "dxvk_stats.h" @@ -73,7 +74,6 @@ namespace dxvk { VkBool32 omEnableLogicOp; VkLogicOp omLogicOp; - VkRenderPass omRenderPass; VkPipelineColorBlendAttachmentState omBlendAttachments[MaxNumRenderTargets]; }; @@ -129,17 +129,20 @@ namespace dxvk { * Retrieves a pipeline handle for the given pipeline * state. If necessary, a new pipeline will be created. * \param [in] state Pipeline state vector + * \param [in] renderPass The render pass * \param [in,out] stats Stat counter * \returns Pipeline handle */ VkPipeline getPipelineHandle( const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass& renderPass, DxvkStatCounters& stats); private: struct PipelineStruct { DxvkGraphicsPipelineStateInfo stateVector; + VkRenderPass renderPass; VkPipeline pipeline; }; @@ -167,10 +170,12 @@ namespace dxvk { bool findPipeline( const DxvkGraphicsPipelineStateInfo& state, + VkRenderPass renderPass, VkPipeline& pipeline) const; VkPipeline compilePipeline( const DxvkGraphicsPipelineStateInfo& state, + VkRenderPass renderPass, VkPipeline baseHandle) const; void destroyPipelines(); diff --git a/src/dxvk/dxvk_renderpass.cpp b/src/dxvk/dxvk_renderpass.cpp index 343cddaf..7d2908ab 100644 --- a/src/dxvk/dxvk_renderpass.cpp +++ b/src/dxvk/dxvk_renderpass.cpp @@ -4,6 +4,21 @@ namespace dxvk { + bool DxvkRenderPassFormat::matches(const DxvkRenderPassFormat& fmt) const { + bool eq = sampleCount == fmt.sampleCount; + + for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) { + eq &= color[i].format == fmt.color[i].format + && color[i].layout == fmt.color[i].layout; + } + + eq &= depth.format == fmt.depth.format + && depth.layout == fmt.depth.layout; + + return eq; + } + + DxvkRenderPass::DxvkRenderPass( const Rc& vkd, const DxvkRenderPassFormat& fmt) @@ -23,19 +38,8 @@ namespace dxvk { } - bool DxvkRenderPass::hasCompatibleFormat( - const DxvkRenderPassFormat& fmt) const { - bool eq = m_format.sampleCount == fmt.sampleCount; - - for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) { - eq &= m_format.color[i].format == fmt.color[i].format - && m_format.color[i].layout == fmt.color[i].layout; - } - - eq &= m_format.depth.format == fmt.depth.format - && m_format.depth.layout == fmt.depth.layout; - - return eq; + bool DxvkRenderPass::hasCompatibleFormat(const DxvkRenderPassFormat& fmt) const { + return m_format.matches(fmt); } diff --git a/src/dxvk/dxvk_renderpass.h b/src/dxvk/dxvk_renderpass.h index d44aa487..64b91f5b 100644 --- a/src/dxvk/dxvk_renderpass.h +++ b/src/dxvk/dxvk_renderpass.h @@ -31,6 +31,8 @@ namespace dxvk { VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; DxvkAttachmentFormat depth; DxvkAttachmentFormat color[MaxNumRenderTargets]; + + bool matches(const DxvkRenderPassFormat& fmt) const; }; @@ -94,6 +96,14 @@ namespace dxvk { ~DxvkRenderPass(); + /** + * \brief Retrieves render pass format + * \returns The render pass format + */ + DxvkRenderPassFormat format() const { + return m_format; + } + /** * \brief Checks whether a format is compatible *