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;