mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2024-12-22 22:36:25 +00:00
801b71a128
* dotnet format style --severity info Some changes were manually reverted. * dotnet format analyzers --serverity info Some changes have been minimally adapted. * Restore a few unused methods and variables * Silence dotnet format IDE0060 warnings * Silence dotnet format IDE0059 warnings * Address dotnet format CA1816 warnings * Fix new dotnet-format issues after rebase * Address most dotnet format whitespace warnings * Apply dotnet format whitespace formatting A few of them have been manually reverted and the corresponding warning was silenced * Format if-blocks correctly * Another rebase, another dotnet format run * Run dotnet format whitespace after rebase * Run dotnet format style after rebase * Run dotnet format analyzers after rebase * Run dotnet format style after rebase * Run dotnet format after rebase and remove unused usings - analyzers - style - whitespace * Disable 'prefer switch expression' rule * Add comments to disabled warnings * Simplify properties and array initialization, Use const when possible, Remove trailing commas * Run dotnet format after rebase * Address IDE0251 warnings * Address a few disabled IDE0060 warnings * Silence IDE0060 in .editorconfig * Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas" This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e. * dotnet format whitespace after rebase * First dotnet format pass * Fix naming rule violations * Remove redundant code * Rename generics * Address review feedback * Remove SetOrigin
161 lines
4.9 KiB
C#
161 lines
4.9 KiB
C#
using Ryujinx.Common.Logging;
|
|
using Ryujinx.Graphics.GAL;
|
|
using Ryujinx.Graphics.Shader;
|
|
using shaderc;
|
|
using Silk.NET.Vulkan;
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Ryujinx.Graphics.Vulkan
|
|
{
|
|
class Shader : IDisposable
|
|
{
|
|
// The shaderc.net dependency's Options constructor and dispose are not thread safe.
|
|
// Take this lock when using them.
|
|
private static readonly object _shaderOptionsLock = new();
|
|
|
|
private static readonly IntPtr _ptrMainEntryPointName = Marshal.StringToHGlobalAnsi("main");
|
|
|
|
private readonly Vk _api;
|
|
private readonly Device _device;
|
|
private readonly ShaderStageFlags _stage;
|
|
|
|
private bool _disposed;
|
|
private ShaderModule _module;
|
|
|
|
public ShaderStageFlags StageFlags => _stage;
|
|
|
|
public ProgramLinkStatus CompileStatus { private set; get; }
|
|
|
|
public readonly Task CompileTask;
|
|
|
|
public unsafe Shader(Vk api, Device device, ShaderSource shaderSource)
|
|
{
|
|
_api = api;
|
|
_device = device;
|
|
|
|
CompileStatus = ProgramLinkStatus.Incomplete;
|
|
|
|
_stage = shaderSource.Stage.Convert();
|
|
|
|
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
|
|
{
|
|
SType = StructureType.ShaderModuleCreateInfo,
|
|
CodeSize = (uint)spirv.Length,
|
|
PCode = (uint*)pCode,
|
|
};
|
|
|
|
api.CreateShaderModule(device, shaderModuleCreateInfo, null, out _module).ThrowOnError();
|
|
}
|
|
|
|
CompileStatus = ProgramLinkStatus.Success;
|
|
});
|
|
}
|
|
|
|
private unsafe static byte[] GlslToSpirv(string glsl, ShaderStage stage)
|
|
{
|
|
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(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()[..(int)scr.CodeLength]);
|
|
|
|
return code;
|
|
}
|
|
|
|
private static ShaderKind GetShaderCShaderStage(ShaderStage stage)
|
|
{
|
|
switch (stage)
|
|
{
|
|
case ShaderStage.Vertex:
|
|
return ShaderKind.GlslVertexShader;
|
|
case ShaderStage.Geometry:
|
|
return ShaderKind.GlslGeometryShader;
|
|
case ShaderStage.TessellationControl:
|
|
return ShaderKind.GlslTessControlShader;
|
|
case ShaderStage.TessellationEvaluation:
|
|
return ShaderKind.GlslTessEvaluationShader;
|
|
case ShaderStage.Fragment:
|
|
return ShaderKind.GlslFragmentShader;
|
|
case ShaderStage.Compute:
|
|
return ShaderKind.GlslComputeShader;
|
|
}
|
|
|
|
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(ShaderStage)} enum value: {stage}.");
|
|
|
|
return ShaderKind.GlslVertexShader;
|
|
}
|
|
|
|
public unsafe PipelineShaderStageCreateInfo GetInfo()
|
|
{
|
|
return new PipelineShaderStageCreateInfo
|
|
{
|
|
SType = StructureType.PipelineShaderStageCreateInfo,
|
|
Stage = _stage,
|
|
Module = _module,
|
|
PName = (byte*)_ptrMainEntryPointName,
|
|
};
|
|
}
|
|
|
|
public void WaitForCompile()
|
|
{
|
|
CompileTask.Wait();
|
|
}
|
|
|
|
public unsafe void Dispose()
|
|
{
|
|
if (!_disposed)
|
|
{
|
|
_api.DestroyShaderModule(_device, _module, null);
|
|
_disposed = true;
|
|
}
|
|
}
|
|
}
|
|
}
|