From 231fae1a4c97d7588655e9775f37c1dc9bd55fb0 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 8 Jun 2018 21:15:56 -0300 Subject: Texture/Vertex/Index data cache (#132) * Initial implementation of the texture cache * Cache vertex and index data aswell, some cleanup * Improve handling of the cache by storing cached ranges on a list for each page * Delete old data from the caches automatically, ensure that the cache is cleaned when the mapping/size changes, and some general cleanup --- Ryujinx.Core/Gpu/NvGpuEngine3d.cs | 88 ++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 29 deletions(-) (limited to 'Ryujinx.Core/Gpu/NvGpuEngine3d.cs') diff --git a/Ryujinx.Core/Gpu/NvGpuEngine3d.cs b/Ryujinx.Core/Gpu/NvGpuEngine3d.cs index b827debe..76d21f12 100644 --- a/Ryujinx.Core/Gpu/NvGpuEngine3d.cs +++ b/Ryujinx.Core/Gpu/NvGpuEngine3d.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace Ryujinx.Core.Gpu { - public class NvGpuEngine3d : INvGpuEngine + class NvGpuEngine3d : INvGpuEngine { public int[] Registers { get; private set; } @@ -261,6 +261,8 @@ namespace Ryujinx.Core.Gpu long TextureAddress = Vmm.ReadInt64(TicPosition + 4) & 0xffffffffffff; + long Tag = TextureAddress; + TextureAddress = Vmm.GetPhysicalAddress(TextureAddress); if (IsFrameBufferPosition(TextureAddress)) @@ -273,10 +275,25 @@ namespace Ryujinx.Core.Gpu } else { - GalTexture Texture = TextureFactory.MakeTexture(Gpu, Vmm, TicPosition); + GalTexture NewTexture = TextureFactory.MakeTexture(Vmm, TicPosition); + + long Size = (uint)TextureHelper.GetTextureSize(NewTexture); + + if (Gpu.Renderer.TryGetCachedTexture(Tag, Size, out GalTexture Texture)) + { + if (NewTexture.Equals(Texture) && !Vmm.IsRegionModified(Tag, Size, NvGpuBufferType.Texture)) + { + Gpu.Renderer.BindTexture(Tag, TexIndex); + + return; + } + } + + byte[] Data = TextureFactory.GetTextureData(Vmm, TicPosition); - Gpu.Renderer.SetTextureAndSampler(TexIndex, Texture, Sampler); - Gpu.Renderer.BindTexture(TexIndex); + Gpu.Renderer.SetTextureAndSampler(Tag, Data, NewTexture, Sampler); + + Gpu.Renderer.BindTexture(Tag, TexIndex); } } @@ -330,11 +347,18 @@ namespace Ryujinx.Core.Gpu if (IndexSize != 0) { - int BufferSize = IndexCount * IndexSize; + int IbSize = IndexCount * IndexSize; + + bool IboCached = Gpu.Renderer.IsIboCached(IndexPosition, (uint)IbSize); + + if (!IboCached || Vmm.IsRegionModified(IndexPosition, (uint)IbSize, NvGpuBufferType.Index)) + { + byte[] Data = Vmm.ReadBytes(IndexPosition, (uint)IbSize); - byte[] Data = Vmm.ReadBytes(IndexPosition, BufferSize); + Gpu.Renderer.CreateIbo(IndexPosition, Data); + } - Gpu.Renderer.SetIndexArray(Data, IndexFormat); + Gpu.Renderer.SetIndexArray(IndexPosition, IbSize, IndexFormat); } List[] Attribs = new List[32]; @@ -359,10 +383,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); @@ -378,39 +409,38 @@ 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; + VbSize = VertexCount * Stride; } - //TODO: Support cases where the Stride is 0. - //In this case, we need to use the size of the attribute. - Size *= Stride; + bool VboCached = Gpu.Renderer.IsVboCached(VertexPosition, VbSize); - byte[] Data = Vmm.ReadBytes(VertexPosition, Size); - - GalVertexAttrib[] AttribArray = Attribs[Index]?.ToArray() ?? new GalVertexAttrib[0]; + if (!VboCached || Vmm.IsRegionModified(VertexPosition, VbSize, NvGpuBufferType.Vertex)) + { + byte[] Data = Vmm.ReadBytes(VertexPosition, VbSize); - Gpu.Renderer.SetVertexArray(Index, Stride, Data, AttribArray); + Gpu.Renderer.CreateVbo(VertexPosition, Data); + } - int PrimCtrl = ReadRegister(NvGpuEngine3dReg.VertexBeginGl); + Gpu.Renderer.SetVertexArray(Index, Stride, VertexPosition, Attribs[Index].ToArray()); + } - GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff); + GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff); - if (IndexCount != 0) - { - Gpu.Renderer.DrawElements(Index, IndexFirst, PrimType); - } - else - { - Gpu.Renderer.DrawArrays(Index, VertexFirst, VertexCount, PrimType); - } + if (IndexCount != 0) + { + Gpu.Renderer.DrawElements(IndexPosition, IndexFirst, PrimType); + } + else + { + Gpu.Renderer.DrawArrays(VertexFirst, VertexCount, PrimType); } } -- cgit v1.2.3