Add locking methods to the ogl resource cache (#238)
* Add locking methods to the ogl resource cache * Remove some unused arguments * Add the ZF32 texture format
This commit is contained in:
parent
791fe70810
commit
1968386808
10 changed files with 122 additions and 26 deletions
|
@ -17,6 +17,7 @@ namespace Ryujinx.Graphics.Gal
|
|||
BC3 = 0x26,
|
||||
BC4 = 0x27,
|
||||
BC5 = 0x28,
|
||||
ZF32 = 0x2f,
|
||||
Astc2D4x4 = 0x40,
|
||||
Astc2D5x5 = 0x41,
|
||||
Astc2D6x6 = 0x42,
|
||||
|
|
|
@ -2,6 +2,9 @@ namespace Ryujinx.Graphics.Gal
|
|||
{
|
||||
public interface IGalRasterizer
|
||||
{
|
||||
void LockCaches();
|
||||
void UnlockCaches();
|
||||
|
||||
void ClearBuffers(GalClearBufferFlags Flags);
|
||||
|
||||
bool IsVboCached(long Key, long DataSize);
|
||||
|
@ -46,9 +49,9 @@ namespace Ryujinx.Graphics.Gal
|
|||
|
||||
void CreateIbo(long Key, byte[] Buffer);
|
||||
|
||||
void SetVertexArray(int VbIndex, int Stride, long VboKey, GalVertexAttrib[] Attribs);
|
||||
void SetVertexArray(int Stride, long VboKey, GalVertexAttrib[] Attribs);
|
||||
|
||||
void SetIndexArray(long Key, int Size, GalIndexFormat Format);
|
||||
void SetIndexArray(int Size, GalIndexFormat Format);
|
||||
|
||||
void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType);
|
||||
|
||||
|
|
|
@ -2,6 +2,9 @@ namespace Ryujinx.Graphics.Gal
|
|||
{
|
||||
public interface IGalTexture
|
||||
{
|
||||
void LockCache();
|
||||
void UnlockCache();
|
||||
|
||||
void Create(long Key, byte[] Data, GalTexture Texture);
|
||||
|
||||
bool TryGetCachedTexture(long Key, long DataSize, out GalTexture Texture);
|
||||
|
|
|
@ -36,6 +36,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
private DeleteValue DeleteValueCallback;
|
||||
|
||||
private Queue<T> DeletePending;
|
||||
|
||||
private bool Locked;
|
||||
|
||||
public OGLCachedResource(DeleteValue DeleteValueCallback)
|
||||
{
|
||||
if (DeleteValueCallback == null)
|
||||
|
@ -48,19 +52,48 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
Cache = new Dictionary<long, CacheBucket>();
|
||||
|
||||
SortedCache = new LinkedList<long>();
|
||||
|
||||
DeletePending = new Queue<T>();
|
||||
}
|
||||
|
||||
public void Lock()
|
||||
{
|
||||
Locked = true;
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
Locked = false;
|
||||
|
||||
while (DeletePending.TryDequeue(out T Value))
|
||||
{
|
||||
DeleteValueCallback(Value);
|
||||
}
|
||||
|
||||
ClearCacheIfNeeded();
|
||||
}
|
||||
|
||||
public void AddOrUpdate(long Key, T Value, long Size)
|
||||
{
|
||||
if (!Locked)
|
||||
{
|
||||
ClearCacheIfNeeded();
|
||||
}
|
||||
|
||||
LinkedListNode<long> Node = SortedCache.AddLast(Key);
|
||||
|
||||
CacheBucket NewBucket = new CacheBucket(Value, Size, Node);
|
||||
|
||||
if (Cache.TryGetValue(Key, out CacheBucket Bucket))
|
||||
{
|
||||
if (Locked)
|
||||
{
|
||||
DeletePending.Enqueue(Bucket.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteValueCallback(Bucket.Value);
|
||||
}
|
||||
|
||||
SortedCache.Remove(Bucket.Node);
|
||||
|
||||
|
@ -78,6 +111,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
{
|
||||
Value = Bucket.Value;
|
||||
|
||||
SortedCache.Remove(Bucket.Node);
|
||||
|
||||
LinkedListNode<long> Node = SortedCache.AddLast(Key);
|
||||
|
||||
Cache[Key] = new CacheBucket(Value, Bucket.DataSize, Node);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -138,6 +138,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
case GalTextureFormat.G8R8: return (PixelFormat.Rg, PixelType.UnsignedByte);
|
||||
case GalTextureFormat.R16: return (PixelFormat.Red, PixelType.HalfFloat);
|
||||
case GalTextureFormat.R8: return (PixelFormat.Red, PixelType.UnsignedByte);
|
||||
case GalTextureFormat.ZF32: return (PixelFormat.DepthComponent, PixelType.Float);
|
||||
}
|
||||
|
||||
throw new NotImplementedException(Format.ToString());
|
||||
|
|
|
@ -71,6 +71,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
IndexBuffer = new IbInfo();
|
||||
}
|
||||
|
||||
public void LockCaches()
|
||||
{
|
||||
VboCache.Lock();
|
||||
IboCache.Lock();
|
||||
}
|
||||
|
||||
public void UnlockCaches()
|
||||
{
|
||||
VboCache.Unlock();
|
||||
IboCache.Unlock();
|
||||
}
|
||||
|
||||
public void ClearBuffers(GalClearBufferFlags Flags)
|
||||
{
|
||||
ClearBufferMask Mask = ClearBufferMask.ColorBufferBit;
|
||||
|
@ -223,7 +235,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
GL.BufferData(BufferTarget.ElementArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
|
||||
}
|
||||
|
||||
public void SetVertexArray(int VbIndex, int Stride, long VboKey, GalVertexAttrib[] Attribs)
|
||||
public void SetVertexArray(int Stride, long VboKey, GalVertexAttrib[] Attribs)
|
||||
{
|
||||
if (!VboCache.TryGetValue(VboKey, out int VboHandle))
|
||||
{
|
||||
|
@ -270,7 +282,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
}
|
||||
}
|
||||
|
||||
public void SetIndexArray(long Key, int Size, GalIndexFormat Format)
|
||||
public void SetIndexArray(int Size, GalIndexFormat Format)
|
||||
{
|
||||
IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format);
|
||||
|
||||
|
|
|
@ -26,6 +26,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
TextureCache = new OGLCachedResource<TCE>(DeleteTexture);
|
||||
}
|
||||
|
||||
public void LockCache()
|
||||
{
|
||||
TextureCache.Lock();
|
||||
}
|
||||
|
||||
public void UnlockCache()
|
||||
{
|
||||
TextureCache.Unlock();
|
||||
}
|
||||
|
||||
private static void DeleteTexture(TCE CachedTexture)
|
||||
{
|
||||
GL.DeleteTexture(CachedTexture.Handle);
|
||||
|
|
|
@ -73,6 +73,8 @@ namespace Ryujinx.HLE.Gpu.Engines
|
|||
|
||||
private void VertexEndGl(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
|
||||
{
|
||||
LockCaches();
|
||||
|
||||
SetFrameBuffer(Vmm, 0);
|
||||
|
||||
long[] Keys = UploadShaders(Vmm);
|
||||
|
@ -90,6 +92,20 @@ namespace Ryujinx.HLE.Gpu.Engines
|
|||
UploadTextures(Vmm, Keys);
|
||||
UploadUniforms(Vmm);
|
||||
UploadVertexArrays(Vmm);
|
||||
|
||||
UnlockCaches();
|
||||
}
|
||||
|
||||
private void LockCaches()
|
||||
{
|
||||
Gpu.Renderer.Rasterizer.LockCaches();
|
||||
Gpu.Renderer.Texture.LockCache();
|
||||
}
|
||||
|
||||
private void UnlockCaches()
|
||||
{
|
||||
Gpu.Renderer.Rasterizer.UnlockCaches();
|
||||
Gpu.Renderer.Texture.UnlockCache();
|
||||
}
|
||||
|
||||
private void ClearBuffers(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
|
||||
|
@ -570,7 +586,7 @@ namespace Ryujinx.HLE.Gpu.Engines
|
|||
Gpu.Renderer.Rasterizer.CreateIbo(IboKey, Data);
|
||||
}
|
||||
|
||||
Gpu.Renderer.Rasterizer.SetIndexArray(IboKey, IbSize, IndexFormat);
|
||||
Gpu.Renderer.Rasterizer.SetIndexArray(IbSize, IndexFormat);
|
||||
}
|
||||
|
||||
List<GalVertexAttrib>[] Attribs = new List<GalVertexAttrib>[32];
|
||||
|
@ -634,7 +650,7 @@ namespace Ryujinx.HLE.Gpu.Engines
|
|||
Gpu.Renderer.Rasterizer.CreateVbo(VboKey, Data);
|
||||
}
|
||||
|
||||
Gpu.Renderer.Rasterizer.SetVertexArray(Index, Stride, VboKey, Attribs[Index].ToArray());
|
||||
Gpu.Renderer.Rasterizer.SetVertexArray(Stride, VboKey, Attribs[Index].ToArray());
|
||||
}
|
||||
|
||||
GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff);
|
||||
|
|
|
@ -28,15 +28,25 @@ namespace Ryujinx.HLE.Gpu.Texture
|
|||
{
|
||||
switch (Texture.Format)
|
||||
{
|
||||
case GalTextureFormat.R32G32B32A32: return Texture.Width * Texture.Height * 16;
|
||||
case GalTextureFormat.R16G16B16A16: return Texture.Width * Texture.Height * 8;
|
||||
case GalTextureFormat.A8B8G8R8: return Texture.Width * Texture.Height * 4;
|
||||
case GalTextureFormat.R32: return Texture.Width * Texture.Height * 4;
|
||||
case GalTextureFormat.A1B5G5R5: return Texture.Width * Texture.Height * 2;
|
||||
case GalTextureFormat.B5G6R5: return Texture.Width * Texture.Height * 2;
|
||||
case GalTextureFormat.G8R8: return Texture.Width * Texture.Height * 2;
|
||||
case GalTextureFormat.R16: return Texture.Width * Texture.Height * 2;
|
||||
case GalTextureFormat.R8: return Texture.Width * Texture.Height;
|
||||
case GalTextureFormat.R32G32B32A32:
|
||||
return Texture.Width * Texture.Height * 16;
|
||||
|
||||
case GalTextureFormat.R16G16B16A16:
|
||||
return Texture.Width * Texture.Height * 8;
|
||||
|
||||
case GalTextureFormat.A8B8G8R8:
|
||||
case GalTextureFormat.R32:
|
||||
case GalTextureFormat.ZF32:
|
||||
return Texture.Width * Texture.Height * 4;
|
||||
|
||||
case GalTextureFormat.A1B5G5R5:
|
||||
case GalTextureFormat.B5G6R5:
|
||||
case GalTextureFormat.G8R8:
|
||||
case GalTextureFormat.R16:
|
||||
return Texture.Width * Texture.Height * 2;
|
||||
|
||||
case GalTextureFormat.R8:
|
||||
return Texture.Width * Texture.Height;
|
||||
|
||||
case GalTextureFormat.BC1:
|
||||
case GalTextureFormat.BC4:
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
|||
case GalTextureFormat.BC3: return Read16Bpt4x4(Memory, Texture);
|
||||
case GalTextureFormat.BC4: return Read8Bpt4x4 (Memory, Texture);
|
||||
case GalTextureFormat.BC5: return Read16Bpt4x4(Memory, Texture);
|
||||
case GalTextureFormat.ZF32: return Read4Bpp (Memory, Texture);
|
||||
case GalTextureFormat.Astc2D4x4: return Read16Bpt4x4(Memory, Texture);
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue