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();