/ src / Ryujinx.Graphics.Gpu / Image / SamplerPool.cs
SamplerPool.cs
  1  using Ryujinx.Graphics.Gpu.Memory;
  2  using System.Collections.Generic;
  3  
  4  namespace Ryujinx.Graphics.Gpu.Image
  5  {
  6      /// <summary>
  7      /// Sampler pool.
  8      /// </summary>
  9      class SamplerPool : Pool<Sampler, SamplerDescriptor>, IPool<SamplerPool>
 10      {
 11          private float _forcedAnisotropy;
 12  
 13          /// <summary>
 14          /// Linked list node used on the sampler pool cache.
 15          /// </summary>
 16          public LinkedListNode<SamplerPool> CacheNode { get; set; }
 17  
 18          /// <summary>
 19          /// Timestamp used by the sampler pool cache, updated on every use of this sampler pool.
 20          /// </summary>
 21          public ulong CacheTimestamp { get; set; }
 22  
 23          /// <summary>
 24          /// Creates a new instance of the sampler pool.
 25          /// </summary>
 26          /// <param name="context">GPU context that the sampler pool belongs to</param>
 27          /// <param name="physicalMemory">Physical memory where the sampler descriptors are mapped</param>
 28          /// <param name="address">Address of the sampler pool in guest memory</param>
 29          /// <param name="maximumId">Maximum sampler ID of the sampler pool (equal to maximum samplers minus one)</param>
 30          public SamplerPool(GpuContext context, PhysicalMemory physicalMemory, ulong address, int maximumId) : base(context, physicalMemory, address, maximumId)
 31          {
 32              _forcedAnisotropy = GraphicsConfig.MaxAnisotropy;
 33          }
 34  
 35          /// <summary>
 36          /// Gets the sampler with the given ID.
 37          /// </summary>
 38          /// <param name="id">ID of the sampler. This is effectively a zero-based index</param>
 39          /// <returns>The sampler with the given ID</returns>
 40          public override Sampler Get(int id)
 41          {
 42              if ((uint)id >= Items.Length)
 43              {
 44                  return null;
 45              }
 46  
 47              if (SequenceNumber != Context.SequenceNumber)
 48              {
 49                  if (_forcedAnisotropy != GraphicsConfig.MaxAnisotropy)
 50                  {
 51                      _forcedAnisotropy = GraphicsConfig.MaxAnisotropy;
 52  
 53                      for (int i = 0; i < Items.Length; i++)
 54                      {
 55                          if (Items[i] != null)
 56                          {
 57                              Items[i].Dispose();
 58  
 59                              Items[i] = null;
 60                          }
 61                      }
 62  
 63                      UpdateModifiedSequence();
 64                  }
 65  
 66                  SequenceNumber = Context.SequenceNumber;
 67  
 68                  SynchronizeMemory();
 69              }
 70  
 71              Sampler sampler = Items[id];
 72  
 73              if (sampler == null)
 74              {
 75                  SamplerDescriptor descriptor = GetDescriptor(id);
 76  
 77                  sampler = new Sampler(Context, descriptor);
 78  
 79                  Items[id] = sampler;
 80  
 81                  DescriptorCache[id] = descriptor;
 82              }
 83  
 84              return sampler;
 85          }
 86  
 87          /// <summary>
 88          /// Checks if the pool was modified, and returns the last sequence number where a modification was detected.
 89          /// </summary>
 90          /// <returns>A number that increments each time a modification is detected</returns>
 91          public int CheckModified()
 92          {
 93              if (SequenceNumber != Context.SequenceNumber)
 94              {
 95                  SequenceNumber = Context.SequenceNumber;
 96  
 97                  if (_forcedAnisotropy != GraphicsConfig.MaxAnisotropy)
 98                  {
 99                      _forcedAnisotropy = GraphicsConfig.MaxAnisotropy;
100  
101                      for (int i = 0; i < Items.Length; i++)
102                      {
103                          if (Items[i] != null)
104                          {
105                              Items[i].Dispose();
106  
107                              Items[i] = null;
108                          }
109                      }
110  
111                      UpdateModifiedSequence();
112                  }
113  
114                  SynchronizeMemory();
115              }
116  
117              return ModifiedSequenceNumber;
118          }
119  
120          /// <summary>
121          /// Implementation of the sampler pool range invalidation.
122          /// </summary>
123          /// <param name="address">Start address of the range of the sampler pool</param>
124          /// <param name="size">Size of the range being invalidated</param>
125          protected override void InvalidateRangeImpl(ulong address, ulong size)
126          {
127              ulong endAddress = address + size;
128  
129              for (; address < endAddress; address += DescriptorSize)
130              {
131                  int id = (int)((address - Address) / DescriptorSize);
132  
133                  Sampler sampler = Items[id];
134  
135                  if (sampler != null)
136                  {
137                      SamplerDescriptor descriptor = GetDescriptor(id);
138  
139                      // If the descriptors are the same, the sampler is still valid.
140                      if (descriptor.Equals(ref DescriptorCache[id]))
141                      {
142                          continue;
143                      }
144  
145                      sampler.Dispose();
146  
147                      Items[id] = null;
148                  }
149              }
150          }
151  
152          /// <summary>
153          /// Deletes a given sampler pool entry.
154          /// The host memory used by the sampler is released by the driver.
155          /// </summary>
156          /// <param name="item">The entry to be deleted</param>
157          protected override void Delete(Sampler item)
158          {
159              item?.Dispose();
160          }
161      }
162  }