aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Vulkan/CacheByRange.cs
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2022-09-09 00:30:19 +0100
committerGitHub <noreply@github.com>2022-09-08 20:30:19 -0300
commitc6d82209abeacd2336cde99e5a02b4596e70da83 (patch)
tree8dc8e1055f402c07e6ed9e4ff247ca420729808c /Ryujinx.Graphics.Vulkan/CacheByRange.cs
parentee1825219b8ccca13df7198d4e9ffb966e44c883 (diff)
Restride vertex buffer when stride causes attributes to misalign in Vulkan. (#3679)1.1.254
* Vertex Buffer Alignment part 1 * Update CacheByRange * Add Stride Change compute shader, fix storage buffers in helpers * An AMD exclusive * Reword * Change rules - stride conversion when attrs misalign * Fix stupid mistake * Fix background pipeline compile * Improve a few things. * Fix some feedback * Address Feedback (the shader binary didn't change when i changed the source to use the subgroup size) * Fix bug where rewritten buffer would be disposed instantly.
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/CacheByRange.cs')
-rw-r--r--Ryujinx.Graphics.Vulkan/CacheByRange.cs114
1 files changed, 103 insertions, 11 deletions
diff --git a/Ryujinx.Graphics.Vulkan/CacheByRange.cs b/Ryujinx.Graphics.Vulkan/CacheByRange.cs
index f3f503da..f9edca8a 100644
--- a/Ryujinx.Graphics.Vulkan/CacheByRange.cs
+++ b/Ryujinx.Graphics.Vulkan/CacheByRange.cs
@@ -3,29 +3,110 @@ using System.Collections.Generic;
namespace Ryujinx.Graphics.Vulkan
{
+ interface ICacheKey : IDisposable
+ {
+ bool KeyEqual(ICacheKey other);
+ }
+
+ struct I8ToI16CacheKey : ICacheKey
+ {
+ public I8ToI16CacheKey() { }
+
+ public bool KeyEqual(ICacheKey other)
+ {
+ return other is I8ToI16CacheKey;
+ }
+
+ public void Dispose() { }
+ }
+
+ struct AlignedVertexBufferCacheKey : ICacheKey
+ {
+ private readonly int _stride;
+ private readonly int _alignment;
+
+ // Used to notify the pipeline that bindings have invalidated on dispose.
+ private readonly VulkanRenderer _gd;
+ private Auto<DisposableBuffer> _buffer;
+
+ public AlignedVertexBufferCacheKey(VulkanRenderer gd, int stride, int alignment)
+ {
+ _gd = gd;
+ _stride = stride;
+ _alignment = alignment;
+ _buffer = null;
+ }
+
+ public bool KeyEqual(ICacheKey other)
+ {
+ return other is AlignedVertexBufferCacheKey entry &&
+ entry._stride == _stride &&
+ entry._alignment == _alignment;
+ }
+
+ public void SetBuffer(Auto<DisposableBuffer> buffer)
+ {
+ _buffer = buffer;
+ }
+
+ public void Dispose()
+ {
+ _gd.PipelineInternal.DirtyVertexBuffer(_buffer);
+ }
+ }
+
struct CacheByRange<T> where T : IDisposable
{
- private Dictionary<ulong, T> _ranges;
+ private struct Entry
+ {
+ public ICacheKey Key;
+ public T Value;
+
+ public Entry(ICacheKey key, T value)
+ {
+ Key = key;
+ Value = value;
+ }
+ }
- public void Add(int offset, int size, T value)
+ private Dictionary<ulong, List<Entry>> _ranges;
+
+ public void Add(int offset, int size, ICacheKey key, T value)
{
- EnsureInitialized();
- _ranges.Add(PackRange(offset, size), value);
+ List<Entry> entries = GetEntries(offset, size);
+
+ entries.Add(new Entry(key, value));
}
- public bool TryGetValue(int offset, int size, out T value)
+ public bool TryGetValue(int offset, int size, ICacheKey key, out T value)
{
- EnsureInitialized();
- return _ranges.TryGetValue(PackRange(offset, size), out value);
+ List<Entry> entries = GetEntries(offset, size);
+
+ foreach (Entry entry in entries)
+ {
+ if (entry.Key.KeyEqual(key))
+ {
+ value = entry.Value;
+
+ return true;
+ }
+ }
+
+ value = default;
+ return false;
}
public void Clear()
{
if (_ranges != null)
{
- foreach (T value in _ranges.Values)
+ foreach (List<Entry> entries in _ranges.Values)
{
- value.Dispose();
+ foreach (Entry entry in entries)
+ {
+ entry.Key.Dispose();
+ entry.Value.Dispose();
+ }
}
_ranges.Clear();
@@ -33,12 +114,23 @@ namespace Ryujinx.Graphics.Vulkan
}
}
- private void EnsureInitialized()
+ private List<Entry> GetEntries(int offset, int size)
{
if (_ranges == null)
{
- _ranges = new Dictionary<ulong, T>();
+ _ranges = new Dictionary<ulong, List<Entry>>();
}
+
+ ulong key = PackRange(offset, size);
+
+ List<Entry> value;
+ if (!_ranges.TryGetValue(key, out value))
+ {
+ value = new List<Entry>();
+ _ranges.Add(key, value);
+ }
+
+ return value;
}
private static ulong PackRange(int offset, int size)