diff options
author | Mary <me@thog.eu> | 2020-12-13 08:46:07 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-13 08:46:07 +0100 |
commit | 6bc2733c1796788590c9f0114013d2e4b555e31e (patch) | |
tree | a729af2552637718fc3883108539c6da6523efd6 /Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs | |
parent | 19d18662ea3ed5470898ed2b7bbb06d45f6004dd (diff) |
salieri: Support read-only mode if archive is already opened (#1807)
This improves shader cache resilience when people opens another program that touch the cache.zip.
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs | 78 |
1 files changed, 56 insertions, 22 deletions
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs index a04affc2..d28d7362 100644 --- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs +++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs @@ -61,7 +61,18 @@ namespace Ryujinx.Graphics.Gpu.Shader { _cacheManager = new CacheManager(CacheGraphicsApi.OpenGL, CacheHashType.XxHash128, "glsl", GraphicsConfig.TitleId, ShaderCodeGenVersion); - HashSet<Hash128> invalidEntries = new HashSet<Hash128>(); + bool isReadOnly = _cacheManager.IsReadOnly; + + HashSet<Hash128> invalidEntries = null; + + if (isReadOnly) + { + Logger.Warning?.Print(LogClass.Gpu, "Loading shader cache in read-only mode (cache in use by another program!)"); + } + else + { + invalidEntries = new HashSet<Hash128>(); + } ReadOnlySpan<Hash128> guestProgramList = _cacheManager.GetGuestProgramList(); @@ -84,7 +95,7 @@ namespace Ryujinx.Graphics.Gpu.Shader Logger.Error?.Print(LogClass.Gpu, $"Ignoring orphan shader hash {key} in cache (is the cache incomplete?)"); // Should not happen, but if someone messed with the cache it's better to catch it. - invalidEntries.Add(key); + invalidEntries?.Add(key); continue; } @@ -141,15 +152,18 @@ namespace Ryujinx.Graphics.Gpu.Shader // As the host program was invalidated, save the new entry in the cache. hostProgramBinary = HostShaderCacheEntry.Create(hostProgram.GetBinary(), new ShaderCodeHolder[] { shader }); - if (hasHostCache) - { - _cacheManager.ReplaceHostProgram(ref key, hostProgramBinary); - } - else + if (!isReadOnly) { - Logger.Warning?.Print(LogClass.Gpu, $"Add missing host shader {key} in cache (is the cache incomplete?)"); + if (hasHostCache) + { + _cacheManager.ReplaceHostProgram(ref key, hostProgramBinary); + } + else + { + Logger.Warning?.Print(LogClass.Gpu, $"Add missing host shader {key} in cache (is the cache incomplete?)"); - _cacheManager.AddHostProgram(ref key, hostProgramBinary); + _cacheManager.AddHostProgram(ref key, hostProgramBinary); + } } } @@ -270,15 +284,18 @@ namespace Ryujinx.Graphics.Gpu.Shader // As the host program was invalidated, save the new entry in the cache. hostProgramBinary = HostShaderCacheEntry.Create(hostProgram.GetBinary(), shaders); - if (hasHostCache) - { - _cacheManager.ReplaceHostProgram(ref key, hostProgramBinary); - } - else + if (!isReadOnly) { - Logger.Warning?.Print(LogClass.Gpu, $"Add missing host shader {key} in cache (is the cache incomplete?)"); + if (hasHostCache) + { + _cacheManager.ReplaceHostProgram(ref key, hostProgramBinary); + } + else + { + Logger.Warning?.Print(LogClass.Gpu, $"Add missing host shader {key} in cache (is the cache incomplete?)"); - _cacheManager.AddHostProgram(ref key, hostProgramBinary); + _cacheManager.AddHostProgram(ref key, hostProgramBinary); + } } } @@ -286,10 +303,13 @@ namespace Ryujinx.Graphics.Gpu.Shader } } - // Remove entries that are broken in the cache - _cacheManager.RemoveManifestEntries(invalidEntries); - _cacheManager.FlushToArchive(); - _cacheManager.Synchronize(); + if (!isReadOnly) + { + // Remove entries that are broken in the cache + _cacheManager.RemoveManifestEntries(invalidEntries); + _cacheManager.FlushToArchive(); + _cacheManager.Synchronize(); + } Logger.Info?.Print(LogClass.Gpu, "Shader cache loaded."); } @@ -343,12 +363,15 @@ namespace Ryujinx.Graphics.Gpu.Shader sharedMemorySize); bool isShaderCacheEnabled = _cacheManager != null; + bool isShaderCacheReadOnly = false; Hash128 programCodeHash = default; GuestShaderCacheEntry[] shaderCacheEntries = null; if (isShaderCacheEnabled) { + isShaderCacheReadOnly = _cacheManager.IsReadOnly; + // Compute hash and prepare data for shader disk cache comparison. shaderCacheEntries = CacheHelper.CreateShaderCacheEntries(_context.MemoryManager, shaderContexts); programCodeHash = CacheHelper.ComputeGuestHashFromCache(shaderCacheEntries); @@ -378,7 +401,11 @@ namespace Ryujinx.Graphics.Gpu.Shader if (isShaderCacheEnabled) { _cpProgramsDiskCache.Add(programCodeHash, cpShader); - _cacheManager.SaveProgram(ref programCodeHash, CacheHelper.CreateGuestProgramDump(shaderCacheEntries), hostProgramBinary); + + if (!isShaderCacheReadOnly) + { + _cacheManager.SaveProgram(ref programCodeHash, CacheHelper.CreateGuestProgramDump(shaderCacheEntries), hostProgramBinary); + } } } @@ -447,12 +474,15 @@ namespace Ryujinx.Graphics.Gpu.Shader shaderContexts[4] = DecodeGraphicsShader(state, counts, flags, ShaderStage.Fragment, addresses.Fragment); bool isShaderCacheEnabled = _cacheManager != null; + bool isShaderCacheReadOnly = false; Hash128 programCodeHash = default; GuestShaderCacheEntry[] shaderCacheEntries = null; if (isShaderCacheEnabled) { + isShaderCacheReadOnly = _cacheManager.IsReadOnly; + // Compute hash and prepare data for shader disk cache comparison. shaderCacheEntries = CacheHelper.CreateShaderCacheEntries(_context.MemoryManager, shaderContexts); programCodeHash = CacheHelper.ComputeGuestHashFromCache(shaderCacheEntries, tfd); @@ -504,7 +534,11 @@ namespace Ryujinx.Graphics.Gpu.Shader if (isShaderCacheEnabled) { _gpProgramsDiskCache.Add(programCodeHash, gpShaders); - _cacheManager.SaveProgram(ref programCodeHash, CacheHelper.CreateGuestProgramDump(shaderCacheEntries, tfd), hostProgramBinary); + + if (!isShaderCacheReadOnly) + { + _cacheManager.SaveProgram(ref programCodeHash, CacheHelper.CreateGuestProgramDump(shaderCacheEntries, tfd), hostProgramBinary); + } } } |