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;