HelperShaders class
This commit is contained in:
parent
00fce5a51d
commit
93c71110e1
5 changed files with 72 additions and 45 deletions
59
src/Ryujinx.Graphics.Metal/HelperShaders.cs
Normal file
59
src/Ryujinx.Graphics.Metal/HelperShaders.cs
Normal 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)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
Loading…
Reference in a new issue