diff --git a/Ryujinx.Graphics/Gal/IGalShader.cs b/Ryujinx.Graphics/Gal/IGalShader.cs index 3857189909..63bc086f36 100644 --- a/Ryujinx.Graphics/Gal/IGalShader.cs +++ b/Ryujinx.Graphics/Gal/IGalShader.cs @@ -4,7 +4,9 @@ namespace Ryujinx.Graphics.Gal { public interface IGalShader { - void Create(long Key, byte[] BinaryA, byte[] BinaryB, GalShaderType Type); + void Create(long KeyA, long KeyB, byte[] BinaryA, byte[] BinaryB, GalShaderType Type); + + bool TryGetSize(long Key, out long Size); IEnumerable GetConstBufferUsage(long Key); IEnumerable GetTextureUsage(long Key); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs index 1e70ed0b18..124e07e6d1 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs @@ -19,6 +19,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL private Dictionary TopStages; + private Dictionary TopStageSizes; + private Dictionary Programs; public int CurrentProgramHandle { get; private set; } @@ -35,15 +37,20 @@ namespace Ryujinx.Graphics.Gal.OpenGL TopStages = new Dictionary(); + TopStageSizes = new Dictionary(); + Programs = new Dictionary(); } public void Create( - long Key, + long KeyA, + long KeyB, byte[] BinaryA, byte[] BinaryB, GalShaderType Type) { + long Key = KeyB; + if (Stages.TryGetValue(Key, out List Cache)) { OGLShaderStage CachedStage = Cache.Find((OGLShaderStage Stage) => Stage.EqualsBinary(BinaryA, BinaryB)); @@ -91,6 +98,25 @@ namespace Ryujinx.Graphics.Gal.OpenGL Cache.Add(NewStage); TopStages[Key] = NewStage; + + if (BinaryA != null) + { + TopStageSizes[KeyA] = BinaryA.Length; + } + + TopStageSizes[KeyB] = BinaryB.Length; + } + + public bool TryGetSize(long Key, out long Size) + { + if (TopStageSizes.TryGetValue(Key, out Size)) + { + return true; + } + + Size = 0; + + return false; } public IEnumerable GetConstBufferUsage(long Key) diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs index 8a0feb605f..62bd853c22 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; namespace Ryujinx.Graphics.Gal.Shader @@ -138,7 +139,7 @@ namespace Ryujinx.Graphics.Gal.Shader continue; } - long OpCode = ReadQWord(Binary, Position); + long OpCode = BitConverter.ToInt64(Binary, (int)Position); Position += 8; @@ -199,18 +200,5 @@ namespace Ryujinx.Graphics.Gal.Shader return Op.Inst != ShaderIrInst.Exit && Op.Inst != ShaderIrInst.Bra; } - - private static unsafe long ReadQWord(byte[] Bytes, long Position) - { - if (Position >= Bytes.Length) - { - throw new System.InvalidOperationException(); - } - - fixed (byte* Pointer = Bytes) - { - return *((long*)(Pointer + Position)); - } - } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderHeader.cs b/Ryujinx.Graphics/Gal/Shader/ShaderHeader.cs index b52fb08427..9ed77ad031 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderHeader.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderHeader.cs @@ -61,11 +61,11 @@ namespace Ryujinx.Graphics.Gal.Shader public unsafe ShaderHeader(byte[] Binary) { - uint CommonWord0 = ReadWord(Binary, 0); - uint CommonWord1 = ReadWord(Binary, 4); - uint CommonWord2 = ReadWord(Binary, 8); - uint CommonWord3 = ReadWord(Binary, 12); - uint CommonWord4 = ReadWord(Binary, 16); + uint CommonWord0 = BitConverter.ToUInt32(Binary, 0); + uint CommonWord1 = BitConverter.ToUInt32(Binary, 4); + uint CommonWord2 = BitConverter.ToUInt32(Binary, 8); + uint CommonWord3 = BitConverter.ToUInt32(Binary, 12); + uint CommonWord4 = BitConverter.ToUInt32(Binary, 16); SphType = ReadBits(CommonWord0, 0, 5); Version = ReadBits(CommonWord0, 5, 5); @@ -92,8 +92,8 @@ namespace Ryujinx.Graphics.Gal.Shader StoreReqEnd = ReadBits(CommonWord4, 24, 8); //Type 2 (fragment?) reading - uint Type2OmapTarget = ReadWord(Binary, 72); - uint Type2Omap = ReadWord(Binary, 76); + uint Type2OmapTarget = BitConverter.ToUInt32(Binary, 72); + uint Type2Omap = BitConverter.ToUInt32(Binary, 76); OmapTargets = new OmapTarget[8]; @@ -136,14 +136,6 @@ namespace Ryujinx.Graphics.Gal.Shader } } - private static unsafe uint ReadWord(byte[] Bytes, long Position) - { - fixed (byte* Pointer = Bytes) - { - return *((uint*)(Pointer + Position)); - } - } - private static int ReadBits(uint Word, int Offset, int BitWidth) { uint Mask = (1u << BitWidth) - 1u; diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs index 74746ac35d..6c888d55fe 100644 --- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs +++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs @@ -29,8 +29,6 @@ namespace Ryujinx.HLE.Gpu.Engines private int CurrentInstance = 0; - private Dictionary ShadersSize; - public NvGpuEngine3d(NvGpu Gpu) { this.Gpu = Gpu; @@ -70,8 +68,6 @@ namespace Ryujinx.HLE.Gpu.Engines { UploadedKeys[i] = new List(); } - - ShadersSize = new Dictionary(); } public void CallMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry) @@ -279,7 +275,7 @@ namespace Ryujinx.HLE.Gpu.Engines byte[] BinaryA = ReadShaderBinary(Vmm, VpAPos); byte[] BinaryB = ReadShaderBinary(Vmm, VpBPos); - Gpu.Renderer.Shader.Create(VpBPos, BinaryA, BinaryB, GalShaderType.Vertex); + Gpu.Renderer.Shader.Create(VpAPos, VpBPos, BinaryA, BinaryB, GalShaderType.Vertex); } Gpu.Renderer.Shader.Bind(VpBPos); @@ -312,7 +308,7 @@ namespace Ryujinx.HLE.Gpu.Engines { byte[] Binary = ReadShaderBinary(Vmm, Key); - Gpu.Renderer.Shader.Create(Key, null, Binary, Type); + Gpu.Renderer.Shader.Create(0, Key, null, Binary, Type); } Gpu.Renderer.Shader.Bind(Key); @@ -892,7 +888,7 @@ namespace Ryujinx.HLE.Gpu.Engines { long Address = Vmm.GetPhysicalAddress(Key); - if (ShadersSize.TryGetValue(Address, out long Size)) + if (Gpu.Renderer.Shader.TryGetSize(Address, out long Size)) { if (!QueryKeyUpload(Vmm, Address, Size, NvGpuBufferType.Shader)) { @@ -909,8 +905,6 @@ namespace Ryujinx.HLE.Gpu.Engines long Address = Vmm.GetPhysicalAddress(Key); - ShadersSize[Address] = Size; - return Vmm.ReadBytes(Key, Size); }