diff --git a/Core/System.cpp b/Core/System.cpp index 715a13312c..0b57a81774 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -97,6 +97,10 @@ static volatile CPUThreadState cpuThreadState = CPU_THREAD_NOT_RUNNING; static GPUBackend gpuBackend; +void ResetUIState() { + globalUIState = UISTATE_MENU; +} + void UpdateUIState(GlobalUIState newState) { // Never leave the EXIT state. if (globalUIState != newState && globalUIState != UISTATE_EXIT) { diff --git a/Core/System.h b/Core/System.h index f8f6472d25..3746c01679 100644 --- a/Core/System.h +++ b/Core/System.h @@ -54,6 +54,7 @@ enum PSPDirectories { class GraphicsContext; enum class GPUBackend; +void ResetUIState(); void UpdateUIState(GlobalUIState newState); GlobalUIState GetUIState(); diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 992c30d484..afd08499ea 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1057,8 +1057,7 @@ void GameSettingsScreen::CallbackRenderingBackend(bool yes) { // If the user ends up deciding not to restart, set the config back to the current backend // so it doesn't get switched by accident. if (yes) { - g_Config.bRestartRequired = true; - PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); + System_SendMessage("graphics_restart", ""); } else { g_Config.iGPUBackend = (int)GetGPUBackend(); } diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 0f3743721c..5bdec61383 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -112,6 +112,7 @@ unsigned int WINAPI TheThread(void *) args.push_back(string.c_str()); } + bool performingRestart = NativeIsRestarting(); NativeInit(static_cast(args.size()), &args[0], "1234", "1234", nullptr); Host *nativeHost = host; @@ -123,6 +124,14 @@ unsigned int WINAPI TheThread(void *) std::string error_string; if (!host->InitGraphics(&error_string, &graphicsContext)) { + // Before anything: are we restarting right now? + if (performingRestart) { + // Okay, switching graphics didn't work out. Probably a driver bug - fallback to restart. + // This happens on NVIDIA when switching OpenGL -> Vulkan. + g_Config.Save(); + W32Util::ExitAndRestart(); + } + I18NCategory *err = GetI18NCategory("Error"); Reporting::ReportMessage("Graphics init error: %s", error_string.c_str()); diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 66621fca9a..7a11b27015 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -882,6 +882,14 @@ namespace MainWindow BrowseBackgroundDone(); break; + case WM_USER_RESTART_EMUTHREAD: + NativeSetRestarting(); + EmuThread_Stop(); + coreState = CORE_POWERUP; + ResetUIState(); + EmuThread_Start(); + break; + case WM_MENUSELECT: // Called when a menu is opened. Also when an item is selected, but meh. UpdateMenus(true); diff --git a/Windows/MainWindow.h b/Windows/MainWindow.h index 09d217a40d..bf879b1bc1 100644 --- a/Windows/MainWindow.h +++ b/Windows/MainWindow.h @@ -20,6 +20,7 @@ namespace MainWindow WM_USER_WINDOW_TITLE_CHANGED = WM_USER + 103, WM_USER_BROWSE_BOOT_DONE = WM_USER + 104, WM_USER_TOGGLE_FULLSCREEN = WM_USER + 105, + WM_USER_RESTART_EMUTHREAD = WM_USER + 106, }; enum { diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index 24e01e7b40..db39e1eba1 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -770,26 +770,22 @@ namespace MainWindow { case ID_OPTIONS_DIRECT3D9: g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D9; - g_Config.bRestartRequired = true; - PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); + PostMessage(MainWindow::GetHWND(), WM_USER_RESTART_EMUTHREAD, 0, 0); break; case ID_OPTIONS_DIRECT3D11: g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D11; - g_Config.bRestartRequired = true; - PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); + PostMessage(MainWindow::GetHWND(), WM_USER_RESTART_EMUTHREAD, 0, 0); break; case ID_OPTIONS_OPENGL: g_Config.iGPUBackend = GPU_BACKEND_OPENGL; - g_Config.bRestartRequired = true; - PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); + PostMessage(MainWindow::GetHWND(), WM_USER_RESTART_EMUTHREAD, 0, 0); break; case ID_OPTIONS_VULKAN: g_Config.iGPUBackend = GPU_BACKEND_VULKAN; - g_Config.bRestartRequired = true; - PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); + PostMessage(MainWindow::GetHWND(), WM_USER_RESTART_EMUTHREAD, 0, 0); break; case ID_OPTIONS_NONBUFFEREDRENDERING: setRenderingMode(FB_NON_BUFFERED_MODE); break; diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 2b91bd274d..01fee1cea2 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -146,7 +146,6 @@ void WindowsHost::ShutdownGraphics() { gfx_->Shutdown(); delete gfx_; gfx_ = nullptr; - PostMessage(mainWindow_, WM_CLOSE, 0, 0); } void WindowsHost::SetWindowTitle(const char *message) { diff --git a/Windows/main.cpp b/Windows/main.cpp index b7f6724828..e8db4483b0 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -231,7 +231,11 @@ int System_GetPropertyInt(SystemProperty prop) { void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { - PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); + if (!NativeIsRestarting()) { + PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); + } + } else if (!strcmp(command, "graphics_restart")) { + PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_RESTART_EMUTHREAD, 0, 0); } else if (!strcmp(command, "setclipboardtext")) { if (OpenClipboard(MainWindow::GetDisplayHWND())) { std::wstring data = ConvertUTF8ToWString(parameter);