diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index e29fab326..696b5c1cb 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -694,9 +694,9 @@ namespace Ryujinx.Graphics.Vulkan if (texture is TextureView srcTexture) { var oldCullMode = _supportExtDynamic ? DynamicState.CullMode : _newState.CullMode; - var oldStencilTestEnable = _supportExtDynamic ? DynamicState._stencilTestEnable : _newState.StencilTestEnable; - var oldDepthTestEnable = _supportExtDynamic ? DynamicState._depthtestEnable : _newState.DepthTestEnable; - var oldDepthWriteEnable = _supportExtDynamic ? DynamicState._depthwriteEnable : _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 = _supportExtDynamic ? DynamicState.ViewportsCount : _newState.ViewportsCount; @@ -1082,7 +1082,43 @@ namespace Ryujinx.Graphics.Vulkan public void SetPrimitiveRestart(bool enable, int index) { - _newState.PrimitiveRestartEnable = enable; + bool primitiveRestartEnable = enable; + + bool topologySupportsRestart; + + if (Gd.Capabilities.SupportsPrimitiveTopologyListRestart) + { + topologySupportsRestart = Gd.Capabilities.SupportsPrimitiveTopologyPatchListRestart || + _newState.Topology != Silk.NET.Vulkan.PrimitiveTopology.PatchList; + } + else + { + topologySupportsRestart = _newState.Topology == Silk.NET.Vulkan.PrimitiveTopology.LineStrip || + _newState.Topology == Silk.NET.Vulkan.PrimitiveTopology.TriangleStrip || + _newState.Topology == Silk.NET.Vulkan.PrimitiveTopology.TriangleFan || + _newState.Topology == Silk.NET.Vulkan.PrimitiveTopology.LineStripWithAdjacency || + _newState.Topology == Silk.NET.Vulkan.PrimitiveTopology.TriangleStripWithAdjacency; + } + + primitiveRestartEnable &= topologySupportsRestart; + + //Cannot disable primitveRestartEnable for these Topoligies on MacOS + if ((_newState.Topology == Silk.NET.Vulkan.PrimitiveTopology.LineStrip || _newState.Topology == Silk.NET.Vulkan.PrimitiveTopology.TriangleStrip || + _newState.Topology == Silk.NET.Vulkan.PrimitiveTopology.LineStripWithAdjacency || + _newState.Topology == Silk.NET.Vulkan.PrimitiveTopology.TriangleStripWithAdjacency) && Gd.IsMoltenVk) + { + primitiveRestartEnable = true; + } + + if (_supportExtDynamic2) + { + DynamicState.SetPrimitiveRestartEnable(primitiveRestartEnable); + } + else + { + _newState.PrimitiveRestartEnable = primitiveRestartEnable; + } + // TODO: What to do about the index? SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index bc9939d6c..5d4b473d0 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -32,12 +32,12 @@ namespace Ryujinx.Graphics.Vulkan private StencilOp _frontdepthfailop; private CompareOp _frontcompareop; - private float _linewidth; + private float _lineWidth; - public bool _stencilTestEnable; + public bool StencilTestEnable; - public bool _depthtestEnable; - public bool _depthwriteEnable; + public bool DepthTestEnable; + public bool DepthWriteEnable; private CompareOp _depthCompareOp; private Array4 _blendConstants; @@ -46,7 +46,7 @@ namespace Ryujinx.Graphics.Vulkan public Array16 Viewports; public CullModeFlags CullMode; - public FrontFace FrontFace; + private FrontFace _frontFace; private bool _discard; @@ -63,6 +63,8 @@ namespace Ryujinx.Graphics.Vulkan public bool DepthMode; + private bool _primitiveRestartEnable; + [Flags] private enum DirtyFlags { @@ -86,9 +88,10 @@ namespace Ryujinx.Graphics.Vulkan AlphaToOne = 1 << 16, PatchControlPoints = 1 << 17, DepthMode = 1 << 18, + PrimitiveRestart = 1 << 19, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable, - Extended2 = RasterDiscard | LogicOp | PatchControlPoints, + Extended2 = RasterDiscard | LogicOp | PatchControlPoints | PrimitiveRestart, Extended3 = DepthClampEnable | LogicOpEnable | AlphaToCover | AlphaToOne | DepthMode, } @@ -142,10 +145,10 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthTestBool(bool testEnable, bool writeEnable) { - if (_depthtestEnable != testEnable || _depthwriteEnable != writeEnable) + if (DepthTestEnable != testEnable || DepthWriteEnable != writeEnable) { - _depthtestEnable = testEnable; - _depthwriteEnable = writeEnable; + DepthTestEnable = testEnable; + DepthWriteEnable = writeEnable; _dirty |= DirtyFlags.DepthTestBool; } } @@ -198,14 +201,13 @@ namespace Ryujinx.Graphics.Vulkan public void SetStencilTest(bool stencilTestEnable) { - if (_stencilTestEnable != stencilTestEnable) + if (StencilTestEnable != stencilTestEnable) { - _stencilTestEnable = stencilTestEnable; + StencilTestEnable = stencilTestEnable; _dirty |= DirtyFlags.StencilTestEnable; } } - public void SetViewport(int index, Viewport viewport) { if (!Viewports[index].Equals(viewport)) @@ -239,18 +241,18 @@ namespace Ryujinx.Graphics.Vulkan public void SetFrontFace(FrontFace frontFace) { - if (FrontFace != frontFace) + if (_frontFace != frontFace) { - FrontFace = frontFace; + _frontFace = frontFace; _dirty |= DirtyFlags.FrontFace; } } public void SetLineWidth(float width) { - if (!FloatCompare(_linewidth, width)) + if (!FloatCompare(_lineWidth, width)) { - _linewidth = width; + _lineWidth = width; _dirty |= DirtyFlags.LineWidth; } @@ -265,6 +267,15 @@ namespace Ryujinx.Graphics.Vulkan } } + public void SetPrimitiveRestartEnable(bool primitiveRestart) + { + if (_primitiveRestartEnable != primitiveRestart) + { + _primitiveRestartEnable = primitiveRestart; + _dirty |= DirtyFlags.PrimitiveRestart; + } + } + public void SetLogicOp(LogicOp op) { if (_logicOp != op) @@ -450,6 +461,11 @@ namespace Ryujinx.Graphics.Vulkan RecordRasterizationDiscard(gd, commandBuffer); } + if (_dirty.HasFlag(DirtyFlags.PrimitiveRestart)) + { + RecordPrimitiveRestartEnable(gd, commandBuffer); + } + if (_dirty.HasFlag(DirtyFlags.LogicOp)) { RecordLogicOp(gd, commandBuffer); @@ -528,7 +544,7 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordStencil(VulkanRenderer gd, CommandBuffer commandBuffer) { - if (_opToo && _stencilTestEnable) + if (_opToo && StencilTestEnable) { gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceBackBit, _backfailop, _backpassop, _backdepthfailop, _backcompareop); @@ -546,7 +562,7 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordStencilTestEnable(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { - api.CmdSetStencilTestEnable(commandBuffer, _stencilTestEnable); + api.CmdSetStencilTestEnable(commandBuffer, StencilTestEnable); } private void RecordViewport(VulkanRenderer gd, CommandBuffer commandBuffer) @@ -576,14 +592,14 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordFrontFace(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { - api.CmdSetFrontFace(commandBuffer, FrontFace); + api.CmdSetFrontFace(commandBuffer, _frontFace); } private readonly void RecordDepthTestBool(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { - api.CmdSetDepthTestEnable(commandBuffer, _depthtestEnable); + api.CmdSetDepthTestEnable(commandBuffer, DepthTestEnable); - api.CmdSetDepthWriteEnable(commandBuffer, _depthwriteEnable); + api.CmdSetDepthWriteEnable(commandBuffer, DepthWriteEnable); } private readonly void RecordDepthTestCompareOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) @@ -596,6 +612,11 @@ namespace Ryujinx.Graphics.Vulkan gd.ExtendedDynamicState2Api.CmdSetRasterizerDiscardEnable(commandBuffer, _discard); } + private readonly void RecordPrimitiveRestartEnable(VulkanRenderer gd, CommandBuffer commandBuffer) + { + gd.ExtendedDynamicState2Api.CmdSetPrimitiveRestartEnable(commandBuffer, _primitiveRestartEnable); + } + private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) { if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable && !_logicOpEnable) @@ -640,7 +661,7 @@ namespace Ryujinx.Graphics.Vulkan { if (!OperatingSystem.IsMacOS()) { - api.CmdSetLineWidth(commandBuffer, _linewidth); + api.CmdSetLineWidth(commandBuffer, _lineWidth); } } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index d461ab323..7ae909e16 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -432,40 +432,17 @@ namespace Ryujinx.Graphics.Vulkan return null; } - bool primitiveRestartEnable = PrimitiveRestartEnable; - - bool topologySupportsRestart; - - if (gd.Capabilities.SupportsPrimitiveTopologyListRestart) - { - topologySupportsRestart = gd.Capabilities.SupportsPrimitiveTopologyPatchListRestart || Topology != PrimitiveTopology.PatchList; - } - else - { - topologySupportsRestart = Topology == PrimitiveTopology.LineStrip || - Topology == PrimitiveTopology.TriangleStrip || - Topology == PrimitiveTopology.TriangleFan || - Topology == PrimitiveTopology.LineStripWithAdjacency || - Topology == PrimitiveTopology.TriangleStripWithAdjacency; - } - - primitiveRestartEnable &= topologySupportsRestart; - - //Cannot disable primitveRestartEnable for these Topoligies on MacOS - if ((Topology == PrimitiveTopology.LineStrip || Topology == PrimitiveTopology.TriangleStrip || - Topology == PrimitiveTopology.LineStripWithAdjacency || - Topology == PrimitiveTopology.TriangleStripWithAdjacency) && isMoltenVk) - { - primitiveRestartEnable = true; - } - var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, - PrimitiveRestartEnable = primitiveRestartEnable, Topology = Topology, }; + if (!supportsExtDynamicState) + { + inputAssemblyState.PrimitiveRestartEnable = PrimitiveRestartEnable; + } + var tessellationState = new PipelineTessellationStateCreateInfo { SType = StructureType.PipelineTessellationStateCreateInfo, @@ -631,7 +608,7 @@ namespace Ryujinx.Graphics.Vulkan if (supportsExtDynamicState2) { - additionalDynamicStatesCount += 2; + additionalDynamicStatesCount += 3; if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) { additionalDynamicStatesCount++; @@ -703,6 +680,7 @@ namespace Ryujinx.Graphics.Vulkan { dynamicStates[currentIndex++] = DynamicState.DepthBiasEnableExt; dynamicStates[currentIndex++] = DynamicState.RasterizerDiscardEnableExt; + dynamicStates[currentIndex++] = DynamicState.PrimitiveRestartEnableExt; if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) {