aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BackgroundDiskCacheWriter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BackgroundDiskCacheWriter.cs')
-rw-r--r--src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BackgroundDiskCacheWriter.cs138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BackgroundDiskCacheWriter.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BackgroundDiskCacheWriter.cs
new file mode 100644
index 00000000..568fe968
--- /dev/null
+++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BackgroundDiskCacheWriter.cs
@@ -0,0 +1,138 @@
+using Ryujinx.Common;
+using Ryujinx.Common.Logging;
+using System;
+using System.IO;
+
+namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
+{
+ /// <summary>
+ /// Represents a background disk cache writer.
+ /// </summary>
+ class BackgroundDiskCacheWriter : IDisposable
+ {
+ /// <summary>
+ /// Possible operation to do on the <see cref="_fileWriterWorkerQueue"/>.
+ /// </summary>
+ private enum CacheFileOperation
+ {
+ /// <summary>
+ /// Operation to add a shader to the cache.
+ /// </summary>
+ AddShader
+ }
+
+ /// <summary>
+ /// Represents an operation to perform on the <see cref="_fileWriterWorkerQueue"/>.
+ /// </summary>
+ private readonly struct CacheFileOperationTask
+ {
+ /// <summary>
+ /// The type of operation to perform.
+ /// </summary>
+ public readonly CacheFileOperation Type;
+
+ /// <summary>
+ /// The data associated to this operation or null.
+ /// </summary>
+ public readonly object Data;
+
+ public CacheFileOperationTask(CacheFileOperation type, object data)
+ {
+ Type = type;
+ Data = data;
+ }
+ }
+
+ /// <summary>
+ /// Background shader cache write information.
+ /// </summary>
+ private readonly struct AddShaderData
+ {
+ /// <summary>
+ /// Cached shader program.
+ /// </summary>
+ public readonly CachedShaderProgram Program;
+
+ /// <summary>
+ /// Binary host code.
+ /// </summary>
+ public readonly byte[] HostCode;
+
+ /// <summary>
+ /// Creates a new background shader cache write information.
+ /// </summary>
+ /// <param name="program">Cached shader program</param>
+ /// <param name="hostCode">Binary host code</param>
+ public AddShaderData(CachedShaderProgram program, byte[] hostCode)
+ {
+ Program = program;
+ HostCode = hostCode;
+ }
+ }
+
+ private readonly GpuContext _context;
+ private readonly DiskCacheHostStorage _hostStorage;
+ private readonly AsyncWorkQueue<CacheFileOperationTask> _fileWriterWorkerQueue;
+
+ /// <summary>
+ /// Creates a new background disk cache writer.
+ /// </summary>
+ /// <param name="context">GPU context</param>
+ /// <param name="hostStorage">Disk cache host storage</param>
+ public BackgroundDiskCacheWriter(GpuContext context, DiskCacheHostStorage hostStorage)
+ {
+ _context = context;
+ _hostStorage = hostStorage;
+ _fileWriterWorkerQueue = new AsyncWorkQueue<CacheFileOperationTask>(ProcessTask, "GPU.BackgroundDiskCacheWriter");
+ }
+
+ /// <summary>
+ /// Processes a shader cache background operation.
+ /// </summary>
+ /// <param name="task">Task to process</param>
+ private void ProcessTask(CacheFileOperationTask task)
+ {
+ switch (task.Type)
+ {
+ case CacheFileOperation.AddShader:
+ AddShaderData data = (AddShaderData)task.Data;
+ try
+ {
+ _hostStorage.AddShader(_context, data.Program, data.HostCode);
+ }
+ catch (DiskCacheLoadException diskCacheLoadException)
+ {
+ Logger.Error?.Print(LogClass.Gpu, $"Error writing shader to disk cache. {diskCacheLoadException.Message}");
+ }
+ catch (IOException ioException)
+ {
+ Logger.Error?.Print(LogClass.Gpu, $"Error writing shader to disk cache. {ioException.Message}");
+ }
+ break;
+ }
+ }
+
+ /// <summary>
+ /// Adds a shader program to be cached in the background.
+ /// </summary>
+ /// <param name="program">Shader program to cache</param>
+ /// <param name="hostCode">Host binary code of the program</param>
+ public void AddShader(CachedShaderProgram program, byte[] hostCode)
+ {
+ _fileWriterWorkerQueue.Add(new CacheFileOperationTask(CacheFileOperation.AddShader, new AddShaderData(program, hostCode)));
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _fileWriterWorkerQueue.Dispose();
+ }
+ }
+ }
+}