diff --git a/src/Ryujinx.Graphics.Metal/Pipeline.cs b/src/Ryujinx.Graphics.Metal/Pipeline.cs index e782c9540..9b01bb2a5 100644 --- a/src/Ryujinx.Graphics.Metal/Pipeline.cs +++ b/src/Ryujinx.Graphics.Metal/Pipeline.cs @@ -18,6 +18,26 @@ namespace Ryujinx.Graphics.Metal None } + [SupportedOSPlatform("macos")] + struct ColorClear + { + public int Layer; + public int LayerCount; + public uint ComponentMask; + public ColorF Color; + } + + [SupportedOSPlatform("macos")] + struct DepthStencilClear + { + public int Layer; + public int LayerCount; + public float DepthValue; + public bool DepthMask; + public int StencilValue; + public int StencilMask; + } + [SupportedOSPlatform("macos")] class Pipeline : IPipeline, IDisposable { @@ -36,6 +56,10 @@ namespace Ryujinx.Graphics.Metal private EncoderStateManager _encoderStateManager; + // Deferred clears + private ColorClear?[] _colorClears = new ColorClear?[Constants.MaxColorAttachments]; + private DepthStencilClear? _depthStencilClear; + public Pipeline(MTLDevice device, MTLCommandQueue commandQueue) { _device = device; @@ -152,6 +176,38 @@ namespace Ryujinx.Graphics.Metal return computeCommandEncoder; } + public void ExecuteDeferredColorClears() + { + for (int i = 0; i < Constants.MaxColorAttachments; i++) + { + if (_colorClears[i] != null) + { + ColorF color = _colorClears[i].Value.Color; + float[] colors = [color.Red, color.Green, color.Blue, color.Alpha]; + + Texture target = _encoderStateManager.RenderTargets[i]; + + _encoderStateManager.SwapStates(); + + _helperShader.ClearColor(target, colors); + } + _colorClears[i] = null; + } + } + + public void ExecuteDeferredDepthStencilClear() + { + if (_depthStencilClear != null) + { + Texture target = _encoderStateManager.DepthStencil; + + _encoderStateManager.SwapStates(); + + _helperShader.ClearDepthStencil(target, [_depthStencilClear.Value.DepthValue], _depthStencilClear.Value.DepthMask, _depthStencilClear.Value.StencilValue, _depthStencilClear.Value.StencilMask); + } + _depthStencilClear = null; + } + public void Present(CAMetalDrawable drawable, ITexture texture) { if (texture is not Texture tex) @@ -203,22 +259,30 @@ namespace Ryujinx.Graphics.Metal public void ClearRenderTargetColor(int index, int layer, int layerCount, uint componentMask, ColorF color) { - float[] colors = [color.Red, color.Green, color.Blue, color.Alpha]; + _colorClears[index] = new ColorClear + { + Layer = layer, + LayerCount = layerCount, + ComponentMask = componentMask, + Color = color + }; - Texture target = _encoderStateManager.RenderTargets[index]; - - _encoderStateManager.SwapStates(); - - _helperShader.ClearColor(target, colors); + ExecuteDeferredColorClears(); } public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask) { - Texture target = _encoderStateManager.DepthStencil; + _depthStencilClear = new DepthStencilClear + { + Layer = layer, + LayerCount = layerCount, + DepthValue = depthValue, + DepthMask = depthMask, + StencilValue = stencilValue, + StencilMask = stencilMask + }; - _encoderStateManager.SwapStates(); - - _helperShader.ClearDepthStencil(target, [depthValue], depthMask, stencilValue, stencilMask); + ExecuteDeferredDepthStencilClear(); } public void CommandBufferBarrier() diff --git a/src/Ryujinx.Graphics.Metal/Shaders/DepthStencilClear.metal b/src/Ryujinx.Graphics.Metal/Shaders/DepthStencilClear.metal index ad22837fd..019bf78d4 100644 --- a/src/Ryujinx.Graphics.Metal/Shaders/DepthStencilClear.metal +++ b/src/Ryujinx.Graphics.Metal/Shaders/DepthStencilClear.metal @@ -11,8 +11,7 @@ struct FragmentOut { uint stencil [[stencil]]; }; -vertex VertexOut vertexMain(ushort vid [[vertex_id]]) -{ +vertex VertexOut vertexMain(ushort vid [[vertex_id]]) { int low = vid & 1; int high = vid >> 1; @@ -27,11 +26,10 @@ vertex VertexOut vertexMain(ushort vid [[vertex_id]]) } fragment FragmentOut fragmentMain(VertexOut in [[stage_in]], - constant float& clear_color [[buffer(0)]]) -{ + constant float& clear_depth [[buffer(0)]]) { FragmentOut out; - out.depth = clear_color; + out.depth = clear_depth; // out.stencil = stencil_clear; return out;