diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Vulkan/PipelineLayoutCache.cs')
-rw-r--r-- | src/Ryujinx.Graphics.Vulkan/PipelineLayoutCache.cs | 97 |
1 files changed, 73 insertions, 24 deletions
diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineLayoutCache.cs b/src/Ryujinx.Graphics.Vulkan/PipelineLayoutCache.cs index c834fa62..e7c43567 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineLayoutCache.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineLayoutCache.cs @@ -1,52 +1,101 @@ using Ryujinx.Graphics.GAL; using Silk.NET.Vulkan; -using System.Collections.Generic; +using System; +using System.Collections.Concurrent; +using System.Collections.ObjectModel; namespace Ryujinx.Graphics.Vulkan { class PipelineLayoutCache { - private readonly PipelineLayoutCacheEntry[] _plce; - private readonly List<PipelineLayoutCacheEntry> _plceMinimal; - - public PipelineLayoutCache() + private readonly struct PlceKey : IEquatable<PlceKey> { - _plce = new PipelineLayoutCacheEntry[1 << Constants.MaxShaderStages]; - _plceMinimal = new List<PipelineLayoutCacheEntry>(); + public readonly ReadOnlyCollection<ResourceDescriptorCollection> SetDescriptors; + public readonly bool UsePushDescriptors; + + public PlceKey(ReadOnlyCollection<ResourceDescriptorCollection> setDescriptors, bool usePushDescriptors) + { + SetDescriptors = setDescriptors; + UsePushDescriptors = usePushDescriptors; + } + + public override int GetHashCode() + { + HashCode hasher = new HashCode(); + + if (SetDescriptors != null) + { + foreach (var setDescriptor in SetDescriptors) + { + hasher.Add(setDescriptor); + } + } + + hasher.Add(UsePushDescriptors); + + return hasher.ToHashCode(); + } + + public override bool Equals(object obj) + { + return obj is PlceKey other && Equals(other); + } + + public bool Equals(PlceKey other) + { + if ((SetDescriptors == null) != (other.SetDescriptors == null)) + { + return false; + } + + if (SetDescriptors != null) + { + if (SetDescriptors.Count != other.SetDescriptors.Count) + { + return false; + } + + for (int index = 0; index < SetDescriptors.Count; index++) + { + if (!SetDescriptors[index].Equals(other.SetDescriptors[index])) + { + return false; + } + } + } + + return UsePushDescriptors == other.UsePushDescriptors; + } } - public PipelineLayoutCacheEntry Create(VulkanRenderer gd, Device device, ShaderSource[] shaders) + private readonly ConcurrentDictionary<PlceKey, PipelineLayoutCacheEntry> _plces; + + public PipelineLayoutCache() { - var plce = new PipelineLayoutCacheEntry(gd, device, shaders); - _plceMinimal.Add(plce); - return plce; + _plces = new ConcurrentDictionary<PlceKey, PipelineLayoutCacheEntry>(); } - public PipelineLayoutCacheEntry GetOrCreate(VulkanRenderer gd, Device device, uint stages, bool usePd) + public PipelineLayoutCacheEntry GetOrCreate( + VulkanRenderer gd, + Device device, + ReadOnlyCollection<ResourceDescriptorCollection> setDescriptors, + bool usePushDescriptors) { - if (_plce[stages] == null) - { - _plce[stages] = new PipelineLayoutCacheEntry(gd, device, stages, usePd); - } + var key = new PlceKey(setDescriptors, usePushDescriptors); - return _plce[stages]; + return _plces.GetOrAdd(key, (newKey) => new PipelineLayoutCacheEntry(gd, device, setDescriptors, usePushDescriptors)); } protected virtual unsafe void Dispose(bool disposing) { if (disposing) { - for (int i = 0; i < _plce.Length; i++) - { - _plce[i]?.Dispose(); - } - - foreach (var plce in _plceMinimal) + foreach (var plce in _plces.Values) { plce.Dispose(); } - _plceMinimal.Clear(); + _plces.Clear(); } } |