Program.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. using CommandLine;
  2. using Ryujinx.Graphics.Shader;
  3. using Ryujinx.Graphics.Shader.Translation;
  4. using System;
  5. using System.IO;
  6. using System.Runtime.InteropServices;
  7. namespace Ryujinx.ShaderTools
  8. {
  9. class Program
  10. {
  11. private class GpuAccessor : IGpuAccessor
  12. {
  13. private readonly byte[] _data;
  14. public GpuAccessor(byte[] data)
  15. {
  16. _data = data;
  17. }
  18. public ReadOnlySpan<ulong> GetCode(ulong address, int minimumSize)
  19. {
  20. return MemoryMarshal.Cast<byte, ulong>(new ReadOnlySpan<byte>(_data)[(int)address..]);
  21. }
  22. }
  23. private class Options
  24. {
  25. [Option("compute", Required = false, Default = false, HelpText = "Indicate that the shader is a compute shader.")]
  26. public bool Compute { get; set; }
  27. [Option("vertex-as-compute", Required = false, Default = false, HelpText = "Indicate that the shader is a vertex shader and should be converted to compute.")]
  28. public bool VertexAsCompute { get; set; }
  29. [Option("vertex-passthrough", Required = false, Default = false, HelpText = "Indicate that the shader is a vertex passthrough shader for compute output.")]
  30. public bool VertexPassthrough { get; set; }
  31. [Option("target-language", Required = false, Default = TargetLanguage.Glsl, HelpText = "Indicate the target shader language to use.")]
  32. public TargetLanguage TargetLanguage { get; set; }
  33. [Option("target-api", Required = false, Default = TargetApi.OpenGL, HelpText = "Indicate the target graphics api to use.")]
  34. public TargetApi TargetApi { get; set; }
  35. [Value(0, MetaName = "input", HelpText = "Binary Maxwell shader input path.", Required = true)]
  36. public string InputPath { get; set; }
  37. [Value(1, MetaName = "output", HelpText = "Decompiled shader output path.", Required = false)]
  38. public string OutputPath { get; set; }
  39. }
  40. static void HandleArguments(Options options)
  41. {
  42. TranslationFlags flags = TranslationFlags.DebugMode;
  43. if (options.Compute)
  44. {
  45. flags |= TranslationFlags.Compute;
  46. }
  47. byte[] data = File.ReadAllBytes(options.InputPath);
  48. TranslationOptions translationOptions = new(options.TargetLanguage, options.TargetApi, flags);
  49. TranslatorContext translatorContext = Translator.CreateContext(0, new GpuAccessor(data), translationOptions);
  50. ShaderProgram program;
  51. if (options.VertexPassthrough)
  52. {
  53. program = translatorContext.GenerateVertexPassthroughForCompute();
  54. }
  55. else
  56. {
  57. program = translatorContext.Translate(options.VertexAsCompute);
  58. }
  59. if (options.OutputPath == null)
  60. {
  61. if (program.BinaryCode != null)
  62. {
  63. using Stream outputStream = Console.OpenStandardOutput();
  64. outputStream.Write(program.BinaryCode);
  65. }
  66. else
  67. {
  68. Console.WriteLine(program.Code);
  69. }
  70. }
  71. else
  72. {
  73. if (program.BinaryCode != null)
  74. {
  75. File.WriteAllBytes(options.OutputPath, program.BinaryCode);
  76. }
  77. else
  78. {
  79. File.WriteAllText(options.OutputPath, program.Code);
  80. }
  81. }
  82. }
  83. static void Main(string[] args)
  84. {
  85. Parser.Default.ParseArguments<Options>(args)
  86. .WithParsed(options => HandleArguments(options))
  87. .WithNotParsed(errors => errors.Output());
  88. }
  89. }
  90. }