From 8feee9c005b9144fd6f58ee9ca72b63f95af176c Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Wed, 22 May 2024 17:21:44 -0400 Subject: [PATCH] Shitty Clears + Inline Buffer Improvements? --- src/Ryujinx.Graphics.Metal/EncoderState.cs | 4 +- .../EncoderStateManager.cs | 13 ++-- src/Ryujinx.Graphics.Metal/HelperShader.cs | 68 ++++++++----------- src/Ryujinx.Graphics.Metal/MetalRenderer.cs | 22 +++--- src/Ryujinx.Graphics.Metal/Pipeline.cs | 9 ++- .../Ryujinx.Graphics.Metal.csproj | 4 +- .../Shaders/ColorClear.metal | 28 ++++++++ .../Shaders/ColorClearF.metal | 0 .../Shaders/ColorClearSI.metal | 0 .../Shaders/ColorClearUI.metal | 0 .../Shaders/DepthStencilClear.metal | 37 ++++++++++ 11 files changed, 124 insertions(+), 61 deletions(-) create mode 100644 src/Ryujinx.Graphics.Metal/Shaders/ColorClear.metal delete mode 100644 src/Ryujinx.Graphics.Metal/Shaders/ColorClearF.metal delete mode 100644 src/Ryujinx.Graphics.Metal/Shaders/ColorClearSI.metal delete mode 100644 src/Ryujinx.Graphics.Metal/Shaders/ColorClearUI.metal diff --git a/src/Ryujinx.Graphics.Metal/EncoderState.cs b/src/Ryujinx.Graphics.Metal/EncoderState.cs index a787d1424..3ebf9fbd9 100644 --- a/src/Ryujinx.Graphics.Metal/EncoderState.cs +++ b/src/Ryujinx.Graphics.Metal/EncoderState.cs @@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Metal } [SupportedOSPlatform("macos")] - public struct EncoderState + struct EncoderState { public MTLFunction? VertexFunction = null; public MTLFunction? FragmentFunction = null; @@ -62,7 +62,7 @@ namespace Ryujinx.Graphics.Metal // Changes to attachments take recreation! public MTLTexture DepthStencil = default; - public MTLTexture[] RenderTargets = new MTLTexture[Constants.MaxColorAttachments]; + 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 15a96cc45..ae4be9e34 100644 --- a/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs +++ b/src/Ryujinx.Graphics.Metal/EncoderStateManager.cs @@ -25,6 +25,7 @@ namespace Ryujinx.Graphics.Metal public readonly MTLIndexType IndexType => _currentState.IndexType; public readonly ulong IndexBufferOffset => _currentState.IndexBufferOffset; public readonly PrimitiveTopology Topology => _currentState.Topology; + public readonly Texture[] RenderTargets => _currentState.RenderTargets; public EncoderStateManager(MTLDevice device, Pipeline pipeline) { @@ -50,10 +51,10 @@ namespace Ryujinx.Graphics.Metal for (int i = 0; i < Constants.MaxColorAttachments; i++) { - if (_currentState.RenderTargets[i] != IntPtr.Zero) + if (_currentState.RenderTargets[i] != null) { var passAttachment = renderPassDescriptor.ColorAttachments.Object((ulong)i); - passAttachment.Texture = _currentState.RenderTargets[i]; + passAttachment.Texture = _currentState.RenderTargets[i].MTLTexture; passAttachment.LoadAction = MTLLoadAction.Load; } } @@ -136,10 +137,10 @@ namespace Ryujinx.Graphics.Metal for (int i = 0; i < Constants.MaxColorAttachments; i++) { - if (_currentState.RenderTargets[i] != IntPtr.Zero) + if (_currentState.RenderTargets[i] != null) { var pipelineAttachment = renderPipelineDescriptor.ColorAttachments.Object((ulong)i); - pipelineAttachment.PixelFormat = _currentState.RenderTargets[i].PixelFormat; + pipelineAttachment.PixelFormat = _currentState.RenderTargets[i].MTLTexture.PixelFormat; pipelineAttachment.SourceAlphaBlendFactor = MTLBlendFactor.SourceAlpha; pipelineAttachment.DestinationAlphaBlendFactor = MTLBlendFactor.OneMinusSourceAlpha; pipelineAttachment.SourceRGBBlendFactor = MTLBlendFactor.SourceAlpha; @@ -247,7 +248,7 @@ namespace Ryujinx.Graphics.Metal public void UpdateRenderTargets(ITexture[] colors, ITexture depthStencil) { - _currentState.RenderTargets = new MTLTexture[Constants.MaxColorAttachments]; + _currentState.RenderTargets = new Texture[Constants.MaxColorAttachments]; for (int i = 0; i < colors.Length; i++) { @@ -256,7 +257,7 @@ namespace Ryujinx.Graphics.Metal continue; } - _currentState.RenderTargets[i] = tex.MTLTexture; + _currentState.RenderTargets[i] = tex; } if (depthStencil is Texture depthTexture) diff --git a/src/Ryujinx.Graphics.Metal/HelperShader.cs b/src/Ryujinx.Graphics.Metal/HelperShader.cs index b4ddfe02c..8e95442cd 100644 --- a/src/Ryujinx.Graphics.Metal/HelperShader.cs +++ b/src/Ryujinx.Graphics.Metal/HelperShader.cs @@ -2,8 +2,10 @@ using Ryujinx.Common; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader.Translation; +using SharpMetal.Foundation; using SharpMetal.Metal; using System; +using System.Runtime.CompilerServices; using System.Runtime.Versioning; namespace Ryujinx.Graphics.Metal @@ -23,9 +25,7 @@ namespace Ryujinx.Graphics.Metal private MTLDevice _device; private readonly IProgram _programColorBlit; - private readonly IProgram _programColorClearF; - private readonly IProgram _programColorClearSI; - private readonly IProgram _programColorClearUI; + private readonly IProgram _programColorClear; private readonly IProgram _programDepthStencilClear; public HelperShader(MTLDevice device, Pipeline pipeline) @@ -40,6 +40,13 @@ namespace Ryujinx.Graphics.Metal new ShaderSource(blitSource, ShaderStage.Vertex, TargetLanguage.Msl) ], device); + var colorClearSource = ReadMsl("ColorClear.metal"); + _programColorClear = new Program( + [ + new ShaderSource(colorClearSource, ShaderStage.Fragment, TargetLanguage.Msl), + new ShaderSource(colorClearSource, ShaderStage.Vertex, TargetLanguage.Msl) + ], device); + // var colorClearFSource = ReadMsl("ColorClearF.metal"); // _programColorClearF = new Program( // [ @@ -93,45 +100,30 @@ namespace Ryujinx.Graphics.Metal _pipeline.Finish(); } - public void ClearColor( + public unsafe void ClearColor( Texture dst, - uint componentMask, - int dstWidth, - int dstHeight, - ComponentType type, - Rectangle scissor) + ReadOnlySpan clearColor) { - 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); + clearColor.CopyTo(span); - IProgram program; - - if (type == ComponentType.SignedInteger) + buffer.DidModifyRange(new NSRange { - program = _programColorClearSI; - } - else if (type == ComponentType.UnsignedInteger) - { - program = _programColorClearUI; - } - else - { - program = _programColorClearF; - } + location = 0, + length = ClearColorBufferSize + }); - _pipeline.SetProgram(program); - // _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight); - _pipeline.SetRenderTargetColorMasks([componentMask]); - _pipeline.SetViewports(viewports); - _pipeline.SetScissors([scissor]); + var handle = buffer.NativePtr; + var range = new BufferRange(Unsafe.As(ref handle), 0, ClearColorBufferSize); + + _pipeline.SetUniformBuffers([new BufferAssignment(0, range)]); + + _pipeline.SetProgram(_programColorClear); + _pipeline.SetRenderTargets([dst], null); + // _pipeline.SetRenderTargetColorMasks([componentMask]); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.Draw(4, 1, 0, 0); _pipeline.Finish(); @@ -196,9 +188,7 @@ namespace Ryujinx.Graphics.Metal public void Dispose() { _programColorBlit.Dispose(); - _programColorClearF.Dispose(); - _programColorClearSI.Dispose(); - _programColorClearUI.Dispose(); + _programColorClear.Dispose(); _programDepthStencilClear.Dispose(); _pipeline.Dispose(); } diff --git a/src/Ryujinx.Graphics.Metal/MetalRenderer.cs b/src/Ryujinx.Graphics.Metal/MetalRenderer.cs index e7d26f72a..b5496028c 100644 --- a/src/Ryujinx.Graphics.Metal/MetalRenderer.cs +++ b/src/Ryujinx.Graphics.Metal/MetalRenderer.cs @@ -213,17 +213,19 @@ namespace Ryujinx.Graphics.Metal public unsafe void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan data) { - MTLBuffer mtlBuffer = new(Unsafe.As(ref buffer)); - var span = new Span(mtlBuffer.Contents.ToPointer(), (int)mtlBuffer.Length); - data.CopyTo(span[offset..]); - if (mtlBuffer.StorageMode == MTLStorageMode.Managed) + var blitEncoder = _pipeline.GetOrCreateBlitEncoder(); + + MTLBuffer src = _device.NewBuffer((ulong)data.Length, MTLResourceOptions.ResourceStorageModeManaged); + var span = new Span(src.Contents.ToPointer(), data.Length); + data.CopyTo(span); + src.DidModifyRange(new NSRange { - mtlBuffer.DidModifyRange(new NSRange - { - location = (ulong)offset, - length = (ulong)data.Length - }); - } + location = 0, + length = (ulong)data.Length + }); + + MTLBuffer dst = new(Unsafe.As(ref buffer)); + blitEncoder.CopyFromBuffer(src, 0, dst, (ulong)offset, (ulong)data.Length); } public void UpdateCounters() diff --git a/src/Ryujinx.Graphics.Metal/Pipeline.cs b/src/Ryujinx.Graphics.Metal/Pipeline.cs index 91afb33bf..ce9686b08 100644 --- a/src/Ryujinx.Graphics.Metal/Pipeline.cs +++ b/src/Ryujinx.Graphics.Metal/Pipeline.cs @@ -5,6 +5,7 @@ using SharpMetal.Foundation; using SharpMetal.Metal; using SharpMetal.QuartzCore; using System; +using System.Drawing; using System.Runtime.CompilerServices; using System.Runtime.Versioning; @@ -203,7 +204,13 @@ namespace Ryujinx.Graphics.Metal public void ClearRenderTargetColor(int index, int layer, int layerCount, uint componentMask, ColorF color) { - Logger.Warning?.Print(LogClass.Gpu, "Not Implemented!"); + float[] colors = [color.Red, color.Green, color.Blue, color.Alpha]; + + Texture target = _encoderStateManager.RenderTargets[index]; + + _encoderStateManager.SwapStates(); + + _helperShader.ClearColor(target, colors); } public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask) diff --git a/src/Ryujinx.Graphics.Metal/Ryujinx.Graphics.Metal.csproj b/src/Ryujinx.Graphics.Metal/Ryujinx.Graphics.Metal.csproj index d8da12834..0824accc1 100644 --- a/src/Ryujinx.Graphics.Metal/Ryujinx.Graphics.Metal.csproj +++ b/src/Ryujinx.Graphics.Metal/Ryujinx.Graphics.Metal.csproj @@ -16,9 +16,7 @@ - - - + diff --git a/src/Ryujinx.Graphics.Metal/Shaders/ColorClear.metal b/src/Ryujinx.Graphics.Metal/Shaders/ColorClear.metal new file mode 100644 index 000000000..85ae873e6 --- /dev/null +++ b/src/Ryujinx.Graphics.Metal/Shaders/ColorClear.metal @@ -0,0 +1,28 @@ +#include + +using namespace metal; + +struct VertexOut { + float4 position [[position]]; +}; + +vertex VertexOut vertexMain(ushort vid [[vertex_id]]) +{ + int low = vid & 1; + int high = vid >> 1; + + VertexOut out; + + out.position.x = (float(low) - 0.5f) * 2.0f; + out.position.y = (float(high) - 0.5f) * 2.0f; + out.position.z = 0.0f; + out.position.w = 1.0f; + + return out; +} + +fragment float4 fragmentMain(VertexOut in [[stage_in]], + constant float4& clear_color [[buffer(0)]]) +{ + return clear_color; +} diff --git a/src/Ryujinx.Graphics.Metal/Shaders/ColorClearF.metal b/src/Ryujinx.Graphics.Metal/Shaders/ColorClearF.metal deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/Ryujinx.Graphics.Metal/Shaders/ColorClearSI.metal b/src/Ryujinx.Graphics.Metal/Shaders/ColorClearSI.metal deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/Ryujinx.Graphics.Metal/Shaders/ColorClearUI.metal b/src/Ryujinx.Graphics.Metal/Shaders/ColorClearUI.metal deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/Ryujinx.Graphics.Metal/Shaders/DepthStencilClear.metal b/src/Ryujinx.Graphics.Metal/Shaders/DepthStencilClear.metal index e69de29bb..0a4e10a25 100644 --- a/src/Ryujinx.Graphics.Metal/Shaders/DepthStencilClear.metal +++ b/src/Ryujinx.Graphics.Metal/Shaders/DepthStencilClear.metal @@ -0,0 +1,37 @@ +#include + +using namespace metal; + +struct VertexOut { + float4 position [[position]]; +}; + +struct FragmentOut { + float4 color [[color(0)]]; + float depth [[depth(any)]]; +}; + +vertex VertexOut vertexMain(ushort vid [[vertex_id]]) +{ + int low = vid & 1; + int high = vid >> 1; + + VertexOut out; + + out.position.x = (float(low) - 0.5f) * 2.0f; + out.position.y = (float(high) - 0.5f) * 2.0f; + out.position.z = 0.0f; + out.position.w = 1.0f; + + return out; +} + +fragment float4 fragmentMain(VertexOut in [[stage_in]], + constant float clear_color [[buffer(0)]]) +{ + Fragment out; + + out.depth = clear_color; + + return out; +}