diff options
author | Mary <me@thog.eu> | 2020-11-13 00:15:34 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-13 00:15:34 +0100 |
commit | 48f6570557fc76496936514d94e3ccddf55ec633 (patch) | |
tree | ce455833899cb33a312e5853a7a3d191bb5d18d9 /Ryujinx.Graphics.Gpu/Shader/Cache/CacheManager.cs | |
parent | 7166e82c3cf1fd8cf2fce3281017ee88122684d8 (diff) |
Salieri: shader cache (#1701)
Here come Salieri, my implementation of a disk shader cache!
"I'm sure you know why I named it that."
"It doesn't really mean anything."
This implementation collects shaders at runtime and cache them to be later compiled when starting a game.
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Shader/Cache/CacheManager.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Shader/Cache/CacheManager.cs | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/CacheManager.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/CacheManager.cs new file mode 100644 index 00000000..d241eb01 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Shader/Cache/CacheManager.cs @@ -0,0 +1,168 @@ +using Ryujinx.Common; +using Ryujinx.Common.Configuration; +using Ryujinx.Graphics.Gpu.Shader.Cache.Definition; +using System; +using System.Collections.Generic; +using System.IO; + +namespace Ryujinx.Graphics.Gpu.Shader.Cache +{ + /// <summary> + /// Global Manager of the shader cache. + /// </summary> + class CacheManager : IDisposable + { + private CacheGraphicsApi _graphicsApi; + private CacheHashType _hashType; + private string _shaderProvider; + + /// <summary> + /// Cache storing raw Maxwell shaders as programs. + /// </summary> + private CacheCollection _guestProgramCache; + + /// <summary> + /// Cache storing raw host programs. + /// </summary> + private CacheCollection _hostProgramCache; + + /// <summary> + /// Version of the guest cache shader (to increment when guest cache structure change). + /// </summary> + private const ulong GuestCacheVersion = 1; + + /// <summary> + /// Create a new cache manager instance + /// </summary> + /// <param name="graphicsApi">The graphics api in use</param> + /// <param name="hashType">The hash type in use for the cache</param> + /// <param name="shaderProvider">The name of the codegen provider</param> + /// <param name="titleId">The guest application title ID</param> + /// <param name="shaderCodeGenVersion">Version of the codegen</param> + public CacheManager(CacheGraphicsApi graphicsApi, CacheHashType hashType, string shaderProvider, string titleId, ulong shaderCodeGenVersion) + { + _graphicsApi = graphicsApi; + _hashType = hashType; + _shaderProvider = shaderProvider; + + string baseCacheDirectory = Path.Combine(AppDataManager.GamesDirPath, titleId, "cache", "shader"); + + _guestProgramCache = new CacheCollection(baseCacheDirectory, _hashType, CacheGraphicsApi.Guest, "", "program", GuestCacheVersion); + _hostProgramCache = new CacheCollection(baseCacheDirectory, _hashType, _graphicsApi, _shaderProvider, "host", shaderCodeGenVersion); + } + + + /// <summary> + /// Entries to remove from the manifest. + /// </summary> + /// <param name="entries">Entries to remove from the manifest of all caches</param> + public void RemoveManifestEntries(HashSet<Hash128> entries) + { + _guestProgramCache.RemoveManifestEntries(entries); + _hostProgramCache.RemoveManifestEntries(entries); + } + + /// <summary> + /// Queue a task to flush temporary files to the archives. + /// </summary> + public void FlushToArchive() + { + _guestProgramCache.FlushToArchiveAsync(); + _hostProgramCache.FlushToArchiveAsync(); + } + + /// <summary> + /// Wait for all tasks before this given point to be done. + /// </summary> + public void Synchronize() + { + _guestProgramCache.Synchronize(); + _hostProgramCache.Synchronize(); + } + + /// <summary> + /// Computes the hash of some data using the current cache hashing algorithm. + /// </summary> + /// <param name="data">Some data to generate a hash for.</param> + /// <returns>The hash of some data using the current hashing algorithm of the cache</returns> + public Hash128 ComputeHash(ReadOnlySpan<byte> data) + { + return XXHash128.ComputeHash(data); + } + + /// <summary> + /// Save a shader program not present in the program cache. + /// </summary> + /// <param name="programCodeHash">Target program code hash</param> + /// <param name="guestProgram">Guest program raw data</param> + /// <param name="hostProgram">Host program raw data</param> + public void SaveProgram(ref Hash128 programCodeHash, byte[] guestProgram, byte[] hostProgram) + { + _guestProgramCache.AddValue(ref programCodeHash, guestProgram); + _hostProgramCache.AddValue(ref programCodeHash, hostProgram); + } + + /// <summary> + /// Add a host shader program not present in the program cache. + /// </summary> + /// <param name="programCodeHash">Target program code hash</param> + /// <param name="data">Host program raw data</param> + public void AddHostProgram(ref Hash128 programCodeHash, byte[] data) + { + _hostProgramCache.AddValue(ref programCodeHash, data); + } + + /// <summary> + /// Replace a host shader program present in the program cache. + /// </summary> + /// <param name="programCodeHash">Target program code hash</param> + /// <param name="data">Host program raw data</param> + public void ReplaceHostProgram(ref Hash128 programCodeHash, byte[] data) + { + _hostProgramCache.ReplaceValue(ref programCodeHash, data); + } + + /// <summary> + /// Get all guest program hashes. + /// </summary> + /// <returns>All guest program hashes</returns> + public ReadOnlySpan<Hash128> GetGuestProgramList() + { + return _guestProgramCache.HashTable; + } + + /// <summary> + /// Get a host program by hash. + /// </summary> + /// <param name="hash">The given hash</param> + /// <returns>The host program if present or null</returns> + public byte[] GetHostProgramByHash(ref Hash128 hash) + { + return _hostProgramCache.GetValueRaw(ref hash); + } + + /// <summary> + /// Get a guest program by hash. + /// </summary> + /// <param name="hash">The given hash</param> + /// <returns>The guest program if present or null</returns> + public byte[] GetGuestProgramByHash(ref Hash128 hash) + { + return _guestProgramCache.GetValueRaw(ref hash); + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _guestProgramCache.Dispose(); + _hostProgramCache.Dispose(); + } + } + } +} |