Ryujinx/Ryujinx.Graphics.Gpu/Shader/Cache/CacheManager.cs
gdkchan d9d18439f6
Use a new approach for shader BRX targets (#2532)
* Use a new approach for shader BRX targets

* Make shader cache actually work

* Improve the shader pattern matching a bit

* Extend LDC search to predecessor blocks, catches more cases

* Nit

* Only save the amount of constant buffer data actually used. Avoids crashes on partially mapped buffers

* Ignore Rd on predicate instructions, as they do not have a Rd register (catches more cases)
2021-08-11 20:59:42 +02:00

170 lines
6.2 KiB
C#

using Ryujinx.Common;
using Ryujinx.Graphics.Gpu.Shader.Cache.Definition;
using System;
using System.Collections.Generic;
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 = 1759;
public bool IsReadOnly => _guestProgramCache.IsReadOnly || _hostProgramCache.IsReadOnly;
/// <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 = CacheHelper.GetBaseCacheDirectory(titleId);
CacheMigration.Run(baseCacheDirectory, graphicsApi, hashType, shaderProvider);
_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.RemoveManifestEntriesAsync(entries);
_hostProgramCache.RemoveManifestEntriesAsync(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>
/// 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>
/// Removes a shader program present in the program cache.
/// </summary>
/// <param name="programCodeHash">Target program code hash</param>
public void RemoveProgram(ref Hash128 programCodeHash)
{
_guestProgramCache.RemoveValue(ref programCodeHash);
_hostProgramCache.RemoveValue(ref programCodeHash);
}
/// <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();
}
}
}
}