From 7ee4d2d5a1f50eaef08b11a769a915bc06320cd9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 30 Sep 2018 00:53:21 -0700 Subject: [PATCH] UI: Ask for restart when changing graphics device. Only for D3D11 and Vulkan. Also, makes Vulkan follow D3D11 in not changing the setting if the device is not found on startup. --- Core/System.cpp | 8 ++++- Core/System.h | 3 +- UI/GameSettingsScreen.cpp | 53 ++++++++++++++++++++++------ UI/GameSettingsScreen.h | 2 ++ Windows/GPU/D3D11Context.cpp | 4 ++- Windows/GPU/WindowsVulkanContext.cpp | 5 +-- 6 files changed, 60 insertions(+), 15 deletions(-) diff --git a/Core/System.cpp b/Core/System.cpp index 5bc2208034..33accc49bb 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -97,6 +97,7 @@ volatile bool coreStatePending = false; static volatile CPUThreadState cpuThreadState = CPU_THREAD_NOT_RUNNING; static GPUBackend gpuBackend; +static std::string gpuBackendDevice; void ResetUIState() { globalUIState = UISTATE_MENU; @@ -124,14 +125,19 @@ GlobalUIState GetUIState() { return globalUIState; } -void SetGPUBackend(GPUBackend type) { +void SetGPUBackend(GPUBackend type, const std::string &device) { gpuBackend = type; + gpuBackendDevice = device; } GPUBackend GetGPUBackend() { return gpuBackend; } +std::string GetGPUBackendDevice() { + return gpuBackendDevice; +} + bool IsAudioInitialised() { return audioInitialized; } diff --git a/Core/System.h b/Core/System.h index f25974970e..c46b54fd13 100644 --- a/Core/System.h +++ b/Core/System.h @@ -58,8 +58,9 @@ void ResetUIState(); void UpdateUIState(GlobalUIState newState); GlobalUIState GetUIState(); -void SetGPUBackend(GPUBackend type); +void SetGPUBackend(GPUBackend type, const std::string &device = ""); GPUBackend GetGPUBackend(); +std::string GetGPUBackendDevice(); bool PSP_Init(const CoreParameter &coreParam, std::string *error_string); bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string); diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 14da475a95..9669336244 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -120,6 +120,18 @@ static std::string PostShaderTranslateName(const char *value) { } } +static std::string *GPUDeviceNameSetting() { + if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { + return &g_Config.sVulkanDevice; + } +#ifdef _WIN32 + if (g_Config.iGPUBackend == (int)GPUBackend::DIRECT3D11) { + return &g_Config.sD3D11Device; + } +#endif + return nullptr; +} + void GameSettingsScreen::CreateViews() { ReloadAllPostShaderInfo(); @@ -212,18 +224,10 @@ void GameSettingsScreen::CreateViews() { // Backends that don't allow a device choice will only expose one device. if (draw->GetDeviceList().size() > 1) { - std::string *deviceNameSetting = nullptr; - if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { - deviceNameSetting = &g_Config.sVulkanDevice; - } -#ifdef _WIN32 - if (g_Config.iGPUBackend == (int)GPUBackend::DIRECT3D11) { - deviceNameSetting = &g_Config.sD3D11Device; - } -#endif + std::string *deviceNameSetting = GPUDeviceNameSetting(); if (deviceNameSetting) { PopupMultiChoiceDynamic *deviceChoice = graphicsSettings->Add(new PopupMultiChoiceDynamic(deviceNameSetting, gr->T("Device"), draw->GetDeviceList(), nullptr, screenManager())); - deviceChoice->OnChoice.Handle(this, &GameSettingsScreen::OnRenderingBackend); + deviceChoice->OnChoice.Handle(this, &GameSettingsScreen::OnRenderingDevice); } } @@ -1088,6 +1092,23 @@ void GameSettingsScreen::CallbackRenderingBackend(bool yes) { } } +void GameSettingsScreen::CallbackRenderingDevice(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) { + // Extra save here to make sure the choice really gets saved even if there are shutdown bugs in + // the GPU backend code. + g_Config.Save(); + System_SendMessage("graphics_restart", ""); + } else { + std::string *deviceNameSetting = GPUDeviceNameSetting(); + if (deviceNameSetting) + *deviceNameSetting = GetGPUBackendDevice(); + // Needed to redraw the setting. + RecreateViews(); + } +} + UI::EventReturn GameSettingsScreen::OnRenderingBackend(UI::EventParams &e) { I18NCategory *di = GetI18NCategory("Dialog"); @@ -1099,6 +1120,18 @@ UI::EventReturn GameSettingsScreen::OnRenderingBackend(UI::EventParams &e) { return UI::EVENT_DONE; } +UI::EventReturn GameSettingsScreen::OnRenderingDevice(UI::EventParams &e) { + I18NCategory *di = GetI18NCategory("Dialog"); + + // It only makes sense to show the restart prompt if the device was actually changed. + std::string *deviceNameSetting = GPUDeviceNameSetting(); + if (deviceNameSetting && *deviceNameSetting != GetGPUBackendDevice()) { + screenManager()->push(new PromptScreen(di->T("ChangingGPUBackends", "Changing GPU backends requires PPSSPP to restart. Restart now?"), di->T("Yes"), di->T("No"), + std::bind(&GameSettingsScreen::CallbackRenderingDevice, this, std::placeholders::_1))); + } + return UI::EVENT_DONE; +} + UI::EventReturn GameSettingsScreen::OnChangeNickname(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) const size_t name_len = 256; diff --git a/UI/GameSettingsScreen.h b/UI/GameSettingsScreen.h index 259c8cf58b..2fd3bcc463 100644 --- a/UI/GameSettingsScreen.h +++ b/UI/GameSettingsScreen.h @@ -38,6 +38,7 @@ protected: void CreateViews() override; void CallbackRestoreDefaults(bool yes); void CallbackRenderingBackend(bool yes); + void CallbackRenderingDevice(bool yes); bool UseVerticalLayout() const; private: @@ -87,6 +88,7 @@ private: UI::EventReturn OnRestoreDefaultSettings(UI::EventParams &e); UI::EventReturn OnRenderingMode(UI::EventParams &e); UI::EventReturn OnRenderingBackend(UI::EventParams &e); + UI::EventReturn OnRenderingDevice(UI::EventParams &e); UI::EventReturn OnJitAffectingSetting(UI::EventParams &e); #ifdef _WIN32 UI::EventReturn OnSavePathMydoc(UI::EventParams &e); diff --git a/Windows/GPU/D3D11Context.cpp b/Windows/GPU/D3D11Context.cpp index 1689b51d6c..c5ef162b20 100644 --- a/Windows/GPU/D3D11Context.cpp +++ b/Windows/GPU/D3D11Context.cpp @@ -102,6 +102,7 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { HRESULT hr = E_FAIL; std::vector adapterNames; + std::string chosenAdapterName; if (result == LoadD3D11Error::SUCCESS) { std::vector adapters; int chosenAdapter = 0; @@ -121,6 +122,7 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { } } + chosenAdapterName = adapterNames[chosenAdapter]; hr = CreateTheDevice(adapters[chosenAdapter]); for (int i = 0; i < (int)adapters.size(); i++) { adapters[i]->Release(); @@ -172,7 +174,7 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { #endif draw_ = Draw::T3DCreateD3D11Context(device_, context_, device1_, context1_, featureLevel_, hWnd_, adapterNames); - SetGPUBackend(GPUBackend::DIRECT3D11); + SetGPUBackend(GPUBackend::DIRECT3D11, chosenAdapterName); bool success = draw_->CreatePresets(); // If we can run D3D11, there's a compiler installed. I think. assert(success); diff --git a/Windows/GPU/WindowsVulkanContext.cpp b/Windows/GPU/WindowsVulkanContext.cpp index ad619ab339..c0c512d7bb 100644 --- a/Windows/GPU/WindowsVulkanContext.cpp +++ b/Windows/GPU/WindowsVulkanContext.cpp @@ -113,7 +113,8 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m int deviceNum = g_Vulkan->GetPhysicalDeviceByName(g_Config.sVulkanDevice); if (deviceNum < 0) { deviceNum = g_Vulkan->GetBestPhysicalDevice(); - g_Config.sVulkanDevice = g_Vulkan->GetPhysicalDeviceProperties(deviceNum).deviceName; + if (!g_Config.sVulkanDevice.empty()) + g_Config.sVulkanDevice = g_Vulkan->GetPhysicalDeviceProperties(deviceNum).deviceName; } g_Vulkan->ChooseDevice(deviceNum); if (g_Vulkan->EnableDeviceExtension(VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME)) { @@ -139,7 +140,7 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m bool splitSubmit = g_Config.bGfxDebugSplitSubmit; draw_ = Draw::T3DCreateVulkanContext(g_Vulkan, splitSubmit); - SetGPUBackend(GPUBackend::VULKAN); + SetGPUBackend(GPUBackend::VULKAN, g_Vulkan->GetPhysicalDeviceProperties(deviceNum).deviceName); bool success = draw_->CreatePresets(); assert(success); // Doesn't fail, we include the compiler. draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());