From 29edec768481be113a5e28444ae9222090a90f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 26 Jul 2026 11:31:32 +0200 Subject: [PATCH] Move calling ThreadStart and ThreadEnd into the EmuThread wrapper --- Core/EmuThread.cpp | 2 ++ Qt/QtMain.cpp | 1 - android/jni/app-android.cpp | 43 +++++++++++++++++-------------------- ios/ViewController.mm | 3 --- 4 files changed, 22 insertions(+), 27 deletions(-) diff --git a/Core/EmuThread.cpp b/Core/EmuThread.cpp index c406fcd8a3..811c0b8b90 100644 --- a/Core/EmuThread.cpp +++ b/Core/EmuThread.cpp @@ -80,6 +80,7 @@ std::thread EmuThread_Start(GraphicsContext *graphicsContext, Application *appli _dbg_assert_(g_emuThreadState == EmuThreadState::STOPPED); g_emuThreadState = EmuThreadState::RUNNING; std::thread emuThread = std::thread(&EmuThreadFunc, graphicsContext, application, postFrame); + graphicsContext->ThreadStart(); return emuThread; } @@ -96,6 +97,7 @@ void EmuThread_Join(GraphicsContext *graphicsContext, std::thread &emuThread) { return g_emuThreadState == EmuThreadState::STOPPED; }); } + graphicsContext->ThreadEnd(); emuThread.join(); emuThread = std::thread(); } diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 6443cfc6aa..6fe9e8dd52 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -915,7 +915,6 @@ void MainUI::initializeGL() { } else { INFO_LOG(Log::System, "Not using thread, backend=%d", (int)g_Config.iGPUBackend); } - graphicsContext->ThreadStart(); } void MainUI::paintGL() { diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index a825902aec..7d7ea9940d 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -905,7 +905,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { // Only used in Java EGL path. EmuThread_Join(graphicsContext, g_emuThread); - INFO_LOG(Log::System, "ThreadEnd called."); + INFO_LOG(Log::System, "EmuThread joined."); graphicsContext->ShutdownSurface(); INFO_LOG(Log::System, "Graphics context now shut down from NativeApp_shutdown"); } @@ -953,16 +953,15 @@ extern "C" jboolean Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * e System_Toast("Graphics initialization failed. Quitting."); return false; } - // This is where we start the emuthread now - after InitFromRenderThread. This eliminates a race condition. - g_emuThread = EmuThread_Start(graphicsContext, new NativeApplication(), []() { - ProcessFrameCommands(); - }); graphicsContext->GetDrawContext()->SetErrorCallback([](const char *shortDesc, const char *details, void *userdata) { g_OSD.Show(OSDType::MESSAGE_ERROR, details, 5.0); }, nullptr); - graphicsContext->ThreadStart(); + // This is where we start the emuthread now - after InitFromRenderThread. This eliminates a race condition. + g_emuThread = EmuThread_Start(graphicsContext, new NativeApplication(), []() { + ProcessFrameCommands(); + }); renderer_inited = true; } else { // Would be really nice if we could get something on the GL thread immediately when shutting down, @@ -972,7 +971,6 @@ extern "C" jboolean Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * e INFO_LOG(Log::G3D, "NativeApp.displayInit() restoring"); EmuThread_Join(graphicsContext, g_emuThread); - graphicsContext->ThreadEnd(); graphicsContext->ShutdownSurface(); INFO_LOG(Log::G3D, "Shut down both threads. Now let's bring it up again!"); @@ -990,8 +988,6 @@ extern "C" jboolean Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * e ProcessFrameCommands(); }); - graphicsContext->ThreadStart(); - INFO_LOG(Log::G3D, "Restored."); } @@ -1607,24 +1603,27 @@ static void ProcessFrameCommands() { ERROR_LOG(Log::System, "No activity, clearing commands"); } else { frameCommands = std::move(g_frameCommands); - INFO_LOG(Log::System, "Processing %zu frame commands", g_frameCommands.size()); } g_frameCommands.clear(); } - for (const FrameCommand &frameCmd : frameCommands) { - DEBUG_LOG(Log::System, "frameCommand '%s' '%s'", frameCmd.command.c_str(), frameCmd.params.c_str()); - jstring cmd = env->NewStringUTF(frameCmd.command.c_str()); - jstring param = env->NewStringUTF(frameCmd.params.c_str()); - env->CallVoidMethod(ppssppActivity, postCommand, cmd, param); - env->DeleteLocalRef(cmd); - env->DeleteLocalRef(param); + if (!frameCommands.empty()) { + INFO_LOG(Log::System, "Processing %zu frame commands", g_frameCommands.size()); + for (const FrameCommand &frameCmd : frameCommands) { + DEBUG_LOG(Log::System, "frameCommand '%s' '%s'", frameCmd.command.c_str(), frameCmd.params.c_str()); + + jstring cmd = env->NewStringUTF(frameCmd.command.c_str()); + jstring param = env->NewStringUTF(frameCmd.params.c_str()); + env->CallVoidMethod(ppssppActivity, postCommand, cmd, param); + env->DeleteLocalRef(cmd); + env->DeleteLocalRef(param); + } } } std::thread g_renderLoopThread; -static void VulkanEmuThread(ANativeWindow *wnd, AndroidVulkanContext *graphicsContext); +static void VulkanEmuThread(ANativeWindow *wnd, GraphicsContext *graphicsContext); // This runs in Vulkan mode only. // This handles the entire lifecycle of the Vulkan context, init and exit. @@ -1652,7 +1651,7 @@ extern "C" jboolean JNICALL Java_org_ppsspp_ppsspp_PpssppActivity_runVulkanRende return false; } - g_renderLoopThread = std::thread(VulkanEmuThread, wnd, (AndroidVulkanContext *)graphicsContext); + g_renderLoopThread = std::thread(VulkanEmuThread, wnd, graphicsContext); return true; } @@ -1668,8 +1667,8 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_PpssppActivity_requestExitVulkanR } // TODO: Merge with the Win32 EmuThread and so on, and the Java EmuThread? -// This function must release the window reference. -static void VulkanEmuThread(ANativeWindow *wnd, AndroidVulkanContext *graphicsContext) { +// This function must release the wnd reference. +static void VulkanEmuThread(ANativeWindow *wnd, GraphicsContext *graphicsContext) { SetCurrentThreadName("EmuThread"); AndroidJNIThreadContext ctx; @@ -1708,7 +1707,6 @@ static void VulkanEmuThread(ANativeWindow *wnd, AndroidVulkanContext *graphicsCo ERROR_LOG(Log::G3D, "Failed to initialize graphics."); // Gonna be in a weird state here.. } - graphicsContext->ThreadStart(); renderer_inited = true; // The main loop. @@ -1725,7 +1723,6 @@ static void VulkanEmuThread(ANativeWindow *wnd, AndroidVulkanContext *graphicsCo NativeShutdownGraphics(graphicsContext); renderer_inited = false; - graphicsContext->ThreadEnd(); // Shut the graphics context down to the same state it was in when we entered the render thread. INFO_LOG(Log::G3D, "Shutting down graphics context..."); diff --git a/ios/ViewController.mm b/ios/ViewController.mm index b0ac390b19..51e615a1e5 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -253,8 +253,6 @@ void GLRenderLoop(IOSGLESContext *graphicsContext) { ERROR_LOG(Log::G3D, "InitAPI failed: %s", errorMessage.c_str()); } - graphicsContext->ThreadStart(); - /*self.iCadeView = [[iCadeReaderView alloc] init]; [self.view addSubview:self.iCadeView]; self.iCadeView.delegate = self; @@ -380,7 +378,6 @@ void GLRenderLoop(IOSGLESContext *graphicsContext) { graphicsContext->ThreadFrameUntilCondition([]() -> bool { return !renderLoopRunning; }); - graphicsContext->ThreadEnd(); graphicsContext->ShutdownSurface(); graphicsContext->ShutdownAPI(); delete graphicsContext;