using System;
using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Gpu.Image
{
///
/// Sampler pool.
///
class SamplerPool : Pool
{
private int _sequenceNumber;
///
/// Constructs a new instance of the sampler pool.
///
/// GPU context that the sampler pool belongs to
/// 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, ulong address, int maximumId) : base(context, address, maximumId) { }
///
/// 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)
{
_sequenceNumber = Context.SequenceNumber;
SynchronizeMemory();
}
Sampler sampler = Items[id];
if (sampler == null)
{
ulong address = Address + (ulong)(uint)id * DescriptorSize;
ReadOnlySpan data = Context.PhysicalMemory.GetSpan(address, DescriptorSize);
SamplerDescriptor descriptor = MemoryMarshal.Cast(data)[0];
sampler = new Sampler(Context, descriptor);
Items[id] = sampler;
}
return sampler;
}
///
/// 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)
{
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();
}
}
}