ProgramQueue.cs
1 using Ryujinx.Graphics.GAL.Multithreading.Resources.Programs; 2 using System; 3 using System.Collections.Generic; 4 using System.Threading; 5 6 namespace Ryujinx.Graphics.GAL.Multithreading.Resources 7 { 8 /// <summary> 9 /// A structure handling multithreaded compilation for programs. 10 /// </summary> 11 class ProgramQueue 12 { 13 private const int MaxConcurrentCompilations = 8; 14 15 private readonly IRenderer _renderer; 16 17 private readonly Queue<IProgramRequest> _toCompile; 18 private readonly List<ThreadedProgram> _inProgress; 19 20 public ProgramQueue(IRenderer renderer) 21 { 22 _renderer = renderer; 23 24 _toCompile = new Queue<IProgramRequest>(); 25 _inProgress = new List<ThreadedProgram>(); 26 } 27 28 public void Add(IProgramRequest request) 29 { 30 lock (_toCompile) 31 { 32 _toCompile.Enqueue(request); 33 } 34 } 35 36 public void ProcessQueue() 37 { 38 for (int i = 0; i < _inProgress.Count; i++) 39 { 40 ThreadedProgram program = _inProgress[i]; 41 42 ProgramLinkStatus status = program.Base.CheckProgramLink(false); 43 44 if (status != ProgramLinkStatus.Incomplete) 45 { 46 program.Compiled = true; 47 _inProgress.RemoveAt(i--); 48 } 49 } 50 51 int freeSpace = MaxConcurrentCompilations - _inProgress.Count; 52 53 for (int i = 0; i < freeSpace; i++) 54 { 55 // Begin compilation of some programs in the compile queue. 56 IProgramRequest program; 57 58 lock (_toCompile) 59 { 60 if (!_toCompile.TryDequeue(out program)) 61 { 62 break; 63 } 64 } 65 66 if (program.Threaded.Base != null) 67 { 68 ProgramLinkStatus status = program.Threaded.Base.CheckProgramLink(false); 69 70 if (status != ProgramLinkStatus.Incomplete) 71 { 72 // This program is already compiled. Keep going through the queue. 73 program.Threaded.Compiled = true; 74 i--; 75 continue; 76 } 77 } 78 else 79 { 80 program.Threaded.Base = program.Create(_renderer); 81 } 82 83 _inProgress.Add(program.Threaded); 84 } 85 } 86 87 /// <summary> 88 /// Process the queue until the given program has finished compiling. 89 /// This will begin compilation of other programs on the queue as well. 90 /// </summary> 91 /// <param name="program">The program to wait for</param> 92 public void WaitForProgram(ThreadedProgram program) 93 { 94 Span<SpinWait> spinWait = stackalloc SpinWait[1]; 95 96 while (!program.Compiled) 97 { 98 ProcessQueue(); 99 100 if (!program.Compiled) 101 { 102 spinWait[0].SpinOnce(-1); 103 } 104 } 105 } 106 } 107 }