diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs index 35908cb9..5ee41cdf 100644 --- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs +++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs @@ -110,6 +110,8 @@ namespace Ryujinx.Graphics.Gpu.Shader int programIndex = 0; List activeTasks = new List(); + AutoResetEvent taskDoneEvent = new AutoResetEvent(false); + // 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. @@ -158,7 +160,7 @@ namespace Ryujinx.Graphics.Gpu.Shader hostProgram = _context.Renderer.LoadProgramBinary(hostProgramBinary); } - ShaderCompileTask task = new ShaderCompileTask(); + ShaderCompileTask task = new ShaderCompileTask(taskDoneEvent); activeTasks.Add(task); task.OnCompiled(hostProgram, (bool isHostProgramValid, ShaderCompileTask task) => @@ -261,7 +263,7 @@ namespace Ryujinx.Graphics.Gpu.Shader hostProgram = _context.Renderer.LoadProgramBinary(hostProgramBinary); } - ShaderCompileTask task = new ShaderCompileTask(); + ShaderCompileTask task = new ShaderCompileTask(taskDoneEvent); activeTasks.Add(task); GuestShaderCacheEntry[] entries = cachedShaderEntries.ToArray(); @@ -412,7 +414,11 @@ namespace Ryujinx.Graphics.Gpu.Shader 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); } } diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCompileTask.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCompileTask.cs index cc1b322b..ff48fab0 100644 --- a/Ryujinx.Graphics.Gpu/Shader/ShaderCompileTask.cs +++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCompileTask.cs @@ -1,5 +1,6 @@ using Ryujinx.Graphics.GAL; using System; +using System.Threading; using System.Threading.Tasks; namespace Ryujinx.Graphics.Gpu.Shader @@ -17,6 +18,16 @@ namespace Ryujinx.Graphics.Gpu.Shader private IProgram _program; private ShaderCompileTaskCallback _action; + private AutoResetEvent _taskDoneEvent; + + /// + /// Create a new shader compile task, with an event to signal whenever a subtask completes. + /// + /// Event to signal when a subtask completes + public ShaderCompileTask(AutoResetEvent taskDoneEvent) + { + _taskDoneEvent = taskDoneEvent; + } /// /// 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; _action = action; + + task.ContinueWith(task => _taskDoneEvent.Set()); } ///