diff --git a/src/Ryujinx.Graphics.Metal/EncoderState.cs b/src/Ryujinx.Graphics.Metal/EncoderState.cs index 3ebf9fbd9..93d84cf57 100644 --- a/src/Ryujinx.Graphics.Metal/EncoderState.cs +++ b/src/Ryujinx.Graphics.Metal/EncoderState.cs @@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Metal public MTLScissorRect[] Scissors = []; // Changes to attachments take recreation! - public MTLTexture DepthStencil = default; + public Texture DepthStencil = default; public Texture[] RenderTargets = new Texture[Constants.MaxColorAttachments]; public Dictionary BlendDescriptors = new(); public ColorF BlendColor = new(); diff --git a/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs b/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs index ae4be9e34..fac656132 100644 --- a/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs +++ b/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs @@ -26,6 +26,7 @@ namespace Ryujinx.Graphics.Metal public readonly ulong IndexBufferOffset => _currentState.IndexBufferOffset; public readonly PrimitiveTopology Topology => _currentState.Topology; public readonly Texture[] RenderTargets => _currentState.RenderTargets; + public readonly Texture DepthStencil => _currentState.DepthStencil; public EncoderStateManager(MTLDevice device, Pipeline pipeline) { @@ -62,36 +63,36 @@ namespace Ryujinx.Graphics.Metal var depthAttachment = renderPassDescriptor.DepthAttachment; var stencilAttachment = renderPassDescriptor.StencilAttachment; - if (_currentState.DepthStencil != IntPtr.Zero) + if (_currentState.DepthStencil != null) { - switch (_currentState.DepthStencil.PixelFormat) + switch (_currentState.DepthStencil.MTLTexture.PixelFormat) { // Depth Only Attachment case MTLPixelFormat.Depth16Unorm: case MTLPixelFormat.Depth32Float: - depthAttachment.Texture = _currentState.DepthStencil; + depthAttachment.Texture = _currentState.DepthStencil.MTLTexture; depthAttachment.LoadAction = MTLLoadAction.Load; break; // Stencil Only Attachment case MTLPixelFormat.Stencil8: - stencilAttachment.Texture = _currentState.DepthStencil; + stencilAttachment.Texture = _currentState.DepthStencil.MTLTexture; stencilAttachment.LoadAction = MTLLoadAction.Load; break; // Combined Attachment case MTLPixelFormat.Depth24UnormStencil8: case MTLPixelFormat.Depth32FloatStencil8: - depthAttachment.Texture = _currentState.DepthStencil; + depthAttachment.Texture = _currentState.DepthStencil.MTLTexture; depthAttachment.LoadAction = MTLLoadAction.Load; - var unpackedFormat = FormatTable.PackedStencilToXFormat(_currentState.DepthStencil.PixelFormat); - var stencilView = _currentState.DepthStencil.NewTextureView(unpackedFormat); + var unpackedFormat = FormatTable.PackedStencilToXFormat(_currentState.DepthStencil.MTLTexture.PixelFormat); + var stencilView = _currentState.DepthStencil.MTLTexture.NewTextureView(unpackedFormat); stencilAttachment.Texture = stencilView; stencilAttachment.LoadAction = MTLLoadAction.Load; break; default: - Logger.Error?.PrintMsg(LogClass.Gpu, $"Unsupported Depth/Stencil Format: {_currentState.DepthStencil.PixelFormat}!"); + Logger.Error?.PrintMsg(LogClass.Gpu, $"Unsupported Depth/Stencil Format: {_currentState.DepthStencil.MTLTexture.PixelFormat}!"); break; } } @@ -159,29 +160,29 @@ namespace Ryujinx.Graphics.Metal } } - if (_currentState.DepthStencil != IntPtr.Zero) + if (_currentState.DepthStencil != null) { - switch (_currentState.DepthStencil.PixelFormat) + switch (_currentState.DepthStencil.MTLTexture.PixelFormat) { // Depth Only Attachment case MTLPixelFormat.Depth16Unorm: case MTLPixelFormat.Depth32Float: - renderPipelineDescriptor.DepthAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat; + renderPipelineDescriptor.DepthAttachmentPixelFormat = _currentState.DepthStencil.MTLTexture.PixelFormat; break; // Stencil Only Attachment case MTLPixelFormat.Stencil8: - renderPipelineDescriptor.StencilAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat; + renderPipelineDescriptor.StencilAttachmentPixelFormat = _currentState.DepthStencil.MTLTexture.PixelFormat; break; // Combined Attachment case MTLPixelFormat.Depth24UnormStencil8: case MTLPixelFormat.Depth32FloatStencil8: - renderPipelineDescriptor.DepthAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat; - renderPipelineDescriptor.StencilAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat; + renderPipelineDescriptor.DepthAttachmentPixelFormat = _currentState.DepthStencil.MTLTexture.PixelFormat; + renderPipelineDescriptor.StencilAttachmentPixelFormat = _currentState.DepthStencil.MTLTexture.PixelFormat; break; default: - Logger.Error?.PrintMsg(LogClass.Gpu, $"Unsupported Depth/Stencil Format: {_currentState.DepthStencil.PixelFormat}!"); + Logger.Error?.PrintMsg(LogClass.Gpu, $"Unsupported Depth/Stencil Format: {_currentState.DepthStencil.MTLTexture.PixelFormat}!"); break; } } @@ -262,7 +263,7 @@ namespace Ryujinx.Graphics.Metal if (depthStencil is Texture depthTexture) { - _currentState.DepthStencil = depthTexture.MTLTexture; + _currentState.DepthStencil = depthTexture; } // Requires recreating pipeline diff --git a/src/Ryujinx.Graphics.Metal/HelperShader.cs b/src/Ryujinx.Graphics.Metal/HelperShader.cs index 8e95442cd..a1dab8a5b 100644 --- a/src/Ryujinx.Graphics.Metal/HelperShader.cs +++ b/src/Ryujinx.Graphics.Metal/HelperShader.cs @@ -47,33 +47,12 @@ namespace Ryujinx.Graphics.Metal new ShaderSource(colorClearSource, ShaderStage.Vertex, TargetLanguage.Msl) ], device); - // var colorClearFSource = ReadMsl("ColorClearF.metal"); - // _programColorClearF = new Program( - // [ - // new ShaderSource(colorClearFSource, ShaderStage.Fragment, TargetLanguage.Msl), - // new ShaderSource(colorClearFSource, ShaderStage.Vertex, TargetLanguage.Msl) - // ], device); - // - // var colorClearSiSource = ReadMsl("ColorClearSI.metal"); - // _programColorClearSI = new Program( - // [ - // new ShaderSource(colorClearSiSource, ShaderStage.Fragment, TargetLanguage.Msl), - // new ShaderSource(colorClearSiSource, ShaderStage.Vertex, TargetLanguage.Msl) - // ], device); - // - // var colorClearUiSource = ReadMsl("ColorClearUI.metal"); - // _programColorClearUI = new Program( - // [ - // new ShaderSource(colorClearUiSource, ShaderStage.Fragment, TargetLanguage.Msl), - // new ShaderSource(colorClearUiSource, ShaderStage.Vertex, TargetLanguage.Msl) - // ], device); - // - // var depthStencilClearSource = ReadMsl("DepthStencilClear.metal"); - // _programDepthStencilClear = new Program( - // [ - // new ShaderSource(depthStencilClearSource, ShaderStage.Fragment, TargetLanguage.Msl), - // new ShaderSource(depthStencilClearSource, ShaderStage.Vertex, TargetLanguage.Msl) - // ], device); + var depthStencilClearSource = ReadMsl("DepthStencilClear.metal"); + _programDepthStencilClear = new Program( + [ + new ShaderSource(depthStencilClearSource, ShaderStage.Fragment, TargetLanguage.Msl), + new ShaderSource(depthStencilClearSource, ShaderStage.Vertex, TargetLanguage.Msl) + ], device); } private static string ReadMsl(string fileName) @@ -129,34 +108,35 @@ namespace Ryujinx.Graphics.Metal _pipeline.Finish(); } - public void ClearDepthStencil( + public unsafe void ClearDepthStencil( Texture dst, - float depthValue, + ReadOnlySpan depthValue, bool depthMask, int stencilValue, - int stencilMask, - int dstWidth, - int dstHeight, - Rectangle scissor) + int stencilMask) { - Span viewports = stackalloc Viewport[1]; + const int ClearColorBufferSize = 16; - viewports[0] = new Viewport( - new Rectangle(0, 0, dstWidth, dstHeight), - ViewportSwizzle.PositiveX, - ViewportSwizzle.PositiveY, - ViewportSwizzle.PositiveZ, - ViewportSwizzle.PositiveW, - 0f, - 1f); + var buffer = _device.NewBuffer(ClearColorBufferSize, MTLResourceOptions.ResourceStorageModeManaged); + var span = new Span(buffer.Contents.ToPointer(), ClearColorBufferSize); + depthValue.CopyTo(span); + + buffer.DidModifyRange(new NSRange + { + location = 0, + length = ClearColorBufferSize + }); + + var handle = buffer.NativePtr; + var range = new BufferRange(Unsafe.As(ref handle), 0, ClearColorBufferSize); + + _pipeline.SetUniformBuffers([new BufferAssignment(0, range)]); _pipeline.SetProgram(_programDepthStencilClear); - // _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight); - _pipeline.SetViewports(viewports); - _pipeline.SetScissors([scissor]); + _pipeline.SetRenderTargets([], dst); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.SetDepthTest(new DepthTestDescriptor(true, depthMask, CompareOp.Always)); - _pipeline.SetStencilTest(CreateStencilTestDescriptor(stencilMask != 0, stencilValue, 0xFF, stencilMask)); + // _pipeline.SetStencilTest(CreateStencilTestDescriptor(stencilMask != 0, stencilValue, 0xFF, stencilMask)); _pipeline.Draw(4, 1, 0, 0); _pipeline.Finish(); } diff --git a/src/Ryujinx.Graphics.Metal/Pipeline.cs b/src/Ryujinx.Graphics.Metal/Pipeline.cs index ce9686b08..172439675 100644 --- a/src/Ryujinx.Graphics.Metal/Pipeline.cs +++ b/src/Ryujinx.Graphics.Metal/Pipeline.cs @@ -215,7 +215,11 @@ namespace Ryujinx.Graphics.Metal public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask) { - Logger.Warning?.Print(LogClass.Gpu, "Not Implemented!"); + Texture target = _encoderStateManager.DepthStencil; + + _encoderStateManager.SwapStates(); + + _helperShader.ClearDepthStencil(target, [depthValue], depthMask, stencilValue, stencilMask); } public void CommandBufferBarrier() diff --git a/src/Ryujinx.Graphics.Metal/Shaders/DepthStencilClear.metal b/src/Ryujinx.Graphics.Metal/Shaders/DepthStencilClear.metal index 0a4e10a25..ad22837fd 100644 --- a/src/Ryujinx.Graphics.Metal/Shaders/DepthStencilClear.metal +++ b/src/Ryujinx.Graphics.Metal/Shaders/DepthStencilClear.metal @@ -7,8 +7,8 @@ struct VertexOut { }; struct FragmentOut { - float4 color [[color(0)]]; float depth [[depth(any)]]; + uint stencil [[stencil]]; }; vertex VertexOut vertexMain(ushort vid [[vertex_id]]) @@ -26,12 +26,13 @@ vertex VertexOut vertexMain(ushort vid [[vertex_id]]) return out; } -fragment float4 fragmentMain(VertexOut in [[stage_in]], - constant float clear_color [[buffer(0)]]) +fragment FragmentOut fragmentMain(VertexOut in [[stage_in]], + constant float& clear_color [[buffer(0)]]) { - Fragment out; + FragmentOut out; out.depth = clear_color; + // out.stencil = stencil_clear; return out; }