Make PBO cache actually work, also some style changes, use int instead of long for sizes
This commit is contained in:
parent
7c39c731e2
commit
b7c54a13d4
9 changed files with 128 additions and 98 deletions
|
@ -7,9 +7,9 @@ namespace Ryujinx.Graphics.Gal
|
||||||
void LockCache();
|
void LockCache();
|
||||||
void UnlockCache();
|
void UnlockCache();
|
||||||
|
|
||||||
void Create(long key, IntPtr hostAddress, long size);
|
void Create(long key, IntPtr hostAddress, int size);
|
||||||
void Create(long key, byte[] data);
|
void Create(long key, byte[] buffer);
|
||||||
|
|
||||||
bool IsCached(long Key, long Size);
|
bool IsCached(long Key, int Size);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -24,13 +24,13 @@ namespace Ryujinx.Graphics.Gal
|
||||||
GalVertexAttrib[] attributes,
|
GalVertexAttrib[] attributes,
|
||||||
GalVertexAttribArray[] arrays);
|
GalVertexAttribArray[] arrays);
|
||||||
|
|
||||||
bool IsVboCached(long key, long size);
|
bool IsVboCached(long key, int size);
|
||||||
bool IsIboCached(long key, long size, out long vertexCount);
|
bool IsIboCached(long key, int size, out long vertexCount);
|
||||||
|
|
||||||
void CreateVbo(long Key, int DataSize, IntPtr HostAddress);
|
|
||||||
void CreateVbo(long Key, byte[] Data);
|
|
||||||
|
|
||||||
|
void CreateVbo(long key, IntPtr hostAddress, int size);
|
||||||
void CreateIbo(long key, IntPtr hostAddress, int size, long vertexCount);
|
void CreateIbo(long key, IntPtr hostAddress, int size, long vertexCount);
|
||||||
|
|
||||||
|
void CreateVbo(long key, byte[] buffer);
|
||||||
void CreateIbo(long key, byte[] buffer, long vertexCount);
|
void CreateIbo(long key, byte[] buffer, long vertexCount);
|
||||||
|
|
||||||
void SetIndexArray(int Size, GalIndexFormat Format);
|
void SetIndexArray(int Size, GalIndexFormat Format);
|
||||||
|
|
|
@ -5,13 +5,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
class OGLConstBuffer : IGalConstBuffer
|
class OGLConstBuffer : IGalConstBuffer
|
||||||
{
|
{
|
||||||
private const long MaxConstBufferCacheSize = 64 * 1024 * 1024;
|
private OGLResourceCache<int, OGLStreamBuffer> Cache;
|
||||||
|
|
||||||
private OGLResourceCache<long, OGLStreamBuffer> Cache;
|
|
||||||
|
|
||||||
public OGLConstBuffer()
|
public OGLConstBuffer()
|
||||||
{
|
{
|
||||||
Cache = new OGLResourceCache<long, OGLStreamBuffer>(DeleteBuffer, MaxConstBufferCacheSize);
|
Cache = new OGLResourceCache<int, OGLStreamBuffer>(DeleteBuffer, OGLResourceLimits.ConstBufferLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DeleteBuffer(OGLStreamBuffer Buffer)
|
private static void DeleteBuffer(OGLStreamBuffer Buffer)
|
||||||
|
@ -29,19 +27,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
Cache.Unlock();
|
Cache.Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsCached(long key, long size)
|
public bool IsCached(long key, int size)
|
||||||
{
|
{
|
||||||
return Cache.TryGetSize(key, out long cbSize) && cbSize >= size;
|
return Cache.TryGetSize(key, out int cbSize) && cbSize >= size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Create(long key, IntPtr hostAddress, long size)
|
public void Create(long key, IntPtr hostAddress, int size)
|
||||||
{
|
{
|
||||||
GetBuffer(key, size).SetData(size, hostAddress);
|
GetBuffer(key, size).SetData(hostAddress, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Create(long key, byte[] data)
|
public void Create(long key, byte[] buffer)
|
||||||
{
|
{
|
||||||
GetBuffer(key, data.Length).SetData(data);
|
GetBuffer(key, buffer.Length).SetData(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetUbo(long key, out int uboHandle)
|
public bool TryGetUbo(long key, out int uboHandle)
|
||||||
|
@ -58,7 +56,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OGLStreamBuffer GetBuffer(long Key, long Size)
|
private OGLStreamBuffer GetBuffer(long Key, int Size)
|
||||||
{
|
{
|
||||||
if (!Cache.TryReuseValue(Key, Size, out OGLStreamBuffer Buffer))
|
if (!Cache.TryReuseValue(Key, Size, out OGLStreamBuffer Buffer))
|
||||||
{
|
{
|
||||||
|
|
|
@ -75,9 +75,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{ GalVertexAttribSize._11_11_10, VertexAttribPointerType.UnsignedInt10F11F11FRev }
|
{ GalVertexAttribSize._11_11_10, VertexAttribPointerType.UnsignedInt10F11F11FRev }
|
||||||
};
|
};
|
||||||
|
|
||||||
private const long MaxVertexBufferCacheSize = 128 * 1024 * 1024;
|
|
||||||
private const long MaxIndexBufferCacheSize = 64 * 1024 * 1024;
|
|
||||||
|
|
||||||
private int[] VertexBuffers;
|
private int[] VertexBuffers;
|
||||||
|
|
||||||
private struct CachedVao
|
private struct CachedVao
|
||||||
|
@ -99,7 +96,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
private OGLResourceCache<int, CachedVao> VaoCache;
|
private OGLResourceCache<int, CachedVao> VaoCache;
|
||||||
|
|
||||||
private OGLResourceCache<long, OGLStreamBuffer> VboCache;
|
private OGLResourceCache<int, OGLStreamBuffer> VboCache;
|
||||||
|
|
||||||
private class CachedIbo
|
private class CachedIbo
|
||||||
{
|
{
|
||||||
|
@ -113,7 +110,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private OGLResourceCache<long, CachedIbo> IboCache;
|
private OGLResourceCache<int, CachedIbo> IboCache;
|
||||||
|
|
||||||
private struct IbInfo
|
private struct IbInfo
|
||||||
{
|
{
|
||||||
|
@ -129,11 +126,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
VertexBuffers = new int[32];
|
VertexBuffers = new int[32];
|
||||||
|
|
||||||
VaoCache = new OGLResourceCache<int, CachedVao>(DeleteVao, 64 * 1024);
|
VaoCache = new OGLResourceCache<int, CachedVao>(DeleteVao, OGLResourceLimits.VertexArrayLimit);
|
||||||
|
|
||||||
VboCache = new OGLResourceCache<long, OGLStreamBuffer>(DeleteBuffer, MaxVertexBufferCacheSize);
|
VboCache = new OGLResourceCache<int, OGLStreamBuffer>(DeleteBuffer, OGLResourceLimits.VertexBufferLimit);
|
||||||
|
|
||||||
IboCache = new OGLResourceCache<long, CachedIbo>(DeleteIbo, MaxIndexBufferCacheSize);
|
IboCache = new OGLResourceCache<int, CachedIbo>(DeleteIbo, OGLResourceLimits.IndexBufferLimit);
|
||||||
|
|
||||||
IndexBuffer = new IbInfo();
|
IndexBuffer = new IbInfo();
|
||||||
}
|
}
|
||||||
|
@ -169,13 +166,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
public void ClearBuffers(
|
public void ClearBuffers(
|
||||||
GalClearBufferFlags Flags,
|
GalClearBufferFlags Flags,
|
||||||
int Attachment,
|
int Attachment,
|
||||||
float Red,
|
float Red,
|
||||||
float Green,
|
float Green,
|
||||||
float Blue,
|
float Blue,
|
||||||
float Alpha,
|
float Alpha,
|
||||||
float Depth,
|
float Depth,
|
||||||
int Stencil)
|
int Stencil)
|
||||||
{
|
{
|
||||||
GL.ColorMask(
|
GL.ColorMask(
|
||||||
Attachment,
|
Attachment,
|
||||||
|
@ -200,14 +197,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsVboCached(long key, long size)
|
public bool IsVboCached(long key, int size)
|
||||||
{
|
{
|
||||||
return VboCache.TryGetSize(key, out long vbSize) && vbSize >= size;
|
return VboCache.TryGetSize(key, out int vbSize) && vbSize >= size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsIboCached(long key, long size, out long vertexCount)
|
public bool IsIboCached(long key, int size, out long vertexCount)
|
||||||
{
|
{
|
||||||
if (IboCache.TryGetSizeAndValue(key, out long ibSize, out CachedIbo ibo) && ibSize >= size)
|
if (IboCache.TryGetSizeAndValue(key, out int ibSize, out CachedIbo ibo) && ibSize >= size)
|
||||||
{
|
{
|
||||||
vertexCount = ibo.VertexCount;
|
vertexCount = ibo.VertexCount;
|
||||||
|
|
||||||
|
@ -523,19 +520,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
throw new NotImplementedException("Unsupported size \"" + Attrib.Size + "\" on type \"" + Attrib.Type + "\"!");
|
throw new NotImplementedException("Unsupported size \"" + Attrib.Size + "\" on type \"" + Attrib.Type + "\"!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateVbo(long Key, int DataSize, IntPtr HostAddress)
|
public void CreateVbo(long key, IntPtr hostAddress, int size)
|
||||||
{
|
{
|
||||||
GetVbo(Key, DataSize).SetData(DataSize, HostAddress);
|
GetVbo(key, size).SetData(hostAddress, size);
|
||||||
}
|
|
||||||
|
|
||||||
public void CreateVbo(long Key, byte[] Data)
|
|
||||||
{
|
|
||||||
GetVbo(Key, Data.Length).SetData(Data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateIbo(long key, IntPtr hostAddress, int size, long vertexCount)
|
public void CreateIbo(long key, IntPtr hostAddress, int size, long vertexCount)
|
||||||
{
|
{
|
||||||
GetIbo(key, size, vertexCount).SetData(size, hostAddress);
|
GetIbo(key, size, vertexCount).SetData(hostAddress, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateVbo(long key, byte[] buffer)
|
||||||
|
{
|
||||||
|
GetVbo(key, buffer.Length).SetData(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateIbo(long key, byte[] buffer, long vertexCount)
|
public void CreateIbo(long key, byte[] buffer, long vertexCount)
|
||||||
|
@ -620,7 +617,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OGLStreamBuffer GetVbo(long Key, long Size)
|
private OGLStreamBuffer GetVbo(long Key, int Size)
|
||||||
{
|
{
|
||||||
if (!VboCache.TryReuseValue(Key, Size, out OGLStreamBuffer Buffer))
|
if (!VboCache.TryReuseValue(Key, Size, out OGLStreamBuffer Buffer))
|
||||||
{
|
{
|
||||||
|
@ -632,7 +629,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
return Buffer;
|
return Buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OGLStreamBuffer GetIbo(long Key, long Size, long VertexCount)
|
private OGLStreamBuffer GetIbo(long Key, int Size, long VertexCount)
|
||||||
{
|
{
|
||||||
if (!IboCache.TryReuseValue(Key, Size, out CachedIbo Ibo))
|
if (!IboCache.TryReuseValue(Key, Size, out CachedIbo Ibo))
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,9 +7,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
class OGLResourceCache<TPoolKey, TValue>
|
class OGLResourceCache<TPoolKey, TValue>
|
||||||
{
|
{
|
||||||
private const int MinTimeDelta = 5 * 60000;
|
private const int MinTimeDelta = 5 * 60000;
|
||||||
private const int MinTimeDeltaPool = 2500;
|
|
||||||
private const int MaxRemovalsPerRun = 10;
|
private const int MaxRemovalsPerRun = 10;
|
||||||
|
|
||||||
|
private const int DefaultMinTimeForPoolTransfer = 2500;
|
||||||
|
|
||||||
private class CacheBucket
|
private class CacheBucket
|
||||||
{
|
{
|
||||||
public long Key { get; private set; }
|
public long Key { get; private set; }
|
||||||
|
@ -21,18 +22,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
private Queue<Action> _deleteDeps;
|
private Queue<Action> _deleteDeps;
|
||||||
|
|
||||||
public long DataSize { get; private set; }
|
public int Size { get; private set; }
|
||||||
|
|
||||||
public long Timestamp { get; private set; }
|
public long Timestamp { get; private set; }
|
||||||
|
|
||||||
public bool Orphan { get; private set; }
|
public bool Orphan { get; private set; }
|
||||||
|
|
||||||
public CacheBucket(long key, TPoolKey poolKey, TValue value, long dataSize)
|
public CacheBucket(long key, TPoolKey poolKey, TValue value, int size)
|
||||||
{
|
{
|
||||||
Key = key;
|
Key = key;
|
||||||
PoolKey = poolKey;
|
PoolKey = poolKey;
|
||||||
Value = value;
|
Value = value;
|
||||||
DataSize = dataSize;
|
Size = size;
|
||||||
|
|
||||||
_deleteDeps = new Queue<Action>();
|
_deleteDeps = new Queue<Action>();
|
||||||
}
|
}
|
||||||
|
@ -82,14 +83,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
private bool _locked;
|
private bool _locked;
|
||||||
|
|
||||||
private long _maxSize;
|
private int _maxSize;
|
||||||
private long _totalSize;
|
private int _totalSize;
|
||||||
|
private int _minTimeForPoolTransfer;
|
||||||
|
|
||||||
public OGLResourceCache(Action<TValue> DeleteValueCallback, long MaxSize)
|
public OGLResourceCache(
|
||||||
|
Action<TValue> deleteValueCallback,
|
||||||
|
int maxSize,
|
||||||
|
int minTimeForPoolTransfer = DefaultMinTimeForPoolTransfer)
|
||||||
{
|
{
|
||||||
_maxSize = MaxSize;
|
_maxSize = maxSize;
|
||||||
|
|
||||||
_deleteValueCallback = DeleteValueCallback ?? throw new ArgumentNullException(nameof(DeleteValueCallback));
|
_deleteValueCallback = deleteValueCallback ?? throw new ArgumentNullException(nameof(deleteValueCallback));
|
||||||
|
|
||||||
_cache = new Dictionary<long, CacheBucket>();
|
_cache = new Dictionary<long, CacheBucket>();
|
||||||
|
|
||||||
|
@ -120,7 +125,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
ClearCacheIfNeeded();
|
ClearCacheIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddOrUpdate(long key, TPoolKey poolKey, TValue value, long size)
|
public void AddOrUpdate(long key, TPoolKey poolKey, TValue value, int size)
|
||||||
{
|
{
|
||||||
if (!_locked)
|
if (!_locked)
|
||||||
{
|
{
|
||||||
|
@ -181,15 +186,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
public bool TryReuseValue(long key, TPoolKey poolKey, out TValue value)
|
public bool TryReuseValue(long key, TPoolKey poolKey, out TValue value)
|
||||||
{
|
{
|
||||||
|
if (_cache.TryGetValue(key, out CacheBucket bucket) && bucket.PoolKey.Equals(poolKey))
|
||||||
|
{
|
||||||
|
//Value on key is already compatible, we don't need to do anything.
|
||||||
|
value = bucket.Value;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (_pool.TryGetValue(poolKey, out LinkedList<CacheBucket> queue))
|
if (_pool.TryGetValue(poolKey, out LinkedList<CacheBucket> queue))
|
||||||
{
|
{
|
||||||
LinkedListNode<CacheBucket> node = queue.First;
|
LinkedListNode<CacheBucket> node = queue.First;
|
||||||
|
|
||||||
CacheBucket bucket = node.Value;
|
bucket = node.Value;
|
||||||
|
|
||||||
Remove(bucket);
|
Remove(bucket);
|
||||||
|
|
||||||
AddOrUpdate(key, poolKey, bucket.Value, bucket.DataSize);
|
AddOrUpdate(key, poolKey, bucket.Value, bucket.Size);
|
||||||
|
|
||||||
value = bucket.Value;
|
value = bucket.Value;
|
||||||
|
|
||||||
|
@ -201,11 +214,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetSize(long key, out long size)
|
public bool TryGetSize(long key, out int size)
|
||||||
{
|
{
|
||||||
if (_cache.TryGetValue(key, out CacheBucket bucket))
|
if (_cache.TryGetValue(key, out CacheBucket bucket))
|
||||||
{
|
{
|
||||||
size = bucket.DataSize;
|
size = bucket.Size;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -215,11 +228,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetSizeAndValue(long key, out long size, out TValue value)
|
public bool TryGetSizeAndValue(long key, out int size, out TValue value)
|
||||||
{
|
{
|
||||||
if (_cache.TryGetValue(key, out CacheBucket bucket))
|
if (_cache.TryGetValue(key, out CacheBucket bucket))
|
||||||
{
|
{
|
||||||
size = bucket.DataSize;
|
size = bucket.Size;
|
||||||
value = bucket.Value;
|
value = bucket.Value;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -267,7 +280,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
long timeDelta = timestamp - bucket.Timestamp;
|
long timeDelta = timestamp - bucket.Timestamp;
|
||||||
|
|
||||||
if (timeDelta <= MinTimeDeltaPool)
|
if (timeDelta <= _minTimeForPoolTransfer)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -319,7 +332,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
bucket.DeleteAllDependencies();
|
bucket.DeleteAllDependencies();
|
||||||
|
|
||||||
_totalSize -= bucket.DataSize;
|
_totalSize -= bucket.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveFromSortedCache(LinkedListNode<CacheBucket> node)
|
private void RemoveFromSortedCache(LinkedListNode<CacheBucket> node)
|
||||||
|
|
18
Ryujinx.Graphics/Gal/OpenGL/OGLResourceLimits.cs
Normal file
18
Ryujinx.Graphics/Gal/OpenGL/OGLResourceLimits.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
{
|
||||||
|
static class OGLResourceLimits
|
||||||
|
{
|
||||||
|
private const int KB = 1024;
|
||||||
|
private const int MB = 1024 * KB;
|
||||||
|
|
||||||
|
public const int ConstBufferLimit = 64 * MB;
|
||||||
|
|
||||||
|
public const int VertexArrayLimit = 16384;
|
||||||
|
public const int VertexBufferLimit = 128 * MB;
|
||||||
|
public const int IndexBufferLimit = 64 * MB;
|
||||||
|
|
||||||
|
public const int TextureLimit = 768 * MB;
|
||||||
|
|
||||||
|
public const int PixelBufferLimit = 64 * MB;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,30 +11,30 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
protected BufferTarget Target { get; private set; }
|
protected BufferTarget Target { get; private set; }
|
||||||
|
|
||||||
public OGLStreamBuffer(BufferTarget Target, long Size)
|
public OGLStreamBuffer(BufferTarget target, int size)
|
||||||
{
|
{
|
||||||
this.Target = Target;
|
Target = target;
|
||||||
this.Size = Size;
|
Size = size;
|
||||||
|
|
||||||
Handle = GL.GenBuffer();
|
Handle = GL.GenBuffer();
|
||||||
|
|
||||||
GL.BindBuffer(Target, Handle);
|
GL.BindBuffer(target, Handle);
|
||||||
|
|
||||||
GL.BufferData(Target, (IntPtr)Size, IntPtr.Zero, BufferUsageHint.StreamDraw);
|
GL.BufferData(target, new IntPtr(size), IntPtr.Zero, BufferUsageHint.StreamDraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetData(long Size, IntPtr HostAddress)
|
public void SetData(IntPtr hostAddress, int size)
|
||||||
{
|
{
|
||||||
GL.BindBuffer(Target, Handle);
|
GL.BindBuffer(Target, Handle);
|
||||||
|
|
||||||
GL.BufferSubData(Target, IntPtr.Zero, (IntPtr)Size, HostAddress);
|
GL.BufferSubData(Target, IntPtr.Zero, new IntPtr(size), hostAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetData(byte[] Data)
|
public void SetData(byte[] buffer)
|
||||||
{
|
{
|
||||||
GL.BindBuffer(Target, Handle);
|
GL.BindBuffer(Target, Handle);
|
||||||
|
|
||||||
GL.BufferSubData(Target, IntPtr.Zero, (IntPtr)Data.Length, Data);
|
GL.BufferSubData(Target, IntPtr.Zero, new IntPtr(buffer.Length), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -42,9 +42,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool Disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (Disposing && Handle != 0)
|
if (disposing && Handle != 0)
|
||||||
{
|
{
|
||||||
GL.DeleteBuffer(Handle);
|
GL.DeleteBuffer(Handle);
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
class OGLTexture : IGalTexture
|
class OGLTexture : IGalTexture
|
||||||
{
|
{
|
||||||
private const long MaxTextureCacheSize = 768 * 1024 * 1024;
|
|
||||||
|
|
||||||
private struct ImageKey
|
private struct ImageKey
|
||||||
{
|
{
|
||||||
public int Width { get; private set; }
|
public int Width { get; private set; }
|
||||||
|
@ -48,9 +46,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
public OGLTexture()
|
public OGLTexture()
|
||||||
{
|
{
|
||||||
TextureCache = new OGLResourceCache<ImageKey, ImageHandler>(DeleteTexture, MaxTextureCacheSize);
|
TextureCache = new OGLResourceCache<ImageKey, ImageHandler>(DeleteTexture, OGLResourceLimits.TextureLimit);
|
||||||
|
|
||||||
PboCache = new OGLResourceCache<int, int>(GL.DeleteBuffer, 256);
|
PboCache = new OGLResourceCache<int, int>(GL.DeleteBuffer, OGLResourceLimits.PixelBufferLimit, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LockCache()
|
public void LockCache()
|
||||||
|
@ -90,7 +88,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
CachedImage = new ImageHandler(GL.GenTexture(), Image);
|
CachedImage = new ImageHandler(GL.GenTexture(), Image);
|
||||||
|
|
||||||
TextureCache.AddOrUpdate(Key, imageKey, CachedImage, (uint)Size);
|
TextureCache.AddOrUpdate(Key, imageKey, CachedImage, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle);
|
GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle);
|
||||||
|
@ -128,9 +126,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
const int Level = 0; //TODO: Support mipmap textures.
|
const int Level = 0; //TODO: Support mipmap textures.
|
||||||
const int Border = 0;
|
const int Border = 0;
|
||||||
|
|
||||||
ImageKey imgKey = new ImageKey(Image);
|
ImageKey imageKey = new ImageKey(Image);
|
||||||
|
|
||||||
TextureCache.AddOrUpdate(Key, imgKey, new ImageHandler(Handle, Image), (uint)Data.Length);
|
TextureCache.AddOrUpdate(Key, imageKey, new ImageHandler(Handle, Image), Data.Length);
|
||||||
|
|
||||||
if (ImageUtils.IsCompressed(Image.Format) && !IsAstc(Image.Format))
|
if (ImageUtils.IsCompressed(Image.Format) && !IsAstc(Image.Format))
|
||||||
{
|
{
|
||||||
|
@ -195,9 +193,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NewImage.Format == OldImage.Format &&
|
if (NewImage.Width == OldImage.Width &&
|
||||||
NewImage.Width == OldImage.Width &&
|
NewImage.Height == OldImage.Height &&
|
||||||
NewImage.Height == OldImage.Height)
|
NewImage.Format == OldImage.Format)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -208,16 +206,22 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
if (!PboCache.TryReuseValue(0, BufferSize, out int Handle))
|
if (!PboCache.TryReuseValue(0, BufferSize, out int Handle))
|
||||||
{
|
{
|
||||||
PboCache.AddOrUpdate(0, BufferSize, Handle = GL.GenBuffer(), BufferSize);
|
Handle = GL.GenBuffer();
|
||||||
|
|
||||||
|
GL.BindBuffer(BufferTarget.PixelPackBuffer, Handle);
|
||||||
|
|
||||||
|
GL.BufferData(BufferTarget.PixelPackBuffer, BufferSize, IntPtr.Zero, BufferUsageHint.StreamCopy);
|
||||||
|
|
||||||
|
PboCache.AddOrUpdate(0, BufferSize, Handle, BufferSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL.BindBuffer(BufferTarget.PixelPackBuffer, Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.PixelPackBuffer, Handle);
|
|
||||||
|
|
||||||
GL.BufferData(BufferTarget.PixelPackBuffer, BufferSize, IntPtr.Zero, BufferUsageHint.StreamCopy);
|
|
||||||
|
|
||||||
if (!TryGetImageHandler(Key, out ImageHandler CachedImage))
|
if (!TryGetImageHandler(Key, out ImageHandler CachedImage))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new ArgumentException(nameof(Key));
|
||||||
}
|
}
|
||||||
|
|
||||||
(_, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(CachedImage.Format);
|
(_, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(CachedImage.Format);
|
||||||
|
|
|
@ -989,13 +989,13 @@ namespace Ryujinx.Graphics.Graphics3d
|
||||||
VbSize = MaxVbSize;
|
VbSize = MaxVbSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VboCached = Gpu.Renderer.Rasterizer.IsVboCached(VboKey, VbSize);
|
bool VboCached = Gpu.Renderer.Rasterizer.IsVboCached(VboKey, (int)VbSize);
|
||||||
|
|
||||||
if (Gpu.ResourceManager.MemoryRegionModified(Vmm, VboKey, VbSize, NvGpuBufferType.Vertex) || !VboCached)
|
if (Gpu.ResourceManager.MemoryRegionModified(Vmm, VboKey, VbSize, NvGpuBufferType.Vertex) || !VboCached)
|
||||||
{
|
{
|
||||||
if (Vmm.TryGetHostAddress(VbPosition, VbSize, out IntPtr VbPtr))
|
if (Vmm.TryGetHostAddress(VbPosition, VbSize, out IntPtr VbPtr))
|
||||||
{
|
{
|
||||||
Gpu.Renderer.Rasterizer.CreateVbo(VboKey, (int)VbSize, VbPtr);
|
Gpu.Renderer.Rasterizer.CreateVbo(VboKey, VbPtr, (int)VbSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue