Add config key to dump shaders in local directory (#265)

* Add config key to dump shaders in local directory

* Address feedback
This commit is contained in:
ReinUsesLisp 2018-07-15 19:37:27 -03:00 committed by gdkchan
parent 063fae50fe
commit 3e13b40b35
5 changed files with 110 additions and 0 deletions

View File

@ -118,6 +118,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
if (IsDualVp) if (IsDualVp)
{ {
ShaderDumper.Dump(Memory, Position + 0x50, Type, "a");
ShaderDumper.Dump(Memory, PositionB + 0x50, Type, "b");
Program = Decompiler.Decompile( Program = Decompiler.Decompile(
Memory, Memory,
Position + 0x50, Position + 0x50,
@ -126,6 +129,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
} }
else else
{ {
ShaderDumper.Dump(Memory, Position + 0x50, Type);
Program = Decompiler.Decompile(Memory, Position + 0x50, Type); Program = Decompiler.Decompile(Memory, Position + 0x50, Type);
} }

View File

@ -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));
}
}
}
}

View File

@ -0,0 +1,4 @@
public static class GraphicsConfig
{
public static string ShadersDumpPath;
}

View File

@ -29,6 +29,8 @@ namespace Ryujinx
AOptimizations.DisableMemoryChecks = !Convert.ToBoolean(Parser.Value("Enable_Memory_Checks")); 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.Debug, Convert.ToBoolean(Parser.Value("Logging_Enable_Debug")));
Log.SetEnable(LogLevel.Stub, Convert.ToBoolean(Parser.Value("Logging_Enable_Stub"))); Log.SetEnable(LogLevel.Stub, Convert.ToBoolean(Parser.Value("Logging_Enable_Stub")));
Log.SetEnable(LogLevel.Info, Convert.ToBoolean(Parser.Value("Logging_Enable_Info"))); Log.SetEnable(LogLevel.Info, Convert.ToBoolean(Parser.Value("Logging_Enable_Info")));

View File

@ -1,6 +1,9 @@
#Enable cpu memory checks (slow) #Enable cpu memory checks (slow)
Enable_Memory_Checks = false Enable_Memory_Checks = false
#Dump shaders in local directory (e.g. `C:\ShaderDumps`)
Graphics_Shaders_Dump_Path =
#Enable print debug logs #Enable print debug logs
Logging_Enable_Debug = false Logging_Enable_Debug = false