diff options
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs | 273 |
1 files changed, 0 insertions, 273 deletions
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs deleted file mode 100644 index d16afb65..00000000 --- a/Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs +++ /dev/null @@ -1,273 +0,0 @@ -using ICSharpCode.SharpZipLib.Zip; -using Ryujinx.Common; -using Ryujinx.Common.Configuration; -using Ryujinx.Common.Logging; -using Ryujinx.Graphics.Gpu.Shader.Cache.Definition; -using Ryujinx.Graphics.Shader; -using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace Ryujinx.Graphics.Gpu.Shader.Cache -{ - /// <summary> - /// Helper to manipulate the disk shader cache. - /// </summary> - static class CacheHelper - { - /// <summary> - /// Compute a cache manifest from runtime data. - /// </summary> - /// <param name="version">The version of the cache</param> - /// <param name="graphicsApi">The graphics api used by the cache</param> - /// <param name="hashType">The hash type of the cache</param> - /// <param name="entries">The entries in the cache</param> - /// <returns>The cache manifest from runtime data</returns> - public static byte[] ComputeManifest(ulong version, CacheGraphicsApi graphicsApi, CacheHashType hashType, HashSet<Hash128> entries) - { - if (hashType != CacheHashType.XxHash128) - { - throw new NotImplementedException($"{hashType}"); - } - - CacheManifestHeader manifestHeader = new CacheManifestHeader(version, graphicsApi, hashType); - - byte[] data = new byte[Unsafe.SizeOf<CacheManifestHeader>() + entries.Count * Unsafe.SizeOf<Hash128>()]; - - // CacheManifestHeader has the same size as a Hash128. - Span<Hash128> dataSpan = MemoryMarshal.Cast<byte, Hash128>(data.AsSpan()).Slice(1); - - int i = 0; - - foreach (Hash128 hash in entries) - { - dataSpan[i++] = hash; - } - - manifestHeader.UpdateChecksum(data.AsSpan(Unsafe.SizeOf<CacheManifestHeader>())); - - MemoryMarshal.Write(data, ref manifestHeader); - - return data; - } - - /// <summary> - /// Get the base directory of the shader cache for a given title id. - /// </summary> - /// <param name="titleId">The title id of the target application</param> - /// <returns>The base directory of the shader cache for a given title id</returns> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string GetBaseCacheDirectory(string titleId) => Path.Combine(AppDataManager.GamesDirPath, titleId, "cache", "shader"); - - /// <summary> - /// Get the temp path to the cache data directory. - /// </summary> - /// <param name="cacheDirectory">The cache directory</param> - /// <returns>The temp path to the cache data directory</returns> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string GetCacheTempDataPath(string cacheDirectory) => Path.Combine(cacheDirectory, "temp"); - - /// <summary> - /// The path to the cache archive file. - /// </summary> - /// <param name="cacheDirectory">The cache directory</param> - /// <returns>The path to the cache archive file</returns> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string GetArchivePath(string cacheDirectory) => Path.Combine(cacheDirectory, "cache.zip"); - - /// <summary> - /// The path to the cache manifest file. - /// </summary> - /// <param name="cacheDirectory">The cache directory</param> - /// <returns>The path to the cache manifest file</returns> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string GetManifestPath(string cacheDirectory) => Path.Combine(cacheDirectory, "cache.info"); - - /// <summary> - /// Create a new temp path to the given cached file via its hash. - /// </summary> - /// <param name="cacheDirectory">The cache directory</param> - /// <param name="key">The hash of the cached data</param> - /// <returns>New path to the given cached file</returns> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string GenCacheTempFilePath(string cacheDirectory, Hash128 key) => Path.Combine(GetCacheTempDataPath(cacheDirectory), key.ToString()); - - /// <summary> - /// Generate the path to the cache directory. - /// </summary> - /// <param name="baseCacheDirectory">The base of the cache directory</param> - /// <param name="graphicsApi">The graphics api in use</param> - /// <param name="shaderProvider">The name of the shader provider in use</param> - /// <param name="cacheName">The name of the cache</param> - /// <returns>The path to the cache directory</returns> - public static string GenerateCachePath(string baseCacheDirectory, CacheGraphicsApi graphicsApi, string shaderProvider, string cacheName) - { - string graphicsApiName = graphicsApi switch - { - CacheGraphicsApi.OpenGL => "opengl", - CacheGraphicsApi.OpenGLES => "opengles", - CacheGraphicsApi.Vulkan => "vulkan", - CacheGraphicsApi.DirectX => "directx", - CacheGraphicsApi.Metal => "metal", - CacheGraphicsApi.Guest => "guest", - _ => throw new NotImplementedException(graphicsApi.ToString()), - }; - - return Path.Combine(baseCacheDirectory, graphicsApiName, shaderProvider, cacheName); - } - - /// <summary> - /// Read a cached file with the given hash that is present in the archive. - /// </summary> - /// <param name="archive">The archive in use</param> - /// <param name="entry">The given hash</param> - /// <returns>The cached file if present or null</returns> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static byte[] ReadFromArchive(ZipFile archive, Hash128 entry) - { - if (archive != null) - { - ZipEntry archiveEntry = archive.GetEntry($"{entry}"); - - if (archiveEntry != null) - { - try - { - byte[] result = new byte[archiveEntry.Size]; - - using (Stream archiveStream = archive.GetInputStream(archiveEntry)) - { - archiveStream.Read(result); - - return result; - } - } - catch (Exception e) - { - Logger.Error?.Print(LogClass.Gpu, $"Cannot load cache file {entry} from archive"); - Logger.Error?.Print(LogClass.Gpu, e.ToString()); - } - } - } - - return null; - } - - /// <summary> - /// Read a cached file with the given hash that is not present in the archive. - /// </summary> - /// <param name="cacheDirectory">The cache directory</param> - /// <param name="entry">The given hash</param> - /// <returns>The cached file if present or null</returns> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static byte[] ReadFromFile(string cacheDirectory, Hash128 entry) - { - string cacheTempFilePath = GenCacheTempFilePath(cacheDirectory, entry); - - try - { - return File.ReadAllBytes(cacheTempFilePath); - } - catch (Exception e) - { - Logger.Error?.Print(LogClass.Gpu, $"Cannot load cache file at {cacheTempFilePath}"); - Logger.Error?.Print(LogClass.Gpu, e.ToString()); - } - - return null; - } - - /// <summary> - /// Read transform feedback descriptors from guest. - /// </summary> - /// <param name="data">The raw guest transform feedback descriptors</param> - /// <param name="header">The guest shader program header</param> - /// <returns>The transform feedback descriptors read from guest</returns> - public static TransformFeedbackDescriptorOld[] ReadTransformFeedbackInformation(ref ReadOnlySpan<byte> data, GuestShaderCacheHeader header) - { - if (header.TransformFeedbackCount != 0) - { - TransformFeedbackDescriptorOld[] result = new TransformFeedbackDescriptorOld[header.TransformFeedbackCount]; - - for (int i = 0; i < result.Length; i++) - { - GuestShaderCacheTransformFeedbackHeader feedbackHeader = MemoryMarshal.Read<GuestShaderCacheTransformFeedbackHeader>(data); - - result[i] = new TransformFeedbackDescriptorOld(feedbackHeader.BufferIndex, feedbackHeader.Stride, data.Slice(Unsafe.SizeOf<GuestShaderCacheTransformFeedbackHeader>(), feedbackHeader.VaryingLocationsLength).ToArray()); - - data = data.Slice(Unsafe.SizeOf<GuestShaderCacheTransformFeedbackHeader>() + feedbackHeader.VaryingLocationsLength); - } - - return result; - } - - return null; - } - - /// <summary> - /// Save temporary files not in archive. - /// </summary> - /// <param name="baseCacheDirectory">The base of the cache directory</param> - /// <param name="archive">The archive to use</param> - /// <param name="entries">The entries in the cache</param> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void EnsureArchiveUpToDate(string baseCacheDirectory, ZipFile archive, HashSet<Hash128> entries) - { - List<string> filesToDelete = new List<string>(); - - archive.BeginUpdate(); - - foreach (Hash128 hash in entries) - { - string cacheTempFilePath = GenCacheTempFilePath(baseCacheDirectory, hash); - - if (File.Exists(cacheTempFilePath)) - { - string cacheHash = $"{hash}"; - - ZipEntry entry = archive.GetEntry(cacheHash); - - if (entry != null) - { - archive.Delete(entry); - } - - // We enforce deflate compression here to avoid possible incompatibilities on older version of Ryujinx that use System.IO.Compression. - archive.Add(new StaticDiskDataSource(cacheTempFilePath), cacheHash, CompressionMethod.Deflated); - filesToDelete.Add(cacheTempFilePath); - } - } - - archive.CommitUpdate(); - - foreach (string filePath in filesToDelete) - { - File.Delete(filePath); - } - } - - public static bool IsArchiveReadOnly(string archivePath) - { - FileInfo info = new FileInfo(archivePath); - - if (!info.Exists) - { - return false; - } - - try - { - using (FileStream stream = info.Open(FileMode.Open, FileAccess.Read, FileShare.None)) - { - return false; - } - } - catch (IOException) - { - return true; - } - } - } -} |