From 79e007036383b11cd53c2563fbb7f139a02c90ec Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Tue, 22 May 2018 22:43:31 -0300
Subject: [PATCH] Improve shader sending method to GAL, use a memory interface
 instead of reading a fixed array size and sending every time

---
 Ryujinx.Core/Gpu/NvGpuEngine3d.cs             |  7 +----
 Ryujinx.Core/Gpu/NvGpuVmm.cs                  |  4 ++-
 Ryujinx.Graphics/Gal/IGalMemory.cs            |  7 +++++
 Ryujinx.Graphics/Gal/IGalRenderer.cs          |  2 +-
 Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs      | 27 +++++--------------
 Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs |  8 +++---
 Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs |  4 +--
 .../Gal/Shader/ShaderDecodeFlow.cs            |  2 +-
 Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs  | 22 +++++++--------
 Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs  | 10 +++----
 Ryushader/Memory.cs                           | 26 ++++++++++++++++++
 Ryushader/Program.cs                          | 16 ++++-------
 12 files changed, 72 insertions(+), 63 deletions(-)
 create mode 100644 Ryujinx.Graphics/Gal/IGalMemory.cs
 create mode 100644 Ryushader/Memory.cs

diff --git a/Ryujinx.Core/Gpu/NvGpuEngine3d.cs b/Ryujinx.Core/Gpu/NvGpuEngine3d.cs
index b08b949617..5639dd02f1 100644
--- a/Ryujinx.Core/Gpu/NvGpuEngine3d.cs
+++ b/Ryujinx.Core/Gpu/NvGpuEngine3d.cs
@@ -138,16 +138,11 @@ namespace Ryujinx.Core.Gpu
 
                 long Tag = BasePosition + (uint)Offset;
 
-                //TODO: Find a better way to calculate the size.
-                int Size = 0x20000;
-
-                byte[] Code = Vmm.ReadBytes(Tag, Size);
-
                 GalShaderType ShaderType = GetTypeFromProgram(Index);
 
                 Tags[(int)ShaderType] = Tag;
 
-                Gpu.Renderer.CreateShader(Tag, ShaderType, Code);
+                Gpu.Renderer.CreateShader(Vmm, Tag, ShaderType);
                 Gpu.Renderer.BindShader(Tag);
             }
 
diff --git a/Ryujinx.Core/Gpu/NvGpuVmm.cs b/Ryujinx.Core/Gpu/NvGpuVmm.cs
index cf94a6c016..ddd2123806 100644
--- a/Ryujinx.Core/Gpu/NvGpuVmm.cs
+++ b/Ryujinx.Core/Gpu/NvGpuVmm.cs
@@ -1,9 +1,11 @@
 using ChocolArm64.Memory;
 using System.Collections.Concurrent;
 
+using Ryujinx.Graphics.Gal;
+
 namespace Ryujinx.Core.Gpu
 {
-    public class NvGpuVmm : IAMemory
+    public class NvGpuVmm : IAMemory, IGalMemory
     {
         public const long AddrSize = 1L << 40;
 
diff --git a/Ryujinx.Graphics/Gal/IGalMemory.cs b/Ryujinx.Graphics/Gal/IGalMemory.cs
new file mode 100644
index 0000000000..e6762b50cc
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/IGalMemory.cs
@@ -0,0 +1,7 @@
+namespace Ryujinx.Graphics.Gal
+{
+    public unsafe interface IGalMemory
+    {
+        int ReadInt32(long Position);
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/IGalRenderer.cs b/Ryujinx.Graphics/Gal/IGalRenderer.cs
index e4aef20606..79c20e0e1b 100644
--- a/Ryujinx.Graphics/Gal/IGalRenderer.cs
+++ b/Ryujinx.Graphics/Gal/IGalRenderer.cs
@@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.Gal
         void DrawElements(int VbIndex, int First, GalPrimitiveType PrimType);
 
         //Shader
-        void CreateShader(long Tag, GalShaderType Type, byte[] Data);
+        void CreateShader(IGalMemory Memory, long Tag, GalShaderType Type);
 
         IEnumerable<ShaderDeclInfo> GetTextureUsage(long Tag);
 
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
index e740a32e4d..a8941d690e 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
@@ -3,7 +3,6 @@ using Ryujinx.Graphics.Gal.Shader;
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
-using System.IO;
 using System.Linq;
 
 namespace Ryujinx.Graphics.Gal.OpenGL
@@ -85,14 +84,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
             Programs = new Dictionary<ShaderProgram, int>();
         }
 
-        public void Create(long Tag, GalShaderType Type, byte[] Data)
+        public void Create(IGalMemory Memory, long Tag, GalShaderType Type)
         {
-            Stages.GetOrAdd(Tag, (Key) => ShaderStageFactory(Type, Tag, Data));
+            Stages.GetOrAdd(Tag, (Key) => ShaderStageFactory(Memory, Tag, Type));
         }
 
-        private ShaderStage ShaderStageFactory(GalShaderType Type, long Tag, byte[] Data)
+        private ShaderStage ShaderStageFactory(IGalMemory Memory, long Position, GalShaderType Type)
         {
-            GlslProgram Program = GetGlslProgram(Data, Type);
+            GlslProgram Program = GetGlslProgram(Memory, Position,  Type);
 
             return new ShaderStage(
                 Type,
@@ -101,25 +100,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
                 Program.Uniforms);
         }
 
-        private GlslProgram GetGlslProgram(byte[] Data, GalShaderType Type)
+        private GlslProgram GetGlslProgram(IGalMemory Memory, long Position, GalShaderType Type)
         {
-            int[] Code = new int[(Data.Length - 0x50) >> 2];
-
-            using (MemoryStream MS = new MemoryStream(Data))
-            {
-                MS.Seek(0x50, SeekOrigin.Begin);
-
-                BinaryReader Reader = new BinaryReader(MS);
-
-                for (int Index = 0; Index < Code.Length; Index++)
-                {
-                    Code[Index] = Reader.ReadInt32();
-                }
-            }
-
             GlslDecompiler Decompiler = new GlslDecompiler();
 
-            return Decompiler.Decompile(Code, Type);
+            return Decompiler.Decompile(Memory, Position + 0x50, Type);
         }
 
         public IEnumerable<ShaderDeclInfo> GetTextureUsage(long Tag)
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs
index f941057375..69e344c74c 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs
@@ -198,14 +198,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
             ActionsQueue.Enqueue(() => Rasterizer.DrawElements(VbIndex, First, PrimType));
         }
 
-        public void CreateShader(long Tag, GalShaderType Type, byte[] Data)
+        public void CreateShader(IGalMemory Memory, long Tag, GalShaderType Type)
         {
-            if (Data == null)
+            if (Memory == null)
             {
-                throw new ArgumentNullException(nameof(Data));
+                throw new ArgumentNullException(nameof(Memory));
             }
 
-            Shader.Create(Tag, Type, Data);
+            Shader.Create(Memory, Tag, Type);
         }
 
         public void SetConstBuffer(long Tag, int Cbuf, byte[] Data)
diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
index d6f171f4c9..88e462439c 100644
--- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
+++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
@@ -89,9 +89,9 @@ namespace Ryujinx.Graphics.Gal.Shader
             };
         }
 
-        public GlslProgram Decompile(int[] Code, GalShaderType ShaderType)
+        public GlslProgram Decompile(IGalMemory Memory, long Position, GalShaderType ShaderType)
         {
-            ShaderIrBlock Block = ShaderDecoder.DecodeBasicBlock(Code, 0);
+            ShaderIrBlock Block = ShaderDecoder.DecodeBasicBlock(Memory, Position);
 
             ShaderIrNode[] Nodes = Block.GetNodes();
 
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs
index b5f3e0b726..6f48d1a8cd 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs
@@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Gal.Shader
                 throw new NotImplementedException();
             }
 
-            int Target = ((int)(OpCode >> 20) << 8) >> 8;
+            long Target = ((int)(OpCode >> 20) << 8) >> 8;
 
             Target += Block.Position + 8;
 
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
index 4958dfcf44..024fa36489 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
@@ -4,28 +4,28 @@ namespace Ryujinx.Graphics.Gal.Shader
     {
         private const bool AddDbgComments = true;
 
-        public static ShaderIrBlock DecodeBasicBlock(int[] Code, int Offset)
+        public static ShaderIrBlock DecodeBasicBlock(IGalMemory Memory, long Position)
         {
             ShaderIrBlock Block = new ShaderIrBlock();
 
-            while (Offset + 2 <= Code.Length)
+            while (true)
             {
-                int InstPos = Offset * 4;
+                Block.Position = Position;
 
-                Block.Position = InstPos;
-
-                Block.MarkLabel(InstPos);
+                Block.MarkLabel(Position);
 
                 //Ignore scheduling instructions, which are written every 32 bytes.
-                if ((Offset & 7) == 0)
+                if ((Position & 0x1f) == 0)
                 {
-                    Offset += 2;
+                    Position += 8;
 
                     continue;
                 }
 
-                uint Word0 = (uint)Code[Offset++];
-                uint Word1 = (uint)Code[Offset++];
+                uint Word0 = (uint)Memory.ReadInt32(Position + 0);
+                uint Word1 = (uint)Memory.ReadInt32(Position + 4);
+
+                Position += 8;
 
                 long OpCode = Word0 | (long)Word1 << 32;
 
@@ -33,7 +33,7 @@ namespace Ryujinx.Graphics.Gal.Shader
 
                 if (AddDbgComments)
                 {
-                    string DbgOpCode = $"0x{InstPos:x8}: 0x{OpCode:x16} ";
+                    string DbgOpCode = $"0x{Position:x16}: 0x{OpCode:x16} ";
 
                     Block.AddNode(new ShaderIrCmnt(DbgOpCode + (Decode?.Method.Name ?? "???")));
                 }
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs
index 5f365d8c8f..31d7216964 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs
@@ -6,15 +6,15 @@ namespace Ryujinx.Graphics.Gal.Shader
     {
         private List<ShaderIrNode> Nodes;
 
-        private Dictionary<int, ShaderIrLabel> LabelsToInsert;
+        private Dictionary<long, ShaderIrLabel> LabelsToInsert;
 
-        public int Position;
+        public long Position;
 
         public ShaderIrBlock()
         {
             Nodes = new List<ShaderIrNode>();
 
-            LabelsToInsert = new Dictionary<int, ShaderIrLabel>();
+            LabelsToInsert = new Dictionary<long, ShaderIrLabel>();
         }
 
         public void AddNode(ShaderIrNode Node)
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gal.Shader
             Nodes.Add(Node);
         }
 
-        public ShaderIrLabel GetLabel(int Position)
+        public ShaderIrLabel GetLabel(long Position)
         {
             if (LabelsToInsert.TryGetValue(Position, out ShaderIrLabel Label))
             {
@@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.Gal.Shader
             return Label;
         }
 
-        public void MarkLabel(int Position)
+        public void MarkLabel(long Position)
         {
             if (LabelsToInsert.TryGetValue(Position, out ShaderIrLabel Label))
             {
diff --git a/Ryushader/Memory.cs b/Ryushader/Memory.cs
new file mode 100644
index 0000000000..ae336e72cb
--- /dev/null
+++ b/Ryushader/Memory.cs
@@ -0,0 +1,26 @@
+using Ryujinx.Graphics.Gal;
+using System.IO;
+
+namespace Ryushader
+{
+    class Memory : IGalMemory
+    {
+        private Stream BaseStream;
+
+        private BinaryReader Reader;
+
+        public Memory(Stream BaseStream)
+        {
+            this.BaseStream = BaseStream;
+
+            Reader = new BinaryReader(BaseStream);
+        }
+
+        public int ReadInt32(long Position)
+        {
+            BaseStream.Seek(Position, SeekOrigin.Begin);
+
+            return Reader.ReadInt32();
+        }
+    }
+}
diff --git a/Ryushader/Program.cs b/Ryushader/Program.cs
index 6fec744d69..9444be6d31 100644
--- a/Ryushader/Program.cs
+++ b/Ryushader/Program.cs
@@ -24,20 +24,14 @@ namespace Ryushader
                     case "f":  ShaderType = GalShaderType.Fragment;       break;
                 }
 
-                byte[] Data = File.ReadAllBytes(args[1]);
-
-                int[] Code = new int[Data.Length / 4];
-
-                for (int Offset = 0; Offset + 4 <= Data.Length; Offset += 4)
+                using (FileStream FS = new FileStream(args[1], FileMode.Open, FileAccess.Read))
                 {
-                    int Value = BitConverter.ToInt32(Data, Offset);
+                    Memory Mem = new Memory(FS);
 
-                    Code[Offset >> 2] = Value;
+                    GlslProgram Program = Decompiler.Decompile(Mem, 0, ShaderType);
+
+                    Console.WriteLine(Program.Code);
                 }
-
-                GlslProgram Program = Decompiler.Decompile(Code, ShaderType);
-
-                Console.WriteLine(Program.Code);
             }
             else
             {