diff --git a/src/Ryujinx.Graphics.Metal/EncoderState.cs b/src/Ryujinx.Graphics.Metal/EncoderState.cs index e4be1fb7c..ed512125b 100644 --- a/src/Ryujinx.Graphics.Metal/EncoderState.cs +++ b/src/Ryujinx.Graphics.Metal/EncoderState.cs @@ -32,6 +32,7 @@ namespace Ryujinx.Graphics.Metal public MTLStencilDescriptor BackFaceStencil = new(); public MTLStencilDescriptor FrontFaceStencil = new(); + public bool StencilTestEnabled = false; public PrimitiveTopology Topology = PrimitiveTopology.Triangles; public MTLCullMode CullMode = MTLCullMode.None; diff --git a/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs b/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs index a7e7de281..49c3b1ee8 100644 --- a/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs +++ b/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs @@ -68,15 +68,43 @@ namespace Ryujinx.Graphics.Metal } var depthAttachment = renderPassDescriptor.DepthAttachment; - depthAttachment.Texture = _currentState.DepthStencil; - depthAttachment.LoadAction = MTLLoadAction.Load; + var stencilAttachment = renderPassDescriptor.StencilAttachment; - // var stencilAttachment = renderPassDescriptor.StencilAttachment; - // stencilAttachment.Texture = - // stencilAttachment.LoadAction = MTLLoadAction.Load; + switch (_currentState.DepthStencil.PixelFormat) + { + // Depth Only Attachment + case MTLPixelFormat.Depth16Unorm: + case MTLPixelFormat.Depth32Float: + depthAttachment.Texture = _currentState.DepthStencil; + depthAttachment.LoadAction = MTLLoadAction.Load; + renderPipelineDescriptor.DepthAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat; + break; - renderPipelineDescriptor.DepthAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat; - // renderPipelineDescriptor.StencilAttachmentPixelFormat = + // Stencil Only Attachment + case MTLPixelFormat.Stencil8: + stencilAttachment.Texture = _currentState.DepthStencil; + stencilAttachment.LoadAction = MTLLoadAction.Load; + renderPipelineDescriptor.StencilAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat; + break; + + // Combined Attachment + case MTLPixelFormat.Depth24UnormStencil8: + case MTLPixelFormat.Depth32FloatStencil8: + depthAttachment.Texture = _currentState.DepthStencil; + depthAttachment.LoadAction = MTLLoadAction.Load; + + var unpackedFormat = FormatTable.PackedStencilToXFormat(_currentState.DepthStencil.PixelFormat); + var stencilView = _currentState.DepthStencil.NewTextureView(unpackedFormat); + stencilAttachment.Texture = stencilView; + stencilAttachment.LoadAction = MTLLoadAction.Load; + + renderPipelineDescriptor.DepthAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat; + renderPipelineDescriptor.StencilAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat; + break; + default: + Logger.Error?.PrintMsg(LogClass.Gpu, $"Unsupported Depth/Stencil Format: {_currentState.DepthStencil.PixelFormat}!"); + break; + } renderPipelineDescriptor.VertexDescriptor = _currentState.VertexDescriptor; @@ -86,7 +114,7 @@ namespace Ryujinx.Graphics.Metal } else { - return new (IntPtr.Zero); + return new(IntPtr.Zero); } if (_currentState.FragmentFunction != null) @@ -230,13 +258,21 @@ namespace Ryujinx.Graphics.Metal WriteMask = (uint)stencilTest.FrontMask }; - _currentState.DepthStencilState = _device.NewDepthStencilState(new MTLDepthStencilDescriptor + _currentState.StencilTestEnabled = stencilTest.TestEnable; + + var descriptor = new MTLDepthStencilDescriptor { DepthCompareFunction = _currentState.DepthCompareFunction, - DepthWriteEnabled = _currentState.DepthWriteEnabled, - BackFaceStencil = stencilTest.TestEnable ? _currentState.BackFaceStencil : new MTLStencilDescriptor(IntPtr.Zero), - FrontFaceStencil = stencilTest.TestEnable ? _currentState.FrontFaceStencil : new MTLStencilDescriptor(IntPtr.Zero) - }); + DepthWriteEnabled = _currentState.DepthWriteEnabled + }; + + if (_currentState.StencilTestEnabled) + { + descriptor.BackFaceStencil = _currentState.BackFaceStencil; + descriptor.FrontFaceStencil = _currentState.FrontFaceStencil; + } + + _currentState.DepthStencilState = _device.NewDepthStencilState(descriptor); // Inline Update @@ -253,13 +289,19 @@ namespace Ryujinx.Graphics.Metal _currentState.DepthCompareFunction = depthTest.TestEnable ? depthTest.Func.Convert() : MTLCompareFunction.Always; _currentState.DepthWriteEnabled = depthTest.WriteEnable; - _currentState.DepthStencilState = _device.NewDepthStencilState(new MTLDepthStencilDescriptor + var descriptor = new MTLDepthStencilDescriptor { DepthCompareFunction = _currentState.DepthCompareFunction, - DepthWriteEnabled = _currentState.DepthWriteEnabled, - BackFaceStencil = _currentState.BackFaceStencil, - FrontFaceStencil = _currentState.FrontFaceStencil - }); + DepthWriteEnabled = _currentState.DepthWriteEnabled + }; + + if (_currentState.StencilTestEnabled) + { + descriptor.BackFaceStencil = _currentState.BackFaceStencil; + descriptor.FrontFaceStencil = _currentState.FrontFaceStencil; + } + + _currentState.DepthStencilState = _device.NewDepthStencilState(descriptor); // Inline Update diff --git a/src/Ryujinx.Graphics.Metal/FormatTable.cs b/src/Ryujinx.Graphics.Metal/FormatTable.cs index 29f348cac..0ef710011 100644 --- a/src/Ryujinx.Graphics.Metal/FormatTable.cs +++ b/src/Ryujinx.Graphics.Metal/FormatTable.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using SharpMetal.Metal; using System; @@ -64,8 +65,7 @@ namespace Ryujinx.Graphics.Metal Add(Format.R32G32B32A32Sint, MTLPixelFormat.RGBA32Sint); Add(Format.S8Uint, MTLPixelFormat.Stencil8); Add(Format.D16Unorm, MTLPixelFormat.Depth16Unorm); - // Approximate - Add(Format.S8UintD24Unorm, MTLPixelFormat.BGRA8Unorm); + // Add(Format.S8UintD24Unorm, MTLPixelFormat.BGRA8Unorm); Add(Format.D32Float, MTLPixelFormat.Depth32Float); Add(Format.D24UnormS8Uint, MTLPixelFormat.Depth24UnormStencil8); Add(Format.D32FloatS8Uint, MTLPixelFormat.Depth32FloatStencil8); @@ -181,5 +181,17 @@ namespace Ryujinx.Graphics.Metal return mtlFormat; } + + public static MTLPixelFormat PackedStencilToXFormat(MTLPixelFormat format) + { + switch (format) + { + case MTLPixelFormat.Depth24UnormStencil8: return MTLPixelFormat.X24Stencil8; + case MTLPixelFormat.Depth32FloatStencil8: return MTLPixelFormat.X32Stencil8; + default: + Logger.Warning?.PrintMsg(LogClass.Gpu, $"Attempted to get stencil format for non packed format {format}!"); + return MTLPixelFormat.Invalid; + } + } } }