From 3ec45f73f43a33bcc32f2c769934f24509094079 Mon Sep 17 00:00:00 2001 From: Samuliak Date: Fri, 24 May 2024 15:28:16 +0200 Subject: [PATCH] don't interrupt render pass before color clear --- src/Ryujinx.Graphics.Metal/HelperShader.cs | 25 +++++++++++++------ src/Ryujinx.Graphics.Metal/Pipeline.cs | 2 +- .../Shaders/ColorClear.metal | 14 ++++++----- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/Ryujinx.Graphics.Metal/HelperShader.cs b/src/Ryujinx.Graphics.Metal/HelperShader.cs index d5446f615..2405e8066 100644 --- a/src/Ryujinx.Graphics.Metal/HelperShader.cs +++ b/src/Ryujinx.Graphics.Metal/HelperShader.cs @@ -5,6 +5,7 @@ using Ryujinx.Graphics.Shader.Translation; using SharpMetal.Foundation; using SharpMetal.Metal; using System; +using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.Versioning; @@ -18,7 +19,7 @@ namespace Ryujinx.Graphics.Metal private MTLDevice _device; private readonly IProgram _programColorBlit; - private readonly IProgram _programColorClear; + private readonly List _programsColorClear = new(); private readonly IProgram _programDepthStencilClear; public HelperShader(MTLDevice device, Pipeline pipeline) @@ -34,11 +35,15 @@ namespace Ryujinx.Graphics.Metal ], device); var colorClearSource = ReadMsl("ColorClear.metal"); - _programColorClear = new Program( - [ - new ShaderSource(colorClearSource, ShaderStage.Fragment, TargetLanguage.Msl), - new ShaderSource(colorClearSource, ShaderStage.Vertex, TargetLanguage.Msl) - ], device); + for (int i = 0; i < Constants.MaxColorAttachments; i++) + { + var crntSource = colorClearSource.Replace("COLOR_ATTACHMENT_INDEX", i.ToString()); + _programsColorClear.Add(new Program( + [ + new ShaderSource(crntSource, ShaderStage.Fragment, TargetLanguage.Msl), + new ShaderSource(crntSource, ShaderStage.Vertex, TargetLanguage.Msl) + ], device)); + } var depthStencilClearSource = ReadMsl("DepthStencilClear.metal"); _programDepthStencilClear = new Program( @@ -79,6 +84,7 @@ namespace Ryujinx.Graphics.Metal public unsafe void ClearColor( Texture dst, + int index, ReadOnlySpan clearColor) { const int ClearColorBufferSize = 16; @@ -101,7 +107,7 @@ namespace Ryujinx.Graphics.Metal _pipeline.SetUniformBuffers([new BufferAssignment(0, range)]); - _pipeline.SetProgram(_programColorClear); + _pipeline.SetProgram(_programsColorClear[index]); _pipeline.SetRenderTargets([dst], null); // _pipeline.SetRenderTargetColorMasks([componentMask]); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); @@ -175,7 +181,10 @@ namespace Ryujinx.Graphics.Metal public void Dispose() { _programColorBlit.Dispose(); - _programColorClear.Dispose(); + foreach (var programColorClear in _programsColorClear) + { + programColorClear.Dispose(); + } _programDepthStencilClear.Dispose(); _pipeline.Dispose(); } diff --git a/src/Ryujinx.Graphics.Metal/Pipeline.cs b/src/Ryujinx.Graphics.Metal/Pipeline.cs index e3e392177..3d9e108a1 100644 --- a/src/Ryujinx.Graphics.Metal/Pipeline.cs +++ b/src/Ryujinx.Graphics.Metal/Pipeline.cs @@ -216,7 +216,7 @@ namespace Ryujinx.Graphics.Metal Texture target = _encoderStateManager.RenderTargets[index]; - _helperShader.ClearColor(target, colors); + _helperShader.ClearColor(target, index, colors); } public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask) diff --git a/src/Ryujinx.Graphics.Metal/Shaders/ColorClear.metal b/src/Ryujinx.Graphics.Metal/Shaders/ColorClear.metal index 85ae873e6..087c48606 100644 --- a/src/Ryujinx.Graphics.Metal/Shaders/ColorClear.metal +++ b/src/Ryujinx.Graphics.Metal/Shaders/ColorClear.metal @@ -6,8 +6,7 @@ struct VertexOut { float4 position [[position]]; }; -vertex VertexOut vertexMain(ushort vid [[vertex_id]]) -{ +vertex VertexOut vertexMain(ushort vid [[vertex_id]]) { int low = vid & 1; int high = vid >> 1; @@ -21,8 +20,11 @@ vertex VertexOut vertexMain(ushort vid [[vertex_id]]) return out; } -fragment float4 fragmentMain(VertexOut in [[stage_in]], - constant float4& clear_color [[buffer(0)]]) -{ - return clear_color; +struct FragmentOut { + float4 color [[color(COLOR_ATTACHMENT_INDEX)]]; +}; + +fragment FragmentOut fragmentMain(VertexOut in [[stage_in]], + constant float4& clear_color [[buffer(0)]]) { + return {clear_color}; }