From 422198952ab544b8b396c2f5defbd9124c12149a Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 16 Jan 2019 20:55:41 +0100 Subject: [PATCH] [dxvk] Use minimal set of dynamic state We don't need to enable blend constants for pipelines that don't have blending enabled, etc. This helps reduce the number of API calls slightly and may help the driver work more efficiently. --- src/dxvk/dxvk_context.cpp | 48 +++++++++++++++++++++++++++-------- src/dxvk/dxvk_context_state.h | 7 +++-- src/dxvk/dxvk_graphics.cpp | 24 ++++++++++++------ 3 files changed, 59 insertions(+), 20 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 36dc0af9..2969a4a6 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -2590,6 +2590,7 @@ namespace dxvk { this->pauseTransformFeedback(); + // Fix up vertex binding strides for unbound buffers for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++) { const uint32_t binding = m_state.gp.state.ilBindings[i].binding; @@ -2602,6 +2603,25 @@ namespace dxvk { for (uint32_t i = m_state.gp.state.ilBindingCount; i < MaxNumVertexBindings; i++) m_state.gp.state.ilBindings[i].stride = 0; + // Check which dynamic states need to be active. States that + // are not dynamic will be invalidated in the command buffer. + m_flags.clr(DxvkContextFlag::GpDynamicBlendConstants, + DxvkContextFlag::GpDynamicDepthBias, + DxvkContextFlag::GpDynamicStencilRef); + + m_flags.set(m_state.gp.state.useDynamicBlendConstants() + ? DxvkContextFlag::GpDynamicBlendConstants + : DxvkContextFlag::GpDirtyBlendConstants); + + m_flags.set(m_state.gp.state.useDynamicDepthBias() + ? DxvkContextFlag::GpDynamicDepthBias + : DxvkContextFlag::GpDirtyDepthBias); + + m_flags.set(m_state.gp.state.useDynamicStencilRef() + ? DxvkContextFlag::GpDynamicStencilRef + : DxvkContextFlag::GpDirtyStencilRef); + + // Retrieve and bind actual Vulkan pipeline handle 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()) @@ -3006,29 +3026,37 @@ namespace dxvk { return; if (m_flags.test(DxvkContextFlag::GpDirtyViewport)) { + m_flags.clr(DxvkContextFlag::GpDirtyViewport); + uint32_t viewportCount = m_state.gp.state.rsViewportCount; m_cmd->cmdSetViewport(0, viewportCount, m_state.vp.viewports.data()); m_cmd->cmdSetScissor (0, viewportCount, m_state.vp.scissorRects.data()); } - if (m_flags.test(DxvkContextFlag::GpDirtyBlendConstants)) + if (m_flags.all(DxvkContextFlag::GpDirtyBlendConstants, + DxvkContextFlag::GpDynamicBlendConstants)) { + m_flags.clr(DxvkContextFlag::GpDirtyBlendConstants); m_cmd->cmdSetBlendConstants(&m_state.om.blendConstants.r); + } - if (m_flags.test(DxvkContextFlag::GpDirtyStencilRef)) - m_cmd->cmdSetStencilReference(VK_STENCIL_FRONT_AND_BACK, m_state.om.stencilReference); + if (m_flags.all(DxvkContextFlag::GpDirtyStencilRef, + DxvkContextFlag::GpDynamicStencilRef)) { + m_flags.clr(DxvkContextFlag::GpDirtyStencilRef); + + m_cmd->cmdSetStencilReference( + VK_STENCIL_FRONT_AND_BACK, + m_state.om.stencilReference); + } - if (m_flags.test(DxvkContextFlag::GpDirtyDepthBias)) { + if (m_flags.all(DxvkContextFlag::GpDirtyDepthBias, + DxvkContextFlag::GpDynamicDepthBias)) { + m_flags.clr(DxvkContextFlag::GpDirtyDepthBias); + m_cmd->cmdSetDepthBias( m_state.ds.depthBiasConstant, m_state.ds.depthBiasClamp, m_state.ds.depthBiasSlope); } - - m_flags.clr( - DxvkContextFlag::GpDirtyBlendConstants, - DxvkContextFlag::GpDirtyStencilRef, - DxvkContextFlag::GpDirtyViewport, - DxvkContextFlag::GpDirtyDepthBias); } diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h index 3e5512c2..3beca32f 100644 --- a/src/dxvk/dxvk_context_state.h +++ b/src/dxvk/dxvk_context_state.h @@ -35,16 +35,19 @@ namespace dxvk { GpDirtyXfbBuffers, ///< Transform feedback buffer bindings are out of date GpDirtyXfbCounters, ///< Counter buffer values are dirty GpDirtyBlendConstants, ///< Blend constants have changed + GpDirtyDepthBias, ///< Depth bias has changed GpDirtyStencilRef, ///< Stencil reference has changed GpDirtyViewport, ///< Viewport state has changed - GpDirtyDepthBias, ///< Depth bias has changed + GpDynamicBlendConstants, ///< Blend constants are dynamic + GpDynamicDepthBias, ///< Depth bias is dynamic + GpDynamicStencilRef, ///< Stencil reference is dynamic CpDirtyPipeline, ///< Compute pipeline binding are out of date CpDirtyPipelineState, ///< Compute pipeline needs to be recompiled CpDirtyResources, ///< Compute pipeline resource bindings are out of date CpDirtyDescriptorOffsets, ///< Compute descriptor set needs to be rebound CpDirtyDescriptorSet, ///< Compute descriptor set needs to be updated - + DirtyDrawBuffer, ///< Indirect argument buffer is dirty }; diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index dae1a9b3..9d20b4ac 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -177,13 +177,21 @@ namespace dxvk { this->logPipelineState(LogLevel::Debug, state); } - std::array dynamicStates = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - VK_DYNAMIC_STATE_DEPTH_BIAS, - VK_DYNAMIC_STATE_BLEND_CONSTANTS, - VK_DYNAMIC_STATE_STENCIL_REFERENCE, - }; + // Set up dynamic states as needed + std::array dynamicStates; + uint32_t dynamicStateCount = 0; + + dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_VIEWPORT; + dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_SCISSOR; + + if (state.useDynamicDepthBias()) + dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_DEPTH_BIAS; + + if (state.useDynamicBlendConstants()) + dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_BLEND_CONSTANTS; + + if (state.useDynamicStencilRef()) + dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_STENCIL_REFERENCE; // Figure out the actual sample count to use VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; @@ -366,7 +374,7 @@ namespace dxvk { dyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; dyInfo.pNext = nullptr; dyInfo.flags = 0; - dyInfo.dynamicStateCount = dynamicStates.size(); + dyInfo.dynamicStateCount = dynamicStateCount; dyInfo.pDynamicStates = dynamicStates.data(); VkGraphicsPipelineCreateInfo info;