mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-02-21 16:43:35 +00:00
Remove old CompileShader methods from the Vulkan backend
This commit is contained in:
parent
b6764620be
commit
38ecf0f117
5 changed files with 86 additions and 134 deletions
|
@ -1,6 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
public interface IShader : IDisposable { }
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Shader;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
using VkFormat = Silk.NET.Vulkan.Format;
|
||||
|
@ -127,12 +128,17 @@ void main()
|
|||
new[] { Constants.MaxTexturesPerStage * 2 },
|
||||
Array.Empty<int>());
|
||||
|
||||
var colorBlitVertexShader = gd.CompileShader(ShaderStage.Vertex, vertexBindings, ColorBlitVertexShaderSource);
|
||||
var colorBlitFragmentShader = gd.CompileShader(ShaderStage.Fragment, fragmentBindings, ColorBlitFragmentShaderSource);
|
||||
var colorBlitClearAlphaFragmentShader = gd.CompileShader(ShaderStage.Fragment, fragmentBindings, ColorBlitClearAlphaFragmentShaderSource);
|
||||
_programColorBlit = gd.CreateProgram(new[]
|
||||
{
|
||||
new ShaderSource(ColorBlitVertexShaderSource, vertexBindings, ShaderStage.Vertex, TargetLanguage.Glsl),
|
||||
new ShaderSource(ColorBlitFragmentShaderSource, fragmentBindings, ShaderStage.Fragment, TargetLanguage.Glsl),
|
||||
}, new ShaderInfo(-1));
|
||||
|
||||
_programColorBlit = gd.CreateProgram(new[] { colorBlitVertexShader, colorBlitFragmentShader }, new ShaderInfo(-1));
|
||||
_programColorBlitClearAlpha = gd.CreateProgram(new[] { colorBlitVertexShader, colorBlitClearAlphaFragmentShader }, new ShaderInfo(-1));
|
||||
_programColorBlitClearAlpha = gd.CreateProgram(new[]
|
||||
{
|
||||
new ShaderSource(ColorBlitVertexShaderSource, vertexBindings, ShaderStage.Vertex, TargetLanguage.Glsl),
|
||||
new ShaderSource(ColorBlitClearAlphaFragmentShaderSource, fragmentBindings, ShaderStage.Fragment, TargetLanguage.Glsl),
|
||||
}, new ShaderInfo(-1));
|
||||
|
||||
var fragmentBindings2 = new ShaderBindings(
|
||||
Array.Empty<int>(),
|
||||
|
@ -140,10 +146,11 @@ void main()
|
|||
Array.Empty<int>(),
|
||||
Array.Empty<int>());
|
||||
|
||||
var colorClearVertexShader = gd.CompileShader(ShaderStage.Vertex, vertexBindings, ColorClearVertexShaderSource);
|
||||
var colorClearFragmentShader = gd.CompileShader(ShaderStage.Fragment, fragmentBindings2, ColorClearFragmentShaderSource);
|
||||
|
||||
_programColorClear = gd.CreateProgram(new[] { colorClearVertexShader, colorClearFragmentShader }, new ShaderInfo(-1));
|
||||
_programColorClear = gd.CreateProgram(new[]
|
||||
{
|
||||
new ShaderSource(ColorClearVertexShaderSource, vertexBindings, ShaderStage.Vertex, TargetLanguage.Glsl),
|
||||
new ShaderSource(ColorClearFragmentShaderSource, fragmentBindings2, ShaderStage.Fragment, TargetLanguage.Glsl),
|
||||
}, new ShaderInfo(-1));
|
||||
}
|
||||
|
||||
public void Blit(
|
||||
|
|
|
@ -10,7 +10,7 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
class Shader : IShader
|
||||
class Shader
|
||||
{
|
||||
// The shaderc.net dependency's Options constructor and dispose are not thread safe.
|
||||
// Take this lock when using them.
|
||||
|
@ -31,86 +31,33 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
public readonly Task CompileTask;
|
||||
|
||||
public unsafe Shader(Vk api, Device device, ShaderStage stage, ShaderBindings bindings, string glsl)
|
||||
public unsafe Shader(Vk api, Device device, ShaderSource shaderSource)
|
||||
{
|
||||
_api = api;
|
||||
_device = device;
|
||||
_stage = stage.Convert();
|
||||
_entryPointName = Marshal.StringToHGlobalAnsi("main");
|
||||
|
||||
Bindings = bindings;
|
||||
|
||||
CompileTask = Task.Run(() =>
|
||||
{
|
||||
glsl = glsl.Replace("gl_VertexID", "(gl_VertexIndex - gl_BaseVertex)");
|
||||
glsl = glsl.Replace("gl_InstanceID", "(gl_InstanceIndex - gl_BaseInstance)");
|
||||
|
||||
// System.Console.WriteLine(glsl);
|
||||
|
||||
Options options;
|
||||
|
||||
lock (_shaderOptionsLock)
|
||||
{
|
||||
options = new Options(false)
|
||||
{
|
||||
SourceLanguage = SourceLanguage.Glsl,
|
||||
TargetSpirVVersion = new SpirVVersion(1, 5)
|
||||
};
|
||||
}
|
||||
|
||||
options.SetTargetEnvironment(TargetEnvironment.Vulkan, EnvironmentVersion.Vulkan_1_2);
|
||||
Compiler compiler = new Compiler(options);
|
||||
var scr = compiler.Compile(glsl, "Ryu", GetShaderCShaderStage(stage));
|
||||
|
||||
lock (_shaderOptionsLock)
|
||||
{
|
||||
options.Dispose();
|
||||
}
|
||||
|
||||
if (scr.Status != Status.Success)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Gpu, $"Shader compilation error: {scr.Status} {scr.ErrorMessage}");
|
||||
|
||||
CompileStatus = ProgramLinkStatus.Failure;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var spirvBytes = new Span<byte>((void*)scr.CodePointer, (int)scr.CodeLength);
|
||||
|
||||
uint[] code = new uint[(scr.CodeLength + 3) / 4];
|
||||
|
||||
spirvBytes.CopyTo(MemoryMarshal.Cast<uint, byte>(new Span<uint>(code)).Slice(0, (int)scr.CodeLength));
|
||||
|
||||
fixed (uint* pCode = code)
|
||||
{
|
||||
var shaderModuleCreateInfo = new ShaderModuleCreateInfo()
|
||||
{
|
||||
SType = StructureType.ShaderModuleCreateInfo,
|
||||
CodeSize = scr.CodeLength,
|
||||
PCode = pCode
|
||||
};
|
||||
|
||||
api.CreateShaderModule(device, shaderModuleCreateInfo, null, out _module).ThrowOnError();
|
||||
}
|
||||
|
||||
CompileStatus = ProgramLinkStatus.Success;
|
||||
});
|
||||
}
|
||||
|
||||
public unsafe Shader(Vk api, Device device, ShaderStage stage, ShaderBindings bindings, byte[] spirv)
|
||||
{
|
||||
_api = api;
|
||||
_device = device;
|
||||
Bindings = bindings;
|
||||
Bindings = shaderSource.Bindings;
|
||||
|
||||
CompileStatus = ProgramLinkStatus.Incomplete;
|
||||
|
||||
_stage = stage.Convert();
|
||||
_stage = shaderSource.Stage.Convert();
|
||||
_entryPointName = Marshal.StringToHGlobalAnsi("main");
|
||||
|
||||
CompileTask = Task.Run(() =>
|
||||
{
|
||||
byte[] spirv = shaderSource.BinaryCode;
|
||||
|
||||
if (spirv == null)
|
||||
{
|
||||
spirv = GlslToSpirv(shaderSource.Code, shaderSource.Stage);
|
||||
|
||||
if (spirv == null)
|
||||
{
|
||||
CompileStatus = ProgramLinkStatus.Failure;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fixed (byte* pCode = spirv)
|
||||
{
|
||||
var shaderModuleCreateInfo = new ShaderModuleCreateInfo()
|
||||
|
@ -127,16 +74,46 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
});
|
||||
}
|
||||
|
||||
private static uint[] LoadShaderData(string filePath, out int codeSize)
|
||||
private unsafe static byte[] GlslToSpirv(string glsl, ShaderStage stage)
|
||||
{
|
||||
var fileBytes = File.ReadAllBytes(filePath);
|
||||
var shaderData = new uint[(int)Math.Ceiling(fileBytes.Length / 4f)];
|
||||
// TODO: We should generate the correct code on the shader translator instead of doing this compensation.
|
||||
glsl = glsl.Replace("gl_VertexID", "(gl_VertexIndex - gl_BaseVertex)");
|
||||
glsl = glsl.Replace("gl_InstanceID", "(gl_InstanceIndex - gl_BaseInstance)");
|
||||
|
||||
System.Buffer.BlockCopy(fileBytes, 0, shaderData, 0, fileBytes.Length);
|
||||
Options options;
|
||||
|
||||
codeSize = fileBytes.Length;
|
||||
lock (_shaderOptionsLock)
|
||||
{
|
||||
options = new Options(false)
|
||||
{
|
||||
SourceLanguage = SourceLanguage.Glsl,
|
||||
TargetSpirVVersion = new SpirVVersion(1, 5)
|
||||
};
|
||||
}
|
||||
|
||||
return shaderData;
|
||||
options.SetTargetEnvironment(TargetEnvironment.Vulkan, EnvironmentVersion.Vulkan_1_2);
|
||||
Compiler compiler = new Compiler(options);
|
||||
var scr = compiler.Compile(glsl, "Ryu", GetShaderCShaderStage(stage));
|
||||
|
||||
lock (_shaderOptionsLock)
|
||||
{
|
||||
options.Dispose();
|
||||
}
|
||||
|
||||
if (scr.Status != Status.Success)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Gpu, $"Shader compilation error: {scr.Status} {scr.ErrorMessage}");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var spirvBytes = new Span<byte>((void*)scr.CodePointer, (int)scr.CodeLength);
|
||||
|
||||
byte[] code = new byte[(scr.CodeLength + 3) & ~3];
|
||||
|
||||
spirvBytes.CopyTo(code.AsSpan().Slice(0, (int)scr.CodeLength));
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
private static ShaderKind GetShaderCShaderStage(ShaderStage stage)
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
class ShaderCollection : IProgram
|
||||
{
|
||||
private readonly PipelineShaderStageCreateInfo[] _infos;
|
||||
private readonly IShader[] _shaders;
|
||||
private readonly Shader[] _shaders;
|
||||
|
||||
private readonly PipelineLayoutCacheEntry _plce;
|
||||
|
||||
|
@ -49,11 +49,10 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
private Task _compileTask;
|
||||
private bool _firstBackgroundUse;
|
||||
|
||||
public ShaderCollection(VulkanGraphicsDevice gd, Device device, IShader[] shaders)
|
||||
public ShaderCollection(VulkanGraphicsDevice gd, Device device, ShaderSource[] shaders)
|
||||
{
|
||||
_gd = gd;
|
||||
_device = device;
|
||||
_shaders = shaders;
|
||||
|
||||
gd.Shaders.Add(this);
|
||||
|
||||
|
@ -67,7 +66,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
for (int i = 0; i < shaders.Length; i++)
|
||||
{
|
||||
var shader = (Shader)shaders[i];
|
||||
var shader = new Shader(gd.Api, device, shaders[i]);
|
||||
|
||||
stages |= 1u << shader.StageFlags switch
|
||||
{
|
||||
|
@ -86,6 +85,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
internalShaders[i] = shader;
|
||||
}
|
||||
|
||||
_shaders = internalShaders;
|
||||
|
||||
_plce = gd.PipelineLayoutCache.GetOrCreate(gd, device, stages);
|
||||
|
||||
Stages = stages;
|
||||
|
@ -120,8 +121,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
public ShaderCollection(
|
||||
VulkanGraphicsDevice gd,
|
||||
Device device,
|
||||
IShader[] shaders,
|
||||
ProgramPipelineState state) : this(gd, device, shaders)
|
||||
ShaderSource[] sources,
|
||||
ProgramPipelineState state) : this(gd, device, sources)
|
||||
{
|
||||
_state = state;
|
||||
|
||||
|
@ -131,9 +132,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
private async Task BackgroundCompilation()
|
||||
{
|
||||
await Task.WhenAll(_shaders.Select(shader => ((Shader)shader).CompileTask));
|
||||
await Task.WhenAll(_shaders.Select(shader => shader.CompileTask));
|
||||
|
||||
if (_shaders.Any(shader => ((Shader)shader).CompileStatus == ProgramLinkStatus.Failure))
|
||||
if (_shaders.Any(shader => shader.CompileStatus == ProgramLinkStatus.Failure))
|
||||
{
|
||||
LinkStatus = ProgramLinkStatus.Failure;
|
||||
|
||||
|
@ -169,7 +170,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
for (int i = 0; i < _shaders.Length; i++)
|
||||
{
|
||||
var shader = (Shader)_shaders[i];
|
||||
var shader = _shaders[i];
|
||||
|
||||
if (shader.CompileStatus != ProgramLinkStatus.Success)
|
||||
{
|
||||
|
@ -211,7 +212,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
PipelineState pipeline = new PipelineState();
|
||||
pipeline.Initialize();
|
||||
|
||||
pipeline.Stages[0] = ((Shader)_shaders[0]).GetInfo();
|
||||
pipeline.Stages[0] = _shaders[0].GetInfo();
|
||||
pipeline.StagesCount = 1;
|
||||
|
||||
pipeline.CreateComputePipeline(_gd, _device, this, (_gd.Pipeline as PipelineBase).PipelineCache);
|
||||
|
@ -236,7 +237,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
for (int i = 0; i < _shaders.Length; i++)
|
||||
{
|
||||
stages[i] = ((Shader)_shaders[i]).GetInfo();
|
||||
stages[i] = _shaders[i].GetInfo();
|
||||
}
|
||||
|
||||
pipeline.StagesCount = (uint)_shaders.Length;
|
||||
|
|
|
@ -298,52 +298,25 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
_window = new ImageWindow(this, _physicalDevice, _device);
|
||||
}
|
||||
|
||||
public IShader CompileShader(ShaderStage stage, ShaderBindings bindings, string code)
|
||||
{
|
||||
return new Shader(Api, _device, stage, bindings, code);
|
||||
}
|
||||
|
||||
public IShader CompileShader(ShaderStage stage, ShaderBindings bindings, byte[] code)
|
||||
{
|
||||
return new Shader(Api, _device, stage, bindings, code);
|
||||
}
|
||||
|
||||
public BufferHandle CreateBuffer(int size)
|
||||
{
|
||||
return BufferManager.CreateWithHandle(this, size, false);
|
||||
}
|
||||
|
||||
public IProgram CreateProgram(IShader[] shaders, ShaderInfo info)
|
||||
public IProgram CreateProgram(ShaderSource[] sources, ShaderInfo info)
|
||||
{
|
||||
bool isCompute = shaders.Length == 1 && ((Shader)shaders[0]).StageFlags == ShaderStageFlags.ShaderStageComputeBit;
|
||||
bool isCompute = sources.Length == 1 && sources[0].Stage == ShaderStage.Compute;
|
||||
|
||||
if (info.BackgroundCompile && (info.State.HasValue || isCompute) && VulkanConfiguration.UseDynamicState)
|
||||
{
|
||||
return new ShaderCollection(this, _device, shaders, info.State.Value);
|
||||
return new ShaderCollection(this, _device, sources, info.State.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ShaderCollection(this, _device, shaders);
|
||||
return new ShaderCollection(this, _device, sources);
|
||||
}
|
||||
}
|
||||
|
||||
public IProgram CreateProgram(ShaderSource[] sources, ShaderInfo info)
|
||||
{
|
||||
IShader[] shaders = new IShader[sources.Length];
|
||||
|
||||
for (int index = 0; index < sources.Length; index++)
|
||||
{
|
||||
var source = sources[index];
|
||||
var shader = source.BinaryCode != null
|
||||
? CompileShader(source.Stage, source.Bindings, source.BinaryCode)
|
||||
: CompileShader(source.Stage, source.Bindings, source.Code);
|
||||
|
||||
shaders[index] = shader;
|
||||
}
|
||||
|
||||
return CreateProgram(shaders, info);
|
||||
}
|
||||
|
||||
public ISampler CreateSampler(GAL.SamplerCreateInfo info)
|
||||
{
|
||||
return new SamplerHolder(this, _device, info);
|
||||
|
|
Loading…
Reference in a new issue