shadertools: Prepare for new target Languages and APIs (#2465)

* shadertools: Prepare for new target Langugaes and APIs

This improves shader tools command line by adding support for target
language and api.

* Address gdkchan's comments
This commit is contained in:
Mary 2021-07-18 12:49:39 +02:00 committed by GitHub
parent ca5ac37cd6
commit 97a2133207
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 87 additions and 19 deletions

View File

@ -7,11 +7,21 @@ namespace Ryujinx.Graphics.Shader
public ShaderStage Stage { get; } public ShaderStage Stage { get; }
public string Code { get; private set; } public string Code { get; private set; }
public byte[] BinaryCode { get; }
public ShaderProgram(ShaderStage stage, string code) private ShaderProgram(ShaderStage stage)
{ {
Stage = stage; Stage = stage;
Code = code; }
public ShaderProgram(ShaderStage stage, string code) : this(stage)
{
Code = code;
}
public ShaderProgram(ShaderStage stage, byte[] binaryCode) : this(stage)
{
BinaryCode = binaryCode;
} }
public void Prepend(string line) public void Prepend(string line)

View File

@ -3,6 +3,7 @@ namespace Ryujinx.Graphics.Shader.Translation
public enum TargetLanguage public enum TargetLanguage
{ {
Glsl, Glsl,
Spirv Spirv,
Arb
} }
} }

View File

@ -3,6 +3,7 @@ using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr; using Ryujinx.Graphics.Shader.StructuredIr;
using Ryujinx.Graphics.Shader.Translation.Optimizations; using Ryujinx.Graphics.Shader.Translation.Optimizations;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@ -87,7 +88,16 @@ namespace Ryujinx.Graphics.Shader.Translation
StructuredProgramInfo sInfo = StructuredProgram.MakeStructuredProgram(funcs, config); StructuredProgramInfo sInfo = StructuredProgram.MakeStructuredProgram(funcs, config);
string glslCode = GlslGenerator.Generate(sInfo, config); ShaderProgram program;
switch (config.Options.TargetLanguage)
{
case TargetLanguage.Glsl:
program = new ShaderProgram(config.Stage, GlslGenerator.Generate(sInfo, config));
break;
default:
throw new NotImplementedException(config.Options.TargetLanguage.ToString());
}
shaderProgramInfo = new ShaderProgramInfo( shaderProgramInfo = new ShaderProgramInfo(
config.GetConstantBufferDescriptors(), config.GetConstantBufferDescriptors(),
@ -97,7 +107,7 @@ namespace Ryujinx.Graphics.Shader.Translation
config.UsedFeatures.HasFlag(FeatureFlags.InstanceId), config.UsedFeatures.HasFlag(FeatureFlags.InstanceId),
config.ClipDistancesWritten); config.ClipDistancesWritten);
return new ShaderProgram(config.Stage, glslCode); return program;
} }
private static Block[][] DecodeShader( private static Block[][] DecodeShader(

View File

@ -1,4 +1,5 @@
using Ryujinx.Graphics.Shader; using CommandLine;
using Ryujinx.Graphics.Shader;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System; using System;
using System.IO; using System.IO;
@ -23,28 +24,70 @@ namespace Ryujinx.ShaderTools
} }
} }
static void Main(string[] args) private class Options
{ {
if (args.Length == 1 || args.Length == 2) [Option("compute", Required = false, Default = false, HelpText = "Indicate that the shader is a compute shader.")]
public bool Compute { get; set; }
[Option("target-language", Required = false, Default = TargetLanguage.Glsl, HelpText = "Indicate the target shader language to use.")]
public TargetLanguage TargetLanguage { get; set; }
[Option("target-api", Required = false, Default = TargetApi.OpenGL, HelpText = "Indicate the target graphics api to use.")]
public TargetApi TargetApi { get; set; }
[Value(0, MetaName = "input", HelpText = "Binary Maxwell shader input path.", Required = true)]
public string InputPath { get; set; }
[Value(1, MetaName = "output", HelpText = "Decompiled shader output path.", Required = false)]
public string OutputPath { get; set; }
}
static void HandleArguments(Options options)
{
TranslationFlags flags = TranslationFlags.DebugMode;
if (options.Compute)
{ {
TranslationFlags flags = TranslationFlags.DebugMode; flags |= TranslationFlags.Compute;
}
if (args.Length == 2 && args[0] == "--compute") byte[] data = File.ReadAllBytes(options.InputPath);
TranslationOptions translationOptions = new TranslationOptions(options.TargetLanguage, options.TargetApi, flags);
ShaderProgram program = Translator.CreateContext(0, new GpuAccessor(data), translationOptions).Translate(out _);
if (options.OutputPath == null)
{
if (program.BinaryCode != null)
{ {
flags |= TranslationFlags.Compute; using Stream outputStream = Console.OpenStandardOutput();
outputStream.Write(program.BinaryCode);
}
else
{
Console.WriteLine(program.Code);
} }
byte[] data = File.ReadAllBytes(args[^1]);
TranslationOptions options = new TranslationOptions(TargetLanguage.Glsl, TargetApi.OpenGL, flags);
string code = Translator.CreateContext(0, new GpuAccessor(data), options).Translate(out _).Code;
Console.WriteLine(code);
} }
else else
{ {
Console.WriteLine("Usage: Ryujinx.ShaderTools [--compute] shader.bin"); if (program.BinaryCode != null)
{
File.WriteAllBytes(options.OutputPath, program.BinaryCode);
}
else
{
File.WriteAllText(options.OutputPath, program.Code);
}
} }
} }
static void Main(string[] args)
{
Parser.Default.ParseArguments<Options>(args)
.WithParsed(options => HandleArguments(options))
.WithNotParsed(errors => errors.Output());
}
} }
} }

View File

@ -11,4 +11,8 @@
<ProjectReference Include="..\Ryujinx.Graphics.Shader\Ryujinx.Graphics.Shader.csproj" /> <ProjectReference Include="..\Ryujinx.Graphics.Shader\Ryujinx.Graphics.Shader.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.8.0" />
</ItemGroup>
</Project> </Project>