diff --git a/src/ARMeilleure/Translation/Translator.cs b/src/ARMeilleure/Translation/Translator.cs
index 7f6a25b07e..48c1a575c3 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 2fd9ce00da..e434deb0aa 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 a50852b050..aaf03ff79c 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;
+
///
/// Creates a new instance of the GPU emulation context.
///
@@ -121,6 +123,7 @@ namespace Ryujinx.Graphics.Gpu
Window = new Window(this);
HostInitalized = new ManualResetEvent(false);
+ _gpuReadyEvent = new ManualResetEvent(false);
SyncActions = new List();
SyncpointActions = new List();
@@ -216,7 +219,7 @@ namespace Ryujinx.Graphics.Gpu
/// Gets a sequence number for resource modification ordering. This increments on each call.
///
/// A sequence number for resource modification ordering
- public long GetModifiedSequence()
+ internal long GetModifiedSequence()
{
return _modifiedSequence++;
}
@@ -225,7 +228,7 @@ namespace Ryujinx.Graphics.Gpu
/// Gets the value of the GPU timer.
///
/// The current GPU timestamp
- 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();
+ }
+
+ ///
+ /// Waits until the GPU is ready to receive commands.
+ ///
+ public void WaitUntilGpuReady()
+ {
+ _gpuReadyEvent.WaitOne();
}
///
@@ -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 af682e4223..0b17af8b27 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 ff2185464b..4de00978c8 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 7e3c79f541..e545079b91 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 adab076411..1bfe431212 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 35158c0b4b..da0f03e6bd 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 f5eb94fa9c..6a690834f2 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 2a088f5618..6cce034b64 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 6ae122a0ae..7660f190e2 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);