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
This commit is contained in:
gdkchan 2018-06-08 21:15:56 -03:00 committed by GitHub
parent 6fe51f9705
commit 231fae1a4c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 837 additions and 819 deletions

View file

@ -44,24 +44,29 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ GalVertexAttribSize._11_11_10, VertexAttribPointerType.Int } //?
};
private int VaoHandle;
private int[] VertexBuffers;
private OGLCachedResource<int> VboCache;
private OGLCachedResource<int> IboCache;
private struct IbInfo
{
public int IboHandle;
public int Count;
public DrawElementsType Type;
}
private int VaoHandle;
private int[] VertexBuffers;
private IbInfo IndexBuffer;
public OGLRasterizer()
{
VertexBuffers = new int[32];
VboCache = new OGLCachedResource<int>(GL.DeleteBuffer);
IboCache = new OGLCachedResource<int>(GL.DeleteBuffer);
IndexBuffer = new IbInfo();
}
@ -92,15 +97,53 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.Clear(Mask);
}
public void SetVertexArray(int VbIndex, int Stride, byte[] Buffer, GalVertexAttrib[] Attribs)
public bool IsVboCached(long Tag, long DataSize)
{
EnsureVbInitialized(VbIndex);
return VboCache.TryGetSize(Tag, out long Size) && Size == DataSize;
}
public bool IsIboCached(long Tag, long DataSize)
{
return IboCache.TryGetSize(Tag, out long Size) && Size == DataSize;
}
public void CreateVbo(long Tag, byte[] Buffer)
{
int Handle = GL.GenBuffer();
VboCache.AddOrUpdate(Tag, Handle, (uint)Buffer.Length);
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)
{
int Handle = GL.GenBuffer();
IboCache.AddOrUpdate(Tag, Handle, (uint)Buffer.Length);
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 +151,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 +182,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 +201,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();
}
}
}
}