/ src / Ryujinx.Graphics.Vulkan / PipelineLayoutCache.cs
PipelineLayoutCache.cs
  1  using Ryujinx.Graphics.GAL;
  2  using Silk.NET.Vulkan;
  3  using System;
  4  using System.Collections.Concurrent;
  5  using System.Collections.ObjectModel;
  6  
  7  namespace Ryujinx.Graphics.Vulkan
  8  {
  9      class PipelineLayoutCache
 10      {
 11          private readonly struct PlceKey : IEquatable<PlceKey>
 12          {
 13              public readonly ReadOnlyCollection<ResourceDescriptorCollection> SetDescriptors;
 14              public readonly bool UsePushDescriptors;
 15  
 16              public PlceKey(ReadOnlyCollection<ResourceDescriptorCollection> setDescriptors, bool usePushDescriptors)
 17              {
 18                  SetDescriptors = setDescriptors;
 19                  UsePushDescriptors = usePushDescriptors;
 20              }
 21  
 22              public override int GetHashCode()
 23              {
 24                  HashCode hasher = new();
 25  
 26                  if (SetDescriptors != null)
 27                  {
 28                      foreach (var setDescriptor in SetDescriptors)
 29                      {
 30                          hasher.Add(setDescriptor);
 31                      }
 32                  }
 33  
 34                  hasher.Add(UsePushDescriptors);
 35  
 36                  return hasher.ToHashCode();
 37              }
 38  
 39              public override bool Equals(object obj)
 40              {
 41                  return obj is PlceKey other && Equals(other);
 42              }
 43  
 44              public bool Equals(PlceKey other)
 45              {
 46                  if ((SetDescriptors == null) != (other.SetDescriptors == null))
 47                  {
 48                      return false;
 49                  }
 50  
 51                  if (SetDescriptors != null)
 52                  {
 53                      if (SetDescriptors.Count != other.SetDescriptors.Count)
 54                      {
 55                          return false;
 56                      }
 57  
 58                      for (int index = 0; index < SetDescriptors.Count; index++)
 59                      {
 60                          if (!SetDescriptors[index].Equals(other.SetDescriptors[index]))
 61                          {
 62                              return false;
 63                          }
 64                      }
 65                  }
 66  
 67                  return UsePushDescriptors == other.UsePushDescriptors;
 68              }
 69          }
 70  
 71          private readonly ConcurrentDictionary<PlceKey, PipelineLayoutCacheEntry> _plces;
 72  
 73          public PipelineLayoutCache()
 74          {
 75              _plces = new ConcurrentDictionary<PlceKey, PipelineLayoutCacheEntry>();
 76          }
 77  
 78          public PipelineLayoutCacheEntry GetOrCreate(
 79              VulkanRenderer gd,
 80              Device device,
 81              ReadOnlyCollection<ResourceDescriptorCollection> setDescriptors,
 82              bool usePushDescriptors)
 83          {
 84              var key = new PlceKey(setDescriptors, usePushDescriptors);
 85  
 86              return _plces.GetOrAdd(key, newKey => new PipelineLayoutCacheEntry(gd, device, setDescriptors, usePushDescriptors));
 87          }
 88  
 89          protected virtual void Dispose(bool disposing)
 90          {
 91              if (disposing)
 92              {
 93                  foreach (var plce in _plces.Values)
 94                  {
 95                      plce.Dispose();
 96                  }
 97  
 98                  _plces.Clear();
 99              }
100          }
101  
102          public void Dispose()
103          {
104              Dispose(true);
105          }
106      }
107  }