Shader cache support
This commit is contained in:
parent
eb2dae561f
commit
b44167d12a
3 changed files with 73 additions and 32 deletions
|
@ -38,7 +38,7 @@
|
||||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
||||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||||
<PackageVersion Include="SharpMetal" Version="1.0.0-preview14" />
|
<PackageVersion Include="SharpMetal" Version="1.0.0-preview18" />
|
||||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.21.0" />
|
<PackageVersion Include="Silk.NET.Vulkan" Version="2.21.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" />
|
||||||
|
|
|
@ -324,6 +324,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||||
|
|
||||||
bool loadHostCache = header.CodeGenVersion == CodeGenVersion;
|
bool loadHostCache = header.CodeGenVersion == CodeGenVersion;
|
||||||
|
|
||||||
|
if (context.Capabilities.Api == TargetApi.Metal)
|
||||||
|
{
|
||||||
|
loadHostCache = false;
|
||||||
|
}
|
||||||
|
|
||||||
int programIndex = 0;
|
int programIndex = 0;
|
||||||
|
|
||||||
DataEntry entry = new();
|
DataEntry entry = new();
|
||||||
|
@ -630,7 +635,10 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteHostCode(context, hostCode, program.Shaders, streams, timestamp);
|
if (context.Capabilities.Api != TargetApi.Metal)
|
||||||
|
{
|
||||||
|
WriteHostCode(context, hostCode, program.Shaders, streams, timestamp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -6,6 +6,7 @@ using SharpMetal.Metal;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Metal
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
@ -13,7 +14,11 @@ namespace Ryujinx.Graphics.Metal
|
||||||
[SupportedOSPlatform("macos")]
|
[SupportedOSPlatform("macos")]
|
||||||
class Program : IProgram
|
class Program : IProgram
|
||||||
{
|
{
|
||||||
private readonly ProgramLinkStatus _status;
|
private ProgramLinkStatus _status;
|
||||||
|
private ShaderSource[] _shaders;
|
||||||
|
private GCHandle[] _handles;
|
||||||
|
private int _successCount;
|
||||||
|
|
||||||
public MTLFunction VertexFunction;
|
public MTLFunction VertexFunction;
|
||||||
public MTLFunction FragmentFunction;
|
public MTLFunction FragmentFunction;
|
||||||
public MTLFunction ComputeFunction;
|
public MTLFunction ComputeFunction;
|
||||||
|
@ -33,44 +38,64 @@ namespace Ryujinx.Graphics.Metal
|
||||||
public Program(ShaderSource[] shaders, ResourceLayout resourceLayout, MTLDevice device, ComputeSize computeLocalSize = default)
|
public Program(ShaderSource[] shaders, ResourceLayout resourceLayout, MTLDevice device, ComputeSize computeLocalSize = default)
|
||||||
{
|
{
|
||||||
ComputeLocalSize = computeLocalSize;
|
ComputeLocalSize = computeLocalSize;
|
||||||
|
_shaders = shaders;
|
||||||
|
_handles = new GCHandle[_shaders.Length];
|
||||||
|
|
||||||
for (int index = 0; index < shaders.Length; index++)
|
_status = ProgramLinkStatus.Incomplete;
|
||||||
|
|
||||||
|
for (int i = 0; i < _shaders.Length; i++)
|
||||||
{
|
{
|
||||||
ShaderSource shader = shaders[index];
|
ShaderSource shader = _shaders[i];
|
||||||
|
|
||||||
var compileOptions = new MTLCompileOptions { PreserveInvariance = true };
|
var compileOptions = new MTLCompileOptions { PreserveInvariance = true };
|
||||||
|
var index = i;
|
||||||
|
|
||||||
var libraryError = new NSError(IntPtr.Zero);
|
_handles[i] = device.NewLibrary(StringHelper.NSString(shader.Code), compileOptions, (library, error) => CompilationResultHandler(library, error, index));
|
||||||
var shaderLibrary = device.NewLibrary(StringHelper.NSString(shader.Code), compileOptions, 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)}");
|
|
||||||
_status = ProgramLinkStatus.Failure;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearSegments = BuildClearSegments(resourceLayout.Sets);
|
ClearSegments = BuildClearSegments(resourceLayout.Sets);
|
||||||
(BindingSegments, ArgumentBufferSizes, FragArgumentBufferSizes) = BuildBindingSegments(resourceLayout.SetUsages);
|
(BindingSegments, ArgumentBufferSizes, FragArgumentBufferSizes) = BuildBindingSegments(resourceLayout.SetUsages);
|
||||||
|
}
|
||||||
|
|
||||||
_status = ProgramLinkStatus.Success;
|
public void CompilationResultHandler(MTLLibrary library, NSError error, int index)
|
||||||
|
{
|
||||||
|
var shader = _shaders[index];
|
||||||
|
|
||||||
|
if (_handles[index].IsAllocated)
|
||||||
|
{
|
||||||
|
_handles[index].Free();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Logger.Warning?.PrintMsg(LogClass.Gpu, shader.Code);
|
||||||
|
Logger.Warning?.Print(LogClass.Gpu, $"{shader.Stage} shader linking failed: \n{StringHelper.String(error.LocalizedDescription)}");
|
||||||
|
_status = ProgramLinkStatus.Failure;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (_shaders[index].Stage)
|
||||||
|
{
|
||||||
|
case ShaderStage.Compute:
|
||||||
|
ComputeFunction = library.NewFunction(StringHelper.NSString("kernelMain"));
|
||||||
|
break;
|
||||||
|
case ShaderStage.Vertex:
|
||||||
|
VertexFunction = library.NewFunction(StringHelper.NSString("vertexMain"));
|
||||||
|
break;
|
||||||
|
case ShaderStage.Fragment:
|
||||||
|
FragmentFunction = library.NewFunction(StringHelper.NSString("fragmentMain"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Logger.Warning?.Print(LogClass.Gpu, $"Cannot handle stage {_shaders[index].Stage}!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_successCount++;
|
||||||
|
|
||||||
|
if (_successCount >= _shaders.Length && _status != ProgramLinkStatus.Failure)
|
||||||
|
{
|
||||||
|
_status = ProgramLinkStatus.Success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ResourceBindingSegment[][] BuildClearSegments(ReadOnlyCollection<ResourceDescriptorCollection> sets)
|
private static ResourceBindingSegment[][] BuildClearSegments(ReadOnlyCollection<ResourceDescriptorCollection> sets)
|
||||||
|
@ -218,12 +243,20 @@ namespace Ryujinx.Graphics.Metal
|
||||||
|
|
||||||
public ProgramLinkStatus CheckProgramLink(bool blocking)
|
public ProgramLinkStatus CheckProgramLink(bool blocking)
|
||||||
{
|
{
|
||||||
|
if (blocking)
|
||||||
|
{
|
||||||
|
while (_status == ProgramLinkStatus.Incomplete)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
return _status;
|
||||||
|
}
|
||||||
|
|
||||||
return _status;
|
return _status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] GetBinary()
|
public byte[] GetBinary()
|
||||||
{
|
{
|
||||||
return ""u8.ToArray();
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddGraphicsPipeline(ref PipelineUid key, MTLRenderPipelineState pipeline)
|
public void AddGraphicsPipeline(ref PipelineUid key, MTLRenderPipelineState pipeline)
|
||||||
|
|
Loading…
Reference in a new issue