diff --git a/src/Ryujinx.Graphics.Metal/EncoderState.cs b/src/Ryujinx.Graphics.Metal/EncoderState.cs index 043fb1660..2932c5e1d 100644 --- a/src/Ryujinx.Graphics.Metal/EncoderState.cs +++ b/src/Ryujinx.Graphics.Metal/EncoderState.cs @@ -53,6 +53,8 @@ namespace Ryujinx.Graphics.Metal public MTLStencilDescriptor BackFaceStencil = new(); public MTLStencilDescriptor FrontFaceStencil = new(); + public int BackRefValue = 0; + public int FrontRefValue = 0; public bool StencilTestEnabled = false; public PrimitiveTopology Topology = PrimitiveTopology.Triangles; diff --git a/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs b/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs index e9d615c96..b2c490ec9 100644 --- a/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs +++ b/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs @@ -81,6 +81,7 @@ namespace Ryujinx.Graphics.Metal SetBuffers(renderCommandEncoder, _currentState.StorageBuffers, true); SetCullMode(renderCommandEncoder); SetFrontFace(renderCommandEncoder); + SetStencilRefValue(renderCommandEncoder); // Mark the other state as dirty _currentState.Dirty.MarkAll(); @@ -161,6 +162,7 @@ namespace Ryujinx.Graphics.Metal SetDepthClamp(renderCommandEncoder); SetCullMode(renderCommandEncoder); SetFrontFace(renderCommandEncoder); + SetStencilRefValue(renderCommandEncoder); SetViewports(renderCommandEncoder); SetScissors(renderCommandEncoder); SetVertexBuffers(renderCommandEncoder, _currentState.VertexBuffers); @@ -433,6 +435,8 @@ namespace Ryujinx.Graphics.Metal _currentState.DepthStencilState = _depthStencilCache.GetOrCreate(descriptor); + UpdateStencilRefValue(stencilTest.FrontFuncRef, stencilTest.BackFuncRef); + // Mark dirty _currentState.Dirty.DepthStencil = true; @@ -635,6 +639,19 @@ namespace Ryujinx.Graphics.Metal } } + private void UpdateStencilRefValue(int frontRef, int backRef) + { + _currentState.FrontRefValue = frontRef; + _currentState.BackRefValue = backRef; + + // Inline update + if (_pipeline.CurrentEncoderType == EncoderType.Render && _pipeline.CurrentEncoder != null) + { + var renderCommandEncoder = new MTLRenderCommandEncoder(_pipeline.CurrentEncoder.Value); + SetStencilRefValue(renderCommandEncoder); + } + } + // Inlineable public readonly void UpdateTextureAndSampler(ShaderStage stage, ulong binding, MTLTexture texture, MTLSamplerState sampler) { @@ -786,6 +803,11 @@ namespace Ryujinx.Graphics.Metal renderCommandEncoder.SetFrontFacingWinding(_currentState.Winding); } + private readonly void SetStencilRefValue(MTLRenderCommandEncoder renderCommandEncoder) + { + renderCommandEncoder.SetStencilReferenceValues((uint)_currentState.FrontRefValue, (uint)_currentState.BackRefValue); + } + private static void SetTextureAndSampler(MTLRenderCommandEncoder renderCommandEncoder, ShaderStage stage, MTLTexture[] textures, MTLSamplerState[] samplers) { for (int i = 0; i < textures.Length; i++)