diff --git a/src/Ryujinx.Graphics.Metal/Pipeline.cs b/src/Ryujinx.Graphics.Metal/Pipeline.cs index 254f3e842..b1c3c03de 100644 --- a/src/Ryujinx.Graphics.Metal/Pipeline.cs +++ b/src/Ryujinx.Graphics.Metal/Pipeline.cs @@ -10,6 +10,13 @@ using System.Runtime.Versioning; namespace Ryujinx.Graphics.Metal { + enum EncoderType + { + Blit, + Compute, + Render + } + [SupportedOSPlatform("macos")] class Pipeline : IPipeline, IDisposable { @@ -24,6 +31,7 @@ namespace Ryujinx.Graphics.Metal private MTLCommandBuffer _commandBuffer; private MTLCommandEncoder? _currentEncoder; + private EncoderType _currentEncoderType; private MTLTexture[] _renderTargets = []; private RenderEncoderState _renderEncoderState; @@ -77,9 +85,12 @@ namespace Ryujinx.Graphics.Metal public MTLRenderCommandEncoder GetOrCreateRenderEncoder() { - if (_currentEncoder is MTLRenderCommandEncoder encoder) + if (_currentEncoder != null) { - return encoder; + if (_currentEncoderType == EncoderType.Render) + { + return new MTLRenderCommandEncoder(_currentEncoder.Value); + } } return BeginRenderPass(); @@ -87,9 +98,12 @@ namespace Ryujinx.Graphics.Metal public MTLBlitCommandEncoder GetOrCreateBlitEncoder() { - if (_currentEncoder is MTLBlitCommandEncoder encoder) + if (_currentEncoder != null) { - return encoder; + if (_currentEncoderType == EncoderType.Blit) + { + return new MTLBlitCommandEncoder(_currentEncoder.Value); + } } return BeginBlitPass(); @@ -97,9 +111,12 @@ namespace Ryujinx.Graphics.Metal public MTLComputeCommandEncoder GetOrCreateComputeEncoder() { - if (_currentEncoder is MTLComputeCommandEncoder encoder) + if (_currentEncoder != null) { - return encoder; + if (_currentEncoderType == EncoderType.Compute) + { + return new MTLComputeCommandEncoder(_currentEncoder.Value); + } } return BeginComputePass(); @@ -109,8 +126,23 @@ namespace Ryujinx.Graphics.Metal { if (_currentEncoder != null) { - _currentEncoder.EndEncoding(); - _currentEncoder = null; + switch (_currentEncoderType) + { + case EncoderType.Blit: + new MTLBlitCommandEncoder(_currentEncoder.Value).EndEncoding(); + _currentEncoder = null; + break; + case EncoderType.Compute: + new MTLComputeCommandEncoder(_currentEncoder.Value).EndEncoding(); + _currentEncoder = null; + break; + case EncoderType.Render: + new MTLRenderCommandEncoder(_currentEncoder.Value).EndEncoding(); + _currentEncoder = null; + break; + default: + throw new ArgumentOutOfRangeException(); + } } } @@ -140,6 +172,7 @@ namespace Ryujinx.Graphics.Metal } _currentEncoder = renderCommandEncoder; + _currentEncoderType = EncoderType.Render; return renderCommandEncoder; } @@ -151,6 +184,7 @@ namespace Ryujinx.Graphics.Metal var blitCommandEncoder = _commandBuffer.BlitCommandEncoder(descriptor); _currentEncoder = blitCommandEncoder; + _currentEncoderType = EncoderType.Blit; return blitCommandEncoder; } @@ -162,6 +196,7 @@ namespace Ryujinx.Graphics.Metal var computeCommandEncoder = _commandBuffer.ComputeCommandEncoder(descriptor); _currentEncoder = computeCommandEncoder; + _currentEncoderType = EncoderType.Compute; return computeCommandEncoder; } @@ -175,9 +210,13 @@ namespace Ryujinx.Graphics.Metal EndCurrentPass(); var descriptor = new MTLRenderPassDescriptor(); - descriptor.ColorAttachments.Object(0).Texture = drawable.Texture; - descriptor.ColorAttachments.Object(0).LoadAction = MTLLoadAction.Clear; - descriptor.ColorAttachments.Object(0).ClearColor = _clearColor; + var colorAttachment = descriptor.ColorAttachments.Object(0); + + colorAttachment.Texture = drawable.Texture; + colorAttachment.LoadAction = MTLLoadAction.Clear; + colorAttachment.ClearColor = _clearColor; + + descriptor.ColorAttachments.SetObject(colorAttachment, 0); var renderCommandEncoder = _commandBuffer.RenderCommandEncoder(descriptor); _renderEncoderState.SetEncoderState(renderCommandEncoder, _vertexDescriptor); @@ -352,9 +391,9 @@ namespace Ryujinx.Graphics.Metal depthTest.TestEnable ? depthTest.Func.Convert() : MTLCompareFunction.Always, depthTest.WriteEnable); - if (_currentEncoder is MTLRenderCommandEncoder renderCommandEncoder) + if (_currentEncoderType == EncoderType.Render) { - renderCommandEncoder.SetDepthStencilState(depthStencilState); + new MTLRenderCommandEncoder(_currentEncoder.Value).SetDepthStencilState(depthStencilState); } } @@ -362,9 +401,9 @@ namespace Ryujinx.Graphics.Metal { var cullMode = enable ? face.Convert() : MTLCullMode.None; - if (_currentEncoder is MTLRenderCommandEncoder renderCommandEncoder) + if (_currentEncoderType == EncoderType.Render) { - renderCommandEncoder.SetCullMode(cullMode); + new MTLRenderCommandEncoder(_currentEncoder.Value).SetCullMode(cullMode); } _renderEncoderState.CullMode = cullMode; @@ -374,9 +413,9 @@ namespace Ryujinx.Graphics.Metal { var winding = frontFace.Convert(); - if (_currentEncoder is MTLRenderCommandEncoder renderCommandEncoder) + if (_currentEncoderType == EncoderType.Render) { - renderCommandEncoder.SetFrontFacingWinding(winding); + new MTLRenderCommandEncoder(_currentEncoder.Value).SetFrontFacingWinding(winding); } _renderEncoderState.Winding = winding; @@ -545,9 +584,9 @@ namespace Ryujinx.Graphics.Metal var depthStencilState = _renderEncoderState.UpdateStencilState(backFace, frontFace); - if (_currentEncoder is MTLRenderCommandEncoder renderCommandEncoder) + if (_currentEncoderType == EncoderType.Render) { - renderCommandEncoder.SetDepthStencilState(depthStencilState); + new MTLRenderCommandEncoder(_currentEncoder.Value).SetDepthStencilState(depthStencilState); } } @@ -594,7 +633,11 @@ namespace Ryujinx.Graphics.Metal { if (vertexBuffers[i].Stride != 0) { - _vertexDescriptor.Layouts.Object((ulong)i).Stride = (ulong)vertexBuffers[i].Stride; + var layout = _vertexDescriptor.Layouts.Object(0); + + layout.Stride = (ulong)vertexBuffers[i].Stride; + + _vertexDescriptor.Layouts.SetObject(layout, (ulong)i); _vertexBuffers[i] = _device.NewBuffer( vertexBuffers[i].Buffer.Handle.ToIntPtr(), (ulong)vertexBuffers[i].Buffer.Size, diff --git a/src/Ryujinx/AppHost.cs b/src/Ryujinx/AppHost.cs index eee17d206..a995e36bc 100644 --- a/src/Ryujinx/AppHost.cs +++ b/src/Ryujinx/AppHost.cs @@ -832,7 +832,7 @@ namespace Ryujinx.Ava } else if (ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Metal && OperatingSystem.IsMacOS()) { - renderer = new MetalRenderer(); + renderer = new MetalRenderer((RendererHost.EmbeddedWindow as EmbeddedWindowMetal).CreateSurface); } else { diff --git a/src/Ryujinx/UI/Renderer/EmbeddedWindowMetal.cs b/src/Ryujinx/UI/Renderer/EmbeddedWindowMetal.cs index 5373f8ed1..e55b75715 100644 --- a/src/Ryujinx/UI/Renderer/EmbeddedWindowMetal.cs +++ b/src/Ryujinx/UI/Renderer/EmbeddedWindowMetal.cs @@ -1,25 +1,12 @@ -using SPB.Windowing; -using SPB.Platform.Metal; -using System; +using SharpMetal.QuartzCore; namespace Ryujinx.Ava.UI.Renderer { public class EmbeddedWindowMetal : EmbeddedWindow { - public SimpleMetalWindow CreateSurface() + public CAMetalLayer CreateSurface() { - SimpleMetalWindow simpleMetalWindow; - - if (OperatingSystem.IsMacOS()) - { - simpleMetalWindow = new SimpleMetalWindow(new NativeHandle(NsView), new NativeHandle(MetalLayer)); - } - else - { - throw new PlatformNotSupportedException(); - } - - return simpleMetalWindow; + return new CAMetalLayer(MetalLayer); } } } diff --git a/src/Ryujinx/UI/Renderer/RendererHost.axaml.cs b/src/Ryujinx/UI/Renderer/RendererHost.axaml.cs index d055d9ea4..f137dab99 100644 --- a/src/Ryujinx/UI/Renderer/RendererHost.axaml.cs +++ b/src/Ryujinx/UI/Renderer/RendererHost.axaml.cs @@ -17,14 +17,13 @@ namespace Ryujinx.Ava.UI.Renderer { InitializeComponent(); - if (ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.OpenGl) + EmbeddedWindow = ConfigurationState.Instance.Graphics.GraphicsBackend.Value switch { - EmbeddedWindow = new EmbeddedWindowOpenGL(); - } - else - { - EmbeddedWindow = new EmbeddedWindowVulkan(); - } + GraphicsBackend.OpenGl => new EmbeddedWindowOpenGL(), + GraphicsBackend.Metal => new EmbeddedWindowMetal(), + GraphicsBackend.Vulkan => new EmbeddedWindowVulkan(), + _ => throw new NotSupportedException() + }; Initialize(); }