From 870d9599cc056e515dd63620fd10bf9fee4992ee Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Thu, 18 Jan 2024 14:17:38 -0300
Subject: [PATCH] Change shader cache init wait method (#6131)

* Change shader cache init wait method

* Make field readonly
---
 src/ARMeilleure/Translation/Translator.cs      |  5 -----
 src/Ryujinx.Ava/AppHost.cs                     |  2 --
 src/Ryujinx.Graphics.Gpu/GpuContext.cs         | 18 ++++++++++++++++--
 src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs |  3 ++-
 src/Ryujinx.HLE/HOS/ArmProcessContext.cs       |  2 ++
 src/Ryujinx.Headless.SDL2/Program.cs           |  4 ----
 src/Ryujinx.Headless.SDL2/WindowBase.cs        |  2 --
 src/Ryujinx.Tests/Cpu/CpuTest.cs               |  1 -
 src/Ryujinx.Tests/Cpu/CpuTest32.cs             |  1 -
 src/Ryujinx/Ui/MainWindow.cs                   |  3 ---
 src/Ryujinx/Ui/RendererWidgetBase.cs           |  2 --
 11 files changed, 20 insertions(+), 23 deletions(-)

diff --git a/src/ARMeilleure/Translation/Translator.cs b/src/ARMeilleure/Translation/Translator.cs
index 7f6a25b07..48c1a575c 100644
--- a/src/ARMeilleure/Translation/Translator.cs
+++ b/src/ARMeilleure/Translation/Translator.cs
@@ -57,9 +57,6 @@ namespace ARMeilleure.Translation
         private Thread[] _backgroundTranslationThreads;
         private volatile int _threadCount;
 
-        // FIXME: Remove this once the init logic of the emulator will be redone.
-        public static readonly ManualResetEvent IsReadyForTranslation = new(false);
-
         public Translator(IJitMemoryAllocator allocator, IMemoryManager memory, bool for64Bits)
         {
             _allocator = allocator;
@@ -100,8 +97,6 @@ namespace ARMeilleure.Translation
         {
             if (Interlocked.Increment(ref _threadCount) == 1)
             {
-                IsReadyForTranslation.WaitOne();
-
                 if (_ptc.State == PtcState.Enabled)
                 {
                     Debug.Assert(Functions.Count == 0);
diff --git a/src/Ryujinx.Ava/AppHost.cs b/src/Ryujinx.Ava/AppHost.cs
index 2fd9ce00d..e434deb0a 100644
--- a/src/Ryujinx.Ava/AppHost.cs
+++ b/src/Ryujinx.Ava/AppHost.cs
@@ -1,4 +1,3 @@
-using ARMeilleure.Translation;
 using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Controls.ApplicationLifetimes;
@@ -916,7 +915,6 @@ namespace Ryujinx.Ava
             {
                 Device.Gpu.SetGpuThread();
                 Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
-                Translator.IsReadyForTranslation.Set();
 
                 _renderer.Window.ChangeVSyncMode(Device.EnableDeviceVsync);
 
diff --git a/src/Ryujinx.Graphics.Gpu/GpuContext.cs b/src/Ryujinx.Graphics.Gpu/GpuContext.cs
index a50852b05..aaf03ff79 100644
--- a/src/Ryujinx.Graphics.Gpu/GpuContext.cs
+++ b/src/Ryujinx.Graphics.Gpu/GpuContext.cs
@@ -106,6 +106,8 @@ namespace Ryujinx.Graphics.Gpu
         private long _modifiedSequence;
         private readonly ulong _firstTimestamp;
 
+        private readonly ManualResetEvent _gpuReadyEvent;
+
         /// <summary>
         /// Creates a new instance of the GPU emulation context.
         /// </summary>
@@ -121,6 +123,7 @@ namespace Ryujinx.Graphics.Gpu
             Window = new Window(this);
 
             HostInitalized = new ManualResetEvent(false);
+            _gpuReadyEvent = new ManualResetEvent(false);
 
             SyncActions = new List<ISyncActionHandler>();
             SyncpointActions = new List<ISyncActionHandler>();
@@ -216,7 +219,7 @@ namespace Ryujinx.Graphics.Gpu
         /// Gets a sequence number for resource modification ordering. This increments on each call.
         /// </summary>
         /// <returns>A sequence number for resource modification ordering</returns>
-        public long GetModifiedSequence()
+        internal long GetModifiedSequence()
         {
             return _modifiedSequence++;
         }
@@ -225,7 +228,7 @@ namespace Ryujinx.Graphics.Gpu
         /// Gets the value of the GPU timer.
         /// </summary>
         /// <returns>The current GPU timestamp</returns>
-        public ulong GetTimestamp()
+        internal ulong GetTimestamp()
         {
             // Guest timestamp will start at 0, instead of host value.
             ulong ticks = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds) - _firstTimestamp;
@@ -262,6 +265,16 @@ namespace Ryujinx.Graphics.Gpu
             {
                 physicalMemory.ShaderCache.Initialize(cancellationToken);
             }
+
+            _gpuReadyEvent.Set();
+        }
+
+        /// <summary>
+        /// Waits until the GPU is ready to receive commands.
+        /// </summary>
+        public void WaitUntilGpuReady()
+        {
+            _gpuReadyEvent.WaitOne();
         }
 
         /// <summary>
@@ -399,6 +412,7 @@ namespace Ryujinx.Graphics.Gpu
         {
             GPFifo.Dispose();
             HostInitalized.Dispose();
+            _gpuReadyEvent.Dispose();
 
             // Has to be disposed before processing deferred actions, as it will produce some.
             foreach (var physicalMemory in PhysicalMemoryRegistry.Values)
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
index af682e422..0b17af8b2 100644
--- a/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
+++ b/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
@@ -161,7 +161,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
                     _graphicsShaderCache,
                     _computeShaderCache,
                     _diskCacheHostStorage,
-                    ShaderCacheStateUpdate, cancellationToken);
+                    ShaderCacheStateUpdate,
+                    cancellationToken);
 
                 loader.LoadShaders();
 
diff --git a/src/Ryujinx.HLE/HOS/ArmProcessContext.cs b/src/Ryujinx.HLE/HOS/ArmProcessContext.cs
index ff2185464..4de00978c 100644
--- a/src/Ryujinx.HLE/HOS/ArmProcessContext.cs
+++ b/src/Ryujinx.HLE/HOS/ArmProcessContext.cs
@@ -57,6 +57,8 @@ namespace Ryujinx.HLE.HOS
 
         public void Execute(IExecutionContext context, ulong codeAddress)
         {
+            // We must wait until shader cache is loaded, among other things, before executing CPU code.
+            _gpuContext.WaitUntilGpuReady();
             _cpuContext.Execute(context, codeAddress);
         }
 
diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs
index 7e3c79f54..e545079b9 100644
--- a/src/Ryujinx.Headless.SDL2/Program.cs
+++ b/src/Ryujinx.Headless.SDL2/Program.cs
@@ -1,4 +1,3 @@
-using ARMeilleure.Translation;
 using CommandLine;
 using LibHac.Tools.FsSystem;
 using Ryujinx.Audio.Backends.SDL2;
@@ -710,9 +709,6 @@ namespace Ryujinx.Headless.SDL2
             }
 
             SetupProgressHandler();
-
-            Translator.IsReadyForTranslation.Reset();
-
             ExecutionEntrypoint();
 
             return true;
diff --git a/src/Ryujinx.Headless.SDL2/WindowBase.cs b/src/Ryujinx.Headless.SDL2/WindowBase.cs
index adab07641..1bfe43121 100644
--- a/src/Ryujinx.Headless.SDL2/WindowBase.cs
+++ b/src/Ryujinx.Headless.SDL2/WindowBase.cs
@@ -1,4 +1,3 @@
-using ARMeilleure.Translation;
 using Ryujinx.Common.Configuration;
 using Ryujinx.Common.Configuration.Hid;
 using Ryujinx.Common.Logging;
@@ -276,7 +275,6 @@ namespace Ryujinx.Headless.SDL2
             {
                 Device.Gpu.SetGpuThread();
                 Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
-                Translator.IsReadyForTranslation.Set();
 
                 while (_isActive)
                 {
diff --git a/src/Ryujinx.Tests/Cpu/CpuTest.cs b/src/Ryujinx.Tests/Cpu/CpuTest.cs
index 35158c0b4..da0f03e6b 100644
--- a/src/Ryujinx.Tests/Cpu/CpuTest.cs
+++ b/src/Ryujinx.Tests/Cpu/CpuTest.cs
@@ -61,7 +61,6 @@ namespace Ryujinx.Tests.Cpu
             _memory.Map(DataBaseAddress, Size, Size, MemoryMapFlags.Private);
 
             _context = CpuContext.CreateExecutionContext();
-            Translator.IsReadyForTranslation.Set();
 
             _cpuContext = new CpuContext(_memory, for64Bit: true);
 
diff --git a/src/Ryujinx.Tests/Cpu/CpuTest32.cs b/src/Ryujinx.Tests/Cpu/CpuTest32.cs
index f5eb94fa9..6a690834f 100644
--- a/src/Ryujinx.Tests/Cpu/CpuTest32.cs
+++ b/src/Ryujinx.Tests/Cpu/CpuTest32.cs
@@ -56,7 +56,6 @@ namespace Ryujinx.Tests.Cpu
 
             _context = CpuContext.CreateExecutionContext();
             _context.IsAarch32 = true;
-            Translator.IsReadyForTranslation.Set();
 
             _cpuContext = new CpuContext(_memory, for64Bit: false);
 
diff --git a/src/Ryujinx/Ui/MainWindow.cs b/src/Ryujinx/Ui/MainWindow.cs
index 2a088f561..6cce034b6 100644
--- a/src/Ryujinx/Ui/MainWindow.cs
+++ b/src/Ryujinx/Ui/MainWindow.cs
@@ -1,4 +1,3 @@
-using ARMeilleure.Translation;
 using Gtk;
 using LibHac.Common;
 using LibHac.Common.Keys;
@@ -931,8 +930,6 @@ namespace Ryujinx.Ui
 
                 _deviceExitStatus.Reset();
 
-                Translator.IsReadyForTranslation.Reset();
-
                 Thread windowThread = new(CreateGameWindow)
                 {
                     Name = "GUI.WindowThread",
diff --git a/src/Ryujinx/Ui/RendererWidgetBase.cs b/src/Ryujinx/Ui/RendererWidgetBase.cs
index 6ae122a0a..7660f190e 100644
--- a/src/Ryujinx/Ui/RendererWidgetBase.cs
+++ b/src/Ryujinx/Ui/RendererWidgetBase.cs
@@ -1,4 +1,3 @@
-using ARMeilleure.Translation;
 using Gdk;
 using Gtk;
 using Ryujinx.Common;
@@ -450,7 +449,6 @@ namespace Ryujinx.Ui
             {
                 Device.Gpu.SetGpuThread();
                 Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
-                Translator.IsReadyForTranslation.Set();
 
                 Renderer.Window.ChangeVSyncMode(Device.EnableDeviceVsync);