Metal: Buffers Take 2 (#21)
* Basic BufferManager * Start Scoped Command Buffers * Fences stuff * Remember to cleanup sync manager * Auto, Command Buffer Dependants * Cleanup * Cleanup + Fix Texture->Buffer Copies * Slow buffer upload * Cleanup + Rework TextureBuffer * Don’t get unsafe * Cleanup * Goddamn it * Staging Buffer + Interrupt Action + Flush
This commit is contained in:
parent
d0946213fa
commit
58b3e2e82b
24 changed files with 2380 additions and 205 deletions
|
@ -5,12 +5,11 @@ using SharpMetal.Foundation;
|
|||
using SharpMetal.Metal;
|
||||
using SharpMetal.QuartzCore;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace Ryujinx.Graphics.Metal
|
||||
{
|
||||
enum EncoderType
|
||||
public enum EncoderType
|
||||
{
|
||||
Blit,
|
||||
Compute,
|
||||
|
@ -19,14 +18,19 @@ namespace Ryujinx.Graphics.Metal
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("macos")]
|
||||
class Pipeline : IPipeline, IDisposable
|
||||
public class Pipeline : IPipeline, IDisposable
|
||||
{
|
||||
private readonly MTLDevice _device;
|
||||
private readonly MTLCommandQueue _commandQueue;
|
||||
private readonly HelperShader _helperShader;
|
||||
private readonly MetalRenderer _renderer;
|
||||
|
||||
private MTLCommandBuffer _commandBuffer;
|
||||
public MTLCommandBuffer CommandBuffer => _commandBuffer;
|
||||
private CommandBufferScoped Cbs;
|
||||
private CommandBufferScoped? PreloadCbs;
|
||||
public MTLCommandBuffer CommandBuffer;
|
||||
|
||||
public readonly Action EndRenderPassDelegate;
|
||||
|
||||
public CommandBufferScoped CurrentCommandBuffer => Cbs;
|
||||
|
||||
private MTLCommandEncoder? _currentEncoder;
|
||||
public MTLCommandEncoder? CurrentEncoder => _currentEncoder;
|
||||
|
@ -36,14 +40,20 @@ namespace Ryujinx.Graphics.Metal
|
|||
|
||||
private EncoderStateManager _encoderStateManager;
|
||||
|
||||
public Pipeline(MTLDevice device, MTLCommandQueue commandQueue)
|
||||
public Pipeline(MTLDevice device, MetalRenderer renderer, MTLCommandQueue commandQueue)
|
||||
{
|
||||
_device = device;
|
||||
_renderer = renderer;
|
||||
_commandQueue = commandQueue;
|
||||
_helperShader = new HelperShader(_device, this);
|
||||
|
||||
_commandBuffer = _commandQueue.CommandBuffer();
|
||||
_encoderStateManager = new EncoderStateManager(_device, this);
|
||||
EndRenderPassDelegate = EndCurrentPass;
|
||||
|
||||
CommandBuffer = (Cbs = _renderer.CommandBufferPool.Rent()).CommandBuffer;
|
||||
}
|
||||
|
||||
public void InitEncoderStateManager(BufferManager bufferManager)
|
||||
{
|
||||
_encoderStateManager = new EncoderStateManager(_device, bufferManager, this);
|
||||
}
|
||||
|
||||
public void SaveState()
|
||||
|
@ -156,7 +166,7 @@ namespace Ryujinx.Graphics.Metal
|
|||
EndCurrentPass();
|
||||
|
||||
var descriptor = new MTLBlitPassDescriptor();
|
||||
var blitCommandEncoder = _commandBuffer.BlitCommandEncoder(descriptor);
|
||||
var blitCommandEncoder = Cbs.CommandBuffer.BlitCommandEncoder(descriptor);
|
||||
|
||||
_currentEncoder = blitCommandEncoder;
|
||||
_currentEncoderType = EncoderType.Blit;
|
||||
|
@ -178,21 +188,35 @@ namespace Ryujinx.Graphics.Metal
|
|||
{
|
||||
// TODO: Clean this up
|
||||
var textureInfo = new TextureCreateInfo((int)drawable.Texture.Width, (int)drawable.Texture.Height, (int)drawable.Texture.Depth, (int)drawable.Texture.MipmapLevelCount, (int)drawable.Texture.SampleCount, 0, 0, 0, Format.B8G8R8A8Unorm, 0, Target.Texture2D, SwizzleComponent.Red, SwizzleComponent.Green, SwizzleComponent.Blue, SwizzleComponent.Alpha);
|
||||
var dst = new Texture(_device, this, textureInfo, drawable.Texture, 0, 0);
|
||||
var dst = new Texture(_device, _renderer, this, textureInfo, drawable.Texture, 0, 0);
|
||||
|
||||
_helperShader.BlitColor(src, dst, srcRegion, dstRegion, isLinear);
|
||||
_renderer.HelperShader.BlitColor(src, dst, srcRegion, dstRegion, isLinear);
|
||||
|
||||
EndCurrentPass();
|
||||
|
||||
_commandBuffer.PresentDrawable(drawable);
|
||||
_commandBuffer.Commit();
|
||||
Cbs.CommandBuffer.PresentDrawable(drawable);
|
||||
|
||||
_commandBuffer = _commandQueue.CommandBuffer();
|
||||
CommandBuffer = (Cbs = _renderer.CommandBufferPool.ReturnAndRent(Cbs)).CommandBuffer;
|
||||
|
||||
// TODO: Auto flush counting
|
||||
_renderer.SyncManager.GetAndResetWaitTicks();
|
||||
|
||||
// Cleanup
|
||||
dst.Dispose();
|
||||
}
|
||||
|
||||
public void FlushCommandsImpl()
|
||||
{
|
||||
SaveState();
|
||||
|
||||
EndCurrentPass();
|
||||
|
||||
CommandBuffer = (Cbs = _renderer.CommandBufferPool.ReturnAndRent(Cbs)).CommandBuffer;
|
||||
_renderer.RegisterFlush();
|
||||
|
||||
RestoreState();
|
||||
}
|
||||
|
||||
public void BlitColor(
|
||||
ITexture src,
|
||||
ITexture dst,
|
||||
|
@ -200,7 +224,7 @@ namespace Ryujinx.Graphics.Metal
|
|||
Extents2D dstRegion,
|
||||
bool linearFilter)
|
||||
{
|
||||
_helperShader.BlitColor(src, dst, srcRegion, dstRegion, linearFilter);
|
||||
_renderer.HelperShader.BlitColor(src, dst, srcRegion, dstRegion, linearFilter);
|
||||
}
|
||||
|
||||
public void Barrier()
|
||||
|
@ -235,9 +259,10 @@ namespace Ryujinx.Graphics.Metal
|
|||
{
|
||||
var blitCommandEncoder = GetOrCreateBlitEncoder();
|
||||
|
||||
var mtlBuffer = _renderer.BufferManager.GetBuffer(destination, offset, size, true).Get(Cbs, offset, size, true).Value;
|
||||
|
||||
// Might need a closer look, range's count, lower, and upper bound
|
||||
// must be a multiple of 4
|
||||
MTLBuffer mtlBuffer = new(Unsafe.As<BufferHandle, IntPtr>(ref destination));
|
||||
blitCommandEncoder.FillBuffer(mtlBuffer,
|
||||
new NSRange
|
||||
{
|
||||
|
@ -259,7 +284,7 @@ namespace Ryujinx.Graphics.Metal
|
|||
return;
|
||||
}
|
||||
|
||||
_helperShader.ClearColor(index, colors, componentMask, dst.Width, dst.Height);
|
||||
_renderer.HelperShader.ClearColor(index, colors, componentMask, dst.Width, dst.Height);
|
||||
}
|
||||
|
||||
public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask)
|
||||
|
@ -273,7 +298,7 @@ namespace Ryujinx.Graphics.Metal
|
|||
return;
|
||||
}
|
||||
|
||||
_helperShader.ClearDepthStencil(depthValue, depthMask, stencilValue, stencilMask, depthStencil.Width, depthStencil.Height);
|
||||
_renderer.HelperShader.ClearDepthStencil(depthValue, depthMask, stencilValue, stencilMask, depthStencil.Width, depthStencil.Height);
|
||||
}
|
||||
|
||||
public void CommandBufferBarrier()
|
||||
|
@ -281,19 +306,12 @@ namespace Ryujinx.Graphics.Metal
|
|||
Logger.Warning?.Print(LogClass.Gpu, "Not Implemented!");
|
||||
}
|
||||
|
||||
public void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size)
|
||||
public void CopyBuffer(BufferHandle src, BufferHandle dst, int srcOffset, int dstOffset, int size)
|
||||
{
|
||||
var blitCommandEncoder = GetOrCreateBlitEncoder();
|
||||
var srcBuffer = _renderer.BufferManager.GetBuffer(src, srcOffset, size, false);
|
||||
var dstBuffer = _renderer.BufferManager.GetBuffer(dst, dstOffset, size, true);
|
||||
|
||||
MTLBuffer sourceBuffer = new(Unsafe.As<BufferHandle, IntPtr>(ref source));
|
||||
MTLBuffer destinationBuffer = new(Unsafe.As<BufferHandle, IntPtr>(ref destination));
|
||||
|
||||
blitCommandEncoder.CopyFromBuffer(
|
||||
sourceBuffer,
|
||||
(ulong)srcOffset,
|
||||
destinationBuffer,
|
||||
(ulong)dstOffset,
|
||||
(ulong)size);
|
||||
BufferHolder.Copy(this, Cbs, srcBuffer, dstBuffer, srcOffset, dstOffset, size);
|
||||
}
|
||||
|
||||
public void DispatchCompute(int groupsX, int groupsY, int groupsZ, int groupSizeX, int groupSizeY, int groupSizeZ)
|
||||
|
@ -327,11 +345,13 @@ namespace Ryujinx.Graphics.Metal
|
|||
// TODO: Support topology re-indexing to provide support for TriangleFans
|
||||
var primitiveType = _encoderStateManager.Topology.Convert();
|
||||
|
||||
var indexBuffer = _renderer.BufferManager.GetBuffer(_encoderStateManager.IndexBuffer.Handle, false);
|
||||
|
||||
renderCommandEncoder.DrawIndexedPrimitives(
|
||||
primitiveType,
|
||||
(ulong)indexCount,
|
||||
_encoderStateManager.IndexType,
|
||||
_encoderStateManager.IndexBuffer,
|
||||
indexBuffer.Get(Cbs, 0, indexCount * sizeof(int)).Value,
|
||||
_encoderStateManager.IndexBufferOffset,
|
||||
(ulong)instanceCount,
|
||||
firstVertex,
|
||||
|
@ -368,7 +388,7 @@ namespace Ryujinx.Graphics.Metal
|
|||
|
||||
public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion)
|
||||
{
|
||||
_helperShader.DrawTexture(texture, sampler, srcRegion, dstRegion);
|
||||
_renderer.HelperShader.DrawTexture(texture, sampler, srcRegion, dstRegion);
|
||||
}
|
||||
|
||||
public void SetAlphaTest(bool enable, float reference, CompareOp op)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue