Ryujinx/src/Ryujinx.Graphics.Metal/Program.cs

133 lines
4.3 KiB
C#
Raw Normal View History

2023-10-10 18:14:28 +00:00
using Ryujinx.Common.Logging;
2023-08-03 01:53:49 +00:00
using Ryujinx.Graphics.GAL;
2023-10-10 18:14:28 +00:00
using Ryujinx.Graphics.Shader;
using SharpMetal.Foundation;
using SharpMetal.Metal;
using System;
using System.Runtime.Versioning;
2023-08-03 01:53:49 +00:00
namespace Ryujinx.Graphics.Metal
{
2023-10-10 18:14:28 +00:00
[SupportedOSPlatform("macos")]
2023-08-03 18:50:49 +00:00
class Program : IProgram
2023-08-03 01:53:49 +00:00
{
2023-10-11 04:42:38 +00:00
private readonly ProgramLinkStatus _status;
2023-10-10 19:26:40 +00:00
public MTLFunction VertexFunction;
public MTLFunction FragmentFunction;
public MTLFunction ComputeFunction;
2023-10-10 18:14:28 +00:00
private HashTableSlim<PipelineUid, MTLRenderPipelineState> _graphicsPipelineCache;
private MTLComputePipelineState? _computePipelineCache;
private bool _firstBackgroundUse;
2023-10-10 18:14:28 +00:00
public Program(ShaderSource[] shaders, MTLDevice device)
{
for (int index = 0; index < shaders.Length; index++)
{
ShaderSource shader = shaders[index];
var libraryError = new NSError(IntPtr.Zero);
2023-10-10 18:14:28 +00:00
var shaderLibrary = device.NewLibrary(StringHelper.NSString(shader.Code), new MTLCompileOptions(IntPtr.Zero), ref libraryError);
if (libraryError != IntPtr.Zero)
{
Logger.Warning?.PrintMsg(LogClass.Gpu, shader.Code);
Logger.Warning?.Print(LogClass.Gpu, $"{shader.Stage} shader linking failed: \n{StringHelper.String(libraryError.LocalizedDescription)}");
2023-10-10 18:14:28 +00:00
_status = ProgramLinkStatus.Failure;
return;
2023-10-10 18:14:28 +00:00
}
switch (shaders[index].Stage)
{
case ShaderStage.Compute:
ComputeFunction = shaderLibrary.NewFunction(StringHelper.NSString("kernelMain"));
break;
case ShaderStage.Vertex:
VertexFunction = shaderLibrary.NewFunction(StringHelper.NSString("vertexMain"));
break;
case ShaderStage.Fragment:
FragmentFunction = shaderLibrary.NewFunction(StringHelper.NSString("fragmentMain"));
break;
default:
Logger.Warning?.Print(LogClass.Gpu, $"Cannot handle stage {shaders[index].Stage}!");
break;
2023-10-10 18:14:28 +00:00
}
}
_status = ProgramLinkStatus.Success;
2023-10-10 18:14:28 +00:00
}
2023-08-03 01:53:49 +00:00
public ProgramLinkStatus CheckProgramLink(bool blocking)
{
2023-10-10 18:14:28 +00:00
return _status;
2023-08-03 01:53:49 +00:00
}
public byte[] GetBinary()
{
2023-08-03 18:50:49 +00:00
return ""u8.ToArray();
}
public void AddGraphicsPipeline(ref PipelineUid key, MTLRenderPipelineState pipeline)
{
(_graphicsPipelineCache ??= new()).Add(ref key, pipeline);
}
public void AddComputePipeline(MTLComputePipelineState pipeline)
{
_computePipelineCache = pipeline;
}
public bool TryGetGraphicsPipeline(ref PipelineUid key, out MTLRenderPipelineState pipeline)
{
if (_graphicsPipelineCache == null)
{
pipeline = default;
return false;
}
if (!_graphicsPipelineCache.TryGetValue(ref key, out pipeline))
{
if (_firstBackgroundUse)
{
Logger.Warning?.Print(LogClass.Gpu, "Background pipeline compile missed on draw - incorrect pipeline state?");
_firstBackgroundUse = false;
}
return false;
}
_firstBackgroundUse = false;
return true;
}
public bool TryGetComputePipeline(out MTLComputePipelineState pipeline)
{
if (_computePipelineCache.HasValue)
{
pipeline = _computePipelineCache.Value;
return true;
}
pipeline = default;
return false;
}
2023-08-03 18:50:49 +00:00
public void Dispose()
{
if (_graphicsPipelineCache != null)
{
foreach (MTLRenderPipelineState pipeline in _graphicsPipelineCache.Values)
{
pipeline.Dispose();
}
}
_computePipelineCache?.Dispose();
2024-05-23 17:15:23 +00:00
VertexFunction.Dispose();
FragmentFunction.Dispose();
ComputeFunction.Dispose();
2023-08-03 01:53:49 +00:00
}
}
}