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 UnlockCache();
|
||||
|
||||
void Create(long key, IntPtr hostAddress, long size);
|
||||
void Create(long key, byte[] data);
|
||||
void Create(long key, IntPtr hostAddress, int size);
|
||||
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,
|
||||
GalVertexAttribArray[] arrays);
|
||||
|
||||
bool IsVboCached(long key, long size);
|
||||
bool IsIboCached(long key, long size, out long vertexCount);
|
||||
|
||||
void CreateVbo(long Key, int DataSize, IntPtr HostAddress);
|
||||
void CreateVbo(long Key, byte[] Data);
|
||||
bool IsVboCached(long key, int size);
|
||||
bool IsIboCached(long key, int size, out long vertexCount);
|
||||
|
||||
void CreateVbo(long key, IntPtr hostAddress, int size);
|
||||
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 SetIndexArray(int Size, GalIndexFormat Format);
|
||||
|
|
|
@ -5,13 +5,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
{
|
||||
class OGLConstBuffer : IGalConstBuffer
|
||||
{
|
||||
private const long MaxConstBufferCacheSize = 64 * 1024 * 1024;
|
||||
|
||||
private OGLResourceCache<long, OGLStreamBuffer> Cache;
|
||||
private OGLResourceCache<int, OGLStreamBuffer> Cache;
|
||||
|
||||
public OGLConstBuffer()
|
||||
{
|
||||
Cache = new OGLResourceCache<long, OGLStreamBuffer>(DeleteBuffer, MaxConstBufferCacheSize);
|
||||
Cache = new OGLResourceCache<int, OGLStreamBuffer>(DeleteBuffer, OGLResourceLimits.ConstBufferLimit);
|
||||
}
|
||||
|
||||
private static void DeleteBuffer(OGLStreamBuffer Buffer)
|
||||
|
@ -29,19 +27,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
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)
|
||||
|
@ -58,7 +56,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
return false;
|
||||
}
|
||||
|
||||
private OGLStreamBuffer GetBuffer(long Key, long Size)
|
||||
private OGLStreamBuffer GetBuffer(long Key, int Size)
|
||||
{
|
||||
if (!Cache.TryReuseValue(Key, Size, out OGLStreamBuffer Buffer))
|
||||
{
|
||||
|
|
|
@ -75,9 +75,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
{ GalVertexAttribSize._11_11_10, VertexAttribPointerType.UnsignedInt10F11F11FRev }
|
||||
};
|
||||
|
||||
private const long MaxVertexBufferCacheSize = 128 * 1024 * 1024;
|
||||
private const long MaxIndexBufferCacheSize = 64 * 1024 * 1024;
|
||||
|
||||
private int[] VertexBuffers;
|
||||
|
||||
private struct CachedVao
|
||||
|
@ -99,7 +96,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
private OGLResourceCache<int, CachedVao> VaoCache;
|
||||
|
||||
private OGLResourceCache<long, OGLStreamBuffer> VboCache;
|
||||
private OGLResourceCache<int, OGLStreamBuffer> VboCache;
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -129,11 +126,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
{
|
||||
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();
|
||||
}
|
||||
|
@ -169,13 +166,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
public void ClearBuffers(
|
||||
GalClearBufferFlags Flags,
|
||||
int Attachment,
|
||||
float Red,
|
||||
float Green,
|
||||
float Blue,
|
||||
float Alpha,
|
||||
float Depth,
|
||||
int Stencil)
|
||||
int Attachment,
|
||||
float Red,
|
||||
float Green,
|
||||
float Blue,
|
||||
float Alpha,
|
||||
float Depth,
|
||||
int Stencil)
|
||||
{
|
||||
GL.ColorMask(
|
||||
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;
|
||||
|
||||
|
@ -523,19 +520,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
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);
|
||||
}
|
||||
|
||||
public void CreateVbo(long Key, byte[] Data)
|
||||
{
|
||||
GetVbo(Key, Data.Length).SetData(Data);
|
||||
GetVbo(key, size).SetData(hostAddress, size);
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -620,7 +617,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
return false;
|
||||
}
|
||||
|
||||
private OGLStreamBuffer GetVbo(long Key, long Size)
|
||||
private OGLStreamBuffer GetVbo(long Key, int Size)
|
||||
{
|
||||
if (!VboCache.TryReuseValue(Key, Size, out OGLStreamBuffer Buffer))
|
||||
{
|
||||
|
@ -632,7 +629,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
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))
|
||||
{
|
||||
|
|
|
@ -7,9 +7,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
class OGLResourceCache<TPoolKey, TValue>
|
||||
{
|
||||
private const int MinTimeDelta = 5 * 60000;
|
||||
private const int MinTimeDeltaPool = 2500;
|
||||
private const int MaxRemovalsPerRun = 10;
|
||||
|
||||
private const int DefaultMinTimeForPoolTransfer = 2500;
|
||||
|
||||
private class CacheBucket
|
||||
{
|
||||
public long Key { get; private set; }
|
||||
|
@ -21,18 +22,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
private Queue<Action> _deleteDeps;
|
||||
|
||||
public long DataSize { get; private set; }
|
||||
public int Size { get; private set; }
|
||||
|
||||
public long Timestamp { 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;
|
||||
PoolKey = poolKey;
|
||||
Value = value;
|
||||
DataSize = dataSize;
|
||||
Key = key;
|
||||
PoolKey = poolKey;
|
||||
Value = value;
|
||||
Size = size;
|
||||
|
||||
_deleteDeps = new Queue<Action>();
|
||||
}
|
||||
|
@ -82,14 +83,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
private bool _locked;
|
||||
|
||||
private long _maxSize;
|
||||
private long _totalSize;
|
||||
private int _maxSize;
|
||||
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>();
|
||||
|
||||
|
@ -120,7 +125,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
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)
|
||||
{
|
||||
|
@ -181,15 +186,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
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))
|
||||
{
|
||||
LinkedListNode<CacheBucket> node = queue.First;
|
||||
|
||||
CacheBucket bucket = node.Value;
|
||||
bucket = node.Value;
|
||||
|
||||
Remove(bucket);
|
||||
|
||||
AddOrUpdate(key, poolKey, bucket.Value, bucket.DataSize);
|
||||
AddOrUpdate(key, poolKey, bucket.Value, bucket.Size);
|
||||
|
||||
value = bucket.Value;
|
||||
|
||||
|
@ -201,11 +214,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
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))
|
||||
{
|
||||
size = bucket.DataSize;
|
||||
size = bucket.Size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -215,11 +228,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
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))
|
||||
{
|
||||
size = bucket.DataSize;
|
||||
size = bucket.Size;
|
||||
value = bucket.Value;
|
||||
|
||||
return true;
|
||||
|
@ -267,7 +280,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
long timeDelta = timestamp - bucket.Timestamp;
|
||||
|
||||
if (timeDelta <= MinTimeDeltaPool)
|
||||
if (timeDelta <= _minTimeForPoolTransfer)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -319,7 +332,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
bucket.DeleteAllDependencies();
|
||||
|
||||
_totalSize -= bucket.DataSize;
|
||||
_totalSize -= bucket.Size;
|
||||
}
|
||||
|
||||
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; }
|
||||
|
||||
public OGLStreamBuffer(BufferTarget Target, long Size)
|
||||
public OGLStreamBuffer(BufferTarget target, int size)
|
||||
{
|
||||
this.Target = Target;
|
||||
this.Size = Size;
|
||||
Target = target;
|
||||
Size = size;
|
||||
|
||||
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.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.BufferSubData(Target, IntPtr.Zero, (IntPtr)Data.Length, Data);
|
||||
GL.BufferSubData(Target, IntPtr.Zero, new IntPtr(buffer.Length), buffer);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
@ -42,9 +42,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
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);
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
{
|
||||
class OGLTexture : IGalTexture
|
||||
{
|
||||
private const long MaxTextureCacheSize = 768 * 1024 * 1024;
|
||||
|
||||
private struct ImageKey
|
||||
{
|
||||
public int Width { get; private set; }
|
||||
|
@ -48,9 +46,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
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()
|
||||
|
@ -90,7 +88,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
{
|
||||
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);
|
||||
|
@ -128,9 +126,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
const int Level = 0; //TODO: Support mipmap textures.
|
||||
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))
|
||||
{
|
||||
|
@ -195,9 +193,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
return;
|
||||
}
|
||||
|
||||
if (NewImage.Format == OldImage.Format &&
|
||||
NewImage.Width == OldImage.Width &&
|
||||
NewImage.Height == OldImage.Height)
|
||||
if (NewImage.Width == OldImage.Width &&
|
||||
NewImage.Height == OldImage.Height &&
|
||||
NewImage.Format == OldImage.Format)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -208,16 +206,22 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
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))
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
throw new ArgumentException(nameof(Key));
|
||||
}
|
||||
|
||||
(_, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(CachedImage.Format);
|
||||
|
|
|
@ -989,13 +989,13 @@ namespace Ryujinx.Graphics.Graphics3d
|
|||
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 (Vmm.TryGetHostAddress(VbPosition, VbSize, out IntPtr VbPtr))
|
||||
{
|
||||
Gpu.Renderer.Rasterizer.CreateVbo(VboKey, (int)VbSize, VbPtr);
|
||||
Gpu.Renderer.Rasterizer.CreateVbo(VboKey, VbPtr, (int)VbSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue