using Ryujinx.Graphics.Gpu.Memory; using System.Collections.Generic; namespace Ryujinx.Graphics.Gpu.Image { /// /// Sampler pool. /// class SamplerPool : Pool, IPool { private float _forcedAnisotropy; /// /// Linked list node used on the sampler pool cache. /// public LinkedListNode CacheNode { get; set; } /// /// Timestamp used by the sampler pool cache, updated on every use of this sampler pool. /// public ulong CacheTimestamp { get; set; } /// /// Creates a new instance of the sampler pool. /// /// GPU context that the sampler pool belongs to /// Physical memory where the sampler descriptors are mapped /// Address of the sampler pool in guest memory /// Maximum sampler ID of the sampler pool (equal to maximum samplers minus one) public SamplerPool(GpuContext context, PhysicalMemory physicalMemory, ulong address, int maximumId) : base(context, physicalMemory, address, maximumId) { _forcedAnisotropy = GraphicsConfig.MaxAnisotropy; } /// /// Gets the sampler with the given ID. /// /// ID of the sampler. This is effectively a zero-based index /// The sampler with the given ID public override Sampler Get(int id) { if ((uint)id >= Items.Length) { return null; } if (SequenceNumber != Context.SequenceNumber) { if (_forcedAnisotropy != GraphicsConfig.MaxAnisotropy) { _forcedAnisotropy = GraphicsConfig.MaxAnisotropy; for (int i = 0; i < Items.Length; i++) { if (Items[i] != null) { Items[i].Dispose(); Items[i] = null; } } UpdateModifiedSequence(); } SequenceNumber = Context.SequenceNumber; SynchronizeMemory(); } Sampler sampler = Items[id]; if (sampler == null) { SamplerDescriptor descriptor = GetDescriptor(id); sampler = new Sampler(Context, descriptor); Items[id] = sampler; DescriptorCache[id] = descriptor; } return sampler; } /// /// Checks if the pool was modified, and returns the last sequence number where a modification was detected. /// /// A number that increments each time a modification is detected public int CheckModified() { if (SequenceNumber != Context.SequenceNumber) { SequenceNumber = Context.SequenceNumber; if (_forcedAnisotropy != GraphicsConfig.MaxAnisotropy) { _forcedAnisotropy = GraphicsConfig.MaxAnisotropy; for (int i = 0; i < Items.Length; i++) { if (Items[i] != null) { Items[i].Dispose(); Items[i] = null; } } UpdateModifiedSequence(); } SynchronizeMemory(); } return ModifiedSequenceNumber; } /// /// Implementation of the sampler pool range invalidation. /// /// Start address of the range of the sampler pool /// Size of the range being invalidated protected override void InvalidateRangeImpl(ulong address, ulong size) { ulong endAddress = address + size; for (; address < endAddress; address += DescriptorSize) { int id = (int)((address - Address) / DescriptorSize); Sampler sampler = Items[id]; if (sampler != null) { SamplerDescriptor descriptor = GetDescriptor(id); // If the descriptors are the same, the sampler is still valid. if (descriptor.Equals(ref DescriptorCache[id])) { continue; } sampler.Dispose(); Items[id] = null; } } } /// /// Deletes a given sampler pool entry. /// The host memory used by the sampler is released by the driver. /// /// The entry to be deleted protected override void Delete(Sampler item) { item?.Dispose(); } } }