using Ryujinx.Graphics.Gpu.Shader.HashTable;
using System.Collections.Generic;
namespace Ryujinx.Graphics.Gpu.Shader
{
///
/// Compute shader cache hash table.
///
class ComputeShaderCacheHashTable
{
private readonly PartitionedHashTable _cache;
private readonly List _shaderPrograms;
///
/// Creates a new compute shader cache hash table.
///
public ComputeShaderCacheHashTable()
{
_cache = new PartitionedHashTable();
_shaderPrograms = new List();
}
///
/// Adds a program to the cache.
///
/// Program to be added
public void Add(CachedShaderProgram program)
{
var specList = _cache.GetOrAdd(program.Shaders[0].Code, new ShaderSpecializationList());
specList.Add(program);
_shaderPrograms.Add(program);
}
///
/// Tries to find a cached program.
///
/// GPU channel
/// Texture pool state
/// Compute state
/// GPU virtual address of the compute shader
/// Cached host program for the given state, if found
/// Cached guest code, if any found
/// True if a cached host program was found, false otherwise
public bool TryFind(
GpuChannel channel,
GpuChannelPoolState poolState,
GpuChannelComputeState computeState,
ulong gpuVa,
out CachedShaderProgram program,
out byte[] cachedGuestCode)
{
program = null;
ShaderCodeAccessor codeAccessor = new(channel.MemoryManager, gpuVa);
bool hasSpecList = _cache.TryFindItem(codeAccessor, out var specList, out cachedGuestCode);
return hasSpecList && specList.TryFindForCompute(channel, poolState, computeState, out program);
}
///
/// Gets all programs that have been added to the table.
///
/// Programs added to the table
public IEnumerable GetPrograms()
{
foreach (var program in _shaderPrograms)
{
yield return program;
}
}
}
}