Shitty Clears + Inline Buffer Improvements?

This commit is contained in:
Isaac Marovitz 2024-05-22 17:21:44 -04:00 committed by Isaac Marovitz
parent 087bf71a13
commit 8feee9c005
11 changed files with 124 additions and 61 deletions

View file

@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Metal
} }
[SupportedOSPlatform("macos")] [SupportedOSPlatform("macos")]
public struct EncoderState struct EncoderState
{ {
public MTLFunction? VertexFunction = null; public MTLFunction? VertexFunction = null;
public MTLFunction? FragmentFunction = null; public MTLFunction? FragmentFunction = null;
@ -62,7 +62,7 @@ namespace Ryujinx.Graphics.Metal
// Changes to attachments take recreation! // Changes to attachments take recreation!
public MTLTexture DepthStencil = default; public MTLTexture DepthStencil = default;
public MTLTexture[] RenderTargets = new MTLTexture[Constants.MaxColorAttachments]; public Texture[] RenderTargets = new Texture[Constants.MaxColorAttachments];
public Dictionary<int, BlendDescriptor> BlendDescriptors = new(); public Dictionary<int, BlendDescriptor> BlendDescriptors = new();
public ColorF BlendColor = new(); public ColorF BlendColor = new();

View file

@ -25,6 +25,7 @@ namespace Ryujinx.Graphics.Metal
public readonly MTLIndexType IndexType => _currentState.IndexType; public readonly MTLIndexType IndexType => _currentState.IndexType;
public readonly ulong IndexBufferOffset => _currentState.IndexBufferOffset; public readonly ulong IndexBufferOffset => _currentState.IndexBufferOffset;
public readonly PrimitiveTopology Topology => _currentState.Topology; public readonly PrimitiveTopology Topology => _currentState.Topology;
public readonly Texture[] RenderTargets => _currentState.RenderTargets;
public EncoderStateManager(MTLDevice device, Pipeline pipeline) public EncoderStateManager(MTLDevice device, Pipeline pipeline)
{ {
@ -50,10 +51,10 @@ namespace Ryujinx.Graphics.Metal
for (int i = 0; i < Constants.MaxColorAttachments; i++) for (int i = 0; i < Constants.MaxColorAttachments; i++)
{ {
if (_currentState.RenderTargets[i] != IntPtr.Zero) if (_currentState.RenderTargets[i] != null)
{ {
var passAttachment = renderPassDescriptor.ColorAttachments.Object((ulong)i); var passAttachment = renderPassDescriptor.ColorAttachments.Object((ulong)i);
passAttachment.Texture = _currentState.RenderTargets[i]; passAttachment.Texture = _currentState.RenderTargets[i].MTLTexture;
passAttachment.LoadAction = MTLLoadAction.Load; passAttachment.LoadAction = MTLLoadAction.Load;
} }
} }
@ -136,10 +137,10 @@ namespace Ryujinx.Graphics.Metal
for (int i = 0; i < Constants.MaxColorAttachments; i++) for (int i = 0; i < Constants.MaxColorAttachments; i++)
{ {
if (_currentState.RenderTargets[i] != IntPtr.Zero) if (_currentState.RenderTargets[i] != null)
{ {
var pipelineAttachment = renderPipelineDescriptor.ColorAttachments.Object((ulong)i); var pipelineAttachment = renderPipelineDescriptor.ColorAttachments.Object((ulong)i);
pipelineAttachment.PixelFormat = _currentState.RenderTargets[i].PixelFormat; pipelineAttachment.PixelFormat = _currentState.RenderTargets[i].MTLTexture.PixelFormat;
pipelineAttachment.SourceAlphaBlendFactor = MTLBlendFactor.SourceAlpha; pipelineAttachment.SourceAlphaBlendFactor = MTLBlendFactor.SourceAlpha;
pipelineAttachment.DestinationAlphaBlendFactor = MTLBlendFactor.OneMinusSourceAlpha; pipelineAttachment.DestinationAlphaBlendFactor = MTLBlendFactor.OneMinusSourceAlpha;
pipelineAttachment.SourceRGBBlendFactor = MTLBlendFactor.SourceAlpha; pipelineAttachment.SourceRGBBlendFactor = MTLBlendFactor.SourceAlpha;
@ -247,7 +248,7 @@ namespace Ryujinx.Graphics.Metal
public void UpdateRenderTargets(ITexture[] colors, ITexture depthStencil) public void UpdateRenderTargets(ITexture[] colors, ITexture depthStencil)
{ {
_currentState.RenderTargets = new MTLTexture[Constants.MaxColorAttachments]; _currentState.RenderTargets = new Texture[Constants.MaxColorAttachments];
for (int i = 0; i < colors.Length; i++) for (int i = 0; i < colors.Length; i++)
{ {
@ -256,7 +257,7 @@ namespace Ryujinx.Graphics.Metal
continue; continue;
} }
_currentState.RenderTargets[i] = tex.MTLTexture; _currentState.RenderTargets[i] = tex;
} }
if (depthStencil is Texture depthTexture) if (depthStencil is Texture depthTexture)

View file

@ -2,8 +2,10 @@ using Ryujinx.Common;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using SharpMetal.Foundation;
using SharpMetal.Metal; using SharpMetal.Metal;
using System; using System;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.Graphics.Metal namespace Ryujinx.Graphics.Metal
@ -23,9 +25,7 @@ namespace Ryujinx.Graphics.Metal
private MTLDevice _device; private MTLDevice _device;
private readonly IProgram _programColorBlit; private readonly IProgram _programColorBlit;
private readonly IProgram _programColorClearF; private readonly IProgram _programColorClear;
private readonly IProgram _programColorClearSI;
private readonly IProgram _programColorClearUI;
private readonly IProgram _programDepthStencilClear; private readonly IProgram _programDepthStencilClear;
public HelperShader(MTLDevice device, Pipeline pipeline) public HelperShader(MTLDevice device, Pipeline pipeline)
@ -40,6 +40,13 @@ namespace Ryujinx.Graphics.Metal
new ShaderSource(blitSource, ShaderStage.Vertex, TargetLanguage.Msl) new ShaderSource(blitSource, ShaderStage.Vertex, TargetLanguage.Msl)
], device); ], device);
var colorClearSource = ReadMsl("ColorClear.metal");
_programColorClear = new Program(
[
new ShaderSource(colorClearSource, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(colorClearSource, ShaderStage.Vertex, TargetLanguage.Msl)
], device);
// var colorClearFSource = ReadMsl("ColorClearF.metal"); // var colorClearFSource = ReadMsl("ColorClearF.metal");
// _programColorClearF = new Program( // _programColorClearF = new Program(
// [ // [
@ -93,45 +100,30 @@ namespace Ryujinx.Graphics.Metal
_pipeline.Finish(); _pipeline.Finish();
} }
public void ClearColor( public unsafe void ClearColor(
Texture dst, Texture dst,
uint componentMask, ReadOnlySpan<float> clearColor)
int dstWidth,
int dstHeight,
ComponentType type,
Rectangle<int> scissor)
{ {
Span<Viewport> viewports = stackalloc Viewport[1]; const int ClearColorBufferSize = 16;
viewports[0] = new Viewport( var buffer = _device.NewBuffer(ClearColorBufferSize, MTLResourceOptions.ResourceStorageModeManaged);
new Rectangle<float>(0, 0, dstWidth, dstHeight), var span = new Span<float>(buffer.Contents.ToPointer(), ClearColorBufferSize);
ViewportSwizzle.PositiveX, clearColor.CopyTo(span);
ViewportSwizzle.PositiveY,
ViewportSwizzle.PositiveZ,
ViewportSwizzle.PositiveW,
0f,
1f);
IProgram program; buffer.DidModifyRange(new NSRange
if (type == ComponentType.SignedInteger)
{ {
program = _programColorClearSI; location = 0,
} length = ClearColorBufferSize
else if (type == ComponentType.UnsignedInteger) });
{
program = _programColorClearUI;
}
else
{
program = _programColorClearF;
}
_pipeline.SetProgram(program); var handle = buffer.NativePtr;
// _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight); var range = new BufferRange(Unsafe.As<IntPtr, BufferHandle>(ref handle), 0, ClearColorBufferSize);
_pipeline.SetRenderTargetColorMasks([componentMask]);
_pipeline.SetViewports(viewports); _pipeline.SetUniformBuffers([new BufferAssignment(0, range)]);
_pipeline.SetScissors([scissor]);
_pipeline.SetProgram(_programColorClear);
_pipeline.SetRenderTargets([dst], null);
// _pipeline.SetRenderTargetColorMasks([componentMask]);
_pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
_pipeline.Draw(4, 1, 0, 0); _pipeline.Draw(4, 1, 0, 0);
_pipeline.Finish(); _pipeline.Finish();
@ -196,9 +188,7 @@ namespace Ryujinx.Graphics.Metal
public void Dispose() public void Dispose()
{ {
_programColorBlit.Dispose(); _programColorBlit.Dispose();
_programColorClearF.Dispose(); _programColorClear.Dispose();
_programColorClearSI.Dispose();
_programColorClearUI.Dispose();
_programDepthStencilClear.Dispose(); _programDepthStencilClear.Dispose();
_pipeline.Dispose(); _pipeline.Dispose();
} }

View file

@ -213,17 +213,19 @@ namespace Ryujinx.Graphics.Metal
public unsafe void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data) public unsafe void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data)
{ {
MTLBuffer mtlBuffer = new(Unsafe.As<BufferHandle, IntPtr>(ref buffer)); var blitEncoder = _pipeline.GetOrCreateBlitEncoder();
var span = new Span<byte>(mtlBuffer.Contents.ToPointer(), (int)mtlBuffer.Length);
data.CopyTo(span[offset..]); MTLBuffer src = _device.NewBuffer((ulong)data.Length, MTLResourceOptions.ResourceStorageModeManaged);
if (mtlBuffer.StorageMode == MTLStorageMode.Managed) var span = new Span<byte>(src.Contents.ToPointer(), data.Length);
data.CopyTo(span);
src.DidModifyRange(new NSRange
{ {
mtlBuffer.DidModifyRange(new NSRange location = 0,
{
location = (ulong)offset,
length = (ulong)data.Length length = (ulong)data.Length
}); });
}
MTLBuffer dst = new(Unsafe.As<BufferHandle, IntPtr>(ref buffer));
blitEncoder.CopyFromBuffer(src, 0, dst, (ulong)offset, (ulong)data.Length);
} }
public void UpdateCounters() public void UpdateCounters()

View file

@ -5,6 +5,7 @@ using SharpMetal.Foundation;
using SharpMetal.Metal; using SharpMetal.Metal;
using SharpMetal.QuartzCore; using SharpMetal.QuartzCore;
using System; using System;
using System.Drawing;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
@ -203,7 +204,13 @@ namespace Ryujinx.Graphics.Metal
public void ClearRenderTargetColor(int index, int layer, int layerCount, uint componentMask, ColorF color) public void ClearRenderTargetColor(int index, int layer, int layerCount, uint componentMask, ColorF color)
{ {
Logger.Warning?.Print(LogClass.Gpu, "Not Implemented!"); float[] colors = [color.Red, color.Green, color.Blue, color.Alpha];
Texture target = _encoderStateManager.RenderTargets[index];
_encoderStateManager.SwapStates();
_helperShader.ClearColor(target, colors);
} }
public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask) public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask)

View file

@ -16,9 +16,7 @@
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Shaders\Blit.metal" /> <EmbeddedResource Include="Shaders\Blit.metal" />
<EmbeddedResource Include="Shaders\ColorClearF.metal" /> <EmbeddedResource Include="Shaders\ColorClear.metal" />
<EmbeddedResource Include="Shaders\ColorClearSI.metal" />
<EmbeddedResource Include="Shaders\ColorClearUI.metal" />
<EmbeddedResource Include="Shaders\DepthStencilClear.metal" /> <EmbeddedResource Include="Shaders\DepthStencilClear.metal" />
</ItemGroup> </ItemGroup>

View file

@ -0,0 +1,28 @@
#include <metal_stdlib>
using namespace metal;
struct VertexOut {
float4 position [[position]];
};
vertex VertexOut vertexMain(ushort vid [[vertex_id]])
{
int low = vid & 1;
int high = vid >> 1;
VertexOut out;
out.position.x = (float(low) - 0.5f) * 2.0f;
out.position.y = (float(high) - 0.5f) * 2.0f;
out.position.z = 0.0f;
out.position.w = 1.0f;
return out;
}
fragment float4 fragmentMain(VertexOut in [[stage_in]],
constant float4& clear_color [[buffer(0)]])
{
return clear_color;
}

View file

@ -0,0 +1,37 @@
#include <metal_stdlib>
using namespace metal;
struct VertexOut {
float4 position [[position]];
};
struct FragmentOut {
float4 color [[color(0)]];
float depth [[depth(any)]];
};
vertex VertexOut vertexMain(ushort vid [[vertex_id]])
{
int low = vid & 1;
int high = vid >> 1;
VertexOut out;
out.position.x = (float(low) - 0.5f) * 2.0f;
out.position.y = (float(high) - 0.5f) * 2.0f;
out.position.z = 0.0f;
out.position.w = 1.0f;
return out;
}
fragment float4 fragmentMain(VertexOut in [[stage_in]],
constant float clear_color [[buffer(0)]])
{
Fragment out;
out.depth = clear_color;
return out;
}