From d274328c3192fd85b9eec661b00f1599d673776c Mon Sep 17 00:00:00 2001 From: gdk Date: Sun, 10 Nov 2019 11:03:38 -0300 Subject: [PATCH] Fix image units bindings and shader dump in the presence of NOPs --- Ryujinx.Graphics.Gpu/Engine/ShaderCache.cs | 28 ++++++++-- Ryujinx.Graphics.Gpu/Engine/ShaderDumper.cs | 62 ++++++++------------- Ryujinx.Graphics.OpenGL/Program.cs | 9 +-- 3 files changed, 51 insertions(+), 48 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Engine/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Engine/ShaderCache.cs index d280ea6f5..922f4a44e 100644 --- a/Ryujinx.Graphics.Gpu/Engine/ShaderCache.cs +++ b/Ryujinx.Graphics.Gpu/Engine/ShaderCache.cs @@ -117,7 +117,13 @@ namespace Ryujinx.Graphics.Gpu.Engine program = Translator.Translate(code, translationConfig); - _dumper.Dump(gpuVa, compute : true); + _dumper.Dump(code, compute : true, out string fullPath, out string codePath); + + if (fullPath != null && codePath != null) + { + program.Prepend("// " + codePath); + program.Prepend("// " + fullPath); + } return program; } @@ -144,8 +150,16 @@ namespace Ryujinx.Graphics.Gpu.Engine program = Translator.Translate(codeA, codeB, translationConfig); - _dumper.Dump(gpuVaA, compute: false); - _dumper.Dump(gpuVa, compute: false); + _dumper.Dump(codeA, compute: false, out string fullPathA, out string codePathA); + _dumper.Dump(codeB, compute: false, out string fullPathB, out string codePathB); + + if (fullPathA != null && fullPathB != null && codePathA != null && codePathB != null) + { + program.Prepend("// " + codePathB); + program.Prepend("// " + fullPathB); + program.Prepend("// " + codePathA); + program.Prepend("// " + fullPathA); + } } else { @@ -153,7 +167,13 @@ namespace Ryujinx.Graphics.Gpu.Engine program = Translator.Translate(code, translationConfig); - _dumper.Dump(gpuVa, compute: false); + _dumper.Dump(code, compute: false, out string fullPath, out string codePath); + + if (fullPath != null && codePath != null) + { + program.Prepend("// " + codePath); + program.Prepend("// " + fullPath); + } } if (program.Stage == ShaderStage.Geometry) diff --git a/Ryujinx.Graphics.Gpu/Engine/ShaderDumper.cs b/Ryujinx.Graphics.Gpu/Engine/ShaderDumper.cs index fdcf06121..b2eb0f33e 100644 --- a/Ryujinx.Graphics.Gpu/Engine/ShaderDumper.cs +++ b/Ryujinx.Graphics.Gpu/Engine/ShaderDumper.cs @@ -1,11 +1,11 @@ +using Ryujinx.Graphics.Shader.Translation; +using System; using System.IO; namespace Ryujinx.Graphics.Gpu.Engine { class ShaderDumper { - private const int ShaderHeaderSize = 0x50; - private GpuContext _context; private string _runtimeDir; @@ -21,67 +21,49 @@ namespace Ryujinx.Graphics.Gpu.Engine _dumpIndex = 1; } - public void Dump(ulong gpuVa, bool compute) + public void Dump(Span code, bool compute, out string fullPath, out string codePath) { _dumpPath = GraphicsConfig.ShadersDumpPath; if (string.IsNullOrWhiteSpace(_dumpPath)) { + fullPath = null; + codePath = null; + return; } string fileName = "Shader" + _dumpIndex.ToString("d4") + ".bin"; - string fullPath = Path.Combine(FullDir(), fileName); - string codePath = Path.Combine(CodeDir(), fileName); + fullPath = Path.Combine(FullDir(), fileName); + codePath = Path.Combine(CodeDir(), fileName); _dumpIndex++; - ulong headerSize = compute ? 0UL : ShaderHeaderSize; + code = Translator.ExtractCode(code, compute, out int headerSize); - using (FileStream fullFile = File.Create(fullPath)) - using (FileStream codeFile = File.Create(codePath)) + using (MemoryStream stream = new MemoryStream(code.ToArray())) { - BinaryWriter fullWriter = new BinaryWriter(fullFile); - BinaryWriter codeWriter = new BinaryWriter(codeFile); + BinaryReader codeReader = new BinaryReader(stream); - for (ulong i = 0; i < headerSize; i += 4) + using (FileStream fullFile = File.Create(fullPath)) + using (FileStream codeFile = File.Create(codePath)) { - fullWriter.Write(_context.MemoryAccessor.ReadInt32(gpuVa + i)); - } + BinaryWriter fullWriter = new BinaryWriter(fullFile); + BinaryWriter codeWriter = new BinaryWriter(codeFile); - ulong offset = 0; + fullWriter.Write(codeReader.ReadBytes(headerSize)); - ulong instruction = 0; + byte[] temp = codeReader.ReadBytes(code.Length - headerSize); - // 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); + fullWriter.Write(temp); + codeWriter.Write(temp); - instruction = word0 | (ulong)word1 << 32; - - // Zero instructions (other kind of NOP) stop immediately, - // this is to avoid two rows of zeroes. - if (instruction == 0) + // Align to meet nvdisasm requirements. + while (codeFile.Length % 0x20 != 0) { - break; + codeWriter.Write(0); } - - 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; } } } diff --git a/Ryujinx.Graphics.OpenGL/Program.cs b/Ryujinx.Graphics.OpenGL/Program.cs index 61b1645ad..820910a90 100644 --- a/Ryujinx.Graphics.OpenGL/Program.cs +++ b/Ryujinx.Graphics.OpenGL/Program.cs @@ -79,6 +79,7 @@ namespace Ryujinx.Graphics.OpenGL int ubBindingPoint = 1; int sbBindingPoint = 0; int textureUnit = 0; + int imageUnit = 0; for (int index = 0; index < shaders.Length; index++) { @@ -151,13 +152,13 @@ namespace Ryujinx.Graphics.OpenGL continue; } - GL.Uniform1(location, textureUnit); + GL.Uniform1(location, imageUnit); int uIndex = (int)shader.Stage << ImgStageShift | imageIndex++; - _textureUnits[uIndex] = textureUnit; + _imageUnits[uIndex] = imageUnit; - textureUnit++; + imageUnit++; } } } @@ -184,7 +185,7 @@ namespace Ryujinx.Graphics.OpenGL public int GetImageUnit(ShaderStage stage, int index) { - return _textureUnits[(int)stage << ImgStageShift | index]; + return _imageUnits[(int)stage << ImgStageShift | index]; } private void CheckProgramLink()