Просмотр исходного кода

Use event to wake the main thread on task completion

riperiperi 5 лет назад
Родитель
Сommit
a0aa09912c
2 измененных файлов с 22 добавлено и 3 удалено
  1. 9 3
      Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
  2. 13 0
      Ryujinx.Graphics.Gpu/Shader/ShaderCompileTask.cs

+ 9 - 3
Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs

@@ -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);
                     }
                     }
                 }
                 }
 
 

+ 13 - 0
Ryujinx.Graphics.Gpu/Shader/ShaderCompileTask.cs

@@ -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>