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