From 8a579b64be45c4b672a20a726db8bbaf58a7a2ea Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Mon, 12 Aug 2024 15:54:41 +0100 Subject: [PATCH] Logic Operations --- Directory.Packages.props | 2 +- .../EncoderStateManager.cs | 8 ++++++ src/Ryujinx.Graphics.Metal/EnumConversion.cs | 25 +++++++++++++++++++ src/Ryujinx.Graphics.Metal/Pipeline.cs | 2 +- .../State/PipelineState.cs | 14 +++++------ 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 47cce9599..e59d2d4fb 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -38,7 +38,7 @@ - + diff --git a/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs b/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs index a417f950a..7687b80df 100644 --- a/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs +++ b/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs @@ -663,6 +663,14 @@ namespace Ryujinx.Graphics.Metal SignalDirty(DirtyFlags.DepthBias); } + public readonly void UpdateLogicOpState(bool enable, LogicalOp op) + { + _currentState.Pipeline.LogicOpEnable = enable; + _currentState.Pipeline.LogicOp = op.Convert(); + + SignalDirty(DirtyFlags.RenderPipeline); + } + public readonly void UpdateMultisampleState(MultisampleDescriptor multisample) { _currentState.Pipeline.AlphaToCoverageEnable = multisample.AlphaToCoverageEnable; diff --git a/src/Ryujinx.Graphics.Metal/EnumConversion.cs b/src/Ryujinx.Graphics.Metal/EnumConversion.cs index 091de7ef8..e498546e8 100644 --- a/src/Ryujinx.Graphics.Metal/EnumConversion.cs +++ b/src/Ryujinx.Graphics.Metal/EnumConversion.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using SharpMetal.Metal; +using System; using System.Runtime.Versioning; namespace Ryujinx.Graphics.Metal @@ -112,6 +113,30 @@ namespace Ryujinx.Graphics.Metal }; } + public static MTLLogicOperation Convert(this LogicalOp op) + { + return op switch + { + LogicalOp.Clear => MTLLogicOperation.Clear, + LogicalOp.And => MTLLogicOperation.And, + LogicalOp.AndReverse => MTLLogicOperation.AndReverse, + LogicalOp.Copy => MTLLogicOperation.Copy, + LogicalOp.AndInverted => MTLLogicOperation.AndInverted, + LogicalOp.Noop => MTLLogicOperation.Noop, + LogicalOp.Xor => MTLLogicOperation.Xor, + LogicalOp.Or => MTLLogicOperation.Or, + LogicalOp.Nor => MTLLogicOperation.Nor, + LogicalOp.Equiv => MTLLogicOperation.Equivalence, + LogicalOp.Invert => MTLLogicOperation.Invert, + LogicalOp.OrReverse => MTLLogicOperation.OrReverse, + LogicalOp.CopyInverted => MTLLogicOperation.CopyInverted, + LogicalOp.OrInverted => MTLLogicOperation.OrInverted, + LogicalOp.Nand => MTLLogicOperation.Nand, + LogicalOp.Set => MTLLogicOperation.Set, + _ => LogInvalidAndReturn(op, nameof(LogicalOp), MTLLogicOperation.And) + }; + } + public static MTLSamplerMinMagFilter Convert(this MagFilter filter) { return filter switch diff --git a/src/Ryujinx.Graphics.Metal/Pipeline.cs b/src/Ryujinx.Graphics.Metal/Pipeline.cs index 9a6bcc052..6b42578ea 100644 --- a/src/Ryujinx.Graphics.Metal/Pipeline.cs +++ b/src/Ryujinx.Graphics.Metal/Pipeline.cs @@ -669,7 +669,7 @@ namespace Ryujinx.Graphics.Metal public void SetLogicOpState(bool enable, LogicalOp op) { - // Metal does not support logic operations. + _encoderStateManager.UpdateLogicOpState(enable, op); } public void SetMultisampleState(MultisampleDescriptor multisample) diff --git a/src/Ryujinx.Graphics.Metal/State/PipelineState.cs b/src/Ryujinx.Graphics.Metal/State/PipelineState.cs index 425b9a977..85e6907bd 100644 --- a/src/Ryujinx.Graphics.Metal/State/PipelineState.cs +++ b/src/Ryujinx.Graphics.Metal/State/PipelineState.cs @@ -45,10 +45,9 @@ namespace Ryujinx.Graphics.Metal } */ - // Reserved for when API is available. - public int LogicOp + public MTLLogicOperation LogicOp { - readonly get => (int)((Internal.Id0 >> 32) & 0xF); + readonly get => (MTLLogicOperation)((Internal.Id0 >> 32) & 0xF); set => Internal.Id0 = (Internal.Id0 & 0xFFFFFFF0FFFFFFFF) | ((ulong)value << 32); } @@ -65,7 +64,6 @@ namespace Ryujinx.Graphics.Metal set => Internal.Id0 = (Internal.Id0 & 0xFFFFFFDFFFFFFFFF) | ((value ? 1UL : 0UL) << 37); } - // Reserved for when API is available. public bool LogicOpEnable { readonly get => ((Internal.Id0 >> 38) & 0x1) != 0UL; @@ -208,9 +206,11 @@ namespace Ryujinx.Graphics.Metal } } - renderPipelineDescriptor.SetAlphaToCoverageEnabled(AlphaToCoverageEnable); - renderPipelineDescriptor.SetAlphaToOneEnabled(AlphaToOneEnable); - renderPipelineDescriptor.SetRasterizationEnabled(!RasterizerDiscardEnable); + renderPipelineDescriptor.LogicOperationEnabled = LogicOpEnable; + renderPipelineDescriptor.LogicOperation = LogicOp; + renderPipelineDescriptor.AlphaToCoverageEnabled = AlphaToCoverageEnable; + renderPipelineDescriptor.AlphaToOneEnabled = AlphaToOneEnable; + renderPipelineDescriptor.RasterizationEnabled = !RasterizerDiscardEnable; renderPipelineDescriptor.SampleCount = Math.Max(1, SamplesCount); var vertexDescriptor = BuildVertexDescriptor();