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();
}
}
}