diff options
| author | gdk <gab.dark.100@gmail.com> | 2019-10-13 03:02:07 -0300 |
|---|---|---|
| committer | Thog <thog@protonmail.com> | 2020-01-09 02:13:00 +0100 |
| commit | 1876b346fea647e8284a66bb6d62c38801035cff (patch) | |
| tree | 6eeff094298cda84d1613dc5ec0691e51d7b35f1 /Ryujinx.Graphics.Gpu/Engine/ShaderDumper.cs | |
| parent | f617fb542a0e3d36012d77a4b5acbde7b08902f2 (diff) | |
Initial work
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Engine/ShaderDumper.cs')
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/ShaderDumper.cs | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/ShaderDumper.cs b/Ryujinx.Graphics.Gpu/Engine/ShaderDumper.cs new file mode 100644 index 00000000..fdcf0612 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/ShaderDumper.cs @@ -0,0 +1,126 @@ +using System.IO; + +namespace Ryujinx.Graphics.Gpu.Engine +{ + class ShaderDumper + { + private const int ShaderHeaderSize = 0x50; + + private GpuContext _context; + + private string _runtimeDir; + private string _dumpPath; + private int _dumpIndex; + + public int CurrentDumpIndex => _dumpIndex; + + public ShaderDumper(GpuContext context) + { + _context = context; + + _dumpIndex = 1; + } + + public void Dump(ulong gpuVa, bool compute) + { + _dumpPath = GraphicsConfig.ShadersDumpPath; + + if (string.IsNullOrWhiteSpace(_dumpPath)) + { + return; + } + + string fileName = "Shader" + _dumpIndex.ToString("d4") + ".bin"; + + string fullPath = Path.Combine(FullDir(), fileName); + string codePath = Path.Combine(CodeDir(), fileName); + + _dumpIndex++; + + ulong headerSize = compute ? 0UL : ShaderHeaderSize; + + using (FileStream fullFile = File.Create(fullPath)) + using (FileStream codeFile = File.Create(codePath)) + { + BinaryWriter fullWriter = new BinaryWriter(fullFile); + BinaryWriter codeWriter = new BinaryWriter(codeFile); + + for (ulong i = 0; i < headerSize; i += 4) + { + fullWriter.Write(_context.MemoryAccessor.ReadInt32(gpuVa + i)); + } + + ulong offset = 0; + + ulong instruction = 0; + + // Dump until a NOP instruction is found. + while ((instruction >> 48 & 0xfff8) != 0x50b0) + { + uint word0 = (uint)_context.MemoryAccessor.ReadInt32(gpuVa + headerSize + offset + 0); + uint word1 = (uint)_context.MemoryAccessor.ReadInt32(gpuVa + headerSize + offset + 4); + + instruction = word0 | (ulong)word1 << 32; + + // Zero instructions (other kind of NOP) stop immediately, + // this is to avoid two rows of zeroes. + if (instruction == 0) + { + break; + } + + fullWriter.Write(instruction); + codeWriter.Write(instruction); + + offset += 8; + } + + // Align to meet nvdisasm requirements. + while (offset % 0x20 != 0) + { + fullWriter.Write(0); + codeWriter.Write(0); + + offset += 4; + } + } + } + + private string FullDir() + { + return CreateAndReturn(Path.Combine(DumpDir(), "Full")); + } + + private string CodeDir() + { + return CreateAndReturn(Path.Combine(DumpDir(), "Code")); + } + + private string DumpDir() + { + if (string.IsNullOrEmpty(_runtimeDir)) + { + int index = 1; + + do + { + _runtimeDir = Path.Combine(_dumpPath, "Dumps" + index.ToString("d2")); + + index++; + } + while (Directory.Exists(_runtimeDir)); + + Directory.CreateDirectory(_runtimeDir); + } + + return _runtimeDir; + } + + private static string CreateAndReturn(string dir) + { + Directory.CreateDirectory(dir); + + return dir; + } + } +}
\ No newline at end of file |
