aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2018-07-15 19:37:27 -0300
committergdkchan <gab.dark.100@gmail.com>2018-07-15 19:37:27 -0300
commit3e13b40b353a61fe57d1bc1440e1db9bc133df08 (patch)
tree524a073524241c6868f149d8807e23a842e33adf /Ryujinx.Graphics
parent063fae50fe25388d10e9ec1915c561dc0f4d519d (diff)
Add config key to dump shaders in local directory (#265)
* Add config key to dump shaders in local directory * Address feedback
Diffstat (limited to 'Ryujinx.Graphics')
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs5
-rw-r--r--Ryujinx.Graphics/Gal/ShaderDumper.cs96
-rw-r--r--Ryujinx.Graphics/GraphicsConfig.cs4
3 files changed, 105 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;
+}