mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-07-21 13:27:10 +02:00
EXPERIMENTAL: Metal backend (#441)
This is not a continuation of the Metal backend; this is simply bringing the branch up to date and merging it as-is behind an experiment. --------- Co-authored-by: Isaac Marovitz <isaacryu@icloud.com> Co-authored-by: Samuliak <samuliak77@gmail.com> Co-authored-by: SamoZ256 <96914946+SamoZ256@users.noreply.github.com> Co-authored-by: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com> Co-authored-by: riperiperi <rhy3756547@hotmail.com> Co-authored-by: Gabriel A <gab.dark.100@gmail.com>
This commit is contained in:
parent
3094df54dd
commit
852823104f
131 changed files with 14992 additions and 140 deletions
|
@ -324,6 +324,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||
|
||||
bool loadHostCache = header.CodeGenVersion == CodeGenVersion;
|
||||
|
||||
if (context.Capabilities.Api == TargetApi.Metal)
|
||||
{
|
||||
loadHostCache = false;
|
||||
}
|
||||
|
||||
int programIndex = 0;
|
||||
|
||||
DataEntry entry = new();
|
||||
|
@ -392,7 +397,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||
context,
|
||||
shaders,
|
||||
specState.PipelineState,
|
||||
specState.TransformFeedbackDescriptors != null);
|
||||
specState.TransformFeedbackDescriptors != null,
|
||||
specState.ComputeState.GetLocalSize());
|
||||
|
||||
IProgram hostProgram;
|
||||
|
||||
|
@ -629,7 +635,10 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||
return;
|
||||
}
|
||||
|
||||
WriteHostCode(context, hostCode, program.Shaders, streams, timestamp);
|
||||
if (context.Capabilities.Api != TargetApi.Metal)
|
||||
{
|
||||
WriteHostCode(context, hostCode, program.Shaders, streams, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -490,7 +490,12 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||
{
|
||||
ShaderSource[] shaderSources = new ShaderSource[compilation.TranslatedStages.Length];
|
||||
|
||||
ShaderInfoBuilder shaderInfoBuilder = new(_context, compilation.SpecializationState.TransformFeedbackDescriptors != null);
|
||||
ref GpuChannelComputeState computeState = ref compilation.SpecializationState.ComputeState;
|
||||
|
||||
ShaderInfoBuilder shaderInfoBuilder = new(
|
||||
_context,
|
||||
compilation.SpecializationState.TransformFeedbackDescriptors != null,
|
||||
computeLocalSize: computeState.GetLocalSize());
|
||||
|
||||
for (int index = 0; index < compilation.TranslatedStages.Length; index++)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
private readonly GpuAccessorState _state;
|
||||
private readonly int _stageIndex;
|
||||
private readonly bool _compute;
|
||||
private readonly bool _isVulkan;
|
||||
private readonly bool _isOpenGL;
|
||||
private readonly bool _hasGeometryShader;
|
||||
private readonly bool _supportsQuads;
|
||||
|
||||
|
@ -38,7 +38,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
_channel = channel;
|
||||
_state = state;
|
||||
_stageIndex = stageIndex;
|
||||
_isVulkan = context.Capabilities.Api == TargetApi.Vulkan;
|
||||
_isOpenGL = context.Capabilities.Api == TargetApi.OpenGL;
|
||||
_hasGeometryShader = hasGeometryShader;
|
||||
_supportsQuads = context.Capabilities.SupportsQuads;
|
||||
|
||||
|
@ -116,10 +116,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
public GpuGraphicsState QueryGraphicsState()
|
||||
{
|
||||
return _state.GraphicsState.CreateShaderGraphicsState(
|
||||
!_isVulkan,
|
||||
_isOpenGL,
|
||||
_supportsQuads,
|
||||
_hasGeometryShader,
|
||||
_isVulkan || _state.GraphicsState.YNegateEnabled);
|
||||
!_isOpenGL || _state.GraphicsState.YNegateEnabled);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
{
|
||||
int binding;
|
||||
|
||||
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
||||
if (_context.Capabilities.Api != TargetApi.OpenGL)
|
||||
{
|
||||
binding = GetBindingFromIndex(index, _context.Capabilities.MaximumUniformBuffersPerStage, "Uniform buffer");
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
{
|
||||
int binding;
|
||||
|
||||
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
||||
if (_context.Capabilities.Api != TargetApi.OpenGL)
|
||||
{
|
||||
if (count == 1)
|
||||
{
|
||||
|
@ -103,7 +103,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
{
|
||||
int binding;
|
||||
|
||||
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
||||
if (_context.Capabilities.Api != TargetApi.OpenGL)
|
||||
{
|
||||
binding = GetBindingFromIndex(index, _context.Capabilities.MaximumStorageBuffersPerStage, "Storage buffer");
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
{
|
||||
int binding;
|
||||
|
||||
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
||||
if (_context.Capabilities.Api != TargetApi.OpenGL)
|
||||
{
|
||||
if (count == 1)
|
||||
{
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
using Ryujinx.Graphics.GAL;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Shader
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -61,5 +63,14 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
SharedMemorySize = sharedMemorySize;
|
||||
HasUnalignedStorageBuffer = hasUnalignedStorageBuffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local group size of the shader in a GAL compatible struct.
|
||||
/// </summary>
|
||||
/// <returns>Local group size</returns>
|
||||
public ComputeSize GetLocalSize()
|
||||
{
|
||||
return new ComputeSize(LocalSizeX, LocalSizeY, LocalSizeZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -224,7 +224,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
TranslatedShader translatedShader = TranslateShader(_dumper, channel, translatorContext, cachedGuestCode, asCompute: false);
|
||||
|
||||
ShaderSource[] shaderSourcesArray = new ShaderSource[] { CreateShaderSource(translatedShader.Program) };
|
||||
ShaderInfo info = ShaderInfoBuilder.BuildForCompute(_context, translatedShader.Program.Info);
|
||||
ShaderInfo info = ShaderInfoBuilder.BuildForCompute(
|
||||
_context,
|
||||
translatedShader.Program.Info,
|
||||
computeState.GetLocalSize());
|
||||
IProgram hostProgram = _context.Renderer.CreateProgram(shaderSourcesArray, info);
|
||||
|
||||
cpShader = new CachedShaderProgram(hostProgram, specState, translatedShader.Shader);
|
||||
|
@ -425,7 +428,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
|
||||
TranslatorContext lastInVertexPipeline = geometryToCompute ? translatorContexts[4] ?? currentStage : currentStage;
|
||||
|
||||
program = lastInVertexPipeline.GenerateVertexPassthroughForCompute();
|
||||
(program, ShaderProgramInfo vacInfo) = lastInVertexPipeline.GenerateVertexPassthroughForCompute();
|
||||
infoBuilder.AddStageInfoVac(vacInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -530,7 +534,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
private ShaderAsCompute CreateHostVertexAsComputeProgram(ShaderProgram program, TranslatorContext context, bool tfEnabled)
|
||||
{
|
||||
ShaderSource source = new(program.Code, program.BinaryCode, ShaderStage.Compute, program.Language);
|
||||
ShaderInfo info = ShaderInfoBuilder.BuildForVertexAsCompute(_context, program.Info, tfEnabled);
|
||||
ShaderInfo info = ShaderInfoBuilder.BuildForVertexAsCompute(_context, program.Info, context.GetVertexAsComputeInfo(), tfEnabled);
|
||||
|
||||
return new(_context.Renderer.CreateProgram(new[] { source }, info), program.Info, context.GetResourceReservations());
|
||||
}
|
||||
|
@ -822,16 +826,19 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
|
||||
/// <summary>
|
||||
/// Creates shader translation options with the requested graphics API and flags.
|
||||
/// The shader language is choosen based on the current configuration and graphics API.
|
||||
/// The shader language is chosen based on the current configuration and graphics API.
|
||||
/// </summary>
|
||||
/// <param name="api">Target graphics API</param>
|
||||
/// <param name="flags">Translation flags</param>
|
||||
/// <returns>Translation options</returns>
|
||||
private static TranslationOptions CreateTranslationOptions(TargetApi api, TranslationFlags flags)
|
||||
{
|
||||
TargetLanguage lang = GraphicsConfig.EnableSpirvCompilationOnVulkan && api == TargetApi.Vulkan
|
||||
? TargetLanguage.Spirv
|
||||
: TargetLanguage.Glsl;
|
||||
TargetLanguage lang = api switch
|
||||
{
|
||||
TargetApi.OpenGL => TargetLanguage.Glsl,
|
||||
TargetApi.Vulkan => GraphicsConfig.EnableSpirvCompilationOnVulkan ? TargetLanguage.Spirv : TargetLanguage.Glsl,
|
||||
TargetApi.Metal => TargetLanguage.Msl,
|
||||
};
|
||||
|
||||
return new TranslationOptions(lang, api, flags);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
ResourceStages.Geometry;
|
||||
|
||||
private readonly GpuContext _context;
|
||||
private readonly ComputeSize _computeLocalSize;
|
||||
|
||||
private int _fragmentOutputMap;
|
||||
|
||||
|
@ -39,9 +40,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// <param name="context">GPU context that owns the shaders that will be added to the builder</param>
|
||||
/// <param name="tfEnabled">Indicates if the graphics shader is used with transform feedback enabled</param>
|
||||
/// <param name="vertexAsCompute">Indicates that the vertex shader will be emulated on a compute shader</param>
|
||||
public ShaderInfoBuilder(GpuContext context, bool tfEnabled, bool vertexAsCompute = false)
|
||||
/// <param name="computeLocalSize">Indicates the local thread size for a compute shader</param>
|
||||
public ShaderInfoBuilder(GpuContext context, bool tfEnabled, bool vertexAsCompute = false, ComputeSize computeLocalSize = default)
|
||||
{
|
||||
_context = context;
|
||||
_computeLocalSize = computeLocalSize;
|
||||
|
||||
_fragmentOutputMap = -1;
|
||||
|
||||
|
@ -95,7 +98,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
private void PopulateDescriptorAndUsages(ResourceStages stages, ResourceType type, int setIndex, int start, int count, bool write = false)
|
||||
{
|
||||
AddDescriptor(stages, type, setIndex, start, count);
|
||||
AddUsage(stages, type, setIndex, start, count, write);
|
||||
// AddUsage(stages, type, setIndex, start, count, write);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -159,6 +162,25 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
AddUsage(info.Images, stages, isImage: true);
|
||||
}
|
||||
|
||||
public void AddStageInfoVac(ShaderProgramInfo info)
|
||||
{
|
||||
ResourceStages stages = info.Stage switch
|
||||
{
|
||||
ShaderStage.Compute => ResourceStages.Compute,
|
||||
ShaderStage.Vertex => ResourceStages.Vertex,
|
||||
ShaderStage.TessellationControl => ResourceStages.TessellationControl,
|
||||
ShaderStage.TessellationEvaluation => ResourceStages.TessellationEvaluation,
|
||||
ShaderStage.Geometry => ResourceStages.Geometry,
|
||||
ShaderStage.Fragment => ResourceStages.Fragment,
|
||||
_ => ResourceStages.None,
|
||||
};
|
||||
|
||||
AddUsage(info.CBuffers, stages, isStorage: false);
|
||||
AddUsage(info.SBuffers, stages, isStorage: true);
|
||||
AddUsage(info.Textures, stages, isImage: false);
|
||||
AddUsage(info.Images, stages, isImage: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a resource descriptor to the list of descriptors.
|
||||
/// </summary>
|
||||
|
@ -361,14 +383,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
|
||||
ResourceLayout resourceLayout = new(descriptors.AsReadOnly(), usages.AsReadOnly());
|
||||
|
||||
if (pipeline.HasValue)
|
||||
{
|
||||
return new ShaderInfo(_fragmentOutputMap, resourceLayout, pipeline.Value, fromCache);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ShaderInfo(_fragmentOutputMap, resourceLayout, fromCache);
|
||||
}
|
||||
return new ShaderInfo(_fragmentOutputMap, resourceLayout, _computeLocalSize, pipeline, fromCache);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -378,14 +393,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// <param name="programs">Shaders from the disk cache</param>
|
||||
/// <param name="pipeline">Optional pipeline for background compilation</param>
|
||||
/// <param name="tfEnabled">Indicates if the graphics shader is used with transform feedback enabled</param>
|
||||
/// <param name="computeLocalSize">Compute local thread size</param>
|
||||
/// <returns>Shader information</returns>
|
||||
public static ShaderInfo BuildForCache(
|
||||
GpuContext context,
|
||||
IEnumerable<CachedShaderStage> programs,
|
||||
ProgramPipelineState? pipeline,
|
||||
bool tfEnabled)
|
||||
bool tfEnabled,
|
||||
ComputeSize computeLocalSize)
|
||||
{
|
||||
ShaderInfoBuilder builder = new(context, tfEnabled);
|
||||
ShaderInfoBuilder builder = new(context, tfEnabled, computeLocalSize: computeLocalSize);
|
||||
|
||||
foreach (CachedShaderStage program in programs)
|
||||
{
|
||||
|
@ -403,11 +420,12 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// </summary>
|
||||
/// <param name="context">GPU context that owns the shader</param>
|
||||
/// <param name="info">Compute shader information</param>
|
||||
/// <param name="computeLocalSize">Compute local thread size</param>
|
||||
/// <param name="fromCache">True if the compute shader comes from a disk cache, false otherwise</param>
|
||||
/// <returns>Shader information</returns>
|
||||
public static ShaderInfo BuildForCompute(GpuContext context, ShaderProgramInfo info, bool fromCache = false)
|
||||
public static ShaderInfo BuildForCompute(GpuContext context, ShaderProgramInfo info, ComputeSize computeLocalSize, bool fromCache = false)
|
||||
{
|
||||
ShaderInfoBuilder builder = new(context, tfEnabled: false, vertexAsCompute: false);
|
||||
ShaderInfoBuilder builder = new(context, tfEnabled: false, vertexAsCompute: false, computeLocalSize: computeLocalSize);
|
||||
|
||||
builder.AddStageInfo(info);
|
||||
|
||||
|
@ -422,10 +440,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// <param name="tfEnabled">Indicates if the graphics shader is used with transform feedback enabled</param>
|
||||
/// <param name="fromCache">True if the compute shader comes from a disk cache, false otherwise</param>
|
||||
/// <returns>Shader information</returns>
|
||||
public static ShaderInfo BuildForVertexAsCompute(GpuContext context, ShaderProgramInfo info, bool tfEnabled, bool fromCache = false)
|
||||
public static ShaderInfo BuildForVertexAsCompute(GpuContext context, ShaderProgramInfo info, ShaderProgramInfo info2, bool tfEnabled, bool fromCache = false)
|
||||
{
|
||||
ShaderInfoBuilder builder = new(context, tfEnabled, vertexAsCompute: true);
|
||||
ShaderInfoBuilder builder = new(context, tfEnabled, vertexAsCompute: true, computeLocalSize: ComputeSize.VtgAsCompute);
|
||||
|
||||
builder.AddStageInfoVac(info2);
|
||||
builder.AddStageInfo(info, vertexAsCompute: true);
|
||||
|
||||
return builder.Build(null, fromCache);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue