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 }