diff --git a/src/Ryujinx.Graphics.Metal/MetalRenderer.cs b/src/Ryujinx.Graphics.Metal/MetalRenderer.cs index 48ddfba7a..b08e23b80 100644 --- a/src/Ryujinx.Graphics.Metal/MetalRenderer.cs +++ b/src/Ryujinx.Graphics.Metal/MetalRenderer.cs @@ -31,9 +31,7 @@ namespace Ryujinx.Graphics.Metal _device = MTLDevice.CreateSystemDefaultDevice(); Queue = _device.NewCommandQueue(); - var commandBuffer = Queue.CommandBuffer(); - - _pipeline = new Pipeline(_device, commandBuffer); + _pipeline = new Pipeline(_device, Queue); } public void BackgroundContextAction(Action action, bool alwaysBackground = false) diff --git a/src/Ryujinx.Graphics.Metal/Pipeline.cs b/src/Ryujinx.Graphics.Metal/Pipeline.cs index ff111a2ec..dd1a5e071 100644 --- a/src/Ryujinx.Graphics.Metal/Pipeline.cs +++ b/src/Ryujinx.Graphics.Metal/Pipeline.cs @@ -11,9 +11,16 @@ namespace Ryujinx.Graphics.Metal [SupportedOSPlatform("macos")] public class Pipeline : IPipeline, IDisposable { - private MTLDevice _device; + private readonly MTLDevice _device; + private readonly MTLCommandQueue _mtlCommandQueue; + private MTLCommandBuffer _commandBuffer; private MTLRenderCommandEncoder _renderCommandEncoder; + private MTLRenderPipelineState _renderPipelineState; + private MTLBlitCommandEncoder _blitCommandEncoder; + + public MTLRenderCommandEncoder RenderCommandEncoder => _renderCommandEncoder; + public MTLBlitCommandEncoder BlitCommandEncoder => _blitCommandEncoder; private PrimitiveTopology _topology; @@ -21,21 +28,42 @@ namespace Ryujinx.Graphics.Metal private MTLIndexType _indexType; private ulong _indexBufferOffset; - public Pipeline(MTLDevice device, MTLCommandBuffer commandBuffer) + public Pipeline(MTLDevice device, MTLCommandQueue commandQueue) { + _device = device; + _mtlCommandQueue = commandQueue; + var renderPipelineDescriptor = new MTLRenderPipelineDescriptor(); var error = new NSError(IntPtr.Zero); - _device = device; - var renderPipelineState = _device.NewRenderPipelineState(renderPipelineDescriptor, ref error); + _renderPipelineState = _device.NewRenderPipelineState(renderPipelineDescriptor, ref error); if (error != IntPtr.Zero) { // throw new Exception($"Failed to create render pipeline state! {StringHelp}"); throw new Exception($"Failed to create render pipeline state!"); } - _commandBuffer = commandBuffer; + CreateCommandBuffer(); + } + + public void Present() + { + _renderCommandEncoder.EndEncoding(); + _blitCommandEncoder.EndEncoding(); + // TODO: Give command buffer a valid MTLDrawable + // _commandBuffer.PresentDrawable(); + _commandBuffer.Commit(); + + CreateCommandBuffer(); + } + + public void CreateCommandBuffer() + { + _commandBuffer = _mtlCommandQueue.CommandBuffer(); + _renderCommandEncoder = _commandBuffer.RenderCommandEncoder(new MTLRenderPassDescriptor()); - _renderCommandEncoder.SetRenderPipelineState(renderPipelineState); + _renderCommandEncoder.SetRenderPipelineState(_renderPipelineState); + + _blitCommandEncoder = _commandBuffer.BlitCommandEncoder(new MTLBlitPassDescriptor()); } public void Barrier() diff --git a/src/Ryujinx.Graphics.Metal/Texture.cs b/src/Ryujinx.Graphics.Metal/Texture.cs index 064d6bd1a..a2c2443b4 100644 --- a/src/Ryujinx.Graphics.Metal/Texture.cs +++ b/src/Ryujinx.Graphics.Metal/Texture.cs @@ -10,13 +10,14 @@ namespace Ryujinx.Graphics.Metal class Texture : ITexture, IDisposable { private readonly TextureCreateInfo _info; + private readonly Pipeline _pipeline; public MTLTexture MTLTexture; public TextureCreateInfo Info => Info; public int Width => Info.Width; public int Height => Info.Height; - public Texture(MTLDevice device, TextureCreateInfo info, int firstLayer, int firstLevel) + public Texture(MTLDevice device, Pipeline pipeline, TextureCreateInfo info, int firstLayer, int firstLevel) { _info = info; @@ -27,6 +28,7 @@ namespace Ryujinx.Graphics.Metal descriptor.Height = (ulong)Height; descriptor.Depth = (ulong)Info.Depth; descriptor.SampleCount = (ulong)Info.Samples; + descriptor.MipmapLevelCount = (ulong)Info.Levels; descriptor.TextureType = Info.Target.Convert(); descriptor.Swizzle = new MTLTextureSwizzleChannels { @@ -37,16 +39,39 @@ namespace Ryujinx.Graphics.Metal }; MTLTexture = device.NewTexture(descriptor); + _pipeline = pipeline; } public void CopyTo(ITexture destination, int firstLayer, int firstLevel) { - throw new NotImplementedException(); + if (destination is Texture destinationTexture) + { + _pipeline.BlitCommandEncoder.CopyFromTexture( + MTLTexture, + (ulong)firstLayer, + (ulong)firstLevel, + destinationTexture.MTLTexture, + (ulong)firstLayer, + (ulong)firstLevel, + MTLTexture.ArrayLength, + MTLTexture.MipmapLevelCount); + } } public void CopyTo(ITexture destination, int srcLayer, int dstLayer, int srcLevel, int dstLevel) { - throw new NotImplementedException(); + if (destination is Texture destinationTexture) + { + _pipeline.BlitCommandEncoder.CopyFromTexture( + MTLTexture, + (ulong)srcLayer, + (ulong)srcLevel, + destinationTexture.MTLTexture, + (ulong)dstLayer, + (ulong)dstLevel, + MTLTexture.ArrayLength, + MTLTexture.MipmapLevelCount); + } } public void CopyTo(ITexture destination, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter) diff --git a/src/Ryujinx.Graphics.Metal/Window.cs b/src/Ryujinx.Graphics.Metal/Window.cs index 59122a493..31c534958 100644 --- a/src/Ryujinx.Graphics.Metal/Window.cs +++ b/src/Ryujinx.Graphics.Metal/Window.cs @@ -1,23 +1,25 @@ using Ryujinx.Graphics.GAL; using System; -using SharpMetal; +using System.Runtime.Versioning; namespace Ryujinx.Graphics.Metal { + [SupportedOSPlatform("macos")] public class Window : IWindow, IDisposable { + private readonly MetalRenderer _renderer; - public Window() + public Window(MetalRenderer renderer) { - /*var viewport = new MTLViewport - { - - };*/ + _renderer = renderer; } public void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback) { - throw new NotImplementedException(); + if (_renderer.Pipeline is Pipeline pipeline) + { + pipeline.Present(); + } } public void SetSize(int width, int height) @@ -50,4 +52,4 @@ namespace Ryujinx.Graphics.Metal } } -} \ No newline at end of file +}