| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- using Ryujinx.Graphics.Shader;
- using System.IO;
- namespace Ryujinx.Graphics.Gpu.Shader
- {
- /// <summary>
- /// Shader dumper, writes binary shader code to disk.
- /// </summary>
- class ShaderDumper
- {
- private string _runtimeDir;
- private string _dumpPath;
- /// <summary>
- /// Current index of the shader dump binary file.
- /// This is incremented after each save, in order to give unique names to the files.
- /// </summary>
- public int CurrentDumpIndex { get; private set; }
- /// <summary>
- /// Creates a new instance of the shader dumper.
- /// </summary>
- public ShaderDumper()
- {
- CurrentDumpIndex = 1;
- }
- /// <summary>
- /// Dumps shader code to disk.
- /// </summary>
- /// <param name="code">Code to be dumped</param>
- /// <param name="compute">True for compute shader code, false for graphics shader code</param>
- /// <returns>Paths where the shader code was dumped</returns>
- public ShaderDumpPaths Dump(byte[] code, bool compute)
- {
- _dumpPath = GraphicsConfig.ShadersDumpPath;
- if (string.IsNullOrWhiteSpace(_dumpPath))
- {
- return default;
- }
- string fileName = "Shader" + CurrentDumpIndex.ToString("d4") + ".bin";
- string fullPath = Path.Combine(FullDir(), fileName);
- string codePath = Path.Combine(CodeDir(), fileName);
- CurrentDumpIndex++;
- using MemoryStream stream = new MemoryStream(code);
- BinaryReader codeReader = new BinaryReader(stream);
- using FileStream fullFile = File.Create(fullPath);
- using FileStream codeFile = File.Create(codePath);
- BinaryWriter fullWriter = new BinaryWriter(fullFile);
- BinaryWriter codeWriter = new BinaryWriter(codeFile);
- int headerSize = compute ? 0 : 0x50;
- fullWriter.Write(codeReader.ReadBytes(headerSize));
- byte[] temp = codeReader.ReadBytes(code.Length - headerSize);
- fullWriter.Write(temp);
- codeWriter.Write(temp);
- // Align to meet nvdisasm requirements.
- while (codeFile.Length % 0x20 != 0)
- {
- codeWriter.Write(0);
- }
- return new ShaderDumpPaths(fullPath, codePath);
- }
- /// <summary>
- /// Returns the output directory for shader code with header.
- /// </summary>
- /// <returns>Directory path</returns>
- private string FullDir()
- {
- return CreateAndReturn(Path.Combine(DumpDir(), "Full"));
- }
- /// <summary>
- /// Returns the output directory for shader code without header.
- /// </summary>
- /// <returns>Directory path</returns>
- private string CodeDir()
- {
- return CreateAndReturn(Path.Combine(DumpDir(), "Code"));
- }
- /// <summary>
- /// Returns the full output directory for the current shader dump.
- /// </summary>
- /// <returns>Directory path</returns>
- 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;
- }
- /// <summary>
- /// Creates a new specified directory if needed.
- /// </summary>
- /// <param name="dir">The directory to create</param>
- /// <returns>The same directory passed to the method</returns>
- private static string CreateAndReturn(string dir)
- {
- Directory.CreateDirectory(dir);
- return dir;
- }
- }
- }
|