Cache vertex and index data aswell, some cleanup

This commit is contained in:
gdkchan 2018-06-06 00:33:58 -03:00
parent e7a9b0a870
commit 197944f783
5 changed files with 127 additions and 97 deletions

View file

@ -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;

View file

@ -23,8 +23,6 @@ namespace Ryujinx.Core.Gpu
private HashSet<long> FrameBuffers;
private HashSet<long> ModifiedPages;
public NvGpuEngine3d(NvGpu Gpu)
{
this.Gpu = Gpu;
@ -57,8 +55,6 @@ namespace Ryujinx.Core.Gpu
}
FrameBuffers = new HashSet<long>();
ModifiedPages = new HashSet<long>();
}
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<GalVertexAttrib>[] Attribs = new List<GalVertexAttrib>[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);
}
}

View file

@ -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);

View file

@ -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<long, int> VboCache;
private Dictionary<long, int> IboCache;
private IbInfo IndexBuffer;
public OGLRasterizer()
{
VertexBuffers = new int[32];
VboCache = new Dictionary<long, int>();
IboCache = new Dictionary<long, int>();
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();
}
}
}
}

View file

@ -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)