BackgroundDiskCacheWriter.cs
1 using Ryujinx.Common; 2 using Ryujinx.Common.Logging; 3 using System; 4 using System.IO; 5 6 namespace Ryujinx.Graphics.Gpu.Shader.DiskCache 7 { 8 /// <summary> 9 /// Represents a background disk cache writer. 10 /// </summary> 11 class BackgroundDiskCacheWriter : IDisposable 12 { 13 /// <summary> 14 /// Possible operation to do on the <see cref="_fileWriterWorkerQueue"/>. 15 /// </summary> 16 private enum CacheFileOperation 17 { 18 /// <summary> 19 /// Operation to add a shader to the cache. 20 /// </summary> 21 AddShader, 22 } 23 24 /// <summary> 25 /// Represents an operation to perform on the <see cref="_fileWriterWorkerQueue"/>. 26 /// </summary> 27 private readonly struct CacheFileOperationTask 28 { 29 /// <summary> 30 /// The type of operation to perform. 31 /// </summary> 32 public readonly CacheFileOperation Type; 33 34 /// <summary> 35 /// The data associated to this operation or null. 36 /// </summary> 37 public readonly object Data; 38 39 public CacheFileOperationTask(CacheFileOperation type, object data) 40 { 41 Type = type; 42 Data = data; 43 } 44 } 45 46 /// <summary> 47 /// Background shader cache write information. 48 /// </summary> 49 private readonly struct AddShaderData 50 { 51 /// <summary> 52 /// Cached shader program. 53 /// </summary> 54 public readonly CachedShaderProgram Program; 55 56 /// <summary> 57 /// Binary host code. 58 /// </summary> 59 public readonly byte[] HostCode; 60 61 /// <summary> 62 /// Creates a new background shader cache write information. 63 /// </summary> 64 /// <param name="program">Cached shader program</param> 65 /// <param name="hostCode">Binary host code</param> 66 public AddShaderData(CachedShaderProgram program, byte[] hostCode) 67 { 68 Program = program; 69 HostCode = hostCode; 70 } 71 } 72 73 private readonly GpuContext _context; 74 private readonly DiskCacheHostStorage _hostStorage; 75 private readonly AsyncWorkQueue<CacheFileOperationTask> _fileWriterWorkerQueue; 76 77 /// <summary> 78 /// Creates a new background disk cache writer. 79 /// </summary> 80 /// <param name="context">GPU context</param> 81 /// <param name="hostStorage">Disk cache host storage</param> 82 public BackgroundDiskCacheWriter(GpuContext context, DiskCacheHostStorage hostStorage) 83 { 84 _context = context; 85 _hostStorage = hostStorage; 86 _fileWriterWorkerQueue = new AsyncWorkQueue<CacheFileOperationTask>(ProcessTask, "GPU.BackgroundDiskCacheWriter"); 87 } 88 89 /// <summary> 90 /// Processes a shader cache background operation. 91 /// </summary> 92 /// <param name="task">Task to process</param> 93 private void ProcessTask(CacheFileOperationTask task) 94 { 95 switch (task.Type) 96 { 97 case CacheFileOperation.AddShader: 98 AddShaderData data = (AddShaderData)task.Data; 99 try 100 { 101 _hostStorage.AddShader(_context, data.Program, data.HostCode); 102 } 103 catch (DiskCacheLoadException diskCacheLoadException) 104 { 105 Logger.Error?.Print(LogClass.Gpu, $"Error writing shader to disk cache. {diskCacheLoadException.Message}"); 106 } 107 catch (IOException ioException) 108 { 109 Logger.Error?.Print(LogClass.Gpu, $"Error writing shader to disk cache. {ioException.Message}"); 110 } 111 break; 112 } 113 } 114 115 /// <summary> 116 /// Adds a shader program to be cached in the background. 117 /// </summary> 118 /// <param name="program">Shader program to cache</param> 119 /// <param name="hostCode">Host binary code of the program</param> 120 public void AddShader(CachedShaderProgram program, byte[] hostCode) 121 { 122 _fileWriterWorkerQueue.Add(new CacheFileOperationTask(CacheFileOperation.AddShader, new AddShaderData(program, hostCode))); 123 } 124 125 public void Dispose() 126 { 127 Dispose(true); 128 } 129 130 protected virtual void Dispose(bool disposing) 131 { 132 if (disposing) 133 { 134 _fileWriterWorkerQueue.Dispose(); 135 } 136 } 137 } 138 }