From 197944f7839593802e48825394b5f06cb9b46ef5 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 6 Jun 2018 00:33:58 -0300 Subject: [PATCH] Cache vertex and index data aswell, some cleanup --- ChocolArm64/Memory/AMemoryWin32.cs | 6 ++ Ryujinx.Core/Gpu/NvGpuEngine3d.cs | 67 +++++++------ Ryujinx.Graphics/Gal/IGalRenderer.cs | 12 ++- Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs | 93 +++++++++++-------- Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs | 46 +++++---- 5 files changed, 127 insertions(+), 97 deletions(-) diff --git a/ChocolArm64/Memory/AMemoryWin32.cs b/ChocolArm64/Memory/AMemoryWin32.cs index c21c808d37..35b8f2d762 100644 --- a/ChocolArm64/Memory/AMemoryWin32.cs +++ b/ChocolArm64/Memory/AMemoryWin32.cs @@ -68,6 +68,12 @@ namespace ChocolArm64.Memory if (Count != 0) { + //We shouldn't reset pages that aren't being fully used, + //to prevent missing modifications to other parts of the + //page that may be accessed later. + //This rounds the size down to the nearest page-aligned size. + Size = (IntPtr)((long)Size & ~(Granularity - 1)); + ResetWriteWatch(Address, Size); return true; diff --git a/Ryujinx.Core/Gpu/NvGpuEngine3d.cs b/Ryujinx.Core/Gpu/NvGpuEngine3d.cs index ff2ce10364..1d59758776 100644 --- a/Ryujinx.Core/Gpu/NvGpuEngine3d.cs +++ b/Ryujinx.Core/Gpu/NvGpuEngine3d.cs @@ -23,8 +23,6 @@ namespace Ryujinx.Core.Gpu private HashSet FrameBuffers; - private HashSet ModifiedPages; - public NvGpuEngine3d(NvGpu Gpu) { this.Gpu = Gpu; @@ -57,8 +55,6 @@ namespace Ryujinx.Core.Gpu } FrameBuffers = new HashSet(); - - ModifiedPages = new HashSet(); } public void CallMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry) @@ -287,8 +283,6 @@ namespace Ryujinx.Core.Gpu if (NewTexture.Equals(Texture) && !Vmm.IsRegionModified(Tag, Size)) { - //System.Console.WriteLine("skip upload texture!"); - Gpu.Renderer.BindTexture(Tag, TexIndex); return; @@ -353,11 +347,16 @@ namespace Ryujinx.Core.Gpu if (IndexSize != 0) { - int BufferSize = IndexCount * IndexSize; + int IbSize = IndexCount * IndexSize; - byte[] Data = Vmm.ReadBytes(IndexPosition, BufferSize); + if (Vmm.IsRegionModified(IndexPosition, (uint)IbSize)) + { + byte[] Data = Vmm.ReadBytes(IndexPosition, IbSize); - Gpu.Renderer.SetIndexArray(Data, IndexFormat); + Gpu.Renderer.CreateIbo(IndexPosition, Data); + } + + Gpu.Renderer.SetIndexArray(IndexPosition, IbSize, IndexFormat); } List[] Attribs = new List[32]; @@ -382,10 +381,17 @@ namespace Ryujinx.Core.Gpu ((Packed >> 31) & 0x1) != 0)); } + int VertexFirst = ReadRegister(NvGpuEngine3dReg.VertexArrayFirst); + int VertexCount = ReadRegister(NvGpuEngine3dReg.VertexArrayCount); + + int PrimCtrl = ReadRegister(NvGpuEngine3dReg.VertexBeginGl); + for (int Index = 0; Index < 32; Index++) { - int VertexFirst = ReadRegister(NvGpuEngine3dReg.VertexArrayFirst); - int VertexCount = ReadRegister(NvGpuEngine3dReg.VertexArrayCount); + if (Attribs[Index] == null) + { + continue; + } int Control = ReadRegister(NvGpuEngine3dReg.VertexArrayNControl + Index * 4); @@ -401,35 +407,36 @@ namespace Ryujinx.Core.Gpu int Stride = Control & 0xfff; - long Size = 0; + long VbSize = 0; if (IndexCount != 0) { - Size = (VertexEndPos - VertexPosition) + 1; + VbSize = (VertexEndPos - VertexPosition) + 1; } else { - Size = VertexCount * Stride; + VbSize = VertexCount * Stride; } - byte[] Data = Vmm.ReadBytes(VertexPosition, Size); - - GalVertexAttrib[] AttribArray = Attribs[Index]?.ToArray() ?? new GalVertexAttrib[0]; - - Gpu.Renderer.SetVertexArray(Index, Stride, Data, AttribArray); - - int PrimCtrl = ReadRegister(NvGpuEngine3dReg.VertexBeginGl); - - GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff); - - if (IndexCount != 0) + if (Vmm.IsRegionModified(VertexPosition, VbSize)) { - Gpu.Renderer.DrawElements(Index, IndexFirst, PrimType); - } - else - { - Gpu.Renderer.DrawArrays(Index, VertexFirst, VertexCount, PrimType); + byte[] Data = Vmm.ReadBytes(VertexPosition, VbSize); + + Gpu.Renderer.CreateVbo(VertexPosition, Data); } + + Gpu.Renderer.SetVertexArray(Index, Stride, VertexPosition, Attribs[Index].ToArray()); + } + + GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff); + + if (IndexCount != 0) + { + Gpu.Renderer.DrawElements(IndexPosition, IndexFirst, PrimType); + } + else + { + Gpu.Renderer.DrawArrays(VertexFirst, VertexCount, PrimType); } } diff --git a/Ryujinx.Graphics/Gal/IGalRenderer.cs b/Ryujinx.Graphics/Gal/IGalRenderer.cs index 3535888983..9fc6f39d7d 100644 --- a/Ryujinx.Graphics/Gal/IGalRenderer.cs +++ b/Ryujinx.Graphics/Gal/IGalRenderer.cs @@ -49,13 +49,17 @@ namespace Ryujinx.Graphics.Gal //Rasterizer void ClearBuffers(int RtIndex, GalClearBufferFlags Flags); - void SetVertexArray(int VbIndex, int Stride, byte[] Buffer, GalVertexAttrib[] Attribs); + void CreateVbo(long Tag, byte[] Buffer); - void SetIndexArray(byte[] Buffer, GalIndexFormat Format); + void CreateIbo(long Tag, byte[] Buffer); - void DrawArrays(int VbIndex, int First, int PrimCount, GalPrimitiveType PrimType); + void SetVertexArray(int VbIndex, int Stride, long VboTag, GalVertexAttrib[] Attribs); - void DrawElements(int VbIndex, int First, GalPrimitiveType PrimType); + void SetIndexArray(long Tag, int Size, GalIndexFormat Format); + + void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType); + + void DrawElements(long IboTag, int First, GalPrimitiveType PrimType); //Shader void CreateShader(IGalMemory Memory, long Tag, GalShaderType Type); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs index 5b115446e7..b129a080b4 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs @@ -46,7 +46,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL private struct IbInfo { - public int IboHandle; public int Count; public DrawElementsType Type; @@ -56,12 +55,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL private int[] VertexBuffers; + private Dictionary VboCache; + private Dictionary IboCache; + private IbInfo IndexBuffer; public OGLRasterizer() { VertexBuffers = new int[32]; + VboCache = new Dictionary(); + IboCache = new Dictionary(); + IndexBuffer = new IbInfo(); } @@ -92,15 +97,49 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.Clear(Mask); } - public void SetVertexArray(int VbIndex, int Stride, byte[] Buffer, GalVertexAttrib[] Attribs) + public void CreateVbo(long Tag, byte[] Buffer) { - EnsureVbInitialized(VbIndex); + if (!VboCache.TryGetValue(Tag, out int Handle)) + { + Handle = GL.GenBuffer(); + + VboCache.Add(Tag, Handle); + } IntPtr Length = new IntPtr(Buffer.Length); - GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBuffers[VbIndex]); + GL.BindBuffer(BufferTarget.ArrayBuffer, Handle); GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); + } + + public void CreateIbo(long Tag, byte[] Buffer) + { + if (!IboCache.TryGetValue(Tag, out int Handle)) + { + Handle = GL.GenBuffer(); + + IboCache.Add(Tag, Handle); + } + + IntPtr Length = new IntPtr(Buffer.Length); + + GL.BindBuffer(BufferTarget.ElementArrayBuffer, Handle); + GL.BufferData(BufferTarget.ElementArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw); + GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); + } + + public void SetVertexArray(int VbIndex, int Stride, long VboTag, GalVertexAttrib[] Attribs) + { + if (!VboCache.TryGetValue(VboTag, out int VboHandle)) + { + return; + } + + if (VaoHandle == 0) + { + VaoHandle = GL.GenVertexArray(); + } GL.BindVertexArray(VaoHandle); @@ -108,7 +147,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL { GL.EnableVertexAttribArray(Attrib.Index); - GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBuffers[VbIndex]); + GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle); bool Unsigned = Attrib.Type == GalVertexAttribType.Unorm || @@ -139,22 +178,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.BindVertexArray(0); } - public void SetIndexArray(byte[] Buffer, GalIndexFormat Format) + public void SetIndexArray(long Tag, int Size, GalIndexFormat Format) { - EnsureIbInitialized(); - IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format); - IndexBuffer.Count = Buffer.Length >> (int)Format; - - IntPtr Length = new IntPtr(Buffer.Length); - - GL.BindBuffer(BufferTarget.ElementArrayBuffer, IndexBuffer.IboHandle); - GL.BufferData(BufferTarget.ElementArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw); - GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); + IndexBuffer.Count = Size >> (int)Format; } - public void DrawArrays(int VbIndex, int First, int PrimCount, GalPrimitiveType PrimType) + public void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType) { if (PrimCount == 0) { @@ -166,36 +197,20 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount); } - public void DrawElements(int VbIndex, int First, GalPrimitiveType PrimType) + public void DrawElements(long IboTag, int First, GalPrimitiveType PrimType) { + if (!IboCache.TryGetValue(IboTag, out int IboHandle)) + { + return; + } + PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType); GL.BindVertexArray(VaoHandle); - GL.BindBuffer(BufferTarget.ElementArrayBuffer, IndexBuffer.IboHandle); + GL.BindBuffer(BufferTarget.ElementArrayBuffer, IboHandle); GL.DrawElements(Mode, IndexBuffer.Count, IndexBuffer.Type, First); } - - private void EnsureVbInitialized(int VbIndex) - { - if (VaoHandle == 0) - { - VaoHandle = GL.GenVertexArray(); - } - - if (VertexBuffers[VbIndex] == 0) - { - VertexBuffers[VbIndex] = GL.GenBuffer(); - } - } - - private void EnsureIbInitialized() - { - if (IndexBuffer.IboHandle == 0) - { - IndexBuffer.IboHandle = GL.GenBuffer(); - } - } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs index e1260bf97b..6893270de6 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs @@ -156,46 +156,44 @@ namespace Ryujinx.Graphics.Gal.OpenGL ActionsQueue.Enqueue(() => Rasterizer.ClearBuffers(RtIndex, Flags)); } - public void SetVertexArray(int VbIndex, int Stride, byte[] Buffer, GalVertexAttrib[] Attribs) + public void CreateVbo(long Tag, byte[] Buffer) + { + ActionsQueue.Enqueue(() => Rasterizer.CreateVbo(Tag, Buffer)); + } + + public void CreateIbo(long Tag, byte[] Buffer) + { + ActionsQueue.Enqueue(() => Rasterizer.CreateIbo(Tag, Buffer)); + } + + public void SetVertexArray(int VbIndex, int Stride, long VboTag, GalVertexAttrib[] Attribs) { if ((uint)VbIndex > 31) { throw new ArgumentOutOfRangeException(nameof(VbIndex)); } - ActionsQueue.Enqueue(() => Rasterizer.SetVertexArray(VbIndex, Stride, - Buffer ?? throw new ArgumentNullException(nameof(Buffer)), - Attribs ?? throw new ArgumentNullException(nameof(Attribs)))); - } - - public void SetIndexArray(byte[] Buffer, GalIndexFormat Format) - { - if (Buffer == null) + if (Attribs == null) { - throw new ArgumentNullException(nameof(Buffer)); + throw new ArgumentNullException(nameof(Attribs)); } - ActionsQueue.Enqueue(() => Rasterizer.SetIndexArray(Buffer, Format)); + ActionsQueue.Enqueue(() => Rasterizer.SetVertexArray(VbIndex, Stride, VboTag, Attribs)); } - public void DrawArrays(int VbIndex, int First, int PrimCount, GalPrimitiveType PrimType) + public void SetIndexArray(long Tag, int Size, GalIndexFormat Format) { - if ((uint)VbIndex > 31) - { - throw new ArgumentOutOfRangeException(nameof(VbIndex)); - } - - ActionsQueue.Enqueue(() => Rasterizer.DrawArrays(VbIndex, First, PrimCount, PrimType)); + ActionsQueue.Enqueue(() => Rasterizer.SetIndexArray(Tag, Size, Format)); } - public void DrawElements(int VbIndex, int First, GalPrimitiveType PrimType) + public void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType) { - if ((uint)VbIndex > 31) - { - throw new ArgumentOutOfRangeException(nameof(VbIndex)); - } + ActionsQueue.Enqueue(() => Rasterizer.DrawArrays(First, PrimCount, PrimType)); + } - ActionsQueue.Enqueue(() => Rasterizer.DrawElements(VbIndex, First, PrimType)); + public void DrawElements(long IboTag, int First, GalPrimitiveType PrimType) + { + ActionsQueue.Enqueue(() => Rasterizer.DrawElements(IboTag, First, PrimType)); } public void CreateShader(IGalMemory Memory, long Tag, GalShaderType Type)