Shitty Clears + Inline Buffer Improvements?
This commit is contained in:
parent
087bf71a13
commit
8feee9c005
11 changed files with 124 additions and 61 deletions
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
28
src/Ryujinx.Graphics.Metal/Shaders/ColorClear.metal
Normal file
28
src/Ryujinx.Graphics.Metal/Shaders/ColorClear.metal
Normal 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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in a new issue