aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Core/Gpu/NvGpuEngine3d.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-06-08 21:15:56 -0300
committerGitHub <noreply@github.com>2018-06-08 21:15:56 -0300
commit231fae1a4c97d7588655e9775f37c1dc9bd55fb0 (patch)
tree1c0e7b298ec33d5bf5b6a5693dd69a8c7e0bd23b /Ryujinx.Core/Gpu/NvGpuEngine3d.cs
parent6fe51f970501fe732276c17ed0dacb564b92a73d (diff)
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
Diffstat (limited to 'Ryujinx.Core/Gpu/NvGpuEngine3d.cs')
-rw-r--r--Ryujinx.Core/Gpu/NvGpuEngine3d.cs88
1 files changed, 59 insertions, 29 deletions
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<GalVertexAttrib>[] Attribs = new List<GalVertexAttrib>[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);
}
}