aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Shader/Cache
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Shader/Cache')
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/CacheCollection.cs617
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs273
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/CacheManager.cs168
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/Definition/CacheGraphicsApi.cs38
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/Definition/CacheHashType.cs13
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/Definition/CacheManifestHeader.cs97
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuAccessorHeader.cs67
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuStateFlags.cs10
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheEntry.cs88
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheEntryHeader.cs69
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheHeader.cs42
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheTransformFeedbackHeader.cs38
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestTextureDescriptor.cs41
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntry.cs222
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntryHeader.cs114
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheHeader.cs42
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/Migration.cs258
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/Cache/TransformFeedbackDescriptorOld.cs19
18 files changed, 0 insertions, 2216 deletions
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/CacheCollection.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/CacheCollection.cs
deleted file mode 100644
index a98531f6..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/CacheCollection.cs
+++ /dev/null
@@ -1,617 +0,0 @@
-using ICSharpCode.SharpZipLib.Zip;
-using Ryujinx.Common;
-using Ryujinx.Common.Logging;
-using Ryujinx.Graphics.Gpu.Shader.Cache.Definition;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Threading;
-
-namespace Ryujinx.Graphics.Gpu.Shader.Cache
-{
- /// <summary>
- /// Represent a cache collection handling one shader cache.
- /// </summary>
- class CacheCollection : IDisposable
- {
- /// <summary>
- /// Possible operation to do on the <see cref="_fileWriterWorkerQueue"/>.
- /// </summary>
- private enum CacheFileOperation
- {
- /// <summary>
- /// Save a new entry in the temp cache.
- /// </summary>
- SaveTempEntry,
-
- /// <summary>
- /// Save the hash manifest.
- /// </summary>
- SaveManifest,
-
- /// <summary>
- /// Remove entries from the hash manifest and save it.
- /// </summary>
- RemoveManifestEntries,
-
- /// <summary>
- /// Remove entries from the hash manifest and save it, and also deletes the temporary file.
- /// </summary>
- RemoveManifestEntryAndTempFile,
-
- /// <summary>
- /// Flush temporary cache to archive.
- /// </summary>
- FlushToArchive,
-
- /// <summary>
- /// Signal when hitting this point. This is useful to know if all previous operations were performed.
- /// </summary>
- Synchronize
- }
-
- /// <summary>
- /// Represent an operation to perform on the <see cref="_fileWriterWorkerQueue"/>.
- /// </summary>
- private class CacheFileOperationTask
- {
- /// <summary>
- /// The type of operation to perform.
- /// </summary>
- public CacheFileOperation Type;
-
- /// <summary>
- /// The data associated to this operation or null.
- /// </summary>
- public object Data;
- }
-
- /// <summary>
- /// Data associated to the <see cref="CacheFileOperation.SaveTempEntry"/> operation.
- /// </summary>
- private class CacheFileSaveEntryTaskData
- {
- /// <summary>
- /// The key of the entry to cache.
- /// </summary>
- public Hash128 Key;
-
- /// <summary>
- /// The value of the entry to cache.
- /// </summary>
- public byte[] Value;
- }
-
- /// <summary>
- /// The directory of the shader cache.
- /// </summary>
- private readonly string _cacheDirectory;
-
- /// <summary>
- /// The version of the cache.
- /// </summary>
- private readonly ulong _version;
-
- /// <summary>
- /// The hash type of the cache.
- /// </summary>
- private readonly CacheHashType _hashType;
-
- /// <summary>
- /// The graphics API of the cache.
- /// </summary>
- private readonly CacheGraphicsApi _graphicsApi;
-
- /// <summary>
- /// The table of all the hash registered in the cache.
- /// </summary>
- private HashSet<Hash128> _hashTable;
-
- /// <summary>
- /// The queue of operations to be performed by the file writer worker.
- /// </summary>
- private AsyncWorkQueue<CacheFileOperationTask> _fileWriterWorkerQueue;
-
- /// <summary>
- /// Main storage of the cache collection.
- /// </summary>
- private ZipFile _cacheArchive;
-
- /// <summary>
- /// Indicates if the cache collection supports modification.
- /// </summary>
- public bool IsReadOnly { get; }
-
- /// <summary>
- /// Immutable copy of the hash table.
- /// </summary>
- public ReadOnlySpan<Hash128> HashTable => _hashTable.ToArray();
-
- /// <summary>
- /// Get the temp path to the cache data directory.
- /// </summary>
- /// <returns>The temp path to the cache data directory</returns>
- private string GetCacheTempDataPath() => CacheHelper.GetCacheTempDataPath(_cacheDirectory);
-
- /// <summary>
- /// The path to the cache archive file.
- /// </summary>
- /// <returns>The path to the cache archive file</returns>
- private string GetArchivePath() => CacheHelper.GetArchivePath(_cacheDirectory);
-
- /// <summary>
- /// The path to the cache manifest file.
- /// </summary>
- /// <returns>The path to the cache manifest file</returns>
- private string GetManifestPath() => CacheHelper.GetManifestPath(_cacheDirectory);
-
- /// <summary>
- /// Create a new temp path to the given cached file via its hash.
- /// </summary>
- /// <param name="key">The hash of the cached data</param>
- /// <returns>New path to the given cached file</returns>
- private string GenCacheTempFilePath(Hash128 key) => CacheHelper.GenCacheTempFilePath(_cacheDirectory, key);
-
- /// <summary>
- /// Create a new cache collection.
- /// </summary>
- /// <param name="baseCacheDirectory">The directory of the shader cache</param>
- /// <param name="hashType">The hash type of the shader cache</param>
- /// <param name="graphicsApi">The graphics api of the shader cache</param>
- /// <param name="shaderProvider">The shader provider name of the shader cache</param>
- /// <param name="cacheName">The name of the cache</param>
- /// <param name="version">The version of the cache</param>
- public CacheCollection(string baseCacheDirectory, CacheHashType hashType, CacheGraphicsApi graphicsApi, string shaderProvider, string cacheName, ulong version)
- {
- if (hashType != CacheHashType.XxHash128)
- {
- throw new NotImplementedException($"{hashType}");
- }
-
- _cacheDirectory = CacheHelper.GenerateCachePath(baseCacheDirectory, graphicsApi, shaderProvider, cacheName);
- _graphicsApi = graphicsApi;
- _hashType = hashType;
- _version = version;
- _hashTable = new HashSet<Hash128>();
- IsReadOnly = CacheHelper.IsArchiveReadOnly(GetArchivePath());
-
- Load();
-
- _fileWriterWorkerQueue = new AsyncWorkQueue<CacheFileOperationTask>(HandleCacheTask, $"CacheCollection.Worker.{cacheName}");
- }
-
- /// <summary>
- /// Load the cache manifest file and recreate it if invalid.
- /// </summary>
- private void Load()
- {
- bool isValid = false;
-
- if (Directory.Exists(_cacheDirectory))
- {
- string manifestPath = GetManifestPath();
-
- if (File.Exists(manifestPath))
- {
- Memory<byte> rawManifest = File.ReadAllBytes(manifestPath);
-
- if (MemoryMarshal.TryRead(rawManifest.Span, out CacheManifestHeader manifestHeader))
- {
- Memory<byte> hashTableRaw = rawManifest.Slice(Unsafe.SizeOf<CacheManifestHeader>());
-
- isValid = manifestHeader.IsValid(_graphicsApi, _hashType, hashTableRaw.Span) && _version == manifestHeader.Version;
-
- if (isValid)
- {
- ReadOnlySpan<Hash128> hashTable = MemoryMarshal.Cast<byte, Hash128>(hashTableRaw.Span);
-
- foreach (Hash128 hash in hashTable)
- {
- _hashTable.Add(hash);
- }
- }
- }
- }
- }
-
- if (!isValid)
- {
- Logger.Warning?.Print(LogClass.Gpu, $"Shader collection \"{_cacheDirectory}\" got invalidated, cache will need to be rebuilt.");
-
- if (Directory.Exists(_cacheDirectory))
- {
- Directory.Delete(_cacheDirectory, true);
- }
-
- Directory.CreateDirectory(_cacheDirectory);
-
- SaveManifest();
- }
-
- FlushToArchive();
- }
-
- /// <summary>
- /// Queue a task to remove entries from the hash manifest.
- /// </summary>
- /// <param name="entries">Entries to remove from the manifest</param>
- public void RemoveManifestEntriesAsync(HashSet<Hash128> entries)
- {
- if (IsReadOnly)
- {
- Logger.Warning?.Print(LogClass.Gpu, "Trying to remove manifest entries on a read-only cache, ignoring.");
-
- return;
- }
-
- _fileWriterWorkerQueue.Add(new CacheFileOperationTask
- {
- Type = CacheFileOperation.RemoveManifestEntries,
- Data = entries
- });
- }
-
- /// <summary>
- /// Remove given entries from the manifest.
- /// </summary>
- /// <param name="entries">Entries to remove from the manifest</param>
- private void RemoveManifestEntries(HashSet<Hash128> entries)
- {
- lock (_hashTable)
- {
- foreach (Hash128 entry in entries)
- {
- _hashTable.Remove(entry);
- }
-
- SaveManifest();
- }
- }
-
- /// <summary>
- /// Remove given entry from the manifest and delete the temporary file.
- /// </summary>
- /// <param name="entry">Entry to remove from the manifest</param>
- private void RemoveManifestEntryAndTempFile(Hash128 entry)
- {
- lock (_hashTable)
- {
- _hashTable.Remove(entry);
- SaveManifest();
- }
-
- File.Delete(GenCacheTempFilePath(entry));
- }
-
- /// <summary>
- /// Queue a task to flush temporary files to the archive on the worker.
- /// </summary>
- public void FlushToArchiveAsync()
- {
- _fileWriterWorkerQueue.Add(new CacheFileOperationTask
- {
- Type = CacheFileOperation.FlushToArchive
- });
- }
-
- /// <summary>
- /// Wait for all tasks before this given point to be done.
- /// </summary>
- public void Synchronize()
- {
- using (ManualResetEvent evnt = new ManualResetEvent(false))
- {
- _fileWriterWorkerQueue.Add(new CacheFileOperationTask
- {
- Type = CacheFileOperation.Synchronize,
- Data = evnt
- });
-
- evnt.WaitOne();
- }
- }
-
- /// <summary>
- /// Flush temporary files to the archive.
- /// </summary>
- /// <remarks>This dispose <see cref="_cacheArchive"/> if not null and reinstantiate it.</remarks>
- private void FlushToArchive()
- {
- EnsureArchiveUpToDate();
-
- // Open the zip in readonly to avoid anyone modifying/corrupting it during normal operations.
- _cacheArchive = new ZipFile(File.OpenRead(GetArchivePath()));
- }
-
- /// <summary>
- /// Save temporary files not in archive.
- /// </summary>
- /// <remarks>This dispose <see cref="_cacheArchive"/> if not null.</remarks>
- public void EnsureArchiveUpToDate()
- {
- // First close previous opened instance if found.
- if (_cacheArchive != null)
- {
- _cacheArchive.Close();
- }
-
- string archivePath = GetArchivePath();
-
- if (IsReadOnly)
- {
- Logger.Warning?.Print(LogClass.Gpu, $"Cache collection archive in read-only, archiving task skipped.");
-
- return;
- }
-
- if (CacheHelper.IsArchiveReadOnly(archivePath))
- {
- Logger.Warning?.Print(LogClass.Gpu, $"Cache collection archive in use, archiving task skipped.");
-
- return;
- }
-
- if (!File.Exists(archivePath))
- {
- using (ZipFile newZip = ZipFile.Create(archivePath))
- {
- // Workaround for SharpZipLib issue #395
- newZip.BeginUpdate();
- newZip.CommitUpdate();
- }
- }
-
- // Open the zip in read/write.
- _cacheArchive = new ZipFile(File.Open(archivePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None));
-
- Logger.Info?.Print(LogClass.Gpu, $"Updating cache collection archive {archivePath}...");
-
- // Update the content of the zip.
- lock (_hashTable)
- {
- CacheHelper.EnsureArchiveUpToDate(_cacheDirectory, _cacheArchive, _hashTable);
-
- // Close the instance to force a flush.
- _cacheArchive.Close();
- _cacheArchive = null;
-
- string cacheTempDataPath = GetCacheTempDataPath();
-
- // Create the cache data path if missing.
- if (!Directory.Exists(cacheTempDataPath))
- {
- Directory.CreateDirectory(cacheTempDataPath);
- }
- }
-
- Logger.Info?.Print(LogClass.Gpu, $"Updated cache collection archive {archivePath}.");
- }
-
- /// <summary>
- /// Save the manifest file.
- /// </summary>
- private void SaveManifest()
- {
- byte[] data;
-
- lock (_hashTable)
- {
- data = CacheHelper.ComputeManifest(_version, _graphicsApi, _hashType, _hashTable);
- }
-
- File.WriteAllBytes(GetManifestPath(), data);
- }
-
- /// <summary>
- /// Get a cached file with the given hash.
- /// </summary>
- /// <param name="keyHash">The given hash</param>
- /// <returns>The cached file if present or null</returns>
- public byte[] GetValueRaw(ref Hash128 keyHash)
- {
- return GetValueRawFromArchive(ref keyHash) ?? GetValueRawFromFile(ref keyHash);
- }
-
- /// <summary>
- /// Get a cached file with the given hash that is present in the archive.
- /// </summary>
- /// <param name="keyHash">The given hash</param>
- /// <returns>The cached file if present or null</returns>
- private byte[] GetValueRawFromArchive(ref Hash128 keyHash)
- {
- bool found;
-
- lock (_hashTable)
- {
- found = _hashTable.Contains(keyHash);
- }
-
- if (found)
- {
- return CacheHelper.ReadFromArchive(_cacheArchive, keyHash);
- }
-
- return null;
- }
-
- /// <summary>
- /// Get a cached file with the given hash that is not present in the archive.
- /// </summary>
- /// <param name="keyHash">The given hash</param>
- /// <returns>The cached file if present or null</returns>
- private byte[] GetValueRawFromFile(ref Hash128 keyHash)
- {
- bool found;
-
- lock (_hashTable)
- {
- found = _hashTable.Contains(keyHash);
- }
-
- if (found)
- {
- return CacheHelper.ReadFromFile(GetCacheTempDataPath(), keyHash);
- }
-
- return null;
- }
-
- private void HandleCacheTask(CacheFileOperationTask task)
- {
- switch (task.Type)
- {
- case CacheFileOperation.SaveTempEntry:
- SaveTempEntry((CacheFileSaveEntryTaskData)task.Data);
- break;
- case CacheFileOperation.SaveManifest:
- SaveManifest();
- break;
- case CacheFileOperation.RemoveManifestEntries:
- RemoveManifestEntries((HashSet<Hash128>)task.Data);
- break;
- case CacheFileOperation.RemoveManifestEntryAndTempFile:
- RemoveManifestEntryAndTempFile((Hash128)task.Data);
- break;
- case CacheFileOperation.FlushToArchive:
- FlushToArchive();
- break;
- case CacheFileOperation.Synchronize:
- ((ManualResetEvent)task.Data).Set();
- break;
- default:
- throw new NotImplementedException($"{task.Type}");
- }
-
- }
-
- /// <summary>
- /// Save a new entry in the temp cache.
- /// </summary>
- /// <param name="entry">The entry to save in the temp cache</param>
- private void SaveTempEntry(CacheFileSaveEntryTaskData entry)
- {
- string tempPath = GenCacheTempFilePath(entry.Key);
-
- File.WriteAllBytes(tempPath, entry.Value);
- }
-
- /// <summary>
- /// Add a new value in the cache with a given hash.
- /// </summary>
- /// <param name="keyHash">The hash to use for the value in the cache</param>
- /// <param name="value">The value to cache</param>
- public void AddValue(ref Hash128 keyHash, byte[] value)
- {
- if (IsReadOnly)
- {
- Logger.Warning?.Print(LogClass.Gpu, $"Trying to add {keyHash} on a read-only cache, ignoring.");
-
- return;
- }
-
- Debug.Assert(value != null);
-
- bool isAlreadyPresent;
-
- lock (_hashTable)
- {
- isAlreadyPresent = !_hashTable.Add(keyHash);
- }
-
- if (isAlreadyPresent)
- {
- // NOTE: Used for debug
- File.WriteAllBytes(GenCacheTempFilePath(new Hash128()), value);
-
- throw new InvalidOperationException($"Cache collision found on {GenCacheTempFilePath(keyHash)}");
- }
-
- // Queue file change operations
- _fileWriterWorkerQueue.Add(new CacheFileOperationTask
- {
- Type = CacheFileOperation.SaveTempEntry,
- Data = new CacheFileSaveEntryTaskData
- {
- Key = keyHash,
- Value = value
- }
- });
-
- // Save the manifest changes
- _fileWriterWorkerQueue.Add(new CacheFileOperationTask
- {
- Type = CacheFileOperation.SaveManifest,
- });
- }
-
- /// <summary>
- /// Replace a value at the given hash in the cache.
- /// </summary>
- /// <param name="keyHash">The hash to use for the value in the cache</param>
- /// <param name="value">The value to cache</param>
- public void ReplaceValue(ref Hash128 keyHash, byte[] value)
- {
- if (IsReadOnly)
- {
- Logger.Warning?.Print(LogClass.Gpu, $"Trying to replace {keyHash} on a read-only cache, ignoring.");
-
- return;
- }
-
- Debug.Assert(value != null);
-
- // Only queue file change operations
- _fileWriterWorkerQueue.Add(new CacheFileOperationTask
- {
- Type = CacheFileOperation.SaveTempEntry,
- Data = new CacheFileSaveEntryTaskData
- {
- Key = keyHash,
- Value = value
- }
- });
- }
-
- /// <summary>
- /// Removes a value at the given hash from the cache.
- /// </summary>
- /// <param name="keyHash">The hash of the value in the cache</param>
- public void RemoveValue(ref Hash128 keyHash)
- {
- if (IsReadOnly)
- {
- Logger.Warning?.Print(LogClass.Gpu, $"Trying to remove {keyHash} on a read-only cache, ignoring.");
-
- return;
- }
-
- // Only queue file change operations
- _fileWriterWorkerQueue.Add(new CacheFileOperationTask
- {
- Type = CacheFileOperation.RemoveManifestEntryAndTempFile,
- Data = keyHash
- });
- }
-
- public void Dispose()
- {
- Dispose(true);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- // Make sure all operations on _fileWriterWorkerQueue are done.
- Synchronize();
-
- _fileWriterWorkerQueue.Dispose();
- EnsureArchiveUpToDate();
- }
- }
- }
-}
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;
- }
- }
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/CacheManager.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/CacheManager.cs
deleted file mode 100644
index e67221e7..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/CacheManager.cs
+++ /dev/null
@@ -1,168 +0,0 @@
-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);
-
- _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();
- }
- }
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/CacheGraphicsApi.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/CacheGraphicsApi.cs
deleted file mode 100644
index 9f8b5c39..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/CacheGraphicsApi.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
-{
- /// <summary>
- /// Graphics API type accepted by the shader cache.
- /// </summary>
- enum CacheGraphicsApi : byte
- {
- /// <summary>
- /// OpenGL Core
- /// </summary>
- OpenGL,
-
- /// <summary>
- /// OpenGL ES
- /// </summary>
- OpenGLES,
-
- /// <summary>
- /// Vulkan
- /// </summary>
- Vulkan,
-
- /// <summary>
- /// DirectX
- /// </summary>
- DirectX,
-
- /// <summary>
- /// Metal
- /// </summary>
- Metal,
-
- /// <summary>
- /// Guest, used to cache games raw shader programs.
- /// </summary>
- Guest
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/CacheHashType.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/CacheHashType.cs
deleted file mode 100644
index e4ebe416..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/CacheHashType.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
-{
- /// <summary>
- /// Hash algorithm accepted by the shader cache.
- /// </summary>
- enum CacheHashType : byte
- {
- /// <summary>
- /// xxHash128
- /// </summary>
- XxHash128
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/CacheManifestHeader.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/CacheManifestHeader.cs
deleted file mode 100644
index 0601451d..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/CacheManifestHeader.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
-{
- /// <summary>
- /// Header of the shader cache manifest.
- /// </summary>
- [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x10)]
- struct CacheManifestHeader
- {
- /// <summary>
- /// The version of the cache.
- /// </summary>
- public ulong Version;
-
- /// <summary>
- /// The graphics api used for this cache.
- /// </summary>
- public CacheGraphicsApi GraphicsApi;
-
- /// <summary>
- /// The hash type used for this cache.
- /// </summary>
- public CacheHashType HashType;
-
- /// <summary>
- /// CRC-16 checksum over the data in the file.
- /// </summary>
- public ushort TableChecksum;
-
- /// <summary>
- /// Construct a new cache manifest header.
- /// </summary>
- /// <param name="version">The version of the cache</param>
- /// <param name="graphicsApi">The graphics api used for this cache</param>
- /// <param name="hashType">The hash type used for this cache</param>
- public CacheManifestHeader(ulong version, CacheGraphicsApi graphicsApi, CacheHashType hashType)
- {
- Version = version;
- GraphicsApi = graphicsApi;
- HashType = hashType;
- TableChecksum = 0;
- }
-
- /// <summary>
- /// Update the checksum in the header.
- /// </summary>
- /// <param name="data">The data to perform the checksum on</param>
- public void UpdateChecksum(ReadOnlySpan<byte> data)
- {
- TableChecksum = CalculateCrc16(data);
- }
-
- /// <summary>
- /// Calculate a CRC-16 over data.
- /// </summary>
- /// <param name="data">The data to perform the CRC-16 on</param>
- /// <returns>A CRC-16 over data</returns>
- private static ushort CalculateCrc16(ReadOnlySpan<byte> data)
- {
- int crc = 0;
-
- const ushort poly = 0x1021;
-
- for (int i = 0; i < data.Length; i++)
- {
- crc ^= data[i] << 8;
-
- for (int j = 0; j < 8; j++)
- {
- crc <<= 1;
-
- if ((crc & 0x10000) != 0)
- {
- crc = (crc ^ poly) & 0xFFFF;
- }
- }
- }
-
- return (ushort)crc;
- }
-
- /// <summary>
- /// Check the validity of the header.
- /// </summary>
- /// <param name="graphicsApi">The target graphics api in use</param>
- /// <param name="hashType">The target hash type in use</param>
- /// <param name="data">The data after this header</param>
- /// <returns>True if the header is valid</returns>
- /// <remarks>This doesn't check that versions match</remarks>
- public bool IsValid(CacheGraphicsApi graphicsApi, CacheHashType hashType, ReadOnlySpan<byte> data)
- {
- return GraphicsApi == graphicsApi && HashType == hashType && TableChecksum == CalculateCrc16(data);
- }
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuAccessorHeader.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuAccessorHeader.cs
deleted file mode 100644
index 2e044750..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuAccessorHeader.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using Ryujinx.Graphics.Shader;
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
-{
- /// <summary>
- /// Header of a cached guest gpu accessor.
- /// </summary>
- [StructLayout(LayoutKind.Sequential, Size = 0x20, Pack = 1)]
- struct GuestGpuAccessorHeader
- {
- /// <summary>
- /// The count of texture descriptors.
- /// </summary>
- public int TextureDescriptorCount;
-
- /// <summary>
- /// Local Size X for compute shaders.
- /// </summary>
- public int ComputeLocalSizeX;
-
- /// <summary>
- /// Local Size Y for compute shaders.
- /// </summary>
- public int ComputeLocalSizeY;
-
- /// <summary>
- /// Local Size Z for compute shaders.
- /// </summary>
- public int ComputeLocalSizeZ;
-
- /// <summary>
- /// Local Memory size in bytes for compute shaders.
- /// </summary>
- public int ComputeLocalMemorySize;
-
- /// <summary>
- /// Shared Memory size in bytes for compute shaders.
- /// </summary>
- public int ComputeSharedMemorySize;
-
- /// <summary>
- /// Unused/reserved.
- /// </summary>
- public int Reserved1;
-
- /// <summary>
- /// Current primitive topology for geometry shaders.
- /// </summary>
- public InputTopology PrimitiveTopology;
-
- /// <summary>
- /// Tessellation parameters (packed to fit on a byte).
- /// </summary>
- public byte TessellationModePacked;
-
- /// <summary>
- /// Unused/reserved.
- /// </summary>
- public byte Reserved2;
-
- /// <summary>
- /// GPU boolean state that can influence shader compilation.
- /// </summary>
- public GuestGpuStateFlags StateFlags;
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuStateFlags.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuStateFlags.cs
deleted file mode 100644
index 4b1fbb06..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuStateFlags.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System;
-
-namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
-{
- [Flags]
- enum GuestGpuStateFlags : byte
- {
- EarlyZForce = 1 << 0
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheEntry.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheEntry.cs
deleted file mode 100644
index 373fa6c6..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheEntry.cs
+++ /dev/null
@@ -1,88 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
-{
- /// <summary>
- /// Represent a cached shader entry in a guest shader program.
- /// </summary>
- class GuestShaderCacheEntry
- {
- /// <summary>
- /// The header of the cached shader entry.
- /// </summary>
- public GuestShaderCacheEntryHeader Header { get; }
-
- /// <summary>
- /// The code of this shader.
- /// </summary>
- /// <remarks>If a Vertex A is present, this also contains the code 2 section.</remarks>
- public byte[] Code { get; }
-
- /// <summary>
- /// The textures descriptors used for this shader.
- /// </summary>
- public Dictionary<int, GuestTextureDescriptor> TextureDescriptors { get; }
-
- /// <summary>
- /// Create a new instance of <see cref="GuestShaderCacheEntry"/>.
- /// </summary>
- /// <param name="header">The header of the cached shader entry</param>
- /// <param name="code">The code of this shader</param>
- public GuestShaderCacheEntry(GuestShaderCacheEntryHeader header, byte[] code)
- {
- Header = header;
- Code = code;
- TextureDescriptors = new Dictionary<int, GuestTextureDescriptor>();
- }
-
- /// <summary>
- /// Parse a raw cached user shader program into an array of shader cache entry.
- /// </summary>
- /// <param name="data">The raw cached user shader program</param>
- /// <param name="fileHeader">The user shader program header</param>
- /// <returns>An array of shader cache entry</returns>
- public static GuestShaderCacheEntry[] Parse(ref ReadOnlySpan<byte> data, out GuestShaderCacheHeader fileHeader)
- {
- fileHeader = MemoryMarshal.Read<GuestShaderCacheHeader>(data);
-
- data = data.Slice(Unsafe.SizeOf<GuestShaderCacheHeader>());
-
- ReadOnlySpan<GuestShaderCacheEntryHeader> entryHeaders = MemoryMarshal.Cast<byte, GuestShaderCacheEntryHeader>(data.Slice(0, fileHeader.Count * Unsafe.SizeOf<GuestShaderCacheEntryHeader>()));
-
- data = data.Slice(fileHeader.Count * Unsafe.SizeOf<GuestShaderCacheEntryHeader>());
-
- GuestShaderCacheEntry[] result = new GuestShaderCacheEntry[fileHeader.Count];
-
- for (int i = 0; i < result.Length; i++)
- {
- GuestShaderCacheEntryHeader header = entryHeaders[i];
-
- // Ignore empty entries
- if (header.Size == 0 && header.SizeA == 0)
- {
- continue;
- }
-
- byte[] code = data.Slice(0, header.Size + header.SizeA).ToArray();
-
- data = data.Slice(header.Size + header.SizeA);
-
- result[i] = new GuestShaderCacheEntry(header, code);
-
- ReadOnlySpan<GuestTextureDescriptor> textureDescriptors = MemoryMarshal.Cast<byte, GuestTextureDescriptor>(data.Slice(0, header.GpuAccessorHeader.TextureDescriptorCount * Unsafe.SizeOf<GuestTextureDescriptor>()));
-
- foreach (GuestTextureDescriptor textureDescriptor in textureDescriptors)
- {
- result[i].TextureDescriptors.Add((int)textureDescriptor.Handle, textureDescriptor);
- }
-
- data = data.Slice(header.GpuAccessorHeader.TextureDescriptorCount * Unsafe.SizeOf<GuestTextureDescriptor>());
- }
-
- return result;
- }
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheEntryHeader.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheEntryHeader.cs
deleted file mode 100644
index 9b22cac5..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheEntryHeader.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-using Ryujinx.Graphics.Shader;
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
-{
- /// <summary>
- /// The header of a guest shader entry in a guest shader program.
- /// </summary>
- [StructLayout(LayoutKind.Sequential, Pack = 0x1, Size = 0x30)]
- struct GuestShaderCacheEntryHeader
- {
- /// <summary>
- /// The stage of this shader.
- /// </summary>
- public ShaderStage Stage;
-
- /// <summary>
- /// Unused/reserved.
- /// </summary>
- public byte Reserved1;
-
- /// <summary>
- /// Unused/reserved.
- /// </summary>
- public byte Reserved2;
-
- /// <summary>
- /// Unused/reserved.
- /// </summary>
- public byte Reserved3;
-
- /// <summary>
- /// The size of the code section.
- /// </summary>
- public int Size;
-
- /// <summary>
- /// The size of the code2 section if present. (Vertex A)
- /// </summary>
- public int SizeA;
-
- /// <summary>
- /// Constant buffer 1 data size.
- /// </summary>
- public int Cb1DataSize;
-
- /// <summary>
- /// The header of the cached gpu accessor.
- /// </summary>
- public GuestGpuAccessorHeader GpuAccessorHeader;
-
- /// <summary>
- /// Create a new guest shader entry header.
- /// </summary>
- /// <param name="stage">The stage of this shader</param>
- /// <param name="size">The size of the code section</param>
- /// <param name="sizeA">The size of the code2 section if present (Vertex A)</param>
- /// <param name="cb1DataSize">Constant buffer 1 data size</param>
- /// <param name="gpuAccessorHeader">The header of the cached gpu accessor</param>
- public GuestShaderCacheEntryHeader(ShaderStage stage, int size, int sizeA, int cb1DataSize, GuestGpuAccessorHeader gpuAccessorHeader) : this()
- {
- Stage = stage;
- Size = size;
- SizeA = sizeA;
- Cb1DataSize = cb1DataSize;
- GpuAccessorHeader = gpuAccessorHeader;
- }
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheHeader.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheHeader.cs
deleted file mode 100644
index 700be47d..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheHeader.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
-{
- /// <summary>
- /// The header of a shader program in the guest cache.
- /// </summary>
- [StructLayout(LayoutKind.Sequential, Pack = 0x1, Size = 0x10)]
- struct GuestShaderCacheHeader
- {
- /// <summary>
- /// The count of shaders defining this program.
- /// </summary>
- public byte Count;
-
- /// <summary>
- /// The count of transform feedback data used in this program.
- /// </summary>
- public byte TransformFeedbackCount;
-
- /// <summary>
- /// Unused/reserved.
- /// </summary>
- public ushort Reserved1;
-
- /// <summary>
- /// Unused/reserved.
- /// </summary>
- public ulong Reserved2;
-
- /// <summary>
- /// Create a new guest shader cache header.
- /// </summary>
- /// <param name="count">The count of shaders defining this program</param>
- /// <param name="transformFeedbackCount">The count of transform feedback data used in this program</param>
- public GuestShaderCacheHeader(byte count, byte transformFeedbackCount) : this()
- {
- Count = count;
- TransformFeedbackCount = transformFeedbackCount;
- }
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheTransformFeedbackHeader.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheTransformFeedbackHeader.cs
deleted file mode 100644
index 18cfdf55..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestShaderCacheTransformFeedbackHeader.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
-{
- /// <summary>
- /// Header for transform feedback.
- /// </summary>
- [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x10)]
- struct GuestShaderCacheTransformFeedbackHeader
- {
- /// <summary>
- /// The buffer index of the transform feedback.
- /// </summary>
- public int BufferIndex;
-
- /// <summary>
- /// The stride of the transform feedback.
- /// </summary>
- public int Stride;
-
- /// <summary>
- /// The length of the varying location buffer of the transform feedback.
- /// </summary>
- public int VaryingLocationsLength;
-
- /// <summary>
- /// Reserved/unused.
- /// </summary>
- public int Reserved1;
-
- public GuestShaderCacheTransformFeedbackHeader(int bufferIndex, int stride, int varyingLocationsLength) : this()
- {
- BufferIndex = bufferIndex;
- Stride = stride;
- VaryingLocationsLength = varyingLocationsLength;
- }
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestTextureDescriptor.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestTextureDescriptor.cs
deleted file mode 100644
index 9491496d..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestTextureDescriptor.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using Ryujinx.Graphics.Gpu.Image;
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
-{
- /// <summary>
- /// Contains part of TextureDescriptor from <see cref="Image"/> used for shader codegen.
- /// </summary>
- [StructLayout(LayoutKind.Sequential, Size = 0xC, Pack = 1)]
- struct GuestTextureDescriptor : ITextureDescriptor
- {
- public uint Handle;
- public uint Format;
- public TextureTarget Target;
- [MarshalAs(UnmanagedType.I1)]
- public bool IsSrgb;
- [MarshalAs(UnmanagedType.I1)]
- public bool IsTextureCoordNormalized;
- public byte Reserved;
-
- public uint UnpackFormat()
- {
- return Format;
- }
-
- public bool UnpackSrgb()
- {
- return IsSrgb;
- }
-
- public bool UnpackTextureCoordNormalized()
- {
- return IsTextureCoordNormalized;
- }
-
- public TextureTarget UnpackTextureTarget()
- {
- return Target;
- }
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntry.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntry.cs
deleted file mode 100644
index fe79acb3..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntry.cs
+++ /dev/null
@@ -1,222 +0,0 @@
-using Ryujinx.Common;
-using Ryujinx.Graphics.Shader;
-using System;
-using System.IO;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
-{
- /// <summary>
- /// Host shader entry used for binding information.
- /// </summary>
- class HostShaderCacheEntry
- {
- /// <summary>
- /// The header of the cached shader entry.
- /// </summary>
- public HostShaderCacheEntryHeader Header { get; }
-
- /// <summary>
- /// Cached constant buffers.
- /// </summary>
- public BufferDescriptor[] CBuffers { get; }
-
- /// <summary>
- /// Cached storage buffers.
- /// </summary>
- public BufferDescriptor[] SBuffers { get; }
-
- /// <summary>
- /// Cached texture descriptors.
- /// </summary>
- public TextureDescriptor[] Textures { get; }
-
- /// <summary>
- /// Cached image descriptors.
- /// </summary>
- public TextureDescriptor[] Images { get; }
-
- /// <summary>
- /// Create a new instance of <see cref="HostShaderCacheEntry"/>.
- /// </summary>
- /// <param name="header">The header of the cached shader entry</param>
- /// <param name="cBuffers">Cached constant buffers</param>
- /// <param name="sBuffers">Cached storage buffers</param>
- /// <param name="textures">Cached texture descriptors</param>
- /// <param name="images">Cached image descriptors</param>
- private HostShaderCacheEntry(
- HostShaderCacheEntryHeader header,
- BufferDescriptor[] cBuffers,
- BufferDescriptor[] sBuffers,
- TextureDescriptor[] textures,
- TextureDescriptor[] images)
- {
- Header = header;
- CBuffers = cBuffers;
- SBuffers = sBuffers;
- Textures = textures;
- Images = images;
- }
-
- private HostShaderCacheEntry()
- {
- Header = new HostShaderCacheEntryHeader();
- CBuffers = new BufferDescriptor[0];
- SBuffers = new BufferDescriptor[0];
- Textures = new TextureDescriptor[0];
- Images = new TextureDescriptor[0];
- }
-
- private HostShaderCacheEntry(ShaderProgramInfo programInfo)
- {
- Header = new HostShaderCacheEntryHeader(programInfo.CBuffers.Count,
- programInfo.SBuffers.Count,
- programInfo.Textures.Count,
- programInfo.Images.Count,
- programInfo.UsesInstanceId,
- programInfo.UsesRtLayer,
- programInfo.ClipDistancesWritten,
- programInfo.FragmentOutputMap);
- CBuffers = programInfo.CBuffers.ToArray();
- SBuffers = programInfo.SBuffers.ToArray();
- Textures = programInfo.Textures.ToArray();
- Images = programInfo.Images.ToArray();
- }
-
- /// <summary>
- /// Convert the host shader entry to a <see cref="ShaderProgramInfo"/>.
- /// </summary>
- /// <returns>A new <see cref="ShaderProgramInfo"/> from this instance</returns>
- internal ShaderProgramInfo ToShaderProgramInfo()
- {
- return new ShaderProgramInfo(
- CBuffers,
- SBuffers,
- Textures,
- Images,
- default,
- Header.UseFlags.HasFlag(UseFlags.InstanceId),
- Header.UseFlags.HasFlag(UseFlags.RtLayer),
- Header.ClipDistancesWritten,
- Header.FragmentOutputMap);
- }
-
- /// <summary>
- /// Parse a raw cached user shader program into an array of shader cache entry.
- /// </summary>
- /// <param name="data">The raw cached host shader</param>
- /// <param name="programCode">The host shader program</param>
- /// <returns>An array of shader cache entry</returns>
- internal static HostShaderCacheEntry[] Parse(ReadOnlySpan<byte> data, out ReadOnlySpan<byte> programCode)
- {
- HostShaderCacheHeader fileHeader = MemoryMarshal.Read<HostShaderCacheHeader>(data);
-
- data = data.Slice(Unsafe.SizeOf<HostShaderCacheHeader>());
-
- ReadOnlySpan<HostShaderCacheEntryHeader> entryHeaders = MemoryMarshal.Cast<byte, HostShaderCacheEntryHeader>(data.Slice(0, fileHeader.Count * Unsafe.SizeOf<HostShaderCacheEntryHeader>()));
-
- data = data.Slice(fileHeader.Count * Unsafe.SizeOf<HostShaderCacheEntryHeader>());
-
- HostShaderCacheEntry[] result = new HostShaderCacheEntry[fileHeader.Count];
-
- for (int i = 0; i < result.Length; i++)
- {
- HostShaderCacheEntryHeader header = entryHeaders[i];
-
- if (!header.InUse)
- {
- continue;
- }
-
- int cBufferDescriptorsSize = header.CBuffersCount * Unsafe.SizeOf<BufferDescriptor>();
- int sBufferDescriptorsSize = header.SBuffersCount * Unsafe.SizeOf<BufferDescriptor>();
- int textureDescriptorsSize = header.TexturesCount * Unsafe.SizeOf<TextureDescriptor>();
- int imageDescriptorsSize = header.ImagesCount * Unsafe.SizeOf<TextureDescriptor>();
-
- ReadOnlySpan<BufferDescriptor> cBuffers = MemoryMarshal.Cast<byte, BufferDescriptor>(data.Slice(0, cBufferDescriptorsSize));
- data = data.Slice(cBufferDescriptorsSize);
-
- ReadOnlySpan<BufferDescriptor> sBuffers = MemoryMarshal.Cast<byte, BufferDescriptor>(data.Slice(0, sBufferDescriptorsSize));
- data = data.Slice(sBufferDescriptorsSize);
-
- ReadOnlySpan<TextureDescriptor> textureDescriptors = MemoryMarshal.Cast<byte, TextureDescriptor>(data.Slice(0, textureDescriptorsSize));
- data = data.Slice(textureDescriptorsSize);
-
- ReadOnlySpan<TextureDescriptor> imageDescriptors = MemoryMarshal.Cast<byte, TextureDescriptor>(data.Slice(0, imageDescriptorsSize));
- data = data.Slice(imageDescriptorsSize);
-
- result[i] = new HostShaderCacheEntry(header, cBuffers.ToArray(), sBuffers.ToArray(), textureDescriptors.ToArray(), imageDescriptors.ToArray());
- }
-
- programCode = data.Slice(0, fileHeader.CodeSize);
-
- return result;
- }
-
- /// <summary>
- /// Create a new host shader cache file.
- /// </summary>
- /// <param name="programCode">The host shader program</param>
- /// <param name="codeHolders">The shaders code holder</param>
- /// <returns>Raw data of a new host shader cache file</returns>
- internal static byte[] Create(ReadOnlySpan<byte> programCode, CachedShaderStage[] codeHolders)
- {
- HostShaderCacheHeader header = new HostShaderCacheHeader((byte)codeHolders.Length, programCode.Length);
-
- HostShaderCacheEntry[] entries = new HostShaderCacheEntry[codeHolders.Length];
-
- for (int i = 0; i < codeHolders.Length; i++)
- {
- if (codeHolders[i] == null)
- {
- entries[i] = new HostShaderCacheEntry();
- }
- else
- {
- entries[i] = new HostShaderCacheEntry(codeHolders[i].Info);
- }
- }
-
- using (MemoryStream stream = new MemoryStream())
- {
- BinaryWriter writer = new BinaryWriter(stream);
-
- writer.WriteStruct(header);
-
- foreach (HostShaderCacheEntry entry in entries)
- {
- writer.WriteStruct(entry.Header);
- }
-
- foreach (HostShaderCacheEntry entry in entries)
- {
- foreach (BufferDescriptor cBuffer in entry.CBuffers)
- {
- writer.WriteStruct(cBuffer);
- }
-
- foreach (BufferDescriptor sBuffer in entry.SBuffers)
- {
- writer.WriteStruct(sBuffer);
- }
-
- foreach (TextureDescriptor texture in entry.Textures)
- {
- writer.WriteStruct(texture);
- }
-
- foreach (TextureDescriptor image in entry.Images)
- {
- writer.WriteStruct(image);
- }
- }
-
- writer.Write(programCode);
-
- return stream.ToArray();
- }
- }
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntryHeader.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntryHeader.cs
deleted file mode 100644
index c3c0de22..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntryHeader.cs
+++ /dev/null
@@ -1,114 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
-{
- /// <summary>
- /// Flags indicating if the shader accesses certain built-ins, such as the instance ID.
- /// </summary>
- enum UseFlags : byte
- {
- /// <summary>
- /// None of the built-ins are used.
- /// </summary>
- None = 0,
-
- /// <summary>
- /// Indicates whenever the vertex shader reads the gl_InstanceID built-in.
- /// </summary>
- InstanceId = 1 << 0,
-
- /// <summary>
- /// Indicates whenever any of the VTG stages writes to the gl_Layer built-in.
- /// </summary>
- RtLayer = 1 << 1
- }
-
- /// <summary>
- /// Host shader entry header used for binding information.
- /// </summary>
- [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x18)]
- struct HostShaderCacheEntryHeader
- {
- /// <summary>
- /// Count of constant buffer descriptors.
- /// </summary>
- public int CBuffersCount;
-
- /// <summary>
- /// Count of storage buffer descriptors.
- /// </summary>
- public int SBuffersCount;
-
- /// <summary>
- /// Count of texture descriptors.
- /// </summary>
- public int TexturesCount;
-
- /// <summary>
- /// Count of image descriptors.
- /// </summary>
- public int ImagesCount;
-
- /// <summary>
- /// Flags indicating if the shader accesses certain built-ins, such as the instance ID.
- /// </summary>
- public UseFlags UseFlags;
-
- /// <summary>
- /// Set to true if this entry is in use.
- /// </summary>
- [MarshalAs(UnmanagedType.I1)]
- public bool InUse;
-
- /// <summary>
- /// Mask of clip distances that are written to on the shader.
- /// </summary>
- public byte ClipDistancesWritten;
-
- /// <summary>
- /// Reserved / unused.
- /// </summary>
- public byte Reserved;
-
- /// <summary>
- /// Mask of components written by the fragment shader stage.
- /// </summary>
- public int FragmentOutputMap;
-
- /// <summary>
- /// Create a new host shader cache entry header.
- /// </summary>
- /// <param name="cBuffersCount">Count of constant buffer descriptors</param>
- /// <param name="sBuffersCount">Count of storage buffer descriptors</param>
- /// <param name="texturesCount">Count of texture descriptors</param>
- /// <param name="imagesCount">Count of image descriptors</param>
- /// <param name="usesInstanceId">Set to true if the shader uses instance id</param>
- /// <param name="clipDistancesWritten">Mask of clip distances that are written to on the shader</param>
- /// <param name="fragmentOutputMap">Mask of components written by the fragment shader stage</param>
- public HostShaderCacheEntryHeader(
- int cBuffersCount,
- int sBuffersCount,
- int texturesCount,
- int imagesCount,
- bool usesInstanceId,
- bool usesRtLayer,
- byte clipDistancesWritten,
- int fragmentOutputMap) : this()
- {
- CBuffersCount = cBuffersCount;
- SBuffersCount = sBuffersCount;
- TexturesCount = texturesCount;
- ImagesCount = imagesCount;
- ClipDistancesWritten = clipDistancesWritten;
- FragmentOutputMap = fragmentOutputMap;
- InUse = true;
-
- UseFlags = usesInstanceId ? UseFlags.InstanceId : UseFlags.None;
-
- if (usesRtLayer)
- {
- UseFlags |= UseFlags.RtLayer;
- }
- }
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheHeader.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheHeader.cs
deleted file mode 100644
index 27f216cc..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheHeader.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
-{
- /// <summary>
- /// The header of a shader program in the guest cache.
- /// </summary>
- [StructLayout(LayoutKind.Sequential, Pack = 0x1, Size = 0x10)]
- struct HostShaderCacheHeader
- {
- /// <summary>
- /// The count of shaders defining this program.
- /// </summary>
- public byte Count;
-
- /// <summary>
- /// Unused/reserved.
- /// </summary>
- public byte Reserved1;
-
- /// <summary>
- /// Unused/reserved.
- /// </summary>
- public ushort Reserved2;
-
- /// <summary>
- /// Size of the shader binary.
- /// </summary>
- public int CodeSize;
-
- /// <summary>
- /// Create a new host shader cache header.
- /// </summary>
- /// <param name="count">The count of shaders defining this program</param>
- /// <param name="codeSize">The size of the shader binary</param>
- public HostShaderCacheHeader(byte count, int codeSize) : this()
- {
- Count = count;
- CodeSize = codeSize;
- }
- }
-}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Migration.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Migration.cs
deleted file mode 100644
index 885bcd09..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Migration.cs
+++ /dev/null
@@ -1,258 +0,0 @@
-using Ryujinx.Common;
-using Ryujinx.Common.Logging;
-using Ryujinx.Common.Memory;
-using Ryujinx.Graphics.GAL;
-using Ryujinx.Graphics.Gpu.Engine.Threed;
-using Ryujinx.Graphics.Gpu.Shader.Cache.Definition;
-using Ryujinx.Graphics.Gpu.Shader.DiskCache;
-using Ryujinx.Graphics.Shader;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Graphics.Gpu.Shader.Cache
-{
- /// <summary>
- /// Class handling shader cache migrations.
- /// </summary>
- static class Migration
- {
- // Last codegen version before the migration to the new cache.
- private const ulong ShaderCodeGenVersion = 3054;
-
- /// <summary>
- /// Migrates from the old cache format to the new one.
- /// </summary>
- /// <param name="context">GPU context</param>
- /// <param name="hostStorage">Disk cache host storage (used to create the new shader files)</param>
- /// <returns>Number of migrated shaders</returns>
- public static int MigrateFromLegacyCache(GpuContext context, DiskCacheHostStorage hostStorage)
- {
- string baseCacheDirectory = CacheHelper.GetBaseCacheDirectory(GraphicsConfig.TitleId);
- string cacheDirectory = CacheHelper.GenerateCachePath(baseCacheDirectory, CacheGraphicsApi.Guest, "", "program");
-
- // If the directory does not exist, we have no old cache.
- // Exist early as the CacheManager constructor will create the directories.
- if (!Directory.Exists(cacheDirectory))
- {
- return 0;
- }
-
- if (GraphicsConfig.EnableShaderCache && GraphicsConfig.TitleId != null)
- {
- CacheManager cacheManager = new CacheManager(CacheGraphicsApi.OpenGL, CacheHashType.XxHash128, "glsl", GraphicsConfig.TitleId, ShaderCodeGenVersion);
-
- 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();
-
- for (int programIndex = 0; programIndex < guestProgramList.Length; programIndex++)
- {
- Hash128 key = guestProgramList[programIndex];
-
- byte[] guestProgram = cacheManager.GetGuestProgramByHash(ref key);
-
- if (guestProgram == null)
- {
- Logger.Error?.Print(LogClass.Gpu, $"Ignoring orphan shader hash {key} in cache (is the cache incomplete?)");
-
- continue;
- }
-
- ReadOnlySpan<byte> guestProgramReadOnlySpan = guestProgram;
-
- ReadOnlySpan<GuestShaderCacheEntry> cachedShaderEntries = GuestShaderCacheEntry.Parse(ref guestProgramReadOnlySpan, out GuestShaderCacheHeader fileHeader);
-
- if (cachedShaderEntries[0].Header.Stage == ShaderStage.Compute)
- {
- Debug.Assert(cachedShaderEntries.Length == 1);
-
- GuestShaderCacheEntry entry = cachedShaderEntries[0];
-
- byte[] code = entry.Code.AsSpan(0, entry.Header.Size - entry.Header.Cb1DataSize).ToArray();
-
- Span<byte> codeSpan = entry.Code;
- byte[] cb1Data = codeSpan.Slice(codeSpan.Length - entry.Header.Cb1DataSize).ToArray();
-
- ShaderProgramInfo info = new ShaderProgramInfo(
- Array.Empty<BufferDescriptor>(),
- Array.Empty<BufferDescriptor>(),
- Array.Empty<TextureDescriptor>(),
- Array.Empty<TextureDescriptor>(),
- ShaderStage.Compute,
- false,
- false,
- 0,
- 0);
-
- GpuChannelComputeState computeState = new GpuChannelComputeState(
- entry.Header.GpuAccessorHeader.ComputeLocalSizeX,
- entry.Header.GpuAccessorHeader.ComputeLocalSizeY,
- entry.Header.GpuAccessorHeader.ComputeLocalSizeZ,
- entry.Header.GpuAccessorHeader.ComputeLocalMemorySize,
- entry.Header.GpuAccessorHeader.ComputeSharedMemorySize);
-
- ShaderSpecializationState specState = new ShaderSpecializationState(computeState);
-
- foreach (var td in entry.TextureDescriptors)
- {
- var handle = td.Key;
- var data = td.Value;
-
- specState.RegisterTexture(
- 0,
- handle,
- -1,
- data.UnpackFormat(),
- data.UnpackSrgb(),
- data.UnpackTextureTarget(),
- data.UnpackTextureCoordNormalized());
- }
-
- CachedShaderStage shader = new CachedShaderStage(info, code, cb1Data);
- CachedShaderProgram program = new CachedShaderProgram(null, specState, shader);
-
- hostStorage.AddShader(context, program, ReadOnlySpan<byte>.Empty);
- }
- else
- {
- Debug.Assert(cachedShaderEntries.Length == Constants.ShaderStages);
-
- CachedShaderStage[] shaders = new CachedShaderStage[Constants.ShaderStages + 1];
- List<ShaderProgram> shaderPrograms = new List<ShaderProgram>();
-
- TransformFeedbackDescriptorOld[] tfd = CacheHelper.ReadTransformFeedbackInformation(ref guestProgramReadOnlySpan, fileHeader);
-
- GuestShaderCacheEntry[] entries = cachedShaderEntries.ToArray();
-
- GuestGpuAccessorHeader accessorHeader = entries[0].Header.GpuAccessorHeader;
-
- TessMode tessMode = new TessMode();
-
- int tessPatchType = accessorHeader.TessellationModePacked & 3;
- int tessSpacing = (accessorHeader.TessellationModePacked >> 2) & 3;
- bool tessCw = (accessorHeader.TessellationModePacked & 0x10) != 0;
-
- tessMode.Packed = (uint)tessPatchType;
- tessMode.Packed |= (uint)(tessSpacing << 4);
-
- if (tessCw)
- {
- tessMode.Packed |= 0x100;
- }
-
- PrimitiveTopology topology = accessorHeader.PrimitiveTopology switch
- {
- InputTopology.Lines => PrimitiveTopology.Lines,
- InputTopology.LinesAdjacency => PrimitiveTopology.LinesAdjacency,
- InputTopology.Triangles => PrimitiveTopology.Triangles,
- InputTopology.TrianglesAdjacency => PrimitiveTopology.TrianglesAdjacency,
- _ => PrimitiveTopology.Points
- };
-
- GpuChannelGraphicsState graphicsState = new GpuChannelGraphicsState(
- accessorHeader.StateFlags.HasFlag(GuestGpuStateFlags.EarlyZForce),
- topology,
- tessMode,
- false,
- false,
- false);
-
- TransformFeedbackDescriptor[] tfdNew = null;
-
- if (tfd != null)
- {
- tfdNew = new TransformFeedbackDescriptor[tfd.Length];
-
- for (int tfIndex = 0; tfIndex < tfd.Length; tfIndex++)
- {
- Array32<uint> varyingLocations = new Array32<uint>();
- Span<byte> varyingLocationsSpan = MemoryMarshal.Cast<uint, byte>(varyingLocations.ToSpan());
- tfd[tfIndex].VaryingLocations.CopyTo(varyingLocationsSpan.Slice(0, tfd[tfIndex].VaryingLocations.Length));
-
- tfdNew[tfIndex] = new TransformFeedbackDescriptor(
- tfd[tfIndex].BufferIndex,
- tfd[tfIndex].Stride,
- tfd[tfIndex].VaryingLocations.Length,
- ref varyingLocations);
- }
- }
-
- ShaderSpecializationState specState = new ShaderSpecializationState(graphicsState, tfdNew);
-
- for (int i = 0; i < entries.Length; i++)
- {
- GuestShaderCacheEntry entry = entries[i];
-
- if (entry == null)
- {
- continue;
- }
-
- ShaderProgramInfo info = new ShaderProgramInfo(
- Array.Empty<BufferDescriptor>(),
- Array.Empty<BufferDescriptor>(),
- Array.Empty<TextureDescriptor>(),
- Array.Empty<TextureDescriptor>(),
- (ShaderStage)(i + 1),
- false,
- false,
- 0,
- 0);
-
- // NOTE: Vertex B comes first in the shader cache.
- byte[] code = entry.Code.AsSpan(0, entry.Header.Size - entry.Header.Cb1DataSize).ToArray();
- byte[] code2 = entry.Header.SizeA != 0 ? entry.Code.AsSpan(entry.Header.Size, entry.Header.SizeA).ToArray() : null;
-
- Span<byte> codeSpan = entry.Code;
- byte[] cb1Data = codeSpan.Slice(codeSpan.Length - entry.Header.Cb1DataSize).ToArray();
-
- shaders[i + 1] = new CachedShaderStage(info, code, cb1Data);
-
- if (code2 != null)
- {
- shaders[0] = new CachedShaderStage(null, code2, cb1Data);
- }
-
- foreach (var td in entry.TextureDescriptors)
- {
- var handle = td.Key;
- var data = td.Value;
-
- specState.RegisterTexture(
- i,
- handle,
- -1,
- data.UnpackFormat(),
- data.UnpackSrgb(),
- data.UnpackTextureTarget(),
- data.UnpackTextureCoordNormalized());
- }
- }
-
- CachedShaderProgram program = new CachedShaderProgram(null, specState, shaders);
-
- hostStorage.AddShader(context, program, ReadOnlySpan<byte>.Empty);
- }
- }
-
- return guestProgramList.Length;
- }
-
- return 0;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/TransformFeedbackDescriptorOld.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/TransformFeedbackDescriptorOld.cs
deleted file mode 100644
index 5e9c6711..00000000
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/TransformFeedbackDescriptorOld.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System;
-
-namespace Ryujinx.Graphics.Gpu.Shader.Cache
-{
- struct TransformFeedbackDescriptorOld
- {
- public int BufferIndex { get; }
- public int Stride { get; }
-
- public byte[] VaryingLocations { get; }
-
- public TransformFeedbackDescriptorOld(int bufferIndex, int stride, byte[] varyingLocations)
- {
- BufferIndex = bufferIndex;
- Stride = stride;
- VaryingLocations = varyingLocations ?? throw new ArgumentNullException(nameof(varyingLocations));
- }
- }
-}