diff options
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/CacheByRange.cs')
-rw-r--r-- | Ryujinx.Graphics.Vulkan/CacheByRange.cs | 166 |
1 files changed, 162 insertions, 4 deletions
diff --git a/Ryujinx.Graphics.Vulkan/CacheByRange.cs b/Ryujinx.Graphics.Vulkan/CacheByRange.cs index c77e66ae..afd7140e 100644 --- a/Ryujinx.Graphics.Vulkan/CacheByRange.cs +++ b/Ryujinx.Graphics.Vulkan/CacheByRange.cs @@ -106,17 +106,125 @@ namespace Ryujinx.Graphics.Vulkan } } + struct TopologyConversionIndirectCacheKey : ICacheKey + { + private readonly TopologyConversionCacheKey _baseKey; + private readonly BufferHolder _indirectDataBuffer; + private readonly int _indirectDataOffset; + private readonly int _indirectDataSize; + + public TopologyConversionIndirectCacheKey( + VulkanRenderer gd, + IndexBufferPattern pattern, + int indexSize, + BufferHolder indirectDataBuffer, + int indirectDataOffset, + int indirectDataSize) + { + _baseKey = new TopologyConversionCacheKey(gd, pattern, indexSize); + _indirectDataBuffer = indirectDataBuffer; + _indirectDataOffset = indirectDataOffset; + _indirectDataSize = indirectDataSize; + } + + public bool KeyEqual(ICacheKey other) + { + return other is TopologyConversionIndirectCacheKey entry && + entry._baseKey.KeyEqual(_baseKey) && + entry._indirectDataBuffer == _indirectDataBuffer && + entry._indirectDataOffset == _indirectDataOffset && + entry._indirectDataSize == _indirectDataSize; + } + + public void SetBuffer(Auto<DisposableBuffer> buffer) + { + _baseKey.SetBuffer(buffer); + } + + public void Dispose() + { + _baseKey.Dispose(); + } + } + + struct IndirectDataCacheKey : ICacheKey + { + private IndexBufferPattern _pattern; + + public IndirectDataCacheKey(IndexBufferPattern pattern) + { + _pattern = pattern; + } + + public bool KeyEqual(ICacheKey other) + { + return other is IndirectDataCacheKey entry && entry._pattern == _pattern; + } + + public void Dispose() + { + } + } + + struct DrawCountCacheKey : ICacheKey + { + public bool KeyEqual(ICacheKey other) + { + return other is DrawCountCacheKey; + } + + public void Dispose() + { + } + } + + struct Dependency + { + private readonly BufferHolder _buffer; + private readonly int _offset; + private readonly int _size; + private readonly ICacheKey _key; + + public Dependency(BufferHolder buffer, int offset, int size, ICacheKey key) + { + _buffer = buffer; + _offset = offset; + _size = size; + _key = key; + } + + public void RemoveFromOwner() + { + _buffer.RemoveCachedConvertedBuffer(_offset, _size, _key); + } + } + struct CacheByRange<T> where T : IDisposable { private struct Entry { public ICacheKey Key; public T Value; + public List<Dependency> DependencyList; public Entry(ICacheKey key, T value) { Key = key; Value = value; + DependencyList = null; + } + + public void InvalidateDependencies() + { + if (DependencyList != null) + { + foreach (Dependency dependency in DependencyList) + { + dependency.RemoveFromOwner(); + } + + DependencyList.Clear(); + } } } @@ -129,6 +237,51 @@ namespace Ryujinx.Graphics.Vulkan entries.Add(new Entry(key, value)); } + public void AddDependency(int offset, int size, ICacheKey key, Dependency dependency) + { + List<Entry> entries = GetEntries(offset, size); + + for (int i = 0; i < entries.Count; i++) + { + Entry entry = entries[i]; + + if (entry.Key.KeyEqual(key)) + { + if (entry.DependencyList == null) + { + entry.DependencyList = new List<Dependency>(); + entries[i] = entry; + } + + entry.DependencyList.Add(dependency); + + break; + } + } + } + + public void Remove(int offset, int size, ICacheKey key) + { + List<Entry> entries = GetEntries(offset, size); + + for (int i = 0; i < entries.Count; i++) + { + Entry entry = entries[i]; + + if (entry.Key.KeyEqual(key)) + { + entries.RemoveAt(i--); + + DestroyEntry(entry); + } + } + + if (entries.Count == 0) + { + _ranges.Remove(PackRange(offset, size)); + } + } + public bool TryGetValue(int offset, int size, ICacheKey key, out T value) { List<Entry> entries = GetEntries(offset, size); @@ -155,8 +308,7 @@ namespace Ryujinx.Graphics.Vulkan { foreach (Entry entry in entries) { - entry.Key.Dispose(); - entry.Value.Dispose(); + DestroyEntry(entry); } } @@ -185,8 +337,7 @@ namespace Ryujinx.Graphics.Vulkan foreach (Entry entry in entries) { - entry.Key.Dispose(); - entry.Value.Dispose(); + DestroyEntry(entry); } (toRemove ??= new List<ulong>()).Add(range.Key); @@ -222,6 +373,13 @@ namespace Ryujinx.Graphics.Vulkan return value; } + private static void DestroyEntry(Entry entry) + { + entry.Key.Dispose(); + entry.Value?.Dispose(); + entry.InvalidateDependencies(); + } + private static ulong PackRange(int offset, int size) { return (uint)offset | ((ulong)size << 32); |