From e6e5829abfeb2711f462ba6a60f1952f52bf7b5f Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 11 May 2024 22:11:47 -0700 Subject: [PATCH 001/132] Dynamic state for Depth Bounds should not be passed to PipelineDynamicStateCreateInfo as the command to set them is never called. Do not pass pointer to viewport and scissor as those dynamic states should be supported on all devices. Same as above for DepthBias values. --- .../PipelineConverter.cs | 6 ---- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 32 +++++++------------ src/Ryujinx.Graphics.Vulkan/PipelineUid.cs | 2 -- 3 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 41618c736..ad2c7f866 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -208,17 +208,11 @@ namespace Ryujinx.Graphics.Vulkan pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert(); pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert(); pipeline.StencilFrontCompareOp = state.StencilTest.FrontFunc.Convert(); - pipeline.StencilFrontCompareMask = 0; - pipeline.StencilFrontWriteMask = 0; - pipeline.StencilFrontReference = 0; pipeline.StencilBackFailOp = state.StencilTest.BackSFail.Convert(); pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert(); pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert(); pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert(); - pipeline.StencilBackCompareMask = 0; - pipeline.StencilBackWriteMask = 0; - pipeline.StencilBackReference = 0; pipeline.StencilTestEnable = state.StencilTest.TestEnable; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index c38748936..a22f137d4 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -408,8 +408,6 @@ namespace Ryujinx.Graphics.Vulkan fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0]) fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions2 = &_vertexAttributeDescriptions2[0]) fixed (VertexInputBindingDescription* pVertexBindingDescriptions = &Internal.VertexBindingDescriptions[0]) - fixed (Viewport* pViewports = &Internal.Viewports[0]) - fixed (Rect2D* pScissors = &Internal.Scissors[0]) fixed (PipelineColorBlendAttachmentState* pColorBlendAttachmentState = &Internal.ColorBlendAttachmentState[0]) { var vertexInputState = new PipelineVertexInputStateCreateInfo @@ -472,18 +470,13 @@ namespace Ryujinx.Graphics.Vulkan CullMode = CullMode, FrontFace = FrontFace, DepthBiasEnable = DepthBiasEnable, - DepthBiasClamp = DepthBiasClamp, - DepthBiasConstantFactor = DepthBiasConstantFactor, - DepthBiasSlopeFactor = DepthBiasSlopeFactor, }; var viewportState = new PipelineViewportStateCreateInfo { SType = StructureType.PipelineViewportStateCreateInfo, ViewportCount = ViewportsCount, - PViewports = pViewports, ScissorCount = ScissorsCount, - PScissors = pScissors, }; if (gd.Capabilities.SupportsDepthClipControl) @@ -512,18 +505,18 @@ namespace Ryujinx.Graphics.Vulkan StencilFrontPassOp, StencilFrontDepthFailOp, StencilFrontCompareOp, - StencilFrontCompareMask, - StencilFrontWriteMask, - StencilFrontReference); + null, + null, + null); var stencilBack = new StencilOpState( StencilBackFailOp, StencilBackPassOp, StencilBackDepthFailOp, StencilBackCompareOp, - StencilBackCompareMask, - StencilBackWriteMask, - StencilBackReference); + null, + null, + null); var depthStencilState = new PipelineDepthStencilStateCreateInfo { @@ -591,22 +584,21 @@ namespace Ryujinx.Graphics.Vulkan } bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState; - int dynamicStatesCount = supportsExtDynamicState ? 9 : 8; + int dynamicStatesCount = supportsExtDynamicState ? 8 : 7; DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount]; dynamicStates[0] = DynamicState.Viewport; dynamicStates[1] = DynamicState.Scissor; dynamicStates[2] = DynamicState.DepthBias; - dynamicStates[3] = DynamicState.DepthBounds; - dynamicStates[4] = DynamicState.StencilCompareMask; - dynamicStates[5] = DynamicState.StencilWriteMask; - dynamicStates[6] = DynamicState.StencilReference; - dynamicStates[7] = DynamicState.BlendConstants; + dynamicStates[3] = DynamicState.StencilCompareMask; + dynamicStates[4] = DynamicState.StencilWriteMask; + dynamicStates[5] = DynamicState.StencilReference; + dynamicStates[6] = DynamicState.BlendConstants; if (supportsExtDynamicState) { - dynamicStates[8] = DynamicState.VertexInputBindingStrideExt; + dynamicStates[7] = DynamicState.VertexInputBindingStrideExt; } var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs b/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs index 238f06e2a..9dfe78669 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs @@ -29,8 +29,6 @@ namespace Ryujinx.Graphics.Vulkan public Array32 VertexAttributeDescriptions; public Array33 VertexBindingDescriptions; - public Array16 Viewports; - public Array16 Scissors; public Array8 ColorBlendAttachmentState; public Array9 AttachmentFormats; public uint AttachmentIntegerFormatMask; From 4933888a9da4fa2eae9971e14ad83971a921b9ea Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 12 May 2024 23:16:06 -0700 Subject: [PATCH 002/132] Make StencilOp, FrontFace and CullMode Dynamic States. Also prevent Vertex Input Binding Stride dynamic state from enabling with MoltenVK. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 84 +++++++++++++---- .../PipelineConverter.cs | 31 +++---- .../PipelineDynamicState.cs | 89 +++++++++++++++++-- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 69 ++++++++------ 4 files changed, 210 insertions(+), 63 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 918de59b7..0aee69732 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -84,6 +84,8 @@ namespace Ryujinx.Graphics.Vulkan private bool _tfEnabled; private bool _tfActive; + private bool _supportExtDynamic; + private readonly PipelineColorBlendAttachmentState[] _storedBlend; private ulong _drawCountSinceBarrier; @@ -122,6 +124,8 @@ namespace Ryujinx.Graphics.Vulkan _storedBlend = new PipelineColorBlendAttachmentState[Constants.MaxRenderTargets]; + _supportExtDynamic = gd.Capabilities.SupportsExtendedDynamicState; + _newState.Initialize(); } @@ -685,7 +689,7 @@ namespace Ryujinx.Graphics.Vulkan { if (texture is TextureView srcTexture) { - var oldCullMode = _newState.CullMode; + var oldCullMode = _supportExtDynamic ? DynamicState.CullMode : _newState.CullMode; var oldStencilTestEnable = _newState.StencilTestEnable; var oldDepthTestEnable = _newState.DepthTestEnable; var oldDepthWriteEnable = _newState.DepthWriteEnable; @@ -693,7 +697,15 @@ namespace Ryujinx.Graphics.Vulkan var oldViewports = DynamicState.Viewports; var oldViewportsCount = _newState.ViewportsCount; - _newState.CullMode = CullModeFlags.None; + if (_supportExtDynamic) + { + DynamicState.SetCullMode(CullModeFlags.None); + } + else + { + _newState.CullMode = CullModeFlags.None; + } + _newState.StencilTestEnable = false; _newState.DepthTestEnable = false; _newState.DepthWriteEnable = false; @@ -707,7 +719,15 @@ namespace Ryujinx.Graphics.Vulkan srcRegion, dstRegion); - _newState.CullMode = oldCullMode; + if (_supportExtDynamic) + { + DynamicState.SetCullMode(oldCullMode); + } + else + { + _newState.CullMode = oldCullMode; + } + _newState.StencilTestEnable = oldStencilTestEnable; _newState.DepthTestEnable = oldDepthTestEnable; _newState.DepthWriteEnable = oldDepthWriteEnable; @@ -876,13 +896,29 @@ namespace Ryujinx.Graphics.Vulkan public void SetFaceCulling(bool enable, Face face) { - _newState.CullMode = enable ? face.Convert() : CullModeFlags.None; + if (_supportExtDynamic) + { + DynamicState.SetCullMode(enable ? face.Convert() : CullModeFlags.None); + } + else + { + _newState.CullMode = enable ? face.Convert() : CullModeFlags.None; + } + SignalStateChange(); } public void SetFrontFace(FrontFace frontFace) { - _newState.FrontFace = frontFace.Convert(); + if (_supportExtDynamic) + { + DynamicState.SetFrontFace(frontFace.Convert()); + } + else + { + _newState.FrontFace = frontFace.Convert(); + } + SignalStateChange(); } @@ -1112,23 +1148,39 @@ namespace Ryujinx.Graphics.Vulkan public void SetStencilTest(StencilTestDescriptor stencilTest) { - DynamicState.SetStencilMasks( - (uint)stencilTest.BackFuncMask, + if (Gd.Capabilities.SupportsExtendedDynamicState) + { + DynamicState.SetStencilOp( + stencilTest.BackSFail.Convert(), + stencilTest.BackDpPass.Convert(), + stencilTest.BackDpFail.Convert(), + stencilTest.BackFunc.Convert(), + stencilTest.FrontSFail.Convert(), + stencilTest.FrontDpPass.Convert(), + stencilTest.FrontDpFail.Convert(), + stencilTest.FrontFunc.Convert()); + } + else + { + _newState.StencilBackFailOp = stencilTest.BackSFail.Convert(); + _newState.StencilBackPassOp = stencilTest.BackDpPass.Convert(); + _newState.StencilBackDepthFailOp = stencilTest.BackDpFail.Convert(); + _newState.StencilBackCompareOp = stencilTest.BackFunc.Convert(); + _newState.StencilFrontFailOp = stencilTest.FrontSFail.Convert(); + _newState.StencilFrontPassOp = stencilTest.FrontDpPass.Convert(); + _newState.StencilFrontDepthFailOp = stencilTest.FrontDpFail.Convert(); + _newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert(); + } + + _newState.StencilTestEnable = stencilTest.TestEnable; + + DynamicState.SetStencilMask((uint)stencilTest.BackFuncMask, (uint)stencilTest.BackMask, (uint)stencilTest.BackFuncRef, (uint)stencilTest.FrontFuncMask, (uint)stencilTest.FrontMask, (uint)stencilTest.FrontFuncRef); - _newState.StencilTestEnable = stencilTest.TestEnable; - _newState.StencilBackFailOp = stencilTest.BackSFail.Convert(); - _newState.StencilBackPassOp = stencilTest.BackDpPass.Convert(); - _newState.StencilBackDepthFailOp = stencilTest.BackDpFail.Convert(); - _newState.StencilBackCompareOp = stencilTest.BackFunc.Convert(); - _newState.StencilFrontFailOp = stencilTest.FrontSFail.Convert(); - _newState.StencilFrontPassOp = stencilTest.FrontDpPass.Convert(); - _newState.StencilFrontDepthFailOp = stencilTest.FrontDpFail.Convert(); - _newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert(); SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index ad2c7f866..1a7cba1e5 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -161,9 +161,6 @@ namespace Ryujinx.Graphics.Vulkan pipeline.Initialize(); // It is assumed that Dynamic State is enabled when this conversion is used. - - pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None; - pipeline.DepthBoundsTestEnable = false; // Not implemented. pipeline.DepthClampEnable = state.DepthClampEnable; @@ -172,9 +169,7 @@ namespace Ryujinx.Graphics.Vulkan pipeline.DepthWriteEnable = state.DepthTest.WriteEnable; pipeline.DepthCompareOp = state.DepthTest.Func.Convert(); pipeline.DepthMode = state.DepthMode == DepthMode.MinusOneToOne; - - pipeline.FrontFace = state.FrontFace.Convert(); - + pipeline.HasDepthStencil = state.DepthStencilEnable; pipeline.LineWidth = state.LineWidth; pipeline.LogicOpEnable = state.LogicOpEnable; @@ -203,16 +198,22 @@ namespace Ryujinx.Graphics.Vulkan pipeline.DepthBiasEnable = state.BiasEnable != 0; // Stencil masks and ref are dynamic, so are 0 in the Vulkan pipeline. + if (!gd.Capabilities.SupportsExtendedDynamicState) + { + pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None; + + pipeline.FrontFace = state.FrontFace.Convert(); + + pipeline.StencilFrontFailOp = state.StencilTest.FrontSFail.Convert(); + pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert(); + pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert(); + pipeline.StencilFrontCompareOp = state.StencilTest.FrontFunc.Convert(); - pipeline.StencilFrontFailOp = state.StencilTest.FrontSFail.Convert(); - pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert(); - pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert(); - pipeline.StencilFrontCompareOp = state.StencilTest.FrontFunc.Convert(); - - pipeline.StencilBackFailOp = state.StencilTest.BackSFail.Convert(); - pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert(); - pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert(); - pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert(); + pipeline.StencilBackFailOp = state.StencilTest.BackSFail.Convert(); + pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert(); + pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert(); + pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert(); + } pipeline.StencilTestEnable = state.StencilTest.TestEnable; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 1cc33f728..31eb64d80 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -1,5 +1,6 @@ using Ryujinx.Common.Memory; using Silk.NET.Vulkan; +using System; namespace Ryujinx.Graphics.Vulkan { @@ -18,12 +19,25 @@ namespace Ryujinx.Graphics.Vulkan private uint _frontCompareMask; private uint _frontWriteMask; private uint _frontReference; + private bool _opToo; + private StencilOp _backfailop; + private StencilOp _backpassop; + private StencilOp _backdepthfailop; + private CompareOp _backcompareop; + private StencilOp _frontfailop; + private StencilOp _frontpassop; + private StencilOp _frontdepthfailop; + private CompareOp _frontcompareop; private Array4 _blendConstants; public uint ViewportsCount; public Array16 Viewports; + public CullModeFlags CullMode; + public FrontFace FrontFace; + + [Flags] private enum DirtyFlags { None = 0, @@ -32,7 +46,9 @@ namespace Ryujinx.Graphics.Vulkan Scissor = 1 << 2, Stencil = 1 << 3, Viewport = 1 << 4, - All = Blend | DepthBias | Scissor | Stencil | Viewport, + CullMode = 1 << 5, + FrontFace = 1 << 6, + All = Blend | DepthBias | Scissor | Stencil | Viewport | CullMode | FrontFace, } private DirtyFlags _dirty; @@ -63,7 +79,7 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.Scissor; } - public void SetStencilMasks( + public void SetStencilMask( uint backCompareMask, uint backWriteMask, uint backReference, @@ -80,6 +96,27 @@ 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) + { + _backfailop = backFailOp; + _backpassop = backPassOp; + _backdepthfailop = backDepthFailOp; + _backcompareop = backCompareOp; + + _frontfailop = frontFailOp; + _frontpassop = frontPassOp; + _frontdepthfailop = frontDepthFailOp; + _frontcompareop = frontCompareOp; + _opToo = true; + } public void SetViewport(int index, Viewport viewport) { @@ -98,6 +135,20 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.Viewport; } } + + public void SetCullMode(CullModeFlags cullMode) + { + CullMode = cullMode; + + _dirty |= DirtyFlags.CullMode; + } + + public void SetFrontFace(FrontFace frontFace) + { + FrontFace = frontFace; + + _dirty |= DirtyFlags.FrontFace; + } public void ForceAllDirty() { @@ -123,13 +174,23 @@ namespace Ryujinx.Graphics.Vulkan if (_dirty.HasFlag(DirtyFlags.Stencil)) { - RecordStencilMasks(api, commandBuffer); + RecordStencil(api, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.Viewport)) { RecordViewport(api, commandBuffer); } + + if (_dirty.HasFlag(DirtyFlags.CullMode)) + { + RecordCullMode(api, commandBuffer); + } + + if (_dirty.HasFlag(DirtyFlags.FrontFace)) + { + RecordFrontFace(api, commandBuffer); + } _dirty = DirtyFlags.None; } @@ -151,9 +212,17 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan()); } } - - private readonly void RecordStencilMasks(Vk api, CommandBuffer commandBuffer) + + private readonly void RecordStencil(Vk api, CommandBuffer commandBuffer) { + if (_opToo) + { + api.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceBackBit, _backfailop, _backpassop, + _backdepthfailop, _backcompareop); + api.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontfailop, _frontpassop, + _frontdepthfailop, _frontcompareop); + } + api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backCompareMask); api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backWriteMask); api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceBackBit, _backReference); @@ -169,5 +238,15 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan()); } } + + private void RecordCullMode(Vk api, CommandBuffer commandBuffer) + { + api.CmdSetCullMode(commandBuffer, CullMode); + } + + private void RecordFrontFace(Vk api, CommandBuffer commandBuffer) + { + api.CmdSetFrontFace(commandBuffer, FrontFace); + } } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index a22f137d4..24586800e 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -404,6 +404,8 @@ namespace Ryujinx.Graphics.Vulkan { UpdateVertexAttributeDescriptions(gd); } + + bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState; fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0]) fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions2 = &_vertexAttributeDescriptions2[0]) @@ -467,11 +469,15 @@ namespace Ryujinx.Graphics.Vulkan RasterizerDiscardEnable = RasterizerDiscardEnable, PolygonMode = PolygonMode, LineWidth = LineWidth, - CullMode = CullMode, - FrontFace = FrontFace, DepthBiasEnable = DepthBiasEnable, }; + if (!supportsExtDynamicState) + { + rasterizationState.CullMode = CullMode; + rasterizationState.FrontFace = FrontFace; + } + var viewportState = new PipelineViewportStateCreateInfo { SType = StructureType.PipelineViewportStateCreateInfo, @@ -500,24 +506,6 @@ namespace Ryujinx.Graphics.Vulkan AlphaToOneEnable = AlphaToOneEnable, }; - var stencilFront = new StencilOpState( - StencilFrontFailOp, - StencilFrontPassOp, - StencilFrontDepthFailOp, - StencilFrontCompareOp, - null, - null, - null); - - var stencilBack = new StencilOpState( - StencilBackFailOp, - StencilBackPassOp, - StencilBackDepthFailOp, - StencilBackCompareOp, - null, - null, - null); - var depthStencilState = new PipelineDepthStencilStateCreateInfo { SType = StructureType.PipelineDepthStencilStateCreateInfo, @@ -526,15 +514,37 @@ namespace Ryujinx.Graphics.Vulkan DepthCompareOp = DepthCompareOp, DepthBoundsTestEnable = DepthBoundsTestEnable, StencilTestEnable = StencilTestEnable, - Front = stencilFront, - Back = stencilBack, MinDepthBounds = MinDepthBounds, MaxDepthBounds = MaxDepthBounds, }; + + if (!supportsExtDynamicState) + { + var stencilFront = new StencilOpState( + StencilFrontFailOp, + StencilFrontPassOp, + StencilFrontDepthFailOp, + StencilFrontCompareOp, + null, + null, + null); + + var stencilBack = new StencilOpState( + StencilBackFailOp, + StencilBackPassOp, + StencilBackDepthFailOp, + StencilBackCompareOp, + null, + null, + null); + + depthStencilState.Front = stencilFront; + depthStencilState.Back = stencilBack; + } uint blendEnables = 0; - if (gd.IsMoltenVk && Internal.AttachmentIntegerFormatMask != 0) + if (isMoltenVk && Internal.AttachmentIntegerFormatMask != 0) { // Blend can't be enabled for integer formats, so let's make sure it is disabled. uint attachmentIntegerFormatMask = Internal.AttachmentIntegerFormatMask; @@ -582,9 +592,8 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.PNext = &colorBlendAdvancedState; } - - bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState; - int dynamicStatesCount = supportsExtDynamicState ? 8 : 7; + + int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 10 : 11) : 7; DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount]; @@ -598,7 +607,13 @@ namespace Ryujinx.Graphics.Vulkan if (supportsExtDynamicState) { - dynamicStates[7] = DynamicState.VertexInputBindingStrideExt; + int index = 7; + if (!isMoltenVk) { + dynamicStates[index++] = DynamicState.VertexInputBindingStrideExt; + } + dynamicStates[index++] = DynamicState.CullMode; + dynamicStates[index++] = DynamicState.FrontFace; + dynamicStates[index] = DynamicState.StencilOp; } var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo From 5f02e280170818cf4668a7d2b1b0a18b2f87dfcd Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 12 May 2024 23:57:40 -0700 Subject: [PATCH 003/132] More Dynamic States --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 44 ++++--- .../PipelineDynamicState.cs | 107 ++++++++++++++---- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 14 ++- 3 files changed, 125 insertions(+), 40 deletions(-) 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; } From 24e6105e6fda830ce9753c724d0b96ce1ca80560 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 13 May 2024 00:18:20 -0700 Subject: [PATCH 004/132] Primitive Topolgy DynamicState maybe causing performance degredation. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 18 ++++++++++----- .../PipelineConverter.cs | 19 ++++++++-------- .../PipelineDynamicState.cs | 22 +++++++++++++++++-- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 9 ++++++-- 4 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 096627e0b..3c67d952a 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -693,7 +693,7 @@ namespace Ryujinx.Graphics.Vulkan 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 oldTopology = _supportExtDynamic ? DynamicState. Topology : _newState.Topology; var oldViewports = DynamicState.Viewports; var oldViewportsCount = _newState.ViewportsCount; @@ -726,6 +726,7 @@ namespace Ryujinx.Graphics.Vulkan DynamicState.SetCullMode(oldCullMode); DynamicState.SetStencilTest(oldStencilTestEnable); DynamicState.SetDepthTestBool(oldDepthTestEnable, oldDepthWriteEnable); + DynamicState.SetPrimitiveTopology(ref oldTopology); } else { @@ -733,9 +734,8 @@ namespace Ryujinx.Graphics.Vulkan _newState.StencilTestEnable = oldStencilTestEnable; _newState.DepthTestEnable = oldDepthTestEnable; _newState.DepthWriteEnable = oldDepthWriteEnable; + _newState.Topology = oldTopology; } - - _newState.Topology = oldTopology; DynamicState.SetViewports(ref oldViewports, oldViewportsCount); @@ -1019,9 +1019,15 @@ namespace Ryujinx.Graphics.Vulkan _topology = topology; var vkTopology = Gd.TopologyRemap(topology).Convert(); - - _newState.Topology = vkTopology; - + if (_supportExtDynamic) + { + DynamicState.SetPrimitiveTopology(ref vkTopology); + } + else + { + _newState.Topology = vkTopology; + } + SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 1a7cba1e5..d0344ee4b 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -164,10 +164,7 @@ namespace Ryujinx.Graphics.Vulkan pipeline.DepthBoundsTestEnable = false; // Not implemented. pipeline.DepthClampEnable = state.DepthClampEnable; - - pipeline.DepthTestEnable = state.DepthTest.TestEnable; - pipeline.DepthWriteEnable = state.DepthTest.WriteEnable; - pipeline.DepthCompareOp = state.DepthTest.Func.Convert(); + pipeline.DepthMode = state.DepthMode == DepthMode.MinusOneToOne; pipeline.HasDepthStencil = state.DepthStencilEnable; @@ -200,6 +197,10 @@ namespace Ryujinx.Graphics.Vulkan // Stencil masks and ref are dynamic, so are 0 in the Vulkan pipeline. if (!gd.Capabilities.SupportsExtendedDynamicState) { + pipeline.DepthTestEnable = state.DepthTest.TestEnable; + pipeline.DepthWriteEnable = state.DepthTest.WriteEnable; + pipeline.DepthCompareOp = state.DepthTest.Func.Convert(); + pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None; pipeline.FrontFace = state.FrontFace.Convert(); @@ -213,12 +214,12 @@ namespace Ryujinx.Graphics.Vulkan pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert(); pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert(); pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert(); + + pipeline.StencilTestEnable = state.StencilTest.TestEnable; + + pipeline.Topology = gd.TopologyRemap(state.Topology).Convert(); } - - pipeline.StencilTestEnable = state.StencilTest.TestEnable; - - pipeline.Topology = gd.TopologyRemap(state.Topology).Convert(); - + int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount); int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 7a1c39b04..916b065bd 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -36,6 +36,8 @@ namespace Ryujinx.Graphics.Vulkan public bool _depthwriteEnable; private CompareOp _depthCompareOp; + public PrimitiveTopology Topology; + private Array4 _blendConstants; public uint ViewportsCount; @@ -58,7 +60,8 @@ namespace Ryujinx.Graphics.Vulkan DepthTestBool = 1 << 7, DepthTestCompareOp = 1 << 8, StencilTestEnable = 1 << 9, - All = Blend | DepthBias | Scissor | Stencil | Viewport | CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable, + Toplogy = 1 << 10, + All = Blend | DepthBias | Scissor | Stencil | Viewport | CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable | Toplogy, } private DirtyFlags _dirty; @@ -103,8 +106,13 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.DepthTestCompareOp; } + + public void SetPrimitiveTopology(ref PrimitiveTopology topology) + { + Topology = topology; - + _dirty |= DirtyFlags.Toplogy; + } public void SetStencilOp(StencilOp backFailOp, StencilOp backPassOp, @@ -242,6 +250,11 @@ namespace Ryujinx.Graphics.Vulkan { RecordStencilTestEnable(api, commandBuffer); } + + if (_dirty.HasFlag(DirtyFlags.Toplogy)) + { + RecordPrimitiveTopology(api, commandBuffer); + } _dirty = DirtyFlags.None; } @@ -315,5 +328,10 @@ namespace Ryujinx.Graphics.Vulkan { api.CmdSetDepthCompareOp(commandBuffer, _depthCompareOp); } + + private void RecordPrimitiveTopology(Vk api, CommandBuffer commandBuffer) + { + api.CmdSetPrimitiveTopology(commandBuffer, Topology); + } } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 6182ccaa0..3dbc01f2d 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -453,9 +453,13 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.PipelineInputAssemblyStateCreateInfo, PrimitiveRestartEnable = primitiveRestartEnable, - Topology = Topology, }; + if (!supportsExtDynamicState) + { + inputAssemblyState.Topology = Topology; + } + var tessellationState = new PipelineTessellationStateCreateInfo { SType = StructureType.PipelineTessellationStateCreateInfo, @@ -593,7 +597,7 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.PNext = &colorBlendAdvancedState; } - int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 14 : 15) : 7; + int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 15 : 16) : 7; DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount]; @@ -617,6 +621,7 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[index++] = DynamicState.DepthWriteEnable; dynamicStates[index++] = DynamicState.DepthCompareOp; dynamicStates[index++] = DynamicState.StencilTestEnable; + dynamicStates[index++] = DynamicState.PrimitiveTopology; dynamicStates[index] = DynamicState.StencilOp; } From 07ac4192cd2761b13506a3a452864992917c5166 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 15 May 2024 00:30:22 -0700 Subject: [PATCH 005/132] Resolve MoltenVK (future version) warning. Flags are not set for deriving pipelines so remove unnecessary basePipelineIndex value. --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 3dbc01f2d..620ab291b 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -449,6 +449,13 @@ namespace Ryujinx.Graphics.Vulkan primitiveRestartEnable &= topologySupportsRestart; + if ((Topology == PrimitiveTopology.LineStrip || Topology == PrimitiveTopology.TriangleStrip || + Topology == PrimitiveTopology.LineStripWithAdjacency || + Topology == PrimitiveTopology.TriangleStripWithAdjacency) && isMoltenVk) + { + primitiveRestartEnable = true; + } + var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, @@ -648,7 +655,6 @@ namespace Ryujinx.Graphics.Vulkan PDynamicState = &pipelineDynamicStateCreateInfo, Layout = PipelineLayout, RenderPass = renderPass, - BasePipelineIndex = -1, }; Result result = gd.Api.CreateGraphicsPipelines(device, cache, 1, &pipelineCreateInfo, null, &pipelineHandle); From 5894ef043b90f7a41597cd141178ac41a17eab07 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 15 May 2024 00:54:08 -0700 Subject: [PATCH 006/132] No need to by reference --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 4 ++-- src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 3c67d952a..b49233834 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -726,7 +726,7 @@ namespace Ryujinx.Graphics.Vulkan DynamicState.SetCullMode(oldCullMode); DynamicState.SetStencilTest(oldStencilTestEnable); DynamicState.SetDepthTestBool(oldDepthTestEnable, oldDepthWriteEnable); - DynamicState.SetPrimitiveTopology(ref oldTopology); + DynamicState.SetPrimitiveTopology(oldTopology); } else { @@ -1021,7 +1021,7 @@ namespace Ryujinx.Graphics.Vulkan var vkTopology = Gd.TopologyRemap(topology).Convert(); if (_supportExtDynamic) { - DynamicState.SetPrimitiveTopology(ref vkTopology); + DynamicState.SetPrimitiveTopology(vkTopology); } else { diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 916b065bd..aaa97660a 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -107,7 +107,7 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.DepthTestCompareOp; } - public void SetPrimitiveTopology(ref PrimitiveTopology topology) + public void SetPrimitiveTopology(PrimitiveTopology topology) { Topology = topology; From 1befb5bd8fb2c5d80daf871ec524cd68b9d7749f Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Thu, 16 May 2024 12:48:03 -0700 Subject: [PATCH 007/132] Check if widelines is supported. --- .../HardwareCapabilities.cs | 3 +++ src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 3 ++- .../PipelineDynamicState.cs | 22 +++++++++++++++++- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 23 ++++++++++--------- .../VulkanInitialization.cs | 1 + src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 1 + 6 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs index b6694bcb3..8c7089aa5 100644 --- a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs +++ b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs @@ -46,6 +46,7 @@ namespace Ryujinx.Graphics.Vulkan public readonly bool SupportsViewportArray2; public readonly bool SupportsHostImportedMemory; public readonly bool SupportsDepthClipControl; + public readonly bool SupportsWideLines; public readonly uint SubgroupSize; public readonly SampleCountFlags SupportedSampleCounts; public readonly PortabilitySubsetFlags PortabilitySubset; @@ -84,6 +85,7 @@ namespace Ryujinx.Graphics.Vulkan bool supportsViewportArray2, bool supportsHostImportedMemory, bool supportsDepthClipControl, + bool supportsWideLines, uint subgroupSize, SampleCountFlags supportedSampleCounts, PortabilitySubsetFlags portabilitySubset, @@ -121,6 +123,7 @@ namespace Ryujinx.Graphics.Vulkan SupportsViewportArray2 = supportsViewportArray2; SupportsHostImportedMemory = supportsHostImportedMemory; SupportsDepthClipControl = supportsDepthClipControl; + SupportsWideLines = supportsWideLines; SubgroupSize = subgroupSize; SupportedSampleCounts = supportedSampleCounts; PortabilitySubset = portabilitySubset; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index b49233834..301718974 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -971,7 +971,8 @@ namespace Ryujinx.Graphics.Vulkan public void SetLineParameters(float width, bool smooth) { - _newState.LineWidth = width; + DynamicState.SetLineWidth(Gd.Capabilities.SupportsWideLines ? width : 1.0f); + SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index aaa97660a..b5af582da 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -29,6 +29,8 @@ namespace Ryujinx.Graphics.Vulkan private StencilOp _frontpassop; private StencilOp _frontdepthfailop; private CompareOp _frontcompareop; + + private float _linewidth; public bool _stencilTestEnable; @@ -61,7 +63,8 @@ namespace Ryujinx.Graphics.Vulkan DepthTestCompareOp = 1 << 8, StencilTestEnable = 1 << 9, Toplogy = 1 << 10, - All = Blend | DepthBias | Scissor | Stencil | Viewport | CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable | Toplogy, + LineWidth = 1 <<11, + All = Blend | DepthBias | Scissor | Stencil | Viewport | CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable | Toplogy | LineWidth, } private DirtyFlags _dirty; @@ -193,6 +196,13 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.FrontFace; } + + public void SetLineWidth(float width) + { + _linewidth = width; + + _dirty |= DirtyFlags.LineWidth; + } public void ForceAllDirty() { @@ -255,6 +265,11 @@ namespace Ryujinx.Graphics.Vulkan { RecordPrimitiveTopology(api, commandBuffer); } + + if (_dirty.HasFlag(DirtyFlags.LineWidth)) + { + RecordLineWidth(api, commandBuffer); + } _dirty = DirtyFlags.None; } @@ -333,5 +348,10 @@ namespace Ryujinx.Graphics.Vulkan { api.CmdSetPrimitiveTopology(commandBuffer, Topology); } + + private void RecordLineWidth(Vk api, CommandBuffer commandBuffer) + { + api.CmdSetLineWidth(commandBuffer, _linewidth); + } } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 620ab291b..ddfd39070 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -479,7 +479,6 @@ namespace Ryujinx.Graphics.Vulkan DepthClampEnable = DepthClampEnable, RasterizerDiscardEnable = RasterizerDiscardEnable, PolygonMode = PolygonMode, - LineWidth = LineWidth, DepthBiasEnable = DepthBiasEnable, }; @@ -604,7 +603,7 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.PNext = &colorBlendAdvancedState; } - int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 15 : 16) : 7; + int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 16 : 17) : 8; DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount]; @@ -615,21 +614,23 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[4] = DynamicState.StencilWriteMask; dynamicStates[5] = DynamicState.StencilReference; dynamicStates[6] = DynamicState.BlendConstants; + dynamicStates[7] = DynamicState.LineWidth; + if (supportsExtDynamicState) { - int index = 7; + int index = 8; if (!isMoltenVk) { dynamicStates[index++] = DynamicState.VertexInputBindingStrideExt; } - 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.PrimitiveTopology; - dynamicStates[index] = DynamicState.StencilOp; + dynamicStates[index++] = DynamicState.CullModeExt; + dynamicStates[index++] = DynamicState.FrontFaceExt; + dynamicStates[index++] = DynamicState.DepthTestEnableExt; + dynamicStates[index++] = DynamicState.DepthWriteEnableExt; + dynamicStates[index++] = DynamicState.DepthCompareOpExt; + dynamicStates[index++] = DynamicState.StencilTestEnableExt; + dynamicStates[index++] = DynamicState.PrimitiveTopologyExt; + dynamicStates[index] = DynamicState.StencilOpExt; } var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index d59ca7e0e..a8de50f6d 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -382,6 +382,7 @@ namespace Ryujinx.Graphics.Vulkan TessellationShader = supportedFeatures.TessellationShader, VertexPipelineStoresAndAtomics = supportedFeatures.VertexPipelineStoresAndAtomics, RobustBufferAccess = useRobustBufferAccess, + WideLines = supportedFeatures.WideLines, }; void* pExtendedFeatures = null; diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 86a347e01..e8dd766a0 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -397,6 +397,7 @@ namespace Ryujinx.Graphics.Vulkan _physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"), _physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName), supportsDepthClipControl && featuresDepthClipControl.DepthClipControl, + _physicalDevice.PhysicalDeviceFeatures.WideLines, propertiesSubgroup.SubgroupSize, supportedSampleCounts, portabilityFlags, From 506f25054df719d11043bb7ae9c71fbbdd80aa03 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Thu, 16 May 2024 19:09:40 -0700 Subject: [PATCH 008/132] LineWidth is not supported on MoltenVK --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 9 ++++--- .../PipelineDynamicState.cs | 24 +++++++++++++++---- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 14 ++++++++--- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 301718974..6881ba911 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -971,8 +971,11 @@ namespace Ryujinx.Graphics.Vulkan public void SetLineParameters(float width, bool smooth) { - DynamicState.SetLineWidth(Gd.Capabilities.SupportsWideLines ? width : 1.0f); - + if (!Gd.IsMoltenVk) + { + DynamicState.SetLineWidth(Gd.Capabilities.SupportsWideLines ? width : 1.0f); + } + SignalStateChange(); } @@ -1506,7 +1509,7 @@ namespace Ryujinx.Graphics.Vulkan _vertexBuffersDirty = ulong.MaxValue >> (64 - _vertexBuffers.Length); _descriptorSetUpdater.SignalCommandBufferChange(); - DynamicState.ForceAllDirty(); + DynamicState.ForceAllDirty(Gd); _currentPipelineHandle = 0; } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index b5af582da..9ec4bbb59 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -63,8 +63,9 @@ namespace Ryujinx.Graphics.Vulkan DepthTestCompareOp = 1 << 8, StencilTestEnable = 1 << 9, Toplogy = 1 << 10, - LineWidth = 1 <<11, - All = Blend | DepthBias | Scissor | Stencil | Viewport | CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable | Toplogy | LineWidth, + LineWidth = 1 << 11, + Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, + Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable | Toplogy, } private DirtyFlags _dirty; @@ -204,9 +205,19 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.LineWidth; } - public void ForceAllDirty() + public void ForceAllDirty(VulkanRenderer gd) { - _dirty = DirtyFlags.All; + _dirty = DirtyFlags.Standard; + + if (gd.Capabilities.SupportsExtendedDynamicState) + { + _dirty = DirtyFlags.Standard | DirtyFlags.Extended; + } + + if (gd.IsMoltenVk) + { + _dirty &= ~DirtyFlags.LineWidth; + } } public void ReplayIfDirty(Vk api, CommandBuffer commandBuffer) @@ -351,7 +362,10 @@ namespace Ryujinx.Graphics.Vulkan private void RecordLineWidth(Vk api, CommandBuffer commandBuffer) { - api.CmdSetLineWidth(commandBuffer, _linewidth); + if (!OperatingSystem.IsMacOS()) + { + api.CmdSetLineWidth(commandBuffer, _linewidth); + } } } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index ddfd39070..212062c69 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -482,6 +482,11 @@ namespace Ryujinx.Graphics.Vulkan DepthBiasEnable = DepthBiasEnable, }; + if (isMoltenVk) + { + rasterizationState.LineWidth = 1.0f; + } + if (!supportsExtDynamicState) { rasterizationState.CullMode = CullMode; @@ -603,7 +608,7 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.PNext = &colorBlendAdvancedState; } - int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 16 : 17) : 8; + int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 16 : 17) : (isMoltenVk ? 7 : 8); DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount]; @@ -614,8 +619,11 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[4] = DynamicState.StencilWriteMask; dynamicStates[5] = DynamicState.StencilReference; dynamicStates[6] = DynamicState.BlendConstants; - dynamicStates[7] = DynamicState.LineWidth; - + + if(!isMoltenVk) + { + dynamicStates[7] = DynamicState.LineWidth; + } if (supportsExtDynamicState) { From e7fbc9a1bedd3bc1a510eff8af8bc52e8eb02c97 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Thu, 16 May 2024 21:22:43 -0700 Subject: [PATCH 009/132] Use Correct namespace --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 +- .../PipelineDynamicState.cs | 39 ++++++++++--------- src/Ryujinx.Graphics.Vulkan/PipelineFull.cs | 2 +- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 6881ba911..6b4024911 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1645,7 +1645,7 @@ namespace Ryujinx.Graphics.Vulkan Gd.FlushAllCommands(); } - DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer); + DynamicState.ReplayIfDirty(Gd, CommandBuffer); if (_needsIndexBufferRebind && _indexBufferPattern == null) { diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 9ec4bbb59..9b549ebc1 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -1,5 +1,6 @@ using Ryujinx.Common.Memory; using Silk.NET.Vulkan; +using Silk.NET.Vulkan.Extensions.EXT; using System; namespace Ryujinx.Graphics.Vulkan @@ -220,66 +221,66 @@ namespace Ryujinx.Graphics.Vulkan } } - public void ReplayIfDirty(Vk api, CommandBuffer commandBuffer) + public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) { if (_dirty.HasFlag(DirtyFlags.Blend)) { - RecordBlend(api, commandBuffer); + RecordBlend(gd.Api, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.DepthBias)) { - RecordDepthBias(api, commandBuffer); + RecordDepthBias(gd.Api, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.Scissor)) { - RecordScissor(api, commandBuffer); + RecordScissor(gd.Api, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.Stencil)) { - RecordStencil(api, commandBuffer); + RecordStencil(gd.Api, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.Viewport)) { - RecordViewport(api, commandBuffer); + RecordViewport(gd.Api, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.CullMode)) { - RecordCullMode(api, commandBuffer); + RecordCullMode(gd.ExtendedDynamicStateApi, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.FrontFace)) { - RecordFrontFace(api, commandBuffer); + RecordFrontFace(gd.ExtendedDynamicStateApi, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.DepthTestBool)) { - RecordDepthTestBool(api, commandBuffer); + RecordDepthTestBool(gd.ExtendedDynamicStateApi, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.DepthTestCompareOp)) { - RecordDepthTestCompareOp(api, commandBuffer); + RecordDepthTestCompareOp(gd.ExtendedDynamicStateApi, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.StencilTestEnable)) { - RecordStencilTestEnable(api, commandBuffer); + RecordStencilTestEnable(gd.ExtendedDynamicStateApi, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.Toplogy)) { - RecordPrimitiveTopology(api, commandBuffer); + RecordPrimitiveTopology(gd.ExtendedDynamicStateApi, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.LineWidth)) { - RecordLineWidth(api, commandBuffer); + RecordLineWidth(gd.Api, commandBuffer); } _dirty = DirtyFlags.None; @@ -321,7 +322,7 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference); } - private readonly void RecordStencilTestEnable(Vk api, CommandBuffer commandBuffer) + private readonly void RecordStencilTestEnable(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetStencilTestEnable(commandBuffer, _stencilTestEnable); } @@ -334,28 +335,28 @@ namespace Ryujinx.Graphics.Vulkan } } - private void RecordCullMode(Vk api, CommandBuffer commandBuffer) + private void RecordCullMode(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetCullMode(commandBuffer, CullMode); } - private void RecordFrontFace(Vk api, CommandBuffer commandBuffer) + private void RecordFrontFace(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetFrontFace(commandBuffer, FrontFace); } - private void RecordDepthTestBool(Vk api, CommandBuffer commandBuffer) + private void RecordDepthTestBool(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetDepthTestEnable(commandBuffer, _depthtestEnable); api.CmdSetDepthWriteEnable(commandBuffer, _depthwriteEnable); } - private void RecordDepthTestCompareOp(Vk api, CommandBuffer commandBuffer) + private void RecordDepthTestCompareOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetDepthCompareOp(commandBuffer, _depthCompareOp); } - private void RecordPrimitiveTopology(Vk api, CommandBuffer commandBuffer) + private void RecordPrimitiveTopology(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetPrimitiveTopology(commandBuffer, Topology); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs b/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs index 357d517eb..73d5a088a 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs @@ -233,7 +233,7 @@ namespace Ryujinx.Graphics.Vulkan if (Pipeline != null && Pbp == PipelineBindPoint.Graphics) { - DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer); + DynamicState.ReplayIfDirty(Gd, CommandBuffer); } } From eaedc3ec9eed1a8610260cd6a446f1b87e204266 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Thu, 16 May 2024 22:18:47 -0700 Subject: [PATCH 010/132] Use Viewport and Scissor with count. Topology Dynamic State is not working as intended. Need to add check to set correct Topology class. Circle back to this later. For now revert it. Some minor fixes. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 27 +++--- .../PipelineDynamicState.cs | 82 ++++++++++--------- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 25 +++--- src/Ryujinx/UI/Helpers/LoggerAdapter.cs | 12 +-- 4 files changed, 73 insertions(+), 73 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 6b4024911..0425d17bd 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -693,9 +693,9 @@ namespace Ryujinx.Graphics.Vulkan var oldStencilTestEnable = _supportExtDynamic ? DynamicState._stencilTestEnable : _newState.StencilTestEnable; var oldDepthTestEnable = _supportExtDynamic ? DynamicState._depthtestEnable : _newState.DepthTestEnable; var oldDepthWriteEnable = _supportExtDynamic ? DynamicState._depthwriteEnable : _newState.DepthWriteEnable; - var oldTopology = _supportExtDynamic ? DynamicState. Topology : _newState.Topology; + var oldTopology = _newState.Topology; var oldViewports = DynamicState.Viewports; - var oldViewportsCount = _newState.ViewportsCount; + var oldViewportsCount = _supportExtDynamic ? DynamicState.ViewportsCount : _newState.ViewportsCount; if (_supportExtDynamic) { @@ -726,7 +726,6 @@ namespace Ryujinx.Graphics.Vulkan DynamicState.SetCullMode(oldCullMode); DynamicState.SetStencilTest(oldStencilTestEnable); DynamicState.SetDepthTestBool(oldDepthTestEnable, oldDepthWriteEnable); - DynamicState.SetPrimitiveTopology(oldTopology); } else { @@ -734,12 +733,13 @@ namespace Ryujinx.Graphics.Vulkan _newState.StencilTestEnable = oldStencilTestEnable; _newState.DepthTestEnable = oldDepthTestEnable; _newState.DepthWriteEnable = oldDepthWriteEnable; - _newState.Topology = oldTopology; + _newState.ViewportsCount = oldViewportsCount; } + + _newState.Topology = oldTopology; DynamicState.SetViewports(ref oldViewports, oldViewportsCount); - _newState.ViewportsCount = oldViewportsCount; SignalStateChange(); } } @@ -1023,14 +1023,8 @@ namespace Ryujinx.Graphics.Vulkan _topology = topology; var vkTopology = Gd.TopologyRemap(topology).Convert(); - if (_supportExtDynamic) - { - DynamicState.SetPrimitiveTopology(vkTopology); - } - else - { - _newState.Topology = vkTopology; - } + + _newState.Topology = vkTopology; SignalStateChange(); } @@ -1441,8 +1435,11 @@ namespace Ryujinx.Graphics.Vulkan Clamp(viewport.DepthNear), Clamp(viewport.DepthFar))); } - - _newState.ViewportsCount = (uint)count; + + if (!_supportExtDynamic) + { + _newState.ViewportsCount = (uint)count; + } SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 9b549ebc1..b6bb954fb 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -38,9 +38,7 @@ namespace Ryujinx.Graphics.Vulkan public bool _depthtestEnable; public bool _depthwriteEnable; private CompareOp _depthCompareOp; - - public PrimitiveTopology Topology; - + private Array4 _blendConstants; public uint ViewportsCount; @@ -63,10 +61,9 @@ namespace Ryujinx.Graphics.Vulkan DepthTestBool = 1 << 7, DepthTestCompareOp = 1 << 8, StencilTestEnable = 1 << 9, - Toplogy = 1 << 10, - LineWidth = 1 << 11, + LineWidth = 1 << 10, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, - Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable | Toplogy, + Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable, } private DirtyFlags _dirty; @@ -112,13 +109,6 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.DepthTestCompareOp; } - public void SetPrimitiveTopology(PrimitiveTopology topology) - { - Topology = topology; - - _dirty |= DirtyFlags.Toplogy; - } - public void SetStencilOp(StencilOp backFailOp, StencilOp backPassOp, StencilOp backDepthFailOp, @@ -235,17 +225,17 @@ namespace Ryujinx.Graphics.Vulkan if (_dirty.HasFlag(DirtyFlags.Scissor)) { - RecordScissor(gd.Api, commandBuffer); + RecordScissor(gd, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.Stencil)) { - RecordStencil(gd.Api, commandBuffer); + RecordStencil(gd, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.Viewport)) { - RecordViewport(gd.Api, commandBuffer); + RecordViewport(gd, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.CullMode)) @@ -273,11 +263,6 @@ namespace Ryujinx.Graphics.Vulkan RecordStencilTestEnable(gd.ExtendedDynamicStateApi, commandBuffer); } - if (_dirty.HasFlag(DirtyFlags.Toplogy)) - { - RecordPrimitiveTopology(gd.ExtendedDynamicStateApi, commandBuffer); - } - if (_dirty.HasFlag(DirtyFlags.LineWidth)) { RecordLineWidth(gd.Api, commandBuffer); @@ -296,30 +281,40 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); } - private void RecordScissor(Vk api, CommandBuffer commandBuffer) + private void RecordScissor(VulkanRenderer gd, CommandBuffer commandBuffer) { if (ScissorsCount != 0) { - api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan()); + if (gd.Capabilities.SupportsExtendedDynamicState) + { + + gd.ExtendedDynamicStateApi.CmdSetScissorWithCount(commandBuffer, (uint)ScissorsCount, + _scissors.AsSpan()); + } + else + { + gd.Api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, + _scissors.AsSpan()); + } } } - private readonly void RecordStencil(Vk api, CommandBuffer commandBuffer) + private readonly void RecordStencil(VulkanRenderer gd, CommandBuffer commandBuffer) { if (_opToo) { - api.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceBackBit, _backfailop, _backpassop, + gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceBackBit, _backfailop, _backpassop, _backdepthfailop, _backcompareop); - api.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontfailop, _frontpassop, + gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontfailop, _frontpassop, _frontdepthfailop, _frontcompareop); } - api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backCompareMask); - api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backWriteMask); - api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceBackBit, _backReference); - api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontCompareMask); - api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontWriteMask); - api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference); + gd.Api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backCompareMask); + gd.Api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backWriteMask); + gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceBackBit, _backReference); + gd.Api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontCompareMask); + gd.Api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontWriteMask); + gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference); } private readonly void RecordStencilTestEnable(ExtExtendedDynamicState api, CommandBuffer commandBuffer) @@ -327,11 +322,23 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetStencilTestEnable(commandBuffer, _stencilTestEnable); } - private void RecordViewport(Vk api, CommandBuffer commandBuffer) + private void RecordViewport(VulkanRenderer gd, CommandBuffer commandBuffer) { - if (ViewportsCount != 0) + if (ViewportsCount == 0) { - api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan()); + return; + } + + if (gd.Capabilities.SupportsExtendedDynamicState) + { + + gd.ExtendedDynamicStateApi.CmdSetViewportWithCount(commandBuffer, ViewportsCount, + Viewports.AsSpan()); + } + else + { + gd.Api.CmdSetViewport(commandBuffer, 0, ViewportsCount, + Viewports.AsSpan()); } } @@ -356,11 +363,6 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetDepthCompareOp(commandBuffer, _depthCompareOp); } - private void RecordPrimitiveTopology(ExtExtendedDynamicState api, CommandBuffer commandBuffer) - { - api.CmdSetPrimitiveTopology(commandBuffer, Topology); - } - private void RecordLineWidth(Vk api, CommandBuffer commandBuffer) { if (!OperatingSystem.IsMacOS()) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 212062c69..f7a63a5da 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -455,18 +455,14 @@ namespace Ryujinx.Graphics.Vulkan { primitiveRestartEnable = true; } - + var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, PrimitiveRestartEnable = primitiveRestartEnable, + Topology = Topology, }; - if (!supportsExtDynamicState) - { - inputAssemblyState.Topology = Topology; - } - var tessellationState = new PipelineTessellationStateCreateInfo { SType = StructureType.PipelineTessellationStateCreateInfo, @@ -492,13 +488,17 @@ namespace Ryujinx.Graphics.Vulkan rasterizationState.CullMode = CullMode; rasterizationState.FrontFace = FrontFace; } - + var viewportState = new PipelineViewportStateCreateInfo { SType = StructureType.PipelineViewportStateCreateInfo, - ViewportCount = ViewportsCount, - ScissorCount = ScissorsCount, }; + + if (!supportsExtDynamicState) + { + viewportState.ViewportCount = ViewportsCount; + viewportState.ScissorCount = ScissorsCount; + } if (gd.Capabilities.SupportsDepthClipControl) { @@ -608,7 +608,7 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.PNext = &colorBlendAdvancedState; } - int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 16 : 17) : (isMoltenVk ? 7 : 8); + int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 17 : 18) : (isMoltenVk ? 7 : 8); DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount]; @@ -627,7 +627,7 @@ namespace Ryujinx.Graphics.Vulkan if (supportsExtDynamicState) { - int index = 8; + int index = (isMoltenVk ? 7 : 8); if (!isMoltenVk) { dynamicStates[index++] = DynamicState.VertexInputBindingStrideExt; } @@ -637,7 +637,8 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[index++] = DynamicState.DepthWriteEnableExt; dynamicStates[index++] = DynamicState.DepthCompareOpExt; dynamicStates[index++] = DynamicState.StencilTestEnableExt; - dynamicStates[index++] = DynamicState.PrimitiveTopologyExt; + dynamicStates[index++] = DynamicState.ViewportWithCountExt; + dynamicStates[index++] = DynamicState.ScissorWithCountExt; dynamicStates[index] = DynamicState.StencilOpExt; } diff --git a/src/Ryujinx/UI/Helpers/LoggerAdapter.cs b/src/Ryujinx/UI/Helpers/LoggerAdapter.cs index fc7145410..b2fffd6c8 100644 --- a/src/Ryujinx/UI/Helpers/LoggerAdapter.cs +++ b/src/Ryujinx/UI/Helpers/LoggerAdapter.cs @@ -22,12 +22,12 @@ namespace Ryujinx.Ava.UI.Helpers { return level switch { - AvaLogLevel.Verbose => RyuLogger.Debug, - AvaLogLevel.Debug => RyuLogger.Debug, - AvaLogLevel.Information => RyuLogger.Debug, - AvaLogLevel.Warning => RyuLogger.Debug, - AvaLogLevel.Error => RyuLogger.Error, - AvaLogLevel.Fatal => RyuLogger.Error, + AvaLogLevel.Verbose => RyuLogger.Trace, + AvaLogLevel.Debug => RyuLogger.Trace, + AvaLogLevel.Information => RyuLogger.Trace, + AvaLogLevel.Warning => RyuLogger.Trace, + AvaLogLevel.Error => RyuLogger.Trace, + AvaLogLevel.Fatal => RyuLogger.Trace, _ => throw new ArgumentOutOfRangeException(nameof(level), level, null), }; } From 398ca7ad82eff68ca3c9fd6a01cf57f0d5279eff Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Thu, 16 May 2024 22:20:06 -0700 Subject: [PATCH 011/132] Revert unrelated changes. --- src/Ryujinx/UI/Helpers/LoggerAdapter.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Ryujinx/UI/Helpers/LoggerAdapter.cs b/src/Ryujinx/UI/Helpers/LoggerAdapter.cs index b2fffd6c8..fc7145410 100644 --- a/src/Ryujinx/UI/Helpers/LoggerAdapter.cs +++ b/src/Ryujinx/UI/Helpers/LoggerAdapter.cs @@ -22,12 +22,12 @@ namespace Ryujinx.Ava.UI.Helpers { return level switch { - AvaLogLevel.Verbose => RyuLogger.Trace, - AvaLogLevel.Debug => RyuLogger.Trace, - AvaLogLevel.Information => RyuLogger.Trace, - AvaLogLevel.Warning => RyuLogger.Trace, - AvaLogLevel.Error => RyuLogger.Trace, - AvaLogLevel.Fatal => RyuLogger.Trace, + AvaLogLevel.Verbose => RyuLogger.Debug, + AvaLogLevel.Debug => RyuLogger.Debug, + AvaLogLevel.Information => RyuLogger.Debug, + AvaLogLevel.Warning => RyuLogger.Debug, + AvaLogLevel.Error => RyuLogger.Error, + AvaLogLevel.Fatal => RyuLogger.Error, _ => throw new ArgumentOutOfRangeException(nameof(level), level, null), }; } From cee5ae5551c3142e76a00f0ba73a907fe7764d68 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Thu, 16 May 2024 22:59:37 -0700 Subject: [PATCH 012/132] Some missed values --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 5 +++- .../PipelineConverter.cs | 27 +++++++++---------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 0425d17bd..0fee64770 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1159,7 +1159,10 @@ namespace Ryujinx.Graphics.Vulkan DynamicState.ScissorsCount = count; - _newState.ScissorsCount = (uint)count; + if (!_supportExtDynamic) + { + _newState.ScissorsCount = (uint)count; + } SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index d0344ee4b..9bc16b4de 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -168,7 +168,6 @@ namespace Ryujinx.Graphics.Vulkan pipeline.DepthMode = state.DepthMode == DepthMode.MinusOneToOne; pipeline.HasDepthStencil = state.DepthStencilEnable; - pipeline.LineWidth = state.LineWidth; pipeline.LogicOpEnable = state.LogicOpEnable; pipeline.LogicOp = state.LogicOp.Convert(); @@ -181,17 +180,6 @@ namespace Ryujinx.Graphics.Vulkan pipeline.RasterizerDiscardEnable = state.RasterizerDiscard; pipeline.SamplesCount = (uint)state.SamplesCount; - if (gd.Capabilities.SupportsMultiView) - { - pipeline.ScissorsCount = Constants.MaxViewports; - pipeline.ViewportsCount = Constants.MaxViewports; - } - else - { - pipeline.ScissorsCount = 1; - pipeline.ViewportsCount = 1; - } - pipeline.DepthBiasEnable = state.BiasEnable != 0; // Stencil masks and ref are dynamic, so are 0 in the Vulkan pipeline. @@ -205,6 +193,17 @@ namespace Ryujinx.Graphics.Vulkan pipeline.FrontFace = state.FrontFace.Convert(); + if (gd.Capabilities.SupportsMultiView) + { + pipeline.ScissorsCount = Constants.MaxViewports; + pipeline.ViewportsCount = Constants.MaxViewports; + } + else + { + pipeline.ScissorsCount = 1; + pipeline.ViewportsCount = 1; + } + pipeline.StencilFrontFailOp = state.StencilTest.FrontSFail.Convert(); pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert(); pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert(); @@ -216,10 +215,10 @@ namespace Ryujinx.Graphics.Vulkan pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert(); pipeline.StencilTestEnable = state.StencilTest.TestEnable; - - pipeline.Topology = gd.TopologyRemap(state.Topology).Convert(); } + pipeline.Topology = gd.TopologyRemap(state.Topology).Convert(); + int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount); int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount); From c728a3b6a48ade56637537078bfdec0f716cc766 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Thu, 16 May 2024 23:50:45 -0700 Subject: [PATCH 013/132] ExtDynamicState2 --- .../HardwareCapabilities.cs | 3 ++ src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 22 ++++++++-- .../PipelineDynamicState.cs | 43 ++++++++++++++++--- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 20 +++++++-- .../VulkanInitialization.cs | 12 +++++- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 8 ++++ 6 files changed, 95 insertions(+), 13 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs index 8c7089aa5..952867642 100644 --- a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs +++ b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs @@ -31,6 +31,7 @@ namespace Ryujinx.Graphics.Vulkan public readonly bool SupportsShaderStorageImageMultisample; public readonly bool SupportsConditionalRendering; public readonly bool SupportsExtendedDynamicState; + public readonly bool SupportsExtendedDynamicState2; public readonly bool SupportsMultiView; public readonly bool SupportsNullDescriptors; public readonly bool SupportsPushDescriptors; @@ -70,6 +71,7 @@ namespace Ryujinx.Graphics.Vulkan bool supportsShaderStorageImageMultisample, bool supportsConditionalRendering, bool supportsExtendedDynamicState, + bool supportsExtendedDynamicState2, bool supportsMultiView, bool supportsNullDescriptors, bool supportsPushDescriptors, @@ -108,6 +110,7 @@ namespace Ryujinx.Graphics.Vulkan SupportsShaderStorageImageMultisample = supportsShaderStorageImageMultisample; SupportsConditionalRendering = supportsConditionalRendering; SupportsExtendedDynamicState = supportsExtendedDynamicState; + SupportsExtendedDynamicState2 = supportsExtendedDynamicState2; SupportsMultiView = supportsMultiView; SupportsNullDescriptors = supportsNullDescriptors; SupportsPushDescriptors = supportsPushDescriptors; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 0fee64770..631800881 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -85,6 +85,7 @@ namespace Ryujinx.Graphics.Vulkan private bool _tfActive; private bool _supportExtDynamic; + private bool _supportExtDynamic2; private readonly PipelineColorBlendAttachmentState[] _storedBlend; @@ -125,6 +126,9 @@ namespace Ryujinx.Graphics.Vulkan _storedBlend = new PipelineColorBlendAttachmentState[Constants.MaxRenderTargets]; _supportExtDynamic = gd.Capabilities.SupportsExtendedDynamicState; + + _supportExtDynamic2 = gd.Capabilities.SupportsExtendedDynamicState2; + _newState.Initialize(); } @@ -868,9 +872,13 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) { - DynamicState.SetDepthBias(factor, units, clamp); + DynamicState.SetDepthBias(factor, units, clamp, (enables != 0)); - _newState.DepthBiasEnable = enables != 0; + if (!_supportExtDynamic2) + { + _newState.DepthBiasEnable = enables != 0; + } + SignalStateChange(); } @@ -983,6 +991,7 @@ namespace Ryujinx.Graphics.Vulkan { _newState.LogicOpEnable = enable; _newState.LogicOp = op.Convert(); + SignalStateChange(); } @@ -1071,7 +1080,14 @@ namespace Ryujinx.Graphics.Vulkan public void SetRasterizerDiscard(bool discard) { - _newState.RasterizerDiscardEnable = discard; + if (!_supportExtDynamic2) + { + _newState.RasterizerDiscardEnable = discard; + } + else + { + DynamicState.SetRasterizerDiscard(discard); + } SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index b6bb954fb..efee04b10 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -10,6 +10,7 @@ namespace Ryujinx.Graphics.Vulkan private float _depthBiasSlopeFactor; private float _depthBiasConstantFactor; private float _depthBiasClamp; + private bool _depthBiasEnable; public int ScissorsCount; private Array16 _scissors; @@ -47,6 +48,8 @@ namespace Ryujinx.Graphics.Vulkan public CullModeFlags CullMode; public FrontFace FrontFace; + private bool _discard; + [Flags] private enum DirtyFlags { @@ -62,8 +65,10 @@ namespace Ryujinx.Graphics.Vulkan DepthTestCompareOp = 1 << 8, StencilTestEnable = 1 << 9, LineWidth = 1 << 10, + RasterDiscard = 1 << 11, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable, + Extended2 = RasterDiscard, } private DirtyFlags _dirty; @@ -78,11 +83,12 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.Blend; } - public void SetDepthBias(float slopeFactor, float constantFactor, float clamp) + public void SetDepthBias(float slopeFactor, float constantFactor, float clamp, bool enable) { _depthBiasSlopeFactor = slopeFactor; _depthBiasConstantFactor = constantFactor; _depthBiasClamp = clamp; + _depthBiasEnable = enable; _dirty |= DirtyFlags.DepthBias; } @@ -195,6 +201,13 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.LineWidth; } + + public void SetRasterizerDiscard(bool discard) + { + _discard = discard; + + _dirty |= DirtyFlags.RasterDiscard; + } public void ForceAllDirty(VulkanRenderer gd) { @@ -205,6 +218,11 @@ namespace Ryujinx.Graphics.Vulkan _dirty = DirtyFlags.Standard | DirtyFlags.Extended; } + if (gd.Capabilities.SupportsExtendedDynamicState2) + { + _dirty = DirtyFlags.Standard | DirtyFlags.Extended | DirtyFlags.Extended2; + } + if (gd.IsMoltenVk) { _dirty &= ~DirtyFlags.LineWidth; @@ -220,7 +238,7 @@ namespace Ryujinx.Graphics.Vulkan if (_dirty.HasFlag(DirtyFlags.DepthBias)) { - RecordDepthBias(gd.Api, commandBuffer); + RecordDepthBias(gd, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.Scissor)) @@ -267,7 +285,12 @@ namespace Ryujinx.Graphics.Vulkan { RecordLineWidth(gd.Api, commandBuffer); } - + + if (_dirty.HasFlag(DirtyFlags.RasterDiscard)) + { + RecordRasterizationDiscard(gd, commandBuffer); + } + _dirty = DirtyFlags.None; } @@ -276,9 +299,14 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetBlendConstants(commandBuffer, _blendConstants.AsSpan()); } - private readonly void RecordDepthBias(Vk api, CommandBuffer commandBuffer) + private readonly void RecordDepthBias(VulkanRenderer gd, CommandBuffer commandBuffer) { - api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); + gd.Api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); + + if (gd.Capabilities.SupportsExtendedDynamicState2) + { + gd.ExtendedDynamicState2Api.CmdSetDepthBiasEnable(commandBuffer, _depthBiasEnable); + } } private void RecordScissor(VulkanRenderer gd, CommandBuffer commandBuffer) @@ -363,6 +391,11 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetDepthCompareOp(commandBuffer, _depthCompareOp); } + private void RecordRasterizationDiscard(VulkanRenderer gd, CommandBuffer commandBuffer) + { + gd.ExtendedDynamicState2Api.CmdSetRasterizerDiscardEnable(commandBuffer, _discard); + } + private void RecordLineWidth(Vk api, CommandBuffer commandBuffer) { if (!OperatingSystem.IsMacOS()) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index f7a63a5da..94bab99e6 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -406,6 +406,8 @@ namespace Ryujinx.Graphics.Vulkan } bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState; + bool supportsExtDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2; + fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0]) fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions2 = &_vertexAttributeDescriptions2[0]) @@ -473,9 +475,7 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.PipelineRasterizationStateCreateInfo, DepthClampEnable = DepthClampEnable, - RasterizerDiscardEnable = RasterizerDiscardEnable, PolygonMode = PolygonMode, - DepthBiasEnable = DepthBiasEnable, }; if (isMoltenVk) @@ -488,6 +488,12 @@ namespace Ryujinx.Graphics.Vulkan rasterizationState.CullMode = CullMode; rasterizationState.FrontFace = FrontFace; } + + if (!supportsExtDynamicState2) + { + rasterizationState.DepthBiasEnable = DepthBiasEnable; + rasterizationState.RasterizerDiscardEnable = RasterizerDiscardEnable; + } var viewportState = new PipelineViewportStateCreateInfo { @@ -590,7 +596,7 @@ namespace Ryujinx.Graphics.Vulkan AttachmentCount = ColorBlendAttachmentStateCount, PAttachments = pColorBlendAttachmentState, }; - + PipelineColorBlendAdvancedStateCreateInfoEXT colorBlendAdvancedState; if (!AdvancedBlendSrcPreMultiplied || @@ -608,7 +614,7 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.PNext = &colorBlendAdvancedState; } - int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 17 : 18) : (isMoltenVk ? 7 : 8); + int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 18 : 19) : (isMoltenVk ? 7 : 8); DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount]; @@ -642,6 +648,12 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[index] = DynamicState.StencilOpExt; } + if (supportsExtDynamicState2) + { + dynamicStates[16] = DynamicState.DepthBiasEnableExt; + dynamicStates[17] = DynamicState.RasterizerDiscardEnableExt; + } + var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo { SType = StructureType.PipelineDynamicStateCreateInfo, diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index a8de50f6d..b12f48202 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -23,6 +23,7 @@ namespace Ryujinx.Graphics.Vulkan private static readonly string[] _desirableExtensions = { ExtConditionalRendering.ExtensionName, ExtExtendedDynamicState.ExtensionName, + ExtExtendedDynamicState2.ExtensionName, ExtTransformFeedback.ExtensionName, KhrDrawIndirectCount.ExtensionName, KhrPushDescriptor.ExtensionName, @@ -290,7 +291,7 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.PhysicalDeviceFeatures2, }; - + PhysicalDeviceVulkan11Features supportedFeaturesVk11 = new() { SType = StructureType.PhysicalDeviceVulkan11Features, @@ -438,6 +439,15 @@ namespace Ryujinx.Graphics.Vulkan }; pExtendedFeatures = &featuresExtendedDynamicState; + + var featuresExtendedDynamicState2 = new PhysicalDeviceExtendedDynamicState2FeaturesEXT() + { + SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, + PNext = pExtendedFeatures, + ExtendedDynamicState2 = physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName), + }; + + pExtendedFeatures = &featuresExtendedDynamicState2; var featuresVk11 = new PhysicalDeviceVulkan11Features { diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index e8dd766a0..c75c4a39f 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -35,6 +35,8 @@ namespace Ryujinx.Graphics.Vulkan internal KhrSwapchain SwapchainApi { get; private set; } internal ExtConditionalRendering ConditionalRenderingApi { get; private set; } internal ExtExtendedDynamicState ExtendedDynamicStateApi { get; private set; } + internal ExtExtendedDynamicState2 ExtendedDynamicState2Api { get; private set; } + internal KhrPushDescriptor PushDescriptorApi { get; private set; } internal ExtTransformFeedback TransformFeedbackApi { get; private set; } internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; } @@ -131,6 +133,11 @@ namespace Ryujinx.Graphics.Vulkan { ExtendedDynamicStateApi = extendedDynamicStateApi; } + + if (Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExtendedDynamicState2 extendedDynamicState2Api)) + { + ExtendedDynamicState2Api = extendedDynamicState2Api; + } if (Api.TryGetDeviceExtension(_instance.Instance, _device, out KhrPushDescriptor pushDescriptorApi)) { @@ -382,6 +389,7 @@ namespace Ryujinx.Graphics.Vulkan features2.Features.ShaderStorageImageMultisample, _physicalDevice.IsDeviceExtensionPresent(ExtConditionalRendering.ExtensionName), _physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState.ExtensionName), + _physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName), features2.Features.MultiViewport && !(IsMoltenVk && Vendor == Vendor.Amd), // Workaround for AMD on MoltenVK issue featuresRobustness2.NullDescriptor || IsMoltenVk, supportsPushDescriptors && !IsMoltenVk, From 0049585a36435d0a1157dd381dd61c628bb8dd19 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Fri, 17 May 2024 13:17:54 -0700 Subject: [PATCH 014/132] Enable if supported. --- src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index b12f48202..d6b4c7a87 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -310,6 +310,17 @@ namespace Ryujinx.Graphics.Vulkan { features2.PNext = &supportedFeaturesCustomBorderColor; } + + PhysicalDeviceExtendedDynamicState2FeaturesEXT supportedFeaturesExtExtendedDynamicState2 = new() + { + SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, + PNext = features2.PNext, + }; + + if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName)) + { + features2.PNext = &supportedFeaturesExtExtendedDynamicState2; + } PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT supportedFeaturesPrimitiveTopologyListRestart = new() { @@ -445,6 +456,8 @@ namespace Ryujinx.Graphics.Vulkan SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, PNext = pExtendedFeatures, ExtendedDynamicState2 = physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName), + ExtendedDynamicState2LogicOp = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp, + ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints, }; pExtendedFeatures = &featuresExtendedDynamicState2; From 66b6b46716d6adb38c3ee07bd9786027c4d166e0 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Fri, 17 May 2024 15:02:56 -0700 Subject: [PATCH 015/132] Use device features to enable to disable LogicOp Extended Dynamic State Improve index counting --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 38 +++--- .../PipelineConverter.cs | 18 +-- .../PipelineDynamicState.cs | 115 +++++++++++------- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 14 +-- .../VulkanInitialization.cs | 10 +- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 8 +- 6 files changed, 121 insertions(+), 82 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 631800881..bf22a120a 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -84,8 +84,8 @@ namespace Ryujinx.Graphics.Vulkan private bool _tfEnabled; private bool _tfActive; - private bool _supportExtDynamic; - private bool _supportExtDynamic2; + private readonly bool _supportExtDynamic; + private readonly bool _supportExtDynamic2; private readonly PipelineColorBlendAttachmentState[] _storedBlend; @@ -126,7 +126,7 @@ namespace Ryujinx.Graphics.Vulkan _storedBlend = new PipelineColorBlendAttachmentState[Constants.MaxRenderTargets]; _supportExtDynamic = gd.Capabilities.SupportsExtendedDynamicState; - + _supportExtDynamic2 = gd.Capabilities.SupportsExtendedDynamicState2; @@ -714,7 +714,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.DepthTestEnable = false; _newState.DepthWriteEnable = false; } - + SignalStateChange(); Gd.HelperShader.DrawTexture( @@ -739,7 +739,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.DepthWriteEnable = oldDepthWriteEnable; _newState.ViewportsCount = oldViewportsCount; } - + _newState.Topology = oldTopology; DynamicState.SetViewports(ref oldViewports, oldViewportsCount); @@ -878,7 +878,7 @@ namespace Ryujinx.Graphics.Vulkan { _newState.DepthBiasEnable = enables != 0; } - + SignalStateChange(); } @@ -911,7 +911,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.DepthWriteEnable = depthTest.WriteEnable; _newState.DepthCompareOp = depthTest.Func.Convert(); } - + SignalStateChange(); } @@ -983,14 +983,22 @@ namespace Ryujinx.Graphics.Vulkan { DynamicState.SetLineWidth(Gd.Capabilities.SupportsWideLines ? width : 1.0f); } - + SignalStateChange(); } public void SetLogicOpState(bool enable, LogicalOp op) { + if (_supportExtDynamic2 && Gd.ExtendedLogicOp) + { + DynamicState.SetLogicOp(op.Convert()); + } + else + { + _newState.LogicOp = op.Convert(); + } + _newState.LogicOpEnable = enable; - _newState.LogicOp = op.Convert(); SignalStateChange(); } @@ -1032,9 +1040,9 @@ namespace Ryujinx.Graphics.Vulkan _topology = topology; var vkTopology = Gd.TopologyRemap(topology).Convert(); - + _newState.Topology = vkTopology; - + SignalStateChange(); } @@ -1195,7 +1203,7 @@ namespace Ryujinx.Graphics.Vulkan stencilTest.FrontDpPass.Convert(), stencilTest.FrontDpFail.Convert(), stencilTest.FrontFunc.Convert()); - + DynamicState.SetStencilTest(stencilTest.TestEnable); } else @@ -1210,7 +1218,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert(); _newState.StencilTestEnable = stencilTest.TestEnable; } - + DynamicState.SetStencilMask((uint)stencilTest.BackFuncMask, (uint)stencilTest.BackMask, (uint)stencilTest.BackFuncRef, @@ -1454,11 +1462,11 @@ namespace Ryujinx.Graphics.Vulkan Clamp(viewport.DepthNear), Clamp(viewport.DepthFar))); } - + if (!_supportExtDynamic) { _newState.ViewportsCount = (uint)count; - } + } SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 9bc16b4de..e8fbea999 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -164,9 +164,9 @@ namespace Ryujinx.Graphics.Vulkan pipeline.DepthBoundsTestEnable = false; // Not implemented. pipeline.DepthClampEnable = state.DepthClampEnable; - + pipeline.DepthMode = state.DepthMode == DepthMode.MinusOneToOne; - + pipeline.HasDepthStencil = state.DepthStencilEnable; pipeline.LogicOpEnable = state.LogicOpEnable; pipeline.LogicOp = state.LogicOp.Convert(); @@ -188,11 +188,11 @@ namespace Ryujinx.Graphics.Vulkan pipeline.DepthTestEnable = state.DepthTest.TestEnable; pipeline.DepthWriteEnable = state.DepthTest.WriteEnable; pipeline.DepthCompareOp = state.DepthTest.Func.Convert(); - + pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None; - + pipeline.FrontFace = state.FrontFace.Convert(); - + if (gd.Capabilities.SupportsMultiView) { pipeline.ScissorsCount = Constants.MaxViewports; @@ -203,7 +203,7 @@ namespace Ryujinx.Graphics.Vulkan pipeline.ScissorsCount = 1; pipeline.ViewportsCount = 1; } - + pipeline.StencilFrontFailOp = state.StencilTest.FrontSFail.Convert(); pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert(); pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert(); @@ -213,12 +213,12 @@ namespace Ryujinx.Graphics.Vulkan pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert(); pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert(); pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert(); - + pipeline.StencilTestEnable = state.StencilTest.TestEnable; } - + pipeline.Topology = gd.TopologyRemap(state.Topology).Convert(); - + int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount); int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index efee04b10..783f2bf71 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Vulkan private uint _frontCompareMask; private uint _frontWriteMask; private uint _frontReference; - + private bool _opToo; private StencilOp _backfailop; private StencilOp _backpassop; @@ -33,13 +33,13 @@ namespace Ryujinx.Graphics.Vulkan private CompareOp _frontcompareop; private float _linewidth; - + public bool _stencilTestEnable; public bool _depthtestEnable; public bool _depthwriteEnable; private CompareOp _depthCompareOp; - + private Array4 _blendConstants; public uint ViewportsCount; @@ -49,7 +49,9 @@ namespace Ryujinx.Graphics.Vulkan public FrontFace FrontFace; private bool _discard; - + + private LogicOp _logicOp; + [Flags] private enum DirtyFlags { @@ -61,14 +63,15 @@ namespace Ryujinx.Graphics.Vulkan Viewport = 1 << 4, CullMode = 1 << 5, FrontFace = 1 << 6, - DepthTestBool = 1 << 7, + DepthTestBool = 1 << 7, DepthTestCompareOp = 1 << 8, StencilTestEnable = 1 << 9, LineWidth = 1 << 10, RasterDiscard = 1 << 11, + LogicOp = 1 << 12, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable, - Extended2 = RasterDiscard, + Extended2 = RasterDiscard | LogicOp, } private DirtyFlags _dirty; @@ -107,14 +110,14 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.DepthTestBool; } - + public void SetDepthTestCompareOp(CompareOp depthTestOp) { _depthCompareOp = depthTestOp; _dirty |= DirtyFlags.DepthTestCompareOp; } - + public void SetStencilOp(StencilOp backFailOp, StencilOp backPassOp, StencilOp backDepthFailOp, @@ -133,10 +136,10 @@ namespace Ryujinx.Graphics.Vulkan _frontpassop = frontPassOp; _frontdepthfailop = frontDepthFailOp; _frontcompareop = frontCompareOp; - + _opToo = true; } - + public void SetStencilMask( uint backCompareMask, uint backWriteMask, @@ -154,11 +157,11 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.Stencil; } - + public void SetStencilTest(bool stencilTestEnable) { _stencilTestEnable = stencilTestEnable; - + _dirty |= DirtyFlags.StencilTestEnable; } @@ -180,35 +183,42 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.Viewport; } } - + public void SetCullMode(CullModeFlags cullMode) { CullMode = cullMode; - + _dirty |= DirtyFlags.CullMode; } - + public void SetFrontFace(FrontFace frontFace) { FrontFace = frontFace; - + _dirty |= DirtyFlags.FrontFace; } - + public void SetLineWidth(float width) { _linewidth = width; - + _dirty |= DirtyFlags.LineWidth; } - + public void SetRasterizerDiscard(bool discard) { _discard = discard; - + _dirty |= DirtyFlags.RasterDiscard; } + public void SetLogicOp(LogicOp op) + { + _logicOp = op; + + _dirty |= DirtyFlags.LogicOp; + } + public void ForceAllDirty(VulkanRenderer gd) { _dirty = DirtyFlags.Standard; @@ -227,6 +237,11 @@ namespace Ryujinx.Graphics.Vulkan { _dirty &= ~DirtyFlags.LineWidth; } + + if (!gd.ExtendedLogicOp) + { + _dirty &= ~DirtyFlags.LogicOp; + } } public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) @@ -255,42 +270,47 @@ namespace Ryujinx.Graphics.Vulkan { RecordViewport(gd, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.CullMode)) { RecordCullMode(gd.ExtendedDynamicStateApi, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.FrontFace)) { RecordFrontFace(gd.ExtendedDynamicStateApi, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.DepthTestBool)) { RecordDepthTestBool(gd.ExtendedDynamicStateApi, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.DepthTestCompareOp)) { RecordDepthTestCompareOp(gd.ExtendedDynamicStateApi, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.StencilTestEnable)) { RecordStencilTestEnable(gd.ExtendedDynamicStateApi, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.LineWidth)) { RecordLineWidth(gd.Api, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.RasterDiscard)) { RecordRasterizationDiscard(gd, commandBuffer); } - + + if (_dirty.HasFlag(DirtyFlags.RasterDiscard)) + { + RecordLogicOp(gd, commandBuffer); + } + _dirty = DirtyFlags.None; } @@ -302,7 +322,7 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordDepthBias(VulkanRenderer gd, CommandBuffer commandBuffer) { gd.Api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); - + if (gd.Capabilities.SupportsExtendedDynamicState2) { gd.ExtendedDynamicState2Api.CmdSetDepthBiasEnable(commandBuffer, _depthBiasEnable); @@ -326,7 +346,7 @@ namespace Ryujinx.Graphics.Vulkan } } } - + private readonly void RecordStencil(VulkanRenderer gd, CommandBuffer commandBuffer) { if (_opToo) @@ -336,7 +356,7 @@ namespace Ryujinx.Graphics.Vulkan gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontfailop, _frontpassop, _frontdepthfailop, _frontcompareop); } - + gd.Api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backCompareMask); gd.Api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backWriteMask); gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceBackBit, _backReference); @@ -344,12 +364,12 @@ namespace Ryujinx.Graphics.Vulkan gd.Api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontWriteMask); gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference); } - + private readonly void RecordStencilTestEnable(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetStencilTestEnable(commandBuffer, _stencilTestEnable); } - + private void RecordViewport(VulkanRenderer gd, CommandBuffer commandBuffer) { if (ViewportsCount == 0) @@ -369,34 +389,39 @@ namespace Ryujinx.Graphics.Vulkan Viewports.AsSpan()); } } - - private void RecordCullMode(ExtExtendedDynamicState api, CommandBuffer commandBuffer) + + private readonly void RecordCullMode(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetCullMode(commandBuffer, CullMode); } - - private void RecordFrontFace(ExtExtendedDynamicState api, CommandBuffer commandBuffer) + + private readonly void RecordFrontFace(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetFrontFace(commandBuffer, FrontFace); } - - private void RecordDepthTestBool(ExtExtendedDynamicState api, CommandBuffer commandBuffer) + + private readonly void RecordDepthTestBool(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetDepthTestEnable(commandBuffer, _depthtestEnable); api.CmdSetDepthWriteEnable(commandBuffer, _depthwriteEnable); } - - private void RecordDepthTestCompareOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) + + private readonly void RecordDepthTestCompareOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetDepthCompareOp(commandBuffer, _depthCompareOp); } - - private void RecordRasterizationDiscard(VulkanRenderer gd, CommandBuffer commandBuffer) + + private readonly void RecordRasterizationDiscard(VulkanRenderer gd, CommandBuffer commandBuffer) { gd.ExtendedDynamicState2Api.CmdSetRasterizerDiscardEnable(commandBuffer, _discard); } - - private void RecordLineWidth(Vk api, CommandBuffer commandBuffer) + + private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) + { + gd.ExtendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp); + } + + private readonly void RecordLineWidth(Vk api, CommandBuffer commandBuffer) { if (!OperatingSystem.IsMacOS()) { diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 94bab99e6..7c6f6a83f 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -584,19 +584,19 @@ namespace Ryujinx.Graphics.Vulkan } } - // Vendors other than NVIDIA have a bug where it enables logical operations even for float formats, - // so we need to force disable them here. - bool logicOpEnable = LogicOpEnable && (gd.Vendor == Vendor.Nvidia || Internal.LogicOpsAllowed); - var colorBlendState = new PipelineColorBlendStateCreateInfo { SType = StructureType.PipelineColorBlendStateCreateInfo, - LogicOpEnable = logicOpEnable, - LogicOp = LogicOp, + LogicOpEnable = LogicOpEnable, AttachmentCount = ColorBlendAttachmentStateCount, PAttachments = pColorBlendAttachmentState, }; - + + if (!(supportsExtDynamicState2 && gd.ExtendedLogicOp)) + { + colorBlendState.LogicOp = LogicOp; + } + PipelineColorBlendAdvancedStateCreateInfoEXT colorBlendAdvancedState; if (!AdvancedBlendSrcPreMultiplied || diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index d6b4c7a87..6b4ca1d3d 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -263,7 +263,7 @@ namespace Ryujinx.Graphics.Vulkan return InvalidIndex; } - internal static Device CreateDevice(Vk api, VulkanPhysicalDevice physicalDevice, uint queueFamilyIndex, uint queueCount) + internal static Device CreateDevice(Vk api, VulkanPhysicalDevice physicalDevice, uint queueFamilyIndex, uint queueCount, out bool extendedLogicOp) { if (queueCount > QueuesCount) { @@ -291,7 +291,7 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.PhysicalDeviceFeatures2, }; - + PhysicalDeviceVulkan11Features supportedFeaturesVk11 = new() { SType = StructureType.PhysicalDeviceVulkan11Features, @@ -310,7 +310,7 @@ namespace Ryujinx.Graphics.Vulkan { features2.PNext = &supportedFeaturesCustomBorderColor; } - + PhysicalDeviceExtendedDynamicState2FeaturesEXT supportedFeaturesExtExtendedDynamicState2 = new() { SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, @@ -450,7 +450,7 @@ namespace Ryujinx.Graphics.Vulkan }; pExtendedFeatures = &featuresExtendedDynamicState; - + var featuresExtendedDynamicState2 = new PhysicalDeviceExtendedDynamicState2FeaturesEXT() { SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, @@ -460,6 +460,8 @@ namespace Ryujinx.Graphics.Vulkan ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints, }; + extendedLogicOp = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp; + pExtendedFeatures = &featuresExtendedDynamicState2; var featuresVk11 = new PhysicalDeviceVulkan11Features diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index c75c4a39f..1807711d6 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -99,6 +99,8 @@ namespace Ryujinx.Graphics.Vulkan public bool PreferThreading => true; + public bool ExtendedLogicOp; + public event EventHandler ScreenCaptured; public VulkanRenderer(Vk api, Func surfaceFunc, Func requiredExtensionsFunc, string preferredGpuId) @@ -133,7 +135,7 @@ namespace Ryujinx.Graphics.Vulkan { ExtendedDynamicStateApi = extendedDynamicStateApi; } - + if (Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExtendedDynamicState2 extendedDynamicState2Api)) { ExtendedDynamicState2Api = extendedDynamicState2Api; @@ -454,7 +456,9 @@ namespace Ryujinx.Graphics.Vulkan var queueFamilyIndex = VulkanInitialization.FindSuitableQueueFamily(Api, _physicalDevice, _surface, out uint maxQueueCount); - _device = VulkanInitialization.CreateDevice(Api, _physicalDevice, queueFamilyIndex, maxQueueCount); + _device = VulkanInitialization.CreateDevice(Api, _physicalDevice, queueFamilyIndex, maxQueueCount, out bool extendedLogicOp); + + ExtendedLogicOp = extendedLogicOp; if (Api.TryGetDeviceExtension(_instance.Instance, _device, out KhrSwapchain swapchainApi)) { From 19db5a0ce2d896aea85dcdc8d273ad2554408d14 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Fri, 17 May 2024 16:32:05 -0700 Subject: [PATCH 016/132] Implement VK_EXT_extended_dynamic_state3 --- Directory.Packages.props | 6 +- .../HardwareCapabilities.cs | 3 + src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 52 ++++++- .../PipelineDynamicState.cs | 130 +++++++++++++++++- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 126 +++++++++++++---- .../VulkanInitialization.cs | 58 ++++++-- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 17 ++- 7 files changed, 342 insertions(+), 50 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index a93247547..e73701629 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -39,9 +39,9 @@ - - - + + + diff --git a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs index 952867642..07c7e2618 100644 --- a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs +++ b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs @@ -32,6 +32,7 @@ namespace Ryujinx.Graphics.Vulkan public readonly bool SupportsConditionalRendering; public readonly bool SupportsExtendedDynamicState; public readonly bool SupportsExtendedDynamicState2; + public readonly bool SupportsExtendedDynamicState3; public readonly bool SupportsMultiView; public readonly bool SupportsNullDescriptors; public readonly bool SupportsPushDescriptors; @@ -72,6 +73,7 @@ namespace Ryujinx.Graphics.Vulkan bool supportsConditionalRendering, bool supportsExtendedDynamicState, bool supportsExtendedDynamicState2, + bool supportsExtendedDynamicState3, bool supportsMultiView, bool supportsNullDescriptors, bool supportsPushDescriptors, @@ -111,6 +113,7 @@ namespace Ryujinx.Graphics.Vulkan SupportsConditionalRendering = supportsConditionalRendering; SupportsExtendedDynamicState = supportsExtendedDynamicState; SupportsExtendedDynamicState2 = supportsExtendedDynamicState2; + SupportsExtendedDynamicState3 = supportsExtendedDynamicState3; SupportsMultiView = supportsMultiView; SupportsNullDescriptors = supportsNullDescriptors; SupportsPushDescriptors = supportsPushDescriptors; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index bf22a120a..5024fdd4e 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -884,7 +884,15 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthClamp(bool clamp) { - _newState.DepthClampEnable = clamp; + if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable) + { + DynamicState.SetDepthClampEnable(clamp); + } + else + { + _newState.DepthClampEnable = clamp; + } + SignalStateChange(); } @@ -989,7 +997,7 @@ namespace Ryujinx.Graphics.Vulkan public void SetLogicOpState(bool enable, LogicalOp op) { - if (_supportExtDynamic2 && Gd.ExtendedLogicOp) + if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) { DynamicState.SetLogicOp(op.Convert()); } @@ -998,21 +1006,53 @@ namespace Ryujinx.Graphics.Vulkan _newState.LogicOp = op.Convert(); } - _newState.LogicOpEnable = enable; + if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable) + { + DynamicState.SetLogicOpEnable(enable); + + } + else + { + _newState.LogicOpEnable = enable; + } SignalStateChange(); } public void SetMultisampleState(MultisampleDescriptor multisample) { - _newState.AlphaToCoverageEnable = multisample.AlphaToCoverageEnable; - _newState.AlphaToOneEnable = multisample.AlphaToOneEnable; + if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable) + { + DynamicState.SetAlphaToCoverEnable(multisample.AlphaToCoverageEnable); + } + else + { + _newState.AlphaToCoverageEnable = multisample.AlphaToCoverageEnable; + } + + if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable) + { + DynamicState.SetAlphaToOneEnable(multisample.AlphaToOneEnable); + } + else + { + _newState.AlphaToOneEnable = multisample.AlphaToOneEnable; + } + SignalStateChange(); } public void SetPatchParameters(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel) { - _newState.PatchControlPoints = (uint)vertices; + if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + { + DynamicState.SetPatchControlPoints((uint)vertices); + } + else + { + _newState.PatchControlPoints = (uint)vertices; + } + SignalStateChange(); // TODO: Default levels (likely needs emulation on shaders?) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 783f2bf71..90d75724a 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -52,6 +52,15 @@ namespace Ryujinx.Graphics.Vulkan private LogicOp _logicOp; + private uint _patchControlPoints; + + private bool _logicOpEnable; + + private bool _depthClampEnable; + + private bool _alphaToCoverEnable; + private bool _alphaToOneEnable; + [Flags] private enum DirtyFlags { @@ -69,9 +78,14 @@ namespace Ryujinx.Graphics.Vulkan LineWidth = 1 << 10, RasterDiscard = 1 << 11, LogicOp = 1 << 12, + DepthClampEnable = 1 << 13, + LogicOpEnalbe = 1 << 14, + AlphaToCover = 1 << 15, + AlphaToOne = 1 << 16, + PatchControlPoints = 1 << 17, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable, - Extended2 = RasterDiscard | LogicOp, + Extended2 = RasterDiscard | LogicOp | PatchControlPoints, } private DirtyFlags _dirty; @@ -219,6 +233,41 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.LogicOp; } + public void SetPatchControlPoints(uint points) + { + _patchControlPoints = points; + + _dirty |= DirtyFlags.PatchControlPoints; + } + + public void SetLogicOpEnable(bool logicOpEnable) + { + _logicOpEnable = logicOpEnable; + + _dirty |= DirtyFlags.LogicOpEnalbe; + } + + public void SetDepthClampEnable(bool depthClampEnable) + { + _depthClampEnable = depthClampEnable; + + _dirty |= DirtyFlags.DepthClampEnable; + } + + public void SetAlphaToCoverEnable(bool alphaToCoverEnable) + { + _alphaToCoverEnable = alphaToCoverEnable; + + _dirty |= DirtyFlags.AlphaToCover; + } + + public void SetAlphaToOneEnable(bool alphaToOneEnable) + { + _alphaToOneEnable = alphaToOneEnable; + + _dirty |= DirtyFlags.AlphaToOne; + } + public void ForceAllDirty(VulkanRenderer gd) { _dirty = DirtyFlags.Standard; @@ -238,10 +287,35 @@ namespace Ryujinx.Graphics.Vulkan _dirty &= ~DirtyFlags.LineWidth; } - if (!gd.ExtendedLogicOp) + if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) { _dirty &= ~DirtyFlags.LogicOp; } + + if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + { + _dirty &= ~DirtyFlags.LogicOp; + } + + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable) + { + _dirty = DirtyFlags.AlphaToCover; + } + + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable) + { + _dirty = DirtyFlags.AlphaToOne; + } + + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable) + { + _dirty = DirtyFlags.DepthClampEnable; + } + + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable) + { + _dirty = DirtyFlags.LogicOpEnalbe; + } } public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) @@ -306,11 +380,36 @@ namespace Ryujinx.Graphics.Vulkan RecordRasterizationDiscard(gd, commandBuffer); } - if (_dirty.HasFlag(DirtyFlags.RasterDiscard)) + if (_dirty.HasFlag(DirtyFlags.LogicOp)) { RecordLogicOp(gd, commandBuffer); } + if (_dirty.HasFlag(DirtyFlags.PatchControlPoints)) + { + RecordPatchControlPoints(gd, commandBuffer); + } + + if (_dirty.HasFlag(DirtyFlags.LogicOpEnalbe)) + { + RecordLogicOpEnable(gd, commandBuffer); + } + + if (_dirty.HasFlag(DirtyFlags.DepthClampEnable)) + { + RecordDepthClampEnable(gd, commandBuffer); + } + + if (_dirty.HasFlag(DirtyFlags.AlphaToCover)) + { + RecordAlphaToCoverEnable(gd, commandBuffer); + } + + if (_dirty.HasFlag(DirtyFlags.AlphaToOne)) + { + RecordAlphaToOneEnable(gd, commandBuffer); + } + _dirty = DirtyFlags.None; } @@ -421,6 +520,31 @@ namespace Ryujinx.Graphics.Vulkan gd.ExtendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp); } + private readonly void RecordLogicOpEnable(VulkanRenderer gd, CommandBuffer commandBuffer) + { + gd.ExtendedDynamicState3Api.CmdSetLogicOpEnable(commandBuffer, _logicOpEnable); + } + + private readonly void RecordDepthClampEnable(VulkanRenderer gd, CommandBuffer commandBuffer) + { + gd.ExtendedDynamicState3Api.CmdSetDepthClampEnable(commandBuffer, _depthClampEnable); + } + + private readonly void RecordAlphaToCoverEnable(VulkanRenderer gd, CommandBuffer commandBuffer) + { + gd.ExtendedDynamicState3Api.CmdSetAlphaToCoverageEnable(commandBuffer, _alphaToCoverEnable); + } + + private readonly void RecordAlphaToOneEnable(VulkanRenderer gd, CommandBuffer commandBuffer) + { + gd.ExtendedDynamicState3Api.CmdSetAlphaToOneEnable(commandBuffer, _alphaToOneEnable); + } + + private readonly void RecordPatchControlPoints(VulkanRenderer gd, CommandBuffer commandBuffer) + { + gd.ExtendedDynamicState2Api.CmdSetPatchControlPoints(commandBuffer, _patchControlPoints); + } + private readonly void RecordLineWidth(Vk api, CommandBuffer commandBuffer) { if (!OperatingSystem.IsMacOS()) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 7c6f6a83f..e4fe002d9 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -404,7 +404,7 @@ namespace Ryujinx.Graphics.Vulkan { UpdateVertexAttributeDescriptions(gd); } - + bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState; bool supportsExtDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2; @@ -457,7 +457,7 @@ namespace Ryujinx.Graphics.Vulkan { primitiveRestartEnable = true; } - + var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, @@ -494,12 +494,12 @@ namespace Ryujinx.Graphics.Vulkan rasterizationState.DepthBiasEnable = DepthBiasEnable; rasterizationState.RasterizerDiscardEnable = RasterizerDiscardEnable; } - + var viewportState = new PipelineViewportStateCreateInfo { SType = StructureType.PipelineViewportStateCreateInfo, }; - + if (!supportsExtDynamicState) { viewportState.ViewportCount = ViewportsCount; @@ -534,7 +534,7 @@ namespace Ryujinx.Graphics.Vulkan MinDepthBounds = MinDepthBounds, MaxDepthBounds = MaxDepthBounds, }; - + if (!supportsExtDynamicState) { var stencilFront = new StencilOpState( @@ -613,9 +613,54 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.PNext = &colorBlendAdvancedState; } - - int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 18 : 19) : (isMoltenVk ? 7 : 8); + int baseDynamicStatesCount = 7; + int additionalDynamicStatesCount = 0; + + if (!isMoltenVk) + { + baseDynamicStatesCount++; + } + + if (supportsExtDynamicState) + { + additionalDynamicStatesCount += isMoltenVk ? 10 : 11; + } + + if (supportsExtDynamicState2) + { + additionalDynamicStatesCount += 2; + if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) + { + additionalDynamicStatesCount++; + } + if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + { + additionalDynamicStatesCount++; + } + } + + if (supportsExtDynamicState3) + { + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable) + { + additionalDynamicStatesCount++; + } + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable) + { + additionalDynamicStatesCount++; + } + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable) + { + additionalDynamicStatesCount++; + } + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable) + { + additionalDynamicStatesCount++; + } + } + + int dynamicStatesCount = baseDynamicStatesCount + additionalDynamicStatesCount; DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount]; dynamicStates[0] = DynamicState.Viewport; @@ -625,33 +670,64 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[4] = DynamicState.StencilWriteMask; dynamicStates[5] = DynamicState.StencilReference; dynamicStates[6] = DynamicState.BlendConstants; - - if(!isMoltenVk) + + int currentIndex = 7; + + if (!isMoltenVk) { - dynamicStates[7] = DynamicState.LineWidth; + dynamicStates[currentIndex++] = DynamicState.LineWidth; } - + if (supportsExtDynamicState) { - int index = (isMoltenVk ? 7 : 8); - if (!isMoltenVk) { - dynamicStates[index++] = DynamicState.VertexInputBindingStrideExt; + if (!isMoltenVk) + { + dynamicStates[currentIndex++] = DynamicState.VertexInputBindingStrideExt; } - dynamicStates[index++] = DynamicState.CullModeExt; - dynamicStates[index++] = DynamicState.FrontFaceExt; - dynamicStates[index++] = DynamicState.DepthTestEnableExt; - dynamicStates[index++] = DynamicState.DepthWriteEnableExt; - dynamicStates[index++] = DynamicState.DepthCompareOpExt; - dynamicStates[index++] = DynamicState.StencilTestEnableExt; - dynamicStates[index++] = DynamicState.ViewportWithCountExt; - dynamicStates[index++] = DynamicState.ScissorWithCountExt; - dynamicStates[index] = DynamicState.StencilOpExt; + dynamicStates[currentIndex++] = DynamicState.CullModeExt; + dynamicStates[currentIndex++] = DynamicState.FrontFaceExt; + dynamicStates[currentIndex++] = DynamicState.DepthTestEnableExt; + dynamicStates[currentIndex++] = DynamicState.DepthWriteEnableExt; + dynamicStates[currentIndex++] = DynamicState.DepthCompareOpExt; + dynamicStates[currentIndex++] = DynamicState.StencilTestEnableExt; + dynamicStates[currentIndex++] = DynamicState.ViewportWithCountExt; + dynamicStates[currentIndex++] = DynamicState.ScissorWithCountExt; + dynamicStates[currentIndex++] = DynamicState.StencilOpExt; } if (supportsExtDynamicState2) { - dynamicStates[16] = DynamicState.DepthBiasEnableExt; - dynamicStates[17] = DynamicState.RasterizerDiscardEnableExt; + dynamicStates[currentIndex++] = DynamicState.DepthBiasEnableExt; + dynamicStates[currentIndex++] = DynamicState.RasterizerDiscardEnableExt; + + if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) + { + dynamicStates[currentIndex++] = DynamicState.LogicOpExt; + } + if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + { + dynamicStates[currentIndex++] = DynamicState.PatchControlPointsExt; + } + } + + if (supportsExtDynamicState3) + { + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable) + { + dynamicStates[currentIndex++] = DynamicState.DepthClampEnableExt; + } + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable) + { + dynamicStates[currentIndex++] = DynamicState.LogicOpEnableExt; + } + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable) + { + dynamicStates[currentIndex++] = DynamicState.AlphaToCoverageEnableExt; + } + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable) + { + dynamicStates[currentIndex++] = DynamicState.AlphaToOneEnableExt; + } } var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index 6b4ca1d3d..4a1aa2b0b 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -263,7 +263,7 @@ namespace Ryujinx.Graphics.Vulkan return InvalidIndex; } - internal static Device CreateDevice(Vk api, VulkanPhysicalDevice physicalDevice, uint queueFamilyIndex, uint queueCount, out bool extendedLogicOp) + internal static Device CreateDevice(Vk api, VulkanPhysicalDevice physicalDevice, uint queueFamilyIndex, uint queueCount, out PhysicalDeviceExtendedDynamicState2FeaturesEXT extendedDynamicState2Features, out PhysicalDeviceExtendedDynamicState3FeaturesEXT extendedDynamicState3Features) { if (queueCount > QueuesCount) { @@ -322,6 +322,17 @@ namespace Ryujinx.Graphics.Vulkan features2.PNext = &supportedFeaturesExtExtendedDynamicState2; } + PhysicalDeviceExtendedDynamicState3FeaturesEXT supportedFeaturesExtExtendedDynamicState3 = new() + { + SType = StructureType.PhysicalDeviceExtendedDynamicState3FeaturesExt, + PNext = features2.PNext, + }; + + if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState3.ExtensionName)) + { + features2.PNext = &supportedFeaturesExtExtendedDynamicState3; + } + PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT supportedFeaturesPrimitiveTopologyListRestart = new() { SType = StructureType.PhysicalDevicePrimitiveTopologyListRestartFeaturesExt, @@ -451,18 +462,45 @@ namespace Ryujinx.Graphics.Vulkan pExtendedFeatures = &featuresExtendedDynamicState; - var featuresExtendedDynamicState2 = new PhysicalDeviceExtendedDynamicState2FeaturesEXT() + if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName)) { - SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, - PNext = pExtendedFeatures, - ExtendedDynamicState2 = physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName), - ExtendedDynamicState2LogicOp = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp, - ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints, - }; + var featuresExtendedDynamicState2 = new PhysicalDeviceExtendedDynamicState2FeaturesEXT() + { + SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, + PNext = pExtendedFeatures, + ExtendedDynamicState2 = + physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName), + ExtendedDynamicState2LogicOp = + supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp, + ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2 + .ExtendedDynamicState2PatchControlPoints, + }; - extendedLogicOp = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp; + pExtendedFeatures = &featuresExtendedDynamicState2; + } - pExtendedFeatures = &featuresExtendedDynamicState2; + extendedDynamicState2Features = supportedFeaturesExtExtendedDynamicState2; + + + if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState3.ExtensionName)) + { + var featuresExtendedDynamicState3 = new PhysicalDeviceExtendedDynamicState3FeaturesEXT() + { + SType = StructureType.PhysicalDeviceExtendedDynamicState3FeaturesExt, + PNext = pExtendedFeatures, + ExtendedDynamicState3LogicOpEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3LogicOpEnable, + ExtendedDynamicState3AlphaToCoverageEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3AlphaToCoverageEnable, + ExtendedDynamicState3AlphaToOneEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3AlphaToOneEnable, + ExtendedDynamicState3DepthClampEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3DepthClampEnable, + }; + + pExtendedFeatures = &featuresExtendedDynamicState3; + } + + //Seems to be a error in Silk.Net bidings investigate further later + supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3DepthClampEnable = false; + + extendedDynamicState3Features = supportedFeaturesExtExtendedDynamicState3; var featuresVk11 = new PhysicalDeviceVulkan11Features { diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 1807711d6..69d075951 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -36,6 +36,7 @@ namespace Ryujinx.Graphics.Vulkan internal ExtConditionalRendering ConditionalRenderingApi { get; private set; } internal ExtExtendedDynamicState ExtendedDynamicStateApi { get; private set; } internal ExtExtendedDynamicState2 ExtendedDynamicState2Api { get; private set; } + internal ExtExtendedDynamicState3 ExtendedDynamicState3Api { get; private set; } internal KhrPushDescriptor PushDescriptorApi { get; private set; } internal ExtTransformFeedback TransformFeedbackApi { get; private set; } @@ -99,7 +100,10 @@ namespace Ryujinx.Graphics.Vulkan public bool PreferThreading => true; - public bool ExtendedLogicOp; + public PhysicalDeviceExtendedDynamicState2FeaturesEXT ExtendedDynamicState2Features; + + public PhysicalDeviceExtendedDynamicState3FeaturesEXT ExtendedDynamicState3Features; + public event EventHandler ScreenCaptured; @@ -141,6 +145,11 @@ namespace Ryujinx.Graphics.Vulkan ExtendedDynamicState2Api = extendedDynamicState2Api; } + if (Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExtendedDynamicState3 extendedDynamicState3Api)) + { + ExtendedDynamicState3Api = extendedDynamicState3Api; + } + if (Api.TryGetDeviceExtension(_instance.Instance, _device, out KhrPushDescriptor pushDescriptorApi)) { PushDescriptorApi = pushDescriptorApi; @@ -392,6 +401,7 @@ namespace Ryujinx.Graphics.Vulkan _physicalDevice.IsDeviceExtensionPresent(ExtConditionalRendering.ExtensionName), _physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState.ExtensionName), _physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName), + _physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState3.ExtensionName), features2.Features.MultiViewport && !(IsMoltenVk && Vendor == Vendor.Amd), // Workaround for AMD on MoltenVK issue featuresRobustness2.NullDescriptor || IsMoltenVk, supportsPushDescriptors && !IsMoltenVk, @@ -456,9 +466,10 @@ namespace Ryujinx.Graphics.Vulkan var queueFamilyIndex = VulkanInitialization.FindSuitableQueueFamily(Api, _physicalDevice, _surface, out uint maxQueueCount); - _device = VulkanInitialization.CreateDevice(Api, _physicalDevice, queueFamilyIndex, maxQueueCount, out bool extendedLogicOp); + _device = VulkanInitialization.CreateDevice(Api, _physicalDevice, queueFamilyIndex, maxQueueCount, out PhysicalDeviceExtendedDynamicState2FeaturesEXT extendedDynamicState2Features, out PhysicalDeviceExtendedDynamicState3FeaturesEXT extendedDynamicState3Features); - ExtendedLogicOp = extendedLogicOp; + ExtendedDynamicState2Features = extendedDynamicState2Features; + ExtendedDynamicState3Features = extendedDynamicState3Features; if (Api.TryGetDeviceExtension(_instance.Instance, _device, out KhrSwapchain swapchainApi)) { From 5f2d924bac19c428bfbb9de35f6f61b9c3c94ca9 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Fri, 17 May 2024 17:41:09 -0700 Subject: [PATCH 017/132] Misc --- src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index 4a1aa2b0b..ce3a34fdb 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -499,6 +499,9 @@ namespace Ryujinx.Graphics.Vulkan //Seems to be a error in Silk.Net bidings investigate further later supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3DepthClampEnable = false; + supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3LogicOpEnable = false; + supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3AlphaToCoverageEnable = false; + extendedDynamicState3Features = supportedFeaturesExtExtendedDynamicState3; From 767abfe5005ca5e73f0fe9370e69491e2de31b80 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 18 May 2024 14:31:38 -0700 Subject: [PATCH 018/132] Avoid unncessary state changes? --- .../PipelineDynamicState.cs | 244 +++++++++++------- 1 file changed, 148 insertions(+), 96 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 90d75724a..6a321c4c1 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -90,182 +90,229 @@ namespace Ryujinx.Graphics.Vulkan private DirtyFlags _dirty; + private const float Epsilon = 1e-6f; + + private bool FloatCompare(float a, float b) + { + return Math.Abs(a - b) < Epsilon; + } + public void SetBlendConstants(float r, float g, float b, float a) { - _blendConstants[0] = r; - _blendConstants[1] = g; - _blendConstants[2] = b; - _blendConstants[3] = a; - - _dirty |= DirtyFlags.Blend; + if (!FloatCompare(_blendConstants[0], r) || + !FloatCompare(_blendConstants[1], g) || + !FloatCompare(_blendConstants[2], b) || + !FloatCompare(_blendConstants[3], a)) + { + _blendConstants[0] = r; + _blendConstants[1] = g; + _blendConstants[2] = b; + _blendConstants[3] = a; + _dirty |= DirtyFlags.Blend; + } } public void SetDepthBias(float slopeFactor, float constantFactor, float clamp, bool enable) { - _depthBiasSlopeFactor = slopeFactor; - _depthBiasConstantFactor = constantFactor; - _depthBiasClamp = clamp; - _depthBiasEnable = enable; - - _dirty |= DirtyFlags.DepthBias; + if (!FloatCompare(_depthBiasSlopeFactor, slopeFactor) || + !FloatCompare(_depthBiasConstantFactor, constantFactor) || + !FloatCompare(_depthBiasClamp, clamp) || + _depthBiasEnable != enable) + { + _depthBiasSlopeFactor = slopeFactor; + _depthBiasConstantFactor = constantFactor; + _depthBiasClamp = clamp; + _depthBiasEnable = enable; + _dirty |= DirtyFlags.DepthBias; + } } public void SetScissor(int index, Rect2D scissor) { - _scissors[index] = scissor; - - _dirty |= DirtyFlags.Scissor; + if (!_scissors[index].Equals(scissor)) + { + _scissors[index] = scissor; + _dirty |= DirtyFlags.Scissor; + } } public void SetDepthTestBool(bool testEnable, bool writeEnable) { - _depthtestEnable = testEnable; - _depthwriteEnable = writeEnable; - - _dirty |= DirtyFlags.DepthTestBool; + if (_depthtestEnable != testEnable || _depthwriteEnable != writeEnable) + { + _depthtestEnable = testEnable; + _depthwriteEnable = writeEnable; + _dirty |= DirtyFlags.DepthTestBool; + } } public void SetDepthTestCompareOp(CompareOp depthTestOp) { - _depthCompareOp = depthTestOp; - - _dirty |= DirtyFlags.DepthTestCompareOp; + if (_depthCompareOp != depthTestOp) + { + _depthCompareOp = depthTestOp; + _dirty |= DirtyFlags.DepthTestCompareOp; + } } - public void SetStencilOp(StencilOp backFailOp, - StencilOp backPassOp, - StencilOp backDepthFailOp, - CompareOp backCompareOp, - StencilOp frontFailOp, - StencilOp frontPassOp, - StencilOp frontDepthFailOp, + 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; + if (_backfailop != backFailOp || _backpassop != backPassOp || _backdepthfailop != backDepthFailOp || + _backcompareop != backCompareOp || _frontfailop != frontFailOp || _frontpassop != frontPassOp || + _frontdepthfailop != frontDepthFailOp || _frontcompareop != 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, - uint backReference, - uint frontCompareMask, - uint frontWriteMask, - uint frontReference) + public void SetStencilMask(uint backCompareMask, uint backWriteMask, uint backReference, + uint frontCompareMask, uint frontWriteMask, uint frontReference) { - _backCompareMask = backCompareMask; - _backWriteMask = backWriteMask; - _backReference = backReference; - _frontCompareMask = frontCompareMask; - _frontWriteMask = frontWriteMask; - _frontReference = frontReference; - - _dirty |= DirtyFlags.Stencil; + if (_backCompareMask != backCompareMask || _backWriteMask != backWriteMask || + _backReference != backReference || _frontCompareMask != frontCompareMask || + _frontWriteMask != frontWriteMask || _frontReference != frontReference) + { + _backCompareMask = backCompareMask; + _backWriteMask = backWriteMask; + _backReference = backReference; + _frontCompareMask = frontCompareMask; + _frontWriteMask = frontWriteMask; + _frontReference = frontReference; + _dirty |= DirtyFlags.Stencil; + } } public void SetStencilTest(bool stencilTestEnable) { - _stencilTestEnable = stencilTestEnable; - - _dirty |= DirtyFlags.StencilTestEnable; + if (_stencilTestEnable != stencilTestEnable) + { + _stencilTestEnable = stencilTestEnable; + _dirty |= DirtyFlags.StencilTestEnable; + } } public void SetViewport(int index, Viewport viewport) { - Viewports[index] = viewport; - - _dirty |= DirtyFlags.Viewport; + if (!Viewports[index].Equals(viewport)) + { + Viewports[index] = viewport; + _dirty |= DirtyFlags.Viewport; + } } public void SetViewports(ref Array16 viewports, uint viewportsCount) { - Viewports = viewports; - ViewportsCount = viewportsCount; - - if (ViewportsCount != 0) + if (!Viewports.Equals(viewports) || ViewportsCount != viewportsCount) { - _dirty |= DirtyFlags.Viewport; + Viewports = viewports; + ViewportsCount = viewportsCount; + if (ViewportsCount != 0) + { + _dirty |= DirtyFlags.Viewport; + } } } public void SetCullMode(CullModeFlags cullMode) { - CullMode = cullMode; - - _dirty |= DirtyFlags.CullMode; + if (CullMode != cullMode) + { + CullMode = cullMode; + _dirty |= DirtyFlags.CullMode; + } } public void SetFrontFace(FrontFace frontFace) { - FrontFace = frontFace; - - _dirty |= DirtyFlags.FrontFace; + if (FrontFace != frontFace) + { + FrontFace = frontFace; + _dirty |= DirtyFlags.FrontFace; + } } public void SetLineWidth(float width) { - _linewidth = width; + if (!FloatCompare(_linewidth, width)) + { + _linewidth = width; - _dirty |= DirtyFlags.LineWidth; + _dirty |= DirtyFlags.LineWidth; + } } public void SetRasterizerDiscard(bool discard) { - _discard = discard; - - _dirty |= DirtyFlags.RasterDiscard; + if (_discard != discard) + { + _discard = discard; + _dirty |= DirtyFlags.RasterDiscard; + } } public void SetLogicOp(LogicOp op) { - _logicOp = op; - - _dirty |= DirtyFlags.LogicOp; + if (_logicOp != op) + { + _logicOp = op; + _dirty |= DirtyFlags.LogicOp; + } } public void SetPatchControlPoints(uint points) { - _patchControlPoints = points; - - _dirty |= DirtyFlags.PatchControlPoints; + if (_patchControlPoints != points) + { + _patchControlPoints = points; + _dirty |= DirtyFlags.PatchControlPoints; + } } public void SetLogicOpEnable(bool logicOpEnable) { - _logicOpEnable = logicOpEnable; - - _dirty |= DirtyFlags.LogicOpEnalbe; + if (_logicOpEnable != logicOpEnable) + { + _logicOpEnable = logicOpEnable; + _dirty |= DirtyFlags.LogicOpEnalbe; + } } public void SetDepthClampEnable(bool depthClampEnable) { - _depthClampEnable = depthClampEnable; - - _dirty |= DirtyFlags.DepthClampEnable; + if (_depthClampEnable != depthClampEnable) + { + _depthClampEnable = depthClampEnable; + _dirty |= DirtyFlags.DepthClampEnable; + } } public void SetAlphaToCoverEnable(bool alphaToCoverEnable) { - _alphaToCoverEnable = alphaToCoverEnable; - - _dirty |= DirtyFlags.AlphaToCover; + if (_alphaToCoverEnable != alphaToCoverEnable) + { + _alphaToCoverEnable = alphaToCoverEnable; + _dirty |= DirtyFlags.AlphaToCover; + } } public void SetAlphaToOneEnable(bool alphaToOneEnable) { - _alphaToOneEnable = alphaToOneEnable; - - _dirty |= DirtyFlags.AlphaToOne; + if (_alphaToOneEnable != alphaToOneEnable) + { + _alphaToOneEnable = alphaToOneEnable; + _dirty |= DirtyFlags.AlphaToOne; + } } public void ForceAllDirty(VulkanRenderer gd) @@ -418,7 +465,7 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetBlendConstants(commandBuffer, _blendConstants.AsSpan()); } - private readonly void RecordDepthBias(VulkanRenderer gd, CommandBuffer commandBuffer) + private void RecordDepthBias(VulkanRenderer gd, CommandBuffer commandBuffer) { gd.Api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); @@ -517,6 +564,11 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) { + if (!_logicOpEnable) + { + return; + } + gd.ExtendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp); } From eeecd894b920701e728eecf41a3f2baa88e3776d Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 18 May 2024 14:57:53 -0700 Subject: [PATCH 019/132] Add Some Comments --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index e4fe002d9..57b531575 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -451,6 +451,7 @@ namespace Ryujinx.Graphics.Vulkan primitiveRestartEnable &= topologySupportsRestart; + //Cannot disable primitveRestartEnable for these Topoligies on MacOS if ((Topology == PrimitiveTopology.LineStrip || Topology == PrimitiveTopology.TriangleStrip || Topology == PrimitiveTopology.LineStripWithAdjacency || Topology == PrimitiveTopology.TriangleStripWithAdjacency) && isMoltenVk) @@ -675,6 +676,7 @@ namespace Ryujinx.Graphics.Vulkan if (!isMoltenVk) { + //LineWidth is only supported on MacOS when using Metal Private API on newer version of MoltenVK dynamicStates[currentIndex++] = DynamicState.LineWidth; } @@ -682,6 +684,7 @@ namespace Ryujinx.Graphics.Vulkan { if (!isMoltenVk) { + //Requires Metal 3.1 dynamicStates[currentIndex++] = DynamicState.VertexInputBindingStrideExt; } dynamicStates[currentIndex++] = DynamicState.CullModeExt; From fd9b4cc10fb66dd73d638aa85f501b9ad5cb4804 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 18 May 2024 15:22:23 -0700 Subject: [PATCH 020/132] More comments and formatting fixes --- .../PipelineDynamicState.cs | 20 +++++++++---------- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 3 ++- .../VulkanInitialization.cs | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 6a321c4c1..303633df0 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -92,7 +92,7 @@ namespace Ryujinx.Graphics.Vulkan private const float Epsilon = 1e-6f; - private bool FloatCompare(float a, float b) + private readonly bool FloatCompare(float a, float b) { return Math.Abs(a - b) < Epsilon; } @@ -155,12 +155,12 @@ namespace Ryujinx.Graphics.Vulkan } } - public void SetStencilOp(StencilOp backFailOp, StencilOp backPassOp, StencilOp backDepthFailOp, - CompareOp backCompareOp, StencilOp frontFailOp, StencilOp frontPassOp, StencilOp frontDepthFailOp, + public void SetStencilOp(StencilOp backFailOp, StencilOp backPassOp, StencilOp backDepthFailOp, + CompareOp backCompareOp, StencilOp frontFailOp, StencilOp frontPassOp, StencilOp frontDepthFailOp, CompareOp frontCompareOp) { - if (_backfailop != backFailOp || _backpassop != backPassOp || _backdepthfailop != backDepthFailOp || - _backcompareop != backCompareOp || _frontfailop != frontFailOp || _frontpassop != frontPassOp || + if (_backfailop != backFailOp || _backpassop != backPassOp || _backdepthfailop != backDepthFailOp || + _backcompareop != backCompareOp || _frontfailop != frontFailOp || _frontpassop != frontPassOp || _frontdepthfailop != frontDepthFailOp || _frontcompareop != frontCompareOp) { _backfailop = backFailOp; @@ -175,11 +175,11 @@ namespace Ryujinx.Graphics.Vulkan } } - public void SetStencilMask(uint backCompareMask, uint backWriteMask, uint backReference, + public void SetStencilMask(uint backCompareMask, uint backWriteMask, uint backReference, uint frontCompareMask, uint frontWriteMask, uint frontReference) { - if (_backCompareMask != backCompareMask || _backWriteMask != backWriteMask || - _backReference != backReference || _frontCompareMask != frontCompareMask || + if (_backCompareMask != backCompareMask || _backWriteMask != backWriteMask || + _backReference != backReference || _frontCompareMask != frontCompareMask || _frontWriteMask != frontWriteMask || _frontReference != frontReference) { _backCompareMask = backCompareMask; @@ -465,7 +465,7 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetBlendConstants(commandBuffer, _blendConstants.AsSpan()); } - private void RecordDepthBias(VulkanRenderer gd, CommandBuffer commandBuffer) + private readonly void RecordDepthBias(VulkanRenderer gd, CommandBuffer commandBuffer) { gd.Api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); @@ -568,7 +568,7 @@ namespace Ryujinx.Graphics.Vulkan { return; } - + gd.ExtendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 57b531575..841512854 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -481,6 +481,7 @@ namespace Ryujinx.Graphics.Vulkan if (isMoltenVk) { + //When widelines feature is not supported it must be 1.0f per spec. rasterizationState.LineWidth = 1.0f; } @@ -684,7 +685,7 @@ namespace Ryujinx.Graphics.Vulkan { if (!isMoltenVk) { - //Requires Metal 3.1 + //Requires Metal 3.1 and new MoltenVK dynamicStates[currentIndex++] = DynamicState.VertexInputBindingStrideExt; } dynamicStates[currentIndex++] = DynamicState.CullModeExt; diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index ce3a34fdb..8f9e926c1 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -502,7 +502,7 @@ namespace Ryujinx.Graphics.Vulkan supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3LogicOpEnable = false; supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3AlphaToCoverageEnable = false; - + extendedDynamicState3Features = supportedFeaturesExtExtendedDynamicState3; var featuresVk11 = new PhysicalDeviceVulkan11Features From 404f4be9e7348eae8ab651416a9c8b321ea388c9 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 18 May 2024 15:32:36 -0700 Subject: [PATCH 021/132] Enable the extension... --- src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index 8f9e926c1..1c8b675dc 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -24,6 +24,7 @@ namespace Ryujinx.Graphics.Vulkan ExtConditionalRendering.ExtensionName, ExtExtendedDynamicState.ExtensionName, ExtExtendedDynamicState2.ExtensionName, + ExtExtendedDynamicState3.ExtensionName, ExtTransformFeedback.ExtensionName, KhrDrawIndirectCount.ExtensionName, KhrPushDescriptor.ExtensionName, @@ -497,12 +498,6 @@ namespace Ryujinx.Graphics.Vulkan pExtendedFeatures = &featuresExtendedDynamicState3; } - //Seems to be a error in Silk.Net bidings investigate further later - supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3DepthClampEnable = false; - supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3LogicOpEnable = false; - supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3AlphaToCoverageEnable = false; - - extendedDynamicState3Features = supportedFeaturesExtExtendedDynamicState3; var featuresVk11 = new PhysicalDeviceVulkan11Features From 0f2ed45f96e8bf6f6f6c15fbf33c7f7af6ed9303 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 18 May 2024 15:53:24 -0700 Subject: [PATCH 022/132] Revert "Enable the extension..." This reverts commit 8bbdaab9a1aa22dd14d3f49b9253cc9d1a372844. --- src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index 1c8b675dc..8f9e926c1 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -24,7 +24,6 @@ namespace Ryujinx.Graphics.Vulkan ExtConditionalRendering.ExtensionName, ExtExtendedDynamicState.ExtensionName, ExtExtendedDynamicState2.ExtensionName, - ExtExtendedDynamicState3.ExtensionName, ExtTransformFeedback.ExtensionName, KhrDrawIndirectCount.ExtensionName, KhrPushDescriptor.ExtensionName, @@ -498,6 +497,12 @@ namespace Ryujinx.Graphics.Vulkan pExtendedFeatures = &featuresExtendedDynamicState3; } + //Seems to be a error in Silk.Net bidings investigate further later + supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3DepthClampEnable = false; + supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3LogicOpEnable = false; + supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3AlphaToCoverageEnable = false; + + extendedDynamicState3Features = supportedFeaturesExtExtendedDynamicState3; var featuresVk11 = new PhysicalDeviceVulkan11Features From 5bf0937be1153fb6d44b9413f5f6162eb20a56e6 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 18 May 2024 15:55:16 -0700 Subject: [PATCH 023/132] Reverted previous commit as it caused mass seizures, disable for now. --- src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index 8f9e926c1..3446941ab 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -497,10 +497,11 @@ namespace Ryujinx.Graphics.Vulkan pExtendedFeatures = &featuresExtendedDynamicState3; } - //Seems to be a error in Silk.Net bidings investigate further later + //Need To Enable the extension, once this is fixed supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3DepthClampEnable = false; supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3LogicOpEnable = false; supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3AlphaToCoverageEnable = false; + supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3LogicOpEnable = false; extendedDynamicState3Features = supportedFeaturesExtExtendedDynamicState3; From 2483b1a52ab02fe5bf1cd3ce89dd32673a875482 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 18 May 2024 16:06:21 -0700 Subject: [PATCH 024/132] Enable VK_EXT_extended_dynamic_state3 this time without seizures. --- .../PipelineDynamicState.cs | 30 +++++++++++-------- .../VulkanInitialization.cs | 8 +---- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 303633df0..94bb9e175 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -79,13 +79,14 @@ namespace Ryujinx.Graphics.Vulkan RasterDiscard = 1 << 11, LogicOp = 1 << 12, DepthClampEnable = 1 << 13, - LogicOpEnalbe = 1 << 14, + LogicOpEnable = 1 << 14, AlphaToCover = 1 << 15, AlphaToOne = 1 << 16, PatchControlPoints = 1 << 17, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable, Extended2 = RasterDiscard | LogicOp | PatchControlPoints, + Extended3 = DepthClampEnable | LogicOpEnable | AlphaToCover | AlphaToOne, } private DirtyFlags _dirty; @@ -284,7 +285,7 @@ namespace Ryujinx.Graphics.Vulkan if (_logicOpEnable != logicOpEnable) { _logicOpEnable = logicOpEnable; - _dirty |= DirtyFlags.LogicOpEnalbe; + _dirty |= DirtyFlags.LogicOpEnable; } } @@ -328,7 +329,12 @@ namespace Ryujinx.Graphics.Vulkan { _dirty = DirtyFlags.Standard | DirtyFlags.Extended | DirtyFlags.Extended2; } - + + if (gd.Capabilities.SupportsExtendedDynamicState3) + { + _dirty = DirtyFlags.Standard | DirtyFlags.Extended | DirtyFlags.Extended2 | DirtyFlags.Extended3; + } + if (gd.IsMoltenVk) { _dirty &= ~DirtyFlags.LineWidth; @@ -344,24 +350,24 @@ namespace Ryujinx.Graphics.Vulkan _dirty &= ~DirtyFlags.LogicOp; } - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable) + if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable) { - _dirty = DirtyFlags.AlphaToCover; + _dirty &= ~DirtyFlags.AlphaToCover; } - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable) + if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable) { - _dirty = DirtyFlags.AlphaToOne; + _dirty &= ~DirtyFlags.AlphaToOne; } - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable) + if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable) { - _dirty = DirtyFlags.DepthClampEnable; + _dirty &= ~DirtyFlags.DepthClampEnable; } - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable) + if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable) { - _dirty = DirtyFlags.LogicOpEnalbe; + _dirty &= ~DirtyFlags.LogicOpEnable; } } @@ -437,7 +443,7 @@ namespace Ryujinx.Graphics.Vulkan RecordPatchControlPoints(gd, commandBuffer); } - if (_dirty.HasFlag(DirtyFlags.LogicOpEnalbe)) + if (_dirty.HasFlag(DirtyFlags.LogicOpEnable)) { RecordLogicOpEnable(gd, commandBuffer); } diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index 3446941ab..1c8b675dc 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -24,6 +24,7 @@ namespace Ryujinx.Graphics.Vulkan ExtConditionalRendering.ExtensionName, ExtExtendedDynamicState.ExtensionName, ExtExtendedDynamicState2.ExtensionName, + ExtExtendedDynamicState3.ExtensionName, ExtTransformFeedback.ExtensionName, KhrDrawIndirectCount.ExtensionName, KhrPushDescriptor.ExtensionName, @@ -497,13 +498,6 @@ namespace Ryujinx.Graphics.Vulkan pExtendedFeatures = &featuresExtendedDynamicState3; } - //Need To Enable the extension, once this is fixed - supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3DepthClampEnable = false; - supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3LogicOpEnable = false; - supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3AlphaToCoverageEnable = false; - supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3LogicOpEnable = false; - - extendedDynamicState3Features = supportedFeaturesExtExtendedDynamicState3; var featuresVk11 = new PhysicalDeviceVulkan11Features From d4e4ddca9175dda08d6296dfffe5f501cefc042f Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 18 May 2024 16:13:12 -0700 Subject: [PATCH 025/132] Fix formatting --- src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 94bb9e175..f1b802bed 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -329,12 +329,12 @@ namespace Ryujinx.Graphics.Vulkan { _dirty = DirtyFlags.Standard | DirtyFlags.Extended | DirtyFlags.Extended2; } - + if (gd.Capabilities.SupportsExtendedDynamicState3) { _dirty = DirtyFlags.Standard | DirtyFlags.Extended | DirtyFlags.Extended2 | DirtyFlags.Extended3; } - + if (gd.IsMoltenVk) { _dirty &= ~DirtyFlags.LineWidth; From 3fe159f4dd81000474d51b05d5063fa4354cf8dd Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 18 May 2024 17:20:20 -0700 Subject: [PATCH 026/132] Small fix --- .../PipelineDynamicState.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index f1b802bed..8f15cc61b 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -473,12 +473,17 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordDepthBias(VulkanRenderer gd, CommandBuffer commandBuffer) { - gd.Api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); - if (gd.Capabilities.SupportsExtendedDynamicState2) { gd.ExtendedDynamicState2Api.CmdSetDepthBiasEnable(commandBuffer, _depthBiasEnable); + + if (!_depthBiasEnable) + { + return; + } } + + gd.Api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); } private void RecordScissor(VulkanRenderer gd, CommandBuffer commandBuffer) @@ -501,7 +506,7 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordStencil(VulkanRenderer gd, CommandBuffer commandBuffer) { - if (_opToo) + if (_opToo && _stencilTestEnable) { gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceBackBit, _backfailop, _backpassop, _backdepthfailop, _backcompareop); @@ -555,6 +560,7 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordDepthTestBool(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetDepthTestEnable(commandBuffer, _depthtestEnable); + api.CmdSetDepthWriteEnable(commandBuffer, _depthwriteEnable); } @@ -570,7 +576,7 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) { - if (!_logicOpEnable) + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable && !_logicOpEnable) { return; } From ecadc6a4f91a42c98c1d6a9f97791cbae5238780 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 18 May 2024 21:46:22 -0700 Subject: [PATCH 027/132] Implement VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 16 ++++++++-- .../PipelineDynamicState.cs | 29 ++++++++++++++++++- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 6 +++- .../VulkanInitialization.cs | 1 + 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 5024fdd4e..4b9d32ee9 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -898,9 +898,19 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthMode(DepthMode mode) { - bool oldMode = _newState.DepthMode; - _newState.DepthMode = mode == DepthMode.MinusOneToOne; - if (_newState.DepthMode != oldMode) + bool oldMode; + if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne) + { + oldMode = DynamicState.DepthMode; + DynamicState.SetDepthMode(mode == DepthMode.MinusOneToOne); + } + else + { + oldMode = _newState.DepthMode; + _newState.DepthMode = mode == DepthMode.MinusOneToOne; + } + + if ((Gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne ? DynamicState.DepthMode : _newState.DepthMode) != oldMode) { SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 8f15cc61b..9126771a0 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -61,6 +61,8 @@ namespace Ryujinx.Graphics.Vulkan private bool _alphaToCoverEnable; private bool _alphaToOneEnable; + public bool DepthMode; + [Flags] private enum DirtyFlags { @@ -83,10 +85,11 @@ namespace Ryujinx.Graphics.Vulkan AlphaToCover = 1 << 15, AlphaToOne = 1 << 16, PatchControlPoints = 1 << 17, + DepthMode = 1 << 18, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable, Extended2 = RasterDiscard | LogicOp | PatchControlPoints, - Extended3 = DepthClampEnable | LogicOpEnable | AlphaToCover | AlphaToOne, + Extended3 = DepthClampEnable | LogicOpEnable | AlphaToCover | AlphaToOne | DepthMode, } private DirtyFlags _dirty; @@ -315,6 +318,15 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.AlphaToOne; } } + + public void SetDepthMode(bool mode) + { + if (DepthMode != mode) + { + DepthMode = mode; + _dirty |= DirtyFlags.DepthMode; + } + } public void ForceAllDirty(VulkanRenderer gd) { @@ -369,6 +381,11 @@ namespace Ryujinx.Graphics.Vulkan { _dirty &= ~DirtyFlags.LogicOpEnable; } + + if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne) + { + _dirty &= ~DirtyFlags.DepthMode; + } } public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) @@ -462,6 +479,11 @@ namespace Ryujinx.Graphics.Vulkan { RecordAlphaToOneEnable(gd, commandBuffer); } + + if (_dirty.HasFlag(DirtyFlags.DepthMode)) + { + RecordDepthMode(gd, commandBuffer); + } _dirty = DirtyFlags.None; } @@ -608,6 +630,11 @@ namespace Ryujinx.Graphics.Vulkan { gd.ExtendedDynamicState2Api.CmdSetPatchControlPoints(commandBuffer, _patchControlPoints); } + + private readonly void RecordDepthMode(VulkanRenderer gd, CommandBuffer commandBuffer) + { + gd.ExtendedDynamicState3Api.CmdSetDepthClipNegativeOneToOne(commandBuffer, DepthMode); + } private readonly void RecordLineWidth(Vk api, CommandBuffer commandBuffer) { diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 841512854..01cf1741c 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -513,9 +513,13 @@ namespace Ryujinx.Graphics.Vulkan var viewportDepthClipControlState = new PipelineViewportDepthClipControlCreateInfoEXT { SType = StructureType.PipelineViewportDepthClipControlCreateInfoExt, - NegativeOneToOne = DepthMode, }; + if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne) + { + viewportDepthClipControlState.NegativeOneToOne = DepthMode; + } + viewportState.PNext = &viewportDepthClipControlState; } diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index 1c8b675dc..4b8c15526 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -493,6 +493,7 @@ namespace Ryujinx.Graphics.Vulkan ExtendedDynamicState3AlphaToCoverageEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3AlphaToCoverageEnable, ExtendedDynamicState3AlphaToOneEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3AlphaToOneEnable, ExtendedDynamicState3DepthClampEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3DepthClampEnable, + ExtendedDynamicState3DepthClipNegativeOneToOne = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3DepthClipNegativeOneToOne, }; pExtendedFeatures = &featuresExtendedDynamicState3; From ab7f379e114061e3ece91c918557c27313da5cae Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 18 May 2024 21:48:27 -0700 Subject: [PATCH 028/132] Formatting --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 +- src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 4b9d32ee9..fff6cf05e 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -909,7 +909,7 @@ namespace Ryujinx.Graphics.Vulkan oldMode = _newState.DepthMode; _newState.DepthMode = mode == DepthMode.MinusOneToOne; } - + if ((Gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne ? DynamicState.DepthMode : _newState.DepthMode) != oldMode) { SignalStateChange(); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 9126771a0..bc9939d6c 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -318,7 +318,7 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.AlphaToOne; } } - + public void SetDepthMode(bool mode) { if (DepthMode != mode) @@ -381,7 +381,7 @@ namespace Ryujinx.Graphics.Vulkan { _dirty &= ~DirtyFlags.LogicOpEnable; } - + if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne) { _dirty &= ~DirtyFlags.DepthMode; @@ -479,7 +479,7 @@ namespace Ryujinx.Graphics.Vulkan { RecordAlphaToOneEnable(gd, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.DepthMode)) { RecordDepthMode(gd, commandBuffer); @@ -630,7 +630,7 @@ namespace Ryujinx.Graphics.Vulkan { gd.ExtendedDynamicState2Api.CmdSetPatchControlPoints(commandBuffer, _patchControlPoints); } - + private readonly void RecordDepthMode(VulkanRenderer gd, CommandBuffer commandBuffer) { gd.ExtendedDynamicState3Api.CmdSetDepthClipNegativeOneToOne(commandBuffer, DepthMode); From 863674768d861d79178bfca71daa1758df700d83 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 18 May 2024 22:14:38 -0700 Subject: [PATCH 029/132] Some more small changes --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 6 ++++-- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 8 ++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index fff6cf05e..e29fab326 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -899,7 +899,9 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthMode(DepthMode mode) { bool oldMode; - if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne) + bool supportsDepthClipandDynamicState = Gd.Capabilities.SupportsDepthClipControl && + Gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne; + if (supportsDepthClipandDynamicState) { oldMode = DynamicState.DepthMode; DynamicState.SetDepthMode(mode == DepthMode.MinusOneToOne); @@ -910,7 +912,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.DepthMode = mode == DepthMode.MinusOneToOne; } - if ((Gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne ? DynamicState.DepthMode : _newState.DepthMode) != oldMode) + if ((supportsDepthClipandDynamicState ? DynamicState.DepthMode : _newState.DepthMode) != oldMode) { SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 01cf1741c..d461ab323 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -508,18 +508,14 @@ namespace Ryujinx.Graphics.Vulkan viewportState.ScissorCount = ScissorsCount; } - if (gd.Capabilities.SupportsDepthClipControl) + if (gd.Capabilities.SupportsDepthClipControl && !gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne) { var viewportDepthClipControlState = new PipelineViewportDepthClipControlCreateInfoEXT { SType = StructureType.PipelineViewportDepthClipControlCreateInfoExt, + NegativeOneToOne = DepthMode, }; - if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne) - { - viewportDepthClipControlState.NegativeOneToOne = DepthMode; - } - viewportState.PNext = &viewportDepthClipControlState; } From 5d5f482d57d10a34172cb6acbcc3fee05b68792f Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 19 May 2024 00:24:07 -0700 Subject: [PATCH 030/132] Enable VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 44 +++++++++++-- .../PipelineDynamicState.cs | 65 ++++++++++++------- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 36 ++-------- 3 files changed, 90 insertions(+), 55 deletions(-) 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) { From 8bb369f37d7166be12b0e3157767d1d85aa2df9e Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 19 May 2024 10:31:53 -0700 Subject: [PATCH 031/132] Missed enabling Dynamic State --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 3 +-- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 8 ++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 696b5c1cb..f78184c3b 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -899,8 +899,7 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthMode(DepthMode mode) { bool oldMode; - bool supportsDepthClipandDynamicState = Gd.Capabilities.SupportsDepthClipControl && - Gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne; + bool supportsDepthClipandDynamicState = Gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne; if (supportsDepthClipandDynamicState) { oldMode = DynamicState.DepthMode; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 7ae909e16..479279916 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -637,6 +637,10 @@ namespace Ryujinx.Graphics.Vulkan { additionalDynamicStatesCount++; } + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne) + { + additionalDynamicStatesCount++; + } } int dynamicStatesCount = baseDynamicStatesCount + additionalDynamicStatesCount; @@ -710,6 +714,10 @@ namespace Ryujinx.Graphics.Vulkan { dynamicStates[currentIndex++] = DynamicState.AlphaToOneEnableExt; } + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne) + { + dynamicStates[currentIndex++] = DynamicState.DepthClipNegativeOneToOneExt; + } } var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo From 6c6cd8927ae004f6f6e141c0becdf4e67604d086 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 19 May 2024 10:43:07 -0700 Subject: [PATCH 032/132] Combine compatibility check. --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 26 +++++++------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 479279916..3ddb21dad 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -438,11 +438,6 @@ namespace Ryujinx.Graphics.Vulkan Topology = Topology, }; - if (!supportsExtDynamicState) - { - inputAssemblyState.PrimitiveRestartEnable = PrimitiveRestartEnable; - } - var tessellationState = new PipelineTessellationStateCreateInfo { SType = StructureType.PipelineTessellationStateCreateInfo, @@ -461,12 +456,7 @@ namespace Ryujinx.Graphics.Vulkan //When widelines feature is not supported it must be 1.0f per spec. rasterizationState.LineWidth = 1.0f; } - - if (!supportsExtDynamicState) - { - rasterizationState.CullMode = CullMode; - rasterizationState.FrontFace = FrontFace; - } + if (!supportsExtDynamicState2) { @@ -479,12 +469,6 @@ namespace Ryujinx.Graphics.Vulkan SType = StructureType.PipelineViewportStateCreateInfo, }; - if (!supportsExtDynamicState) - { - viewportState.ViewportCount = ViewportsCount; - viewportState.ScissorCount = ScissorsCount; - } - if (gd.Capabilities.SupportsDepthClipControl && !gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne) { var viewportDepthClipControlState = new PipelineViewportDepthClipControlCreateInfoEXT @@ -516,6 +500,14 @@ namespace Ryujinx.Graphics.Vulkan if (!supportsExtDynamicState) { + inputAssemblyState.PrimitiveRestartEnable = PrimitiveRestartEnable; + + rasterizationState.CullMode = CullMode; + rasterizationState.FrontFace = FrontFace; + + viewportState.ViewportCount = ViewportsCount; + viewportState.ScissorCount = ScissorsCount; + var stencilFront = new StencilOpState( StencilFrontFailOp, StencilFrontPassOp, From f30a8f1580c21eb645de63094ee87bbf2cc450bc Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 19 May 2024 11:15:29 -0700 Subject: [PATCH 033/132] Whitespace --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 3ddb21dad..8ab9f9dfd 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -456,7 +456,7 @@ namespace Ryujinx.Graphics.Vulkan //When widelines feature is not supported it must be 1.0f per spec. rasterizationState.LineWidth = 1.0f; } - + if (!supportsExtDynamicState2) { @@ -501,13 +501,13 @@ namespace Ryujinx.Graphics.Vulkan if (!supportsExtDynamicState) { inputAssemblyState.PrimitiveRestartEnable = PrimitiveRestartEnable; - + rasterizationState.CullMode = CullMode; rasterizationState.FrontFace = FrontFace; - + viewportState.ViewportCount = ViewportsCount; viewportState.ScissorCount = ScissorsCount; - + var stencilFront = new StencilOpState( StencilFrontFailOp, StencilFrontPassOp, From 76c9c2ac8c33346a80489d3ca3f565c7666d6eea Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Tue, 21 May 2024 11:16:57 -0700 Subject: [PATCH 034/132] Resolve the below validation errors. VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-01442(ERROR / SPEC): msgNum: 1313692360 - Validation Error: [ VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-01442 ] | MessageID = 0x4e4d5ac8 | vkCreateGraphicsPipelines(): pCreateInfos[0].pDynamicState has VK_DYNAMIC_STATE_VIEWPORT at pDynamicStates[0] and pDynamicStates[28]. The Vulkan spec states: Each element of pDynamicStates must be unique (https://vulkan.lunarg.com/doc/view/1.3.283.0/windows/1.3-extensions/vkspec.html#VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-01442) Objects: 0 VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04132(ERROR / SPEC): msgNum: -206448348 - Validation Error: [ VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04132 ] | MessageID = 0xf3b1d924 | vkCreateGraphicsPipelines(): pCreateInfos[0].pDynamicState pDynamicStates[15] is VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT and pDynamicStates[28] is VK_DYNAMIC_STATE_VIEWPORT. The Vulkan spec states: If the pipeline requires pre-rasterization shader state, and VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT is included in the pDynamicStates array then VK_DYNAMIC_STATE_VIEWPORT must not be present (https://vulkan.lunarg.com/doc/view/1.3.283.0/windows/1.3-extensions/vkspec.html#VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04132) Objects: 0 VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04133(ERROR / SPEC): msgNum: -858144982 - Validation Error: [ VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04133 ] | MessageID = 0xccd9bf2a | vkCreateGraphicsPipelines(): pCreateInfos[0].pDynamicState pDynamicStates[16] is VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT and pDynamicStates[1] is VK_DYNAMIC_STATE_SCISSOR. The Vulkan spec states: If the pipeline requires pre-rasterization shader state, and VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT is included in the pDynamicStates array then VK_DYNAMIC_STATE_SCISSOR must not be present (https://vulkan.lunarg.com/doc/view/1.3.283.0/windows/1.3-extensions/vkspec.html#VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04133) Objects: 0 --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 8ab9f9dfd..50e3926ca 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -595,7 +595,7 @@ namespace Ryujinx.Graphics.Vulkan if (supportsExtDynamicState) { - additionalDynamicStatesCount += isMoltenVk ? 10 : 11; + additionalDynamicStatesCount += isMoltenVk ? 7 : 8; } if (supportsExtDynamicState2) @@ -661,14 +661,14 @@ namespace Ryujinx.Graphics.Vulkan //Requires Metal 3.1 and new MoltenVK dynamicStates[currentIndex++] = DynamicState.VertexInputBindingStrideExt; } + dynamicStates[0] = DynamicState.ViewportWithCountExt; + dynamicStates[1] = DynamicState.ScissorWithCountExt; dynamicStates[currentIndex++] = DynamicState.CullModeExt; dynamicStates[currentIndex++] = DynamicState.FrontFaceExt; dynamicStates[currentIndex++] = DynamicState.DepthTestEnableExt; dynamicStates[currentIndex++] = DynamicState.DepthWriteEnableExt; dynamicStates[currentIndex++] = DynamicState.DepthCompareOpExt; dynamicStates[currentIndex++] = DynamicState.StencilTestEnableExt; - dynamicStates[currentIndex++] = DynamicState.ViewportWithCountExt; - dynamicStates[currentIndex++] = DynamicState.ScissorWithCountExt; dynamicStates[currentIndex++] = DynamicState.StencilOpExt; } From de5cb66caf282ffd5b17b310e5e5a567dad027ed Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Tue, 21 May 2024 11:47:33 -0700 Subject: [PATCH 035/132] Resolve below validation error VUID-vkCmdDraw-logicOp-04878(ERROR / SPEC): msgNum: 282117419 - Validation Error: [ VUID-vkCmdDraw-logicOp-04878 ] Object 0: handle = 0x2db247c7370, type = VK_OBJECT_TYPE_COMMAND_BUFFER; Object 1: handle = 0x81dc7e0000000305, type = VK_OBJECT_TYPE_PIPELINE; | MessageID = 0x10d0c52b | vkCmdDraw(): VK_DYNAMIC_STATE_LOGIC_OP_EXT state not set for this command buffer. The Vulkan spec states: If the bound graphics pipeline state was created with the VK_DYNAMIC_STATE_LOGIC_OP_EXT dynamic state enabled then vkCmdSetLogicOpEXT must have been called in the current command buffer prior to this drawing command and the logicOp must be a valid VkLogicOp value (https://vulkan.lunarg.com/doc/view/1.3.283.0/windows/1.3-extensions/vkspec.html#VUID-vkCmdDraw-logicOp-04878) Objects: 2 [0] 0x2db247c7370, type: 6, name: NULL [1] 0x81dc7e0000000305, type: 19, name: NULL --- src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 5d4b473d0..4d231684a 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -619,11 +619,6 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) { - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable && !_logicOpEnable) - { - return; - } - gd.ExtendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp); } From 7d7b1923aa08cf1811804f35c82cdcdacc99c439 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Tue, 21 May 2024 18:26:21 -0700 Subject: [PATCH 036/132] Resolve VUID-vkCmdSetPatchControlPointsEXT-None-09422(ERROR / SPEC): msgNum: -1559328192 - Validation Error: [ VUID-vkCmdSetPatchControlPointsEXT-None-09422 ] Object 0: handle = 0x25f0eb40170, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0xa30e8a40 | vkCmdSetPatchControlPointsEXT(): extendedDynamicState2PatchControlPoints or shaderObject feature is not enabled. The Vulkan spec states: At least one of the following must be true: The extendedDynamicState2PatchControlPoints feature is enabled The shaderObject feature is enabled (https://vulkan.lunarg.com/doc/view/1.3.283.0/windows/1.3-extensions/vkspec.html#VUID-vkCmdSetPatchControlPointsEXT-None-09422) Objects: 1 [0] 0x25f0eb40170, type: 6, name: NULL --- src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 4d231684a..cb248097b 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -370,7 +370,7 @@ namespace Ryujinx.Graphics.Vulkan if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) { - _dirty &= ~DirtyFlags.LogicOp; + _dirty &= ~DirtyFlags.PatchControlPoints; } if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable) From dcc999c79821d1f3491e075c4d0ef23ad85a703f Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Tue, 21 May 2024 20:24:49 -0700 Subject: [PATCH 037/132] Set dirty flag even when value has not changed. --- .../PipelineDynamicState.cs | 208 ++++++------------ 1 file changed, 67 insertions(+), 141 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index cb248097b..61d9a6502 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -97,124 +97,81 @@ namespace Ryujinx.Graphics.Vulkan private DirtyFlags _dirty; - private const float Epsilon = 1e-6f; - - private readonly bool FloatCompare(float a, float b) - { - return Math.Abs(a - b) < Epsilon; - } - public void SetBlendConstants(float r, float g, float b, float a) { - if (!FloatCompare(_blendConstants[0], r) || - !FloatCompare(_blendConstants[1], g) || - !FloatCompare(_blendConstants[2], b) || - !FloatCompare(_blendConstants[3], a)) - { - _blendConstants[0] = r; - _blendConstants[1] = g; - _blendConstants[2] = b; - _blendConstants[3] = a; - _dirty |= DirtyFlags.Blend; - } + _blendConstants[0] = r; + _blendConstants[1] = g; + _blendConstants[2] = b; + _blendConstants[3] = a; + _dirty |= DirtyFlags.Blend; } public void SetDepthBias(float slopeFactor, float constantFactor, float clamp, bool enable) { - if (!FloatCompare(_depthBiasSlopeFactor, slopeFactor) || - !FloatCompare(_depthBiasConstantFactor, constantFactor) || - !FloatCompare(_depthBiasClamp, clamp) || - _depthBiasEnable != enable) - { - _depthBiasSlopeFactor = slopeFactor; - _depthBiasConstantFactor = constantFactor; - _depthBiasClamp = clamp; - _depthBiasEnable = enable; - _dirty |= DirtyFlags.DepthBias; - } + _depthBiasSlopeFactor = slopeFactor; + _depthBiasConstantFactor = constantFactor; + _depthBiasClamp = clamp; + + _depthBiasEnable = enable; + _dirty |= DirtyFlags.DepthBias; } public void SetScissor(int index, Rect2D scissor) { - if (!_scissors[index].Equals(scissor)) - { - _scissors[index] = scissor; - _dirty |= DirtyFlags.Scissor; - } + _scissors[index] = scissor; + _dirty |= DirtyFlags.Scissor; } public void SetDepthTestBool(bool testEnable, bool writeEnable) { - if (DepthTestEnable != testEnable || DepthWriteEnable != writeEnable) - { - DepthTestEnable = testEnable; - DepthWriteEnable = writeEnable; - _dirty |= DirtyFlags.DepthTestBool; - } + DepthTestEnable = testEnable; + DepthWriteEnable = writeEnable; + _dirty |= DirtyFlags.DepthTestBool; } public void SetDepthTestCompareOp(CompareOp depthTestOp) { - if (_depthCompareOp != depthTestOp) - { - _depthCompareOp = depthTestOp; - _dirty |= DirtyFlags.DepthTestCompareOp; - } + _depthCompareOp = depthTestOp; + _dirty |= DirtyFlags.DepthTestCompareOp; } public void SetStencilOp(StencilOp backFailOp, StencilOp backPassOp, StencilOp backDepthFailOp, CompareOp backCompareOp, StencilOp frontFailOp, StencilOp frontPassOp, StencilOp frontDepthFailOp, CompareOp frontCompareOp) { - if (_backfailop != backFailOp || _backpassop != backPassOp || _backdepthfailop != backDepthFailOp || - _backcompareop != backCompareOp || _frontfailop != frontFailOp || _frontpassop != frontPassOp || - _frontdepthfailop != frontDepthFailOp || _frontcompareop != frontCompareOp) - { - _backfailop = backFailOp; - _backpassop = backPassOp; - _backdepthfailop = backDepthFailOp; - _backcompareop = backCompareOp; - _frontfailop = frontFailOp; - _frontpassop = frontPassOp; - _frontdepthfailop = frontDepthFailOp; - _frontcompareop = frontCompareOp; - _opToo = true; - } + _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, uint backReference, uint frontCompareMask, uint frontWriteMask, uint frontReference) { - if (_backCompareMask != backCompareMask || _backWriteMask != backWriteMask || - _backReference != backReference || _frontCompareMask != frontCompareMask || - _frontWriteMask != frontWriteMask || _frontReference != frontReference) - { - _backCompareMask = backCompareMask; - _backWriteMask = backWriteMask; - _backReference = backReference; - _frontCompareMask = frontCompareMask; - _frontWriteMask = frontWriteMask; - _frontReference = frontReference; - _dirty |= DirtyFlags.Stencil; - } + _backCompareMask = backCompareMask; + _backWriteMask = backWriteMask; + _backReference = backReference; + _frontCompareMask = frontCompareMask; + _frontWriteMask = frontWriteMask; + _frontReference = frontReference; + _dirty |= DirtyFlags.Stencil; } public void SetStencilTest(bool stencilTestEnable) { - if (StencilTestEnable != stencilTestEnable) - { - StencilTestEnable = stencilTestEnable; - _dirty |= DirtyFlags.StencilTestEnable; - } + StencilTestEnable = stencilTestEnable; + _dirty |= DirtyFlags.StencilTestEnable; } public void SetViewport(int index, Viewport viewport) { - if (!Viewports[index].Equals(viewport)) - { - Viewports[index] = viewport; - _dirty |= DirtyFlags.Viewport; - } + Viewports[index] = viewport; + _dirty |= DirtyFlags.Viewport; } public void SetViewports(ref Array16 viewports, uint viewportsCount) @@ -232,111 +189,75 @@ namespace Ryujinx.Graphics.Vulkan public void SetCullMode(CullModeFlags cullMode) { - if (CullMode != cullMode) - { - CullMode = cullMode; - _dirty |= DirtyFlags.CullMode; - } + CullMode = cullMode; + _dirty |= DirtyFlags.CullMode; } public void SetFrontFace(FrontFace frontFace) { - if (_frontFace != frontFace) - { - _frontFace = frontFace; - _dirty |= DirtyFlags.FrontFace; - } + _frontFace = frontFace; + _dirty |= DirtyFlags.FrontFace; } public void SetLineWidth(float width) { - if (!FloatCompare(_lineWidth, width)) - { - _lineWidth = width; + _lineWidth = width; - _dirty |= DirtyFlags.LineWidth; - } + _dirty |= DirtyFlags.LineWidth; } public void SetRasterizerDiscard(bool discard) { - if (_discard != discard) - { - _discard = discard; - _dirty |= DirtyFlags.RasterDiscard; - } + _discard = discard; + _dirty |= DirtyFlags.RasterDiscard; } public void SetPrimitiveRestartEnable(bool primitiveRestart) { - if (_primitiveRestartEnable != primitiveRestart) - { - _primitiveRestartEnable = primitiveRestart; - _dirty |= DirtyFlags.PrimitiveRestart; - } + _primitiveRestartEnable = primitiveRestart; + _dirty |= DirtyFlags.PrimitiveRestart; } public void SetLogicOp(LogicOp op) { - if (_logicOp != op) - { - _logicOp = op; - _dirty |= DirtyFlags.LogicOp; - } + _logicOp = op; + _dirty |= DirtyFlags.LogicOp; } public void SetPatchControlPoints(uint points) { - if (_patchControlPoints != points) - { - _patchControlPoints = points; - _dirty |= DirtyFlags.PatchControlPoints; - } + _patchControlPoints = points; + _dirty |= DirtyFlags.PatchControlPoints; } public void SetLogicOpEnable(bool logicOpEnable) { - if (_logicOpEnable != logicOpEnable) - { - _logicOpEnable = logicOpEnable; - _dirty |= DirtyFlags.LogicOpEnable; - } + _logicOpEnable = logicOpEnable; + _dirty |= DirtyFlags.LogicOpEnable; } public void SetDepthClampEnable(bool depthClampEnable) { - if (_depthClampEnable != depthClampEnable) - { - _depthClampEnable = depthClampEnable; - _dirty |= DirtyFlags.DepthClampEnable; - } + _depthClampEnable = depthClampEnable; + _dirty |= DirtyFlags.DepthClampEnable; } public void SetAlphaToCoverEnable(bool alphaToCoverEnable) { - if (_alphaToCoverEnable != alphaToCoverEnable) - { - _alphaToCoverEnable = alphaToCoverEnable; - _dirty |= DirtyFlags.AlphaToCover; - } + _alphaToCoverEnable = alphaToCoverEnable; + _dirty |= DirtyFlags.AlphaToCover; } public void SetAlphaToOneEnable(bool alphaToOneEnable) { - if (_alphaToOneEnable != alphaToOneEnable) - { - _alphaToOneEnable = alphaToOneEnable; - _dirty |= DirtyFlags.AlphaToOne; - } + _alphaToOneEnable = alphaToOneEnable; + _dirty |= DirtyFlags.AlphaToOne; } public void SetDepthMode(bool mode) { - if (DepthMode != mode) - { - DepthMode = mode; - _dirty |= DirtyFlags.DepthMode; - } + DepthMode = mode; + _dirty |= DirtyFlags.DepthMode; } public void ForceAllDirty(VulkanRenderer gd) @@ -619,6 +540,11 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) { + if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable && !_logicOpEnable) + { + return; + } + gd.ExtendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp); } From 89dee194d2a846110c830c8c4683a0408ae607ac Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 22 May 2024 09:45:50 -0700 Subject: [PATCH 038/132] Use dynamic state for primitive topology if dynamicPrimitiveTopologyUnrestricted is supported. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 20 ++++++++++-- .../PipelineDynamicState.cs | 31 ++++++++++++++++++- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 16 +++++++++- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 15 +++++++++ 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index f78184c3b..5433f3402 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -697,7 +697,7 @@ namespace Ryujinx.Graphics.Vulkan 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 oldTopology = Gd.SupportsUnrestrictedDynamicTopology ? DynamicState.Topology : _newState.Topology; var oldViewports = DynamicState.Viewports; var oldViewportsCount = _supportExtDynamic ? DynamicState.ViewportsCount : _newState.ViewportsCount; @@ -740,7 +740,14 @@ namespace Ryujinx.Graphics.Vulkan _newState.ViewportsCount = oldViewportsCount; } - _newState.Topology = oldTopology; + if (Gd.SupportsUnrestrictedDynamicTopology) + { + DynamicState.SetPrimitiveTopology(oldTopology); + } + else + { + _newState.Topology = oldTopology; + } DynamicState.SetViewports(ref oldViewports, oldViewportsCount); @@ -1128,7 +1135,14 @@ namespace Ryujinx.Graphics.Vulkan var vkTopology = Gd.TopologyRemap(topology).Convert(); - _newState.Topology = vkTopology; + if (Gd.SupportsUnrestrictedDynamicTopology) + { + DynamicState.SetPrimitiveTopology(vkTopology); + } + else + { + _newState.Topology = vkTopology; + } SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 61d9a6502..ecf8013be 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -65,6 +65,8 @@ namespace Ryujinx.Graphics.Vulkan private bool _primitiveRestartEnable; + public PrimitiveTopology Topology; + [Flags] private enum DirtyFlags { @@ -89,10 +91,11 @@ namespace Ryujinx.Graphics.Vulkan PatchControlPoints = 1 << 17, DepthMode = 1 << 18, PrimitiveRestart = 1 << 19, + PrimitiveTopology = 1 << 20, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable, Extended2 = RasterDiscard | LogicOp | PatchControlPoints | PrimitiveRestart, - Extended3 = DepthClampEnable | LogicOpEnable | AlphaToCover | AlphaToOne | DepthMode, + Extended3 = DepthClampEnable | LogicOpEnable | AlphaToCover | AlphaToOne | DepthMode | PrimitiveTopology, } private DirtyFlags _dirty; @@ -218,6 +221,12 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.PrimitiveRestart; } + public void SetPrimitiveTopology(PrimitiveTopology topology) + { + Topology = topology; + _dirty |= DirtyFlags.PrimitiveTopology; + } + public void SetLogicOp(LogicOp op) { _logicOp = op; @@ -318,6 +327,11 @@ namespace Ryujinx.Graphics.Vulkan { _dirty &= ~DirtyFlags.DepthMode; } + + if (!gd.SupportsUnrestrictedDynamicTopology) + { + _dirty &= ~DirtyFlags.PrimitiveTopology; + } } public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) @@ -387,6 +401,11 @@ namespace Ryujinx.Graphics.Vulkan RecordPrimitiveRestartEnable(gd, commandBuffer); } + if (_dirty.HasFlag(DirtyFlags.PrimitiveTopology)) + { + RecordPrimitiveRestartEnable(gd, commandBuffer); + } + if (_dirty.HasFlag(DirtyFlags.LogicOp)) { RecordLogicOp(gd, commandBuffer); @@ -422,6 +441,11 @@ namespace Ryujinx.Graphics.Vulkan RecordDepthMode(gd, commandBuffer); } + if (_dirty.HasFlag(DirtyFlags.PrimitiveTopology)) + { + RecordPrimitiveTopology(gd, commandBuffer); + } + _dirty = DirtyFlags.None; } @@ -538,6 +562,11 @@ namespace Ryujinx.Graphics.Vulkan gd.ExtendedDynamicState2Api.CmdSetPrimitiveRestartEnable(commandBuffer, _primitiveRestartEnable); } + private readonly void RecordPrimitiveTopology(VulkanRenderer gd, CommandBuffer commandBuffer) + { + gd.ExtendedDynamicStateApi.CmdSetPrimitiveTopology(commandBuffer, Topology); + } + private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) { if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable && !_logicOpEnable) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 50e3926ca..f8b71ed15 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -435,9 +435,13 @@ namespace Ryujinx.Graphics.Vulkan var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, - Topology = Topology, }; + if (!gd.SupportsUnrestrictedDynamicTopology) + { + inputAssemblyState.Topology = Topology; + } + var tessellationState = new PipelineTessellationStateCreateInfo { SType = StructureType.PipelineTessellationStateCreateInfo, @@ -633,6 +637,11 @@ namespace Ryujinx.Graphics.Vulkan { additionalDynamicStatesCount++; } + + if (gd.SupportsUnrestrictedDynamicTopology) + { + additionalDynamicStatesCount++; + } } int dynamicStatesCount = baseDynamicStatesCount + additionalDynamicStatesCount; @@ -710,6 +719,11 @@ namespace Ryujinx.Graphics.Vulkan { dynamicStates[currentIndex++] = DynamicState.DepthClipNegativeOneToOneExt; } + + if (gd.SupportsUnrestrictedDynamicTopology) + { + dynamicStates[currentIndex++] = DynamicState.PrimitiveTopology; + } } var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 69d075951..537936796 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -104,6 +104,8 @@ namespace Ryujinx.Graphics.Vulkan public PhysicalDeviceExtendedDynamicState3FeaturesEXT ExtendedDynamicState3Features; + public bool SupportsUnrestrictedDynamicTopology; + public event EventHandler ScreenCaptured; @@ -211,6 +213,17 @@ namespace Ryujinx.Graphics.Vulkan properties2.PNext = &propertiesTransformFeedback; } + PhysicalDeviceExtendedDynamicState3PropertiesEXT propertiesExtendedDynamicState3 = new() + { + SType = StructureType.PhysicalDeviceExtendedDynamicState3PropertiesExt, + }; + + if (_physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState3.ExtensionName)) + { + propertiesExtendedDynamicState3.PNext = properties2.PNext; + properties2.PNext = &propertiesExtendedDynamicState3; + } + PhysicalDevicePortabilitySubsetPropertiesKHR propertiesPortabilitySubset = new() { SType = StructureType.PhysicalDevicePortabilitySubsetPropertiesKhr, @@ -425,6 +438,8 @@ namespace Ryujinx.Graphics.Vulkan properties.Limits.SubTexelPrecisionBits, minResourceAlignment); + SupportsUnrestrictedDynamicTopology = propertiesExtendedDynamicState3.DynamicPrimitiveTopologyUnrestricted; + IsSharedMemory = MemoryAllocator.IsDeviceMemoryShared(_physicalDevice); MemoryAllocator = new MemoryAllocator(Api, _physicalDevice, _device); From 74a1ab031db6b350b8d7e6652feeeb3f3ed9db52 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 22 May 2024 17:51:54 -0700 Subject: [PATCH 039/132] Attempt to resolve more validation errors. --- src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index ecf8013be..481d96bf8 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -489,7 +489,7 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordStencil(VulkanRenderer gd, CommandBuffer commandBuffer) { - if (_opToo && StencilTestEnable) + if (_opToo) { gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceBackBit, _backfailop, _backpassop, _backdepthfailop, _backcompareop); @@ -569,11 +569,6 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) { - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable && !_logicOpEnable) - { - return; - } - gd.ExtendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp); } From 0000a7ac9ce7024b4be3144272f9b269438a5151 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 22 May 2024 22:05:01 -0700 Subject: [PATCH 040/132] Rebased --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 8 +++- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 48 ++++++++++++++------ 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 5433f3402..2ec66ef31 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1024,14 +1024,18 @@ namespace Ryujinx.Graphics.Vulkan _newState.LogicOp = op.Convert(); } + // AMD has a bug where it enables logical operations even for float formats, + // so we need to force disable them here. + bool logicOpEnable = enable && (Gd.Vendor != Vendor.Amd || _newState.Internal.LogicOpsAllowed); + if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable) { - DynamicState.SetLogicOpEnable(enable); + DynamicState.SetLogicOpEnable(logicOpEnable); } else { - _newState.LogicOpEnable = enable; + _newState.LogicOpEnable = logicOpEnable; } SignalStateChange(); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index f8b71ed15..70fe8bb62 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -407,6 +407,7 @@ namespace Ryujinx.Graphics.Vulkan bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState; bool supportsExtDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2; + bool supportsExtDynamicState3 = gd.Capabilities.SupportsExtendedDynamicState3; fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0]) @@ -445,16 +446,24 @@ namespace Ryujinx.Graphics.Vulkan var tessellationState = new PipelineTessellationStateCreateInfo { SType = StructureType.PipelineTessellationStateCreateInfo, - PatchControlPoints = PatchControlPoints, }; + if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + { + tessellationState.PatchControlPoints = PatchControlPoints; + } + var rasterizationState = new PipelineRasterizationStateCreateInfo { SType = StructureType.PipelineRasterizationStateCreateInfo, - DepthClampEnable = DepthClampEnable, PolygonMode = PolygonMode, }; + if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable) + { + rasterizationState.DepthClampEnable = DepthClampEnable; + } + if (isMoltenVk) { //When widelines feature is not supported it must be 1.0f per spec. @@ -490,10 +499,18 @@ namespace Ryujinx.Graphics.Vulkan SampleShadingEnable = false, RasterizationSamples = TextureStorage.ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, SamplesCount), MinSampleShading = 1, - AlphaToCoverageEnable = AlphaToCoverageEnable, - AlphaToOneEnable = AlphaToOneEnable, }; + if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable) + { + multisampleState.AlphaToCoverageEnable = AlphaToCoverageEnable; + } + + if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable) + { + multisampleState.AlphaToOneEnable = AlphaToOneEnable; + } + var depthStencilState = new PipelineDepthStencilStateCreateInfo { SType = StructureType.PipelineDepthStencilStateCreateInfo, @@ -516,19 +533,13 @@ namespace Ryujinx.Graphics.Vulkan StencilFrontFailOp, StencilFrontPassOp, StencilFrontDepthFailOp, - StencilFrontCompareOp, - null, - null, - null); + StencilFrontCompareOp); var stencilBack = new StencilOpState( StencilBackFailOp, StencilBackPassOp, StencilBackDepthFailOp, - StencilBackCompareOp, - null, - null, - null); + StencilBackCompareOp); depthStencilState.Front = stencilFront; depthStencilState.Back = stencilBack; @@ -559,19 +570,27 @@ namespace Ryujinx.Graphics.Vulkan } } + // AMD has a bug where it enables logical operations even for float formats, + // so we need to force disable them here. + bool logicOpEnable = LogicOpEnable && (gd.Vendor != Vendor.Amd || Internal.LogicOpsAllowed); + var colorBlendState = new PipelineColorBlendStateCreateInfo { SType = StructureType.PipelineColorBlendStateCreateInfo, - LogicOpEnable = LogicOpEnable, AttachmentCount = ColorBlendAttachmentStateCount, PAttachments = pColorBlendAttachmentState, }; - if (!(supportsExtDynamicState2 && gd.ExtendedLogicOp)) + if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) { colorBlendState.LogicOp = LogicOp; } + if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable) + { + colorBlendState.LogicOpEnable = LogicOpEnable; + } + PipelineColorBlendAdvancedStateCreateInfoEXT colorBlendAdvancedState; if (!AdvancedBlendSrcPreMultiplied || @@ -733,6 +752,7 @@ namespace Ryujinx.Graphics.Vulkan PDynamicStates = dynamicStates, }; + var pipelineCreateInfo = new GraphicsPipelineCreateInfo { SType = StructureType.GraphicsPipelineCreateInfo, From fb4ef3347abd8fd001fd1a3b0a7c1b85fba106ec Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Thu, 23 May 2024 19:37:56 -0700 Subject: [PATCH 041/132] Rebase --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 2ec66ef31..ade6fb165 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1024,9 +1024,9 @@ namespace Ryujinx.Graphics.Vulkan _newState.LogicOp = op.Convert(); } - // AMD has a bug where it enables logical operations even for float formats, + // Vendors other than NVIDIA have a bug where it enables logical operations even for float formats, // so we need to force disable them here. - bool logicOpEnable = enable && (Gd.Vendor != Vendor.Amd || _newState.Internal.LogicOpsAllowed); + bool logicOpEnable = enable && (Gd.Vendor == Vendor.Nvidia || _newState.Internal.LogicOpsAllowed); if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable) { From f43413f374fa5005aebee2c9e0ca38444e6bc003 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 25 May 2024 21:48:33 -0700 Subject: [PATCH 042/132] Revert Silk.NET to main branch version. Remove VK_EXT_extended_dynamic_state3 functionality until later PR --- Directory.Packages.props | 8 +- .../HardwareCapabilities.cs | 3 - src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 74 +------ .../PipelineDynamicState.cs | 195 +++--------------- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 92 +-------- .../VulkanInitialization.cs | 32 +-- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 28 +-- 7 files changed, 46 insertions(+), 386 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index e73701629..261753ad1 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -39,9 +39,9 @@ - - - + + + @@ -49,4 +49,4 @@ - \ No newline at end of file + diff --git a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs index 07c7e2618..952867642 100644 --- a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs +++ b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs @@ -32,7 +32,6 @@ namespace Ryujinx.Graphics.Vulkan public readonly bool SupportsConditionalRendering; public readonly bool SupportsExtendedDynamicState; public readonly bool SupportsExtendedDynamicState2; - public readonly bool SupportsExtendedDynamicState3; public readonly bool SupportsMultiView; public readonly bool SupportsNullDescriptors; public readonly bool SupportsPushDescriptors; @@ -73,7 +72,6 @@ namespace Ryujinx.Graphics.Vulkan bool supportsConditionalRendering, bool supportsExtendedDynamicState, bool supportsExtendedDynamicState2, - bool supportsExtendedDynamicState3, bool supportsMultiView, bool supportsNullDescriptors, bool supportsPushDescriptors, @@ -113,7 +111,6 @@ namespace Ryujinx.Graphics.Vulkan SupportsConditionalRendering = supportsConditionalRendering; SupportsExtendedDynamicState = supportsExtendedDynamicState; SupportsExtendedDynamicState2 = supportsExtendedDynamicState2; - SupportsExtendedDynamicState3 = supportsExtendedDynamicState3; SupportsMultiView = supportsMultiView; SupportsNullDescriptors = supportsNullDescriptors; SupportsPushDescriptors = supportsPushDescriptors; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index ade6fb165..83dad8e82 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -129,7 +129,6 @@ namespace Ryujinx.Graphics.Vulkan _supportExtDynamic2 = gd.Capabilities.SupportsExtendedDynamicState2; - _newState.Initialize(); } @@ -697,7 +696,7 @@ namespace Ryujinx.Graphics.Vulkan var oldStencilTestEnable = _supportExtDynamic ? DynamicState.StencilTestEnable : _newState.StencilTestEnable; var oldDepthTestEnable = _supportExtDynamic ? DynamicState.DepthTestEnable : _newState.DepthTestEnable; var oldDepthWriteEnable = _supportExtDynamic ? DynamicState.DepthWriteEnable : _newState.DepthWriteEnable; - var oldTopology = Gd.SupportsUnrestrictedDynamicTopology ? DynamicState.Topology : _newState.Topology; + var oldTopology = _newState.Topology; var oldViewports = DynamicState.Viewports; var oldViewportsCount = _supportExtDynamic ? DynamicState.ViewportsCount : _newState.ViewportsCount; @@ -740,14 +739,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.ViewportsCount = oldViewportsCount; } - if (Gd.SupportsUnrestrictedDynamicTopology) - { - DynamicState.SetPrimitiveTopology(oldTopology); - } - else - { - _newState.Topology = oldTopology; - } + _newState.Topology = oldTopology; DynamicState.SetViewports(ref oldViewports, oldViewportsCount); @@ -891,14 +883,7 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthClamp(bool clamp) { - if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable) - { - DynamicState.SetDepthClampEnable(clamp); - } - else - { - _newState.DepthClampEnable = clamp; - } + _newState.DepthClampEnable = clamp; SignalStateChange(); } @@ -906,19 +891,11 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthMode(DepthMode mode) { bool oldMode; - bool supportsDepthClipandDynamicState = Gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne; - if (supportsDepthClipandDynamicState) - { - oldMode = DynamicState.DepthMode; - DynamicState.SetDepthMode(mode == DepthMode.MinusOneToOne); - } - else - { - oldMode = _newState.DepthMode; - _newState.DepthMode = mode == DepthMode.MinusOneToOne; - } - if ((supportsDepthClipandDynamicState ? DynamicState.DepthMode : _newState.DepthMode) != oldMode) + oldMode = _newState.DepthMode; + _newState.DepthMode = mode == DepthMode.MinusOneToOne; + + if (_newState.DepthMode != oldMode) { SignalStateChange(); } @@ -1028,38 +1005,16 @@ namespace Ryujinx.Graphics.Vulkan // so we need to force disable them here. bool logicOpEnable = enable && (Gd.Vendor == Vendor.Nvidia || _newState.Internal.LogicOpsAllowed); - if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable) - { - DynamicState.SetLogicOpEnable(logicOpEnable); - - } - else - { - _newState.LogicOpEnable = logicOpEnable; - } + _newState.LogicOpEnable = logicOpEnable; SignalStateChange(); } public void SetMultisampleState(MultisampleDescriptor multisample) { - if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable) - { - DynamicState.SetAlphaToCoverEnable(multisample.AlphaToCoverageEnable); - } - else - { - _newState.AlphaToCoverageEnable = multisample.AlphaToCoverageEnable; - } + _newState.AlphaToCoverageEnable = multisample.AlphaToCoverageEnable; - if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable) - { - DynamicState.SetAlphaToOneEnable(multisample.AlphaToOneEnable); - } - else - { - _newState.AlphaToOneEnable = multisample.AlphaToOneEnable; - } + _newState.AlphaToOneEnable = multisample.AlphaToOneEnable; SignalStateChange(); } @@ -1139,14 +1094,7 @@ namespace Ryujinx.Graphics.Vulkan var vkTopology = Gd.TopologyRemap(topology).Convert(); - if (Gd.SupportsUnrestrictedDynamicTopology) - { - DynamicState.SetPrimitiveTopology(vkTopology); - } - else - { - _newState.Topology = vkTopology; - } + _newState.Topology = vkTopology; SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 481d96bf8..63527c472 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -23,14 +23,14 @@ namespace Ryujinx.Graphics.Vulkan private uint _frontReference; private bool _opToo; - private StencilOp _backfailop; - private StencilOp _backpassop; - private StencilOp _backdepthfailop; - private CompareOp _backcompareop; - private StencilOp _frontfailop; - private StencilOp _frontpassop; - private StencilOp _frontdepthfailop; - private CompareOp _frontcompareop; + private StencilOp _backFailOp; + private StencilOp _backPassOp; + private StencilOp _backDepthFailOp; + private CompareOp _backCompareOp; + private StencilOp _frontFailOp; + private StencilOp _frontPassOp; + private StencilOp _frontDepthFailOp; + private CompareOp _frontCompareOp; private float _lineWidth; @@ -54,19 +54,8 @@ namespace Ryujinx.Graphics.Vulkan private uint _patchControlPoints; - private bool _logicOpEnable; - - private bool _depthClampEnable; - - private bool _alphaToCoverEnable; - private bool _alphaToOneEnable; - - public bool DepthMode; - private bool _primitiveRestartEnable; - public PrimitiveTopology Topology; - [Flags] private enum DirtyFlags { @@ -84,18 +73,11 @@ namespace Ryujinx.Graphics.Vulkan LineWidth = 1 << 10, RasterDiscard = 1 << 11, LogicOp = 1 << 12, - DepthClampEnable = 1 << 13, - LogicOpEnable = 1 << 14, - AlphaToCover = 1 << 15, - AlphaToOne = 1 << 16, - PatchControlPoints = 1 << 17, - DepthMode = 1 << 18, - PrimitiveRestart = 1 << 19, - PrimitiveTopology = 1 << 20, + PatchControlPoints = 1 << 13, + PrimitiveRestart = 1 << 14, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable, Extended2 = RasterDiscard | LogicOp | PatchControlPoints | PrimitiveRestart, - Extended3 = DepthClampEnable | LogicOpEnable | AlphaToCover | AlphaToOne | DepthMode | PrimitiveTopology, } private DirtyFlags _dirty; @@ -142,14 +124,14 @@ namespace Ryujinx.Graphics.Vulkan 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; + _backFailOp = backFailOp; + _backPassOp = backPassOp; + _backDepthFailOp = backDepthFailOp; + _backCompareOp = backCompareOp; + _frontFailOp = frontFailOp; + _frontPassOp = frontPassOp; + _frontDepthFailOp = frontDepthFailOp; + _frontCompareOp = frontCompareOp; _opToo = true; } @@ -221,12 +203,6 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.PrimitiveRestart; } - public void SetPrimitiveTopology(PrimitiveTopology topology) - { - Topology = topology; - _dirty |= DirtyFlags.PrimitiveTopology; - } - public void SetLogicOp(LogicOp op) { _logicOp = op; @@ -239,36 +215,6 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.PatchControlPoints; } - public void SetLogicOpEnable(bool logicOpEnable) - { - _logicOpEnable = logicOpEnable; - _dirty |= DirtyFlags.LogicOpEnable; - } - - public void SetDepthClampEnable(bool depthClampEnable) - { - _depthClampEnable = depthClampEnable; - _dirty |= DirtyFlags.DepthClampEnable; - } - - public void SetAlphaToCoverEnable(bool alphaToCoverEnable) - { - _alphaToCoverEnable = alphaToCoverEnable; - _dirty |= DirtyFlags.AlphaToCover; - } - - public void SetAlphaToOneEnable(bool alphaToOneEnable) - { - _alphaToOneEnable = alphaToOneEnable; - _dirty |= DirtyFlags.AlphaToOne; - } - - public void SetDepthMode(bool mode) - { - DepthMode = mode; - _dirty |= DirtyFlags.DepthMode; - } - public void ForceAllDirty(VulkanRenderer gd) { _dirty = DirtyFlags.Standard; @@ -283,11 +229,6 @@ namespace Ryujinx.Graphics.Vulkan _dirty = DirtyFlags.Standard | DirtyFlags.Extended | DirtyFlags.Extended2; } - if (gd.Capabilities.SupportsExtendedDynamicState3) - { - _dirty = DirtyFlags.Standard | DirtyFlags.Extended | DirtyFlags.Extended2 | DirtyFlags.Extended3; - } - if (gd.IsMoltenVk) { _dirty &= ~DirtyFlags.LineWidth; @@ -302,36 +243,6 @@ namespace Ryujinx.Graphics.Vulkan { _dirty &= ~DirtyFlags.PatchControlPoints; } - - if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable) - { - _dirty &= ~DirtyFlags.AlphaToCover; - } - - if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable) - { - _dirty &= ~DirtyFlags.AlphaToOne; - } - - if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable) - { - _dirty &= ~DirtyFlags.DepthClampEnable; - } - - if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable) - { - _dirty &= ~DirtyFlags.LogicOpEnable; - } - - if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne) - { - _dirty &= ~DirtyFlags.DepthMode; - } - - if (!gd.SupportsUnrestrictedDynamicTopology) - { - _dirty &= ~DirtyFlags.PrimitiveTopology; - } } public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) @@ -401,7 +312,7 @@ namespace Ryujinx.Graphics.Vulkan RecordPrimitiveRestartEnable(gd, commandBuffer); } - if (_dirty.HasFlag(DirtyFlags.PrimitiveTopology)) + if (_dirty.HasFlag(DirtyFlags.PrimitiveRestart)) { RecordPrimitiveRestartEnable(gd, commandBuffer); } @@ -416,36 +327,6 @@ namespace Ryujinx.Graphics.Vulkan RecordPatchControlPoints(gd, commandBuffer); } - if (_dirty.HasFlag(DirtyFlags.LogicOpEnable)) - { - RecordLogicOpEnable(gd, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.DepthClampEnable)) - { - RecordDepthClampEnable(gd, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.AlphaToCover)) - { - RecordAlphaToCoverEnable(gd, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.AlphaToOne)) - { - RecordAlphaToOneEnable(gd, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.DepthMode)) - { - RecordDepthMode(gd, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.PrimitiveTopology)) - { - RecordPrimitiveTopology(gd, commandBuffer); - } - _dirty = DirtyFlags.None; } @@ -491,10 +372,10 @@ namespace Ryujinx.Graphics.Vulkan { if (_opToo) { - gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceBackBit, _backfailop, _backpassop, - _backdepthfailop, _backcompareop); - gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontfailop, _frontpassop, - _frontdepthfailop, _frontcompareop); + gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceBackBit, _backFailOp, _backPassOp, + _backDepthFailOp, _backCompareOp); + gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontFailOp, _frontPassOp, + _frontDepthFailOp, _frontCompareOp); } gd.Api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backCompareMask); @@ -562,46 +443,16 @@ namespace Ryujinx.Graphics.Vulkan gd.ExtendedDynamicState2Api.CmdSetPrimitiveRestartEnable(commandBuffer, _primitiveRestartEnable); } - private readonly void RecordPrimitiveTopology(VulkanRenderer gd, CommandBuffer commandBuffer) - { - gd.ExtendedDynamicStateApi.CmdSetPrimitiveTopology(commandBuffer, Topology); - } - private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) { gd.ExtendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp); } - private readonly void RecordLogicOpEnable(VulkanRenderer gd, CommandBuffer commandBuffer) - { - gd.ExtendedDynamicState3Api.CmdSetLogicOpEnable(commandBuffer, _logicOpEnable); - } - - private readonly void RecordDepthClampEnable(VulkanRenderer gd, CommandBuffer commandBuffer) - { - gd.ExtendedDynamicState3Api.CmdSetDepthClampEnable(commandBuffer, _depthClampEnable); - } - - private readonly void RecordAlphaToCoverEnable(VulkanRenderer gd, CommandBuffer commandBuffer) - { - gd.ExtendedDynamicState3Api.CmdSetAlphaToCoverageEnable(commandBuffer, _alphaToCoverEnable); - } - - private readonly void RecordAlphaToOneEnable(VulkanRenderer gd, CommandBuffer commandBuffer) - { - gd.ExtendedDynamicState3Api.CmdSetAlphaToOneEnable(commandBuffer, _alphaToOneEnable); - } - private readonly void RecordPatchControlPoints(VulkanRenderer gd, CommandBuffer commandBuffer) { gd.ExtendedDynamicState2Api.CmdSetPatchControlPoints(commandBuffer, _patchControlPoints); } - private readonly void RecordDepthMode(VulkanRenderer gd, CommandBuffer commandBuffer) - { - gd.ExtendedDynamicState3Api.CmdSetDepthClipNegativeOneToOne(commandBuffer, DepthMode); - } - private readonly void RecordLineWidth(Vk api, CommandBuffer commandBuffer) { if (!OperatingSystem.IsMacOS()) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 70fe8bb62..087ddda16 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -407,8 +407,6 @@ namespace Ryujinx.Graphics.Vulkan bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState; bool supportsExtDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2; - bool supportsExtDynamicState3 = gd.Capabilities.SupportsExtendedDynamicState3; - fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0]) fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions2 = &_vertexAttributeDescriptions2[0]) @@ -436,13 +434,9 @@ namespace Ryujinx.Graphics.Vulkan var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, + Topology = Topology, }; - if (!gd.SupportsUnrestrictedDynamicTopology) - { - inputAssemblyState.Topology = Topology; - } - var tessellationState = new PipelineTessellationStateCreateInfo { SType = StructureType.PipelineTessellationStateCreateInfo, @@ -457,13 +451,9 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.PipelineRasterizationStateCreateInfo, PolygonMode = PolygonMode, + DepthClampEnable = DepthClampEnable, }; - if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable) - { - rasterizationState.DepthClampEnable = DepthClampEnable; - } - if (isMoltenVk) { //When widelines feature is not supported it must be 1.0f per spec. @@ -482,7 +472,7 @@ namespace Ryujinx.Graphics.Vulkan SType = StructureType.PipelineViewportStateCreateInfo, }; - if (gd.Capabilities.SupportsDepthClipControl && !gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne) + if (gd.Capabilities.SupportsDepthClipControl) { var viewportDepthClipControlState = new PipelineViewportDepthClipControlCreateInfoEXT { @@ -499,18 +489,10 @@ namespace Ryujinx.Graphics.Vulkan SampleShadingEnable = false, RasterizationSamples = TextureStorage.ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, SamplesCount), MinSampleShading = 1, + AlphaToCoverageEnable = AlphaToCoverageEnable, + AlphaToOneEnable = AlphaToOneEnable, }; - if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable) - { - multisampleState.AlphaToCoverageEnable = AlphaToCoverageEnable; - } - - if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable) - { - multisampleState.AlphaToOneEnable = AlphaToOneEnable; - } - var depthStencilState = new PipelineDepthStencilStateCreateInfo { SType = StructureType.PipelineDepthStencilStateCreateInfo, @@ -579,6 +561,7 @@ namespace Ryujinx.Graphics.Vulkan SType = StructureType.PipelineColorBlendStateCreateInfo, AttachmentCount = ColorBlendAttachmentStateCount, PAttachments = pColorBlendAttachmentState, + LogicOpEnable = LogicOpEnable, }; if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) @@ -586,11 +569,6 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.LogicOp = LogicOp; } - if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable) - { - colorBlendState.LogicOpEnable = LogicOpEnable; - } - PipelineColorBlendAdvancedStateCreateInfoEXT colorBlendAdvancedState; if (!AdvancedBlendSrcPreMultiplied || @@ -634,35 +612,6 @@ namespace Ryujinx.Graphics.Vulkan } } - if (supportsExtDynamicState3) - { - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable) - { - additionalDynamicStatesCount++; - } - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable) - { - additionalDynamicStatesCount++; - } - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable) - { - additionalDynamicStatesCount++; - } - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable) - { - additionalDynamicStatesCount++; - } - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne) - { - additionalDynamicStatesCount++; - } - - if (gd.SupportsUnrestrictedDynamicTopology) - { - additionalDynamicStatesCount++; - } - } - int dynamicStatesCount = baseDynamicStatesCount + additionalDynamicStatesCount; DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount]; @@ -716,35 +665,6 @@ namespace Ryujinx.Graphics.Vulkan } } - if (supportsExtDynamicState3) - { - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable) - { - dynamicStates[currentIndex++] = DynamicState.DepthClampEnableExt; - } - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable) - { - dynamicStates[currentIndex++] = DynamicState.LogicOpEnableExt; - } - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable) - { - dynamicStates[currentIndex++] = DynamicState.AlphaToCoverageEnableExt; - } - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable) - { - dynamicStates[currentIndex++] = DynamicState.AlphaToOneEnableExt; - } - if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClipNegativeOneToOne) - { - dynamicStates[currentIndex++] = DynamicState.DepthClipNegativeOneToOneExt; - } - - if (gd.SupportsUnrestrictedDynamicTopology) - { - dynamicStates[currentIndex++] = DynamicState.PrimitiveTopology; - } - } - var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo { SType = StructureType.PipelineDynamicStateCreateInfo, diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index 4b8c15526..eae4edb7f 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -24,7 +24,6 @@ namespace Ryujinx.Graphics.Vulkan ExtConditionalRendering.ExtensionName, ExtExtendedDynamicState.ExtensionName, ExtExtendedDynamicState2.ExtensionName, - ExtExtendedDynamicState3.ExtensionName, ExtTransformFeedback.ExtensionName, KhrDrawIndirectCount.ExtensionName, KhrPushDescriptor.ExtensionName, @@ -264,7 +263,7 @@ namespace Ryujinx.Graphics.Vulkan return InvalidIndex; } - internal static Device CreateDevice(Vk api, VulkanPhysicalDevice physicalDevice, uint queueFamilyIndex, uint queueCount, out PhysicalDeviceExtendedDynamicState2FeaturesEXT extendedDynamicState2Features, out PhysicalDeviceExtendedDynamicState3FeaturesEXT extendedDynamicState3Features) + internal static Device CreateDevice(Vk api, VulkanPhysicalDevice physicalDevice, uint queueFamilyIndex, uint queueCount, out PhysicalDeviceExtendedDynamicState2FeaturesEXT extendedDynamicState2Features) { if (queueCount > QueuesCount) { @@ -323,17 +322,6 @@ namespace Ryujinx.Graphics.Vulkan features2.PNext = &supportedFeaturesExtExtendedDynamicState2; } - PhysicalDeviceExtendedDynamicState3FeaturesEXT supportedFeaturesExtExtendedDynamicState3 = new() - { - SType = StructureType.PhysicalDeviceExtendedDynamicState3FeaturesExt, - PNext = features2.PNext, - }; - - if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState3.ExtensionName)) - { - features2.PNext = &supportedFeaturesExtExtendedDynamicState3; - } - PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT supportedFeaturesPrimitiveTopologyListRestart = new() { SType = StructureType.PhysicalDevicePrimitiveTopologyListRestartFeaturesExt, @@ -483,24 +471,6 @@ namespace Ryujinx.Graphics.Vulkan extendedDynamicState2Features = supportedFeaturesExtExtendedDynamicState2; - if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState3.ExtensionName)) - { - var featuresExtendedDynamicState3 = new PhysicalDeviceExtendedDynamicState3FeaturesEXT() - { - SType = StructureType.PhysicalDeviceExtendedDynamicState3FeaturesExt, - PNext = pExtendedFeatures, - ExtendedDynamicState3LogicOpEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3LogicOpEnable, - ExtendedDynamicState3AlphaToCoverageEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3AlphaToCoverageEnable, - ExtendedDynamicState3AlphaToOneEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3AlphaToOneEnable, - ExtendedDynamicState3DepthClampEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3DepthClampEnable, - ExtendedDynamicState3DepthClipNegativeOneToOne = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3DepthClipNegativeOneToOne, - }; - - pExtendedFeatures = &featuresExtendedDynamicState3; - } - - extendedDynamicState3Features = supportedFeaturesExtExtendedDynamicState3; - var featuresVk11 = new PhysicalDeviceVulkan11Features { SType = StructureType.PhysicalDeviceVulkan11Features, diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 537936796..6ef3e641a 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -36,8 +36,6 @@ namespace Ryujinx.Graphics.Vulkan internal ExtConditionalRendering ConditionalRenderingApi { get; private set; } internal ExtExtendedDynamicState ExtendedDynamicStateApi { get; private set; } internal ExtExtendedDynamicState2 ExtendedDynamicState2Api { get; private set; } - internal ExtExtendedDynamicState3 ExtendedDynamicState3Api { get; private set; } - internal KhrPushDescriptor PushDescriptorApi { get; private set; } internal ExtTransformFeedback TransformFeedbackApi { get; private set; } internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; } @@ -102,10 +100,6 @@ namespace Ryujinx.Graphics.Vulkan public PhysicalDeviceExtendedDynamicState2FeaturesEXT ExtendedDynamicState2Features; - public PhysicalDeviceExtendedDynamicState3FeaturesEXT ExtendedDynamicState3Features; - - public bool SupportsUnrestrictedDynamicTopology; - public event EventHandler ScreenCaptured; @@ -147,11 +141,6 @@ namespace Ryujinx.Graphics.Vulkan ExtendedDynamicState2Api = extendedDynamicState2Api; } - if (Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExtendedDynamicState3 extendedDynamicState3Api)) - { - ExtendedDynamicState3Api = extendedDynamicState3Api; - } - if (Api.TryGetDeviceExtension(_instance.Instance, _device, out KhrPushDescriptor pushDescriptorApi)) { PushDescriptorApi = pushDescriptorApi; @@ -213,17 +202,6 @@ namespace Ryujinx.Graphics.Vulkan properties2.PNext = &propertiesTransformFeedback; } - PhysicalDeviceExtendedDynamicState3PropertiesEXT propertiesExtendedDynamicState3 = new() - { - SType = StructureType.PhysicalDeviceExtendedDynamicState3PropertiesExt, - }; - - if (_physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState3.ExtensionName)) - { - propertiesExtendedDynamicState3.PNext = properties2.PNext; - properties2.PNext = &propertiesExtendedDynamicState3; - } - PhysicalDevicePortabilitySubsetPropertiesKHR propertiesPortabilitySubset = new() { SType = StructureType.PhysicalDevicePortabilitySubsetPropertiesKhr, @@ -414,7 +392,6 @@ namespace Ryujinx.Graphics.Vulkan _physicalDevice.IsDeviceExtensionPresent(ExtConditionalRendering.ExtensionName), _physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState.ExtensionName), _physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName), - _physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState3.ExtensionName), features2.Features.MultiViewport && !(IsMoltenVk && Vendor == Vendor.Amd), // Workaround for AMD on MoltenVK issue featuresRobustness2.NullDescriptor || IsMoltenVk, supportsPushDescriptors && !IsMoltenVk, @@ -438,8 +415,6 @@ namespace Ryujinx.Graphics.Vulkan properties.Limits.SubTexelPrecisionBits, minResourceAlignment); - SupportsUnrestrictedDynamicTopology = propertiesExtendedDynamicState3.DynamicPrimitiveTopologyUnrestricted; - IsSharedMemory = MemoryAllocator.IsDeviceMemoryShared(_physicalDevice); MemoryAllocator = new MemoryAllocator(Api, _physicalDevice, _device); @@ -481,10 +456,9 @@ namespace Ryujinx.Graphics.Vulkan var queueFamilyIndex = VulkanInitialization.FindSuitableQueueFamily(Api, _physicalDevice, _surface, out uint maxQueueCount); - _device = VulkanInitialization.CreateDevice(Api, _physicalDevice, queueFamilyIndex, maxQueueCount, out PhysicalDeviceExtendedDynamicState2FeaturesEXT extendedDynamicState2Features, out PhysicalDeviceExtendedDynamicState3FeaturesEXT extendedDynamicState3Features); + _device = VulkanInitialization.CreateDevice(Api, _physicalDevice, queueFamilyIndex, maxQueueCount, out PhysicalDeviceExtendedDynamicState2FeaturesEXT extendedDynamicState2Features); ExtendedDynamicState2Features = extendedDynamicState2Features; - ExtendedDynamicState3Features = extendedDynamicState3Features; if (Api.TryGetDeviceExtension(_instance.Instance, _device, out KhrSwapchain swapchainApi)) { From ba56c1d3b3cf9639d0679732d7b5a6eef853636f Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 26 May 2024 18:44:53 -0700 Subject: [PATCH 043/132] Missed line --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 087ddda16..0e471f162 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -460,7 +460,6 @@ namespace Ryujinx.Graphics.Vulkan rasterizationState.LineWidth = 1.0f; } - if (!supportsExtDynamicState2) { rasterizationState.DepthBiasEnable = DepthBiasEnable; @@ -552,10 +551,6 @@ namespace Ryujinx.Graphics.Vulkan } } - // AMD has a bug where it enables logical operations even for float formats, - // so we need to force disable them here. - bool logicOpEnable = LogicOpEnable && (gd.Vendor != Vendor.Amd || Internal.LogicOpsAllowed); - var colorBlendState = new PipelineColorBlendStateCreateInfo { SType = StructureType.PipelineColorBlendStateCreateInfo, From 1adae7794a0d4af4289713dd94b3c3f40552718c Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 26 May 2024 18:46:10 -0700 Subject: [PATCH 044/132] Small changes --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 0e471f162..c2bd51a9f 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -564,13 +564,11 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.LogicOp = LogicOp; } - PipelineColorBlendAdvancedStateCreateInfoEXT colorBlendAdvancedState; - if (!AdvancedBlendSrcPreMultiplied || !AdvancedBlendDstPreMultiplied || AdvancedBlendOverlap != BlendOverlapEXT.UncorrelatedExt) { - colorBlendAdvancedState = new PipelineColorBlendAdvancedStateCreateInfoEXT + PipelineColorBlendAdvancedStateCreateInfoEXT colorBlendAdvancedState = new PipelineColorBlendAdvancedStateCreateInfoEXT { SType = StructureType.PipelineColorBlendAdvancedStateCreateInfoExt, SrcPremultiplied = AdvancedBlendSrcPreMultiplied, @@ -622,7 +620,7 @@ namespace Ryujinx.Graphics.Vulkan if (!isMoltenVk) { - //LineWidth is only supported on MacOS when using Metal Private API on newer version of MoltenVK + //LineWidth is only supported on macOS when using Metal Private API on newer version of MoltenVK dynamicStates[currentIndex++] = DynamicState.LineWidth; } From 4b504243d85513e4ab489e80a149b8cb506101ec Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 26 May 2024 19:08:46 -0700 Subject: [PATCH 045/132] Consolidate some checks --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 23 +++++++++++--------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index c2bd51a9f..f1ed68c8c 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -396,6 +396,15 @@ namespace Ryujinx.Graphics.Vulkan return pipeline; } + // Using patches topology without a tessellation shader is invalid. + // If we find such a case, return null pipeline to skip the draw. + if (Topology == PrimitiveTopology.PatchList && !HasTessellationControlShader) + { + program.AddGraphicsPipeline(ref Internal, null); + + return null; + } + Pipeline pipelineHandle = default; bool isMoltenVk = gd.IsMoltenVk; @@ -417,20 +426,10 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.PipelineVertexInputStateCreateInfo, VertexAttributeDescriptionCount = VertexAttributeDescriptionsCount, - PVertexAttributeDescriptions = isMoltenVk ? pVertexAttributeDescriptions2 : pVertexAttributeDescriptions, VertexBindingDescriptionCount = VertexBindingDescriptionsCount, PVertexBindingDescriptions = pVertexBindingDescriptions, }; - // Using patches topology without a tessellation shader is invalid. - // If we find such a case, return null pipeline to skip the draw. - if (Topology == PrimitiveTopology.PatchList && !HasTessellationControlShader) - { - program.AddGraphicsPipeline(ref Internal, null); - - return null; - } - var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, @@ -456,6 +455,8 @@ namespace Ryujinx.Graphics.Vulkan if (isMoltenVk) { + vertexInputState.PVertexAttributeDescriptions = pVertexAttributeDescriptions2; + //When widelines feature is not supported it must be 1.0f per spec. rasterizationState.LineWidth = 1.0f; } @@ -584,6 +585,8 @@ namespace Ryujinx.Graphics.Vulkan if (!isMoltenVk) { + vertexInputState.PVertexAttributeDescriptions = pVertexAttributeDescriptions; + baseDynamicStatesCount++; } From 7ac2cd44d0c735e232b93a264a0e8548106bd1b4 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 26 May 2024 22:08:14 -0700 Subject: [PATCH 046/132] Attempt proper VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY implementation --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 49 +++++++++++++++++-- .../PipelineDynamicState.cs | 20 ++++++-- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 3 +- 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 83dad8e82..1f8677b81 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -696,7 +696,7 @@ namespace Ryujinx.Graphics.Vulkan 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 oldTopology = _supportExtDynamic ? DynamicState.Topology : _newState.Topology; var oldViewports = DynamicState.Viewports; var oldViewportsCount = _supportExtDynamic ? DynamicState.ViewportsCount : _newState.ViewportsCount; @@ -729,6 +729,7 @@ namespace Ryujinx.Graphics.Vulkan DynamicState.SetCullMode(oldCullMode); DynamicState.SetStencilTest(oldStencilTestEnable); DynamicState.SetDepthTestBool(oldDepthTestEnable, oldDepthWriteEnable); + DynamicState.SetPrimitiveTopology(oldTopology); } else { @@ -737,10 +738,9 @@ namespace Ryujinx.Graphics.Vulkan _newState.DepthTestEnable = oldDepthTestEnable; _newState.DepthWriteEnable = oldDepthWriteEnable; _newState.ViewportsCount = oldViewportsCount; + _newState.Topology = oldTopology; } - _newState.Topology = oldTopology; - DynamicState.SetViewports(ref oldViewports, oldViewportsCount); SignalStateChange(); @@ -1094,11 +1094,52 @@ namespace Ryujinx.Graphics.Vulkan var vkTopology = Gd.TopologyRemap(topology).Convert(); - _newState.Topology = vkTopology; + var currentTopologyClass = GetTopologyClass(_newState.Topology); + var newTopologyClass = GetTopologyClass(vkTopology); + + if (_supportExtDynamic) + { + DynamicState.SetPrimitiveTopology(vkTopology); + if (currentTopologyClass != newTopologyClass) + { + _newState.Topology = vkTopology; + } + } + else + { + _newState.Topology = vkTopology; + } SignalStateChange(); } + private TopologyClass GetTopologyClass(Silk.NET.Vulkan.PrimitiveTopology topology) + { + return topology switch + { + Silk.NET.Vulkan.PrimitiveTopology.PointList => TopologyClass.Point, + Silk.NET.Vulkan.PrimitiveTopology.LineList => TopologyClass.Line, + Silk.NET.Vulkan.PrimitiveTopology.LineStrip => TopologyClass.Line, + Silk.NET.Vulkan.PrimitiveTopology.LineListWithAdjacency => TopologyClass.Line, + Silk.NET.Vulkan.PrimitiveTopology.LineStripWithAdjacency => TopologyClass.Line, + Silk.NET.Vulkan.PrimitiveTopology.TriangleList => TopologyClass.Triangle, + Silk.NET.Vulkan.PrimitiveTopology.TriangleStrip => TopologyClass.Triangle, + Silk.NET.Vulkan.PrimitiveTopology.TriangleFan => TopologyClass.Triangle, + Silk.NET.Vulkan.PrimitiveTopology.TriangleListWithAdjacency => TopologyClass.Triangle, + Silk.NET.Vulkan.PrimitiveTopology.TriangleStripWithAdjacency => TopologyClass.Triangle, + Silk.NET.Vulkan.PrimitiveTopology.PatchList => TopologyClass.Patch, + _ => throw new ArgumentOutOfRangeException(nameof(topology), topology, null) + }; + } + + private enum TopologyClass + { + Point, + Line, + Triangle, + Patch + } + public void SetProgram(IProgram program) { var internalProgram = (ShaderCollection)program; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 63527c472..d421086dd 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -54,6 +54,8 @@ namespace Ryujinx.Graphics.Vulkan private uint _patchControlPoints; + public PrimitiveTopology Topology; + private bool _primitiveRestartEnable; [Flags] @@ -75,8 +77,9 @@ namespace Ryujinx.Graphics.Vulkan LogicOp = 1 << 12, PatchControlPoints = 1 << 13, PrimitiveRestart = 1 << 14, + PrimitiveTopology = 1 << 15, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, - Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable, + Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable | PrimitiveTopology, Extended2 = RasterDiscard | LogicOp | PatchControlPoints | PrimitiveRestart, } @@ -203,6 +206,12 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.PrimitiveRestart; } + public void SetPrimitiveTopology(PrimitiveTopology primitiveTopology) + { + Topology = primitiveTopology; + _dirty |= DirtyFlags.PrimitiveTopology; + } + public void SetLogicOp(LogicOp op) { _logicOp = op; @@ -312,9 +321,9 @@ namespace Ryujinx.Graphics.Vulkan RecordPrimitiveRestartEnable(gd, commandBuffer); } - if (_dirty.HasFlag(DirtyFlags.PrimitiveRestart)) + if (_dirty.HasFlag(DirtyFlags.PrimitiveTopology)) { - RecordPrimitiveRestartEnable(gd, commandBuffer); + RecordPrimitiveTopology(gd, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.LogicOp)) @@ -443,6 +452,11 @@ namespace Ryujinx.Graphics.Vulkan gd.ExtendedDynamicState2Api.CmdSetPrimitiveRestartEnable(commandBuffer, _primitiveRestartEnable); } + private readonly void RecordPrimitiveTopology(VulkanRenderer gd, CommandBuffer commandBuffer) + { + gd.ExtendedDynamicStateApi.CmdSetPrimitiveTopology(commandBuffer, Topology); + } + private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) { gd.ExtendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index f1ed68c8c..fa66e9fd8 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -592,7 +592,7 @@ namespace Ryujinx.Graphics.Vulkan if (supportsExtDynamicState) { - additionalDynamicStatesCount += isMoltenVk ? 7 : 8; + additionalDynamicStatesCount += isMoltenVk ? 8 : 9; } if (supportsExtDynamicState2) @@ -643,6 +643,7 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[currentIndex++] = DynamicState.DepthCompareOpExt; dynamicStates[currentIndex++] = DynamicState.StencilTestEnableExt; dynamicStates[currentIndex++] = DynamicState.StencilOpExt; + dynamicStates[currentIndex++] = DynamicState.PrimitiveTopologyExt; } if (supportsExtDynamicState2) From 4a3932ed54e40dfc5692a7664b5d2c76720137e1 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 26 May 2024 22:33:49 -0700 Subject: [PATCH 047/132] Use dictionary instead for clarity and rework some logic. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 44 +++++++++---------- .../PipelineDynamicState.cs | 4 +- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 15 +++---- 3 files changed, 29 insertions(+), 34 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 1f8677b81..32e27ada9 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -2,6 +2,7 @@ using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Shader; using Silk.NET.Vulkan; using System; +using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; @@ -1067,7 +1068,7 @@ namespace Ryujinx.Graphics.Vulkan primitiveRestartEnable &= topologySupportsRestart; - //Cannot disable primitveRestartEnable for these Topoligies on MacOS + //Cannot disable primitiveRestartEnable for these Topologies 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) @@ -1093,19 +1094,15 @@ namespace Ryujinx.Graphics.Vulkan _topology = topology; var vkTopology = Gd.TopologyRemap(topology).Convert(); - - var currentTopologyClass = GetTopologyClass(_newState.Topology); var newTopologyClass = GetTopologyClass(vkTopology); + var currentTopologyClass = GetTopologyClass(_newState.Topology); if (_supportExtDynamic) { DynamicState.SetPrimitiveTopology(vkTopology); - if (currentTopologyClass != newTopologyClass) - { - _newState.Topology = vkTopology; - } } - else + + if (!_supportExtDynamic || currentTopologyClass != newTopologyClass) { _newState.Topology = vkTopology; } @@ -1115,23 +1112,24 @@ namespace Ryujinx.Graphics.Vulkan private TopologyClass GetTopologyClass(Silk.NET.Vulkan.PrimitiveTopology topology) { - return topology switch - { - Silk.NET.Vulkan.PrimitiveTopology.PointList => TopologyClass.Point, - Silk.NET.Vulkan.PrimitiveTopology.LineList => TopologyClass.Line, - Silk.NET.Vulkan.PrimitiveTopology.LineStrip => TopologyClass.Line, - Silk.NET.Vulkan.PrimitiveTopology.LineListWithAdjacency => TopologyClass.Line, - Silk.NET.Vulkan.PrimitiveTopology.LineStripWithAdjacency => TopologyClass.Line, - Silk.NET.Vulkan.PrimitiveTopology.TriangleList => TopologyClass.Triangle, - Silk.NET.Vulkan.PrimitiveTopology.TriangleStrip => TopologyClass.Triangle, - Silk.NET.Vulkan.PrimitiveTopology.TriangleFan => TopologyClass.Triangle, - Silk.NET.Vulkan.PrimitiveTopology.TriangleListWithAdjacency => TopologyClass.Triangle, - Silk.NET.Vulkan.PrimitiveTopology.TriangleStripWithAdjacency => TopologyClass.Triangle, - Silk.NET.Vulkan.PrimitiveTopology.PatchList => TopologyClass.Patch, - _ => throw new ArgumentOutOfRangeException(nameof(topology), topology, null) - }; + return topologyClassMapping.TryGetValue(topology, out var topologyClass) ? topologyClass : throw new ArgumentOutOfRangeException(nameof(topology), topology, null); } + private static readonly Dictionary topologyClassMapping = new() + { + { Silk.NET.Vulkan.PrimitiveTopology.PointList, TopologyClass.Point }, + { Silk.NET.Vulkan.PrimitiveTopology.LineList, TopologyClass.Line }, + { Silk.NET.Vulkan.PrimitiveTopology.LineStrip, TopologyClass.Line }, + { Silk.NET.Vulkan.PrimitiveTopology.LineListWithAdjacency, TopologyClass.Line }, + { Silk.NET.Vulkan.PrimitiveTopology.LineStripWithAdjacency, TopologyClass.Line }, + { Silk.NET.Vulkan.PrimitiveTopology.TriangleList, TopologyClass.Triangle }, + { Silk.NET.Vulkan.PrimitiveTopology.TriangleStrip, TopologyClass.Triangle }, + { Silk.NET.Vulkan.PrimitiveTopology.TriangleFan, TopologyClass.Triangle }, + { Silk.NET.Vulkan.PrimitiveTopology.TriangleListWithAdjacency, TopologyClass.Triangle }, + { Silk.NET.Vulkan.PrimitiveTopology.TriangleStripWithAdjacency, TopologyClass.Triangle }, + { Silk.NET.Vulkan.PrimitiveTopology.PatchList, TopologyClass.Patch } + }; + private enum TopologyClass { Point, diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index d421086dd..e873e1d5e 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -230,12 +230,12 @@ namespace Ryujinx.Graphics.Vulkan if (gd.Capabilities.SupportsExtendedDynamicState) { - _dirty = DirtyFlags.Standard | DirtyFlags.Extended; + _dirty |= DirtyFlags.Extended; } if (gd.Capabilities.SupportsExtendedDynamicState2) { - _dirty = DirtyFlags.Standard | DirtyFlags.Extended | DirtyFlags.Extended2; + _dirty |= DirtyFlags.Extended2; } if (gd.IsMoltenVk) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index fa66e9fd8..c8ffece2d 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -391,11 +391,6 @@ namespace Ryujinx.Graphics.Vulkan RenderPass renderPass, bool throwOnError = false) { - if (program.TryGetGraphicsPipeline(ref Internal, out var pipeline)) - { - return pipeline; - } - // Using patches topology without a tessellation shader is invalid. // If we find such a case, return null pipeline to skip the draw. if (Topology == PrimitiveTopology.PatchList && !HasTessellationControlShader) @@ -405,6 +400,11 @@ namespace Ryujinx.Graphics.Vulkan return null; } + if (program.TryGetGraphicsPipeline(ref Internal, out var pipeline)) + { + return pipeline; + } + Pipeline pipelineHandle = default; bool isMoltenVk = gd.IsMoltenVk; @@ -426,6 +426,7 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.PipelineVertexInputStateCreateInfo, VertexAttributeDescriptionCount = VertexAttributeDescriptionsCount, + PVertexAttributeDescriptions = isMoltenVk ? pVertexAttributeDescriptions2 : pVertexAttributeDescriptions, VertexBindingDescriptionCount = VertexBindingDescriptionsCount, PVertexBindingDescriptions = pVertexBindingDescriptions, }; @@ -455,8 +456,6 @@ namespace Ryujinx.Graphics.Vulkan if (isMoltenVk) { - vertexInputState.PVertexAttributeDescriptions = pVertexAttributeDescriptions2; - //When widelines feature is not supported it must be 1.0f per spec. rasterizationState.LineWidth = 1.0f; } @@ -585,8 +584,6 @@ namespace Ryujinx.Graphics.Vulkan if (!isMoltenVk) { - vertexInputState.PVertexAttributeDescriptions = pVertexAttributeDescriptions; - baseDynamicStatesCount++; } From 3683ee5c29977e94f75592599db8941047760812 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 27 May 2024 23:25:59 -0700 Subject: [PATCH 048/132] Follow namign rules. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 32e27ada9..cadc3d2ae 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1102,7 +1102,7 @@ namespace Ryujinx.Graphics.Vulkan DynamicState.SetPrimitiveTopology(vkTopology); } - if (!_supportExtDynamic || currentTopologyClass != newTopologyClass) + if (!_supportExtDynamic || (currentTopologyClass != newTopologyClass)) { _newState.Topology = vkTopology; } @@ -1112,10 +1112,10 @@ namespace Ryujinx.Graphics.Vulkan private TopologyClass GetTopologyClass(Silk.NET.Vulkan.PrimitiveTopology topology) { - return topologyClassMapping.TryGetValue(topology, out var topologyClass) ? topologyClass : throw new ArgumentOutOfRangeException(nameof(topology), topology, null); + return _topologyClassMapping.TryGetValue(topology, out var topologyClass) ? topologyClass : throw new ArgumentOutOfRangeException(nameof(topology), topology, null); } - private static readonly Dictionary topologyClassMapping = new() + private static readonly Dictionary _topologyClassMapping = new() { { Silk.NET.Vulkan.PrimitiveTopology.PointList, TopologyClass.Point }, { Silk.NET.Vulkan.PrimitiveTopology.LineList, TopologyClass.Line }, From 424166acd8e3a583d92e77d4b15485cae285ac61 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Tue, 28 May 2024 13:01:08 -0700 Subject: [PATCH 049/132] Oversight --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index cadc3d2ae..9e387fd5d 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -727,10 +727,18 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { + var oldTopologyClass = GetTopologyClass(oldTopology); + var newTopologyClass = GetTopologyClass(DynamicState.Topology); + DynamicState.SetCullMode(oldCullMode); DynamicState.SetStencilTest(oldStencilTestEnable); DynamicState.SetDepthTestBool(oldDepthTestEnable, oldDepthWriteEnable); DynamicState.SetPrimitiveTopology(oldTopology); + + if (oldTopologyClass != newTopologyClass) + { + _newState.Topology = oldTopology; + } } else { From efdcce44150934d80f4c5070d1b8d9553816a15b Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 29 May 2024 08:36:24 -0700 Subject: [PATCH 050/132] Only enable enable LogicOp dynamic state and logic op if its enabled. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 18 +++++++++--------- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 9e387fd5d..db4d922b6 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1001,20 +1001,20 @@ namespace Ryujinx.Graphics.Vulkan public void SetLogicOpState(bool enable, LogicalOp op) { - if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) - { - DynamicState.SetLogicOp(op.Convert()); - } - else - { - _newState.LogicOp = op.Convert(); - } - // Vendors other than NVIDIA have a bug where it enables logical operations even for float formats, // so we need to force disable them here. bool logicOpEnable = enable && (Gd.Vendor == Vendor.Nvidia || _newState.Internal.LogicOpsAllowed); _newState.LogicOpEnable = logicOpEnable; + + if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp && logicOpEnable) + { + DynamicState.SetLogicOp(op.Convert()); + } + else if (logicOpEnable) + { + _newState.LogicOp = op.Convert(); + } SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index c8ffece2d..ac95cfb24 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -595,7 +595,7 @@ namespace Ryujinx.Graphics.Vulkan if (supportsExtDynamicState2) { additionalDynamicStatesCount += 3; - if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) + if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp && LogicOpEnable) { additionalDynamicStatesCount++; } @@ -649,7 +649,7 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[currentIndex++] = DynamicState.RasterizerDiscardEnableExt; dynamicStates[currentIndex++] = DynamicState.PrimitiveRestartEnableExt; - if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) + if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp && LogicOpEnable) { dynamicStates[currentIndex++] = DynamicState.LogicOpExt; } From 88786ba29ccae36a6bb2b58a56220f10723091b6 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 29 May 2024 08:44:08 -0700 Subject: [PATCH 051/132] Missed change --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index ac95cfb24..e210bebd7 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -559,7 +559,7 @@ namespace Ryujinx.Graphics.Vulkan LogicOpEnable = LogicOpEnable, }; - if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) + if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp && LogicOpEnable) { colorBlendState.LogicOp = LogicOp; } From 5c65880ec055c1435e1c26208772f5a8b7c190a8 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 29 May 2024 09:16:44 -0700 Subject: [PATCH 052/132] Whitespaces --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index db4d922b6..076d4351c 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -729,7 +729,7 @@ namespace Ryujinx.Graphics.Vulkan { var oldTopologyClass = GetTopologyClass(oldTopology); var newTopologyClass = GetTopologyClass(DynamicState.Topology); - + DynamicState.SetCullMode(oldCullMode); DynamicState.SetStencilTest(oldStencilTestEnable); DynamicState.SetDepthTestBool(oldDepthTestEnable, oldDepthWriteEnable); @@ -1006,7 +1006,7 @@ namespace Ryujinx.Graphics.Vulkan bool logicOpEnable = enable && (Gd.Vendor == Vendor.Nvidia || _newState.Internal.LogicOpsAllowed); _newState.LogicOpEnable = logicOpEnable; - + if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp && logicOpEnable) { DynamicState.SetLogicOp(op.Convert()); From e6492f8e786c3712f80f1ccb53a68282215e436f Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 29 May 2024 09:45:56 -0700 Subject: [PATCH 053/132] Reduce unneeded state changes --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 11 +++-- .../PipelineDynamicState.cs | 5 ++- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 41 ++++++++++++++----- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 076d4351c..eec57b83d 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -880,12 +880,10 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) { - DynamicState.SetDepthBias(factor, units, clamp, (enables != 0)); + bool enable = enables != 0; + DynamicState.SetDepthBias(factor, units, clamp, enable); - if (!_supportExtDynamic2) - { - _newState.DepthBiasEnable = enables != 0; - } + _newState.DepthBiasEnable = enable; SignalStateChange(); } @@ -919,11 +917,12 @@ namespace Ryujinx.Graphics.Vulkan } else { - _newState.DepthTestEnable = depthTest.TestEnable; _newState.DepthWriteEnable = depthTest.WriteEnable; _newState.DepthCompareOp = depthTest.Func.Convert(); } + _newState.DepthTestEnable = depthTest.TestEnable; + SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index e873e1d5e..d44c3f708 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -434,7 +434,10 @@ namespace Ryujinx.Graphics.Vulkan { api.CmdSetDepthTestEnable(commandBuffer, DepthTestEnable); - api.CmdSetDepthWriteEnable(commandBuffer, DepthWriteEnable); + if (DepthTestEnable) + { + api.CmdSetDepthWriteEnable(commandBuffer, DepthWriteEnable); + } } private readonly void RecordDepthTestCompareOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index e210bebd7..bf2be65ca 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -526,7 +526,10 @@ namespace Ryujinx.Graphics.Vulkan depthStencilState.Back = stencilBack; depthStencilState.StencilTestEnable = StencilTestEnable; depthStencilState.DepthTestEnable = DepthTestEnable; - depthStencilState.DepthWriteEnable = DepthWriteEnable; + if (DepthTestEnable) + { + depthStencilState.DepthWriteEnable = DepthWriteEnable; + } depthStencilState.DepthCompareOp = DepthCompareOp; } @@ -579,7 +582,7 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.PNext = &colorBlendAdvancedState; } - int baseDynamicStatesCount = 7; + int baseDynamicStatesCount = 6; int additionalDynamicStatesCount = 0; if (!isMoltenVk) @@ -587,9 +590,19 @@ namespace Ryujinx.Graphics.Vulkan baseDynamicStatesCount++; } + if (DepthBiasEnable) + { + baseDynamicStatesCount++; + } + if (supportsExtDynamicState) { - additionalDynamicStatesCount += isMoltenVk ? 8 : 9; + additionalDynamicStatesCount += isMoltenVk ? 7 : 8; + + if (DepthTestEnable) + { + additionalDynamicStatesCount++; + } } if (supportsExtDynamicState2) @@ -610,13 +623,16 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[0] = DynamicState.Viewport; dynamicStates[1] = DynamicState.Scissor; - dynamicStates[2] = DynamicState.DepthBias; - dynamicStates[3] = DynamicState.StencilCompareMask; - dynamicStates[4] = DynamicState.StencilWriteMask; - dynamicStates[5] = DynamicState.StencilReference; - dynamicStates[6] = DynamicState.BlendConstants; + dynamicStates[2] = DynamicState.StencilCompareMask; + dynamicStates[3] = DynamicState.StencilWriteMask; + dynamicStates[4] = DynamicState.StencilReference; + dynamicStates[5] = DynamicState.BlendConstants; - int currentIndex = 7; + if (DepthBiasEnable) + { + dynamicStates[6] = DynamicState.DepthBias; + } + int currentIndex = DepthBiasEnable ? 7 : 6; if (!isMoltenVk) { @@ -636,7 +652,12 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[currentIndex++] = DynamicState.CullModeExt; dynamicStates[currentIndex++] = DynamicState.FrontFaceExt; dynamicStates[currentIndex++] = DynamicState.DepthTestEnableExt; - dynamicStates[currentIndex++] = DynamicState.DepthWriteEnableExt; + + if (DepthTestEnable) + { + dynamicStates[currentIndex++] = DynamicState.DepthWriteEnableExt; + } + dynamicStates[currentIndex++] = DynamicState.DepthCompareOpExt; dynamicStates[currentIndex++] = DynamicState.StencilTestEnableExt; dynamicStates[currentIndex++] = DynamicState.StencilOpExt; From d8d33417e9e2f451a66af2d1ef2543392bd25f90 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 29 May 2024 10:14:12 -0700 Subject: [PATCH 054/132] Fix oversight with implementing Primitive Topology Dynamic State --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 13 ++++++++----- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 11 +++++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index eec57b83d..05d2e5388 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -737,7 +737,7 @@ namespace Ryujinx.Graphics.Vulkan if (oldTopologyClass != newTopologyClass) { - _newState.Topology = oldTopology; + _newState.TopologyClass = oldTopology; } } else @@ -747,8 +747,9 @@ namespace Ryujinx.Graphics.Vulkan _newState.DepthTestEnable = oldDepthTestEnable; _newState.DepthWriteEnable = oldDepthWriteEnable; _newState.ViewportsCount = oldViewportsCount; - _newState.Topology = oldTopology; } + + _newState.Topology = oldTopology; DynamicState.SetViewports(ref oldViewports, oldViewportsCount); @@ -1102,17 +1103,19 @@ namespace Ryujinx.Graphics.Vulkan var vkTopology = Gd.TopologyRemap(topology).Convert(); var newTopologyClass = GetTopologyClass(vkTopology); - var currentTopologyClass = GetTopologyClass(_newState.Topology); + var currentTopologyClass = GetTopologyClass(_newState.TopologyClass); if (_supportExtDynamic) { DynamicState.SetPrimitiveTopology(vkTopology); } - if (!_supportExtDynamic || (currentTopologyClass != newTopologyClass)) + if ((currentTopologyClass != newTopologyClass)) { - _newState.Topology = vkTopology; + _newState.TopologyClass = vkTopology; } + + _newState.Topology = vkTopology; SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index bf2be65ca..c7d4c5ffd 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -131,6 +131,8 @@ namespace Ryujinx.Graphics.Vulkan set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFFF0FFFF) | ((ulong)value << 16); } + public PrimitiveTopology TopologyClass; + public LogicOp LogicOp { readonly get => (LogicOp)((Internal.Id7 >> 20) & 0xF); @@ -437,6 +439,15 @@ namespace Ryujinx.Graphics.Vulkan Topology = Topology, }; + if (supportsExtDynamicState) + { + inputAssemblyState.Topology = TopologyClass; + } + else + { + inputAssemblyState.Topology = Topology; + } + var tessellationState = new PipelineTessellationStateCreateInfo { SType = StructureType.PipelineTessellationStateCreateInfo, From 16a4374ae800e1e857196aa70086524e92713b5a Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 29 May 2024 10:16:14 -0700 Subject: [PATCH 055/132] Fix whitespace --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 4 ++-- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 05d2e5388..7cc0131d8 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -748,7 +748,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.DepthWriteEnable = oldDepthWriteEnable; _newState.ViewportsCount = oldViewportsCount; } - + _newState.Topology = oldTopology; DynamicState.SetViewports(ref oldViewports, oldViewportsCount); @@ -1114,7 +1114,7 @@ namespace Ryujinx.Graphics.Vulkan { _newState.TopologyClass = vkTopology; } - + _newState.Topology = vkTopology; SignalStateChange(); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index c7d4c5ffd..6e672f797 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -132,7 +132,7 @@ namespace Ryujinx.Graphics.Vulkan } public PrimitiveTopology TopologyClass; - + public LogicOp LogicOp { readonly get => (LogicOp)((Internal.Id7 >> 20) & 0xF); From 985c6488601fa351849270bc64a7bf1fdff54ec1 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 29 May 2024 22:34:23 -0700 Subject: [PATCH 056/132] Bring up pipeline converter inline with dynamic states. --- .../PipelineConverter.cs | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index e8fbea999..ea2fb3080 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -169,24 +169,41 @@ namespace Ryujinx.Graphics.Vulkan pipeline.HasDepthStencil = state.DepthStencilEnable; pipeline.LogicOpEnable = state.LogicOpEnable; - pipeline.LogicOp = state.LogicOp.Convert(); pipeline.MinDepthBounds = 0f; // Not implemented. pipeline.MaxDepthBounds = 0f; // Not implemented. - pipeline.PatchControlPoints = state.PatchControlPoints; pipeline.PolygonMode = PolygonMode.Fill; // Not implemented. - pipeline.PrimitiveRestartEnable = state.PrimitiveRestartEnable; - pipeline.RasterizerDiscardEnable = state.RasterizerDiscard; - pipeline.SamplesCount = (uint)state.SamplesCount; - pipeline.DepthBiasEnable = state.BiasEnable != 0; + if (!gd.Capabilities.SupportsExtendedDynamicState2) + { + pipeline.PrimitiveRestartEnable = state.PrimitiveRestartEnable; + pipeline.RasterizerDiscardEnable = state.RasterizerDiscard; + pipeline.DepthBiasEnable = state.BiasEnable != 0; + } + + if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) + { + pipeline.LogicOp = state.LogicOp.Convert(); + } + + if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + { + pipeline.PatchControlPoints = state.PatchControlPoints; + } + + pipeline.SamplesCount = (uint)state.SamplesCount; // Stencil masks and ref are dynamic, so are 0 in the Vulkan pipeline. if (!gd.Capabilities.SupportsExtendedDynamicState) { pipeline.DepthTestEnable = state.DepthTest.TestEnable; - pipeline.DepthWriteEnable = state.DepthTest.WriteEnable; + + if (pipeline.DepthTestEnable) + { + pipeline.DepthWriteEnable = state.DepthTest.WriteEnable; + } + pipeline.DepthCompareOp = state.DepthTest.Func.Convert(); pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None; From 966c5d463c55a957af99c6e6253650b2d3b3814a Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Thu, 30 May 2024 07:34:34 -0700 Subject: [PATCH 057/132] Sleep Deprivation --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 6e672f797..74a00d151 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -436,18 +436,9 @@ namespace Ryujinx.Graphics.Vulkan var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, - Topology = Topology, + Topology = supportsExtDynamicState ? TopologyClass : Topology, }; - if (supportsExtDynamicState) - { - inputAssemblyState.Topology = TopologyClass; - } - else - { - inputAssemblyState.Topology = Topology; - } - var tessellationState = new PipelineTessellationStateCreateInfo { SType = StructureType.PipelineTessellationStateCreateInfo, From 266649929f23c2f6d062651075baf37b69978943 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 2 Jun 2024 21:00:18 -0700 Subject: [PATCH 058/132] Clean up for some clarity and attempt to resolve some validation errors. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 12 ++--- .../PipelineDynamicState.cs | 46 +++++++++---------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 7cc0131d8..b71dc3f70 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -697,7 +697,7 @@ namespace Ryujinx.Graphics.Vulkan var oldStencilTestEnable = _supportExtDynamic ? DynamicState.StencilTestEnable : _newState.StencilTestEnable; var oldDepthTestEnable = _supportExtDynamic ? DynamicState.DepthTestEnable : _newState.DepthTestEnable; var oldDepthWriteEnable = _supportExtDynamic ? DynamicState.DepthWriteEnable : _newState.DepthWriteEnable; - var oldTopology = _supportExtDynamic ? DynamicState.Topology : _newState.Topology; + var oldTopology = _newState.Topology; var oldViewports = DynamicState.Viewports; var oldViewportsCount = _supportExtDynamic ? DynamicState.ViewportsCount : _newState.ViewportsCount; @@ -728,14 +728,13 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { var oldTopologyClass = GetTopologyClass(oldTopology); - var newTopologyClass = GetTopologyClass(DynamicState.Topology); DynamicState.SetCullMode(oldCullMode); DynamicState.SetStencilTest(oldStencilTestEnable); DynamicState.SetDepthTestBool(oldDepthTestEnable, oldDepthWriteEnable); DynamicState.SetPrimitiveTopology(oldTopology); - if (oldTopologyClass != newTopologyClass) + if (oldTopologyClass != TopologyClass.Triangle) { _newState.TopologyClass = oldTopology; } @@ -1296,7 +1295,7 @@ namespace Ryujinx.Graphics.Vulkan { if (_supportExtDynamic) { - DynamicState.SetStencilOp( + DynamicState.SetStencilTestandOp( stencilTest.BackSFail.Convert(), stencilTest.BackDpPass.Convert(), stencilTest.BackDpFail.Convert(), @@ -1304,9 +1303,8 @@ namespace Ryujinx.Graphics.Vulkan stencilTest.FrontSFail.Convert(), stencilTest.FrontDpPass.Convert(), stencilTest.FrontDpFail.Convert(), - stencilTest.FrontFunc.Convert()); - - DynamicState.SetStencilTest(stencilTest.TestEnable); + stencilTest.FrontFunc.Convert(), + stencilTest.TestEnable); } else { diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index d44c3f708..ebc048cfd 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -22,7 +22,6 @@ namespace Ryujinx.Graphics.Vulkan private uint _frontWriteMask; private uint _frontReference; - private bool _opToo; private StencilOp _backFailOp; private StencilOp _backPassOp; private StencilOp _backDepthFailOp; @@ -71,7 +70,7 @@ namespace Ryujinx.Graphics.Vulkan FrontFace = 1 << 6, DepthTestBool = 1 << 7, DepthTestCompareOp = 1 << 8, - StencilTestEnable = 1 << 9, + StencilTestEnableandStencilOp = 1 << 9, LineWidth = 1 << 10, RasterDiscard = 1 << 11, LogicOp = 1 << 12, @@ -79,7 +78,7 @@ namespace Ryujinx.Graphics.Vulkan PrimitiveRestart = 1 << 14, PrimitiveTopology = 1 << 15, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, - Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable | PrimitiveTopology, + Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnableandStencilOp | PrimitiveTopology, Extended2 = RasterDiscard | LogicOp | PatchControlPoints | PrimitiveRestart, } @@ -123,9 +122,9 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.DepthTestCompareOp; } - public void SetStencilOp(StencilOp backFailOp, StencilOp backPassOp, StencilOp backDepthFailOp, + public void SetStencilTestandOp(StencilOp backFailOp, StencilOp backPassOp, StencilOp backDepthFailOp, CompareOp backCompareOp, StencilOp frontFailOp, StencilOp frontPassOp, StencilOp frontDepthFailOp, - CompareOp frontCompareOp) + CompareOp frontCompareOp, bool stencilTestEnable) { _backFailOp = backFailOp; _backPassOp = backPassOp; @@ -135,7 +134,17 @@ namespace Ryujinx.Graphics.Vulkan _frontPassOp = frontPassOp; _frontDepthFailOp = frontDepthFailOp; _frontCompareOp = frontCompareOp; - _opToo = true; + + StencilTestEnable = stencilTestEnable; + + _dirty |= DirtyFlags.StencilTestEnableandStencilOp; + } + + public void SetStencilTest(bool stencilTestEnable) + { + StencilTestEnable = stencilTestEnable; + + _dirty |= DirtyFlags.StencilTestEnableandStencilOp; } public void SetStencilMask(uint backCompareMask, uint backWriteMask, uint backReference, @@ -150,12 +159,6 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.Stencil; } - public void SetStencilTest(bool stencilTestEnable) - { - StencilTestEnable = stencilTestEnable; - _dirty |= DirtyFlags.StencilTestEnable; - } - public void SetViewport(int index, Viewport viewport) { Viewports[index] = viewport; @@ -301,9 +304,9 @@ namespace Ryujinx.Graphics.Vulkan RecordDepthTestCompareOp(gd.ExtendedDynamicStateApi, commandBuffer); } - if (_dirty.HasFlag(DirtyFlags.StencilTestEnable)) + if (_dirty.HasFlag(DirtyFlags.StencilTestEnableandStencilOp)) { - RecordStencilTestEnable(gd.ExtendedDynamicStateApi, commandBuffer); + RecordStencilTestandOp(gd.ExtendedDynamicStateApi, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.LineWidth)) @@ -379,14 +382,6 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordStencil(VulkanRenderer gd, CommandBuffer commandBuffer) { - if (_opToo) - { - gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceBackBit, _backFailOp, _backPassOp, - _backDepthFailOp, _backCompareOp); - gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontFailOp, _frontPassOp, - _frontDepthFailOp, _frontCompareOp); - } - gd.Api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backCompareMask); gd.Api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backWriteMask); gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceBackBit, _backReference); @@ -395,9 +390,14 @@ namespace Ryujinx.Graphics.Vulkan gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference); } - private readonly void RecordStencilTestEnable(ExtExtendedDynamicState api, CommandBuffer commandBuffer) + private readonly void RecordStencilTestandOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetStencilTestEnable(commandBuffer, StencilTestEnable); + + api.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceBackBit, _backFailOp, _backPassOp, + _backDepthFailOp, _backCompareOp); + api.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontFailOp, _frontPassOp, + _frontDepthFailOp, _frontCompareOp); } private void RecordViewport(VulkanRenderer gd, CommandBuffer commandBuffer) From 933c9c89ff1702f6ee6d5339496490f892beaf02 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 3 Jun 2024 21:10:13 -0700 Subject: [PATCH 059/132] Resolve logic op validation error only primitive topology pending --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 +- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index b71dc3f70..42b129e88 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1006,7 +1006,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.LogicOpEnable = logicOpEnable; - if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp && logicOpEnable) + if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) { DynamicState.SetLogicOp(op.Convert()); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 74a00d151..ace47bef8 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -610,7 +610,7 @@ namespace Ryujinx.Graphics.Vulkan if (supportsExtDynamicState2) { additionalDynamicStatesCount += 3; - if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp && LogicOpEnable) + if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) { additionalDynamicStatesCount++; } @@ -672,7 +672,7 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[currentIndex++] = DynamicState.RasterizerDiscardEnableExt; dynamicStates[currentIndex++] = DynamicState.PrimitiveRestartEnableExt; - if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp && LogicOpEnable) + if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) { dynamicStates[currentIndex++] = DynamicState.LogicOpExt; } From 086656b7361dd1f1477898849564de4c271b658c Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Thu, 4 Jul 2024 23:03:22 -0700 Subject: [PATCH 060/132] Missed changes during merge --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 3a659bd8f..06269eb34 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -485,9 +485,7 @@ namespace Ryujinx.Graphics.Vulkan var depthStencilState = new PipelineDepthStencilStateCreateInfo { SType = StructureType.PipelineDepthStencilStateCreateInfo, - DepthBoundsTestEnable = DepthBoundsTestEnable, - MinDepthBounds = MinDepthBounds, - MaxDepthBounds = MaxDepthBounds, + DepthBoundsTestEnable = false, }; if (!supportsExtDynamicState) From feb67dede698ebc8f76aaeabe5f0f2b4db785fa1 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Thu, 4 Jul 2024 23:35:40 -0700 Subject: [PATCH 061/132] Avoid setting depth bias state when not needed. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 13 ++++++-- .../PipelineDynamicState.cs | 32 +++++++++++-------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 42b129e88..e3374f884 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -880,8 +880,17 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) { - bool enable = enables != 0; - DynamicState.SetDepthBias(factor, units, clamp, enable); + bool enable = (enables != 0) && (factor > 0.0f || units > 0.0f); + + if (enable) + { + DynamicState.SetDepthBias(factor, units, clamp); + } + + if (Gd.Capabilities.SupportsExtendedDynamicState2) + { + DynamicState.SetDepthBiasEnable(enable); + } _newState.DepthBiasEnable = enable; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index ebc048cfd..7733ead98 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -77,9 +77,10 @@ namespace Ryujinx.Graphics.Vulkan PatchControlPoints = 1 << 13, PrimitiveRestart = 1 << 14, PrimitiveTopology = 1 << 15, + DepthBiasEnable = 1 << 16, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnableandStencilOp | PrimitiveTopology, - Extended2 = RasterDiscard | LogicOp | PatchControlPoints | PrimitiveRestart, + Extended2 = RasterDiscard | LogicOp | PatchControlPoints | PrimitiveRestart | DepthBiasEnable, } private DirtyFlags _dirty; @@ -93,16 +94,21 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.Blend; } - public void SetDepthBias(float slopeFactor, float constantFactor, float clamp, bool enable) + public void SetDepthBias(float slopeFactor, float constantFactor, float clamp) { _depthBiasSlopeFactor = slopeFactor; _depthBiasConstantFactor = constantFactor; _depthBiasClamp = clamp; - _depthBiasEnable = enable; _dirty |= DirtyFlags.DepthBias; } + public void SetDepthBiasEnable(bool enable) + { + _depthBiasEnable = enable; + _dirty |= DirtyFlags.DepthBiasEnable; + } + public void SetScissor(int index, Rect2D scissor) { _scissors[index] = scissor; @@ -299,6 +305,11 @@ namespace Ryujinx.Graphics.Vulkan RecordDepthTestBool(gd.ExtendedDynamicStateApi, commandBuffer); } + if (_dirty.HasFlag(DirtyFlags.DepthBiasEnable)) + { + RecordDepthBiasEnable(gd.ExtendedDynamicState2Api, commandBuffer); + } + if (_dirty.HasFlag(DirtyFlags.DepthTestCompareOp)) { RecordDepthTestCompareOp(gd.ExtendedDynamicStateApi, commandBuffer); @@ -349,19 +360,14 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordDepthBias(VulkanRenderer gd, CommandBuffer commandBuffer) { - if (gd.Capabilities.SupportsExtendedDynamicState2) - { - gd.ExtendedDynamicState2Api.CmdSetDepthBiasEnable(commandBuffer, _depthBiasEnable); - - if (!_depthBiasEnable) - { - return; - } - } - gd.Api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); } + private readonly void RecordDepthBiasEnable(ExtExtendedDynamicState2 gd, CommandBuffer commandBuffer) + { + gd.CmdSetDepthBiasEnable(commandBuffer, _depthBiasEnable); + } + private void RecordScissor(VulkanRenderer gd, CommandBuffer commandBuffer) { if (ScissorsCount != 0) From 7610236816cf045f5e79dab52a563acd5829022c Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Fri, 19 Jul 2024 17:36:29 -0700 Subject: [PATCH 062/132] Resolve merge error --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 5301c0fec..7163c3de8 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1155,7 +1155,7 @@ namespace Ryujinx.Graphics.Vulkan { // On Adreno, enabling rasterizer discard somehow corrupts the viewport state. // Force it to be updated on next use to work around this bug. - DynamicState.ForceAllDirty(); + DynamicState.ForceAllDirty(Gd); } } From a5052013f358762f95e6a1744a4d04daa7e15c7d Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Tue, 23 Jul 2024 19:51:08 -0700 Subject: [PATCH 063/132] Fix some conditions --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 82 +++++++++++-------- .../PipelineDynamicState.cs | 12 +-- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 36 ++------ 3 files changed, 61 insertions(+), 69 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 7163c3de8..4a98a456d 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -671,15 +671,15 @@ namespace Ryujinx.Graphics.Vulkan { var oldTopologyClass = GetTopologyClass(oldTopology); - DynamicState.SetCullMode(oldCullMode); - DynamicState.SetStencilTest(oldStencilTestEnable); - DynamicState.SetDepthTestBool(oldDepthTestEnable, oldDepthWriteEnable); - DynamicState.SetPrimitiveTopology(oldTopology); - if (oldTopologyClass != TopologyClass.Triangle) { _newState.TopologyClass = oldTopology; } + + DynamicState.SetCullMode(oldCullMode); + DynamicState.SetStencilTest(oldStencilTestEnable); + DynamicState.SetDepthTestBool(oldDepthTestEnable, oldDepthWriteEnable); + DynamicState.SetPrimitiveTopology(oldTopology); } else { @@ -823,21 +823,35 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) { - bool enable = (enables != 0) && (factor > 0.0f || units > 0.0f); + if (factor == 0 && units == 0 && !_newState.DepthBiasEnable && !_supportExtDynamic2) + { + return; + } - if (enable) + bool depthBiasEnable = (enables != 0) && (factor != 0 && units != 0); + bool changed = false; + + if (_supportExtDynamic2) + { + DynamicState.SetDepthBiasEnable(depthBiasEnable); + changed = true; + } + else if (_newState.DepthBiasEnable != depthBiasEnable) + { + _newState.DepthBiasEnable = depthBiasEnable; + changed = true; + } + + if (depthBiasEnable) { DynamicState.SetDepthBias(factor, units, clamp); + changed = true; } - if (Gd.Capabilities.SupportsExtendedDynamicState2) + if (changed) { - DynamicState.SetDepthBiasEnable(enable); + SignalStateChange(); } - - _newState.DepthBiasEnable = enable; - - SignalStateChange(); } public void SetDepthClamp(bool clamp) @@ -849,15 +863,16 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthMode(DepthMode mode) { - bool oldMode; + bool newMode = mode == DepthMode.MinusOneToOne; - oldMode = _newState.DepthMode; - _newState.DepthMode = mode == DepthMode.MinusOneToOne; - - if (_newState.DepthMode != oldMode) + if (_newState.DepthMode == newMode) { - SignalStateChange(); + return; } + + _newState.DepthMode = newMode; + + SignalStateChange(); } public void SetDepthTest(DepthTestDescriptor depthTest) @@ -865,16 +880,18 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { DynamicState.SetDepthTestBool(depthTest.TestEnable, depthTest.WriteEnable); - DynamicState.SetDepthTestCompareOp(depthTest.Func.Convert()); + if (depthTest.TestEnable) + { + DynamicState.SetDepthTestCompareOp(depthTest.Func.Convert()); + } } else { - _newState.DepthWriteEnable = depthTest.WriteEnable; - _newState.DepthCompareOp = depthTest.Func.Convert(); + _newState.DepthTestEnable = depthTest.TestEnable; + _newState.DepthWriteEnable = depthTest.WriteEnable && depthTest.TestEnable; + _newState.DepthCompareOp = depthTest.TestEnable ? depthTest.Func.Convert() : default; } - _newState.DepthTestEnable = depthTest.TestEnable; - SignalStateChange(); } @@ -958,7 +975,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.LogicOpEnable = logicOpEnable; - if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) + if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp && logicOpEnable) { DynamicState.SetLogicOp(op.Convert()); } @@ -1053,17 +1070,18 @@ namespace Ryujinx.Graphics.Vulkan _topology = topology; var vkTopology = Gd.TopologyRemap(topology).Convert(); - var newTopologyClass = GetTopologyClass(vkTopology); - var currentTopologyClass = GetTopologyClass(_newState.TopologyClass); if (_supportExtDynamic) { - DynamicState.SetPrimitiveTopology(vkTopology); - } + var newTopologyClass = GetTopologyClass(vkTopology); + var currentTopologyClass = GetTopologyClass(_newState.TopologyClass); - if ((currentTopologyClass != newTopologyClass)) - { - _newState.TopologyClass = vkTopology; + if ((currentTopologyClass != newTopologyClass)) + { + _newState.TopologyClass = vkTopology; + } + + DynamicState.SetPrimitiveTopology(vkTopology); } _newState.Topology = vkTopology; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 7733ead98..2c473ab79 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -118,7 +118,7 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthTestBool(bool testEnable, bool writeEnable) { DepthTestEnable = testEnable; - DepthWriteEnable = writeEnable; + DepthWriteEnable = writeEnable && testEnable; _dirty |= DirtyFlags.DepthTestBool; } @@ -440,10 +440,7 @@ namespace Ryujinx.Graphics.Vulkan { api.CmdSetDepthTestEnable(commandBuffer, DepthTestEnable); - if (DepthTestEnable) - { - api.CmdSetDepthWriteEnable(commandBuffer, DepthWriteEnable); - } + api.CmdSetDepthWriteEnable(commandBuffer, DepthWriteEnable); } private readonly void RecordDepthTestCompareOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) @@ -478,10 +475,7 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordLineWidth(Vk api, CommandBuffer commandBuffer) { - 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 06269eb34..7f0205f11 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -446,7 +446,7 @@ namespace Ryujinx.Graphics.Vulkan if (isMoltenVk) { - //When widelines feature is not supported it must be 1.0f per spec. + //When widelines feature is not supported it must be 1.0f. rasterizationState.LineWidth = 1.0f; } @@ -514,10 +514,7 @@ namespace Ryujinx.Graphics.Vulkan depthStencilState.Back = stencilBack; depthStencilState.StencilTestEnable = StencilTestEnable; depthStencilState.DepthTestEnable = DepthTestEnable; - if (DepthTestEnable) - { - depthStencilState.DepthWriteEnable = DepthWriteEnable; - } + depthStencilState.DepthWriteEnable = DepthWriteEnable; depthStencilState.DepthCompareOp = DepthCompareOp; } @@ -570,7 +567,7 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.PNext = &colorBlendAdvancedState; } - int baseDynamicStatesCount = 6; + int baseDynamicStatesCount = 7; int additionalDynamicStatesCount = 0; if (!isMoltenVk) @@ -578,19 +575,9 @@ namespace Ryujinx.Graphics.Vulkan baseDynamicStatesCount++; } - if (DepthBiasEnable) - { - baseDynamicStatesCount++; - } - if (supportsExtDynamicState) { - additionalDynamicStatesCount += isMoltenVk ? 7 : 8; - - if (DepthTestEnable) - { - additionalDynamicStatesCount++; - } + additionalDynamicStatesCount += isMoltenVk ? 8 : 9; } if (supportsExtDynamicState2) @@ -615,16 +602,13 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[3] = DynamicState.StencilWriteMask; dynamicStates[4] = DynamicState.StencilReference; dynamicStates[5] = DynamicState.BlendConstants; + dynamicStates[6] = DynamicState.DepthBias; - if (DepthBiasEnable) - { - dynamicStates[6] = DynamicState.DepthBias; - } - int currentIndex = DepthBiasEnable ? 7 : 6; + int currentIndex = 7; if (!isMoltenVk) { - //LineWidth is only supported on macOS when using Metal Private API on newer version of MoltenVK + //LineWidth dynamic state is only supported on macOS when using Metal Private API on newer version of MoltenVK dynamicStates[currentIndex++] = DynamicState.LineWidth; } @@ -640,11 +624,7 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[currentIndex++] = DynamicState.CullModeExt; dynamicStates[currentIndex++] = DynamicState.FrontFaceExt; dynamicStates[currentIndex++] = DynamicState.DepthTestEnableExt; - - if (DepthTestEnable) - { - dynamicStates[currentIndex++] = DynamicState.DepthWriteEnableExt; - } + dynamicStates[currentIndex++] = DynamicState.DepthWriteEnableExt; dynamicStates[currentIndex++] = DynamicState.DepthCompareOpExt; dynamicStates[currentIndex++] = DynamicState.StencilTestEnableExt; From b66f6ce6732aa245983b18e785df6395e4cf04f5 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Tue, 23 Jul 2024 20:58:47 -0700 Subject: [PATCH 064/132] Resolve some validation errors --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 4a98a456d..eed18c6dd 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -880,10 +880,7 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { DynamicState.SetDepthTestBool(depthTest.TestEnable, depthTest.WriteEnable); - if (depthTest.TestEnable) - { - DynamicState.SetDepthTestCompareOp(depthTest.Func.Convert()); - } + DynamicState.SetDepthTestCompareOp(depthTest.TestEnable ? depthTest.Func.Convert() : default); } else { @@ -975,13 +972,13 @@ namespace Ryujinx.Graphics.Vulkan _newState.LogicOpEnable = logicOpEnable; - if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp && logicOpEnable) + if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) { - DynamicState.SetLogicOp(op.Convert()); + DynamicState.SetLogicOp(logicOpEnable ? op.Convert() : default); } - else if (logicOpEnable) + else { - _newState.LogicOp = op.Convert(); + _newState.LogicOp = logicOpEnable ? op.Convert() : default; } SignalStateChange(); From 2cba50a9ed595d46beea3a94194a6b37bacc76ce Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Tue, 23 Jul 2024 21:54:01 -0700 Subject: [PATCH 065/132] Move TopologyClass conversoin to EnumConversion.cs --- src/Ryujinx.Graphics.Vulkan/EnumConversion.cs | 22 ++++++++++ src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 41 +++---------------- 2 files changed, 28 insertions(+), 35 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs b/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs index 9d1fd9ffd..d58603cd6 100644 --- a/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs +++ b/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs @@ -310,6 +310,28 @@ namespace Ryujinx.Graphics.Vulkan }; } + public static PrimitiveTopology ConvertToClass(this GAL.PrimitiveTopology topology) + { + return topology switch + { + GAL.PrimitiveTopology.Points => PrimitiveTopology.PointList, + GAL.PrimitiveTopology.Lines or + GAL.PrimitiveTopology.LineStrip or + GAL.PrimitiveTopology.LinesAdjacency or + GAL.PrimitiveTopology.LineStripAdjacency => PrimitiveTopology.LineList, + GAL.PrimitiveTopology.Triangles or + GAL.PrimitiveTopology.TriangleStrip or + GAL.PrimitiveTopology.TriangleFan or + GAL.PrimitiveTopology.TrianglesAdjacency or + GAL.PrimitiveTopology.TriangleStripAdjacency or + GAL.PrimitiveTopology.Polygon => PrimitiveTopology.TriangleList, + GAL.PrimitiveTopology.Patches => PrimitiveTopology.PatchList, + GAL.PrimitiveTopology.Quads => throw new NotSupportedException("Quad topology is not available in Vulkan."), + GAL.PrimitiveTopology.QuadStrip => throw new NotSupportedException("QuadStrip topology is not available in Vulkan."), + _ => LogInvalidAndReturn(topology, nameof(GAL.PrimitiveTopology), PrimitiveTopology.TriangleList), + }; + } + public static StencilOp Convert(this GAL.StencilOp op) { return op switch diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index eed18c6dd..4b3221fdd 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -640,6 +640,7 @@ namespace Ryujinx.Graphics.Vulkan var oldDepthTestEnable = _supportExtDynamic ? DynamicState.DepthTestEnable : _newState.DepthTestEnable; var oldDepthWriteEnable = _supportExtDynamic ? DynamicState.DepthWriteEnable : _newState.DepthWriteEnable; var oldTopology = _newState.Topology; + var oldTopologyClass = _newState.TopologyClass; var oldViewports = DynamicState.Viewports; var oldViewportsCount = _supportExtDynamic ? DynamicState.ViewportsCount : _newState.ViewportsCount; @@ -669,9 +670,7 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { - var oldTopologyClass = GetTopologyClass(oldTopology); - - if (oldTopologyClass != TopologyClass.Triangle) + if (oldTopologyClass != Silk.NET.Vulkan.PrimitiveTopology.TriangleList) { _newState.TopologyClass = oldTopology; } @@ -1070,12 +1069,12 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { - var newTopologyClass = GetTopologyClass(vkTopology); - var currentTopologyClass = GetTopologyClass(_newState.TopologyClass); + var oldTopologyClass = _newState.TopologyClass; + var newTopologyClass = Gd.TopologyRemap(topology).ConvertToClass(); - if ((currentTopologyClass != newTopologyClass)) + if ((oldTopologyClass != newTopologyClass)) { - _newState.TopologyClass = vkTopology; + _newState.TopologyClass = newTopologyClass; } DynamicState.SetPrimitiveTopology(vkTopology); @@ -1086,34 +1085,6 @@ namespace Ryujinx.Graphics.Vulkan SignalStateChange(); } - private TopologyClass GetTopologyClass(Silk.NET.Vulkan.PrimitiveTopology topology) - { - return _topologyClassMapping.TryGetValue(topology, out var topologyClass) ? topologyClass : throw new ArgumentOutOfRangeException(nameof(topology), topology, null); - } - - private static readonly Dictionary _topologyClassMapping = new() - { - { Silk.NET.Vulkan.PrimitiveTopology.PointList, TopologyClass.Point }, - { Silk.NET.Vulkan.PrimitiveTopology.LineList, TopologyClass.Line }, - { Silk.NET.Vulkan.PrimitiveTopology.LineStrip, TopologyClass.Line }, - { Silk.NET.Vulkan.PrimitiveTopology.LineListWithAdjacency, TopologyClass.Line }, - { Silk.NET.Vulkan.PrimitiveTopology.LineStripWithAdjacency, TopologyClass.Line }, - { Silk.NET.Vulkan.PrimitiveTopology.TriangleList, TopologyClass.Triangle }, - { Silk.NET.Vulkan.PrimitiveTopology.TriangleStrip, TopologyClass.Triangle }, - { Silk.NET.Vulkan.PrimitiveTopology.TriangleFan, TopologyClass.Triangle }, - { Silk.NET.Vulkan.PrimitiveTopology.TriangleListWithAdjacency, TopologyClass.Triangle }, - { Silk.NET.Vulkan.PrimitiveTopology.TriangleStripWithAdjacency, TopologyClass.Triangle }, - { Silk.NET.Vulkan.PrimitiveTopology.PatchList, TopologyClass.Patch } - }; - - private enum TopologyClass - { - Point, - Line, - Triangle, - Patch - } - public void SetProgram(IProgram program) { var internalProgram = (ShaderCollection)program; From ea44670330d5bc0df405c86755ae8646d00e7341 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Tue, 23 Jul 2024 22:03:47 -0700 Subject: [PATCH 066/132] Set logicOp and DepthCompareOp only if enabled --- src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index da79a42c5..c1a7d52d7 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -178,7 +178,7 @@ namespace Ryujinx.Graphics.Vulkan if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) { - pipeline.LogicOp = state.LogicOp.Convert(); + pipeline.LogicOp = state.LogicOpEnable ? state.LogicOp.Convert() : default; } if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) @@ -192,13 +192,9 @@ namespace Ryujinx.Graphics.Vulkan if (!gd.Capabilities.SupportsExtendedDynamicState) { pipeline.DepthTestEnable = state.DepthTest.TestEnable; + pipeline.DepthWriteEnable = state.DepthTest.WriteEnable && state.DepthTest.TestEnable; - if (pipeline.DepthTestEnable) - { - pipeline.DepthWriteEnable = state.DepthTest.WriteEnable; - } - - pipeline.DepthCompareOp = state.DepthTest.Func.Convert(); + pipeline.DepthCompareOp = state.DepthTest.TestEnable ? state.DepthTest.Func.Convert() : default; pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None; From e7a429940052b7cae53269b61d7e0977dd80d499 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Tue, 23 Jul 2024 22:09:56 -0700 Subject: [PATCH 067/132] Minor change --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 4b3221fdd..d001c46e6 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1069,10 +1069,9 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { - var oldTopologyClass = _newState.TopologyClass; var newTopologyClass = Gd.TopologyRemap(topology).ConvertToClass(); - if ((oldTopologyClass != newTopologyClass)) + if ((_newState.TopologyClass != newTopologyClass)) { _newState.TopologyClass = newTopologyClass; } From 7396c05b354beedfe731683a07fa1c22838beccb Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 29 Jul 2024 20:32:52 -0700 Subject: [PATCH 068/132] Resolve crash --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 7f0205f11..ddbe50f8a 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -547,7 +547,7 @@ namespace Ryujinx.Graphics.Vulkan LogicOpEnable = LogicOpEnable, }; - if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp && LogicOpEnable) + if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) { colorBlendState.LogicOp = LogicOp; } From 1b9e42bdb45af23fb53f12d9dcfa349571ed61b6 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Tue, 30 Jul 2024 18:17:49 -0700 Subject: [PATCH 069/132] Should not just check for extension. This is more correct. --- src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index aec4a8d3e..3107dcf30 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -469,7 +469,7 @@ namespace Ryujinx.Graphics.Vulkan SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, PNext = pExtendedFeatures, ExtendedDynamicState2 = - physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName), + supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2, ExtendedDynamicState2LogicOp = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp, ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2 From fb964b514c162539bd6a9f56d19e0ca7ca6a4c26 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 31 Jul 2024 08:14:26 -0700 Subject: [PATCH 070/132] Do not set patch control points dynamic state if there is no tessalation control shader. Thank you riperiperi --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 +- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index d001c46e6..b1dce459e 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -994,7 +994,7 @@ namespace Ryujinx.Graphics.Vulkan public void SetPatchParameters(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel) { - if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints && _newState.HasTessellationControlShader) { DynamicState.SetPatchControlPoints((uint)vertices); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index ddbe50f8a..1c83cc16d 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -432,7 +432,7 @@ namespace Ryujinx.Graphics.Vulkan SType = StructureType.PipelineTessellationStateCreateInfo, }; - if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2) { tessellationState.PatchControlPoints = PatchControlPoints; } @@ -587,7 +587,7 @@ namespace Ryujinx.Graphics.Vulkan { additionalDynamicStatesCount++; } - if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints && HasTessellationControlShader) { additionalDynamicStatesCount++; } @@ -642,7 +642,7 @@ namespace Ryujinx.Graphics.Vulkan { dynamicStates[currentIndex++] = DynamicState.LogicOpExt; } - if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints && HasTessellationControlShader) { dynamicStates[currentIndex++] = DynamicState.PatchControlPointsExt; } From 693f268090ac1abffc454e61f68a814299eb13a5 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 31 Jul 2024 08:18:58 -0700 Subject: [PATCH 071/132] Accidental change --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 1c83cc16d..a281631d2 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -432,7 +432,7 @@ namespace Ryujinx.Graphics.Vulkan SType = StructureType.PipelineTessellationStateCreateInfo, }; - if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2) + if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) { tessellationState.PatchControlPoints = PatchControlPoints; } From da11dc1288f7bc08dd72e4d3b99c5b649e9ed671 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 31 Jul 2024 17:12:57 -0700 Subject: [PATCH 072/132] Only pass Tesselation state create info if dynamic state is not supported --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index a281631d2..f91ce407f 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -427,13 +427,11 @@ namespace Ryujinx.Graphics.Vulkan Topology = supportsExtDynamicState ? TopologyClass : Topology, }; - var tessellationState = new PipelineTessellationStateCreateInfo - { - SType = StructureType.PipelineTessellationStateCreateInfo, - }; + PipelineTessellationStateCreateInfo tessellationState; if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) { + tessellationState.SType = StructureType.PipelineTessellationStateCreateInfo; tessellationState.PatchControlPoints = PatchControlPoints; } @@ -663,7 +661,6 @@ namespace Ryujinx.Graphics.Vulkan PStages = Stages.Pointer, PVertexInputState = &vertexInputState, PInputAssemblyState = &inputAssemblyState, - PTessellationState = &tessellationState, PViewportState = &viewportState, PRasterizationState = &rasterizationState, PMultisampleState = &multisampleState, @@ -674,6 +671,11 @@ namespace Ryujinx.Graphics.Vulkan RenderPass = renderPass, }; + if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + { + pipelineCreateInfo.PTessellationState = &tessellationState; + } + Result result = gd.Api.CreateGraphicsPipelines(device, cache, 1, &pipelineCreateInfo, null, &pipelineHandle); if (throwOnError) From 3f7a3ac55854ec8eb0044ac963f0c3a5486135c1 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 31 Jul 2024 18:18:46 -0700 Subject: [PATCH 073/132] Adapt changes from #7102 for dynamic states --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 ++ src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index b1dce459e..d2c65fdb5 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1063,6 +1063,8 @@ namespace Ryujinx.Graphics.Vulkan public void SetPrimitiveTopology(PrimitiveTopology topology) { + topology = _newState.HasTessellationControlShader ? PrimitiveTopology.Patches : topology; + _topology = topology; var vkTopology = Gd.TopologyRemap(topology).Convert(); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 16adcae09..f91ce407f 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -424,7 +424,7 @@ namespace Ryujinx.Graphics.Vulkan var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, - Topology = supportsExtDynamicState ? TopologyClass : HasTessellationControlShader ? PrimitiveTopology.PatchList : Topology, + Topology = supportsExtDynamicState ? TopologyClass : Topology, }; PipelineTessellationStateCreateInfo tessellationState; From 38c9ec925c1421fb2cb0030ede3b06ecb36c2209 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 31 Jul 2024 18:22:29 -0700 Subject: [PATCH 074/132] Whitespace fix --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index d2c65fdb5..9e3cf76bd 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1064,7 +1064,7 @@ namespace Ryujinx.Graphics.Vulkan public void SetPrimitiveTopology(PrimitiveTopology topology) { topology = _newState.HasTessellationControlShader ? PrimitiveTopology.Patches : topology; - + _topology = topology; var vkTopology = Gd.TopologyRemap(topology).Convert(); From 1bcc9c029a218f0eb627e8c80eb9dafaabcf4cdb Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 31 Jul 2024 18:51:44 -0700 Subject: [PATCH 075/132] Remove redundant logic, just use max possible dynamic states --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 32 ++------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index f91ce407f..261decea8 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -565,34 +565,7 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.PNext = &colorBlendAdvancedState; } - int baseDynamicStatesCount = 7; - int additionalDynamicStatesCount = 0; - - if (!isMoltenVk) - { - baseDynamicStatesCount++; - } - - if (supportsExtDynamicState) - { - additionalDynamicStatesCount += isMoltenVk ? 8 : 9; - } - - if (supportsExtDynamicState2) - { - additionalDynamicStatesCount += 3; - if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) - { - additionalDynamicStatesCount++; - } - if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints && HasTessellationControlShader) - { - additionalDynamicStatesCount++; - } - } - - int dynamicStatesCount = baseDynamicStatesCount + additionalDynamicStatesCount; - DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount]; + DynamicState* dynamicStates = stackalloc DynamicState[22]; dynamicStates[0] = DynamicState.Viewport; dynamicStates[1] = DynamicState.Scissor; @@ -649,11 +622,10 @@ namespace Ryujinx.Graphics.Vulkan var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo { SType = StructureType.PipelineDynamicStateCreateInfo, - DynamicStateCount = (uint)dynamicStatesCount, + DynamicStateCount = (uint)currentIndex, PDynamicStates = dynamicStates, }; - var pipelineCreateInfo = new GraphicsPipelineCreateInfo { SType = StructureType.GraphicsPipelineCreateInfo, From adc7528b54e05374117233bb86ff5f16dc2e6ea1 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 31 Jul 2024 18:56:06 -0700 Subject: [PATCH 076/132] Why cast when you don't need to cast --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 261decea8..86939b0be 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -575,7 +575,7 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[5] = DynamicState.BlendConstants; dynamicStates[6] = DynamicState.DepthBias; - int currentIndex = 7; + uint currentIndex = 7; if (!isMoltenVk) { @@ -622,7 +622,7 @@ namespace Ryujinx.Graphics.Vulkan var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo { SType = StructureType.PipelineDynamicStateCreateInfo, - DynamicStateCount = (uint)currentIndex, + DynamicStateCount = currentIndex, PDynamicStates = dynamicStates, }; From 9b02fd6dc06b34e83305dae9feb7870acaa4eb6a Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Thu, 1 Aug 2024 08:19:11 -0700 Subject: [PATCH 077/132] Conver to TopologyClass from Vulkan Topology --- src/Ryujinx.Graphics.Vulkan/EnumConversion.cs | 29 +++++++++---------- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 7 ++--- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs b/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs index d58603cd6..7e5207d39 100644 --- a/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs +++ b/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs @@ -310,25 +310,22 @@ namespace Ryujinx.Graphics.Vulkan }; } - public static PrimitiveTopology ConvertToClass(this GAL.PrimitiveTopology topology) + public static PrimitiveTopology ConvertToClass(this PrimitiveTopology topology) { return topology switch { - GAL.PrimitiveTopology.Points => PrimitiveTopology.PointList, - GAL.PrimitiveTopology.Lines or - GAL.PrimitiveTopology.LineStrip or - GAL.PrimitiveTopology.LinesAdjacency or - GAL.PrimitiveTopology.LineStripAdjacency => PrimitiveTopology.LineList, - GAL.PrimitiveTopology.Triangles or - GAL.PrimitiveTopology.TriangleStrip or - GAL.PrimitiveTopology.TriangleFan or - GAL.PrimitiveTopology.TrianglesAdjacency or - GAL.PrimitiveTopology.TriangleStripAdjacency or - GAL.PrimitiveTopology.Polygon => PrimitiveTopology.TriangleList, - GAL.PrimitiveTopology.Patches => PrimitiveTopology.PatchList, - GAL.PrimitiveTopology.Quads => throw new NotSupportedException("Quad topology is not available in Vulkan."), - GAL.PrimitiveTopology.QuadStrip => throw new NotSupportedException("QuadStrip topology is not available in Vulkan."), - _ => LogInvalidAndReturn(topology, nameof(GAL.PrimitiveTopology), PrimitiveTopology.TriangleList), + PrimitiveTopology.PointList => PrimitiveTopology.PointList, + PrimitiveTopology.LineList or + PrimitiveTopology.LineStrip or + PrimitiveTopology.LineListWithAdjacency or + PrimitiveTopology.LineStripWithAdjacency => PrimitiveTopology.LineList, + PrimitiveTopology.TriangleList or + PrimitiveTopology.TriangleStrip or + PrimitiveTopology.TriangleFan or + PrimitiveTopology.TriangleListWithAdjacency or + PrimitiveTopology.TriangleStripWithAdjacency => PrimitiveTopology.TriangleList, + PrimitiveTopology.PatchList => PrimitiveTopology.PatchList, + _ => LogInvalidAndReturn(topology, nameof(PrimitiveTopology), PrimitiveTopology.TriangleList), }; } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 9e3cf76bd..257a22fd9 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -640,7 +640,6 @@ namespace Ryujinx.Graphics.Vulkan var oldDepthTestEnable = _supportExtDynamic ? DynamicState.DepthTestEnable : _newState.DepthTestEnable; var oldDepthWriteEnable = _supportExtDynamic ? DynamicState.DepthWriteEnable : _newState.DepthWriteEnable; var oldTopology = _newState.Topology; - var oldTopologyClass = _newState.TopologyClass; var oldViewports = DynamicState.Viewports; var oldViewportsCount = _supportExtDynamic ? DynamicState.ViewportsCount : _newState.ViewportsCount; @@ -670,9 +669,9 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { - if (oldTopologyClass != Silk.NET.Vulkan.PrimitiveTopology.TriangleList) + if (oldTopology.ConvertToClass() != _newState.TopologyClass.ConvertToClass()) { - _newState.TopologyClass = oldTopology; + _newState.TopologyClass = _newState.TopologyClass.ConvertToClass(); } DynamicState.SetCullMode(oldCullMode); @@ -1071,7 +1070,7 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { - var newTopologyClass = Gd.TopologyRemap(topology).ConvertToClass(); + var newTopologyClass = vkTopology.ConvertToClass(); if ((_newState.TopologyClass != newTopologyClass)) { From fa801ba4725a3cda0117e21d18928d3a410c1ea3 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Thu, 1 Aug 2024 19:17:59 -0700 Subject: [PATCH 078/132] Match other code in project --- .../HardwareCapabilities.cs | 4 ++-- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 6 +++--- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 12 +++++------ .../VulkanInitialization.cs | 8 ++------ src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 20 ++++++++++++------- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs index 952867642..c7df9bafc 100644 --- a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs +++ b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs @@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.Vulkan public readonly bool SupportsShaderStorageImageMultisample; public readonly bool SupportsConditionalRendering; public readonly bool SupportsExtendedDynamicState; - public readonly bool SupportsExtendedDynamicState2; + public readonly PhysicalDeviceExtendedDynamicState2FeaturesEXT SupportsExtendedDynamicState2; public readonly bool SupportsMultiView; public readonly bool SupportsNullDescriptors; public readonly bool SupportsPushDescriptors; @@ -71,7 +71,7 @@ namespace Ryujinx.Graphics.Vulkan bool supportsShaderStorageImageMultisample, bool supportsConditionalRendering, bool supportsExtendedDynamicState, - bool supportsExtendedDynamicState2, + PhysicalDeviceExtendedDynamicState2FeaturesEXT supportsExtendedDynamicState2, bool supportsMultiView, bool supportsNullDescriptors, bool supportsPushDescriptors, diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 257a22fd9..3ccd82a10 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -127,7 +127,7 @@ namespace Ryujinx.Graphics.Vulkan _supportExtDynamic = gd.Capabilities.SupportsExtendedDynamicState; - _supportExtDynamic2 = gd.Capabilities.SupportsExtendedDynamicState2; + _supportExtDynamic2 = gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2; _newState.Initialize(); } @@ -970,7 +970,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.LogicOpEnable = logicOpEnable; - if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) + if (Gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) { DynamicState.SetLogicOp(logicOpEnable ? op.Convert() : default); } @@ -993,7 +993,7 @@ namespace Ryujinx.Graphics.Vulkan public void SetPatchParameters(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel) { - if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints && _newState.HasTessellationControlShader) + if (Gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints && _newState.HasTessellationControlShader) { DynamicState.SetPatchControlPoints((uint)vertices); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 86939b0be..66ce0fa1a 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -405,7 +405,7 @@ namespace Ryujinx.Graphics.Vulkan } bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState; - bool supportsExtDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2; + bool supportsExtDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2; fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0]) fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions2 = &_vertexAttributeDescriptions2[0]) @@ -429,7 +429,7 @@ namespace Ryujinx.Graphics.Vulkan PipelineTessellationStateCreateInfo tessellationState; - if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { tessellationState.SType = StructureType.PipelineTessellationStateCreateInfo; tessellationState.PatchControlPoints = PatchControlPoints; @@ -545,7 +545,7 @@ namespace Ryujinx.Graphics.Vulkan LogicOpEnable = LogicOpEnable, }; - if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) { colorBlendState.LogicOp = LogicOp; } @@ -609,11 +609,11 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[currentIndex++] = DynamicState.RasterizerDiscardEnableExt; dynamicStates[currentIndex++] = DynamicState.PrimitiveRestartEnableExt; - if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) + if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) { dynamicStates[currentIndex++] = DynamicState.LogicOpExt; } - if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints && HasTessellationControlShader) + if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints && HasTessellationControlShader) { dynamicStates[currentIndex++] = DynamicState.PatchControlPointsExt; } @@ -643,7 +643,7 @@ namespace Ryujinx.Graphics.Vulkan RenderPass = renderPass, }; - if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { pipelineCreateInfo.PTessellationState = &tessellationState; } diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index 3107dcf30..72aeae3c8 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -265,7 +265,7 @@ namespace Ryujinx.Graphics.Vulkan return InvalidIndex; } - internal static Device CreateDevice(Vk api, VulkanPhysicalDevice physicalDevice, uint queueFamilyIndex, uint queueCount, out PhysicalDeviceExtendedDynamicState2FeaturesEXT extendedDynamicState2Features) + internal static Device CreateDevice(Vk api, VulkanPhysicalDevice physicalDevice, uint queueFamilyIndex, uint queueCount) { if (queueCount > QueuesCount) { @@ -472,16 +472,12 @@ namespace Ryujinx.Graphics.Vulkan supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2, ExtendedDynamicState2LogicOp = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp, - ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2 - .ExtendedDynamicState2PatchControlPoints, + ExtendedDynamicState2PatchControlPoints = false, }; pExtendedFeatures = &featuresExtendedDynamicState2; } - extendedDynamicState2Features = supportedFeaturesExtExtendedDynamicState2; - - var featuresVk11 = new PhysicalDeviceVulkan11Features { SType = StructureType.PhysicalDeviceVulkan11Features, diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index b8f50e6a1..bb6216be7 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -100,9 +100,6 @@ namespace Ryujinx.Graphics.Vulkan public bool PreferThreading => true; - public PhysicalDeviceExtendedDynamicState2FeaturesEXT ExtendedDynamicState2Features; - - public event EventHandler ScreenCaptured; public VulkanRenderer(Vk api, Func surfaceFunc, Func requiredExtensionsFunc, string preferredGpuId) @@ -232,6 +229,11 @@ namespace Ryujinx.Graphics.Vulkan SType = StructureType.PhysicalDevicePrimitiveTopologyListRestartFeaturesExt, }; + PhysicalDeviceExtendedDynamicState2FeaturesEXT featuresExtendedDynamicState2 = new() + { + SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, + }; + PhysicalDeviceRobustness2FeaturesEXT featuresRobustness2 = new() { SType = StructureType.PhysicalDeviceRobustness2FeaturesExt, @@ -262,6 +264,12 @@ namespace Ryujinx.Graphics.Vulkan features2.PNext = &featuresPrimitiveTopologyListRestart; } + if (_physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName)) + { + featuresExtendedDynamicState2.PNext = features2.PNext; + features2.PNext = &featuresExtendedDynamicState2; + } + if (_physicalDevice.IsDeviceExtensionPresent("VK_EXT_robustness2")) { featuresRobustness2.PNext = features2.PNext; @@ -395,7 +403,7 @@ namespace Ryujinx.Graphics.Vulkan features2.Features.ShaderStorageImageMultisample, _physicalDevice.IsDeviceExtensionPresent(ExtConditionalRendering.ExtensionName), _physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState.ExtensionName), - _physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName), + featuresExtendedDynamicState2, features2.Features.MultiViewport && !(IsMoltenVk && Vendor == Vendor.Amd), // Workaround for AMD on MoltenVK issue featuresRobustness2.NullDescriptor || IsMoltenVk, supportsPushDescriptors && !IsMoltenVk, @@ -460,9 +468,7 @@ namespace Ryujinx.Graphics.Vulkan var queueFamilyIndex = VulkanInitialization.FindSuitableQueueFamily(Api, _physicalDevice, _surface, out uint maxQueueCount); - _device = VulkanInitialization.CreateDevice(Api, _physicalDevice, queueFamilyIndex, maxQueueCount, out PhysicalDeviceExtendedDynamicState2FeaturesEXT extendedDynamicState2Features); - - ExtendedDynamicState2Features = extendedDynamicState2Features; + _device = VulkanInitialization.CreateDevice(Api, _physicalDevice, queueFamilyIndex, maxQueueCount); if (Api.TryGetDeviceExtension(_instance.Instance, _device, out KhrSwapchain swapchainApi)) { From 023f3ed44f01a80cea6c243b6b01876efacb7d5c Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Thu, 1 Aug 2024 19:21:32 -0700 Subject: [PATCH 079/132] Resolve build errors --- src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs | 6 +++--- src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs | 6 +++--- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index c1a7d52d7..3e330ee7f 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -169,19 +169,19 @@ namespace Ryujinx.Graphics.Vulkan pipeline.PolygonMode = PolygonMode.Fill; // Not implemented. - if (!gd.Capabilities.SupportsExtendedDynamicState2) + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2) { pipeline.PrimitiveRestartEnable = state.PrimitiveRestartEnable; pipeline.RasterizerDiscardEnable = state.RasterizerDiscard; pipeline.DepthBiasEnable = state.BiasEnable != 0; } - if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) { pipeline.LogicOp = state.LogicOpEnable ? state.LogicOp.Convert() : default; } - if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { pipeline.PatchControlPoints = state.PatchControlPoints; } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 2c473ab79..dbcd3814d 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -242,7 +242,7 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.Extended; } - if (gd.Capabilities.SupportsExtendedDynamicState2) + if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2) { _dirty |= DirtyFlags.Extended2; } @@ -252,12 +252,12 @@ namespace Ryujinx.Graphics.Vulkan _dirty &= ~DirtyFlags.LineWidth; } - if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp) + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) { _dirty &= ~DirtyFlags.LogicOp; } - if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints) + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { _dirty &= ~DirtyFlags.PatchControlPoints; } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 66ce0fa1a..cd306525c 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -429,7 +429,7 @@ namespace Ryujinx.Graphics.Vulkan PipelineTessellationStateCreateInfo tessellationState; - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints && HasTessellationControlShader) { tessellationState.SType = StructureType.PipelineTessellationStateCreateInfo; tessellationState.PatchControlPoints = PatchControlPoints; @@ -643,7 +643,7 @@ namespace Ryujinx.Graphics.Vulkan RenderPass = renderPass, }; - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints && HasTessellationControlShader) { pipelineCreateInfo.PTessellationState = &tessellationState; } From ce450dc08eda23a5419fb7ac157326ca1d0246e3 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Fri, 2 Aug 2024 07:27:44 -0700 Subject: [PATCH 080/132] Invert logic to only set flags dirty if those are supported. --- .../PipelineDynamicState.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index dbcd3814d..623c47fac 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -80,7 +80,7 @@ namespace Ryujinx.Graphics.Vulkan DepthBiasEnable = 1 << 16, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnableandStencilOp | PrimitiveTopology, - Extended2 = RasterDiscard | LogicOp | PatchControlPoints | PrimitiveRestart | DepthBiasEnable, + Extended2 = RasterDiscard | PrimitiveRestart | DepthBiasEnable, } private DirtyFlags _dirty; @@ -247,19 +247,19 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.Extended2; } - if (gd.IsMoltenVk) + if (!gd.IsMoltenVk) { - _dirty &= ~DirtyFlags.LineWidth; + _dirty |= DirtyFlags.LineWidth; } - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) + if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) { - _dirty &= ~DirtyFlags.LogicOp; + _dirty |= DirtyFlags.LogicOp; } - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) + if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { - _dirty &= ~DirtyFlags.PatchControlPoints; + _dirty |= DirtyFlags.PatchControlPoints; } } From 59ef2ac79919eee53cde092ec6afaf5c6c6fe13f Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Fri, 2 Aug 2024 18:17:28 -0700 Subject: [PATCH 081/132] Accidental change --- src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index 72aeae3c8..f1d86dcf7 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -472,7 +472,7 @@ namespace Ryujinx.Graphics.Vulkan supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2, ExtendedDynamicState2LogicOp = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp, - ExtendedDynamicState2PatchControlPoints = false, + ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints, }; pExtendedFeatures = &featuresExtendedDynamicState2; From 3b398adbe6a4b224ebfd7adeb51f0aaf812c5048 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 3 Aug 2024 19:19:54 -0700 Subject: [PATCH 082/132] Refactor PipelineUid and pack TopologyClass Remove basepipelineindex as its extraneous --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 434 ++++++++----------- src/Ryujinx.Graphics.Vulkan/PipelineUid.cs | 27 +- 2 files changed, 195 insertions(+), 266 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index cd306525c..1dfca2bff 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -11,294 +11,238 @@ namespace Ryujinx.Graphics.Vulkan public PipelineUid Internal; - public float LineWidth + public PolygonMode PolygonMode { - readonly get => BitConverter.Int32BitsToSingle((int)((Internal.Id0 >> 0) & 0xFFFFFFFF)); - set => Internal.Id0 = (Internal.Id0 & 0xFFFFFFFF00000000) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 0); + readonly get => (PolygonMode)((Internal.Id0 >> 0) & 0x3FFFFFFF); + set => Internal.Id0 = (Internal.Id0 & 0xFFFFFFFFC0000000) | ((ulong)value << 0); } - public float DepthBiasClamp + public uint StagesCount { - readonly get => BitConverter.Int32BitsToSingle((int)((Internal.Id0 >> 32) & 0xFFFFFFFF)); - set => Internal.Id0 = (Internal.Id0 & 0xFFFFFFFF) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 32); + readonly get => (byte)((Internal.Id0 >> 30) & 0xFF); + set => Internal.Id0 = (Internal.Id0 & 0xFFFFFFC03FFFFFFF) | ((ulong)value << 30); } - public float DepthBiasConstantFactor + public uint VertexAttributeDescriptionsCount { - readonly get => BitConverter.Int32BitsToSingle((int)((Internal.Id1 >> 0) & 0xFFFFFFFF)); - set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFF00000000) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 0); + readonly get => (byte)((Internal.Id0 >> 38) & 0xFF); + set => Internal.Id0 = (Internal.Id0 & 0xFFFFC03FFFFFFFFF) | ((ulong)value << 38); } - public float DepthBiasSlopeFactor + public uint VertexBindingDescriptionsCount { - readonly get => BitConverter.Int32BitsToSingle((int)((Internal.Id1 >> 32) & 0xFFFFFFFF)); - set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFF) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 32); + readonly get => (byte)((Internal.Id0 >> 46) & 0xFF); + set => Internal.Id0 = (Internal.Id0 & 0xFFC03FFFFFFFFFFF) | ((ulong)value << 46); } - public uint StencilFrontCompareMask + public uint ViewportsCount + { + readonly get => (byte)((Internal.Id0 >> 54) & 0xFF); + set => Internal.Id0 = (Internal.Id0 & 0xC03FFFFFFFFFFFFF) | ((ulong)value << 54); + } + + public uint ScissorsCount + { + readonly get => (byte)((Internal.Id1 >> 0) & 0xFF); + set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFFFFFFFF00) | ((ulong)value << 0); + } + + public uint ColorBlendAttachmentStateCount + { + readonly get => (byte)((Internal.Id1 >> 8) & 0xFF); + set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFFFFFF00FF) | ((ulong)value << 8); + } + + public PrimitiveTopology Topology + { + readonly get => (PrimitiveTopology)((Internal.Id1 >> 16) & 0xF); + set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFFFFF0FFFF) | ((ulong)value << 16); + } + + public LogicOp LogicOp + { + readonly get => (LogicOp)((Internal.Id1 >> 20) & 0xF); + set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFFFF0FFFFF) | ((ulong)value << 20); + } + + public CompareOp DepthCompareOp + { + readonly get => (CompareOp)((Internal.Id1 >> 24) & 0x7); + set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFFF8FFFFFF) | ((ulong)value << 24); + } + + public StencilOp StencilFrontFailOp + { + readonly get => (StencilOp)((Internal.Id1 >> 27) & 0x7); + set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFFC7FFFFFF) | ((ulong)value << 27); + } + + public StencilOp StencilFrontPassOp + { + readonly get => (StencilOp)((Internal.Id1 >> 30) & 0x7); + set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFE3FFFFFFF) | ((ulong)value << 30); + } + + public StencilOp StencilFrontDepthFailOp + { + readonly get => (StencilOp)((Internal.Id1 >> 33) & 0x7); + set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFF1FFFFFFFF) | ((ulong)value << 33); + } + + public CompareOp StencilFrontCompareOp + { + readonly get => (CompareOp)((Internal.Id1 >> 36) & 0x7); + set => Internal.Id1 = (Internal.Id1 & 0xFFFFFF8FFFFFFFFF) | ((ulong)value << 36); + } + + public StencilOp StencilBackFailOp + { + readonly get => (StencilOp)((Internal.Id1 >> 39) & 0x7); + set => Internal.Id1 = (Internal.Id1 & 0xFFFFFC7FFFFFFFFF) | ((ulong)value << 39); + } + + public StencilOp StencilBackPassOp + { + readonly get => (StencilOp)((Internal.Id1 >> 42) & 0x7); + set => Internal.Id1 = (Internal.Id1 & 0xFFFFE3FFFFFFFFFF) | ((ulong)value << 42); + } + + public StencilOp StencilBackDepthFailOp + { + readonly get => (StencilOp)((Internal.Id1 >> 45) & 0x7); + set => Internal.Id1 = (Internal.Id1 & 0xFFFF1FFFFFFFFFFF) | ((ulong)value << 45); + } + + public CompareOp StencilBackCompareOp + { + readonly get => (CompareOp)((Internal.Id1 >> 48) & 0x7); + set => Internal.Id1 = (Internal.Id1 & 0xFFF8FFFFFFFFFFFF) | ((ulong)value << 48); + } + + public CullModeFlags CullMode + { + readonly get => (CullModeFlags)((Internal.Id1 >> 51) & 0x3); + set => Internal.Id1 = (Internal.Id1 & 0xFFE7FFFFFFFFFFFF) | ((ulong)value << 51); + } + + public bool PrimitiveRestartEnable + { + readonly get => ((Internal.Id1 >> 53) & 0x1) != 0UL; + set => Internal.Id1 = (Internal.Id1 & 0xFFDFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 53); + } + + public bool DepthClampEnable + { + readonly get => ((Internal.Id1 >> 54) & 0x1) != 0UL; + set => Internal.Id1 = (Internal.Id1 & 0xFFBFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 54); + } + + public bool RasterizerDiscardEnable + { + readonly get => ((Internal.Id1 >> 55) & 0x1) != 0UL; + set => Internal.Id1 = (Internal.Id1 & 0xFF7FFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 55); + } + + public FrontFace FrontFace + { + readonly get => (FrontFace)((Internal.Id1 >> 56) & 0x1); + set => Internal.Id1 = (Internal.Id1 & 0xFEFFFFFFFFFFFFFF) | ((ulong)value << 56); + } + + public bool DepthBiasEnable + { + readonly get => ((Internal.Id1 >> 57) & 0x1) != 0UL; + set => Internal.Id1 = (Internal.Id1 & 0xFDFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 57); + } + + public bool DepthTestEnable + { + readonly get => ((Internal.Id1 >> 58) & 0x1) != 0UL; + set => Internal.Id1 = (Internal.Id1 & 0xFBFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 58); + } + + public bool DepthWriteEnable + { + readonly get => ((Internal.Id1 >> 59) & 0x1) != 0UL; + set => Internal.Id1 = (Internal.Id1 & 0xF7FFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 59); + } + + public bool DepthBoundsTestEnable + { + readonly get => ((Internal.Id1 >> 60) & 0x1) != 0UL; + set => Internal.Id1 = (Internal.Id1 & 0xEFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 60); + } + + public bool StencilTestEnable + { + readonly get => ((Internal.Id1 >> 61) & 0x1) != 0UL; + set => Internal.Id1 = (Internal.Id1 & 0xDFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 61); + } + + public bool LogicOpEnable + { + readonly get => ((Internal.Id1 >> 62) & 0x1) != 0UL; + set => Internal.Id1 = (Internal.Id1 & 0xBFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 62); + } + + public bool HasDepthStencil + { + readonly get => ((Internal.Id1 >> 63) & 0x1) != 0UL; + set => Internal.Id1 = (Internal.Id1 & 0x7FFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 63); + } + + public uint PatchControlPoints { readonly get => (uint)((Internal.Id2 >> 0) & 0xFFFFFFFF); set => Internal.Id2 = (Internal.Id2 & 0xFFFFFFFF00000000) | ((ulong)value << 0); } - public uint StencilFrontWriteMask + public uint SamplesCount { readonly get => (uint)((Internal.Id2 >> 32) & 0xFFFFFFFF); set => Internal.Id2 = (Internal.Id2 & 0xFFFFFFFF) | ((ulong)value << 32); } - public uint StencilFrontReference - { - readonly get => (uint)((Internal.Id3 >> 0) & 0xFFFFFFFF); - set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFF00000000) | ((ulong)value << 0); - } - - public uint StencilBackCompareMask - { - readonly get => (uint)((Internal.Id3 >> 32) & 0xFFFFFFFF); - set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFF) | ((ulong)value << 32); - } - - public uint StencilBackWriteMask - { - readonly get => (uint)((Internal.Id4 >> 0) & 0xFFFFFFFF); - set => Internal.Id4 = (Internal.Id4 & 0xFFFFFFFF00000000) | ((ulong)value << 0); - } - - public uint StencilBackReference - { - readonly get => (uint)((Internal.Id4 >> 32) & 0xFFFFFFFF); - set => Internal.Id4 = (Internal.Id4 & 0xFFFFFFFF) | ((ulong)value << 32); - } - - public PolygonMode PolygonMode - { - readonly get => (PolygonMode)((Internal.Id5 >> 0) & 0x3FFFFFFF); - set => Internal.Id5 = (Internal.Id5 & 0xFFFFFFFFC0000000) | ((ulong)value << 0); - } - - public uint StagesCount - { - readonly get => (byte)((Internal.Id5 >> 30) & 0xFF); - set => Internal.Id5 = (Internal.Id5 & 0xFFFFFFC03FFFFFFF) | ((ulong)value << 30); - } - - public uint VertexAttributeDescriptionsCount - { - readonly get => (byte)((Internal.Id5 >> 38) & 0xFF); - set => Internal.Id5 = (Internal.Id5 & 0xFFFFC03FFFFFFFFF) | ((ulong)value << 38); - } - - public uint VertexBindingDescriptionsCount - { - readonly get => (byte)((Internal.Id5 >> 46) & 0xFF); - set => Internal.Id5 = (Internal.Id5 & 0xFFC03FFFFFFFFFFF) | ((ulong)value << 46); - } - - public uint ViewportsCount - { - readonly get => (byte)((Internal.Id5 >> 54) & 0xFF); - set => Internal.Id5 = (Internal.Id5 & 0xC03FFFFFFFFFFFFF) | ((ulong)value << 54); - } - - public uint ScissorsCount - { - readonly get => (byte)((Internal.Id6 >> 0) & 0xFF); - set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFFFFFF00) | ((ulong)value << 0); - } - - public uint ColorBlendAttachmentStateCount - { - readonly get => (byte)((Internal.Id6 >> 8) & 0xFF); - set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFFFF00FF) | ((ulong)value << 8); - } - - public PrimitiveTopology Topology - { - readonly get => (PrimitiveTopology)((Internal.Id6 >> 16) & 0xF); - set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFFF0FFFF) | ((ulong)value << 16); - } - - public PrimitiveTopology TopologyClass; - - public LogicOp LogicOp - { - readonly get => (LogicOp)((Internal.Id6 >> 20) & 0xF); - set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFF0FFFFF) | ((ulong)value << 20); - } - - public CompareOp DepthCompareOp - { - readonly get => (CompareOp)((Internal.Id6 >> 24) & 0x7); - set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFF8FFFFFF) | ((ulong)value << 24); - } - - public StencilOp StencilFrontFailOp - { - readonly get => (StencilOp)((Internal.Id6 >> 27) & 0x7); - set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFC7FFFFFF) | ((ulong)value << 27); - } - - public StencilOp StencilFrontPassOp - { - readonly get => (StencilOp)((Internal.Id6 >> 30) & 0x7); - set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFE3FFFFFFF) | ((ulong)value << 30); - } - - public StencilOp StencilFrontDepthFailOp - { - readonly get => (StencilOp)((Internal.Id6 >> 33) & 0x7); - set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFF1FFFFFFFF) | ((ulong)value << 33); - } - - public CompareOp StencilFrontCompareOp - { - readonly get => (CompareOp)((Internal.Id6 >> 36) & 0x7); - set => Internal.Id6 = (Internal.Id6 & 0xFFFFFF8FFFFFFFFF) | ((ulong)value << 36); - } - - public StencilOp StencilBackFailOp - { - readonly get => (StencilOp)((Internal.Id6 >> 39) & 0x7); - set => Internal.Id6 = (Internal.Id6 & 0xFFFFFC7FFFFFFFFF) | ((ulong)value << 39); - } - - public StencilOp StencilBackPassOp - { - readonly get => (StencilOp)((Internal.Id6 >> 42) & 0x7); - set => Internal.Id6 = (Internal.Id6 & 0xFFFFE3FFFFFFFFFF) | ((ulong)value << 42); - } - - public StencilOp StencilBackDepthFailOp - { - readonly get => (StencilOp)((Internal.Id6 >> 45) & 0x7); - set => Internal.Id6 = (Internal.Id6 & 0xFFFF1FFFFFFFFFFF) | ((ulong)value << 45); - } - - public CompareOp StencilBackCompareOp - { - readonly get => (CompareOp)((Internal.Id6 >> 48) & 0x7); - set => Internal.Id6 = (Internal.Id6 & 0xFFF8FFFFFFFFFFFF) | ((ulong)value << 48); - } - - public CullModeFlags CullMode - { - readonly get => (CullModeFlags)((Internal.Id6 >> 51) & 0x3); - set => Internal.Id6 = (Internal.Id6 & 0xFFE7FFFFFFFFFFFF) | ((ulong)value << 51); - } - - public bool PrimitiveRestartEnable - { - readonly get => ((Internal.Id6 >> 53) & 0x1) != 0UL; - set => Internal.Id6 = (Internal.Id6 & 0xFFDFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 53); - } - - public bool DepthClampEnable - { - readonly get => ((Internal.Id6 >> 54) & 0x1) != 0UL; - set => Internal.Id6 = (Internal.Id6 & 0xFFBFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 54); - } - - public bool RasterizerDiscardEnable - { - readonly get => ((Internal.Id6 >> 55) & 0x1) != 0UL; - set => Internal.Id6 = (Internal.Id6 & 0xFF7FFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 55); - } - - public FrontFace FrontFace - { - readonly get => (FrontFace)((Internal.Id6 >> 56) & 0x1); - set => Internal.Id6 = (Internal.Id6 & 0xFEFFFFFFFFFFFFFF) | ((ulong)value << 56); - } - - public bool DepthBiasEnable - { - readonly get => ((Internal.Id6 >> 57) & 0x1) != 0UL; - set => Internal.Id6 = (Internal.Id6 & 0xFDFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 57); - } - - public bool DepthTestEnable - { - readonly get => ((Internal.Id6 >> 58) & 0x1) != 0UL; - set => Internal.Id6 = (Internal.Id6 & 0xFBFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 58); - } - - public bool DepthWriteEnable - { - readonly get => ((Internal.Id6 >> 59) & 0x1) != 0UL; - set => Internal.Id6 = (Internal.Id6 & 0xF7FFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 59); - } - - public bool DepthBoundsTestEnable - { - readonly get => ((Internal.Id6 >> 60) & 0x1) != 0UL; - set => Internal.Id6 = (Internal.Id6 & 0xEFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 60); - } - - public bool StencilTestEnable - { - readonly get => ((Internal.Id6 >> 61) & 0x1) != 0UL; - set => Internal.Id6 = (Internal.Id6 & 0xDFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 61); - } - - public bool LogicOpEnable - { - readonly get => ((Internal.Id6 >> 62) & 0x1) != 0UL; - set => Internal.Id6 = (Internal.Id6 & 0xBFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 62); - } - - public bool HasDepthStencil - { - readonly get => ((Internal.Id6 >> 63) & 0x1) != 0UL; - set => Internal.Id6 = (Internal.Id6 & 0x7FFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 63); - } - - public uint PatchControlPoints - { - readonly get => (uint)((Internal.Id7 >> 0) & 0xFFFFFFFF); - set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFF00000000) | ((ulong)value << 0); - } - - public uint SamplesCount - { - readonly get => (uint)((Internal.Id7 >> 32) & 0xFFFFFFFF); - set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFF) | ((ulong)value << 32); - } - public bool AlphaToCoverageEnable { - readonly get => ((Internal.Id8 >> 0) & 0x1) != 0UL; - set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFFE) | ((value ? 1UL : 0UL) << 0); + readonly get => ((Internal.Id3 >> 0) & 0x1) != 0UL; + set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFFFE) | ((value ? 1UL : 0UL) << 0); } public bool AlphaToOneEnable { - readonly get => ((Internal.Id8 >> 1) & 0x1) != 0UL; - set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFFD) | ((value ? 1UL : 0UL) << 1); + readonly get => ((Internal.Id3 >> 1) & 0x1) != 0UL; + set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFFFD) | ((value ? 1UL : 0UL) << 1); } public bool AdvancedBlendSrcPreMultiplied { - readonly get => ((Internal.Id8 >> 2) & 0x1) != 0UL; - set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFFB) | ((value ? 1UL : 0UL) << 2); + readonly get => ((Internal.Id3 >> 2) & 0x1) != 0UL; + set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFFFB) | ((value ? 1UL : 0UL) << 2); } public bool AdvancedBlendDstPreMultiplied { - readonly get => ((Internal.Id8 >> 3) & 0x1) != 0UL; - set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFF7) | ((value ? 1UL : 0UL) << 3); + readonly get => ((Internal.Id3 >> 3) & 0x1) != 0UL; + set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFFF7) | ((value ? 1UL : 0UL) << 3); } public BlendOverlapEXT AdvancedBlendOverlap { - readonly get => (BlendOverlapEXT)((Internal.Id8 >> 4) & 0x3); - set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFCF) | ((ulong)value << 4); + readonly get => (BlendOverlapEXT)((Internal.Id3 >> 4) & 0x3); + set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFFCF) | ((ulong)value << 4); } public bool DepthMode { - readonly get => ((Internal.Id8 >> 6) & 0x1) != 0UL; - set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6); + readonly get => ((Internal.Id3 >> 6) & 0x1) != 0UL; + set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6); + } + + public PrimitiveTopology TopologyClass + { + readonly get => (PrimitiveTopology)((Internal.Id3 >> 7) & 0xF); + set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFF8F) | ((ulong)value << 7); } public bool HasTessellationControlShader; @@ -317,7 +261,6 @@ namespace Ryujinx.Graphics.Vulkan AdvancedBlendDstPreMultiplied = true; AdvancedBlendOverlap = BlendOverlapEXT.UncorrelatedExt; - LineWidth = 1f; SamplesCount = 1; DepthMode = true; } @@ -337,7 +280,6 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.ComputePipelineCreateInfo, Stage = Stages[0], - BasePipelineIndex = -1, Layout = PipelineLayout, }; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs b/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs index c56224216..1e3253988 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs @@ -11,20 +11,14 @@ namespace Ryujinx.Graphics.Vulkan { public ulong Id0; public ulong Id1; + public ulong Id2; public ulong Id3; - public ulong Id4; - public ulong Id5; - public ulong Id6; - - public ulong Id7; - public ulong Id8; - - private readonly uint VertexAttributeDescriptionsCount => (byte)((Id5 >> 38) & 0xFF); - private readonly uint VertexBindingDescriptionsCount => (byte)((Id5 >> 46) & 0xFF); - private readonly uint ColorBlendAttachmentStateCount => (byte)((Id6 >> 8) & 0xFF); - private readonly bool HasDepthStencil => ((Id6 >> 63) & 0x1) != 0UL; + private readonly uint VertexAttributeDescriptionsCount => (byte)((Id0 >> 38) & 0xFF); + private readonly uint VertexBindingDescriptionsCount => (byte)((Id0 >> 46) & 0xFF); + private readonly uint ColorBlendAttachmentStateCount => (byte)((Id1 >> 8) & 0xFF); + private readonly bool HasDepthStencil => ((Id1 >> 63) & 0x1) != 0UL; public Array32 VertexAttributeDescriptions; public Array33 VertexBindingDescriptions; @@ -40,9 +34,7 @@ namespace Ryujinx.Graphics.Vulkan public bool Equals(ref PipelineUid other) { - if (!Unsafe.As>(ref Id0).Equals(Unsafe.As>(ref other.Id0)) || - !Unsafe.As>(ref Id4).Equals(Unsafe.As>(ref other.Id4)) || - !Unsafe.As>(ref Id7).Equals(Unsafe.As>(ref other.Id7))) + if (!Unsafe.As>(ref Id2).Equals(Unsafe.As>(ref other.Id2))) { return false; } @@ -80,12 +72,7 @@ namespace Ryujinx.Graphics.Vulkan ulong hash64 = Id0 * 23 ^ Id1 * 23 ^ Id2 * 23 ^ - Id3 * 23 ^ - Id4 * 23 ^ - Id5 * 23 ^ - Id6 * 23 ^ - Id7 * 23 ^ - Id8 * 23; + Id3 * 23; for (int i = 0; i < (int)VertexAttributeDescriptionsCount; i++) { From c53f58a4a9d0216762544637c2cebb53f7b9d3ea Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 3 Aug 2024 19:47:08 -0700 Subject: [PATCH 083/132] Resolve issue with primitive toplogy Primitive Restart Enable should depend on Extended dynamic state 2 extension not 1 Resolve Primitive restart enable Fix MoltenVK crash --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 17 ++++----- .../PipelineDynamicState.cs | 8 ++--- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 35 ++++++++----------- 3 files changed, 27 insertions(+), 33 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 3ccd82a10..159229752 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -669,9 +669,9 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { - if (oldTopology.ConvertToClass() != _newState.TopologyClass.ConvertToClass()) + if (oldTopology.ConvertToClass() != _newState.Topology.ConvertToClass()) { - _newState.TopologyClass = _newState.TopologyClass.ConvertToClass(); + _newState.Topology = oldTopology; } DynamicState.SetCullMode(oldCullMode); @@ -686,10 +686,9 @@ namespace Ryujinx.Graphics.Vulkan _newState.DepthTestEnable = oldDepthTestEnable; _newState.DepthWriteEnable = oldDepthWriteEnable; _newState.ViewportsCount = oldViewportsCount; + _newState.Topology = oldTopology; } - _newState.Topology = oldTopology; - DynamicState.SetViewports(ref oldViewports, oldViewportsCount); SignalStateChange(); @@ -1072,15 +1071,17 @@ namespace Ryujinx.Graphics.Vulkan { var newTopologyClass = vkTopology.ConvertToClass(); - if ((_newState.TopologyClass != newTopologyClass)) + if ((_newState.Topology.ConvertToClass() != newTopologyClass)) { - _newState.TopologyClass = newTopologyClass; + _newState.Topology = vkTopology; } DynamicState.SetPrimitiveTopology(vkTopology); } - - _newState.Topology = vkTopology; + else + { + _newState.Topology = vkTopology; + } SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 623c47fac..5194652d6 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -53,7 +53,7 @@ namespace Ryujinx.Graphics.Vulkan private uint _patchControlPoints; - public PrimitiveTopology Topology; + private PrimitiveTopology _topology; private bool _primitiveRestartEnable; @@ -78,7 +78,7 @@ namespace Ryujinx.Graphics.Vulkan PrimitiveRestart = 1 << 14, PrimitiveTopology = 1 << 15, DepthBiasEnable = 1 << 16, - Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, + Standard = Blend | DepthBias | Scissor | Stencil | Viewport, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnableandStencilOp | PrimitiveTopology, Extended2 = RasterDiscard | PrimitiveRestart | DepthBiasEnable, } @@ -217,7 +217,7 @@ namespace Ryujinx.Graphics.Vulkan public void SetPrimitiveTopology(PrimitiveTopology primitiveTopology) { - Topology = primitiveTopology; + _topology = primitiveTopology; _dirty |= DirtyFlags.PrimitiveTopology; } @@ -460,7 +460,7 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordPrimitiveTopology(VulkanRenderer gd, CommandBuffer commandBuffer) { - gd.ExtendedDynamicStateApi.CmdSetPrimitiveTopology(commandBuffer, Topology); + gd.ExtendedDynamicStateApi.CmdSetPrimitiveTopology(commandBuffer, _topology); } private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 1dfca2bff..fb8a65bc6 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -239,12 +239,6 @@ namespace Ryujinx.Graphics.Vulkan set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6); } - public PrimitiveTopology TopologyClass - { - readonly get => (PrimitiveTopology)((Internal.Id3 >> 7) & 0xF); - set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFF8F) | ((ulong)value << 7); - } - public bool HasTessellationControlShader; public NativeArray Stages; public PipelineLayout PipelineLayout; @@ -366,17 +360,11 @@ namespace Ryujinx.Graphics.Vulkan var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, - Topology = supportsExtDynamicState ? TopologyClass : Topology, + Topology = Topology, }; PipelineTessellationStateCreateInfo tessellationState; - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints && HasTessellationControlShader) - { - tessellationState.SType = StructureType.PipelineTessellationStateCreateInfo; - tessellationState.PatchControlPoints = PatchControlPoints; - } - var rasterizationState = new PipelineRasterizationStateCreateInfo { SType = StructureType.PipelineRasterizationStateCreateInfo, @@ -390,12 +378,6 @@ namespace Ryujinx.Graphics.Vulkan rasterizationState.LineWidth = 1.0f; } - if (!supportsExtDynamicState2) - { - rasterizationState.DepthBiasEnable = DepthBiasEnable; - rasterizationState.RasterizerDiscardEnable = RasterizerDiscardEnable; - } - var viewportState = new PipelineViewportStateCreateInfo { SType = StructureType.PipelineViewportStateCreateInfo, @@ -430,8 +412,6 @@ namespace Ryujinx.Graphics.Vulkan if (!supportsExtDynamicState) { - inputAssemblyState.PrimitiveRestartEnable = PrimitiveRestartEnable; - rasterizationState.CullMode = CullMode; rasterizationState.FrontFace = FrontFace; @@ -458,6 +438,19 @@ namespace Ryujinx.Graphics.Vulkan depthStencilState.DepthCompareOp = DepthCompareOp; } + if (!supportsExtDynamicState2) + { + inputAssemblyState.PrimitiveRestartEnable = PrimitiveRestartEnable; + rasterizationState.DepthBiasEnable = DepthBiasEnable; + rasterizationState.RasterizerDiscardEnable = RasterizerDiscardEnable; + } + + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints && HasTessellationControlShader) + { + tessellationState.SType = StructureType.PipelineTessellationStateCreateInfo; + tessellationState.PatchControlPoints = PatchControlPoints; + } + uint blendEnables = 0; if (isMoltenVk && Internal.AttachmentIntegerFormatMask != 0) From f15b6c85f66a87cf622c8a2b90d0e1a8673be726 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 4 Aug 2024 16:16:27 -0700 Subject: [PATCH 084/132] According to spec there is no need to do this as it should automatically be not set when not needed --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 +- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 159229752..fe4a4cb90 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -992,7 +992,7 @@ namespace Ryujinx.Graphics.Vulkan public void SetPatchParameters(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel) { - if (Gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints && _newState.HasTessellationControlShader) + if (Gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { DynamicState.SetPatchControlPoints((uint)vertices); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index fb8a65bc6..14ee61c02 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -445,7 +445,7 @@ namespace Ryujinx.Graphics.Vulkan rasterizationState.RasterizerDiscardEnable = RasterizerDiscardEnable; } - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints && HasTessellationControlShader) + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { tessellationState.SType = StructureType.PipelineTessellationStateCreateInfo; tessellationState.PatchControlPoints = PatchControlPoints; @@ -548,7 +548,7 @@ namespace Ryujinx.Graphics.Vulkan { dynamicStates[currentIndex++] = DynamicState.LogicOpExt; } - if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints && HasTessellationControlShader) + if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { dynamicStates[currentIndex++] = DynamicState.PatchControlPointsExt; } @@ -578,7 +578,7 @@ namespace Ryujinx.Graphics.Vulkan RenderPass = renderPass, }; - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints && HasTessellationControlShader) + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { pipelineCreateInfo.PTessellationState = &tessellationState; } From af9de85a1b39008d2c185728e1fa42b2dd301c39 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 4 Aug 2024 20:34:49 -0700 Subject: [PATCH 085/132] Origin of crash? --- src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs | 3 +++ src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 5 +++++ src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 1 + 3 files changed, 9 insertions(+) diff --git a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs index c7df9bafc..9420aa31c 100644 --- a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs +++ b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs @@ -54,6 +54,7 @@ namespace Ryujinx.Graphics.Vulkan public readonly uint VertexBufferAlignment; public readonly uint SubTexelPrecisionBits; public readonly ulong MinResourceAlignment; + public readonly uint MaxTessellationPatchSize; public HardwareCapabilities( bool supportsIndexTypeUint8, @@ -72,6 +73,7 @@ namespace Ryujinx.Graphics.Vulkan bool supportsConditionalRendering, bool supportsExtendedDynamicState, PhysicalDeviceExtendedDynamicState2FeaturesEXT supportsExtendedDynamicState2, + uint maxTessellationPatchSize, bool supportsMultiView, bool supportsNullDescriptors, bool supportsPushDescriptors, @@ -111,6 +113,7 @@ namespace Ryujinx.Graphics.Vulkan SupportsConditionalRendering = supportsConditionalRendering; SupportsExtendedDynamicState = supportsExtendedDynamicState; SupportsExtendedDynamicState2 = supportsExtendedDynamicState2; + MaxTessellationPatchSize = maxTessellationPatchSize; SupportsMultiView = supportsMultiView; SupportsNullDescriptors = supportsNullDescriptors; SupportsPushDescriptors = supportsPushDescriptors; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index fe4a4cb90..7afa9acce 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -992,6 +992,11 @@ namespace Ryujinx.Graphics.Vulkan public void SetPatchParameters(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel) { + if (vertices == 0 || vertices > Gd.Capabilities.MaxTessellationPatchSize) + { + return; + } + if (Gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { DynamicState.SetPatchControlPoints((uint)vertices); diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index bb6216be7..fbf8856e5 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -404,6 +404,7 @@ namespace Ryujinx.Graphics.Vulkan _physicalDevice.IsDeviceExtensionPresent(ExtConditionalRendering.ExtensionName), _physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState.ExtensionName), featuresExtendedDynamicState2, + _physicalDevice.PhysicalDeviceProperties.Limits.MaxTessellationPatchSize, features2.Features.MultiViewport && !(IsMoltenVk && Vendor == Vendor.Amd), // Workaround for AMD on MoltenVK issue featuresRobustness2.NullDescriptor || IsMoltenVk, supportsPushDescriptors && !IsMoltenVk, From 482b960740b817c2ab0ca887eda8b3442c86d09f Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 4 Aug 2024 20:50:10 -0700 Subject: [PATCH 086/132] More changes to be inline with spec --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 4 ++-- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 7afa9acce..482f11844 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -992,11 +992,11 @@ namespace Ryujinx.Graphics.Vulkan public void SetPatchParameters(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel) { - if (vertices == 0 || vertices > Gd.Capabilities.MaxTessellationPatchSize) + if (vertices == 0 || vertices > Gd.Capabilities.MaxTessellationPatchSize || !_newState.HasTessellationControlShader) { return; } - + if (Gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { DynamicState.SetPatchControlPoints((uint)vertices); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 14ee61c02..d1df300ed 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -578,7 +578,7 @@ namespace Ryujinx.Graphics.Vulkan RenderPass = renderPass, }; - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints && HasTessellationControlShader) { pipelineCreateInfo.PTessellationState = &tessellationState; } From 53ca3b53b6210c312c782738355b665bbdf2197f Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 5 Aug 2024 23:18:28 -0700 Subject: [PATCH 087/132] Exclude Patch Control Points dynamic state at this time --- src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index f1d86dcf7..14df8fade 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -462,6 +462,9 @@ namespace Ryujinx.Graphics.Vulkan pExtendedFeatures = &featuresExtendedDynamicState; + //Temporarily disable this can be added back at a later date, make it easy to re-enable. + supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints = false; + if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName)) { var featuresExtendedDynamicState2 = new PhysicalDeviceExtendedDynamicState2FeaturesEXT() From 6aa30b24ba34ec7a20307445e2b3ecd6c7157f0b Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Tue, 6 Aug 2024 08:15:17 -0700 Subject: [PATCH 088/132] Actually change what is being passed to HwCapabilities instead of just disabling the feature. --- src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs | 3 --- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index 14df8fade..f1d86dcf7 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -462,9 +462,6 @@ namespace Ryujinx.Graphics.Vulkan pExtendedFeatures = &featuresExtendedDynamicState; - //Temporarily disable this can be added back at a later date, make it easy to re-enable. - supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints = false; - if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName)) { var featuresExtendedDynamicState2 = new PhysicalDeviceExtendedDynamicState2FeaturesEXT() diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index fbf8856e5..70b1864a5 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -387,6 +387,9 @@ namespace Ryujinx.Graphics.Vulkan properties.Limits.FramebufferDepthSampleCounts & properties.Limits.FramebufferStencilSampleCounts; + //Temporarily disable this can be added back at a later date, make it easy to re-enable. + featuresExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints = false; + Capabilities = new HardwareCapabilities( _physicalDevice.IsDeviceExtensionPresent("VK_EXT_index_type_uint8"), supportsCustomBorderColor, From af31a14c771ab41b23ef1244456d4ea91e884996 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Tue, 6 Aug 2024 23:24:34 -0700 Subject: [PATCH 089/132] Spec states it CAN be null --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 +- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 482f11844..ab35da99c 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -992,7 +992,7 @@ namespace Ryujinx.Graphics.Vulkan public void SetPatchParameters(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel) { - if (vertices == 0 || vertices > Gd.Capabilities.MaxTessellationPatchSize || !_newState.HasTessellationControlShader) + if (vertices == 0 || vertices > Gd.Capabilities.MaxTessellationPatchSize) { return; } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index d1df300ed..14ee61c02 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -578,7 +578,7 @@ namespace Ryujinx.Graphics.Vulkan RenderPass = renderPass, }; - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints && HasTessellationControlShader) + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { pipelineCreateInfo.PTessellationState = &tessellationState; } From 42c47e408d75818d477489a2f1a923eb9aceea59 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 10 Aug 2024 16:35:30 -0700 Subject: [PATCH 090/132] If dynamic states are enabled use default values for calculation uuid --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 +- .../PipelineConverter.cs | 93 ++++++++++--------- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 66 +++++++++++-- .../ShaderCollection.cs | 2 +- .../VertexBufferUpdater.cs | 2 +- 5 files changed, 109 insertions(+), 56 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index ab35da99c..10cf41cc4 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -129,7 +129,7 @@ namespace Ryujinx.Graphics.Vulkan _supportExtDynamic2 = gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2; - _newState.Initialize(); + _newState.Initialize(_supportExtDynamic, gd.Capabilities.SupportsExtendedDynamicState2); } public void Initialize() diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 3e330ee7f..1c7836da7 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -154,8 +154,11 @@ namespace Ryujinx.Graphics.Vulkan public static PipelineState ToVulkanPipelineState(this ProgramPipelineState state, VulkanRenderer gd) { + var extendedDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2; + var extendedDynamicState = gd.Capabilities.SupportsExtendedDynamicState; + PipelineState pipeline = new(); - pipeline.Initialize(); + pipeline.Initialize(extendedDynamicState, extendedDynamicState2); // It is assumed that Dynamic State is enabled when this conversion is used. pipeline.DepthBoundsTestEnable = false; // Not implemented. @@ -169,62 +172,66 @@ namespace Ryujinx.Graphics.Vulkan pipeline.PolygonMode = PolygonMode.Fill; // Not implemented. - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2) - { - pipeline.PrimitiveRestartEnable = state.PrimitiveRestartEnable; - pipeline.RasterizerDiscardEnable = state.RasterizerDiscard; - pipeline.DepthBiasEnable = state.BiasEnable != 0; - } + pipeline.PrimitiveRestartEnable = extendedDynamicState2.ExtendedDynamicState2 ? false : state.PrimitiveRestartEnable; + pipeline.RasterizerDiscardEnable = extendedDynamicState2.ExtendedDynamicState2 ? false : state.RasterizerDiscard; + pipeline.DepthBiasEnable = extendedDynamicState2.ExtendedDynamicState2 ? false : state.BiasEnable != 0; - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) + + if (!extendedDynamicState2.ExtendedDynamicState2LogicOp) { pipeline.LogicOp = state.LogicOpEnable ? state.LogicOp.Convert() : default; } - - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) + else { - pipeline.PatchControlPoints = state.PatchControlPoints; + pipeline.LogicOp = 0; } + pipeline.PatchControlPoints = extendedDynamicState2.ExtendedDynamicState2PatchControlPoints ? 0 : state.PatchControlPoints; + pipeline.SamplesCount = (uint)state.SamplesCount; - // Stencil masks and ref are dynamic, so are 0 in the Vulkan pipeline. - if (!gd.Capabilities.SupportsExtendedDynamicState) + pipeline.DepthTestEnable = !extendedDynamicState && state.DepthTest.TestEnable; + pipeline.DepthWriteEnable = !extendedDynamicState && state.DepthTest.WriteEnable && state.DepthTest.TestEnable; + + if (!extendedDynamicState) { - pipeline.DepthTestEnable = state.DepthTest.TestEnable; - pipeline.DepthWriteEnable = state.DepthTest.WriteEnable && state.DepthTest.TestEnable; - pipeline.DepthCompareOp = state.DepthTest.TestEnable ? state.DepthTest.Func.Convert() : default; - pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None; - - pipeline.FrontFace = state.FrontFace.Convert(); - - if (gd.Capabilities.SupportsMultiView) - { - pipeline.ScissorsCount = Constants.MaxViewports; - pipeline.ViewportsCount = Constants.MaxViewports; - } - else - { - pipeline.ScissorsCount = 1; - pipeline.ViewportsCount = 1; - } - - pipeline.StencilFrontFailOp = state.StencilTest.FrontSFail.Convert(); - pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert(); - pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert(); - pipeline.StencilFrontCompareOp = state.StencilTest.FrontFunc.Convert(); - - pipeline.StencilBackFailOp = state.StencilTest.BackSFail.Convert(); - pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert(); - pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert(); - pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert(); - - pipeline.StencilTestEnable = state.StencilTest.TestEnable; + } + else + { + pipeline.DepthCompareOp = 0; + pipeline.CullMode = 0; } - pipeline.Topology = gd.TopologyRemap(state.Topology).Convert(); + pipeline.FrontFace = extendedDynamicState ? 0 : state.FrontFace.Convert(); + + if (gd.Capabilities.SupportsMultiView) + { + pipeline.ScissorsCount = (uint)(extendedDynamicState ? 0 : Constants.MaxViewports); + pipeline.ViewportsCount = (uint)(extendedDynamicState ? 0 : Constants.MaxViewports); + } + else + { + pipeline.ScissorsCount = (uint)(extendedDynamicState ? 0 : 1); + pipeline.ViewportsCount = (uint)(extendedDynamicState ? 0 : 1); + } + + pipeline.StencilTestEnable = !extendedDynamicState && state.StencilTest.TestEnable; + + pipeline.StencilFrontFailOp = extendedDynamicState ? 0 : state.StencilTest.FrontSFail.Convert(); + pipeline.StencilFrontPassOp = extendedDynamicState ? 0 : state.StencilTest.FrontDpPass.Convert(); + pipeline.StencilFrontDepthFailOp = extendedDynamicState ? 0 : state.StencilTest.FrontDpFail.Convert(); + pipeline.StencilFrontCompareOp = extendedDynamicState ? 0 : state.StencilTest.FrontFunc.Convert(); + + pipeline.StencilBackFailOp = extendedDynamicState ? 0 : state.StencilTest.BackSFail.Convert(); + pipeline.StencilBackPassOp = extendedDynamicState ? 0 : state.StencilTest.BackDpPass.Convert(); + pipeline.StencilBackDepthFailOp = extendedDynamicState ? 0 : state.StencilTest.BackDpFail.Convert(); + pipeline.StencilBackCompareOp = extendedDynamicState ? 0 : state.StencilTest.BackFunc.Convert(); + + var vkTopology = gd.TopologyRemap(state.Topology).Convert(); + + pipeline.Topology = extendedDynamicState ? vkTopology.ConvertToClass() : vkTopology; int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount); int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 14ee61c02..9679dd8af 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -246,7 +246,12 @@ namespace Ryujinx.Graphics.Vulkan private Array32 _vertexAttributeDescriptions2; - public void Initialize() + private bool _supportsExtDynamicState; + private PhysicalDeviceExtendedDynamicState2FeaturesEXT _supportsExtDynamicState2; + + + public void Initialize(bool supportsExtDynamicState, + PhysicalDeviceExtendedDynamicState2FeaturesEXT extendedDynamicState2) { HasTessellationControlShader = false; Stages = new NativeArray(Constants.MaxShaderStages); @@ -257,6 +262,50 @@ namespace Ryujinx.Graphics.Vulkan SamplesCount = 1; DepthMode = true; + + _supportsExtDynamicState = supportsExtDynamicState; + _supportsExtDynamicState2 = extendedDynamicState2; + + if (_supportsExtDynamicState) + { + StencilFrontFailOp = 0; + StencilFrontPassOp = 0; + StencilFrontDepthFailOp = 0; + StencilFrontCompareOp = 0; + + StencilBackFailOp = 0; + StencilBackPassOp = 0; + StencilBackDepthFailOp = 0; + StencilBackCompareOp = 0; + + ViewportsCount = 0; + ScissorsCount = 0; + + CullMode = 0; + FrontFace = 0; + DepthTestEnable = false; + DepthWriteEnable = false; + DepthCompareOp = 0; + StencilTestEnable = false; + + } + + if (_supportsExtDynamicState2.ExtendedDynamicState2) + { + PrimitiveRestartEnable = false; + DepthBiasEnable = false; + RasterizerDiscardEnable = false; + } + + if (_supportsExtDynamicState2.ExtendedDynamicState2LogicOp) + { + LogicOp = 0; + } + + if (_supportsExtDynamicState2.ExtendedDynamicState2PatchControlPoints) + { + PatchControlPoints = 0; + } } public unsafe Auto CreateComputePipeline( @@ -340,9 +389,6 @@ namespace Ryujinx.Graphics.Vulkan UpdateVertexAttributeDescriptions(gd); } - bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState; - bool supportsExtDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2; - fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0]) fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions2 = &_vertexAttributeDescriptions2[0]) fixed (VertexInputBindingDescription* pVertexBindingDescriptions = &Internal.VertexBindingDescriptions[0]) @@ -410,7 +456,7 @@ namespace Ryujinx.Graphics.Vulkan DepthBoundsTestEnable = false, }; - if (!supportsExtDynamicState) + if (!_supportsExtDynamicState) { rasterizationState.CullMode = CullMode; rasterizationState.FrontFace = FrontFace; @@ -438,7 +484,7 @@ namespace Ryujinx.Graphics.Vulkan depthStencilState.DepthCompareOp = DepthCompareOp; } - if (!supportsExtDynamicState2) + if (!_supportsExtDynamicState2.ExtendedDynamicState2) { inputAssemblyState.PrimitiveRestartEnable = PrimitiveRestartEnable; rasterizationState.DepthBiasEnable = DepthBiasEnable; @@ -518,7 +564,7 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[currentIndex++] = DynamicState.LineWidth; } - if (supportsExtDynamicState) + if (_supportsExtDynamicState) { if (!isMoltenVk) { @@ -538,17 +584,17 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[currentIndex++] = DynamicState.PrimitiveTopologyExt; } - if (supportsExtDynamicState2) + if (_supportsExtDynamicState2.ExtendedDynamicState2) { dynamicStates[currentIndex++] = DynamicState.DepthBiasEnableExt; dynamicStates[currentIndex++] = DynamicState.RasterizerDiscardEnableExt; dynamicStates[currentIndex++] = DynamicState.PrimitiveRestartEnableExt; - if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) + if (_supportsExtDynamicState2.ExtendedDynamicState2LogicOp) { dynamicStates[currentIndex++] = DynamicState.LogicOpExt; } - if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) + if (_supportsExtDynamicState2.ExtendedDynamicState2PatchControlPoints) { dynamicStates[currentIndex++] = DynamicState.PatchControlPointsExt; } diff --git a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs index c9aab4018..5338030d9 100644 --- a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs +++ b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs @@ -528,7 +528,7 @@ namespace Ryujinx.Graphics.Vulkan public void CreateBackgroundComputePipeline() { PipelineState pipeline = new(); - pipeline.Initialize(); + pipeline.Initialize(_gd.Capabilities.SupportsExtendedDynamicState, _gd.Capabilities.SupportsExtendedDynamicState2); pipeline.Stages[0] = _shaders[0].GetInfo(); pipeline.StagesCount = 1; diff --git a/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs b/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs index 94269dd76..44063da70 100644 --- a/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs +++ b/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs @@ -51,7 +51,7 @@ namespace Ryujinx.Graphics.Vulkan { if (_count != 0) { - if (_gd.Capabilities.SupportsExtendedDynamicState) + if (_gd.Capabilities.SupportsExtendedDynamicState && !_gd.IsMoltenVk) { _gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2( cbs.CommandBuffer, From d6f05044ea58030c42b0e81bd68e2bd10c8ab0b5 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 10 Aug 2024 16:49:05 -0700 Subject: [PATCH 091/132] Set stride to 0 if Vertex Input dynamic state is enabled --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 +- src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 10cf41cc4..2b75d2753 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1425,7 +1425,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.Internal.VertexBindingDescriptions[descriptorIndex] = new VertexInputBindingDescription( (uint)binding, - (uint)vertexBuffer.Stride, + _supportExtDynamic && !Gd.IsMoltenVk ? 0 : (uint)vertexBuffer.Stride, inputRate); int vbSize = vertexBuffer.Buffer.Size; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 1c7836da7..a6a88a1e7 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -276,7 +276,7 @@ namespace Ryujinx.Graphics.Vulkan // TODO: Support divisor > 1 pipeline.Internal.VertexBindingDescriptions[descriptorIndex++] = new VertexInputBindingDescription( (uint)i + 1, - (uint)alignedStride, + extendedDynamicState && !gd.IsMoltenVk ? 0 : (uint)alignedStride, inputRate); } } From 49494b5b2d98e78014ebe5eb803ca5b8a76bde1a Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 10 Aug 2024 17:16:48 -0700 Subject: [PATCH 092/132] Some more default values --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 9679dd8af..f6de4c5e7 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -263,6 +263,9 @@ namespace Ryujinx.Graphics.Vulkan SamplesCount = 1; DepthMode = true; + PolygonMode = PolygonMode.Fill; + DepthBoundsTestEnable = false; + _supportsExtDynamicState = supportsExtDynamicState; _supportsExtDynamicState2 = extendedDynamicState2; @@ -414,7 +417,6 @@ namespace Ryujinx.Graphics.Vulkan var rasterizationState = new PipelineRasterizationStateCreateInfo { SType = StructureType.PipelineRasterizationStateCreateInfo, - PolygonMode = PolygonMode, DepthClampEnable = DepthClampEnable, }; @@ -453,7 +455,7 @@ namespace Ryujinx.Graphics.Vulkan var depthStencilState = new PipelineDepthStencilStateCreateInfo { SType = StructureType.PipelineDepthStencilStateCreateInfo, - DepthBoundsTestEnable = false, + DepthBoundsTestEnable = DepthBoundsTestEnable, }; if (!_supportsExtDynamicState) From 1a43536092d113ddd3dd60b9409dea63302732b8 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 11 Aug 2024 19:54:52 -0700 Subject: [PATCH 093/132] LogicOps --- .../PipelineConverter.cs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index a6a88a1e7..75a6674a3 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -168,7 +168,6 @@ namespace Ryujinx.Graphics.Vulkan pipeline.DepthMode = state.DepthMode == DepthMode.MinusOneToOne; pipeline.HasDepthStencil = state.DepthStencilEnable; - pipeline.LogicOpEnable = state.LogicOpEnable; pipeline.PolygonMode = PolygonMode.Fill; // Not implemented. @@ -176,16 +175,6 @@ namespace Ryujinx.Graphics.Vulkan pipeline.RasterizerDiscardEnable = extendedDynamicState2.ExtendedDynamicState2 ? false : state.RasterizerDiscard; pipeline.DepthBiasEnable = extendedDynamicState2.ExtendedDynamicState2 ? false : state.BiasEnable != 0; - - if (!extendedDynamicState2.ExtendedDynamicState2LogicOp) - { - pipeline.LogicOp = state.LogicOpEnable ? state.LogicOp.Convert() : default; - } - else - { - pipeline.LogicOp = 0; - } - pipeline.PatchControlPoints = extendedDynamicState2.ExtendedDynamicState2PatchControlPoints ? 0 : state.PatchControlPoints; pipeline.SamplesCount = (uint)state.SamplesCount; @@ -339,6 +328,20 @@ namespace Ryujinx.Graphics.Vulkan pipeline.Internal.AttachmentIntegerFormatMask = attachmentIntegerFormatMask; pipeline.Internal.LogicOpsAllowed = attachmentCount == 0 || !allFormatsFloatOrSrgb; + bool logicOpEnable = state.LogicOpEnable && + (gd.Vendor == Vendor.Nvidia || (attachmentCount == 0 || !allFormatsFloatOrSrgb)); + + pipeline.LogicOpEnable = logicOpEnable; + + if (!extendedDynamicState2.ExtendedDynamicState2LogicOp) + { + pipeline.LogicOp = logicOpEnable ? state.LogicOp.Convert() : default; + } + else + { + pipeline.LogicOp = 0; + } + return pipeline; } } From 2d1af4ddb44132ed75cab4aef00fcb68e48a4a7e Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 12 Aug 2024 20:57:08 -0700 Subject: [PATCH 094/132] Set a default topology state that can be overwritten later if needed. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 ++ src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs | 4 +--- src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs | 5 +++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 2b75d2753..a1c66de35 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1105,6 +1105,8 @@ namespace Ryujinx.Graphics.Vulkan _newState.HasTessellationControlShader = internalProgram.HasTessellationControlShader; _newState.StagesCount = (uint)stages.Length; + _newState.Topology = internalProgram.ShaderTopology; + stages.CopyTo(_newState.Stages.AsSpan()[..stages.Length]); SignalStateChange(); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 75a6674a3..28241f5da 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -218,9 +218,7 @@ namespace Ryujinx.Graphics.Vulkan pipeline.StencilBackDepthFailOp = extendedDynamicState ? 0 : state.StencilTest.BackDpFail.Convert(); pipeline.StencilBackCompareOp = extendedDynamicState ? 0 : state.StencilTest.BackFunc.Convert(); - var vkTopology = gd.TopologyRemap(state.Topology).Convert(); - - pipeline.Topology = extendedDynamicState ? vkTopology.ConvertToClass() : vkTopology; + pipeline.Topology = gd.TopologyRemap(state.Topology).Convert(); int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount); int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount); diff --git a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs index 5338030d9..821a3cbce 100644 --- a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs +++ b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; +using PrimitiveTopology = Silk.NET.Vulkan.PrimitiveTopology; namespace Ryujinx.Graphics.Vulkan { @@ -23,6 +24,8 @@ namespace Ryujinx.Graphics.Vulkan public bool IsCompute { get; } public bool HasTessellationControlShader => (Stages & (1u << 3)) != 0; + public PrimitiveTopology ShaderTopology; + public bool UpdateTexturesWithoutTemplate { get; } public uint Stages { get; } @@ -551,6 +554,8 @@ namespace Ryujinx.Graphics.Vulkan PipelineState pipeline = _state.ToVulkanPipelineState(_gd); + ShaderTopology = pipeline.Topology; + // Copy the shader stage info to the pipeline. var stages = pipeline.Stages.AsSpan(); From 674288a71f242e851576156170139e438dc90e63 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 12 Aug 2024 22:09:09 -0700 Subject: [PATCH 095/132] Avoid creating pipelines for each topology. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 4 ++-- src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index a1c66de35..15220ddf7 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -671,7 +671,7 @@ namespace Ryujinx.Graphics.Vulkan { if (oldTopology.ConvertToClass() != _newState.Topology.ConvertToClass()) { - _newState.Topology = oldTopology; + _newState.Topology = oldTopology.ConvertToClass(); } DynamicState.SetCullMode(oldCullMode); @@ -1078,7 +1078,7 @@ namespace Ryujinx.Graphics.Vulkan if ((_newState.Topology.ConvertToClass() != newTopologyClass)) { - _newState.Topology = vkTopology; + _newState.Topology = vkTopology.ConvertToClass(); } DynamicState.SetPrimitiveTopology(vkTopology); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 28241f5da..28ddfb292 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -218,7 +218,7 @@ namespace Ryujinx.Graphics.Vulkan pipeline.StencilBackDepthFailOp = extendedDynamicState ? 0 : state.StencilTest.BackDpFail.Convert(); pipeline.StencilBackCompareOp = extendedDynamicState ? 0 : state.StencilTest.BackFunc.Convert(); - pipeline.Topology = gd.TopologyRemap(state.Topology).Convert(); + pipeline.Topology = extendedDynamicState ? gd.TopologyRemap(state.Topology).Convert().ConvertToClass() : gd.TopologyRemap(state.Topology).Convert(); int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount); int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount); From 07f80bdbb79ab2acf25fcd67670cfbf156c7f985 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 1 Sep 2024 16:41:36 -0700 Subject: [PATCH 096/132] Resolve some pipeline creation issue when extended dynamic states are not supported --- src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs | 3 +++ src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs | 3 +++ src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 4 ++-- src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs | 5 +++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs b/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs index c16722af7..6e80e3581 100644 --- a/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs +++ b/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs @@ -63,6 +63,9 @@ namespace Ryujinx.Graphics.GAL public bool PrimitiveRestartEnable; public uint PatchControlPoints; + public float DepthBiasUnits; + public float DepthBiasFactor; + public DepthMode DepthMode; public void SetVertexAttribs(ReadOnlySpan vertexAttribs) diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs index 1dc77b52d..1e8fe5c69 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs @@ -854,6 +854,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed enables |= (depthBias.FillEnable ? PolygonModeMask.Fill : 0); _pipeline.BiasEnable = enables; + _pipeline.DepthBiasUnits = units / 2f; + _pipeline.DepthBiasFactor = factor; + _context.Renderer.Pipeline.SetDepthBias(enables, factor, units / 2f, clamp); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 05430966e..755380188 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -893,11 +893,11 @@ namespace Ryujinx.Graphics.Vulkan { if (_supportExtDynamic) { - DynamicState.SetCullMode(enable ? face.Convert() : CullModeFlags.None); + DynamicState.SetCullMode(enable ? face.Convert() : default); } else { - _newState.CullMode = enable ? face.Convert() : CullModeFlags.None; + _newState.CullMode = enable ? face.Convert() : default; } SignalStateChange(); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 34a9ca8f7..aa5dff3b1 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -173,7 +173,8 @@ namespace Ryujinx.Graphics.Vulkan pipeline.PrimitiveRestartEnable = extendedDynamicState2.ExtendedDynamicState2 ? false : state.PrimitiveRestartEnable; pipeline.RasterizerDiscardEnable = extendedDynamicState2.ExtendedDynamicState2 ? false : state.RasterizerDiscard; - pipeline.DepthBiasEnable = extendedDynamicState2.ExtendedDynamicState2 ? false : state.BiasEnable != 0; + pipeline.DepthBiasEnable = extendedDynamicState2.ExtendedDynamicState2 ? false : ((state.BiasEnable != 0) && + (state.DepthBiasFactor != 0 && state.DepthBiasUnits != 0)); pipeline.PatchControlPoints = extendedDynamicState2.ExtendedDynamicState2PatchControlPoints ? 0 : state.PatchControlPoints; @@ -185,7 +186,7 @@ namespace Ryujinx.Graphics.Vulkan if (!extendedDynamicState) { pipeline.DepthCompareOp = state.DepthTest.TestEnable ? state.DepthTest.Func.Convert() : default; - pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None; + pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : default; } else { From 2298362e7f886fbf4f87bdda01d6a0dbf8d36cfa Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 1 Sep 2024 18:17:19 -0700 Subject: [PATCH 097/132] Resolve remaining pipeline creation errors when extended pipeline states extension not supported --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 34 ++----------------- .../PipelineConverter.cs | 6 ++-- .../PipelineDynamicState.cs | 30 ++++++++++++++-- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 22 +++++++++++- .../ShaderCollection.cs | 2 +- 5 files changed, 57 insertions(+), 37 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 755380188..6bc15743c 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -639,7 +639,7 @@ namespace Ryujinx.Graphics.Vulkan 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 oldTopology = _supportExtDynamic ? DynamicState._topology : _newState.Topology; var oldViewports = DynamicState.Viewports; var oldViewportsCount = _supportExtDynamic ? DynamicState.ViewportsCount : _newState.ViewportsCount; @@ -1023,41 +1023,13 @@ namespace Ryujinx.Graphics.Vulkan public void SetPrimitiveRestart(bool enable, int index) { - 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 primitiveRestartEnable for these Topologies 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); + DynamicState.SetPrimitiveRestartEnable(enable); } else { - _newState.PrimitiveRestartEnable = primitiveRestartEnable; + _newState.PrimitiveRestartEnable = enable; } // TODO: What to do about the index? diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index aa5dff3b1..822838f00 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -4,6 +4,7 @@ using Silk.NET.Vulkan; using System; using Format = Silk.NET.Vulkan.Format; using PolygonMode = Silk.NET.Vulkan.PolygonMode; +using PrimitiveTopology = Ryujinx.Graphics.GAL.PrimitiveTopology; namespace Ryujinx.Graphics.Vulkan { @@ -152,7 +153,7 @@ namespace Ryujinx.Graphics.Vulkan 0); } - public static PipelineState ToVulkanPipelineState(this ProgramPipelineState state, VulkanRenderer gd) + public static PipelineState ToVulkanPipelineState(this ProgramPipelineState state, VulkanRenderer gd, bool hasTCS) { var extendedDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2; var extendedDynamicState = gd.Capabilities.SupportsExtendedDynamicState; @@ -219,7 +220,8 @@ namespace Ryujinx.Graphics.Vulkan pipeline.StencilBackDepthFailOp = extendedDynamicState ? 0 : state.StencilTest.BackDpFail.Convert(); pipeline.StencilBackCompareOp = extendedDynamicState ? 0 : state.StencilTest.BackFunc.Convert(); - pipeline.Topology = extendedDynamicState ? gd.TopologyRemap(state.Topology).Convert().ConvertToClass() : gd.TopologyRemap(state.Topology).Convert(); + var topology = hasTCS ? PrimitiveTopology.Patches : state.Topology; + pipeline.Topology = extendedDynamicState ? gd.TopologyRemap(topology).Convert().ConvertToClass() : gd.TopologyRemap(topology).Convert(); int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount); int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 5194652d6..8fa274f3a 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -53,7 +53,7 @@ namespace Ryujinx.Graphics.Vulkan private uint _patchControlPoints; - private PrimitiveTopology _topology; + public PrimitiveTopology _topology; private bool _primitiveRestartEnable; @@ -455,7 +455,33 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordPrimitiveRestartEnable(VulkanRenderer gd, CommandBuffer commandBuffer) { - gd.ExtendedDynamicState2Api.CmdSetPrimitiveRestartEnable(commandBuffer, _primitiveRestartEnable); + 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 primitiveRestartEnable for these Topologies on MacOS + if (gd.IsMoltenVk) + { + primitiveRestartEnable = true; + } + + gd.ExtendedDynamicState2Api.CmdSetPrimitiveRestartEnable(commandBuffer, primitiveRestartEnable); } private readonly void RecordPrimitiveTopology(VulkanRenderer gd, CommandBuffer commandBuffer) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index f6de4c5e7..d1383fc24 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -488,7 +488,27 @@ namespace Ryujinx.Graphics.Vulkan if (!_supportsExtDynamicState2.ExtendedDynamicState2) { - inputAssemblyState.PrimitiveRestartEnable = PrimitiveRestartEnable; + 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; + + inputAssemblyState.PrimitiveRestartEnable = primitiveRestartEnable; rasterizationState.DepthBiasEnable = DepthBiasEnable; rasterizationState.RasterizerDiscardEnable = RasterizerDiscardEnable; } diff --git a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs index 821a3cbce..232a093b8 100644 --- a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs +++ b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs @@ -552,7 +552,7 @@ namespace Ryujinx.Graphics.Vulkan // The active attachment formats have been provided by the abstraction layer. var renderPass = CreateDummyRenderPass(); - PipelineState pipeline = _state.ToVulkanPipelineState(_gd); + PipelineState pipeline = _state.ToVulkanPipelineState(_gd, HasTessellationControlShader); ShaderTopology = pipeline.Topology; From 3f900e6fa075fb734566c2c191c9ca71780c7ee0 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 1 Sep 2024 18:47:06 -0700 Subject: [PATCH 098/132] Resolve missed changes --- src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs | 4 ++-- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index cda13e3bc..1e252cdef 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -82,7 +82,7 @@ namespace Ryujinx.Graphics.Vulkan PrimitiveRestart = 1 << 15, PrimitiveTopology = 1 << 16, DepthBiasEnable = 1 << 17, - Standard = Blend | DepthBias | Scissor | Stencil | Viewport | FeedbackLoop, + Standard = Blend | DepthBias | Scissor | Stencil | Viewport | FeedbackLoop, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnableandStencilOp | PrimitiveTopology, Extended2 = RasterDiscard | PrimitiveRestart | DepthBiasEnable, } @@ -276,7 +276,7 @@ namespace Ryujinx.Graphics.Vulkan public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) { - Vk api = gd.Api; + _ = gd.Api; if (_dirty.HasFlag(DirtyFlags.Blend)) { diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 923b10d38..facb221ab 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -242,8 +242,8 @@ namespace Ryujinx.Graphics.Vulkan public FeedbackLoopAspects FeedbackLoopAspects { - readonly get => (FeedbackLoopAspects)((Internal.Id8 >> 7) & 0x3); - set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFE7F) | (((ulong)value) << 7); + readonly get => (FeedbackLoopAspects)((Internal.Id3 >> 7) & 0x3); + set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFE7F) | (((ulong)value) << 7); } public bool HasTessellationControlShader; @@ -578,8 +578,8 @@ namespace Ryujinx.Graphics.Vulkan bool supportsFeedbackLoopDynamicState = gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop; DynamicState* dynamicStates = stackalloc DynamicState[MaxDynamicStatesCount]; - - int dynamicStatesCount = 7; + + uint dynamicStatesCount = 7; dynamicStates[0] = DynamicState.Viewport; dynamicStates[1] = DynamicState.Scissor; @@ -639,7 +639,7 @@ namespace Ryujinx.Graphics.Vulkan var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo { SType = StructureType.PipelineDynamicStateCreateInfo, - DynamicStateCount = currentIndex, + DynamicStateCount = dynamicStatesCount, PDynamicStates = dynamicStates, }; From 09b8095584c8449e8d1100a4af74870dac5e5098 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 1 Sep 2024 19:21:44 -0700 Subject: [PATCH 099/132] Avoid changing feedback loop aspect if extension is not supported prevents failed pipeline compiles (or seemingly incompatible) --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 7 ++++++- src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs | 2 ++ src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 9a46cb943..a302f730f 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1721,6 +1721,11 @@ namespace Ryujinx.Graphics.Vulkan [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool UpdateFeedbackLoop() { + if (!Gd.Capabilities.SupportsAttachmentFeedbackLoop) + { + return false; + } + List hazards = _descriptorSetUpdater.FeedbackLoopHazards; if ((hazards?.Count ?? 0) > 0) @@ -1765,7 +1770,7 @@ namespace Ryujinx.Graphics.Vulkan } // Stencil test being enabled doesn't necessarily mean a write, but it's not critical to check. - _passWritesDepthStencil |= (_newState.DepthTestEnable && _newState.DepthWriteEnable) || _newState.StencilTestEnable; + _passWritesDepthStencil |= _supportExtDynamic ? (DynamicState.DepthTestEnable && DynamicState.DepthWriteEnable) || _newState.StencilTestEnable : (_newState.DepthTestEnable && _newState.DepthWriteEnable) || _newState.StencilTestEnable; } private bool RecreateGraphicsPipelineIfNeeded() diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 822838f00..36bd1ff45 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -166,6 +166,8 @@ namespace Ryujinx.Graphics.Vulkan pipeline.DepthClampEnable = state.DepthClampEnable; + pipeline.FeedbackLoopAspects = FeedbackLoopAspects.None; + pipeline.DepthMode = state.DepthMode == DepthMode.MinusOneToOne; pipeline.HasDepthStencil = state.DepthStencilEnable; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index facb221ab..f447d0f20 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -273,6 +273,8 @@ namespace Ryujinx.Graphics.Vulkan PolygonMode = PolygonMode.Fill; DepthBoundsTestEnable = false; + FeedbackLoopAspects = FeedbackLoopAspects.None; + _supportsExtDynamicState = supportsExtDynamicState; _supportsExtDynamicState2 = extendedDynamicState2; From 5e86d5e17884ac0f030850a74c4dcb6ce43f142a Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 1 Sep 2024 21:33:05 -0700 Subject: [PATCH 100/132] There will still be an issue with extension is supported and dynmaic state is not --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 +- .../PipelineConverter.cs | 2 +- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 18 ++++++++++-------- .../ShaderCollection.cs | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index a302f730f..4fa591ced 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -134,7 +134,7 @@ namespace Ryujinx.Graphics.Vulkan _supportExtDynamic2 = gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2; - _newState.Initialize(_supportExtDynamic, gd.Capabilities.SupportsExtendedDynamicState2); + _newState.Initialize(gd.Capabilities); } public void Initialize() diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 36bd1ff45..c45b0fd13 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -159,7 +159,7 @@ namespace Ryujinx.Graphics.Vulkan var extendedDynamicState = gd.Capabilities.SupportsExtendedDynamicState; PipelineState pipeline = new(); - pipeline.Initialize(extendedDynamicState, extendedDynamicState2); + pipeline.Initialize(gd.Capabilities); // It is assumed that Dynamic State is enabled when this conversion is used. pipeline.DepthBoundsTestEnable = false; // Not implemented. diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index f447d0f20..0fb70f92a 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -255,10 +255,10 @@ namespace Ryujinx.Graphics.Vulkan private bool _supportsExtDynamicState; private PhysicalDeviceExtendedDynamicState2FeaturesEXT _supportsExtDynamicState2; + private bool _supportsFeedBackLoopDynamicState; - public void Initialize(bool supportsExtDynamicState, - PhysicalDeviceExtendedDynamicState2FeaturesEXT extendedDynamicState2) + public void Initialize(HardwareCapabilities capabilities) { HasTessellationControlShader = false; Stages = new NativeArray(Constants.MaxShaderStages); @@ -273,10 +273,14 @@ namespace Ryujinx.Graphics.Vulkan PolygonMode = PolygonMode.Fill; DepthBoundsTestEnable = false; - FeedbackLoopAspects = FeedbackLoopAspects.None; + _supportsExtDynamicState = capabilities.SupportsExtendedDynamicState; + _supportsExtDynamicState2 = capabilities.SupportsExtendedDynamicState2; + _supportsFeedBackLoopDynamicState = capabilities.SupportsDynamicAttachmentFeedbackLoop; - _supportsExtDynamicState = supportsExtDynamicState; - _supportsExtDynamicState2 = extendedDynamicState2; + if (_supportsFeedBackLoopDynamicState || !capabilities.SupportsAttachmentFeedbackLoop) + { + FeedbackLoopAspects = FeedbackLoopAspects.None; + } if (_supportsExtDynamicState) { @@ -577,8 +581,6 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.PNext = &colorBlendAdvancedState; } - bool supportsFeedbackLoopDynamicState = gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop; - DynamicState* dynamicStates = stackalloc DynamicState[MaxDynamicStatesCount]; uint dynamicStatesCount = 7; @@ -633,7 +635,7 @@ namespace Ryujinx.Graphics.Vulkan } } - if (supportsFeedbackLoopDynamicState) + if (_supportsFeedBackLoopDynamicState) { dynamicStates[dynamicStatesCount++] = DynamicState.AttachmentFeedbackLoopEnableExt; } diff --git a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs index 232a093b8..e670d840b 100644 --- a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs +++ b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs @@ -531,7 +531,7 @@ namespace Ryujinx.Graphics.Vulkan public void CreateBackgroundComputePipeline() { PipelineState pipeline = new(); - pipeline.Initialize(_gd.Capabilities.SupportsExtendedDynamicState, _gd.Capabilities.SupportsExtendedDynamicState2); + pipeline.Initialize(_gd.Capabilities); pipeline.Stages[0] = _shaders[0].GetInfo(); pipeline.StagesCount = 1; From a7409e6fba8e3f78b2fe8cc356d3ad21f13423ce Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 2 Sep 2024 12:40:29 -0700 Subject: [PATCH 101/132] Some missed changes --- src/Ryujinx.Graphics.Vulkan/EnumConversion.cs | 4 +-- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 27 +++++++++---------- .../PipelineConverter.cs | 5 +++- .../PipelineDynamicState.cs | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs b/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs index 7e5207d39..babcf992c 100644 --- a/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs +++ b/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs @@ -323,9 +323,9 @@ namespace Ryujinx.Graphics.Vulkan PrimitiveTopology.TriangleStrip or PrimitiveTopology.TriangleFan or PrimitiveTopology.TriangleListWithAdjacency or - PrimitiveTopology.TriangleStripWithAdjacency => PrimitiveTopology.TriangleList, + PrimitiveTopology.TriangleStripWithAdjacency => PrimitiveTopology.TriangleStrip, PrimitiveTopology.PatchList => PrimitiveTopology.PatchList, - _ => LogInvalidAndReturn(topology, nameof(PrimitiveTopology), PrimitiveTopology.TriangleList), + _ => LogInvalidAndReturn(topology, nameof(PrimitiveTopology), PrimitiveTopology.TriangleStrip), }; } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 4fa591ced..cb00aaf18 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -644,7 +644,7 @@ namespace Ryujinx.Graphics.Vulkan var oldStencilTestEnable = _supportExtDynamic ? DynamicState.StencilTestEnable : _newState.StencilTestEnable; var oldDepthTestEnable = _supportExtDynamic ? DynamicState.DepthTestEnable : _newState.DepthTestEnable; var oldDepthWriteEnable = _supportExtDynamic ? DynamicState.DepthWriteEnable : _newState.DepthWriteEnable; - var oldTopology = _supportExtDynamic ? DynamicState._topology : _newState.Topology; + var oldTopology = _newState.Topology; var oldViewports = DynamicState.Viewports; var oldViewportsCount = _supportExtDynamic ? DynamicState.ViewportsCount : _newState.ViewportsCount; @@ -825,11 +825,6 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) { - if (factor == 0 && units == 0 && !_newState.DepthBiasEnable && !_supportExtDynamic2) - { - return; - } - bool depthBiasEnable = (enables != 0) && (factor != 0 && units != 0); bool changed = false; @@ -882,7 +877,10 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { DynamicState.SetDepthTestBool(depthTest.TestEnable, depthTest.WriteEnable); - DynamicState.SetDepthTestCompareOp(depthTest.TestEnable ? depthTest.Func.Convert() : default); + if (depthTest.TestEnable) + { + DynamicState.SetDepthTestCompareOp(depthTest.Func.Convert()); + } } else { @@ -899,7 +897,7 @@ namespace Ryujinx.Graphics.Vulkan { if (_supportExtDynamic) { - DynamicState.SetCullMode(enable ? face.Convert() : default); + DynamicState.SetCullMode(enable ? face.Convert() : CullModeFlags.None); } else { @@ -977,7 +975,11 @@ namespace Ryujinx.Graphics.Vulkan if (Gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) { - DynamicState.SetLogicOp(logicOpEnable ? op.Convert() : default); + if (logicOpEnable) + { + DynamicState.SetLogicOp(op.Convert()); + } + } else { @@ -998,11 +1000,6 @@ namespace Ryujinx.Graphics.Vulkan public void SetPatchParameters(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel) { - if (vertices == 0 || vertices > Gd.Capabilities.MaxTessellationPatchSize) - { - return; - } - if (Gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { DynamicState.SetPatchControlPoints((uint)vertices); @@ -1770,7 +1767,7 @@ namespace Ryujinx.Graphics.Vulkan } // Stencil test being enabled doesn't necessarily mean a write, but it's not critical to check. - _passWritesDepthStencil |= _supportExtDynamic ? (DynamicState.DepthTestEnable && DynamicState.DepthWriteEnable) || _newState.StencilTestEnable : (_newState.DepthTestEnable && _newState.DepthWriteEnable) || _newState.StencilTestEnable; + _passWritesDepthStencil |= _supportExtDynamic ? (DynamicState.DepthTestEnable && DynamicState.DepthWriteEnable) || DynamicState.StencilTestEnable : (_newState.DepthTestEnable && _newState.DepthWriteEnable) || _newState.StencilTestEnable; } private bool RecreateGraphicsPipelineIfNeeded() diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index c45b0fd13..f1423fd09 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -166,7 +166,10 @@ namespace Ryujinx.Graphics.Vulkan pipeline.DepthClampEnable = state.DepthClampEnable; - pipeline.FeedbackLoopAspects = FeedbackLoopAspects.None; + if (gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop || !gd.Capabilities.SupportsAttachmentFeedbackLoop) + { + pipeline.FeedbackLoopAspects = FeedbackLoopAspects.None; + } pipeline.DepthMode = state.DepthMode == DepthMode.MinusOneToOne; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 1e252cdef..66dfc1b3e 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.Vulkan private uint _patchControlPoints; - public PrimitiveTopology _topology; + private PrimitiveTopology _topology; private bool _primitiveRestartEnable; From 91c3ac27010dad8c6ac5cba9fad591003c5c9684 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 2 Sep 2024 14:37:29 -0700 Subject: [PATCH 102/132] Revert a change --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 9 +-------- src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs | 9 +++++---- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 7 ++++--- src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs | 6 +----- 4 files changed, 11 insertions(+), 20 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index cb00aaf18..406372dc8 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1080,8 +1080,6 @@ namespace Ryujinx.Graphics.Vulkan _newState.HasTessellationControlShader = internalProgram.HasTessellationControlShader; _newState.StagesCount = (uint)stages.Length; - _newState.Topology = internalProgram.ShaderTopology; - stages.CopyTo(_newState.Stages.AsSpan()[..stages.Length]); SignalStateChange(); @@ -1702,7 +1700,7 @@ namespace Ryujinx.Graphics.Vulkan { DynamicState.SetFeedbackLoop(aspects); } - else + else if (Gd.Capabilities.SupportsAttachmentFeedbackLoop) { _newState.FeedbackLoopAspects = aspects; } @@ -1718,11 +1716,6 @@ namespace Ryujinx.Graphics.Vulkan [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool UpdateFeedbackLoop() { - if (!Gd.Capabilities.SupportsAttachmentFeedbackLoop) - { - return false; - } - List hazards = _descriptorSetUpdater.FeedbackLoopHazards; if ((hazards?.Count ?? 0) > 0) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index f1423fd09..27f1c047b 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -153,13 +153,15 @@ namespace Ryujinx.Graphics.Vulkan 0); } - public static PipelineState ToVulkanPipelineState(this ProgramPipelineState state, VulkanRenderer gd, bool hasTCS) + public static PipelineState ToVulkanPipelineState(this ProgramPipelineState state, VulkanRenderer gd) { var extendedDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2; var extendedDynamicState = gd.Capabilities.SupportsExtendedDynamicState; + var topology = extendedDynamicState ? gd.TopologyRemap(state.Topology).Convert().ConvertToClass() : gd.TopologyRemap(state.Topology).Convert(); + PipelineState pipeline = new(); - pipeline.Initialize(gd.Capabilities); + pipeline.Initialize(gd.Capabilities, topology); // It is assumed that Dynamic State is enabled when this conversion is used. pipeline.DepthBoundsTestEnable = false; // Not implemented. @@ -225,8 +227,7 @@ namespace Ryujinx.Graphics.Vulkan pipeline.StencilBackDepthFailOp = extendedDynamicState ? 0 : state.StencilTest.BackDpFail.Convert(); pipeline.StencilBackCompareOp = extendedDynamicState ? 0 : state.StencilTest.BackFunc.Convert(); - var topology = hasTCS ? PrimitiveTopology.Patches : state.Topology; - pipeline.Topology = extendedDynamicState ? gd.TopologyRemap(topology).Convert().ConvertToClass() : gd.TopologyRemap(topology).Convert(); + pipeline.Topology = topology; int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount); int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 0fb70f92a..8739aaec5 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -258,7 +258,7 @@ namespace Ryujinx.Graphics.Vulkan private bool _supportsFeedBackLoopDynamicState; - public void Initialize(HardwareCapabilities capabilities) + public void Initialize(HardwareCapabilities capabilities, PrimitiveTopology topology = default) { HasTessellationControlShader = false; Stages = new NativeArray(Constants.MaxShaderStages); @@ -277,13 +277,14 @@ namespace Ryujinx.Graphics.Vulkan _supportsExtDynamicState2 = capabilities.SupportsExtendedDynamicState2; _supportsFeedBackLoopDynamicState = capabilities.SupportsDynamicAttachmentFeedbackLoop; - if (_supportsFeedBackLoopDynamicState || !capabilities.SupportsAttachmentFeedbackLoop) + if (!capabilities.SupportsAttachmentFeedbackLoop) { FeedbackLoopAspects = FeedbackLoopAspects.None; } if (_supportsExtDynamicState) { + Topology = topology; StencilFrontFailOp = 0; StencilFrontPassOp = 0; StencilFrontDepthFailOp = 0; @@ -649,7 +650,7 @@ namespace Ryujinx.Graphics.Vulkan PipelineCreateFlags flags = 0; - if (gd.Capabilities.SupportsAttachmentFeedbackLoop) + if (gd.Capabilities.SupportsAttachmentFeedbackLoop && !_supportsFeedBackLoopDynamicState) { FeedbackLoopAspects aspects = FeedbackLoopAspects; diff --git a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs index e670d840b..ae4a2faac 100644 --- a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs +++ b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs @@ -24,8 +24,6 @@ namespace Ryujinx.Graphics.Vulkan public bool IsCompute { get; } public bool HasTessellationControlShader => (Stages & (1u << 3)) != 0; - public PrimitiveTopology ShaderTopology; - public bool UpdateTexturesWithoutTemplate { get; } public uint Stages { get; } @@ -552,9 +550,7 @@ namespace Ryujinx.Graphics.Vulkan // The active attachment formats have been provided by the abstraction layer. var renderPass = CreateDummyRenderPass(); - PipelineState pipeline = _state.ToVulkanPipelineState(_gd, HasTessellationControlShader); - - ShaderTopology = pipeline.Topology; + PipelineState pipeline = _state.ToVulkanPipelineState(_gd); // Copy the shader stage info to the pipeline. var stages = pipeline.Stages.AsSpan(); From 1fa1c7b01d47d2cc69955ef32eb1dafa98b12489 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 2 Sep 2024 20:18:24 -0700 Subject: [PATCH 103/132] Need to test this on Windows --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 11 ++++------- src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs | 8 ++++---- src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs | 2 -- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 10 ++++++++-- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 406372dc8..5d00a30ca 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -674,9 +674,9 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { - if (oldTopology.ConvertToClass() != _newState.Topology.ConvertToClass()) + if (oldTopology != _newState.Topology.ConvertToClass()) { - _newState.Topology = oldTopology.ConvertToClass(); + _newState.Topology = oldTopology; } DynamicState.SetCullMode(oldCullMode); @@ -971,7 +971,7 @@ namespace Ryujinx.Graphics.Vulkan // so we need to force disable them here. bool logicOpEnable = enable && (Gd.Vendor == Vendor.Nvidia || _newState.Internal.LogicOpsAllowed); - _newState.LogicOpEnable = logicOpEnable; + _newState.LogicOpEnable = enable; if (Gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) { @@ -979,7 +979,6 @@ namespace Ryujinx.Graphics.Vulkan { DynamicState.SetLogicOp(op.Convert()); } - } else { @@ -1041,8 +1040,6 @@ namespace Ryujinx.Graphics.Vulkan public void SetPrimitiveTopology(PrimitiveTopology topology) { - topology = _newState.HasTessellationControlShader ? PrimitiveTopology.Patches : topology; - _topology = topology; var vkTopology = Gd.TopologyRemap(topology).Convert(); @@ -1402,7 +1399,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.Internal.VertexBindingDescriptions[descriptorIndex] = new VertexInputBindingDescription( (uint)binding, - _supportExtDynamic && !Gd.IsMoltenVk ? 0 : (uint)vertexBuffer.Stride, + _supportExtDynamic && !Gd.IsMoltenVk ? default : (uint)vertexBuffer.Stride, inputRate); int vbSize = vertexBuffer.Buffer.Size; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 27f1c047b..4c1c1dad2 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -229,6 +229,8 @@ namespace Ryujinx.Graphics.Vulkan pipeline.Topology = topology; + pipeline.LogicOpEnable = state.LogicOpEnable; + int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount); int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount); @@ -272,7 +274,7 @@ namespace Ryujinx.Graphics.Vulkan // TODO: Support divisor > 1 pipeline.Internal.VertexBindingDescriptions[descriptorIndex++] = new VertexInputBindingDescription( (uint)i + 1, - extendedDynamicState && !gd.IsMoltenVk ? 0 : (uint)alignedStride, + extendedDynamicState && !gd.IsMoltenVk ? default : (uint)alignedStride, inputRate); } } @@ -336,9 +338,7 @@ namespace Ryujinx.Graphics.Vulkan pipeline.Internal.LogicOpsAllowed = attachmentCount == 0 || !allFormatsFloatOrSrgb; bool logicOpEnable = state.LogicOpEnable && - (gd.Vendor == Vendor.Nvidia || (attachmentCount == 0 || !allFormatsFloatOrSrgb)); - - pipeline.LogicOpEnable = logicOpEnable; + (gd.Vendor == Vendor.Nvidia || pipeline.Internal.LogicOpsAllowed); if (!extendedDynamicState2.ExtendedDynamicState2LogicOp) { diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 66dfc1b3e..8a3fa7f82 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -276,8 +276,6 @@ namespace Ryujinx.Graphics.Vulkan public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) { - _ = gd.Api; - if (_dirty.HasFlag(DirtyFlags.Blend)) { RecordBlend(gd.Api, commandBuffer); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 8739aaec5..a3b60e74c 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -420,10 +420,12 @@ namespace Ryujinx.Graphics.Vulkan PVertexBindingDescriptions = pVertexBindingDescriptions, }; + var topology = HasTessellationControlShader ? PrimitiveTopology.PatchList : Topology; + var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, - Topology = Topology, + Topology = topology, }; PipelineTessellationStateCreateInfo tessellationState; @@ -554,12 +556,16 @@ namespace Ryujinx.Graphics.Vulkan } } + // Vendors other than NVIDIA have a bug where it enables logical operations even for float formats, + // so we need to force disable them here. + bool logicOpEnable = LogicOpEnable && (gd.Vendor == Vendor.Nvidia || Internal.LogicOpsAllowed); + var colorBlendState = new PipelineColorBlendStateCreateInfo { SType = StructureType.PipelineColorBlendStateCreateInfo, AttachmentCount = ColorBlendAttachmentStateCount, PAttachments = pColorBlendAttachmentState, - LogicOpEnable = LogicOpEnable, + LogicOpEnable = logicOpEnable, }; if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) From 2846e88a5df4b06055c42d31a51d50febc459c75 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 4 Sep 2024 13:50:31 -0700 Subject: [PATCH 104/132] Clean up and some housekeeping --- .../ProgramPipelineState.cs | 4 +- .../Engine/Threed/StateUpdater.cs | 7 +- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 41 ++++---- .../PipelineConverter.cs | 99 +++++++++---------- .../PipelineDynamicState.cs | 20 ++-- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 32 +++--- 6 files changed, 99 insertions(+), 104 deletions(-) diff --git a/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs b/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs index 6e80e3581..fc6e16267 100644 --- a/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs +++ b/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs @@ -55,7 +55,9 @@ namespace Ryujinx.Graphics.GAL public PolygonModeMask BiasEnable; - public float LineWidth; + public bool AlphaToCoverageEnable; + public bool AlphaToOneEnable; + // TODO: Polygon mode. public bool DepthClampEnable; public bool RasterizerDiscard; diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs index 1e8fe5c69..12b305728 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs @@ -709,8 +709,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed { DepthTestDescriptor descriptor = new( _state.State.DepthTestEnable, - _state.State.DepthWriteEnable, - _state.State.DepthTestFunc); + _state.State.DepthWriteEnable && _state.State.DepthTestEnable, + _state.State.DepthTestEnable ? _state.State.DepthTestFunc : default); _pipeline.DepthTest = descriptor; _context.Renderer.Pipeline.SetDepthTest(descriptor); @@ -1029,7 +1029,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed float width = _state.State.LineWidthSmooth; bool smooth = _state.State.LineSmoothEnable; - _pipeline.LineWidth = width; _context.Renderer.Pipeline.SetLineParameters(width, smooth); } @@ -1391,6 +1390,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed bool alphaToCoverageEnable = (_state.State.MultisampleControl & 1) != 0; bool alphaToOneEnable = (_state.State.MultisampleControl & 0x10) != 0; + _pipeline.AlphaToCoverageEnable = alphaToCoverageEnable; + _pipeline.AlphaToOneEnable = alphaToOneEnable; _context.Renderer.Pipeline.SetMultisampleState(new MultisampleDescriptor( alphaToCoverageEnable, _state.State.AlphaToCoverageDitherEnable, diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 5d00a30ca..d5a1e9855 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -644,7 +644,8 @@ namespace Ryujinx.Graphics.Vulkan 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 oldTopology = _supportExtDynamic ? DynamicState.Topology : _newState.Topology; + var oldTopologyClass = _newState.Topology; var oldViewports = DynamicState.Viewports; var oldViewportsCount = _supportExtDynamic ? DynamicState.ViewportsCount : _newState.ViewportsCount; @@ -674,9 +675,9 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { - if (oldTopology != _newState.Topology.ConvertToClass()) + if (oldTopologyClass != _newState.Topology) { - _newState.Topology = oldTopology; + _newState.Topology = oldTopologyClass; } DynamicState.SetCullMode(oldCullMode); @@ -885,8 +886,8 @@ namespace Ryujinx.Graphics.Vulkan else { _newState.DepthTestEnable = depthTest.TestEnable; - _newState.DepthWriteEnable = depthTest.WriteEnable && depthTest.TestEnable; - _newState.DepthCompareOp = depthTest.TestEnable ? depthTest.Func.Convert() : default; + _newState.DepthWriteEnable = depthTest.WriteEnable; + _newState.DepthCompareOp = depthTest.Func.Convert(); } UpdatePassDepthStencil(); @@ -901,7 +902,7 @@ namespace Ryujinx.Graphics.Vulkan } else { - _newState.CullMode = enable ? face.Convert() : default; + _newState.CullMode = enable ? face.Convert() : CullModeFlags.None; } SignalStateChange(); @@ -1048,9 +1049,9 @@ namespace Ryujinx.Graphics.Vulkan { var newTopologyClass = vkTopology.ConvertToClass(); - if ((_newState.Topology.ConvertToClass() != newTopologyClass)) + if ((_newState.Topology != newTopologyClass)) { - _newState.Topology = vkTopology.ConvertToClass(); + _newState.Topology = newTopologyClass; } DynamicState.SetPrimitiveTopology(vkTopology); @@ -1075,7 +1076,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.PipelineLayout = internalProgram.PipelineLayout; _newState.HasTessellationControlShader = internalProgram.HasTessellationControlShader; - _newState.StagesCount = (uint)stages.Length; + _newState.StagesCount = internalProgram.IsCompute ? 1 : (uint)stages.Length; stages.CopyTo(_newState.Stages.AsSpan()[..stages.Length]); @@ -1196,6 +1197,13 @@ namespace Ryujinx.Graphics.Vulkan ClearScissor = regions[0]; } + if (!_supportExtDynamic) + { + _newState.ScissorsCount = (uint)count; + } + + DynamicState.ScissorsCount = count; + for (int i = 0; i < count; i++) { var region = regions[i]; @@ -1205,12 +1213,6 @@ namespace Ryujinx.Graphics.Vulkan DynamicState.SetScissor(i, new Rect2D(offset, extent)); } - DynamicState.ScissorsCount = count; - - if (!_supportExtDynamic) - { - _newState.ScissorsCount = (uint)count; - } SignalStateChange(); } @@ -1473,6 +1475,11 @@ namespace Ryujinx.Graphics.Vulkan return Math.Clamp(value, 0f, 1f); } + if (!_supportExtDynamic) + { + _newState.ViewportsCount = (uint)count; + } + DynamicState.ViewportsCount = (uint)count; for (int i = 0; i < count; i++) @@ -1488,10 +1495,6 @@ namespace Ryujinx.Graphics.Vulkan Clamp(viewport.DepthFar))); } - if (!_supportExtDynamic) - { - _newState.ViewportsCount = (uint)count; - } SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 4c1c1dad2..870a3fd11 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -158,20 +158,16 @@ namespace Ryujinx.Graphics.Vulkan var extendedDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2; var extendedDynamicState = gd.Capabilities.SupportsExtendedDynamicState; - var topology = extendedDynamicState ? gd.TopologyRemap(state.Topology).Convert().ConvertToClass() : gd.TopologyRemap(state.Topology).Convert(); - PipelineState pipeline = new(); - pipeline.Initialize(gd.Capabilities, topology); + pipeline.Initialize(gd.Capabilities); // It is assumed that Dynamic State is enabled when this conversion is used. pipeline.DepthBoundsTestEnable = false; // Not implemented. pipeline.DepthClampEnable = state.DepthClampEnable; - if (gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop || !gd.Capabilities.SupportsAttachmentFeedbackLoop) - { - pipeline.FeedbackLoopAspects = FeedbackLoopAspects.None; - } + pipeline.AlphaToCoverageEnable = state.AlphaToCoverageEnable; + pipeline.AlphaToOneEnable = state.AlphaToOneEnable; pipeline.DepthMode = state.DepthMode == DepthMode.MinusOneToOne; @@ -179,55 +175,56 @@ namespace Ryujinx.Graphics.Vulkan pipeline.PolygonMode = PolygonMode.Fill; // Not implemented. - pipeline.PrimitiveRestartEnable = extendedDynamicState2.ExtendedDynamicState2 ? false : state.PrimitiveRestartEnable; - pipeline.RasterizerDiscardEnable = extendedDynamicState2.ExtendedDynamicState2 ? false : state.RasterizerDiscard; - pipeline.DepthBiasEnable = extendedDynamicState2.ExtendedDynamicState2 ? false : ((state.BiasEnable != 0) && - (state.DepthBiasFactor != 0 && state.DepthBiasUnits != 0)); - - pipeline.PatchControlPoints = extendedDynamicState2.ExtendedDynamicState2PatchControlPoints ? 0 : state.PatchControlPoints; - - pipeline.SamplesCount = (uint)state.SamplesCount; - - pipeline.DepthTestEnable = !extendedDynamicState && state.DepthTest.TestEnable; - pipeline.DepthWriteEnable = !extendedDynamicState && state.DepthTest.WriteEnable && state.DepthTest.TestEnable; + pipeline.Topology = extendedDynamicState ? gd.TopologyRemap(state.Topology).Convert().ConvertToClass() : gd.TopologyRemap(state.Topology).Convert(); if (!extendedDynamicState) { - pipeline.DepthCompareOp = state.DepthTest.TestEnable ? state.DepthTest.Func.Convert() : default; - pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : default; + pipeline.DepthCompareOp = state.DepthTest.Func.Convert(); + pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None; + + pipeline.DepthTestEnable = state.DepthTest.TestEnable; + pipeline.DepthWriteEnable = state.DepthTest.WriteEnable; + + pipeline.FrontFace = state.FrontFace.Convert(); + + if (gd.Capabilities.SupportsMultiView) + { + pipeline.ScissorsCount = Constants.MaxViewports; + pipeline.ViewportsCount = Constants.MaxViewports; + } + else + { + pipeline.ScissorsCount = 1; + pipeline.ViewportsCount = 1; + } + + pipeline.StencilTestEnable = state.StencilTest.TestEnable; + + pipeline.StencilFrontFailOp = state.StencilTest.FrontSFail.Convert(); + pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert(); + pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert(); + pipeline.StencilFrontCompareOp = state.StencilTest.FrontFunc.Convert(); + + pipeline.StencilBackFailOp = state.StencilTest.BackSFail.Convert(); + pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert(); + pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert(); + pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert(); } - else + + if (!extendedDynamicState2.ExtendedDynamicState2) { - pipeline.DepthCompareOp = 0; - pipeline.CullMode = 0; + pipeline.PrimitiveRestartEnable = state.PrimitiveRestartEnable; + pipeline.RasterizerDiscardEnable = state.RasterizerDiscard; + pipeline.DepthBiasEnable = ((state.BiasEnable != 0) && + (state.DepthBiasFactor != 0 && state.DepthBiasUnits != 0)); } - pipeline.FrontFace = extendedDynamicState ? 0 : state.FrontFace.Convert(); - - if (gd.Capabilities.SupportsMultiView) + if (!extendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { - pipeline.ScissorsCount = (uint)(extendedDynamicState ? 0 : Constants.MaxViewports); - pipeline.ViewportsCount = (uint)(extendedDynamicState ? 0 : Constants.MaxViewports); - } - else - { - pipeline.ScissorsCount = (uint)(extendedDynamicState ? 0 : 1); - pipeline.ViewportsCount = (uint)(extendedDynamicState ? 0 : 1); + pipeline.PatchControlPoints = state.PatchControlPoints; } - pipeline.StencilTestEnable = !extendedDynamicState && state.StencilTest.TestEnable; - - pipeline.StencilFrontFailOp = extendedDynamicState ? 0 : state.StencilTest.FrontSFail.Convert(); - pipeline.StencilFrontPassOp = extendedDynamicState ? 0 : state.StencilTest.FrontDpPass.Convert(); - pipeline.StencilFrontDepthFailOp = extendedDynamicState ? 0 : state.StencilTest.FrontDpFail.Convert(); - pipeline.StencilFrontCompareOp = extendedDynamicState ? 0 : state.StencilTest.FrontFunc.Convert(); - - pipeline.StencilBackFailOp = extendedDynamicState ? 0 : state.StencilTest.BackSFail.Convert(); - pipeline.StencilBackPassOp = extendedDynamicState ? 0 : state.StencilTest.BackDpPass.Convert(); - pipeline.StencilBackDepthFailOp = extendedDynamicState ? 0 : state.StencilTest.BackDpFail.Convert(); - pipeline.StencilBackCompareOp = extendedDynamicState ? 0 : state.StencilTest.BackFunc.Convert(); - - pipeline.Topology = topology; + pipeline.SamplesCount = (uint)state.SamplesCount; pipeline.LogicOpEnable = state.LogicOpEnable; @@ -337,17 +334,13 @@ namespace Ryujinx.Graphics.Vulkan pipeline.Internal.AttachmentIntegerFormatMask = attachmentIntegerFormatMask; pipeline.Internal.LogicOpsAllowed = attachmentCount == 0 || !allFormatsFloatOrSrgb; - bool logicOpEnable = state.LogicOpEnable && - (gd.Vendor == Vendor.Nvidia || pipeline.Internal.LogicOpsAllowed); - if (!extendedDynamicState2.ExtendedDynamicState2LogicOp) { + bool logicOpEnable = state.LogicOpEnable && + (gd.Vendor == Vendor.Nvidia || pipeline.Internal.LogicOpsAllowed); + pipeline.LogicOp = logicOpEnable ? state.LogicOp.Convert() : default; } - else - { - pipeline.LogicOp = 0; - } return pipeline; } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 8a3fa7f82..3b6701607 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.Vulkan private uint _patchControlPoints; - private PrimitiveTopology _topology; + public PrimitiveTopology Topology; private bool _primitiveRestartEnable; @@ -122,7 +122,7 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthTestBool(bool testEnable, bool writeEnable) { DepthTestEnable = testEnable; - DepthWriteEnable = writeEnable && testEnable; + DepthWriteEnable = writeEnable; _dirty |= DirtyFlags.DepthTestBool; } @@ -228,7 +228,7 @@ namespace Ryujinx.Graphics.Vulkan public void SetPrimitiveTopology(PrimitiveTopology primitiveTopology) { - _topology = primitiveTopology; + Topology = primitiveTopology; _dirty |= DirtyFlags.PrimitiveTopology; } @@ -478,15 +478,15 @@ namespace Ryujinx.Graphics.Vulkan if (gd.Capabilities.SupportsPrimitiveTopologyListRestart) { topologySupportsRestart = gd.Capabilities.SupportsPrimitiveTopologyPatchListRestart || - _topology != PrimitiveTopology.PatchList; + Topology != PrimitiveTopology.PatchList; } else { - topologySupportsRestart = _topology == PrimitiveTopology.LineStrip || - _topology == PrimitiveTopology.TriangleStrip || - _topology == PrimitiveTopology.TriangleFan || - _topology == PrimitiveTopology.LineStripWithAdjacency || - _topology == PrimitiveTopology.TriangleStripWithAdjacency; + topologySupportsRestart = Topology == PrimitiveTopology.LineStrip || + Topology == PrimitiveTopology.TriangleStrip || + Topology == PrimitiveTopology.TriangleFan || + Topology == PrimitiveTopology.LineStripWithAdjacency || + Topology == PrimitiveTopology.TriangleStripWithAdjacency; } primitiveRestartEnable &= topologySupportsRestart; @@ -502,7 +502,7 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordPrimitiveTopology(VulkanRenderer gd, CommandBuffer commandBuffer) { - gd.ExtendedDynamicStateApi.CmdSetPrimitiveTopology(commandBuffer, _topology); + gd.ExtendedDynamicStateApi.CmdSetPrimitiveTopology(commandBuffer, Topology); } private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index a3b60e74c..b25cdccd5 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -258,7 +258,7 @@ namespace Ryujinx.Graphics.Vulkan private bool _supportsFeedBackLoopDynamicState; - public void Initialize(HardwareCapabilities capabilities, PrimitiveTopology topology = default) + public void Initialize(HardwareCapabilities capabilities) { HasTessellationControlShader = false; Stages = new NativeArray(Constants.MaxShaderStages); @@ -267,7 +267,6 @@ namespace Ryujinx.Graphics.Vulkan AdvancedBlendDstPreMultiplied = true; AdvancedBlendOverlap = BlendOverlapEXT.UncorrelatedExt; - SamplesCount = 1; DepthMode = true; PolygonMode = PolygonMode.Fill; @@ -277,14 +276,8 @@ namespace Ryujinx.Graphics.Vulkan _supportsExtDynamicState2 = capabilities.SupportsExtendedDynamicState2; _supportsFeedBackLoopDynamicState = capabilities.SupportsDynamicAttachmentFeedbackLoop; - if (!capabilities.SupportsAttachmentFeedbackLoop) - { - FeedbackLoopAspects = FeedbackLoopAspects.None; - } - if (_supportsExtDynamicState) { - Topology = topology; StencilFrontFailOp = 0; StencilFrontPassOp = 0; StencilFrontDepthFailOp = 0; @@ -312,16 +305,16 @@ namespace Ryujinx.Graphics.Vulkan PrimitiveRestartEnable = false; DepthBiasEnable = false; RasterizerDiscardEnable = false; - } - if (_supportsExtDynamicState2.ExtendedDynamicState2LogicOp) - { - LogicOp = 0; - } + if (_supportsExtDynamicState2.ExtendedDynamicState2LogicOp) + { + LogicOp = 0; + } - if (_supportsExtDynamicState2.ExtendedDynamicState2PatchControlPoints) - { - PatchControlPoints = 0; + if (_supportsExtDynamicState2.ExtendedDynamicState2PatchControlPoints) + { + PatchControlPoints = 0; + } } } @@ -531,8 +524,11 @@ namespace Ryujinx.Graphics.Vulkan if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { - tessellationState.SType = StructureType.PipelineTessellationStateCreateInfo; - tessellationState.PatchControlPoints = PatchControlPoints; + tessellationState = new PipelineTessellationStateCreateInfo + { + SType = StructureType.PipelineTessellationStateCreateInfo, + PatchControlPoints = PatchControlPoints, + }; } uint blendEnables = 0; From 1cb35a42db2b384136ff8d029866c962bf1977f1 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Wed, 4 Sep 2024 20:01:10 -0700 Subject: [PATCH 105/132] Rework to reduce code duplication and possibility of error. Reduce number of pipelines? --- .../Engine/Threed/StateUpdater.cs | 4 +- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 13 +- .../PipelineConverter.cs | 17 +- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 176 ++++++++++-------- 4 files changed, 115 insertions(+), 95 deletions(-) diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs index 12b305728..153eef8b0 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs @@ -709,8 +709,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed { DepthTestDescriptor descriptor = new( _state.State.DepthTestEnable, - _state.State.DepthWriteEnable && _state.State.DepthTestEnable, - _state.State.DepthTestEnable ? _state.State.DepthTestFunc : default); + _state.State.DepthWriteEnable, + _state.State.DepthTestFunc); _pipeline.DepthTest = descriptor; _context.Renderer.Pipeline.SetDepthTest(descriptor); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index d5a1e9855..7bf4a346a 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Shader; using Silk.NET.Vulkan; @@ -675,9 +676,9 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { - if (oldTopologyClass != _newState.Topology) + if (oldTopologyClass != _newState.Topology.ConvertToClass()) { - _newState.Topology = oldTopologyClass; + _newState.Topology = oldTopology; } DynamicState.SetCullMode(oldCullMode); @@ -983,7 +984,7 @@ namespace Ryujinx.Graphics.Vulkan } else { - _newState.LogicOp = logicOpEnable ? op.Convert() : default; + _newState.LogicOp = op.Convert(); } SignalStateChange(); @@ -1049,9 +1050,9 @@ namespace Ryujinx.Graphics.Vulkan { var newTopologyClass = vkTopology.ConvertToClass(); - if ((_newState.Topology != newTopologyClass)) + if ((_newState.Topology.ConvertToClass() != newTopologyClass)) { - _newState.Topology = newTopologyClass; + _newState.Topology = vkTopology; } DynamicState.SetPrimitiveTopology(vkTopology); @@ -1401,7 +1402,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.Internal.VertexBindingDescriptions[descriptorIndex] = new VertexInputBindingDescription( (uint)binding, - _supportExtDynamic && !Gd.IsMoltenVk ? default : (uint)vertexBuffer.Stride, + (uint)vertexBuffer.Stride, inputRate); int vbSize = vertexBuffer.Buffer.Size; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 870a3fd11..fcc27c667 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -175,7 +175,7 @@ namespace Ryujinx.Graphics.Vulkan pipeline.PolygonMode = PolygonMode.Fill; // Not implemented. - pipeline.Topology = extendedDynamicState ? gd.TopologyRemap(state.Topology).Convert().ConvertToClass() : gd.TopologyRemap(state.Topology).Convert(); + pipeline.Topology = gd.TopologyRemap(state.Topology).Convert(); if (!extendedDynamicState) { @@ -219,6 +219,11 @@ namespace Ryujinx.Graphics.Vulkan (state.DepthBiasFactor != 0 && state.DepthBiasUnits != 0)); } + if (!extendedDynamicState2.ExtendedDynamicState2LogicOp) + { + pipeline.LogicOp = state.LogicOp.Convert(); + } + if (!extendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { pipeline.PatchControlPoints = state.PatchControlPoints; @@ -271,7 +276,7 @@ namespace Ryujinx.Graphics.Vulkan // TODO: Support divisor > 1 pipeline.Internal.VertexBindingDescriptions[descriptorIndex++] = new VertexInputBindingDescription( (uint)i + 1, - extendedDynamicState && !gd.IsMoltenVk ? default : (uint)alignedStride, + (uint)alignedStride, inputRate); } } @@ -334,14 +339,6 @@ namespace Ryujinx.Graphics.Vulkan pipeline.Internal.AttachmentIntegerFormatMask = attachmentIntegerFormatMask; pipeline.Internal.LogicOpsAllowed = attachmentCount == 0 || !allFormatsFloatOrSrgb; - if (!extendedDynamicState2.ExtendedDynamicState2LogicOp) - { - bool logicOpEnable = state.LogicOpEnable && - (gd.Vendor == Vendor.Nvidia || pipeline.Internal.LogicOpsAllowed); - - pipeline.LogicOp = logicOpEnable ? state.LogicOp.Convert() : default; - } - return pipeline; } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index b25cdccd5..ad9d2d657 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -256,6 +256,8 @@ namespace Ryujinx.Graphics.Vulkan private bool _supportsExtDynamicState; private PhysicalDeviceExtendedDynamicState2FeaturesEXT _supportsExtDynamicState2; private bool _supportsFeedBackLoopDynamicState; + private uint _blendEnables; + public void Initialize(HardwareCapabilities capabilities) @@ -297,7 +299,6 @@ namespace Ryujinx.Graphics.Vulkan DepthWriteEnable = false; DepthCompareOp = 0; StencilTestEnable = false; - } if (_supportsExtDynamicState2.ExtendedDynamicState2) @@ -368,6 +369,74 @@ namespace Ryujinx.Graphics.Vulkan return pipeline; } + + private void CheckCapability(VulkanRenderer gd) + { + // Vendors other than NVIDIA have a bug where it enables logical operations even for float formats, + // so we need to force disable them here. + LogicOpEnable = LogicOpEnable && (gd.Vendor == Vendor.Nvidia || Internal.LogicOpsAllowed); + + if (!_supportsExtDynamicState) + { + DepthWriteEnable = DepthWriteEnable && DepthTestEnable; + DepthCompareOp = DepthTestEnable ? DepthCompareOp : default; + } + + if (!_supportsExtDynamicState2.ExtendedDynamicState2LogicOp) + { + LogicOp = LogicOpEnable ? LogicOp : default; + } + + if (!_supportsExtDynamicState2.ExtendedDynamicState2) + { + 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; + } + + if (_supportsExtDynamicState) + { + Topology = Topology.ConvertToClass(); + } + + Topology = HasTessellationControlShader ? PrimitiveTopology.PatchList : Topology; + + if (gd.IsMoltenVk && Internal.AttachmentIntegerFormatMask != 0) + { + _blendEnables = 0; + + // Blend can't be enabled for integer formats, so let's make sure it is disabled. + uint attachmentIntegerFormatMask = Internal.AttachmentIntegerFormatMask; + + while (attachmentIntegerFormatMask != 0) + { + int i = BitOperations.TrailingZeroCount(attachmentIntegerFormatMask); + + if (Internal.ColorBlendAttachmentState[i].BlendEnable) + { + _blendEnables |= 1u << i; + } + + Internal.ColorBlendAttachmentState[i].BlendEnable = false; + attachmentIntegerFormatMask &= ~(1u << i); + } + } + } + public unsafe Auto CreateGraphicsPipeline( VulkanRenderer gd, Device device, @@ -376,6 +445,8 @@ namespace Ryujinx.Graphics.Vulkan RenderPass renderPass, bool throwOnError = false) { + CheckCapability(gd); + // Using patches topology without a tessellation shader is invalid. // If we find such a case, return null pipeline to skip the draw. if (Topology == PrimitiveTopology.PatchList && !HasTessellationControlShader) @@ -413,12 +484,10 @@ namespace Ryujinx.Graphics.Vulkan PVertexBindingDescriptions = pVertexBindingDescriptions, }; - var topology = HasTessellationControlShader ? PrimitiveTopology.PatchList : Topology; - var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, - Topology = topology, + Topology = Topology, }; PipelineTessellationStateCreateInfo tessellationState; @@ -497,27 +566,8 @@ namespace Ryujinx.Graphics.Vulkan if (!_supportsExtDynamicState2.ExtendedDynamicState2) { - 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; - - inputAssemblyState.PrimitiveRestartEnable = primitiveRestartEnable; + inputAssemblyState.PrimitiveRestartEnable = PrimitiveRestartEnable; rasterizationState.DepthBiasEnable = DepthBiasEnable; rasterizationState.RasterizerDiscardEnable = RasterizerDiscardEnable; } @@ -531,37 +581,12 @@ namespace Ryujinx.Graphics.Vulkan }; } - uint blendEnables = 0; - - if (isMoltenVk && Internal.AttachmentIntegerFormatMask != 0) - { - // Blend can't be enabled for integer formats, so let's make sure it is disabled. - uint attachmentIntegerFormatMask = Internal.AttachmentIntegerFormatMask; - - while (attachmentIntegerFormatMask != 0) - { - int i = BitOperations.TrailingZeroCount(attachmentIntegerFormatMask); - - if (Internal.ColorBlendAttachmentState[i].BlendEnable) - { - blendEnables |= 1u << i; - } - - Internal.ColorBlendAttachmentState[i].BlendEnable = false; - attachmentIntegerFormatMask &= ~(1u << i); - } - } - - // Vendors other than NVIDIA have a bug where it enables logical operations even for float formats, - // so we need to force disable them here. - bool logicOpEnable = LogicOpEnable && (gd.Vendor == Vendor.Nvidia || Internal.LogicOpsAllowed); - var colorBlendState = new PipelineColorBlendStateCreateInfo { SType = StructureType.PipelineColorBlendStateCreateInfo, AttachmentCount = ColorBlendAttachmentStateCount, PAttachments = pColorBlendAttachmentState, - LogicOpEnable = logicOpEnable, + LogicOpEnable = LogicOpEnable, }; if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) @@ -650,27 +675,9 @@ namespace Ryujinx.Graphics.Vulkan PDynamicStates = dynamicStates, }; - PipelineCreateFlags flags = 0; - - if (gd.Capabilities.SupportsAttachmentFeedbackLoop && !_supportsFeedBackLoopDynamicState) - { - FeedbackLoopAspects aspects = FeedbackLoopAspects; - - if ((aspects & FeedbackLoopAspects.Color) != 0) - { - flags |= PipelineCreateFlags.CreateColorAttachmentFeedbackLoopBitExt; - } - - if ((aspects & FeedbackLoopAspects.Depth) != 0) - { - flags |= PipelineCreateFlags.CreateDepthStencilAttachmentFeedbackLoopBitExt; - } - } - var pipelineCreateInfo = new GraphicsPipelineCreateInfo { SType = StructureType.GraphicsPipelineCreateInfo, - Flags = flags, StageCount = StagesCount, PStages = Stages.Pointer, PVertexInputState = &vertexInputState, @@ -685,6 +692,21 @@ namespace Ryujinx.Graphics.Vulkan RenderPass = renderPass, }; + if (gd.Capabilities.SupportsAttachmentFeedbackLoop && !_supportsFeedBackLoopDynamicState) + { + FeedbackLoopAspects aspects = FeedbackLoopAspects; + + if ((aspects & FeedbackLoopAspects.Color) != 0) + { + pipelineCreateInfo.Flags |= PipelineCreateFlags.CreateColorAttachmentFeedbackLoopBitExt; + } + + if ((aspects & FeedbackLoopAspects.Depth) != 0) + { + pipelineCreateInfo.Flags |= PipelineCreateFlags.CreateDepthStencilAttachmentFeedbackLoopBitExt; + } + } + if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { pipelineCreateInfo.PTessellationState = &tessellationState; @@ -702,21 +724,21 @@ namespace Ryujinx.Graphics.Vulkan return null; } - - // Restore previous blend enable values if we changed it. - while (blendEnables != 0) - { - int i = BitOperations.TrailingZeroCount(blendEnables); - - Internal.ColorBlendAttachmentState[i].BlendEnable = true; - blendEnables &= ~(1u << i); - } } pipeline = new Auto(new DisposablePipeline(gd.Api, device, pipelineHandle)); program.AddGraphicsPipeline(ref Internal, pipeline); + // Restore previous blend enable values if we changed it. + while (_blendEnables != 0) + { + int i = BitOperations.TrailingZeroCount(_blendEnables); + + Internal.ColorBlendAttachmentState[i].BlendEnable = true; + _blendEnables &= ~(1u << i); + } + return pipeline; } From 9bcc8374daa6df7bb07e419790aebc44afcfd022 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 7 Sep 2024 20:09:38 -0700 Subject: [PATCH 106/132] Only attempt to change topology class if needed --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index ad9d2d657..4b37fb9b0 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -408,7 +408,10 @@ namespace Ryujinx.Graphics.Vulkan PrimitiveRestartEnable &= topologySupportsRestart; } - if (_supportsExtDynamicState) + if (_supportsExtDynamicState && (Topology != PrimitiveTopology.LineList || + Topology != PrimitiveTopology.TriangleStrip || + Topology != PrimitiveTopology.PointList || + Topology != PrimitiveTopology.PatchList)) { Topology = Topology.ConvertToClass(); } From 381abda2c8dc85f007511fe9c90b22e260a6788e Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 9 Sep 2024 09:01:00 -0700 Subject: [PATCH 107/132] Primitive restart is enabled/disabled based on the original topology before its converted to its topology class, make this behavior consistent --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 7bf4a346a..f31f50b17 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -676,7 +676,7 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { - if (oldTopologyClass != _newState.Topology.ConvertToClass()) + if (oldTopologyClass != _newState.Topology) { _newState.Topology = oldTopology; } @@ -1048,9 +1048,7 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic) { - var newTopologyClass = vkTopology.ConvertToClass(); - - if ((_newState.Topology.ConvertToClass() != newTopologyClass)) + if ((_newState.Topology != vkTopology)) { _newState.Topology = vkTopology; } From 2a3069d9a1bfae44bc076b7ab40e11fa67494d0d Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 9 Sep 2024 11:02:07 -0700 Subject: [PATCH 108/132] Enable Vertex Input Binding Stride extended state when available on newer MVK --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 5 +++-- src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs | 2 +- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 3 +++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 4b37fb9b0..fe2349ae9 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -632,9 +632,10 @@ namespace Ryujinx.Graphics.Vulkan if (_supportsExtDynamicState) { - if (!isMoltenVk) + if (gd.SupportsMTL31 || gd.IsMoltenVk) { - //Requires Metal 3.1 and new MoltenVK + //Requires Metal 3.1 and new MoltenVK however extended dynamic states extension is not + //available on older verrsion of MVK so we can safely check only OS version dynamicStates[dynamicStatesCount++] = DynamicState.VertexInputBindingStrideExt; } dynamicStates[0] = DynamicState.ViewportWithCountExt; diff --git a/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs b/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs index 44063da70..7dbdfcb05 100644 --- a/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs +++ b/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs @@ -51,7 +51,7 @@ namespace Ryujinx.Graphics.Vulkan { if (_count != 0) { - if (_gd.Capabilities.SupportsExtendedDynamicState && !_gd.IsMoltenVk) + if (_gd.Capabilities.SupportsExtendedDynamicState && (_gd.SupportsMTL31 || !_gd.IsMoltenVk)) { _gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2( cbs.CommandBuffer, diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 1e9403ba0..010d24942 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -91,6 +91,7 @@ namespace Ryujinx.Graphics.Vulkan internal bool IsIntelArc { get; private set; } internal bool IsQualcommProprietary { get; private set; } internal bool IsMoltenVk { get; private set; } + internal bool SupportsMTL31 { get; private set; } internal bool IsTBDR { get; private set; } internal bool IsSharedMemory { get; private set; } @@ -119,6 +120,8 @@ namespace Ryujinx.Graphics.Vulkan // Any device running on MacOS is using MoltenVK, even Intel and AMD vendors. IsMoltenVk = true; + + SupportsMTL31 = OperatingSystem.IsMacOSVersionAtLeast(14); } } From d9c5b5c753758fc10286b55d24457a51a6b26d5e Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 9 Sep 2024 11:04:33 -0700 Subject: [PATCH 109/132] Correct typo --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index fe2349ae9..75d1ff376 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -632,7 +632,7 @@ namespace Ryujinx.Graphics.Vulkan if (_supportsExtDynamicState) { - if (gd.SupportsMTL31 || gd.IsMoltenVk) + if (gd.SupportsMTL31 || !gd.IsMoltenVk) { //Requires Metal 3.1 and new MoltenVK however extended dynamic states extension is not //available on older verrsion of MVK so we can safely check only OS version From 4a3b10fa9f05f3a2c430fbf45264b7a0d91726ab Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 9 Sep 2024 18:11:35 -0700 Subject: [PATCH 110/132] Apply suggestions from code review Simple suggestions from code review Co-authored-by: gdkchan --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 -- src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs | 4 ++-- src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs | 9 +++------ src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 6 +++--- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 2 +- 5 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index f31f50b17..563201b66 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -94,7 +94,6 @@ namespace Ryujinx.Graphics.Vulkan private FeedbackLoopAspects _feedbackLoop; private bool _passWritesDepthStencil; - private readonly PipelineColorBlendAttachmentState[] _storedBlend; public ulong DrawCount { get; private set; } public bool RenderPassActive { get; private set; } @@ -1250,7 +1249,6 @@ namespace Ryujinx.Graphics.Vulkan (uint)stencilTest.FrontMask, (uint)stencilTest.FrontFuncRef); - UpdatePassDepthStencil(); SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index fcc27c667..c6b317afc 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -215,8 +215,8 @@ namespace Ryujinx.Graphics.Vulkan { pipeline.PrimitiveRestartEnable = state.PrimitiveRestartEnable; pipeline.RasterizerDiscardEnable = state.RasterizerDiscard; - pipeline.DepthBiasEnable = ((state.BiasEnable != 0) && - (state.DepthBiasFactor != 0 && state.DepthBiasUnits != 0)); + pipeline.DepthBiasEnable = (state.BiasEnable != 0) && + (state.DepthBiasFactor != 0 && state.DepthBiasUnits != 0); } if (!extendedDynamicState2.ExtendedDynamicState2LogicOp) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 3b6701607..c11921699 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -3,7 +3,6 @@ using Silk.NET.Vulkan; using Silk.NET.Vulkan.Extensions.EXT; using System; - namespace Ryujinx.Graphics.Vulkan { struct PipelineDynamicState @@ -74,7 +73,7 @@ namespace Ryujinx.Graphics.Vulkan FrontFace = 1 << 7, DepthTestBool = 1 << 8, DepthTestCompareOp = 1 << 9, - StencilTestEnableandStencilOp = 1 << 10, + StencilTestEnableAndStencilOp = 1 << 10, LineWidth = 1 << 11, RasterDiscard = 1 << 12, LogicOp = 1 << 13, @@ -203,7 +202,6 @@ namespace Ryujinx.Graphics.Vulkan public void SetLineWidth(float width) { _lineWidth = width; - _dirty |= DirtyFlags.LineWidth; } @@ -412,7 +410,7 @@ namespace Ryujinx.Graphics.Vulkan gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference); } - private readonly void RecordStencilTestandOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) + private readonly void RecordStencilTestAndOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetStencilTestEnable(commandBuffer, StencilTestEnable); @@ -431,7 +429,6 @@ namespace Ryujinx.Graphics.Vulkan if (gd.Capabilities.SupportsExtendedDynamicState) { - gd.ExtendedDynamicStateApi.CmdSetViewportWithCount(commandBuffer, ViewportsCount, Viewports.AsSpan()); } @@ -491,7 +488,7 @@ namespace Ryujinx.Graphics.Vulkan primitiveRestartEnable &= topologySupportsRestart; - //Cannot disable primitiveRestartEnable for these Topologies on MacOS + // Cannot disable primitiveRestartEnable for these Topologies on MacOS. if (gd.IsMoltenVk) { primitiveRestartEnable = true; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 75d1ff376..793c2c981 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -503,7 +503,7 @@ namespace Ryujinx.Graphics.Vulkan if (isMoltenVk) { - //When widelines feature is not supported it must be 1.0f. + // When widelines feature is not supported it must be 1.0f. rasterizationState.LineWidth = 1.0f; } @@ -634,8 +634,8 @@ namespace Ryujinx.Graphics.Vulkan { if (gd.SupportsMTL31 || !gd.IsMoltenVk) { - //Requires Metal 3.1 and new MoltenVK however extended dynamic states extension is not - //available on older verrsion of MVK so we can safely check only OS version + // Requires Metal 3.1 and new MoltenVK, however extended dynamic states extension is not + // available on older versions of MVK, so we can safely check only OS version. dynamicStates[dynamicStatesCount++] = DynamicState.VertexInputBindingStrideExt; } dynamicStates[0] = DynamicState.ViewportWithCountExt; diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 010d24942..9c603fbe3 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -422,7 +422,7 @@ namespace Ryujinx.Graphics.Vulkan properties.Limits.FramebufferDepthSampleCounts & properties.Limits.FramebufferStencilSampleCounts; - //Temporarily disable this can be added back at a later date, make it easy to re-enable. + // Temporarily disable this, can be added back at a later date, make it easy to re-enable. featuresExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints = false; Capabilities = new HardwareCapabilities( From 01c6d5491e9b5bada21a501c03b9358819feb8e8 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 9 Sep 2024 18:53:40 -0700 Subject: [PATCH 111/132] Code Review Suggestions --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 136 ++++++++++-------- .../PipelineDynamicState.cs | 31 ++-- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 2 - .../VulkanInitialization.cs | 6 +- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 1 + 5 files changed, 100 insertions(+), 76 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 563201b66..0343bac6e 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1,4 +1,5 @@ using Ryujinx.Common.Logging; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Shader; using Silk.NET.Vulkan; @@ -640,14 +641,32 @@ 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 oldTopology = _supportExtDynamic ? DynamicState.Topology : _newState.Topology; - var oldTopologyClass = _newState.Topology; - var oldViewports = DynamicState.Viewports; - var oldViewportsCount = _supportExtDynamic ? DynamicState.ViewportsCount : _newState.ViewportsCount; + CullModeFlags oldCullMode; + bool oldStencilTestEnable; + bool oldDepthTestEnable; + bool oldDepthWriteEnable; + Silk.NET.Vulkan.PrimitiveTopology oldTopology; + Array16 oldViewports = DynamicState.Viewports; + uint oldViewportsCount; + + if (_supportExtDynamic) + { + oldCullMode = DynamicState.CullMode; + oldStencilTestEnable = DynamicState.StencilTestEnable; + oldDepthTestEnable = DynamicState.DepthTestEnable; + oldDepthWriteEnable = DynamicState.DepthWriteEnable; + oldTopology = DynamicState.Topology; + oldViewportsCount = DynamicState.ViewportsCount; + } + else + { + oldCullMode = _newState.CullMode; + oldStencilTestEnable = _newState.StencilTestEnable; + oldDepthTestEnable = _newState.DepthTestEnable; + oldDepthWriteEnable = _newState.DepthWriteEnable; + oldTopology = _newState.Topology; + oldViewportsCount = _newState.ViewportsCount; + } if (_supportExtDynamic) { @@ -661,9 +680,9 @@ namespace Ryujinx.Graphics.Vulkan _newState.StencilTestEnable = false; _newState.DepthTestEnable = false; _newState.DepthWriteEnable = false; - } - SignalStateChange(); + SignalStateChange(); + } Gd.HelperShader.DrawTexture( Gd, @@ -673,13 +692,10 @@ namespace Ryujinx.Graphics.Vulkan srcRegion, dstRegion); + _newState.Topology = oldTopology; + if (_supportExtDynamic) { - if (oldTopologyClass != _newState.Topology) - { - _newState.Topology = oldTopology; - } - DynamicState.SetCullMode(oldCullMode); DynamicState.SetStencilTest(oldStencilTestEnable); DynamicState.SetDepthTestBool(oldDepthTestEnable, oldDepthWriteEnable); @@ -692,7 +708,6 @@ namespace Ryujinx.Graphics.Vulkan _newState.DepthTestEnable = oldDepthTestEnable; _newState.DepthWriteEnable = oldDepthWriteEnable; _newState.ViewportsCount = oldViewportsCount; - _newState.Topology = oldTopology; } DynamicState.SetViewports(ref oldViewports, oldViewportsCount); @@ -832,7 +847,6 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic2) { DynamicState.SetDepthBiasEnable(depthBiasEnable); - changed = true; } else if (_newState.DepthBiasEnable != depthBiasEnable) { @@ -843,7 +857,6 @@ namespace Ryujinx.Graphics.Vulkan if (depthBiasEnable) { DynamicState.SetDepthBias(factor, units, clamp); - changed = true; } if (changed) @@ -888,10 +901,11 @@ namespace Ryujinx.Graphics.Vulkan _newState.DepthTestEnable = depthTest.TestEnable; _newState.DepthWriteEnable = depthTest.WriteEnable; _newState.DepthCompareOp = depthTest.Func.Convert(); + + SignalStateChange(); } UpdatePassDepthStencil(); - SignalStateChange(); } public void SetFaceCulling(bool enable, Face face) @@ -903,9 +917,9 @@ namespace Ryujinx.Graphics.Vulkan else { _newState.CullMode = enable ? face.Convert() : CullModeFlags.None; - } - SignalStateChange(); + SignalStateChange(); + } } public void SetFrontFace(FrontFace frontFace) @@ -917,9 +931,9 @@ namespace Ryujinx.Graphics.Vulkan else { _newState.FrontFace = frontFace.Convert(); - } - SignalStateChange(); + SignalStateChange(); + } } public void SetImage(ShaderStage stage, int binding, ITexture image, Format imageFormat) @@ -962,8 +976,6 @@ namespace Ryujinx.Graphics.Vulkan { DynamicState.SetLineWidth(Gd.Capabilities.SupportsWideLines ? width : 1.0f); } - - SignalStateChange(); } public void SetLogicOpState(bool enable, LogicalOp op) @@ -1007,9 +1019,9 @@ namespace Ryujinx.Graphics.Vulkan else { _newState.PatchControlPoints = (uint)vertices; - } - SignalStateChange(); + SignalStateChange(); + } // TODO: Default levels (likely needs emulation on shaders?) } @@ -1033,10 +1045,11 @@ namespace Ryujinx.Graphics.Vulkan else { _newState.PrimitiveRestartEnable = enable; + + SignalStateChange(); } // TODO: What to do about the index? - SignalStateChange(); } public void SetPrimitiveTopology(PrimitiveTopology topology) @@ -1045,19 +1058,12 @@ namespace Ryujinx.Graphics.Vulkan var vkTopology = Gd.TopologyRemap(topology).Convert(); + _newState.Topology = vkTopology; + if (_supportExtDynamic) { - if ((_newState.Topology != vkTopology)) - { - _newState.Topology = vkTopology; - } - DynamicState.SetPrimitiveTopology(vkTopology); } - else - { - _newState.Topology = vkTopology; - } SignalStateChange(); } @@ -1074,7 +1080,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.PipelineLayout = internalProgram.PipelineLayout; _newState.HasTessellationControlShader = internalProgram.HasTessellationControlShader; - _newState.StagesCount = internalProgram.IsCompute ? 1 : (uint)stages.Length; + _newState.StagesCount = (uint)stages.Length; stages.CopyTo(_newState.Stages.AsSpan()[..stages.Length]); @@ -1104,15 +1110,16 @@ namespace Ryujinx.Graphics.Vulkan public void SetRasterizerDiscard(bool discard) { - if (!_supportExtDynamic2) - { - _newState.RasterizerDiscardEnable = discard; - } - else + if (_supportExtDynamic2) { DynamicState.SetRasterizerDiscard(discard); } - SignalStateChange(); + else + { + _newState.RasterizerDiscardEnable = discard; + + SignalStateChange(); + } if (!discard && Gd.IsQualcommProprietary) { @@ -1195,11 +1202,6 @@ namespace Ryujinx.Graphics.Vulkan ClearScissor = regions[0]; } - if (!_supportExtDynamic) - { - _newState.ScissorsCount = (uint)count; - } - DynamicState.ScissorsCount = count; for (int i = 0; i < count; i++) @@ -1211,7 +1213,12 @@ namespace Ryujinx.Graphics.Vulkan DynamicState.SetScissor(i, new Rect2D(offset, extent)); } - SignalStateChange(); + if (!_supportExtDynamic) + { + _newState.ScissorsCount = (uint)count; + + SignalStateChange(); + } } public void SetStencilTest(StencilTestDescriptor stencilTest) @@ -1228,6 +1235,8 @@ namespace Ryujinx.Graphics.Vulkan stencilTest.FrontDpFail.Convert(), stencilTest.FrontFunc.Convert(), stencilTest.TestEnable); + + UpdatePassDepthStencil(); } else { @@ -1240,6 +1249,9 @@ namespace Ryujinx.Graphics.Vulkan _newState.StencilFrontDepthFailOp = stencilTest.FrontDpFail.Convert(); _newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert(); _newState.StencilTestEnable = stencilTest.TestEnable; + + UpdatePassDepthStencil(); + SignalStateChange(); } DynamicState.SetStencilMask((uint)stencilTest.BackFuncMask, @@ -1248,9 +1260,6 @@ namespace Ryujinx.Graphics.Vulkan (uint)stencilTest.FrontFuncMask, (uint)stencilTest.FrontMask, (uint)stencilTest.FrontFuncRef); - - UpdatePassDepthStencil(); - SignalStateChange(); } public void SetStorageBuffers(ReadOnlySpan buffers) @@ -1472,11 +1481,6 @@ namespace Ryujinx.Graphics.Vulkan return Math.Clamp(value, 0f, 1f); } - if (!_supportExtDynamic) - { - _newState.ViewportsCount = (uint)count; - } - DynamicState.ViewportsCount = (uint)count; for (int i = 0; i < count; i++) @@ -1492,7 +1496,12 @@ namespace Ryujinx.Graphics.Vulkan Clamp(viewport.DepthFar))); } - SignalStateChange(); + if (!_supportExtDynamic) + { + _newState.ViewportsCount = (uint)count; + + SignalStateChange(); + } } public void SwapBuffer(Auto from, Auto to) @@ -1757,7 +1766,14 @@ namespace Ryujinx.Graphics.Vulkan } // Stencil test being enabled doesn't necessarily mean a write, but it's not critical to check. - _passWritesDepthStencil |= _supportExtDynamic ? (DynamicState.DepthTestEnable && DynamicState.DepthWriteEnable) || DynamicState.StencilTestEnable : (_newState.DepthTestEnable && _newState.DepthWriteEnable) || _newState.StencilTestEnable; + if (_supportExtDynamic) + { + _passWritesDepthStencil |= (DynamicState.DepthTestEnable && DynamicState.DepthWriteEnable) || DynamicState.StencilTestEnable; + } + else + { + _passWritesDepthStencil |= (_newState.DepthTestEnable && _newState.DepthWriteEnable) || _newState.StencilTestEnable; + } } private bool RecreateGraphicsPipelineIfNeeded() diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index c11921699..66762232f 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -82,7 +82,7 @@ namespace Ryujinx.Graphics.Vulkan PrimitiveTopology = 1 << 16, DepthBiasEnable = 1 << 17, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | FeedbackLoop, - Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnableandStencilOp | PrimitiveTopology, + Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnableAndStencilOp | PrimitiveTopology, Extended2 = RasterDiscard | PrimitiveRestart | DepthBiasEnable, } @@ -131,9 +131,16 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.DepthTestCompareOp; } - public void SetStencilTestandOp(StencilOp backFailOp, StencilOp backPassOp, StencilOp backDepthFailOp, - CompareOp backCompareOp, StencilOp frontFailOp, StencilOp frontPassOp, StencilOp frontDepthFailOp, - CompareOp frontCompareOp, bool stencilTestEnable) + public void SetStencilTestandOp( + StencilOp backFailOp, + StencilOp backPassOp, + StencilOp backDepthFailOp, + CompareOp backCompareOp, + StencilOp frontFailOp, + StencilOp frontPassOp, + StencilOp frontDepthFailOp, + CompareOp frontCompareOp, + bool stencilTestEnable) { _backFailOp = backFailOp; _backPassOp = backPassOp; @@ -146,18 +153,22 @@ namespace Ryujinx.Graphics.Vulkan StencilTestEnable = stencilTestEnable; - _dirty |= DirtyFlags.StencilTestEnableandStencilOp; + _dirty |= DirtyFlags.StencilTestEnableAndStencilOp; } public void SetStencilTest(bool stencilTestEnable) { StencilTestEnable = stencilTestEnable; - _dirty |= DirtyFlags.StencilTestEnableandStencilOp; + _dirty |= DirtyFlags.StencilTestEnableAndStencilOp; } - public void SetStencilMask(uint backCompareMask, uint backWriteMask, uint backReference, - uint frontCompareMask, uint frontWriteMask, uint frontReference) + public void SetStencilMask(uint backCompareMask, + uint backWriteMask, + uint backReference, + uint frontCompareMask, + uint frontWriteMask, + uint frontReference) { _backCompareMask = backCompareMask; _backWriteMask = backWriteMask; @@ -324,9 +335,9 @@ namespace Ryujinx.Graphics.Vulkan RecordDepthTestCompareOp(gd.ExtendedDynamicStateApi, commandBuffer); } - if (_dirty.HasFlag(DirtyFlags.StencilTestEnableandStencilOp)) + if (_dirty.HasFlag(DirtyFlags.StencilTestEnableAndStencilOp)) { - RecordStencilTestandOp(gd.ExtendedDynamicStateApi, commandBuffer); + RecordStencilTestAndOp(gd.ExtendedDynamicStateApi, commandBuffer); } if (_dirty.HasFlag(DirtyFlags.LineWidth)) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 793c2c981..d1630faf3 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -258,8 +258,6 @@ namespace Ryujinx.Graphics.Vulkan private bool _supportsFeedBackLoopDynamicState; private uint _blendEnables; - - public void Initialize(HardwareCapabilities capabilities) { HasTessellationControlShader = false; diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index a393ee944..44c8a5dea 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -492,10 +492,8 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, PNext = pExtendedFeatures, - ExtendedDynamicState2 = - supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2, - ExtendedDynamicState2LogicOp = - supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp, + ExtendedDynamicState2 = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2, + ExtendedDynamicState2LogicOp = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp, ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints, }; diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 9c603fbe3..f40ddf8f8 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -423,6 +423,7 @@ namespace Ryujinx.Graphics.Vulkan properties.Limits.FramebufferStencilSampleCounts; // Temporarily disable this, can be added back at a later date, make it easy to re-enable. + // Disabled because currently causing Device Lost error on nVidia. featuresExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints = false; Capabilities = new HardwareCapabilities( From d7089682ae0c01114e12ba1cc767a3c2c98b1446 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Tue, 10 Sep 2024 01:57:31 +0000 Subject: [PATCH 112/132] Code Review Suggestion --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 2f613c8e5..301024cf8 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -49,4 +49,4 @@ - + \ No newline at end of file From f085b47b30dcdec3ca640d2354fcbe3349e345cc Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 9 Sep 2024 21:08:13 -0700 Subject: [PATCH 113/132] Address Feedback --- .../PipelineDynamicState.cs | 166 +++++++----------- src/Ryujinx.Graphics.Vulkan/PipelineUid.cs | 2 +- 2 files changed, 65 insertions(+), 103 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 66762232f..d962be52c 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -2,6 +2,7 @@ using Ryujinx.Common.Memory; using Silk.NET.Vulkan; using Silk.NET.Vulkan.Extensions.EXT; using System; +using System.Numerics; namespace Ryujinx.Graphics.Vulkan { @@ -81,7 +82,7 @@ namespace Ryujinx.Graphics.Vulkan PrimitiveRestart = 1 << 15, PrimitiveTopology = 1 << 16, DepthBiasEnable = 1 << 17, - Standard = Blend | DepthBias | Scissor | Stencil | Viewport | FeedbackLoop, + Standard = Blend | DepthBias | Scissor | Stencil | Viewport, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnableAndStencilOp | PrimitiveTopology, Extended2 = RasterDiscard | PrimitiveRestart | DepthBiasEnable, } @@ -265,6 +266,16 @@ namespace Ryujinx.Graphics.Vulkan if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2) { _dirty |= DirtyFlags.Extended2; + + if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) + { + _dirty |= DirtyFlags.LogicOp; + } + + if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) + { + _dirty |= DirtyFlags.PatchControlPoints; + } } if (!gd.IsMoltenVk) @@ -272,107 +283,58 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.LineWidth; } - if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) + if (gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop) { - _dirty |= DirtyFlags.LogicOp; - } - - if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) - { - _dirty |= DirtyFlags.PatchControlPoints; + _dirty |= DirtyFlags.FeedbackLoop; } } public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) { - if (_dirty.HasFlag(DirtyFlags.Blend)) + if (_dirty == DirtyFlags.None) { - RecordBlend(gd.Api, commandBuffer); + return; } - if (_dirty.HasFlag(DirtyFlags.DepthBias)) - { - RecordDepthBias(gd, commandBuffer); - } + var api = gd.Api; + var extendedStateApi = gd.ExtendedDynamicStateApi; + var extendedState2Api = gd.ExtendedDynamicState2Api; + var dynamicFeedbackLoopApi = gd.DynamicFeedbackLoopApi; - if (_dirty.HasFlag(DirtyFlags.Scissor)) - { - RecordScissor(gd, commandBuffer); - } + PipelineDynamicState state = this; - if (_dirty.HasFlag(DirtyFlags.Stencil)) + Action[] actions = new Action[] { - RecordStencil(gd, commandBuffer); - } + () => state.RecordBlend(api, commandBuffer), + () => state.RecordDepthBias(api, commandBuffer), + () => state.RecordScissor(gd, commandBuffer), + () => state.RecordStencil(api, commandBuffer), + () => state.RecordViewport(gd, commandBuffer), + () => state.RecordFeedbackLoop(dynamicFeedbackLoopApi, commandBuffer), + () => state.RecordCullMode(extendedStateApi, commandBuffer), + () => state.RecordFrontFace(extendedStateApi, commandBuffer), + () => state.RecordDepthTestBool(extendedStateApi, commandBuffer), + () => state.RecordDepthTestCompareOp(extendedStateApi, commandBuffer), + () => state.RecordStencilTestAndOp(extendedStateApi, commandBuffer), + () => state.RecordLineWidth(api, commandBuffer), + () => state.RecordRasterizationDiscard(extendedState2Api, commandBuffer), + () => state.RecordLogicOp(extendedState2Api, commandBuffer), + () => state.RecordPatchControlPoints(extendedState2Api, commandBuffer), + () => state.RecordPrimitiveRestartEnable(gd, commandBuffer), + () => state.RecordPrimitiveTopology(extendedStateApi, commandBuffer), + () => state.RecordDepthBiasEnable(extendedState2Api, commandBuffer), + }; - if (_dirty.HasFlag(DirtyFlags.Viewport)) - { - RecordViewport(gd, commandBuffer); - } + DirtyFlags dirtyFlags = _dirty; - if (_dirty.HasFlag(DirtyFlags.CullMode)) + while (dirtyFlags != DirtyFlags.None) { - RecordCullMode(gd.ExtendedDynamicStateApi, commandBuffer); - } + int bitIndex = BitOperations.TrailingZeroCount((uint)dirtyFlags); + DirtyFlags currentFlag = (DirtyFlags)(1 << bitIndex); - if (_dirty.HasFlag(DirtyFlags.FrontFace)) - { - RecordFrontFace(gd.ExtendedDynamicStateApi, commandBuffer); - } + actions[bitIndex](); - if (_dirty.HasFlag(DirtyFlags.DepthTestBool)) - { - RecordDepthTestBool(gd.ExtendedDynamicStateApi, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.DepthBiasEnable)) - { - RecordDepthBiasEnable(gd.ExtendedDynamicState2Api, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.DepthTestCompareOp)) - { - RecordDepthTestCompareOp(gd.ExtendedDynamicStateApi, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.StencilTestEnableAndStencilOp)) - { - RecordStencilTestAndOp(gd.ExtendedDynamicStateApi, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.LineWidth)) - { - RecordLineWidth(gd.Api, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.RasterDiscard)) - { - RecordRasterizationDiscard(gd, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.PrimitiveRestart)) - { - RecordPrimitiveRestartEnable(gd, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.PrimitiveTopology)) - { - RecordPrimitiveTopology(gd, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.LogicOp)) - { - RecordLogicOp(gd, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.PatchControlPoints)) - { - RecordPatchControlPoints(gd, commandBuffer); - } - - if (_dirty.HasFlag(DirtyFlags.FeedbackLoop) && gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop) - { - RecordFeedbackLoop(gd.DynamicFeedbackLoopApi, commandBuffer); + dirtyFlags &= ~currentFlag; } _dirty = DirtyFlags.None; @@ -383,9 +345,9 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetBlendConstants(commandBuffer, _blendConstants.AsSpan()); } - private readonly void RecordDepthBias(VulkanRenderer gd, CommandBuffer commandBuffer) + private readonly void RecordDepthBias(Vk api, CommandBuffer commandBuffer) { - gd.Api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); + api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); } private readonly void RecordDepthBiasEnable(ExtExtendedDynamicState2 gd, CommandBuffer commandBuffer) @@ -411,14 +373,14 @@ namespace Ryujinx.Graphics.Vulkan } } - private readonly void RecordStencil(VulkanRenderer gd, CommandBuffer commandBuffer) + private readonly void RecordStencil(Vk api, CommandBuffer commandBuffer) { - gd.Api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backCompareMask); - gd.Api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backWriteMask); - gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceBackBit, _backReference); - gd.Api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontCompareMask); - gd.Api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontWriteMask); - gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference); + api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backCompareMask); + api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backWriteMask); + api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceBackBit, _backReference); + api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontCompareMask); + api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontWriteMask); + api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference); } private readonly void RecordStencilTestAndOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) @@ -472,9 +434,9 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetDepthCompareOp(commandBuffer, _depthCompareOp); } - private readonly void RecordRasterizationDiscard(VulkanRenderer gd, CommandBuffer commandBuffer) + private readonly void RecordRasterizationDiscard(ExtExtendedDynamicState2 extendedDynamicState2Api, CommandBuffer commandBuffer) { - gd.ExtendedDynamicState2Api.CmdSetRasterizerDiscardEnable(commandBuffer, _discard); + extendedDynamicState2Api.CmdSetRasterizerDiscardEnable(commandBuffer, _discard); } private readonly void RecordPrimitiveRestartEnable(VulkanRenderer gd, CommandBuffer commandBuffer) @@ -508,19 +470,19 @@ namespace Ryujinx.Graphics.Vulkan gd.ExtendedDynamicState2Api.CmdSetPrimitiveRestartEnable(commandBuffer, primitiveRestartEnable); } - private readonly void RecordPrimitiveTopology(VulkanRenderer gd, CommandBuffer commandBuffer) + private readonly void RecordPrimitiveTopology(ExtExtendedDynamicState extendedDynamicStateApi, CommandBuffer commandBuffer) { - gd.ExtendedDynamicStateApi.CmdSetPrimitiveTopology(commandBuffer, Topology); + extendedDynamicStateApi.CmdSetPrimitiveTopology(commandBuffer, Topology); } - private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) + private readonly void RecordLogicOp(ExtExtendedDynamicState2 extendedDynamicState2Api, CommandBuffer commandBuffer) { - gd.ExtendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp); + extendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp); } - private readonly void RecordPatchControlPoints(VulkanRenderer gd, CommandBuffer commandBuffer) + private readonly void RecordPatchControlPoints(ExtExtendedDynamicState2 extendedDynamicState2Api, CommandBuffer commandBuffer) { - gd.ExtendedDynamicState2Api.CmdSetPatchControlPoints(commandBuffer, _patchControlPoints); + extendedDynamicState2Api.CmdSetPatchControlPoints(commandBuffer, _patchControlPoints); } private readonly void RecordLineWidth(Vk api, CommandBuffer commandBuffer) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs b/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs index 1e3253988..18c0464ee 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs @@ -34,7 +34,7 @@ namespace Ryujinx.Graphics.Vulkan public bool Equals(ref PipelineUid other) { - if (!Unsafe.As>(ref Id2).Equals(Unsafe.As>(ref other.Id2))) + if (!Unsafe.As>(ref Id0).Equals(Unsafe.As>(ref other.Id0))) { return false; } From 2fd093d4b478097099d899919ec01f0afdc917f9 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 9 Sep 2024 21:17:44 -0700 Subject: [PATCH 114/132] Avoid setting stride if dynamic state is supported --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 4 ++-- src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs | 4 ++-- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 4 ++-- src/Ryujinx.Graphics.Vulkan/VertexBufferState.cs | 12 +++++++++--- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 0343bac6e..5eb2fc559 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1378,7 +1378,7 @@ namespace Ryujinx.Graphics.Vulkan { int count = Math.Min(Constants.MaxVertexBuffers, vertexBuffers.Length); - _newState.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, 0, VertexInputRate.Vertex); + _newState.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, _supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31) ? null : 0, VertexInputRate.Vertex); int validCount = 1; @@ -1407,7 +1407,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.Internal.VertexBindingDescriptions[descriptorIndex] = new VertexInputBindingDescription( (uint)binding, - (uint)vertexBuffer.Stride, + _supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31) ? null : (uint)vertexBuffer.Stride, inputRate); int vbSize = vertexBuffer.Buffer.Size; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index c6b317afc..ecfa1d839 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -256,7 +256,7 @@ namespace Ryujinx.Graphics.Vulkan } int descriptorIndex = 1; - pipeline.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, 0, VertexInputRate.Vertex); + pipeline.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, extendedDynamicState && (!gd.IsMoltenVk || gd.SupportsMTL31) ? null : 0, VertexInputRate.Vertex); for (int i = 0; i < vbCount; i++) { @@ -276,7 +276,7 @@ namespace Ryujinx.Graphics.Vulkan // TODO: Support divisor > 1 pipeline.Internal.VertexBindingDescriptions[descriptorIndex++] = new VertexInputBindingDescription( (uint)i + 1, - (uint)alignedStride, + extendedDynamicState && (!gd.IsMoltenVk || gd.SupportsMTL31) ? null : (uint)alignedStride, inputRate); } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index d1630faf3..11c748cf4 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -466,7 +466,7 @@ namespace Ryujinx.Graphics.Vulkan bool isMoltenVk = gd.IsMoltenVk; - if (isMoltenVk) + if (isMoltenVk && !_supportsExtDynamicState) { UpdateVertexAttributeDescriptions(gd); } @@ -480,7 +480,7 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.PipelineVertexInputStateCreateInfo, VertexAttributeDescriptionCount = VertexAttributeDescriptionsCount, - PVertexAttributeDescriptions = isMoltenVk ? pVertexAttributeDescriptions2 : pVertexAttributeDescriptions, + PVertexAttributeDescriptions = isMoltenVk && !_supportsExtDynamicState ? pVertexAttributeDescriptions2 : pVertexAttributeDescriptions, VertexBindingDescriptionCount = VertexBindingDescriptionsCount, PVertexBindingDescriptions = pVertexBindingDescriptions, }; diff --git a/src/Ryujinx.Graphics.Vulkan/VertexBufferState.cs b/src/Ryujinx.Graphics.Vulkan/VertexBufferState.cs index 6f27bb68b..9d56e316a 100644 --- a/src/Ryujinx.Graphics.Vulkan/VertexBufferState.cs +++ b/src/Ryujinx.Graphics.Vulkan/VertexBufferState.cs @@ -71,7 +71,10 @@ namespace Ryujinx.Graphics.Vulkan _buffer = autoBuffer; - state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)stride; + if (!gd.Capabilities.SupportsExtendedDynamicState) + { + state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)stride; + } } return; @@ -79,8 +82,11 @@ namespace Ryujinx.Graphics.Vulkan autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int size); - // The original stride must be reapplied in case it was rewritten. - state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)_stride; + if (!gd.Capabilities.SupportsExtendedDynamicState) + { + // The original stride must be reapplied in case it was rewritten. + state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)_stride; + } if (_offset >= size) { From 5a391f38fd70abf66aa5e4d390f48afd3f98c3f0 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 9 Sep 2024 21:50:18 -0700 Subject: [PATCH 115/132] Refactor Cull Mode to only send face. --- src/Ryujinx.Graphics.GAL/Face.cs | 1 + src/Ryujinx.Graphics.GAL/IPipeline.cs | 2 +- .../Commands/SetFaceCullingCommand.cs | 6 ++---- .../Multithreading/ThreadedPipeline.cs | 4 ++-- src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs | 1 - .../Engine/Threed/StateUpdater.cs | 13 ++++++++++--- src/Ryujinx.Graphics.OpenGL/EnumConversion.cs | 3 +++ src/Ryujinx.Graphics.OpenGL/Pipeline.cs | 6 +++--- src/Ryujinx.Graphics.Vulkan/EnumConversion.cs | 1 + src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 6 +++--- src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs | 2 +- 11 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/Ryujinx.Graphics.GAL/Face.cs b/src/Ryujinx.Graphics.GAL/Face.cs index 73e43cf23..e204278eb 100644 --- a/src/Ryujinx.Graphics.GAL/Face.cs +++ b/src/Ryujinx.Graphics.GAL/Face.cs @@ -2,6 +2,7 @@ namespace Ryujinx.Graphics.GAL { public enum Face { + None = 0, Front = 0x404, Back = 0x405, FrontAndBack = 0x408, diff --git a/src/Ryujinx.Graphics.GAL/IPipeline.cs b/src/Ryujinx.Graphics.GAL/IPipeline.cs index cbf1bc3a2..8c71adb9d 100644 --- a/src/Ryujinx.Graphics.GAL/IPipeline.cs +++ b/src/Ryujinx.Graphics.GAL/IPipeline.cs @@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.GAL void SetDepthMode(DepthMode mode); void SetDepthTest(DepthTestDescriptor depthTest); - void SetFaceCulling(bool enable, Face face); + void SetFaceCulling(Face face); void SetFrontFace(FrontFace frontFace); diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs index 611168f85..c88ddba63 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs @@ -3,18 +3,16 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands struct SetFaceCullingCommand : IGALCommand, IGALCommand { public readonly CommandType CommandType => CommandType.SetFaceCulling; - private bool _enable; private Face _face; - public void Set(bool enable, Face face) + public void Set(Face face) { - _enable = enable; _face = face; } public static void Run(ref SetFaceCullingCommand command, ThreadedRenderer threaded, IRenderer renderer) { - renderer.Pipeline.SetFaceCulling(command._enable, command._face); + renderer.Pipeline.SetFaceCulling(command._face); } } } diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs index edd79d8a0..8931e1056 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs @@ -165,9 +165,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading _renderer.QueueCommand(); } - public void SetFaceCulling(bool enable, Face face) + public void SetFaceCulling(Face face) { - _renderer.New().Set(enable, face); + _renderer.New().Set(face); _renderer.QueueCommand(); } diff --git a/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs b/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs index fc6e16267..5bc8e00b7 100644 --- a/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs +++ b/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs @@ -51,7 +51,6 @@ namespace Ryujinx.Graphics.GAL public StencilTestDescriptor StencilTest; public FrontFace FrontFace; public Face CullMode; - public bool CullEnable; public PolygonModeMask BiasEnable; diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs index 153eef8b0..a5ab82978 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs @@ -1198,9 +1198,16 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed var yControl = _state.State.YControl; var face = _state.State.FaceState; - _pipeline.CullEnable = face.CullEnable; - _pipeline.CullMode = face.CullFace; - _context.Renderer.Pipeline.SetFaceCulling(face.CullEnable, face.CullFace); + if (face.CullEnable) + { + _pipeline.CullMode = face.CullFace; + _context.Renderer.Pipeline.SetFaceCulling(face.CullFace); + } + else + { + _pipeline.CullMode = Face.None; + _context.Renderer.Pipeline.SetFaceCulling(Face.None); + } UpdateFrontFace(yControl, face.FrontFace); } diff --git a/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs b/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs index a92c1ce89..498ba4cc7 100644 --- a/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs +++ b/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs @@ -2,6 +2,7 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Shader; +using GL = OpenTK.Graphics.ES11.GL; namespace Ryujinx.Graphics.OpenGL { @@ -334,6 +335,8 @@ namespace Ryujinx.Graphics.OpenGL return CullFaceMode.Front; case Face.FrontAndBack: return CullFaceMode.FrontAndBack; + case Face.None: + return (CullFaceMode)All.None; } Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(Face)} enum value: {face}."); diff --git a/src/Ryujinx.Graphics.OpenGL/Pipeline.cs b/src/Ryujinx.Graphics.OpenGL/Pipeline.cs index 54f6b3f7b..de3269572 100644 --- a/src/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/src/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -915,11 +915,11 @@ namespace Ryujinx.Graphics.OpenGL _depthTestEnable = depthTest.TestEnable; } - public void SetFaceCulling(bool enable, Face face) + public void SetFaceCulling(Face face) { - _cullEnable = enable; + _cullEnable = face != Face.None; - if (!enable) + if (!_cullEnable) { GL.Disable(EnableCap.CullFace); return; diff --git a/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs b/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs index babcf992c..753a2fd43 100644 --- a/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs +++ b/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs @@ -238,6 +238,7 @@ namespace Ryujinx.Graphics.Vulkan Face.Back => CullModeFlags.BackBit, Face.Front => CullModeFlags.FrontBit, Face.FrontAndBack => CullModeFlags.FrontAndBack, + Face.None => CullModeFlags.None, _ => LogInvalidAndReturn(face, nameof(Face), CullModeFlags.BackBit), }; } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 5eb2fc559..171646917 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -908,15 +908,15 @@ namespace Ryujinx.Graphics.Vulkan UpdatePassDepthStencil(); } - public void SetFaceCulling(bool enable, Face face) + public void SetFaceCulling(Face face) { if (_supportExtDynamic) { - DynamicState.SetCullMode(enable ? face.Convert() : CullModeFlags.None); + DynamicState.SetCullMode(face.Convert()); } else { - _newState.CullMode = enable ? face.Convert() : CullModeFlags.None; + _newState.CullMode = face.Convert(); SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index ecfa1d839..acf42a9bc 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -180,7 +180,7 @@ namespace Ryujinx.Graphics.Vulkan if (!extendedDynamicState) { pipeline.DepthCompareOp = state.DepthTest.Func.Convert(); - pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None; + pipeline.CullMode = state.CullMode.Convert(); pipeline.DepthTestEnable = state.DepthTest.TestEnable; pipeline.DepthWriteEnable = state.DepthTest.WriteEnable; From dff81088e8cbb960fe6ea895af81106317a82962 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 9 Sep 2024 22:03:50 -0700 Subject: [PATCH 116/132] Replace Action array with a switch statment. --- .../PipelineDynamicState.cs | 82 +++++++++++++------ 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index d962be52c..0dc4d4527 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -301,30 +301,6 @@ namespace Ryujinx.Graphics.Vulkan var extendedState2Api = gd.ExtendedDynamicState2Api; var dynamicFeedbackLoopApi = gd.DynamicFeedbackLoopApi; - PipelineDynamicState state = this; - - Action[] actions = new Action[] - { - () => state.RecordBlend(api, commandBuffer), - () => state.RecordDepthBias(api, commandBuffer), - () => state.RecordScissor(gd, commandBuffer), - () => state.RecordStencil(api, commandBuffer), - () => state.RecordViewport(gd, commandBuffer), - () => state.RecordFeedbackLoop(dynamicFeedbackLoopApi, commandBuffer), - () => state.RecordCullMode(extendedStateApi, commandBuffer), - () => state.RecordFrontFace(extendedStateApi, commandBuffer), - () => state.RecordDepthTestBool(extendedStateApi, commandBuffer), - () => state.RecordDepthTestCompareOp(extendedStateApi, commandBuffer), - () => state.RecordStencilTestAndOp(extendedStateApi, commandBuffer), - () => state.RecordLineWidth(api, commandBuffer), - () => state.RecordRasterizationDiscard(extendedState2Api, commandBuffer), - () => state.RecordLogicOp(extendedState2Api, commandBuffer), - () => state.RecordPatchControlPoints(extendedState2Api, commandBuffer), - () => state.RecordPrimitiveRestartEnable(gd, commandBuffer), - () => state.RecordPrimitiveTopology(extendedStateApi, commandBuffer), - () => state.RecordDepthBiasEnable(extendedState2Api, commandBuffer), - }; - DirtyFlags dirtyFlags = _dirty; while (dirtyFlags != DirtyFlags.None) @@ -332,7 +308,63 @@ namespace Ryujinx.Graphics.Vulkan int bitIndex = BitOperations.TrailingZeroCount((uint)dirtyFlags); DirtyFlags currentFlag = (DirtyFlags)(1 << bitIndex); - actions[bitIndex](); + switch (currentFlag) + { + case DirtyFlags.Blend: + RecordBlend(api, commandBuffer); + break; + case DirtyFlags.DepthBias: + RecordDepthBias(api, commandBuffer); + break; + case DirtyFlags.Scissor: + RecordScissor(gd, commandBuffer); + break; + case DirtyFlags.Stencil: + RecordStencil(api, commandBuffer); + break; + case DirtyFlags.Viewport: + RecordViewport(gd, commandBuffer); + break; + case DirtyFlags.FeedbackLoop: + RecordFeedbackLoop(dynamicFeedbackLoopApi, commandBuffer); + break; + case DirtyFlags.CullMode: + RecordCullMode(extendedStateApi, commandBuffer); + break; + case DirtyFlags.FrontFace: + RecordFrontFace(extendedStateApi, commandBuffer); + break; + case DirtyFlags.DepthTestBool: + RecordDepthTestBool(extendedStateApi, commandBuffer); + break; + case DirtyFlags.DepthTestCompareOp: + RecordDepthTestCompareOp(extendedStateApi, commandBuffer); + break; + case DirtyFlags.StencilTestEnableAndStencilOp: + RecordStencilTestAndOp(extendedStateApi, commandBuffer); + break; + case DirtyFlags.LineWidth: + RecordLineWidth(api, commandBuffer); + break; + case DirtyFlags.RasterDiscard: + RecordRasterizationDiscard(extendedState2Api, commandBuffer); + break; + case DirtyFlags.LogicOp: + RecordLogicOp(extendedState2Api, commandBuffer); + break; + case DirtyFlags.PatchControlPoints: + RecordPatchControlPoints(extendedState2Api, commandBuffer); + break; + case DirtyFlags.PrimitiveRestart: + RecordPrimitiveRestartEnable(gd, commandBuffer); + break; + case DirtyFlags.PrimitiveTopology: + RecordPrimitiveTopology(extendedStateApi, commandBuffer); + break; + case DirtyFlags.DepthBiasEnable: + RecordDepthBiasEnable(extendedState2Api, commandBuffer); + break; + } dirtyFlags &= ~currentFlag; } From 2d0c1c3a1cb56d5078db232b011f87f707c402f5 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Fri, 13 Sep 2024 08:13:44 -0700 Subject: [PATCH 117/132] Code review suggestions --- src/Ryujinx.Graphics.OpenGL/EnumConversion.cs | 2 -- .../PipelineDynamicState.cs | 19 ++++++------------- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 6 +----- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 2 +- 4 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs b/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs index 498ba4cc7..1654b6fd9 100644 --- a/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs +++ b/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs @@ -335,8 +335,6 @@ namespace Ryujinx.Graphics.OpenGL return CullFaceMode.Front; case Face.FrontAndBack: return CullFaceMode.FrontAndBack; - case Face.None: - return (CullFaceMode)All.None; } Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(Face)} enum value: {face}."); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 0dc4d4527..251378dd7 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -393,14 +393,11 @@ namespace Ryujinx.Graphics.Vulkan { if (gd.Capabilities.SupportsExtendedDynamicState) { - - gd.ExtendedDynamicStateApi.CmdSetScissorWithCount(commandBuffer, (uint)ScissorsCount, - _scissors.AsSpan()); + gd.ExtendedDynamicStateApi.CmdSetScissorWithCount(commandBuffer, (uint)ScissorsCount, _scissors.AsSpan()); } else { - gd.Api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, - _scissors.AsSpan()); + gd.Api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan()); } } } @@ -419,10 +416,8 @@ namespace Ryujinx.Graphics.Vulkan { api.CmdSetStencilTestEnable(commandBuffer, StencilTestEnable); - api.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceBackBit, _backFailOp, _backPassOp, - _backDepthFailOp, _backCompareOp); - api.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontFailOp, _frontPassOp, - _frontDepthFailOp, _frontCompareOp); + api.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceBackBit, _backFailOp, _backPassOp, _backDepthFailOp, _backCompareOp); + api.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontFailOp, _frontPassOp, _frontDepthFailOp, _frontCompareOp); } private void RecordViewport(VulkanRenderer gd, CommandBuffer commandBuffer) @@ -434,13 +429,11 @@ namespace Ryujinx.Graphics.Vulkan if (gd.Capabilities.SupportsExtendedDynamicState) { - gd.ExtendedDynamicStateApi.CmdSetViewportWithCount(commandBuffer, ViewportsCount, - Viewports.AsSpan()); + gd.ExtendedDynamicStateApi.CmdSetViewportWithCount(commandBuffer, ViewportsCount, Viewports.AsSpan()); } else { - gd.Api.CmdSetViewport(commandBuffer, 0, ViewportsCount, - Viewports.AsSpan()); + gd.Api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan()); } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 11c748cf4..f5c0c17da 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -7,7 +7,6 @@ namespace Ryujinx.Graphics.Vulkan { struct PipelineState : IDisposable { - private const int RequiredSubgroupSize = 32; private const int MaxDynamicStatesCount = 23; public PipelineUid Internal; @@ -406,10 +405,7 @@ namespace Ryujinx.Graphics.Vulkan PrimitiveRestartEnable &= topologySupportsRestart; } - if (_supportsExtDynamicState && (Topology != PrimitiveTopology.LineList || - Topology != PrimitiveTopology.TriangleStrip || - Topology != PrimitiveTopology.PointList || - Topology != PrimitiveTopology.PatchList)) + if (_supportsExtDynamicState) { Topology = Topology.ConvertToClass(); } diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index f40ddf8f8..376eb47ef 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -423,7 +423,7 @@ namespace Ryujinx.Graphics.Vulkan properties.Limits.FramebufferStencilSampleCounts; // Temporarily disable this, can be added back at a later date, make it easy to re-enable. - // Disabled because currently causing Device Lost error on nVidia. + // Disabled because currently causing Device Lost error on NVIDIA. featuresExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints = false; Capabilities = new HardwareCapabilities( From b557dc805b7d76b5481b9c5a193ae3292070aaed Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Fri, 13 Sep 2024 10:44:39 -0700 Subject: [PATCH 118/132] Missed line --- src/Ryujinx.Graphics.OpenGL/EnumConversion.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs b/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs index 1654b6fd9..a92c1ce89 100644 --- a/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs +++ b/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs @@ -2,7 +2,6 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Shader; -using GL = OpenTK.Graphics.ES11.GL; namespace Ryujinx.Graphics.OpenGL { From bc14efe5f1a7f0f439f759fb993575b4f90792da Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Fri, 13 Sep 2024 15:22:05 -0700 Subject: [PATCH 119/132] Avoid setting the dynamic state for feedback loop if it is not set avoids validation error. Also linewidth value is ignored if dynamic state is supported. --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 44 ++++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index f5c0c17da..647b77c20 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -495,11 +495,8 @@ namespace Ryujinx.Graphics.Vulkan DepthClampEnable = DepthClampEnable, }; - if (isMoltenVk) - { - // When widelines feature is not supported it must be 1.0f. - rasterizationState.LineWidth = 1.0f; - } + // When widelines feature is not supported it must be 1.0f, this will be ignored if Line Width dynamic state is supported + rasterizationState.LineWidth = 1.0f; var viewportState = new PipelineViewportStateCreateInfo { @@ -661,9 +658,26 @@ namespace Ryujinx.Graphics.Vulkan } } - if (_supportsFeedBackLoopDynamicState) + PipelineCreateFlags pipelineCreateFlags = 0; + + if (gd.Capabilities.SupportsAttachmentFeedbackLoop) { - dynamicStates[dynamicStatesCount++] = DynamicState.AttachmentFeedbackLoopEnableExt; + FeedbackLoopAspects aspects = FeedbackLoopAspects; + + if ((aspects & FeedbackLoopAspects.Color) != 0) + { + pipelineCreateFlags |= PipelineCreateFlags.CreateColorAttachmentFeedbackLoopBitExt; + } + + if ((aspects & FeedbackLoopAspects.Depth) != 0) + { + pipelineCreateFlags |= PipelineCreateFlags.CreateDepthStencilAttachmentFeedbackLoopBitExt; + } + + if (_supportsFeedBackLoopDynamicState && pipelineCreateFlags != 0) + { + dynamicStates[dynamicStatesCount++] = DynamicState.AttachmentFeedbackLoopEnableExt; + } } var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo @@ -677,6 +691,7 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.GraphicsPipelineCreateInfo, StageCount = StagesCount, + Flags = pipelineCreateFlags, PStages = Stages.Pointer, PVertexInputState = &vertexInputState, PInputAssemblyState = &inputAssemblyState, @@ -690,21 +705,6 @@ namespace Ryujinx.Graphics.Vulkan RenderPass = renderPass, }; - if (gd.Capabilities.SupportsAttachmentFeedbackLoop && !_supportsFeedBackLoopDynamicState) - { - FeedbackLoopAspects aspects = FeedbackLoopAspects; - - if ((aspects & FeedbackLoopAspects.Color) != 0) - { - pipelineCreateInfo.Flags |= PipelineCreateFlags.CreateColorAttachmentFeedbackLoopBitExt; - } - - if ((aspects & FeedbackLoopAspects.Depth) != 0) - { - pipelineCreateInfo.Flags |= PipelineCreateFlags.CreateDepthStencilAttachmentFeedbackLoopBitExt; - } - } - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) { pipelineCreateInfo.PTessellationState = &tessellationState; From 6e132e9fd73cdb12eb233a4304ec64c2ab6c386f Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Fri, 13 Sep 2024 15:28:21 -0700 Subject: [PATCH 120/132] Style correction --- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 647b77c20..1e12dead6 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -493,11 +493,10 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.PipelineRasterizationStateCreateInfo, DepthClampEnable = DepthClampEnable, + // When widelines feature is not supported it must be 1.0f, this will be ignored if Line Width dynamic state is supported + LineWidth = 1.0f, }; - // When widelines feature is not supported it must be 1.0f, this will be ignored if Line Width dynamic state is supported - rasterizationState.LineWidth = 1.0f; - var viewportState = new PipelineViewportStateCreateInfo { SType = StructureType.PipelineViewportStateCreateInfo, From 72e57e4c6e178cffaf8b1b2ddabfb7938c22f396 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 14 Sep 2024 01:12:35 -0700 Subject: [PATCH 121/132] Resolve validation error --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 1 + src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 171646917..1bf9d31f8 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1704,6 +1704,7 @@ namespace Ryujinx.Graphics.Vulkan { if (Gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop) { + _newState.FeedbackLoopDynamicState = true; DynamicState.SetFeedbackLoop(aspects); } else if (Gd.Capabilities.SupportsAttachmentFeedbackLoop) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 1e12dead6..50f24f7d2 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -246,6 +246,7 @@ namespace Ryujinx.Graphics.Vulkan } public bool HasTessellationControlShader; + public bool FeedbackLoopDynamicState; public NativeArray Stages; public PipelineLayout PipelineLayout; public SpecData SpecializationData; @@ -659,7 +660,7 @@ namespace Ryujinx.Graphics.Vulkan PipelineCreateFlags pipelineCreateFlags = 0; - if (gd.Capabilities.SupportsAttachmentFeedbackLoop) + if (gd.Capabilities.SupportsAttachmentFeedbackLoop && !_supportsFeedBackLoopDynamicState) { FeedbackLoopAspects aspects = FeedbackLoopAspects; @@ -672,11 +673,12 @@ namespace Ryujinx.Graphics.Vulkan { pipelineCreateFlags |= PipelineCreateFlags.CreateDepthStencilAttachmentFeedbackLoopBitExt; } + } - if (_supportsFeedBackLoopDynamicState && pipelineCreateFlags != 0) - { - dynamicStates[dynamicStatesCount++] = DynamicState.AttachmentFeedbackLoopEnableExt; - } + if (_supportsFeedBackLoopDynamicState && FeedbackLoopDynamicState) + { + dynamicStates[dynamicStatesCount++] = DynamicState.AttachmentFeedbackLoopEnableExt; + FeedbackLoopDynamicState = false; } var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo From 5df2022a6b04dacd3851813ef8a2d192176fa3a3 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 22 Sep 2024 17:03:35 -0700 Subject: [PATCH 122/132] Only call SignalStateChange if there has been a change. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 70 +++++++++++++++++---- src/Ryujinx.Graphics.Vulkan/PipelineUid.cs | 2 +- 2 files changed, 59 insertions(+), 13 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 1bf9d31f8..8b38bd7ac 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -76,6 +76,8 @@ namespace Ryujinx.Graphics.Vulkan private readonly BufferState[] _transformFeedbackBuffers; private readonly VertexBufferState[] _vertexBuffers; private ulong _vertexBuffersDirty; + private readonly int[] _vertexBufferBindings; + private bool _bindingsSet; protected Rectangle ClearScissor; private readonly VertexBufferUpdater _vertexBufferUpdater; @@ -135,6 +137,17 @@ namespace Ryujinx.Graphics.Vulkan _supportExtDynamic2 = gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2; + _vertexBufferBindings = new int[Constants.MaxVertexBuffers]; + + for (int i = 0; i < Constants.MaxVertexBuffers; i++) + { + _vertexBufferBindings[i] = i + 1; + } + + _bindingsSet = false; + + _newState.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, _supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31) ? null : 0, VertexInputRate.Vertex); + _newState.Initialize(gd.Capabilities); } @@ -1378,12 +1391,22 @@ namespace Ryujinx.Graphics.Vulkan { int count = Math.Min(Constants.MaxVertexBuffers, vertexBuffers.Length); - _newState.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, _supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31) ? null : 0, VertexInputRate.Vertex); - int validCount = 1; + if (!_bindingsSet) + { + for (int i = 0; i < count; i++) + { + _newState.Internal.VertexBindingDescriptions[_vertexBufferBindings[i]] = new VertexInputBindingDescription((uint)_vertexBufferBindings[i]); + } + + _bindingsSet = true; + } + BufferHandle lastHandle = default; Auto lastBuffer = default; + bool vertexBindingDescriptionChanged = false; + bool vertexDescriptionCountChanged = false; for (int i = 0; i < count; i++) { @@ -1402,13 +1425,28 @@ namespace Ryujinx.Graphics.Vulkan if (vb != null) { - int binding = i + 1; + //int binding = _vertexBufferBindings[i]; int descriptorIndex = validCount++; - _newState.Internal.VertexBindingDescriptions[descriptorIndex] = new VertexInputBindingDescription( - (uint)binding, - _supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31) ? null : (uint)vertexBuffer.Stride, - inputRate); + if (_supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31)) + { + if (_newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate != inputRate) + { + _newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate = inputRate; + + vertexBindingDescriptionChanged = true; + } + } + else + { + if (_newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate != inputRate || _newState.Internal.VertexBindingDescriptions[descriptorIndex].Stride != vertexBuffer.Stride) + { + _newState.Internal.VertexBindingDescriptions[descriptorIndex].Stride = (uint)vertexBuffer.Stride; + _newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate = inputRate; + + vertexBindingDescriptionChanged = true; + } + } int vbSize = vertexBuffer.Buffer.Size; @@ -1424,7 +1462,7 @@ namespace Ryujinx.Graphics.Vulkan } } - ref var buffer = ref _vertexBuffers[binding]; + ref var buffer = ref _vertexBuffers[_vertexBufferBindings[i]]; int oldScalarAlign = buffer.AttributeScalarAlignment; if (Gd.Capabilities.VertexBufferAlignment < 2 && @@ -1441,7 +1479,7 @@ namespace Ryujinx.Graphics.Vulkan vbSize, vertexBuffer.Stride); - buffer.BindVertexBuffer(Gd, Cbs, (uint)binding, ref _newState, _vertexBufferUpdater); + buffer.BindVertexBuffer(Gd, Cbs, (uint)_vertexBufferBindings[i], ref _newState, _vertexBufferUpdater); } } else @@ -1457,7 +1495,7 @@ namespace Ryujinx.Graphics.Vulkan vbSize, vertexBuffer.Stride); - _vertexBuffersDirty |= 1UL << binding; + _vertexBuffersDirty |= 1UL << _vertexBufferBindings[i]; } buffer.AttributeScalarAlignment = oldScalarAlign; @@ -1467,8 +1505,16 @@ namespace Ryujinx.Graphics.Vulkan _vertexBufferUpdater.Commit(Cbs); - _newState.VertexBindingDescriptionsCount = (uint)validCount; - SignalStateChange(); + if (_newState.VertexBindingDescriptionsCount != validCount) + { + _newState.VertexBindingDescriptionsCount = (uint)validCount; + vertexDescriptionCountChanged = true; + } + + if (vertexDescriptionCountChanged || vertexBindingDescriptionChanged) + { + SignalStateChange(); + } } public void SetViewports(ReadOnlySpan viewports) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs b/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs index 18c0464ee..1a9e58d88 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs @@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Vulkan private readonly bool HasDepthStencil => ((Id1 >> 63) & 0x1) != 0UL; public Array32 VertexAttributeDescriptions; - public Array33 VertexBindingDescriptions; + public Array32 VertexBindingDescriptions; public Array8 ColorBlendAttachmentState; public Array9 AttachmentFormats; public uint AttachmentIntegerFormatMask; From 92f8d211c6f724617f1769da483b1fd5ce1e2766 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 22 Sep 2024 17:25:34 -0700 Subject: [PATCH 123/132] As SetPrimitiveTopology will call SignalStateChange so no need to call it again. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 5f3158a34..28c37af40 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -658,7 +658,7 @@ namespace Ryujinx.Graphics.Vulkan bool oldStencilTestEnable; bool oldDepthTestEnable; bool oldDepthWriteEnable; - Silk.NET.Vulkan.PrimitiveTopology oldTopology; + PrimitiveTopology oldTopology; Array16 oldViewports = DynamicState.Viewports; uint oldViewportsCount; @@ -668,7 +668,7 @@ namespace Ryujinx.Graphics.Vulkan oldStencilTestEnable = DynamicState.StencilTestEnable; oldDepthTestEnable = DynamicState.DepthTestEnable; oldDepthWriteEnable = DynamicState.DepthWriteEnable; - oldTopology = DynamicState.Topology; + oldTopology = _topology; oldViewportsCount = DynamicState.ViewportsCount; } else @@ -705,8 +705,6 @@ namespace Ryujinx.Graphics.Vulkan srcRegion, dstRegion); - SetPrimitiveTopology(oldTopology); - if (_supportExtDynamic) { DynamicState.SetCullMode(oldCullMode); @@ -722,9 +720,9 @@ namespace Ryujinx.Graphics.Vulkan _newState.ViewportsCount = oldViewportsCount; } - DynamicState.SetViewports(ref oldViewports, oldViewportsCount); + SetPrimitiveTopology(oldTopology); - SignalStateChange(); + DynamicState.SetViewports(ref oldViewports, oldViewportsCount); } } From 5350e43f458bd35e0c39f690f1b9635571cd6e87 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 22 Sep 2024 18:32:13 -0700 Subject: [PATCH 124/132] Theoretically avoid calling SignalStateChange when another command will set it --- src/Ryujinx.Graphics.GAL/IPipeline.cs | 12 +-- .../Multithreading/ThreadedPipeline.cs | 12 +-- src/Ryujinx.Graphics.OpenGL/Pipeline.cs | 12 +-- .../Effects/SmaaPostProcessingEffect.cs | 4 +- src/Ryujinx.Graphics.Vulkan/HelperShader.cs | 78 +++++++++---------- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 44 +++++++---- .../PipelineHelperShader.cs | 8 +- 7 files changed, 95 insertions(+), 75 deletions(-) diff --git a/src/Ryujinx.Graphics.GAL/IPipeline.cs b/src/Ryujinx.Graphics.GAL/IPipeline.cs index 1ecbb402c..f10db1c2d 100644 --- a/src/Ryujinx.Graphics.GAL/IPipeline.cs +++ b/src/Ryujinx.Graphics.GAL/IPipeline.cs @@ -50,7 +50,7 @@ namespace Ryujinx.Graphics.GAL void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp); void SetDepthClamp(bool clamp); void SetDepthMode(DepthMode mode); - void SetDepthTest(DepthTestDescriptor depthTest); + void SetDepthTest(DepthTestDescriptor depthTest, bool signalChange = true); void SetFaceCulling(Face face); @@ -75,16 +75,16 @@ namespace Ryujinx.Graphics.GAL void SetPrimitiveRestart(bool enable, int index); - void SetPrimitiveTopology(PrimitiveTopology topology); + void SetPrimitiveTopology(PrimitiveTopology topology, bool signalChange = true); - void SetProgram(IProgram program); + void SetProgram(IProgram program, bool signalChange = true); void SetRasterizerDiscard(bool discard); - void SetRenderTargetColorMasks(ReadOnlySpan componentMask); + void SetRenderTargetColorMasks(ReadOnlySpan componentMask, bool signalChange = true); void SetRenderTargets(ITexture[] colors, ITexture depthStencil); - void SetScissors(ReadOnlySpan> regions); + void SetScissors(ReadOnlySpan> regions, bool signalChange = true); void SetStencilTest(StencilTestDescriptor stencilTest); @@ -102,7 +102,7 @@ namespace Ryujinx.Graphics.GAL void SetVertexAttribs(ReadOnlySpan vertexAttribs); void SetVertexBuffers(ReadOnlySpan vertexBuffers); - void SetViewports(ReadOnlySpan viewports); + void SetViewports(ReadOnlySpan viewports, bool signalChange = true); void TextureBarrier(); void TextureBarrierTiled(); diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs index cee3480fe..7d4bda1c4 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs @@ -159,7 +159,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading _renderer.QueueCommand(); } - public void SetDepthTest(DepthTestDescriptor depthTest) + public void SetDepthTest(DepthTestDescriptor depthTest, bool signalChange = true) { _renderer.New().Set(depthTest); _renderer.QueueCommand(); @@ -243,13 +243,13 @@ namespace Ryujinx.Graphics.GAL.Multithreading _renderer.QueueCommand(); } - public void SetPrimitiveTopology(PrimitiveTopology topology) + public void SetPrimitiveTopology(PrimitiveTopology topology, bool signalChange = true) { _renderer.New().Set(topology); _renderer.QueueCommand(); } - public void SetProgram(IProgram program) + public void SetProgram(IProgram program, bool signalChange = true) { _renderer.New().Set(Ref(program)); _renderer.QueueCommand(); @@ -261,7 +261,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading _renderer.QueueCommand(); } - public void SetRenderTargetColorMasks(ReadOnlySpan componentMask) + public void SetRenderTargetColorMasks(ReadOnlySpan componentMask, bool signalChange = true) { _renderer.New().Set(_renderer.CopySpan(componentMask)); _renderer.QueueCommand(); @@ -273,7 +273,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading _renderer.QueueCommand(); } - public void SetScissors(ReadOnlySpan> scissors) + public void SetScissors(ReadOnlySpan> scissors, bool signalChange = true) { _renderer.New().Set(_renderer.CopySpan(scissors)); _renderer.QueueCommand(); @@ -339,7 +339,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading _renderer.QueueCommand(); } - public void SetViewports(ReadOnlySpan viewports) + public void SetViewports(ReadOnlySpan viewports, bool signalChange = true) { _renderer.New().Set(_renderer.CopySpan(viewports)); _renderer.QueueCommand(); diff --git a/src/Ryujinx.Graphics.OpenGL/Pipeline.cs b/src/Ryujinx.Graphics.OpenGL/Pipeline.cs index ac6bc3f17..b75d4930e 100644 --- a/src/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/src/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -898,7 +898,7 @@ namespace Ryujinx.Graphics.OpenGL } } - public void SetDepthTest(DepthTestDescriptor depthTest) + public void SetDepthTest(DepthTestDescriptor depthTest, bool signalChange = true) { if (depthTest.TestEnable) { @@ -1107,12 +1107,12 @@ namespace Ryujinx.Graphics.OpenGL GL.Enable(EnableCap.PrimitiveRestart); } - public void SetPrimitiveTopology(PrimitiveTopology topology) + public void SetPrimitiveTopology(PrimitiveTopology topology, bool signalChange = true) { _primitiveType = topology.Convert(); } - public void SetProgram(IProgram program) + public void SetProgram(IProgram program, bool signalChange = true) { Program prg = (Program)program; @@ -1154,7 +1154,7 @@ namespace Ryujinx.Graphics.OpenGL _rasterizerDiscard = discard; } - public void SetRenderTargetColorMasks(ReadOnlySpan componentMasks) + public void SetRenderTargetColorMasks(ReadOnlySpan componentMasks, bool signalChange = true) { _componentMasks = 0; @@ -1195,7 +1195,7 @@ namespace Ryujinx.Graphics.OpenGL _framebuffer.SetDrawBuffers(colors.Length); } - public void SetScissors(ReadOnlySpan> regions) + public void SetScissors(ReadOnlySpan> regions, bool signalChange = true) { int count = Math.Min(regions.Length, Constants.MaxViewports); @@ -1388,7 +1388,7 @@ namespace Ryujinx.Graphics.OpenGL _vertexArray.SetVertexBuffers(vertexBuffers); } - public void SetViewports(ReadOnlySpan viewports) + public void SetViewports(ReadOnlySpan viewports, bool signalChange = true) { Array.Resize(ref _viewportArray, viewports.Length * 4); Array.Resize(ref _depthRangeArray, viewports.Length * 2); diff --git a/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs b/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs index a8e68f429..555151992 100644 --- a/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs +++ b/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs @@ -257,8 +257,8 @@ namespace Ryujinx.Graphics.Vulkan.Effects scissors[0] = new Rectangle(0, 0, texture.Width, texture.Height); - _pipeline.SetRenderTarget(texture, (uint)texture.Width, (uint)texture.Height); - _pipeline.SetRenderTargetColorMasks(colorMasks); + _pipeline.SetRenderTarget(texture, (uint)texture.Width, (uint)texture.Height, false); + _pipeline.SetRenderTargetColorMasks(colorMasks, false); _pipeline.SetScissors(scissors); _pipeline.ClearRenderTargetColor(0, 0, 1, new ColorF(0f, 0f, 0f, 1f)); } diff --git a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs index b7c42aff0..ce4f58057 100644 --- a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs +++ b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs @@ -429,35 +429,35 @@ namespace Ryujinx.Graphics.Vulkan if (dstIsDepthOrStencil) { - _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programDepthBlitMs : _programDepthBlit); - _pipeline.SetDepthTest(new DepthTestDescriptor(true, true, CompareOp.Always)); + _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programDepthBlitMs : _programDepthBlit, false); + _pipeline.SetDepthTest(new DepthTestDescriptor(true, true, CompareOp.Always), false); } else if (src.Info.Target.IsMultisample()) { - _pipeline.SetProgram(_programColorBlitMs); + _pipeline.SetProgram(_programColorBlitMs, false); } else if (clearAlpha) { - _pipeline.SetProgram(_programColorBlitClearAlpha); + _pipeline.SetProgram(_programColorBlitClearAlpha, false); } else { - _pipeline.SetProgram(_programColorBlit); + _pipeline.SetProgram(_programColorBlit, false); } int dstWidth = dst.Width; int dstHeight = dst.Height; - _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight); - _pipeline.SetRenderTargetColorMasks(new uint[] { 0xf }); - _pipeline.SetScissors(stackalloc Rectangle[] { new Rectangle(0, 0, dstWidth, dstHeight) }); + _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, false); + _pipeline.SetRenderTargetColorMasks(new uint[] { 0xf }, false); + _pipeline.SetScissors(stackalloc Rectangle[] { new Rectangle(0, 0, dstWidth, dstHeight) }, false); if (clearAlpha) { _pipeline.ClearRenderTargetColor(0, 0, 1, new ColorF(0f, 0f, 0f, 1f)); } - _pipeline.SetViewports(viewports); + _pipeline.SetViewports(viewports, false); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.Draw(4, 1, 0, 0); @@ -524,10 +524,10 @@ namespace Ryujinx.Graphics.Vulkan int dstWidth = dst.Width; int dstHeight = dst.Height; - _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight); - _pipeline.SetScissors(stackalloc Rectangle[] { new Rectangle(0, 0, dstWidth, dstHeight) }); - _pipeline.SetViewports(viewports); - _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); + _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, false); + _pipeline.SetScissors(stackalloc Rectangle[] { new Rectangle(0, 0, dstWidth, dstHeight) }, false); + _pipeline.SetViewports(viewports, false); + _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip, false); var aspectFlags = src.Info.Format.ConvertAspectFlags(); @@ -589,12 +589,12 @@ namespace Ryujinx.Graphics.Vulkan if (isDepth) { - _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programDepthBlitMs : _programDepthBlit); + _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programDepthBlitMs : _programDepthBlit, false); _pipeline.SetDepthTest(new DepthTestDescriptor(true, true, CompareOp.Always)); } else { - _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programStencilBlitMs : _programStencilBlit); + _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programStencilBlitMs : _programStencilBlit, false); _pipeline.SetStencilTest(CreateStencilTestDescriptor(true)); } @@ -684,11 +684,11 @@ namespace Ryujinx.Graphics.Vulkan program = _programColorClearF; } - _pipeline.SetProgram(program); - _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight); - _pipeline.SetRenderTargetColorMasks(new[] { componentMask }); - _pipeline.SetViewports(viewports); - _pipeline.SetScissors(stackalloc Rectangle[] { scissor }); + _pipeline.SetProgram(program, false); + _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, false); + _pipeline.SetRenderTargetColorMasks(new[] { componentMask }, false); + _pipeline.SetViewports(viewports, false); + _pipeline.SetScissors(stackalloc Rectangle[] { scissor }, false); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.Draw(4, 1, 0, 0); _pipeline.Finish(); @@ -731,12 +731,12 @@ namespace Ryujinx.Graphics.Vulkan 0f, 1f); - _pipeline.SetProgram(_programDepthStencilClear); - _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight); - _pipeline.SetViewports(viewports); - _pipeline.SetScissors(stackalloc Rectangle[] { scissor }); - _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); - _pipeline.SetDepthTest(new DepthTestDescriptor(true, depthMask, CompareOp.Always)); + _pipeline.SetProgram(_programDepthStencilClear, false); + _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, false); + _pipeline.SetViewports(viewports, false); + _pipeline.SetScissors(stackalloc Rectangle[] { scissor }, false); + _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip, false); + _pipeline.SetDepthTest(new DepthTestDescriptor(true, depthMask, CompareOp.Always), false); _pipeline.SetStencilTest(CreateStencilTestDescriptor(stencilMask != 0, stencilValue, 0xff, stencilMask)); _pipeline.Draw(4, 1, 0, 0); _pipeline.Finish(); @@ -794,8 +794,8 @@ namespace Ryujinx.Graphics.Vulkan 0f, 1f); - pipeline.SetProgram(_programColorBlit); - pipeline.SetViewports(viewports); + pipeline.SetProgram(_programColorBlit, false); + pipeline.SetViewports(viewports, false); pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); pipeline.Draw(4, 1, 0, 0); @@ -1129,16 +1129,16 @@ namespace Ryujinx.Graphics.Vulkan 0f, 1f); - _pipeline.SetScissors(stackalloc Rectangle[] { new Rectangle(0, 0, dst.Width, dst.Height) }); - _pipeline.SetViewports(viewports); - _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); + _pipeline.SetScissors(stackalloc Rectangle[] { new Rectangle(0, 0, dst.Width, dst.Height) }, false); + _pipeline.SetViewports(viewports, false); + _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip, false); for (int z = 0; z < depth; z++) { var srcView = Create2DLayerView(src, srcLayer + z, 0); var dstView = Create2DLayerView(dst, dstLayer + z, 0); - _pipeline.SetRenderTarget(dstView, (uint)dst.Width, (uint)dst.Height); + _pipeline.SetRenderTarget(dstView, (uint)dst.Width, (uint)dst.Height, false); CopyMSDraw(srcView, aspectFlags, fromMS: true); @@ -1251,9 +1251,9 @@ namespace Ryujinx.Graphics.Vulkan 1f); _pipeline.SetRenderTargetColorMasks(new uint[] { 0xf }); - _pipeline.SetScissors(stackalloc Rectangle[] { new Rectangle(0, 0, dst.Width, dst.Height) }); - _pipeline.SetViewports(viewports); - _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); + _pipeline.SetScissors(stackalloc Rectangle[] { new Rectangle(0, 0, dst.Width, dst.Height) }, false); + _pipeline.SetViewports(viewports, false); + _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip, false); _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, buffer.Range) }); @@ -1264,7 +1264,7 @@ namespace Ryujinx.Graphics.Vulkan var srcView = Create2DLayerView(src, srcLayer + z, 0); var dstView = Create2DLayerView(dst, dstLayer + z, 0); - _pipeline.SetRenderTarget(dstView, (uint)dst.Width, (uint)dst.Height); + _pipeline.SetRenderTarget(dstView, (uint)dst.Width, (uint)dst.Height, false); CopyMSDraw(srcView, aspectFlags, fromMS: false); @@ -1281,7 +1281,7 @@ namespace Ryujinx.Graphics.Vulkan } else { - _pipeline.SetProgram(_programColorDrawToMs); + _pipeline.SetProgram(_programColorDrawToMs, false); var format = GetFormat(src.Info.BytesPerPixel); var vkFormat = FormatTable.GetFormat(format); @@ -1358,12 +1358,12 @@ namespace Ryujinx.Graphics.Vulkan if (isDepth) { - _pipeline.SetProgram(fromMS ? _programDepthDrawToNonMs : _programDepthDrawToMs); + _pipeline.SetProgram(fromMS ? _programDepthDrawToNonMs : _programDepthDrawToMs, false); _pipeline.SetDepthTest(new DepthTestDescriptor(true, true, CompareOp.Always)); } else { - _pipeline.SetProgram(fromMS ? _programStencilDrawToNonMs : _programStencilDrawToMs); + _pipeline.SetProgram(fromMS ? _programStencilDrawToNonMs : _programStencilDrawToMs, false); _pipeline.SetStencilTest(CreateStencilTestDescriptor(true)); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 28c37af40..96d22e878 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -693,8 +693,6 @@ namespace Ryujinx.Graphics.Vulkan _newState.StencilTestEnable = false; _newState.DepthTestEnable = false; _newState.DepthWriteEnable = false; - - SignalStateChange(); } Gd.HelperShader.DrawTexture( @@ -896,7 +894,7 @@ namespace Ryujinx.Graphics.Vulkan SignalStateChange(); } - public void SetDepthTest(DepthTestDescriptor depthTest) + public void SetDepthTest(DepthTestDescriptor depthTest, bool signalChange = true) { if (_supportExtDynamic) { @@ -912,7 +910,10 @@ namespace Ryujinx.Graphics.Vulkan _newState.DepthWriteEnable = depthTest.WriteEnable; _newState.DepthCompareOp = depthTest.Func.Convert(); - SignalStateChange(); + if (signalChange) + { + SignalStateChange(); + } } UpdatePassDepthStencil(); @@ -1062,7 +1063,7 @@ namespace Ryujinx.Graphics.Vulkan // TODO: What to do about the index? } - public void SetPrimitiveTopology(PrimitiveTopology topology) + public void SetPrimitiveTopology(PrimitiveTopology topology, bool signalChange = true) { _topology = topology; @@ -1075,10 +1076,13 @@ namespace Ryujinx.Graphics.Vulkan DynamicState.SetPrimitiveTopology(vkTopology); } - SignalStateChange(); + if (signalChange) + { + SignalStateChange(); + } } - public void SetProgram(IProgram program) + public void SetProgram(IProgram program, bool signalChange = true) { var internalProgram = (ShaderCollection)program; var stages = internalProgram.GetInfos(); @@ -1094,7 +1098,10 @@ namespace Ryujinx.Graphics.Vulkan stages.CopyTo(_newState.Stages.AsSpan()[..stages.Length]); - SignalStateChange(); + if (signalChange) + { + SignalStateChange(); + } if (internalProgram.IsCompute) { @@ -1139,7 +1146,7 @@ namespace Ryujinx.Graphics.Vulkan } } - public void SetRenderTargetColorMasks(ReadOnlySpan componentMask) + public void SetRenderTargetColorMasks(ReadOnlySpan componentMask, bool signalChange = true) { int count = Math.Min(Constants.MaxRenderTargets, componentMask.Length); int writtenAttachments = 0; @@ -1179,7 +1186,10 @@ namespace Ryujinx.Graphics.Vulkan } else { - SignalStateChange(); + if (signalChange) + { + SignalStateChange(); + } if (writtenAttachments != _writtenAttachmentCount) { @@ -1203,7 +1213,7 @@ namespace Ryujinx.Graphics.Vulkan SetRenderTargetsInternal(colors, depthStencil, Gd.IsTBDR); } - public void SetScissors(ReadOnlySpan> regions) + public void SetScissors(ReadOnlySpan> regions, bool signalChange = true) { int maxScissors = Gd.Capabilities.SupportsMultiView ? Constants.MaxViewports : 1; int count = Math.Min(maxScissors, regions.Length); @@ -1227,7 +1237,10 @@ namespace Ryujinx.Graphics.Vulkan { _newState.ScissorsCount = (uint)count; - SignalStateChange(); + if (signalChange) + { + SignalStateChange(); + } } } @@ -1514,7 +1527,7 @@ namespace Ryujinx.Graphics.Vulkan } } - public void SetViewports(ReadOnlySpan viewports) + public void SetViewports(ReadOnlySpan viewports, bool signalChange = true) { int maxViewports = Gd.Capabilities.SupportsMultiView ? Constants.MaxViewports : 1; int count = Math.Min(maxViewports, viewports.Length); @@ -1543,7 +1556,10 @@ namespace Ryujinx.Graphics.Vulkan { _newState.ViewportsCount = (uint)count; - SignalStateChange(); + if (signalChange) + { + SignalStateChange(); + } } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineHelperShader.cs b/src/Ryujinx.Graphics.Vulkan/PipelineHelperShader.cs index dfbf19013..9a29d3fc9 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineHelperShader.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineHelperShader.cs @@ -9,11 +9,15 @@ namespace Ryujinx.Graphics.Vulkan { } - public void SetRenderTarget(TextureView view, uint width, uint height) + public void SetRenderTarget(TextureView view, uint width, uint height, bool signalChange = true) { CreateFramebuffer(view, width, height); CreateRenderPass(); - SignalStateChange(); + + if (signalChange) + { + SignalStateChange(); + } } private void CreateFramebuffer(TextureView view, uint width, uint height) From afb0ce878512942fa5ee740910ed5300913e0e04 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 28 Sep 2024 09:17:58 -0700 Subject: [PATCH 125/132] Not needed --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 96d22e878..e08376882 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -76,7 +76,6 @@ namespace Ryujinx.Graphics.Vulkan private readonly BufferState[] _transformFeedbackBuffers; private readonly VertexBufferState[] _vertexBuffers; private ulong _vertexBuffersDirty; - private readonly int[] _vertexBufferBindings; private bool _bindingsSet; protected Rectangle ClearScissor; @@ -137,13 +136,6 @@ namespace Ryujinx.Graphics.Vulkan _supportExtDynamic2 = gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2; - _vertexBufferBindings = new int[Constants.MaxVertexBuffers]; - - for (int i = 0; i < Constants.MaxVertexBuffers; i++) - { - _vertexBufferBindings[i] = i + 1; - } - _bindingsSet = false; _newState.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, _supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31) ? null : 0, VertexInputRate.Vertex); @@ -1407,7 +1399,7 @@ namespace Ryujinx.Graphics.Vulkan { for (int i = 0; i < count; i++) { - _newState.Internal.VertexBindingDescriptions[_vertexBufferBindings[i]] = new VertexInputBindingDescription((uint)_vertexBufferBindings[i]); + _newState.Internal.VertexBindingDescriptions[i] = new VertexInputBindingDescription((uint)i); } _bindingsSet = true; @@ -1435,7 +1427,6 @@ namespace Ryujinx.Graphics.Vulkan if (vb != null) { - //int binding = _vertexBufferBindings[i]; int descriptorIndex = validCount++; if (_supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31)) @@ -1472,7 +1463,7 @@ namespace Ryujinx.Graphics.Vulkan } } - ref var buffer = ref _vertexBuffers[_vertexBufferBindings[i]]; + ref var buffer = ref _vertexBuffers[i]; int oldScalarAlign = buffer.AttributeScalarAlignment; if (Gd.Capabilities.VertexBufferAlignment < 2 && @@ -1489,7 +1480,7 @@ namespace Ryujinx.Graphics.Vulkan vbSize, vertexBuffer.Stride); - buffer.BindVertexBuffer(Gd, Cbs, (uint)_vertexBufferBindings[i], ref _newState, _vertexBufferUpdater); + buffer.BindVertexBuffer(Gd, Cbs, (uint)i, ref _newState, _vertexBufferUpdater); } } else @@ -1505,7 +1496,7 @@ namespace Ryujinx.Graphics.Vulkan vbSize, vertexBuffer.Stride); - _vertexBuffersDirty |= 1UL << _vertexBufferBindings[i]; + _vertexBuffersDirty |= 1UL << i; } buffer.AttributeScalarAlignment = oldScalarAlign; From 4e501f1a7082b0ea2d5f0d3250828d5d476acb99 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sat, 28 Sep 2024 10:46:01 -0700 Subject: [PATCH 126/132] Fix vertex buffer binding indices in Vulkan pipeline introduced from previous commit. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index e08376882..7ea06b3de 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1397,7 +1397,7 @@ namespace Ryujinx.Graphics.Vulkan if (!_bindingsSet) { - for (int i = 0; i < count; i++) + for (int i = 1; i < count; i++) { _newState.Internal.VertexBindingDescriptions[i] = new VertexInputBindingDescription((uint)i); } @@ -1463,7 +1463,7 @@ namespace Ryujinx.Graphics.Vulkan } } - ref var buffer = ref _vertexBuffers[i]; + ref var buffer = ref _vertexBuffers[descriptorIndex]; int oldScalarAlign = buffer.AttributeScalarAlignment; if (Gd.Capabilities.VertexBufferAlignment < 2 && @@ -1480,7 +1480,7 @@ namespace Ryujinx.Graphics.Vulkan vbSize, vertexBuffer.Stride); - buffer.BindVertexBuffer(Gd, Cbs, (uint)i, ref _newState, _vertexBufferUpdater); + buffer.BindVertexBuffer(Gd, Cbs, (uint)descriptorIndex, ref _newState, _vertexBufferUpdater); } } else @@ -1496,7 +1496,7 @@ namespace Ryujinx.Graphics.Vulkan vbSize, vertexBuffer.Stride); - _vertexBuffersDirty |= 1UL << i; + _vertexBuffersDirty |= 1UL << descriptorIndex; } buffer.AttributeScalarAlignment = oldScalarAlign; From 95a0344eb4c5f29faea3fe64916eafd617f4ce96 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 29 Sep 2024 16:53:56 -0700 Subject: [PATCH 127/132] Update shader cache handling to process old versions --- src/Ryujinx.Graphics.GAL/Capabilities.cs | 12 +++ .../Shader/DiskCache/DiskCacheHostStorage.cs | 2 +- .../DiskCache/ParallelDiskCacheLoader.cs | 78 +++++++++++++++++-- src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs | 4 + src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 4 + 5 files changed, 93 insertions(+), 7 deletions(-) diff --git a/src/Ryujinx.Graphics.GAL/Capabilities.cs b/src/Ryujinx.Graphics.GAL/Capabilities.cs index a5c6eb5c8..cdbd44fad 100644 --- a/src/Ryujinx.Graphics.GAL/Capabilities.cs +++ b/src/Ryujinx.Graphics.GAL/Capabilities.cs @@ -50,6 +50,10 @@ namespace Ryujinx.Graphics.GAL public readonly bool SupportsViewportSwizzle; public readonly bool SupportsIndirectParameters; public readonly bool SupportsDepthClipControl; + public readonly bool SupportsExtendedDynamicState; + public readonly bool SupportsExtendedDynamicState2; + public readonly bool SupportsLogicOpDynamicState; + public readonly bool SupportsPatchControlPointsDynamicState; public readonly int UniformBufferSetIndex; public readonly int StorageBufferSetIndex; @@ -116,6 +120,10 @@ namespace Ryujinx.Graphics.GAL bool supportsViewportSwizzle, bool supportsIndirectParameters, bool supportsDepthClipControl, + bool supportsExtendedDynamicState, + bool supportsExtendedDynamicState2, + bool supportsLogicOpDynamicState, + bool supportsPatchControlPointsDynamicState, int uniformBufferSetIndex, int storageBufferSetIndex, int textureSetIndex, @@ -177,6 +185,10 @@ namespace Ryujinx.Graphics.GAL SupportsViewportSwizzle = supportsViewportSwizzle; SupportsIndirectParameters = supportsIndirectParameters; SupportsDepthClipControl = supportsDepthClipControl; + SupportsExtendedDynamicState = supportsExtendedDynamicState; + SupportsExtendedDynamicState2 = supportsExtendedDynamicState2; + SupportsLogicOpDynamicState = supportsLogicOpDynamicState; + SupportsPatchControlPointsDynamicState = supportsPatchControlPointsDynamicState; UniformBufferSetIndex = uniformBufferSetIndex; StorageBufferSetIndex = storageBufferSetIndex; TextureSetIndex = textureSetIndex; diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs index a5c5abd4b..3f3c3723d 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs @@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache private const ushort FileFormatVersionMajor = 1; private const ushort FileFormatVersionMinor = 2; private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor; - private const uint CodeGenVersion = 7331; + private const uint CodeGenVersion = 7332; private const string SharedTocFileName = "shared.toc"; private const string SharedDataFileName = "shared.data"; diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs index 20f96462e..2db19096c 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs @@ -232,10 +232,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache for (int index = 0; index < ThreadCount; index++) { - workThreads[index] = new Thread(ProcessAsyncQueue) - { - Name = $"GPU.AsyncTranslationThread.{index}", - }; + workThreads[index] = new Thread(ProcessAsyncQueue) { Name = $"GPU.AsyncTranslationThread.{index}", }; } int programCount = _hostStorage.GetProgramCount(); @@ -305,6 +302,9 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache using var streams = _hostStorage.GetOutputStreams(_context); int packagedShaders = 0; + ProgramPipelineState previousPipelineState = default; + ProgramPipelineState currentPipelineState = default; + foreach (var kv in _programList) { if (!Active) @@ -314,9 +314,53 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache (CachedShaderProgram program, byte[] binaryCode) = kv.Value; - _hostStorage.AddShader(_context, program, binaryCode, streams); + if (program.SpecializationState.PipelineState.HasValue && _context.Capabilities.SupportsExtendedDynamicState) + { + currentPipelineState = program.SpecializationState.PipelineState.Value; - _stateChangeCallback(ShaderCacheState.Packaging, ++packagedShaders, _programList.Count); + if (_context.Capabilities.SupportsExtendedDynamicState) + { + currentPipelineState.StencilTest = default; + + currentPipelineState.CullMode = 0; + currentPipelineState.FrontFace = 0; + currentPipelineState.DepthTest = default; + currentPipelineState.Topology = ConvertToClass(currentPipelineState.Topology); + } + + if (_context.Capabilities.SupportsExtendedDynamicState2) + { + currentPipelineState.PrimitiveRestartEnable = false; + currentPipelineState.BiasEnable = 0; + currentPipelineState.RasterizerDiscard = false; + + } + + if (_context.Capabilities.SupportsLogicOpDynamicState) + { + currentPipelineState.LogicOp = 0; + } + + if (_context.Capabilities.SupportsPatchControlPointsDynamicState) + { + currentPipelineState.PatchControlPoints = 0; + } + + currentPipelineState = program.SpecializationState.PipelineState.Value; + } + + + if (currentPipelineState.Equals(previousPipelineState) || !_context.Capabilities.SupportsExtendedDynamicState) + { + _hostStorage.AddShader(_context, program, binaryCode, streams); + + _stateChangeCallback(ShaderCacheState.Packaging, ++packagedShaders, _programList.Count); + } + + if (_context.Capabilities.SupportsExtendedDynamicState) + { + previousPipelineState = currentPipelineState; + } } Logger.Info?.Print(LogClass.Gpu, $"Rebuilt {_programList.Count} shaders successfully."); @@ -343,6 +387,28 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache _stateChangeCallback(ShaderCacheState.Loaded, programCount, programCount); } + private PrimitiveTopology ConvertToClass(PrimitiveTopology topology) + { + return topology switch + { + PrimitiveTopology.Points => PrimitiveTopology.Points, + PrimitiveTopology.Lines or + PrimitiveTopology.LineStrip or + PrimitiveTopology.LinesAdjacency or + PrimitiveTopology.LineStripAdjacency => PrimitiveTopology.Lines, + PrimitiveTopology.Triangles or + PrimitiveTopology.TriangleStrip or + PrimitiveTopology.TriangleFan or + PrimitiveTopology.TrianglesAdjacency or + PrimitiveTopology.TriangleStripAdjacency or + PrimitiveTopology.Polygon => PrimitiveTopology.TriangleStrip, + PrimitiveTopology.Patches => PrimitiveTopology.Patches, + PrimitiveTopology.Quads => PrimitiveTopology.Quads, + PrimitiveTopology.QuadStrip => PrimitiveTopology.QuadStrip, + PrimitiveTopology.LineLoop => PrimitiveTopology.LineLoop, + }; + } + /// /// Enqueues a host program for compilation. /// diff --git a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs index ba9cd45c6..df2ca30de 100644 --- a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs +++ b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs @@ -187,6 +187,10 @@ namespace Ryujinx.Graphics.OpenGL supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle, supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters, supportsDepthClipControl: true, + supportsExtendedDynamicState: false, + supportsExtendedDynamicState2: false, + supportsLogicOpDynamicState: false, + supportsPatchControlPointsDynamicState: false, uniformBufferSetIndex: 0, storageBufferSetIndex: 1, textureSetIndex: 2, diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 376eb47ef..4ae0de460 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -793,6 +793,10 @@ namespace Ryujinx.Graphics.Vulkan supportsViewportSwizzle: false, supportsIndirectParameters: true, supportsDepthClipControl: Capabilities.SupportsDepthClipControl, + supportsExtendedDynamicState: Capabilities.SupportsExtendedDynamicState, + supportsExtendedDynamicState2: Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2, + supportsLogicOpDynamicState: Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp, + supportsPatchControlPointsDynamicState: Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints, uniformBufferSetIndex: PipelineBase.UniformSetIndex, storageBufferSetIndex: PipelineBase.StorageSetIndex, textureSetIndex: PipelineBase.TextureSetIndex, From acbd9eb98fdc4a6a6965c0cb36c22ea6b4486e68 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 29 Sep 2024 17:14:50 -0700 Subject: [PATCH 128/132] Set default Topology --- .../Shader/DiskCache/ParallelDiskCacheLoader.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs index 2db19096c..1e09f0bf9 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs @@ -363,7 +363,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache } } - Logger.Info?.Print(LogClass.Gpu, $"Rebuilt {_programList.Count} shaders successfully."); + Logger.Info?.Print(LogClass.Gpu, $"Rebuilt {packagedShaders} shaders successfully."); } else { @@ -406,6 +406,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache PrimitiveTopology.Quads => PrimitiveTopology.Quads, PrimitiveTopology.QuadStrip => PrimitiveTopology.QuadStrip, PrimitiveTopology.LineLoop => PrimitiveTopology.LineLoop, + _ => PrimitiveTopology.TriangleStrip, }; } From 7cc334b894cb2a6d51b95726b778abc956a93754 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Sun, 29 Sep 2024 18:11:44 -0700 Subject: [PATCH 129/132] Resolve some errors in logic --- .../Shader/DiskCache/ParallelDiskCacheLoader.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs index 1e09f0bf9..2661a828b 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs @@ -345,12 +345,9 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache { currentPipelineState.PatchControlPoints = 0; } - - currentPipelineState = program.SpecializationState.PipelineState.Value; } - - if (currentPipelineState.Equals(previousPipelineState) || !_context.Capabilities.SupportsExtendedDynamicState) + if (!currentPipelineState.Equals(previousPipelineState) || !_context.Capabilities.SupportsExtendedDynamicState || !program.SpecializationState.PipelineState.HasValue) { _hostStorage.AddShader(_context, program, binaryCode, streams); From 62165661662a2153f5de1b0131652e1963dcd845 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 30 Sep 2024 18:15:37 -0700 Subject: [PATCH 130/132] Update disk cache code generation version and use HashSet for processed pipelines Use a hashset to compare against all generated pipelines vs only against the most recent one. --- .../Shader/DiskCache/DiskCacheHostStorage.cs | 2 +- .../Shader/DiskCache/ParallelDiskCacheLoader.cs | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs index 3f3c3723d..32a592cb9 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs @@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache private const ushort FileFormatVersionMajor = 1; private const ushort FileFormatVersionMinor = 2; private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor; - private const uint CodeGenVersion = 7332; + private const uint CodeGenVersion = 6877; private const string SharedTocFileName = "shared.toc"; private const string SharedDataFileName = "shared.data"; diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs index 2661a828b..1aec895f0 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs @@ -22,6 +22,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache private readonly CancellationToken _cancellationToken; private readonly Action _stateChangeCallback; + private readonly HashSet _pipelineStateSet = new(); + /// /// Indicates if the cache should be loaded. /// @@ -302,7 +304,6 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache using var streams = _hostStorage.GetOutputStreams(_context); int packagedShaders = 0; - ProgramPipelineState previousPipelineState = default; ProgramPipelineState currentPipelineState = default; foreach (var kv in _programList) @@ -333,7 +334,6 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache currentPipelineState.PrimitiveRestartEnable = false; currentPipelineState.BiasEnable = 0; currentPipelineState.RasterizerDiscard = false; - } if (_context.Capabilities.SupportsLogicOpDynamicState) @@ -347,19 +347,20 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache } } - if (!currentPipelineState.Equals(previousPipelineState) || !_context.Capabilities.SupportsExtendedDynamicState || !program.SpecializationState.PipelineState.HasValue) + if (!_pipelineStateSet.Contains(currentPipelineState) || + !_context.Capabilities.SupportsExtendedDynamicState || + !program.SpecializationState.PipelineState.HasValue) { _hostStorage.AddShader(_context, program, binaryCode, streams); _stateChangeCallback(ShaderCacheState.Packaging, ++packagedShaders, _programList.Count); - } - if (_context.Capabilities.SupportsExtendedDynamicState) - { - previousPipelineState = currentPipelineState; + if (_context.Capabilities.SupportsExtendedDynamicState) + { + _pipelineStateSet.Add(currentPipelineState); + } } } - Logger.Info?.Print(LogClass.Gpu, $"Rebuilt {packagedShaders} shaders successfully."); } else From 45ce25e84702383ef0dc0f7edef029556b96b2dd Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 30 Sep 2024 21:04:39 -0700 Subject: [PATCH 131/132] Upon closer inspection actually descriptorIndex is only iterrated when there is a valid buffer, but bindings are always i+1. This could lead to potential errors. --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 25 ++++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 7ea06b3de..ee1671464 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -100,6 +100,8 @@ namespace Ryujinx.Graphics.Vulkan public ulong DrawCount { get; private set; } public bool RenderPassActive { get; private set; } + private readonly int[] _vertexBufferBindings; + public unsafe PipelineBase(VulkanRenderer gd, Device device) { Gd = gd; @@ -138,7 +140,11 @@ namespace Ryujinx.Graphics.Vulkan _bindingsSet = false; - _newState.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, _supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31) ? null : 0, VertexInputRate.Vertex); + _vertexBufferBindings = new int[Constants.MaxVertexBuffers]; + for (int i = 0; i < Constants.MaxVertexBuffers; i++) + { + _vertexBufferBindings[i] = i + 1; + } _newState.Initialize(gd.Capabilities); } @@ -1397,6 +1403,8 @@ namespace Ryujinx.Graphics.Vulkan if (!_bindingsSet) { + _newState.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, _supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31) ? null : 0, VertexInputRate.Vertex); + for (int i = 1; i < count; i++) { _newState.Internal.VertexBindingDescriptions[i] = new VertexInputBindingDescription((uint)i); @@ -1431,17 +1439,22 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31)) { - if (_newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate != inputRate) + if (_newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate != inputRate || + _newState.Internal.VertexBindingDescriptions[descriptorIndex].Binding != _vertexBufferBindings[i]) { _newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate = inputRate; + _newState.Internal.VertexBindingDescriptions[descriptorIndex].Binding = (uint)_vertexBufferBindings[i]; vertexBindingDescriptionChanged = true; } } else { - if (_newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate != inputRate || _newState.Internal.VertexBindingDescriptions[descriptorIndex].Stride != vertexBuffer.Stride) + if (_newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate != inputRate || + _newState.Internal.VertexBindingDescriptions[descriptorIndex].Stride != vertexBuffer.Stride || + _newState.Internal.VertexBindingDescriptions[descriptorIndex].Binding != _vertexBufferBindings[i]) { + _newState.Internal.VertexBindingDescriptions[descriptorIndex].Binding = (uint)_vertexBufferBindings[i]; _newState.Internal.VertexBindingDescriptions[descriptorIndex].Stride = (uint)vertexBuffer.Stride; _newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate = inputRate; @@ -1463,7 +1476,7 @@ namespace Ryujinx.Graphics.Vulkan } } - ref var buffer = ref _vertexBuffers[descriptorIndex]; + ref var buffer = ref _vertexBuffers[_vertexBufferBindings[i]]; int oldScalarAlign = buffer.AttributeScalarAlignment; if (Gd.Capabilities.VertexBufferAlignment < 2 && @@ -1480,7 +1493,7 @@ namespace Ryujinx.Graphics.Vulkan vbSize, vertexBuffer.Stride); - buffer.BindVertexBuffer(Gd, Cbs, (uint)descriptorIndex, ref _newState, _vertexBufferUpdater); + buffer.BindVertexBuffer(Gd, Cbs, (uint)_vertexBufferBindings[i], ref _newState, _vertexBufferUpdater); } } else @@ -1496,7 +1509,7 @@ namespace Ryujinx.Graphics.Vulkan vbSize, vertexBuffer.Stride); - _vertexBuffersDirty |= 1UL << descriptorIndex; + _vertexBuffersDirty |= 1UL << _vertexBufferBindings[i]; } buffer.AttributeScalarAlignment = oldScalarAlign; From ca7cc523499dfcc8f9912f9592d43bccb5eb0ecb Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Mon, 30 Sep 2024 21:11:41 -0700 Subject: [PATCH 132/132] Whitespace --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index ee1671464..fe5d13b59 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1439,7 +1439,7 @@ namespace Ryujinx.Graphics.Vulkan if (_supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31)) { - if (_newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate != inputRate || + if (_newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate != inputRate || _newState.Internal.VertexBindingDescriptions[descriptorIndex].Binding != _vertexBufferBindings[i]) { _newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate = inputRate; @@ -1450,8 +1450,8 @@ namespace Ryujinx.Graphics.Vulkan } else { - if (_newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate != inputRate || - _newState.Internal.VertexBindingDescriptions[descriptorIndex].Stride != vertexBuffer.Stride || + if (_newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate != inputRate || + _newState.Internal.VertexBindingDescriptions[descriptorIndex].Stride != vertexBuffer.Stride || _newState.Internal.VertexBindingDescriptions[descriptorIndex].Binding != _vertexBufferBindings[i]) { _newState.Internal.VertexBindingDescriptions[descriptorIndex].Binding = (uint)_vertexBufferBindings[i];