diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 0aee69732..096627e0b 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -690,9 +690,9 @@ namespace Ryujinx.Graphics.Vulkan if (texture is TextureView srcTexture) { var oldCullMode = _supportExtDynamic ? DynamicState.CullMode : _newState.CullMode; - var oldStencilTestEnable = _newState.StencilTestEnable; - var oldDepthTestEnable = _newState.DepthTestEnable; - var oldDepthWriteEnable = _newState.DepthWriteEnable; + var oldStencilTestEnable = _supportExtDynamic ? DynamicState._stencilTestEnable : _newState.StencilTestEnable; + var oldDepthTestEnable = _supportExtDynamic ? DynamicState._depthtestEnable : _newState.DepthTestEnable; + var oldDepthWriteEnable = _supportExtDynamic ? DynamicState._depthwriteEnable : _newState.DepthWriteEnable; var oldTopology = _newState.Topology; var oldViewports = DynamicState.Viewports; var oldViewportsCount = _newState.ViewportsCount; @@ -700,15 +700,17 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { DynamicState.SetCullMode(CullModeFlags.None); + DynamicState.SetDepthTestBool(false, false); + DynamicState.SetStencilTest(false); } else { _newState.CullMode = CullModeFlags.None; + _newState.StencilTestEnable = false; + _newState.DepthTestEnable = false; + _newState.DepthWriteEnable = false; } - _newState.StencilTestEnable = false; - _newState.DepthTestEnable = false; - _newState.DepthWriteEnable = false; SignalStateChange(); Gd.HelperShader.DrawTexture( @@ -722,15 +724,17 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { DynamicState.SetCullMode(oldCullMode); + DynamicState.SetStencilTest(oldStencilTestEnable); + DynamicState.SetDepthTestBool(oldDepthTestEnable, oldDepthWriteEnable); } else { _newState.CullMode = oldCullMode; + _newState.StencilTestEnable = oldStencilTestEnable; + _newState.DepthTestEnable = oldDepthTestEnable; + _newState.DepthWriteEnable = oldDepthWriteEnable; } - _newState.StencilTestEnable = oldStencilTestEnable; - _newState.DepthTestEnable = oldDepthTestEnable; - _newState.DepthWriteEnable = oldDepthWriteEnable; _newState.Topology = oldTopology; DynamicState.SetViewports(ref oldViewports, oldViewportsCount); @@ -888,9 +892,18 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthTest(DepthTestDescriptor depthTest) { - _newState.DepthTestEnable = depthTest.TestEnable; - _newState.DepthWriteEnable = depthTest.WriteEnable; - _newState.DepthCompareOp = depthTest.Func.Convert(); + if (_supportExtDynamic) + { + DynamicState.SetDepthTestBool(depthTest.TestEnable, depthTest.WriteEnable); + DynamicState.SetDepthTestCompareOp(depthTest.Func.Convert()); + } + else + { + _newState.DepthTestEnable = depthTest.TestEnable; + _newState.DepthWriteEnable = depthTest.WriteEnable; + _newState.DepthCompareOp = depthTest.Func.Convert(); + } + SignalStateChange(); } @@ -1148,7 +1161,7 @@ namespace Ryujinx.Graphics.Vulkan public void SetStencilTest(StencilTestDescriptor stencilTest) { - if (Gd.Capabilities.SupportsExtendedDynamicState) + if (_supportExtDynamic) { DynamicState.SetStencilOp( stencilTest.BackSFail.Convert(), @@ -1159,6 +1172,8 @@ namespace Ryujinx.Graphics.Vulkan stencilTest.FrontDpPass.Convert(), stencilTest.FrontDpFail.Convert(), stencilTest.FrontFunc.Convert()); + + DynamicState.SetStencilTest(stencilTest.TestEnable); } else { @@ -1170,10 +1185,9 @@ namespace Ryujinx.Graphics.Vulkan _newState.StencilFrontPassOp = stencilTest.FrontDpPass.Convert(); _newState.StencilFrontDepthFailOp = stencilTest.FrontDpFail.Convert(); _newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert(); + _newState.StencilTestEnable = stencilTest.TestEnable; } - _newState.StencilTestEnable = stencilTest.TestEnable; - DynamicState.SetStencilMask((uint)stencilTest.BackFuncMask, (uint)stencilTest.BackMask, (uint)stencilTest.BackFuncRef, diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 31eb64d80..7a1c39b04 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -19,6 +19,7 @@ namespace Ryujinx.Graphics.Vulkan private uint _frontCompareMask; private uint _frontWriteMask; private uint _frontReference; + private bool _opToo; private StencilOp _backfailop; private StencilOp _backpassop; @@ -28,6 +29,12 @@ namespace Ryujinx.Graphics.Vulkan private StencilOp _frontpassop; private StencilOp _frontdepthfailop; private CompareOp _frontcompareop; + + public bool _stencilTestEnable; + + public bool _depthtestEnable; + public bool _depthwriteEnable; + private CompareOp _depthCompareOp; private Array4 _blendConstants; @@ -48,7 +55,10 @@ namespace Ryujinx.Graphics.Vulkan Viewport = 1 << 4, CullMode = 1 << 5, FrontFace = 1 << 6, - All = Blend | DepthBias | Scissor | Stencil | Viewport | CullMode | FrontFace, + DepthTestBool = 1 << 7, + DepthTestCompareOp = 1 << 8, + StencilTestEnable = 1 << 9, + All = Blend | DepthBias | Scissor | Stencil | Viewport | CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable, } private DirtyFlags _dirty; @@ -79,6 +89,45 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.Scissor; } + public void SetDepthTestBool(bool testEnable, bool writeEnable) + { + _depthtestEnable = testEnable; + _depthwriteEnable = writeEnable; + + _dirty |= DirtyFlags.DepthTestBool; + } + + public void SetDepthTestCompareOp(CompareOp depthTestOp) + { + _depthCompareOp = depthTestOp; + + _dirty |= DirtyFlags.DepthTestCompareOp; + } + + + + public void SetStencilOp(StencilOp backFailOp, + StencilOp backPassOp, + StencilOp backDepthFailOp, + CompareOp backCompareOp, + StencilOp frontFailOp, + StencilOp frontPassOp, + StencilOp frontDepthFailOp, + CompareOp frontCompareOp) + { + _backfailop = backFailOp; + _backpassop = backPassOp; + _backdepthfailop = backDepthFailOp; + _backcompareop = backCompareOp; + + _frontfailop = frontFailOp; + _frontpassop = frontPassOp; + _frontdepthfailop = frontDepthFailOp; + _frontcompareop = frontCompareOp; + + _opToo = true; + } + public void SetStencilMask( uint backCompareMask, uint backWriteMask, @@ -97,27 +146,14 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.Stencil; } - public void SetStencilOp(StencilOp backFailOp = default, - StencilOp backPassOp = default, - StencilOp backDepthFailOp = default, - CompareOp backCompareOp = default, - StencilOp frontFailOp = default, - StencilOp frontPassOp = default, - StencilOp frontDepthFailOp = default, - CompareOp frontCompareOp = default) + public void SetStencilTest(bool stencilTestEnable) { - _backfailop = backFailOp; - _backpassop = backPassOp; - _backdepthfailop = backDepthFailOp; - _backcompareop = backCompareOp; - - _frontfailop = frontFailOp; - _frontpassop = frontPassOp; - _frontdepthfailop = frontDepthFailOp; - _frontcompareop = frontCompareOp; - _opToo = true; + _stencilTestEnable = stencilTestEnable; + + _dirty |= DirtyFlags.StencilTestEnable; } + public void SetViewport(int index, Viewport viewport) { Viewports[index] = viewport; @@ -191,6 +227,21 @@ namespace Ryujinx.Graphics.Vulkan { RecordFrontFace(api, commandBuffer); } + + if (_dirty.HasFlag(DirtyFlags.DepthTestBool)) + { + RecordDepthTestBool(api, commandBuffer); + } + + if (_dirty.HasFlag(DirtyFlags.DepthTestCompareOp)) + { + RecordDepthTestCompareOp(api, commandBuffer); + } + + if (_dirty.HasFlag(DirtyFlags.StencilTestEnable)) + { + RecordStencilTestEnable(api, commandBuffer); + } _dirty = DirtyFlags.None; } @@ -230,7 +281,12 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontWriteMask); api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference); } - + + private readonly void RecordStencilTestEnable(Vk api, CommandBuffer commandBuffer) + { + api.CmdSetStencilTestEnable(commandBuffer, _stencilTestEnable); + } + private void RecordViewport(Vk api, CommandBuffer commandBuffer) { if (ViewportsCount != 0) @@ -248,5 +304,16 @@ namespace Ryujinx.Graphics.Vulkan { api.CmdSetFrontFace(commandBuffer, FrontFace); } + + private void RecordDepthTestBool(Vk api, CommandBuffer commandBuffer) + { + api.CmdSetDepthTestEnable(commandBuffer, _depthtestEnable); + api.CmdSetDepthWriteEnable(commandBuffer, _depthwriteEnable); + } + + private void RecordDepthTestCompareOp(Vk api, CommandBuffer commandBuffer) + { + api.CmdSetDepthCompareOp(commandBuffer, _depthCompareOp); + } } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 24586800e..6182ccaa0 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -509,11 +509,7 @@ namespace Ryujinx.Graphics.Vulkan var depthStencilState = new PipelineDepthStencilStateCreateInfo { SType = StructureType.PipelineDepthStencilStateCreateInfo, - DepthTestEnable = DepthTestEnable, - DepthWriteEnable = DepthWriteEnable, - DepthCompareOp = DepthCompareOp, DepthBoundsTestEnable = DepthBoundsTestEnable, - StencilTestEnable = StencilTestEnable, MinDepthBounds = MinDepthBounds, MaxDepthBounds = MaxDepthBounds, }; @@ -540,6 +536,10 @@ namespace Ryujinx.Graphics.Vulkan depthStencilState.Front = stencilFront; depthStencilState.Back = stencilBack; + depthStencilState.StencilTestEnable = StencilTestEnable; + depthStencilState.DepthTestEnable = DepthTestEnable; + depthStencilState.DepthWriteEnable = DepthWriteEnable; + depthStencilState.DepthCompareOp = DepthCompareOp; } uint blendEnables = 0; @@ -593,7 +593,7 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.PNext = &colorBlendAdvancedState; } - int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 10 : 11) : 7; + int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 14 : 15) : 7; DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount]; @@ -613,6 +613,10 @@ namespace Ryujinx.Graphics.Vulkan } dynamicStates[index++] = DynamicState.CullMode; dynamicStates[index++] = DynamicState.FrontFace; + dynamicStates[index++] = DynamicState.DepthTestEnable; + dynamicStates[index++] = DynamicState.DepthWriteEnable; + dynamicStates[index++] = DynamicState.DepthCompareOp; + dynamicStates[index++] = DynamicState.StencilTestEnable; dynamicStates[index] = DynamicState.StencilOp; }