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 41618c736e..ad2c7f8661 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 c38748936b..a22f137d4e 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 238f06e2ac..9dfe786692 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 918de59b73..0aee69732f 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 ad2c7f8661..1a7cba1e53 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 1cc33f728c..31eb64d808 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 a22f137d4e..24586800e6 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 0aee69732f..096627e0b6 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 31eb64d808..7a1c39b04e 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 24586800e6..6182ccaa04 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 096627e0b6..3c67d952aa 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 1a7cba1e53..d0344ee4bb 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 7a1c39b04e..916b065bda 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 6182ccaa04..3dbc01f2d7 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 3dbc01f2d7..620ab291b8 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 3c67d952aa..b492338344 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 916b065bda..aaa97660a0 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 b6694bcb36..8c7089aa53 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 b492338344..301718974b 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 aaa97660a0..b5af582da1 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 620ab291b8..ddfd39070d 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 d59ca7e0ec..a8de50f6d1 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 86a347e019..e8dd766a00 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 301718974b..6881ba9110 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 b5af582da1..9ec4bbb59b 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 ddfd39070d..212062c695 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 6881ba9110..6b40249113 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 9ec4bbb59b..9b549ebc12 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 357d517eb3..73d5a088ac 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 6b40249113..0425d17bdb 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 9b549ebc12..b6bb954fbc 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 212062c695..f7a63a5da8 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 fc7145410d..b2fffd6c83 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 b2fffd6c83..fc7145410d 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 0425d17bdb..0fee64770f 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 d0344ee4bb..9bc16b4de8 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 8c7089aa53..952867642d 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 0fee64770f..6318008814 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 b6bb954fbc..efee04b10c 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 f7a63a5da8..94bab99e62 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 a8de50f6d1..b12f482026 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 e8dd766a00..c75c4a39f5 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 b12f482026..d6b4c7a87b 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 6318008814..bf22a120a5 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 9bc16b4de8..e8fbea9992 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 efee04b10c..783f2bf710 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 94bab99e62..7c6f6a83ff 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 d6b4c7a87b..6b4ca1d3d2 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 c75c4a39f5..1807711d67 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 a932475479..e737016291 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 952867642d..07c7e26180 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 bf22a120a5..5024fdd4e1 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 783f2bf710..90d75724ab 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 7c6f6a83ff..e4fe002d95 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 6b4ca1d3d2..4a1aa2b0be 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 1807711d67..69d0759511 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 4a1aa2b0be..ce3a34fdbe 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 90d75724ab..6a321c4c1b 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 e4fe002d95..57b531575a 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 6a321c4c1b..303633df0f 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 57b531575a..8415128541 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 ce3a34fdbe..8f9e926c18 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 8f9e926c18..1c8b675dcd 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 1c8b675dcd..8f9e926c18 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 8f9e926c18..3446941ab2 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 303633df0f..94bb9e1753 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 3446941ab2..1c8b675dcd 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 94bb9e1753..f1b802bed1 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 f1b802bed1..8f15cc61b6 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 5024fdd4e1..4b9d32ee92 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 8f15cc61b6..9126771a05 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 8415128541..01cf1741cf 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 1c8b675dcd..4b8c155263 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 4b9d32ee92..fff6cf05ec 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 9126771a05..bc9939d6cf 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 fff6cf05ec..e29fab3263 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 01cf1741cf..d461ab3234 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 e29fab3263..696b5c1cb6 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 bc9939d6cf..5d4b473d0b 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 d461ab3234..7ae909e16e 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 696b5c1cb6..f78184c3bc 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 7ae909e16e..4792799162 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 4792799162..3ddb21dad8 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 3ddb21dad8..8ab9f9dfd7 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 8ab9f9dfd7..50e3926ca7 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 5d4b473d0b..4d231684a3 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 4d231684a3..cb248097bf 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 cb248097bf..61d9a65020 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 f78184c3bc..5433f3402e 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 61d9a65020..ecf8013bec 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 50e3926ca7..f8b71ed15c 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 69d0759511..5379367967 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 ecf8013bec..481d96bf80 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 5433f3402e..2ec66ef318 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 f8b71ed15c..70fe8bb62a 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 2ec66ef318..ade6fb165b 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 e737016291..261753ad11 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 07c7e26180..952867642d 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 ade6fb165b..83dad8e82a 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 481d96bf80..63527c4722 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 70fe8bb62a..087ddda16b 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 4b8c155263..eae4edb7fb 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 5379367967..6ef3e641a4 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 087ddda16b..0e471f162a 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 0e471f162a..c2bd51a9fb 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 c2bd51a9fb..f1ed68c8cf 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 83dad8e82a..1f8677b81c 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 63527c4722..d421086dd1 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 f1ed68c8cf..fa66e9fd81 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 1f8677b81c..32e27ada96 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 d421086dd1..e873e1d5e6 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 fa66e9fd81..c8ffece2d8 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 32e27ada96..cadc3d2aeb 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 cadc3d2aeb..9e387fd5df 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 9e387fd5df..db4d922b6b 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 c8ffece2d8..ac95cfb24e 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 ac95cfb24e..e210bebd76 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 db4d922b6b..076d4351c1 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 076d4351c1..eec57b83d8 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 e873e1d5e6..d44c3f7084 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 e210bebd76..bf2be65ca1 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 eec57b83d8..05d2e53889 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 bf2be65ca1..c7d4c5ffdb 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 05d2e53889..7cc0131d80 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 c7d4c5ffdb..6e672f797c 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 e8fbea9992..ea2fb3080b 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 6e672f797c..74a00d1518 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 7cc0131d80..b71dc3f70c 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 d44c3f7084..ebc048cfd7 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 b71dc3f70c..42b129e886 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 74a00d1518..ace47bef88 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 3a659bd8f2..06269eb343 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 42b129e886..e3374f8847 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 ebc048cfd7..7733ead98c 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 5301c0feca..7163c3de86 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 7163c3de86..4a98a456d1 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 7733ead98c..2c473ab796 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 06269eb343..7f0205f110 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 4a98a456d1..eed18c6ddf 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 9d1fd9ffd3..d58603cd6d 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 eed18c6ddf..4b3221fddf 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 da79a42c5c..c1a7d52d75 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 4b3221fddf..d001c46e68 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 7f0205f110..ddbe50f8a9 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 aec4a8d3e8..3107dcf300 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 d001c46e68..b1dce459e7 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 ddbe50f8a9..1c83cc16d4 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 1c83cc16d4..a281631d2d 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 a281631d2d..f91ce407fb 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 b1dce459e7..d2c65fdb50 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 16adcae09f..f91ce407fb 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 d2c65fdb50..9e3cf76bd2 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 f91ce407fb..261decea8d 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 261decea8d..86939b0bef 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 d58603cd6d..7e5207d394 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 9e3cf76bd2..257a22fd9a 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 952867642d..c7df9bafc1 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 257a22fd9a..3ccd82a10e 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 86939b0bef..66ce0fa1aa 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 3107dcf300..72aeae3c8c 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 b8f50e6a1a..bb6216be77 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 c1a7d52d75..3e330ee7f5 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 2c473ab796..dbcd3814d5 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 66ce0fa1aa..cd306525c2 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 dbcd3814d5..623c47fac9 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 72aeae3c8c..f1d86dcf7d 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 cd306525c2..1dfca2bfff 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 c562242165..1e3253988a 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 3ccd82a10e..1592297523 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 623c47fac9..5194652d68 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 1dfca2bfff..fb8a65bc6b 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 1592297523..fe4a4cb90b 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 fb8a65bc6b..14ee61c029 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 c7df9bafc1..9420aa31c5 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 fe4a4cb90b..7afa9accef 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 bb6216be77..fbf8856e50 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 7afa9accef..482f11844b 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 14ee61c029..d1df300edb 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 f1d86dcf7d..14df8fadec 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 14df8fadec..f1d86dcf7d 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 fbf8856e50..70b1864a50 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 482f11844b..ab35da99c2 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 d1df300edb..14ee61c029 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 ab35da99c2..10cf41cc48 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 3e330ee7f5..1c7836da71 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 14ee61c029..9679dd8af6 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 c9aab4018b..5338030d98 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 94269dd765..44063da70d 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 10cf41cc48..2b75d2753d 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 1c7836da71..a6a88a1e75 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 9679dd8af6..f6de4c5e7c 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 a6a88a1e75..75a6674a30 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 2b75d2753d..a1c66de35f 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 75a6674a30..28241f5da8 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 5338030d98..821a3cbceb 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 a1c66de35f..15220ddf79 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 28241f5da8..28ddfb2921 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 c16722af71..6e80e35810 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 1dc77b52df..1e8fe5c697 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 05430966e4..7553801881 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 34a9ca8f71..aa5dff3b1e 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 7553801881..6bc15743cb 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 aa5dff3b1e..822838f005 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 5194652d68..8fa274f3a1 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 f6de4c5e7c..d1383fc243 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 821a3cbceb..232a093b89 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 cda13e3bc3..1e252cdefa 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 923b10d385..facb221abe 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 9a46cb943e..a302f730f5 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 822838f005..36bd1ff455 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 facb221abe..f447d0f20e 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 a302f730f5..4fa591ced0 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 36bd1ff455..c45b0fd13a 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 f447d0f20e..0fb70f92a8 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 232a093b89..e670d840b2 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 7e5207d394..babcf992c3 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 4fa591ced0..cb00aaf188 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 c45b0fd13a..f1423fd093 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 1e252cdefa..66dfc1b3e7 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 cb00aaf188..406372dc83 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 f1423fd093..27f1c047b5 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 0fb70f92a8..8739aaec56 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 e670d840b2..ae4a2faac8 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 406372dc83..5d00a30caf 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 27f1c047b5..4c1c1dad20 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 66dfc1b3e7..8a3fa7f82f 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 8739aaec56..a3b60e74cf 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 6e80e35810..fc6e16267e 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 1e8fe5c697..12b305728d 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 5d00a30caf..d5a1e9855e 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 4c1c1dad20..870a3fd11f 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 8a3fa7f82f..3b6701607f 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 a3b60e74cf..b25cdccd54 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 12b305728d..153eef8b01 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 d5a1e9855e..7bf4a346aa 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 870a3fd11f..fcc27c6676 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 b25cdccd54..ad9d2d657d 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 ad9d2d657d..4b37fb9b0a 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 7bf4a346aa..f31f50b170 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 4b37fb9b0a..fe2349ae95 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 44063da70d..7dbdfcb05e 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 1e9403ba01..010d24942d 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 fe2349ae95..75d1ff3769 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 f31f50b170..563201b666 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 fcc27c6676..c6b317afc5 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 3b6701607f..c119216990 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 75d1ff3769..793c2c9812 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 010d24942d..9c603fbe35 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 563201b666..0343bac6e3 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 c119216990..66762232f0 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 793c2c9812..d1630faf34 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 a393ee9441..44c8a5dea2 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 9c603fbe35..f40ddf8f8b 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 2f613c8e58..301024cf8a 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 66762232f0..d962be52c1 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 1e3253988a..18c0464eeb 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 0343bac6e3..5eb2fc5594 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 c6b317afc5..ecfa1d839b 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 d1630faf34..11c748cf43 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 6f27bb68b9..9d56e316a6 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 73e43cf239..e204278eb0 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 cbf1bc3a22..8c71adb9d3 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 611168f850..c88ddba636 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 edd79d8a07..8931e10565 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 fc6e16267e..5bc8e00b71 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 153eef8b01..a5ab82978f 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 a92c1ce89d..498ba4cc73 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 54f6b3f7b2..de32695729 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 babcf992c3..753a2fd43b 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 5eb2fc5594..1716469179 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 ecfa1d839b..acf42a9bc1 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 d962be52c1..0dc4d45274 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 498ba4cc73..1654b6fd92 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 0dc4d45274..251378dd7c 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 11c748cf43..f5c0c17da1 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 f40ddf8f8b..376eb47ef7 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 1654b6fd92..a92c1ce89d 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 f5c0c17da1..647b77c20b 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 647b77c20b..1e12dead6e 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 1716469179..1bf9d31f87 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 1e12dead6e..50f24f7d25 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 1bf9d31f87..8b38bd7acc 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 18c0464eeb..1a9e58d882 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 5f3158a342..28c37af40e 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 1ecbb402c3..f10db1c2dd 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 cee3480fec..7d4bda1c4b 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 ac6bc3f175..b75d4930e6 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 a8e68f4292..5551519927 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 b7c42aff0f..ce4f580576 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 28c37af40e..96d22e8787 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 dfbf19013f..9a29d3fc95 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 96d22e8787..e083768829 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 e083768829..7ea06b3dec 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 a5c6eb5c8e..cdbd44fada 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 a5c5abd4bb..3f3c3723dc 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 20f96462ea..2db19096cc 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 ba9cd45c67..df2ca30de2 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 376eb47ef7..4ae0de4607 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 2db19096cc..1e09f0bf98 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 1e09f0bf98..2661a828ba 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 3f3c3723dc..32a592cb91 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 2661a828ba..1aec895f03 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 7ea06b3dec..ee16714643 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 ee16714643..fe5d13b59b 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];