aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Shader/ShaderCacheHashTable.cs
diff options
context:
space:
mode:
authorTSR Berry <20988865+TSRBerry@users.noreply.github.com>2023-04-08 01:22:00 +0200
committerMary <thog@protonmail.com>2023-04-27 23:51:14 +0200
commitcee712105850ac3385cd0091a923438167433f9f (patch)
tree4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /Ryujinx.Graphics.Gpu/Shader/ShaderCacheHashTable.cs
parentcd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff)
Move solution and projects to src
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Shader/ShaderCacheHashTable.cs')
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/ShaderCacheHashTable.cs282
1 files changed, 0 insertions, 282 deletions
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCacheHashTable.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCacheHashTable.cs
deleted file mode 100644
index e35c06b1..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderCacheHashTable.cs
+++ /dev/null
@@ -1,282 +0,0 @@
-using Ryujinx.Graphics.Gpu.Memory;
-using Ryujinx.Graphics.Gpu.Shader.HashTable;
-using Ryujinx.Graphics.Shader;
-using System;
-using System.Collections.Generic;
-
-namespace Ryujinx.Graphics.Gpu.Shader
-{
- /// <summary>
- /// Holds already cached code for a guest shader.
- /// </summary>
- struct CachedGraphicsGuestCode
- {
- public byte[] VertexACode;
- public byte[] VertexBCode;
- public byte[] TessControlCode;
- public byte[] TessEvaluationCode;
- public byte[] GeometryCode;
- public byte[] FragmentCode;
-
- /// <summary>
- /// Gets the guest code of a shader stage by its index.
- /// </summary>
- /// <param name="stageIndex">Index of the shader stage</param>
- /// <returns>Guest code, or null if not present</returns>
- public byte[] GetByIndex(int stageIndex)
- {
- return stageIndex switch
- {
- 1 => TessControlCode,
- 2 => TessEvaluationCode,
- 3 => GeometryCode,
- 4 => FragmentCode,
- _ => VertexBCode
- };
- }
- }
-
- /// <summary>
- /// Graphics shader cache hash table.
- /// </summary>
- class ShaderCacheHashTable
- {
- /// <summary>
- /// Shader ID cache.
- /// </summary>
- private struct IdCache
- {
- private PartitionedHashTable<int> _cache;
- private int _id;
-
- /// <summary>
- /// Initializes the state.
- /// </summary>
- public void Initialize()
- {
- _cache = new PartitionedHashTable<int>();
- _id = 0;
- }
-
- /// <summary>
- /// Adds guest code to the cache.
- /// </summary>
- /// <remarks>
- /// If the code was already cached, it will just return the existing ID.
- /// </remarks>
- /// <param name="code">Code to add</param>
- /// <returns>Unique ID for the guest code</returns>
- public int Add(byte[] code)
- {
- int id = ++_id;
- int cachedId = _cache.GetOrAdd(code, id);
- if (cachedId != id)
- {
- --_id;
- }
-
- return cachedId;
- }
-
- /// <summary>
- /// Tries to find cached guest code.
- /// </summary>
- /// <param name="dataAccessor">Code accessor used to read guest code to find a match on the hash table</param>
- /// <param name="id">ID of the guest code, if found</param>
- /// <param name="data">Cached guest code, if found</param>
- /// <returns>True if found, false otherwise</returns>
- public bool TryFind(IDataAccessor dataAccessor, out int id, out byte[] data)
- {
- return _cache.TryFindItem(dataAccessor, out id, out data);
- }
- }
-
- /// <summary>
- /// Guest code IDs of the guest shaders that when combined forms a single host program.
- /// </summary>
- private struct IdTable : IEquatable<IdTable>
- {
- public int VertexAId;
- public int VertexBId;
- public int TessControlId;
- public int TessEvaluationId;
- public int GeometryId;
- public int FragmentId;
-
- public override bool Equals(object obj)
- {
- return obj is IdTable other && Equals(other);
- }
-
- public bool Equals(IdTable other)
- {
- return other.VertexAId == VertexAId &&
- other.VertexBId == VertexBId &&
- other.TessControlId == TessControlId &&
- other.TessEvaluationId == TessEvaluationId &&
- other.GeometryId == GeometryId &&
- other.FragmentId == FragmentId;
- }
-
- public override int GetHashCode()
- {
- return HashCode.Combine(VertexAId, VertexBId, TessControlId, TessEvaluationId, GeometryId, FragmentId);
- }
- }
-
- private IdCache _vertexACache;
- private IdCache _vertexBCache;
- private IdCache _tessControlCache;
- private IdCache _tessEvaluationCache;
- private IdCache _geometryCache;
- private IdCache _fragmentCache;
-
- private readonly Dictionary<IdTable, ShaderSpecializationList> _shaderPrograms;
-
- /// <summary>
- /// Creates a new graphics shader cache hash table.
- /// </summary>
- public ShaderCacheHashTable()
- {
- _vertexACache.Initialize();
- _vertexBCache.Initialize();
- _tessControlCache.Initialize();
- _tessEvaluationCache.Initialize();
- _geometryCache.Initialize();
- _fragmentCache.Initialize();
-
- _shaderPrograms = new Dictionary<IdTable, ShaderSpecializationList>();
- }
-
- /// <summary>
- /// Adds a program to the cache.
- /// </summary>
- /// <param name="program">Program to be added</param>
- public void Add(CachedShaderProgram program)
- {
- IdTable idTable = new IdTable();
-
- foreach (var shader in program.Shaders)
- {
- if (shader == null)
- {
- continue;
- }
-
- if (shader.Info != null)
- {
- switch (shader.Info.Stage)
- {
- case ShaderStage.Vertex:
- idTable.VertexBId = _vertexBCache.Add(shader.Code);
- break;
- case ShaderStage.TessellationControl:
- idTable.TessControlId = _tessControlCache.Add(shader.Code);
- break;
- case ShaderStage.TessellationEvaluation:
- idTable.TessEvaluationId = _tessEvaluationCache.Add(shader.Code);
- break;
- case ShaderStage.Geometry:
- idTable.GeometryId = _geometryCache.Add(shader.Code);
- break;
- case ShaderStage.Fragment:
- idTable.FragmentId = _fragmentCache.Add(shader.Code);
- break;
- }
- }
- else
- {
- idTable.VertexAId = _vertexACache.Add(shader.Code);
- }
- }
-
- if (!_shaderPrograms.TryGetValue(idTable, out ShaderSpecializationList specList))
- {
- specList = new ShaderSpecializationList();
- _shaderPrograms.Add(idTable, specList);
- }
-
- specList.Add(program);
- }
-
- /// <summary>
- /// Tries to find a cached program.
- /// </summary>
- /// <remarks>
- /// Even if false is returned, <paramref name="guestCode"/> might still contain cached guest code.
- /// This can be used to avoid additional allocations for guest code that was already cached.
- /// </remarks>
- /// <param name="channel">GPU channel</param>
- /// <param name="poolState">Texture pool state</param>
- /// <param name="graphicsState">Graphics state</param>
- /// <param name="addresses">Guest addresses of the shaders to find</param>
- /// <param name="program">Cached host program for the given state, if found</param>
- /// <param name="guestCode">Cached guest code, if any found</param>
- /// <returns>True if a cached host program was found, false otherwise</returns>
- public bool TryFind(
- GpuChannel channel,
- ref GpuChannelPoolState poolState,
- ref GpuChannelGraphicsState graphicsState,
- ShaderAddresses addresses,
- out CachedShaderProgram program,
- out CachedGraphicsGuestCode guestCode)
- {
- var memoryManager = channel.MemoryManager;
- IdTable idTable = new IdTable();
- guestCode = new CachedGraphicsGuestCode();
-
- program = null;
-
- bool found = TryGetId(_vertexACache, memoryManager, addresses.VertexA, out idTable.VertexAId, out guestCode.VertexACode);
- found &= TryGetId(_vertexBCache, memoryManager, addresses.VertexB, out idTable.VertexBId, out guestCode.VertexBCode);
- found &= TryGetId(_tessControlCache, memoryManager, addresses.TessControl, out idTable.TessControlId, out guestCode.TessControlCode);
- found &= TryGetId(_tessEvaluationCache, memoryManager, addresses.TessEvaluation, out idTable.TessEvaluationId, out guestCode.TessEvaluationCode);
- found &= TryGetId(_geometryCache, memoryManager, addresses.Geometry, out idTable.GeometryId, out guestCode.GeometryCode);
- found &= TryGetId(_fragmentCache, memoryManager, addresses.Fragment, out idTable.FragmentId, out guestCode.FragmentCode);
-
- if (found && _shaderPrograms.TryGetValue(idTable, out ShaderSpecializationList specList))
- {
- return specList.TryFindForGraphics(channel, ref poolState, ref graphicsState, out program);
- }
-
- return false;
- }
-
- /// <summary>
- /// Tries to get the ID of a single cached shader stage.
- /// </summary>
- /// <param name="idCache">ID cache of the stage</param>
- /// <param name="memoryManager">GPU memory manager</param>
- /// <param name="baseAddress">Base address of the shader</param>
- /// <param name="id">ID, if found</param>
- /// <param name="data">Cached guest code, if found</param>
- /// <returns>True if a cached shader is found, false otherwise</returns>
- private static bool TryGetId(IdCache idCache, MemoryManager memoryManager, ulong baseAddress, out int id, out byte[] data)
- {
- if (baseAddress == 0)
- {
- id = 0;
- data = null;
- return true;
- }
-
- ShaderCodeAccessor codeAccessor = new ShaderCodeAccessor(memoryManager, baseAddress);
- return idCache.TryFind(codeAccessor, out id, out data);
- }
-
- /// <summary>
- /// Gets all programs that have been added to the table.
- /// </summary>
- /// <returns>Programs added to the table</returns>
- public IEnumerable<CachedShaderProgram> GetPrograms()
- {
- foreach (var specList in _shaderPrograms.Values)
- {
- foreach (var program in specList)
- {
- yield return program;
- }
- }
- }
- }
-} \ No newline at end of file