aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs5
-rw-r--r--Ryujinx.Graphics/Gal/ShaderDumper.cs96
-rw-r--r--Ryujinx.Graphics/GraphicsConfig.cs4
-rw-r--r--Ryujinx/Config.cs2
-rw-r--r--Ryujinx/Ryujinx.conf3
5 files changed, 110 insertions, 0 deletions
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
index c55a758b..ad717755 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
@@ -118,6 +118,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
if (IsDualVp)
{
+ ShaderDumper.Dump(Memory, Position + 0x50, Type, "a");
+ ShaderDumper.Dump(Memory, PositionB + 0x50, Type, "b");
+
Program = Decompiler.Decompile(
Memory,
Position + 0x50,
@@ -126,6 +129,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
}
else
{
+ ShaderDumper.Dump(Memory, Position + 0x50, Type);
+
Program = Decompiler.Decompile(Memory, Position + 0x50, Type);
}
diff --git a/Ryujinx.Graphics/Gal/ShaderDumper.cs b/Ryujinx.Graphics/Gal/ShaderDumper.cs
new file mode 100644
index 00000000..7cd56b21
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/ShaderDumper.cs
@@ -0,0 +1,96 @@
+using System;
+using System.IO;
+
+namespace Ryujinx.Graphics.Gal
+{
+ static class ShaderDumper
+ {
+ private static string RuntimeDir;
+
+ private static int DumpIndex = 1;
+
+ public static void Dump(IGalMemory Memory, long Position, GalShaderType Type, string ExtSuffix = "")
+ {
+ if (string.IsNullOrWhiteSpace(GraphicsConfig.ShadersDumpPath))
+ {
+ return;
+ }
+
+ string FileName = "Shader" + DumpIndex.ToString("d4") + "." + ShaderExtension(Type) + ExtSuffix + ".bin";
+
+ string FilePath = Path.Combine(DumpDir(), FileName);
+
+ DumpIndex++;
+
+ using (FileStream Output = File.Create(FilePath))
+ using (BinaryWriter Writer = new BinaryWriter(Output))
+ {
+ long Offset = 0;
+
+ ulong Instruction = 0;
+
+ //Dump until a NOP instruction is found
+ while ((Instruction >> 52 & 0xfff8) != 0x50b0)
+ {
+ uint Word0 = (uint)Memory.ReadInt32(Position + Offset + 0);
+ uint Word1 = (uint)Memory.ReadInt32(Position + Offset + 4);
+
+ Instruction = Word0 | (ulong)Word1 << 32;
+
+ //Zero instructions (other kind of NOP) stop immediatly,
+ //this is to avoid two rows of zeroes
+ if (Instruction == 0)
+ {
+ break;
+ }
+
+ Writer.Write(Instruction);
+
+ Offset += 8;
+ }
+
+ //Align to meet nvdisasm requeriments
+ while (Offset % 0x20 != 0)
+ {
+ Writer.Write(0);
+
+ Offset += 4;
+ }
+ }
+ }
+
+ private static string DumpDir()
+ {
+ if (string.IsNullOrEmpty(RuntimeDir))
+ {
+ int Index = 1;
+
+ do
+ {
+ RuntimeDir = Path.Combine(GraphicsConfig.ShadersDumpPath, "Dumps" + Index.ToString("d2"));
+
+ Index++;
+ }
+ while (Directory.Exists(RuntimeDir));
+
+ Directory.CreateDirectory(RuntimeDir);
+ }
+
+ return RuntimeDir;
+ }
+
+ private static string ShaderExtension(GalShaderType Type)
+ {
+ switch (Type)
+ {
+ case GalShaderType.Vertex: return "vert";
+ case GalShaderType.TessControl: return "tesc";
+ case GalShaderType.TessEvaluation: return "tese";
+ case GalShaderType.Geometry: return "geom";
+ case GalShaderType.Fragment: return "frag";
+
+ default: throw new ArgumentException(nameof(Type));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/GraphicsConfig.cs b/Ryujinx.Graphics/GraphicsConfig.cs
new file mode 100644
index 00000000..3e3ef4ff
--- /dev/null
+++ b/Ryujinx.Graphics/GraphicsConfig.cs
@@ -0,0 +1,4 @@
+public static class GraphicsConfig
+{
+ public static string ShadersDumpPath;
+}
diff --git a/Ryujinx/Config.cs b/Ryujinx/Config.cs
index 940753ba..0f346122 100644
--- a/Ryujinx/Config.cs
+++ b/Ryujinx/Config.cs
@@ -29,6 +29,8 @@ namespace Ryujinx
AOptimizations.DisableMemoryChecks = !Convert.ToBoolean(Parser.Value("Enable_Memory_Checks"));
+ GraphicsConfig.ShadersDumpPath = Parser.Value("Graphics_Shaders_Dump_Path");
+
Log.SetEnable(LogLevel.Debug, Convert.ToBoolean(Parser.Value("Logging_Enable_Debug")));
Log.SetEnable(LogLevel.Stub, Convert.ToBoolean(Parser.Value("Logging_Enable_Stub")));
Log.SetEnable(LogLevel.Info, Convert.ToBoolean(Parser.Value("Logging_Enable_Info")));
diff --git a/Ryujinx/Ryujinx.conf b/Ryujinx/Ryujinx.conf
index 59f7f859..063bb2de 100644
--- a/Ryujinx/Ryujinx.conf
+++ b/Ryujinx/Ryujinx.conf
@@ -1,6 +1,9 @@
#Enable cpu memory checks (slow)
Enable_Memory_Checks = false
+#Dump shaders in local directory (e.g. `C:\ShaderDumps`)
+Graphics_Shaders_Dump_Path =
+
#Enable print debug logs
Logging_Enable_Debug = false