diff --git a/src/Ryujinx.Graphics.Metal/Pipeline.cs b/src/Ryujinx.Graphics.Metal/Pipeline.cs index 2eb0340a5..327bd849f 100644 --- a/src/Ryujinx.Graphics.Metal/Pipeline.cs +++ b/src/Ryujinx.Graphics.Metal/Pipeline.cs @@ -524,12 +524,17 @@ namespace Ryujinx.Graphics.Metal public unsafe void SetScissors(ReadOnlySpan> regions) { - // TODO: Test max allowed scissor rects on device - var mtlScissorRects = new MTLScissorRect[regions.Length]; + int maxScissors = Math.Min(regions.Length, _renderEncoderState.ViewportCount); - for (int i = 0; i < regions.Length; i++) + if (maxScissors == 0) { return; } + + // TODO: Test max allowed scissor rects on device + var mtlScissorRects = new MTLScissorRect[maxScissors]; + + for (int i = 0; i < maxScissors; i++) { var region = regions[i]; + mtlScissorRects[i] = new MTLScissorRect { height = (ulong)region.Height, @@ -539,10 +544,13 @@ namespace Ryujinx.Graphics.Metal }; } - fixed (MTLScissorRect* pMtlScissorRects = mtlScissorRects) - { - var renderCommandEncoder = GetOrCreateRenderEncoder(); - renderCommandEncoder.SetScissorRects((IntPtr)pMtlScissorRects, (ulong)regions.Length); + _renderEncoderState.UpdateScissors(mtlScissorRects); + if (_currentEncoderType == EncoderType.Render) { + fixed (MTLScissorRect* pMtlScissorRects = mtlScissorRects) + { + var renderCommandEncoder = GetOrCreateRenderEncoder(); + renderCommandEncoder.SetScissorRects((IntPtr)pMtlScissorRects, (ulong)regions.Length); + } } } @@ -730,10 +738,14 @@ namespace Ryujinx.Graphics.Metal }; } - fixed (MTLViewport* pMtlViewports = mtlViewports) + _renderEncoderState.UpdateViewport(mtlViewports); + if (_currentEncoderType == EncoderType.Render) { - var renderCommandEncoder = GetOrCreateRenderEncoder(); - renderCommandEncoder.SetViewports((IntPtr)pMtlViewports, (ulong)viewports.Length); + fixed (MTLViewport* pMtlViewports = mtlViewports) + { + var renderCommandEncoder = GetOrCreateRenderEncoder(); + renderCommandEncoder.SetViewports((IntPtr)pMtlViewports, (ulong)viewports.Length); + } } } diff --git a/src/Ryujinx.Graphics.Metal/RenderEncoderState.cs b/src/Ryujinx.Graphics.Metal/RenderEncoderState.cs index f5e8fe30b..4a045c96b 100644 --- a/src/Ryujinx.Graphics.Metal/RenderEncoderState.cs +++ b/src/Ryujinx.Graphics.Metal/RenderEncoderState.cs @@ -25,6 +25,10 @@ namespace Ryujinx.Graphics.Metal public MTLCullMode CullMode = MTLCullMode.None; public MTLWinding Winding = MTLWinding.Clockwise; + private MTLViewport[] _viewports = []; + private MTLScissorRect[] _scissors = []; + public int ViewportCount => _viewports.Length; + public RenderEncoderState(MTLFunction vertexFunction, MTLFunction fragmentFunction, MTLDevice device) { _vertexFunction = vertexFunction; @@ -32,7 +36,7 @@ namespace Ryujinx.Graphics.Metal _device = device; } - public readonly void SetEncoderState(MTLRenderCommandEncoder renderCommandEncoder, MTLVertexDescriptor vertexDescriptor) + public unsafe readonly void SetEncoderState(MTLRenderCommandEncoder renderCommandEncoder, MTLVertexDescriptor vertexDescriptor) { var renderPipelineDescriptor = new MTLRenderPipelineDescriptor { @@ -72,6 +76,22 @@ namespace Ryujinx.Graphics.Metal { renderCommandEncoder.SetDepthStencilState(_depthStencilState.Value); } + + if (_viewports.Length > 0) + { + fixed (MTLViewport* pMtlViewports = _viewports) + { + renderCommandEncoder.SetViewports((IntPtr)pMtlViewports, (ulong)_viewports.Length); + } + } + + if (_scissors.Length > 0) + { + fixed (MTLScissorRect* pMtlScissors = _scissors) + { + renderCommandEncoder.SetScissorRects((IntPtr)pMtlScissors, (ulong)_scissors.Length); + } + } } public MTLDepthStencilState UpdateStencilState(MTLStencilDescriptor backFace, MTLStencilDescriptor frontFace) @@ -107,5 +127,15 @@ namespace Ryujinx.Graphics.Metal return state; } + + public void UpdateScissors(MTLScissorRect[] scissors) + { + _scissors = scissors; + } + + public void UpdateViewport(MTLViewport[] viewports) + { + _viewports = viewports; + } } }