HelperShaders class

This commit is contained in:
Isaac Marovitz 2023-08-03 08:48:41 -04:00 committed by Isaac Marovitz
parent 00fce5a51d
commit 93c71110e1
5 changed files with 72 additions and 45 deletions

View file

@ -0,0 +1,59 @@
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using SharpMetal.Foundation;
using SharpMetal.Metal;
using System;
using System.Runtime.Versioning;
namespace Ryujinx.Graphics.Metal
{
[SupportedOSPlatform("macos")]
public class HelperShaders
{
private const string ShadersSourcePath = "/Ryujinx.Graphics.Metal/HelperShadersSource.metal";
public HelperShader BlitShader;
public HelperShaders(MTLDevice device)
{
var error = new NSError(IntPtr.Zero);
var shaderSource = EmbeddedResources.ReadAllText(ShadersSourcePath);
var library = device.NewLibrary(StringHelper.NSString(shaderSource), new(IntPtr.Zero), ref error);
if (error != IntPtr.Zero)
{
Logger.Error?.PrintMsg(LogClass.Gpu, $"Failed to create Library: {StringHelper.String(error.LocalizedDescription)}");
}
BlitShader = new HelperShader(device, library, "vertexBlit", "fragmentBlit");
}
}
[SupportedOSPlatform("macos")]
public struct HelperShader
{
private MTLRenderPipelineState _pipelineState;
public static implicit operator MTLRenderPipelineState(HelperShader shader) => shader._pipelineState;
public HelperShader(MTLDevice device, MTLLibrary library, string vertex, string fragment)
{
var renderPipelineDescriptor = new MTLRenderPipelineDescriptor();
renderPipelineDescriptor.VertexFunction = library.NewFunction(StringHelper.NSString(vertex));;
renderPipelineDescriptor.FragmentFunction = library.NewFunction(StringHelper.NSString(fragment));
renderPipelineDescriptor.ColorAttachments.Object(0).SetBlendingEnabled(true);
renderPipelineDescriptor.ColorAttachments.Object(0).PixelFormat = MTLPixelFormat.BGRA8Unorm;
renderPipelineDescriptor.ColorAttachments.Object(0).SourceAlphaBlendFactor = MTLBlendFactor.SourceAlpha;
renderPipelineDescriptor.ColorAttachments.Object(0).DestinationAlphaBlendFactor = MTLBlendFactor.OneMinusSourceAlpha;
renderPipelineDescriptor.ColorAttachments.Object(0).SourceRGBBlendFactor = MTLBlendFactor.SourceAlpha;
renderPipelineDescriptor.ColorAttachments.Object(0).DestinationRGBBlendFactor = MTLBlendFactor.OneMinusSourceAlpha;
var error = new NSError(IntPtr.Zero);
_pipelineState = device.NewRenderPipelineState(renderPipelineDescriptor, ref error);
if (error != IntPtr.Zero)
{
Logger.Error?.PrintMsg(LogClass.Gpu, $"Failed to create Render Pipeline State: {StringHelper.String(error.LocalizedDescription)}");
}
}
}
}

View file

@ -16,7 +16,7 @@ struct CopyVertexOut {
float2 uv; float2 uv;
}; };
vertex CopyVertexOut vertexMain(unsigned short vid [[vertex_id]]) { vertex CopyVertexOut vertexBlit(unsigned short vid [[vertex_id]]) {
float2 position = quadVertices[vid]; float2 position = quadVertices[vid];
CopyVertexOut out; CopyVertexOut out;
@ -28,8 +28,8 @@ vertex CopyVertexOut vertexMain(unsigned short vid [[vertex_id]]) {
return out; return out;
} }
fragment float4 fragmentMain(CopyVertexOut in [[stage_in]], fragment float4 fragmentBlit(CopyVertexOut in [[stage_in]],
texture2d<float> tex) { texture2d<float> tex) {
constexpr sampler sam(min_filter::nearest, mag_filter::nearest, mip_filter::none); constexpr sampler sam(min_filter::nearest, mag_filter::nearest, mip_filter::none);
return tex.sample(sam, in.uv).xyzw; return tex.sample(sam, in.uv).xyzw;

View file

@ -46,12 +46,12 @@ namespace Ryujinx.Graphics.Metal
MTLCaptureManager.SharedCaptureManager().StartCapture(captureDescriptor, ref captureError); MTLCaptureManager.SharedCaptureManager().StartCapture(captureDescriptor, ref captureError);
if (captureError != IntPtr.Zero) if (captureError != IntPtr.Zero)
{ {
Console.Write($"Failed to start capture! {StringHelper.String(captureError.LocalizedDescription)}"); Console.WriteLine($"Failed to start capture! {StringHelper.String(captureError.LocalizedDescription)}");
} }
_window = new Window(this, layer); _window = new Window(this, layer);
_pipeline = new Pipeline(_device, _queue, layer); _pipeline = new Pipeline(_device, _queue);
} }
public void BackgroundContextAction(Action action, bool alwaysBackground = false) public void BackgroundContextAction(Action action, bool alwaysBackground = false)

View file

@ -1,4 +1,3 @@
using Ryujinx.Common;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
@ -14,10 +13,9 @@ namespace Ryujinx.Graphics.Metal
[SupportedOSPlatform("macos")] [SupportedOSPlatform("macos")]
public class Pipeline : IPipeline, IDisposable public class Pipeline : IPipeline, IDisposable
{ {
private const string ShaderSourcePath = "Ryujinx.Graphics.Metal/Shaders";
private readonly MTLDevice _device; private readonly MTLDevice _device;
private readonly MTLCommandQueue _mtlCommandQueue; private readonly MTLCommandQueue _mtlCommandQueue;
private readonly HelperShaders _helperShaders;
private MTLCommandBuffer _commandBuffer; private MTLCommandBuffer _commandBuffer;
private MTLCommandEncoder _currentEncoder; private MTLCommandEncoder _currentEncoder;
@ -32,43 +30,13 @@ namespace Ryujinx.Graphics.Metal
private MTLClearColor _clearColor; private MTLClearColor _clearColor;
private int frameCount = 0; private int frameCount = 0;
public Pipeline(MTLDevice device, MTLCommandQueue commandQueue, CAMetalLayer metalLayer) public Pipeline(MTLDevice device, MTLCommandQueue commandQueue)
{ {
_device = device; _device = device;
_mtlCommandQueue = commandQueue; _mtlCommandQueue = commandQueue;
_helperShaders = new HelperShaders(_device);
var error = new NSError(IntPtr.Zero); _renderEncoderState = new RenderEncoderState(_helperShaders.BlitShader, _device);
var shaderSource = EmbeddedResources.ReadAllText(string.Join('/', ShaderSourcePath, "ColorBlitShaderSource.metal"));
var library = _device.NewLibrary(StringHelper.NSString(shaderSource), new(IntPtr.Zero), ref error);
if (error != IntPtr.Zero)
{
Logger.Error?.PrintMsg(LogClass.Gpu, $"Failed to create Library: {StringHelper.String(error.LocalizedDescription)}");
}
var vertexFunction = library.NewFunction(StringHelper.NSString("vertexMain"));
var fragmentFunction = library.NewFunction(StringHelper.NSString("fragmentMain"));
// TODO: Recreate descriptor and encoder state as needed
var renderPipelineDescriptor = new MTLRenderPipelineDescriptor();
renderPipelineDescriptor.VertexFunction = vertexFunction;
renderPipelineDescriptor.FragmentFunction = fragmentFunction;
// TODO: This should not be hardcoded, but a bug in SharpMetal prevents me from doing this correctly
renderPipelineDescriptor.ColorAttachments.Object(0).SetBlendingEnabled(true);
renderPipelineDescriptor.ColorAttachments.Object(0).PixelFormat = MTLPixelFormat.BGRA8Unorm;
renderPipelineDescriptor.ColorAttachments.Object(0).SourceAlphaBlendFactor = MTLBlendFactor.SourceAlpha;
renderPipelineDescriptor.ColorAttachments.Object(0).DestinationAlphaBlendFactor = MTLBlendFactor.OneMinusSourceAlpha;
renderPipelineDescriptor.ColorAttachments.Object(0).SourceRGBBlendFactor = MTLBlendFactor.SourceAlpha;
renderPipelineDescriptor.ColorAttachments.Object(0).DestinationRGBBlendFactor = MTLBlendFactor.OneMinusSourceAlpha;
var renderPipelineState = _device.NewRenderPipelineState(renderPipelineDescriptor, ref error);
if (error != IntPtr.Zero)
{
Logger.Error?.PrintMsg(LogClass.Gpu, $"Failed to create Render Pipeline State: {StringHelper.String(error.LocalizedDescription)}");
}
_renderEncoderState = new RenderEncoderState(renderPipelineState, _device);
//
_commandBuffer = _mtlCommandQueue.CommandBuffer(); _commandBuffer = _mtlCommandQueue.CommandBuffer();
} }

View file

@ -10,12 +10,12 @@
<ProjectReference Include="..\Ryujinx.Graphics.GAL\Ryujinx.Graphics.GAL.csproj" /> <ProjectReference Include="..\Ryujinx.Graphics.GAL\Ryujinx.Graphics.GAL.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Shaders\ColorBlitShaderSource.metal" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="SharpMetal" /> <PackageReference Include="SharpMetal" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="HelperShadersSource.metal" />
</ItemGroup>
</Project> </Project>