mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2024-12-28 11:33:06 +00:00
Initial SPIR-V decompiling support
This commit is contained in:
parent
f1e866e248
commit
2c9cd5e938
6 changed files with 3843 additions and 8 deletions
70
Ryujinx.Graphics/Gal/Shader/SpirvAssembler.cs
Normal file
70
Ryujinx.Graphics/Gal/Shader/SpirvAssembler.cs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader.SPIRV
|
||||||
|
{
|
||||||
|
public class Assembler
|
||||||
|
{
|
||||||
|
private List<Instruction> Instructions;
|
||||||
|
|
||||||
|
public Assembler()
|
||||||
|
{
|
||||||
|
Instructions = new List<Instruction>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(Stream Output)
|
||||||
|
{
|
||||||
|
uint Bound = DoBindings();
|
||||||
|
|
||||||
|
var BinaryWriter = new BinaryWriter(Output);
|
||||||
|
|
||||||
|
BinaryWriter.Write((uint)BinaryForm.MagicNumber);
|
||||||
|
BinaryWriter.Write((uint)BinaryForm.VersionNumber);
|
||||||
|
BinaryWriter.Write((uint)BinaryForm.GeneratorMagicNumber);
|
||||||
|
BinaryWriter.Write((uint)Bound);
|
||||||
|
BinaryWriter.Write((uint)0); // Reserved for instruction schema
|
||||||
|
|
||||||
|
foreach (var Instruction in Instructions)
|
||||||
|
{
|
||||||
|
Instruction.Write(BinaryWriter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(Instruction Instruction)
|
||||||
|
{
|
||||||
|
Instructions.Add(Instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(Instruction[] Instructions)
|
||||||
|
{
|
||||||
|
foreach (Instruction Instruction in Instructions)
|
||||||
|
{
|
||||||
|
Add(Instruction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(List<Instruction> Instructions)
|
||||||
|
{
|
||||||
|
foreach (Instruction Instruction in Instructions)
|
||||||
|
{
|
||||||
|
Add(Instruction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint DoBindings()
|
||||||
|
{
|
||||||
|
uint Bind = 1;
|
||||||
|
|
||||||
|
foreach (var Instruction in Instructions)
|
||||||
|
{
|
||||||
|
if (Instruction.HoldsResultId)
|
||||||
|
{
|
||||||
|
Instruction.ResultId = Bind;
|
||||||
|
Bind++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Bind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1121
Ryujinx.Graphics/Gal/Shader/SpirvBinaryForm.cs
Normal file
1121
Ryujinx.Graphics/Gal/Shader/SpirvBinaryForm.cs
Normal file
File diff suppressed because it is too large
Load diff
1146
Ryujinx.Graphics/Gal/Shader/SpirvDecompiler.cs
Normal file
1146
Ryujinx.Graphics/Gal/Shader/SpirvDecompiler.cs
Normal file
File diff suppressed because it is too large
Load diff
1332
Ryujinx.Graphics/Gal/Shader/SpirvInstruction.cs
Normal file
1332
Ryujinx.Graphics/Gal/Shader/SpirvInstruction.cs
Normal file
File diff suppressed because it is too large
Load diff
151
Ryujinx.Graphics/Gal/Shader/SpirvOperand.cs
Normal file
151
Ryujinx.Graphics/Gal/Shader/SpirvOperand.cs
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader.SPIRV
|
||||||
|
{
|
||||||
|
public abstract class Operand
|
||||||
|
{
|
||||||
|
public abstract int GetWordCount();
|
||||||
|
|
||||||
|
public abstract void Write(BinaryWriter BinaryWriter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Id: Operand
|
||||||
|
{
|
||||||
|
private Instruction Instruction;
|
||||||
|
|
||||||
|
public Id(Instruction Instruction)
|
||||||
|
{
|
||||||
|
this.Instruction = Instruction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter BinaryWriter)
|
||||||
|
{
|
||||||
|
BinaryWriter.Write((uint)Instruction.ResultId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetWordCount()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class Literal: Operand
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LiteralString: Literal
|
||||||
|
{
|
||||||
|
public byte[] Value;
|
||||||
|
|
||||||
|
public LiteralString(string String)
|
||||||
|
{
|
||||||
|
Value = Encoding.UTF8.GetBytes(String);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter BinaryWriter)
|
||||||
|
{
|
||||||
|
BinaryWriter.Write(Value);
|
||||||
|
|
||||||
|
// Write remaining zero bytes
|
||||||
|
for (int i = 0; i < 4 - (Value.Length % 4); i++)
|
||||||
|
{
|
||||||
|
BinaryWriter.Write((byte)0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetWordCount()
|
||||||
|
{
|
||||||
|
return Value.Length / 4 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object Object)
|
||||||
|
{
|
||||||
|
if (Object is LiteralString Other)
|
||||||
|
{
|
||||||
|
return this.Value == Other.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LiteralNumber: Literal
|
||||||
|
{
|
||||||
|
public TypeCode Type;
|
||||||
|
|
||||||
|
public int Integer;
|
||||||
|
|
||||||
|
public float Float32;
|
||||||
|
|
||||||
|
public double Float64;
|
||||||
|
|
||||||
|
public LiteralNumber(int Value)
|
||||||
|
{
|
||||||
|
Integer = Value;
|
||||||
|
Type = Value.GetTypeCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiteralNumber(float Value)
|
||||||
|
{
|
||||||
|
Float32 = Value;
|
||||||
|
Type = Value.GetTypeCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiteralNumber(double Value)
|
||||||
|
{
|
||||||
|
Float64 = Value;
|
||||||
|
Type = Value.GetTypeCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter BinaryWriter)
|
||||||
|
{
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case TypeCode.Int32:
|
||||||
|
BinaryWriter.Write(Integer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Single:
|
||||||
|
BinaryWriter.Write(Float32);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Double:
|
||||||
|
BinaryWriter.Write(Float64);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetWordCount()
|
||||||
|
{
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case TypeCode.Int32:
|
||||||
|
case TypeCode.Single:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case TypeCode.Double:
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object Object)
|
||||||
|
{
|
||||||
|
if (Object is LiteralNumber Other && this.Type == Other.Type)
|
||||||
|
{
|
||||||
|
return this.Integer == Other.Integer
|
||||||
|
&& this.Float32 == Other.Float32
|
||||||
|
&& this.Float64 == Other.Float64;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
using Ryujinx.Graphics.Gal.Shader;
|
using Ryujinx.Graphics.Gal.Shader;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Ryujinx.ShaderTools
|
namespace Ryujinx.ShaderTools
|
||||||
{
|
{
|
||||||
|
@ -9,13 +10,11 @@ namespace Ryujinx.ShaderTools
|
||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
if (args.Length == 2)
|
if (args.Length == 4)
|
||||||
{
|
{
|
||||||
GlslDecompiler Decompiler = new GlslDecompiler();
|
|
||||||
|
|
||||||
GalShaderType ShaderType = GalShaderType.Vertex;
|
GalShaderType ShaderType = GalShaderType.Vertex;
|
||||||
|
|
||||||
switch (args[0].ToLower())
|
switch (args[1].ToLower())
|
||||||
{
|
{
|
||||||
case "v": ShaderType = GalShaderType.Vertex; break;
|
case "v": ShaderType = GalShaderType.Vertex; break;
|
||||||
case "tc": ShaderType = GalShaderType.TessControl; break;
|
case "tc": ShaderType = GalShaderType.TessControl; break;
|
||||||
|
@ -24,18 +23,34 @@ namespace Ryujinx.ShaderTools
|
||||||
case "f": ShaderType = GalShaderType.Fragment; break;
|
case "f": ShaderType = GalShaderType.Fragment; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
using (FileStream FS = new FileStream(args[1], FileMode.Open, FileAccess.Read))
|
using (FileStream Output = new FileStream(args[3], FileMode.Create))
|
||||||
|
using (FileStream FS = new FileStream(args[2], FileMode.Open, FileAccess.Read))
|
||||||
{
|
{
|
||||||
Memory Mem = new Memory(FS);
|
Memory Mem = new Memory(FS);
|
||||||
|
|
||||||
GlslProgram Program = Decompiler.Decompile(Mem, 0, ShaderType);
|
switch (args[0].ToLower())
|
||||||
|
{
|
||||||
|
case "glsl":
|
||||||
|
GlslDecompiler GlslDecompiler = new GlslDecompiler();
|
||||||
|
|
||||||
Console.WriteLine(Program.Code);
|
GlslProgram Program = GlslDecompiler.Decompile(Mem, 0, ShaderType);
|
||||||
|
|
||||||
|
Output.Write(System.Text.Encoding.UTF8.GetBytes(Program.Code));
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "spirv":
|
||||||
|
SpirvDecompiler SpirvDecompiler = new SpirvDecompiler();
|
||||||
|
|
||||||
|
Output.Write(SpirvDecompiler.Decompile(Mem, 0, ShaderType));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("Usage: Ryujinx.ShaderTools [v|tc|te|g|f] shader.bin");
|
Console.WriteLine("Usage: Ryujinx.ShaderTools [spirv|glsl] [v|tc|te|g|f] shader.bin output.bin");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue