Use event to wake the main thread on task completion

This commit is contained in:
riperiperi 2021-04-02 23:05:55 +01:00
parent 20d560e3f9
commit a0aa09912c
2 changed files with 22 additions and 3 deletions

View file

@ -110,6 +110,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
int programIndex = 0; int programIndex = 0;
List<ShaderCompileTask> activeTasks = new List<ShaderCompileTask>(); List<ShaderCompileTask> activeTasks = new List<ShaderCompileTask>();
AutoResetEvent taskDoneEvent = new AutoResetEvent(false);
// This thread dispatches tasks to do shader translation, and creates programs that OpenGL will link in the background. // This thread dispatches tasks to do shader translation, and creates programs that OpenGL will link in the background.
// The program link status is checked in a non-blocking manner so that multiple shaders can be compiled at once. // The program link status is checked in a non-blocking manner so that multiple shaders can be compiled at once.
@ -158,7 +160,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
hostProgram = _context.Renderer.LoadProgramBinary(hostProgramBinary); hostProgram = _context.Renderer.LoadProgramBinary(hostProgramBinary);
} }
ShaderCompileTask task = new ShaderCompileTask(); ShaderCompileTask task = new ShaderCompileTask(taskDoneEvent);
activeTasks.Add(task); activeTasks.Add(task);
task.OnCompiled(hostProgram, (bool isHostProgramValid, ShaderCompileTask task) => task.OnCompiled(hostProgram, (bool isHostProgramValid, ShaderCompileTask task) =>
@ -261,7 +263,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
hostProgram = _context.Renderer.LoadProgramBinary(hostProgramBinary); hostProgram = _context.Renderer.LoadProgramBinary(hostProgramBinary);
} }
ShaderCompileTask task = new ShaderCompileTask(); ShaderCompileTask task = new ShaderCompileTask(taskDoneEvent);
activeTasks.Add(task); activeTasks.Add(task);
GuestShaderCacheEntry[] entries = cachedShaderEntries.ToArray(); GuestShaderCacheEntry[] entries = cachedShaderEntries.ToArray();
@ -412,7 +414,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
if (activeTasks.Count == maxTaskCount) if (activeTasks.Count == maxTaskCount)
{ {
Thread.Sleep(1); // Wait for a task to be done, or for 1ms.
// Host shader compilation cannot signal when it is done,
// so the 1ms timeout is required to poll status.
taskDoneEvent.WaitOne(1);
} }
} }

View file

@ -1,5 +1,6 @@
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using System; using System;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Graphics.Gpu.Shader namespace Ryujinx.Graphics.Gpu.Shader
@ -17,6 +18,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
private IProgram _program; private IProgram _program;
private ShaderCompileTaskCallback _action; private ShaderCompileTaskCallback _action;
private AutoResetEvent _taskDoneEvent;
/// <summary>
/// Create a new shader compile task, with an event to signal whenever a subtask completes.
/// </summary>
/// <param name="taskDoneEvent">Event to signal when a subtask completes</param>
public ShaderCompileTask(AutoResetEvent taskDoneEvent)
{
_taskDoneEvent = taskDoneEvent;
}
/// <summary> /// <summary>
/// Check the completion status of the shader compile task, and run callbacks on step completion. /// Check the completion status of the shader compile task, and run callbacks on step completion.
@ -58,6 +69,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
_programsTask = task; _programsTask = task;
_action = action; _action = action;
task.ContinueWith(task => _taskDoneEvent.Set());
} }
/// <summary> /// <summary>