diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index a4e30fe4..da1cf882 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -4500,14 +4500,40 @@ namespace dxvk { : DxvkContextFlag::GpDirtyStencilRef); // Retrieve and bind actual Vulkan pipeline handle - VkPipeline pipeline = m_state.gp.pipeline->getPipelineHandle(m_state.gp.state); + auto pipelineInfo = m_state.gp.pipeline->getPipelineHandle(m_state.gp.state); - if (unlikely(!pipeline)) + if (unlikely(!pipelineInfo.first)) return false; m_cmd->cmdBindPipeline( VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline); + pipelineInfo.first); + + // For pipelines created from graphics pipeline libraries, we need + // to apply a bunch of dynamic state that is otherwise static + if (pipelineInfo.second == DxvkGraphicsPipelineType::BasePipeline) { + m_cmd->cmdSetRasterizerState( + m_state.gp.state.rs.cullMode(), + m_state.gp.state.rs.frontFace()); + + m_cmd->cmdSetDepthState( + m_state.gp.state.ds.enableDepthTest(), + m_state.gp.state.ds.enableDepthWrite(), + m_state.gp.state.ds.depthCompareOp()); + + m_cmd->cmdSetStencilState( + m_state.gp.state.ds.enableStencilTest(), + m_state.gp.state.dsFront.state(), + m_state.gp.state.dsBack.state()); + + if (m_device->features().core.features.depthBounds) { + m_cmd->cmdSetDepthBoundsState( + m_state.gp.state.ds.enableDepthBoundsTest()); + } + + if (!m_state.gp.state.rs.depthBiasEnable()) + m_cmd->cmdSetDepthBias(0.0f, 0.0f, 0.0f); + } // Emit barrier based on pipeline properties, in order to avoid // accidental write-after-read hazards after the render pass. diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index a24059fd..020afd29 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -524,14 +524,14 @@ namespace dxvk { } - VkPipeline DxvkGraphicsPipeline::getPipelineHandle( + std::pair DxvkGraphicsPipeline::getPipelineHandle( const DxvkGraphicsPipelineStateInfo& state) { DxvkGraphicsPipelineInstance* instance = this->findInstance(state); if (unlikely(!instance)) { // Exit early if the state vector is invalid if (!this->validatePipelineState(state, true)) - return VK_NULL_HANDLE; + return std::make_pair(VK_NULL_HANDLE, DxvkGraphicsPipelineType::FastPipeline); // Prevent other threads from adding new instances and check again std::lock_guard lock(m_mutex); @@ -545,7 +545,7 @@ namespace dxvk { } } - return instance->handle; + return std::make_pair(instance->handle, DxvkGraphicsPipelineType::FastPipeline); } diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index de4e4846..b4623bd2 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -230,6 +230,15 @@ namespace dxvk { }; + /** + * \brief Graphics pipeline type + */ + enum class DxvkGraphicsPipelineType : uint32_t { + BasePipeline = 0, ///< Unoptimized pipeline using graphics pipeline libraries + FastPipeline = 1, ///< Monolithic pipeline with less dynamic state + }; + + /** * \brief Graphics pipeline instance * @@ -327,9 +336,9 @@ 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 - * \returns Pipeline handle + * \returns Pipeline handle and handle type */ - VkPipeline getPipelineHandle( + std::pair getPipelineHandle( const DxvkGraphicsPipelineStateInfo& state); /**