FullscreenUI: Support renderer swapping without restart
This commit is contained in:
parent
406cd1b6a1
commit
f3f99f7eac
|
@ -592,23 +592,21 @@ bool FullscreenUI::Initialize()
|
||||||
!LoadResources())
|
!LoadResources())
|
||||||
{
|
{
|
||||||
DestroyResources();
|
DestroyResources();
|
||||||
ImGuiFullscreen::Shutdown();
|
Shutdown(true);
|
||||||
s_state.tried_to_initialize = true;
|
s_state.tried_to_initialize = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
s_state.initialized = true;
|
s_state.initialized = true;
|
||||||
s_state.current_main_window = MainWindowType::None;
|
|
||||||
s_state.current_pause_submenu = PauseSubMenu::None;
|
|
||||||
s_state.pause_menu_was_open = false;
|
|
||||||
s_state.was_paused_on_quick_menu_open = false;
|
|
||||||
s_state.about_window_open = false;
|
|
||||||
s_state.hotkey_list_cache = InputManager::GetHotkeyList();
|
s_state.hotkey_list_cache = InputManager::GetHotkeyList();
|
||||||
|
|
||||||
Host::RunOnCPUThread([]() { Host::OnFullscreenUIStartedOrStopped(true); });
|
Host::RunOnCPUThread([]() { Host::OnFullscreenUIStartedOrStopped(true); });
|
||||||
|
|
||||||
if (!GPUThread::HasGPUBackend() && !GPUThread::IsGPUBackendRequested())
|
if (s_state.current_main_window == MainWindowType::None && !GPUThread::HasGPUBackend() &&
|
||||||
|
!GPUThread::IsGPUBackendRequested())
|
||||||
|
{
|
||||||
SwitchToLanding();
|
SwitchToLanding();
|
||||||
|
}
|
||||||
|
|
||||||
UpdateRunIdleState();
|
UpdateRunIdleState();
|
||||||
ForceKeyNavEnabled();
|
ForceKeyNavEnabled();
|
||||||
|
@ -799,27 +797,37 @@ void FullscreenUI::OpenPauseSubMenu(PauseSubMenu submenu)
|
||||||
QueueResetFocus(FocusResetType::ViewChanged);
|
QueueResetFocus(FocusResetType::ViewChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FullscreenUI::Shutdown()
|
void FullscreenUI::Shutdown(bool clear_state)
|
||||||
{
|
{
|
||||||
Achievements::ClearUIState();
|
if (clear_state)
|
||||||
ClearInputBindingVariables();
|
{
|
||||||
CloseSaveStateSelector();
|
s_state.current_main_window = MainWindowType::None;
|
||||||
s_state.cover_image_map.clear();
|
s_state.current_pause_submenu = PauseSubMenu::None;
|
||||||
std::memset(s_state.controller_macro_expanded, 0, sizeof(s_state.controller_macro_expanded));
|
s_state.pause_menu_was_open = false;
|
||||||
s_state.game_list_sorted_entries = {};
|
s_state.was_paused_on_quick_menu_open = false;
|
||||||
s_state.game_list_directories_cache = {};
|
s_state.about_window_open = false;
|
||||||
s_state.game_patch_list = {};
|
|
||||||
s_state.enabled_game_patch_cache = {};
|
Achievements::ClearUIState();
|
||||||
s_state.game_cheats_list = {};
|
ClearInputBindingVariables();
|
||||||
s_state.enabled_game_cheat_cache = {};
|
CloseSaveStateSelector();
|
||||||
s_state.game_cheat_groups = {};
|
s_state.cover_image_map.clear();
|
||||||
s_state.postprocessing_stages = {};
|
std::memset(s_state.controller_macro_expanded, 0, sizeof(s_state.controller_macro_expanded));
|
||||||
s_state.fullscreen_mode_list_cache = {};
|
s_state.game_list_sorted_entries = {};
|
||||||
s_state.graphics_adapter_list_cache = {};
|
s_state.game_list_directories_cache = {};
|
||||||
s_state.hotkey_list_cache = {};
|
s_state.game_patch_list = {};
|
||||||
s_state.current_game_subtitle = {};
|
s_state.enabled_game_patch_cache = {};
|
||||||
|
s_state.game_cheats_list = {};
|
||||||
|
s_state.enabled_game_cheat_cache = {};
|
||||||
|
s_state.game_cheat_groups = {};
|
||||||
|
s_state.postprocessing_stages = {};
|
||||||
|
s_state.fullscreen_mode_list_cache = {};
|
||||||
|
s_state.graphics_adapter_list_cache = {};
|
||||||
|
s_state.hotkey_list_cache = {};
|
||||||
|
s_state.current_game_subtitle = {};
|
||||||
|
}
|
||||||
|
|
||||||
DestroyResources();
|
DestroyResources();
|
||||||
ImGuiFullscreen::Shutdown();
|
ImGuiFullscreen::Shutdown(clear_state);
|
||||||
if (s_state.initialized)
|
if (s_state.initialized)
|
||||||
Host::RunOnCPUThread([]() { Host::OnFullscreenUIStartedOrStopped(false); });
|
Host::RunOnCPUThread([]() { Host::OnFullscreenUIStartedOrStopped(false); });
|
||||||
|
|
||||||
|
@ -4318,7 +4326,6 @@ void FullscreenUI::DrawGraphicsSettingsPage()
|
||||||
else
|
else
|
||||||
bsi->SetStringValue("GPU", "Adapter", value);
|
bsi->SetStringValue("GPU", "Adapter", value);
|
||||||
SetSettingsChanged(bsi);
|
SetSettingsChanged(bsi);
|
||||||
ShowToast(std::string(), FSUI_STR("GPU adapter will be applied after restarting."), 10.0f);
|
|
||||||
CloseChoiceDialog();
|
CloseChoiceDialog();
|
||||||
};
|
};
|
||||||
OpenChoiceDialog(FSUI_ICONSTR(ICON_FA_MICROCHIP, "GPU Adapter"), false, std::move(options), std::move(callback));
|
OpenChoiceDialog(FSUI_ICONSTR(ICON_FA_MICROCHIP, "GPU Adapter"), false, std::move(options), std::move(callback));
|
||||||
|
|
|
@ -35,7 +35,7 @@ void ReturnToPreviousWindow();
|
||||||
void SetStandardSelectionFooterText(bool back_instead_of_cancel);
|
void SetStandardSelectionFooterText(bool back_instead_of_cancel);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Shutdown();
|
void Shutdown(bool clear_state);
|
||||||
void Render();
|
void Render();
|
||||||
void InvalidateCoverCache();
|
void InvalidateCoverCache();
|
||||||
void TimeToPrintableString(SmallStringBase* str, time_t t);
|
void TimeToPrintableString(SmallStringBase* str, time_t t);
|
||||||
|
|
|
@ -68,8 +68,8 @@ static bool IsCommandFIFOEmpty();
|
||||||
static void WakeGPUThread();
|
static void WakeGPUThread();
|
||||||
static bool SleepGPUThread(bool allow_sleep);
|
static bool SleepGPUThread(bool allow_sleep);
|
||||||
|
|
||||||
static bool CreateDeviceOnThread(RenderAPI api, bool fullscreen, Error* error);
|
static bool CreateDeviceOnThread(RenderAPI api, bool fullscreen, bool clear_fsui_state_on_failure, Error* error);
|
||||||
static void DestroyDeviceOnThread();
|
static void DestroyDeviceOnThread(bool clear_fsui_state);
|
||||||
static void ResizeDisplayWindowOnThread(u32 width, u32 height, float scale);
|
static void ResizeDisplayWindowOnThread(u32 width, u32 height, float scale);
|
||||||
static void UpdateDisplayWindowOnThread(bool fullscreen);
|
static void UpdateDisplayWindowOnThread(bool fullscreen);
|
||||||
static void DisplayWindowResizedOnThread();
|
static void DisplayWindowResizedOnThread();
|
||||||
|
@ -610,7 +610,7 @@ bool GPUThread::IsGPUBackendRequested()
|
||||||
return s_state.requested_renderer.has_value();
|
return s_state.requested_renderer.has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPUThread::CreateDeviceOnThread(RenderAPI api, bool fullscreen, Error* error)
|
bool GPUThread::CreateDeviceOnThread(RenderAPI api, bool fullscreen, bool clear_fsui_state_on_failure, Error* error)
|
||||||
{
|
{
|
||||||
DebugAssert(!g_gpu_device);
|
DebugAssert(!g_gpu_device);
|
||||||
|
|
||||||
|
@ -686,7 +686,7 @@ bool GPUThread::CreateDeviceOnThread(RenderAPI api, bool fullscreen, Error* erro
|
||||||
{
|
{
|
||||||
ERROR_LOG("Failed to initialize ImGuiManager: {}", create_error.GetDescription());
|
ERROR_LOG("Failed to initialize ImGuiManager: {}", create_error.GetDescription());
|
||||||
Error::SetStringFmt(error, "Failed to initialize ImGuiManager: {}", create_error.GetDescription());
|
Error::SetStringFmt(error, "Failed to initialize ImGuiManager: {}", create_error.GetDescription());
|
||||||
FullscreenUI::Shutdown();
|
FullscreenUI::Shutdown(clear_fsui_state_on_failure);
|
||||||
ImGuiManager::Shutdown();
|
ImGuiManager::Shutdown();
|
||||||
g_gpu_device->Destroy();
|
g_gpu_device->Destroy();
|
||||||
g_gpu_device.reset();
|
g_gpu_device.reset();
|
||||||
|
@ -707,14 +707,14 @@ bool GPUThread::CreateDeviceOnThread(RenderAPI api, bool fullscreen, Error* erro
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPUThread::DestroyDeviceOnThread()
|
void GPUThread::DestroyDeviceOnThread(bool clear_fsui_state)
|
||||||
{
|
{
|
||||||
if (!g_gpu_device)
|
if (!g_gpu_device)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const bool has_window = g_gpu_device->HasMainSwapChain();
|
const bool has_window = g_gpu_device->HasMainSwapChain();
|
||||||
|
|
||||||
FullscreenUI::Shutdown();
|
FullscreenUI::Shutdown(clear_fsui_state);
|
||||||
ImGuiManager::Shutdown();
|
ImGuiManager::Shutdown();
|
||||||
|
|
||||||
INFO_LOG("Destroying {} GPU device...", GPUDevice::RenderAPIToString(g_gpu_device->GetRenderAPI()));
|
INFO_LOG("Destroying {} GPU device...", GPUDevice::RenderAPIToString(g_gpu_device->GetRenderAPI()));
|
||||||
|
@ -749,12 +749,12 @@ void GPUThread::HandleGPUDeviceLost()
|
||||||
// Device lost, something went really bad.
|
// Device lost, something went really bad.
|
||||||
// Let's just toss out everything, and try to hobble on.
|
// Let's just toss out everything, and try to hobble on.
|
||||||
DestroyGPUBackendOnThread();
|
DestroyGPUBackendOnThread();
|
||||||
DestroyDeviceOnThread();
|
DestroyDeviceOnThread(false);
|
||||||
|
|
||||||
Error error;
|
Error error;
|
||||||
if (!CreateDeviceOnThread(
|
if (!CreateDeviceOnThread(
|
||||||
Settings::GetRenderAPIForRenderer(s_state.requested_renderer.value_or(g_gpu_settings.gpu_renderer)),
|
Settings::GetRenderAPIForRenderer(s_state.requested_renderer.value_or(g_gpu_settings.gpu_renderer)),
|
||||||
is_fullscreen, &error) ||
|
is_fullscreen, true, &error) ||
|
||||||
(s_state.requested_renderer.has_value() &&
|
(s_state.requested_renderer.has_value() &&
|
||||||
!CreateGPUBackendOnThread(s_state.requested_renderer.value(), true, &error)))
|
!CreateGPUBackendOnThread(s_state.requested_renderer.value(), true, &error)))
|
||||||
{
|
{
|
||||||
|
@ -832,7 +832,7 @@ void GPUThread::ReconfigureOnThread(GPUThreadReconfigureCommand* cmd)
|
||||||
if (!cmd->renderer.has_value() && !s_state.requested_fullscreen_ui)
|
if (!cmd->renderer.has_value() && !s_state.requested_fullscreen_ui)
|
||||||
{
|
{
|
||||||
DestroyGPUBackendOnThread();
|
DestroyGPUBackendOnThread();
|
||||||
DestroyDeviceOnThread();
|
DestroyDeviceOnThread(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -864,10 +864,10 @@ void GPUThread::ReconfigureOnThread(GPUThreadReconfigureCommand* cmd)
|
||||||
if (cmd->force_recreate_device || !GPUDevice::IsSameRenderAPI(current_api, expected_api))
|
if (cmd->force_recreate_device || !GPUDevice::IsSameRenderAPI(current_api, expected_api))
|
||||||
{
|
{
|
||||||
const bool fullscreen = cmd->fullscreen.value_or(Host::IsFullscreen());
|
const bool fullscreen = cmd->fullscreen.value_or(Host::IsFullscreen());
|
||||||
DestroyDeviceOnThread();
|
DestroyDeviceOnThread(false);
|
||||||
|
|
||||||
Error local_error;
|
Error local_error;
|
||||||
if (!CreateDeviceOnThread(expected_api, fullscreen, &local_error))
|
if (!CreateDeviceOnThread(expected_api, fullscreen, false, &local_error))
|
||||||
{
|
{
|
||||||
Host::AddIconOSDMessage(
|
Host::AddIconOSDMessage(
|
||||||
"DeviceSwitchFailed", ICON_FA_PAINT_ROLLER,
|
"DeviceSwitchFailed", ICON_FA_PAINT_ROLLER,
|
||||||
|
@ -877,7 +877,7 @@ void GPUThread::ReconfigureOnThread(GPUThreadReconfigureCommand* cmd)
|
||||||
Host::OSD_CRITICAL_ERROR_DURATION);
|
Host::OSD_CRITICAL_ERROR_DURATION);
|
||||||
|
|
||||||
Host::ReleaseRenderWindow();
|
Host::ReleaseRenderWindow();
|
||||||
if (current_api == RenderAPI::None || !CreateDeviceOnThread(current_api, fullscreen, &local_error))
|
if (current_api == RenderAPI::None || !CreateDeviceOnThread(current_api, fullscreen, true, &local_error))
|
||||||
{
|
{
|
||||||
if (cmd->error_ptr)
|
if (cmd->error_ptr)
|
||||||
*cmd->error_ptr = local_error;
|
*cmd->error_ptr = local_error;
|
||||||
|
@ -895,7 +895,8 @@ void GPUThread::ReconfigureOnThread(GPUThreadReconfigureCommand* cmd)
|
||||||
}
|
}
|
||||||
else if (s_state.requested_fullscreen_ui)
|
else if (s_state.requested_fullscreen_ui)
|
||||||
{
|
{
|
||||||
if (!g_gpu_device && !CreateDeviceOnThread(expected_api, cmd->fullscreen.value_or(false), cmd->error_ptr))
|
const bool had_gpu_device = static_cast<bool>(g_gpu_device);
|
||||||
|
if (!g_gpu_device && !CreateDeviceOnThread(expected_api, cmd->fullscreen.value_or(false), true, cmd->error_ptr))
|
||||||
{
|
{
|
||||||
*cmd->out_result = false;
|
*cmd->out_result = false;
|
||||||
return;
|
return;
|
||||||
|
@ -905,12 +906,16 @@ void GPUThread::ReconfigureOnThread(GPUThreadReconfigureCommand* cmd)
|
||||||
g_gpu_device->SetGPUTimingEnabled(false);
|
g_gpu_device->SetGPUTimingEnabled(false);
|
||||||
|
|
||||||
if (!(*cmd->out_result = FullscreenUI::IsInitialized() || FullscreenUI::Initialize()))
|
if (!(*cmd->out_result = FullscreenUI::IsInitialized() || FullscreenUI::Initialize()))
|
||||||
|
{
|
||||||
Error::SetStringView(cmd->error_ptr, "Failed to initialize FullscreenUI.");
|
Error::SetStringView(cmd->error_ptr, "Failed to initialize FullscreenUI.");
|
||||||
|
if (!had_gpu_device)
|
||||||
|
DestroyDeviceOnThread(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Device is no longer needed.
|
// Device is no longer needed.
|
||||||
DestroyDeviceOnThread();
|
DestroyDeviceOnThread(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1093,7 +1093,7 @@ void Settings::FixIncompatibleSettings(const SettingsInterface& si, bool display
|
||||||
|
|
||||||
bool Settings::AreGPUDeviceSettingsChanged(const Settings& old_settings) const
|
bool Settings::AreGPUDeviceSettingsChanged(const Settings& old_settings) const
|
||||||
{
|
{
|
||||||
return (gpu_use_debug_device != old_settings.gpu_use_debug_device ||
|
return (gpu_adapter != old_settings.gpu_adapter || gpu_use_debug_device != old_settings.gpu_use_debug_device ||
|
||||||
gpu_disable_shader_cache != old_settings.gpu_disable_shader_cache ||
|
gpu_disable_shader_cache != old_settings.gpu_disable_shader_cache ||
|
||||||
gpu_disable_dual_source_blend != old_settings.gpu_disable_dual_source_blend ||
|
gpu_disable_dual_source_blend != old_settings.gpu_disable_dual_source_blend ||
|
||||||
gpu_disable_framebuffer_fetch != old_settings.gpu_disable_framebuffer_fetch ||
|
gpu_disable_framebuffer_fetch != old_settings.gpu_disable_framebuffer_fetch ||
|
||||||
|
|
|
@ -4577,7 +4577,7 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
|
||||||
if (GPUThread::IsFullscreenUIRequested())
|
if (GPUThread::IsFullscreenUIRequested())
|
||||||
{
|
{
|
||||||
// handle device setting updates as well
|
// handle device setting updates as well
|
||||||
if (g_settings.AreGPUDeviceSettingsChanged(old_settings))
|
if (g_settings.gpu_renderer != old_settings.gpu_renderer || g_settings.AreGPUDeviceSettingsChanged(old_settings))
|
||||||
GPUThread::UpdateSettings(false, true);
|
GPUThread::UpdateSettings(false, true);
|
||||||
|
|
||||||
if (g_settings.display_vsync != old_settings.display_vsync ||
|
if (g_settings.display_vsync != old_settings.display_vsync ||
|
||||||
|
|
|
@ -216,7 +216,7 @@ bool ImGuiFullscreen::Initialize(const char* placeholder_image_path)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiFullscreen::Shutdown()
|
void ImGuiFullscreen::Shutdown(bool clear_state)
|
||||||
{
|
{
|
||||||
if (s_state.texture_load_thread.joinable())
|
if (s_state.texture_load_thread.joinable())
|
||||||
{
|
{
|
||||||
|
@ -235,33 +235,36 @@ void ImGuiFullscreen::Shutdown()
|
||||||
|
|
||||||
s_state.texture_cache.Clear();
|
s_state.texture_cache.Clear();
|
||||||
|
|
||||||
s_state.notifications.clear();
|
if (clear_state)
|
||||||
s_state.background_progress_dialogs.clear();
|
{
|
||||||
s_state.fullscreen_footer_text.clear();
|
s_state.notifications.clear();
|
||||||
s_state.last_fullscreen_footer_text.clear();
|
s_state.background_progress_dialogs.clear();
|
||||||
s_state.fullscreen_text_change_time = 0.0f;
|
s_state.fullscreen_footer_text.clear();
|
||||||
CloseInputDialog();
|
s_state.last_fullscreen_footer_text.clear();
|
||||||
CloseMessageDialog();
|
s_state.fullscreen_text_change_time = 0.0f;
|
||||||
s_state.choice_dialog_open = false;
|
CloseInputDialog();
|
||||||
s_state.choice_dialog_checkable = false;
|
CloseMessageDialog();
|
||||||
s_state.choice_dialog_title = {};
|
s_state.choice_dialog_open = false;
|
||||||
s_state.choice_dialog_options.clear();
|
s_state.choice_dialog_checkable = false;
|
||||||
s_state.choice_dialog_callback = {};
|
s_state.choice_dialog_title = {};
|
||||||
s_state.enum_choice_button_id = 0;
|
s_state.choice_dialog_options.clear();
|
||||||
s_state.enum_choice_button_value = 0;
|
s_state.choice_dialog_callback = {};
|
||||||
s_state.enum_choice_button_set = false;
|
s_state.enum_choice_button_id = 0;
|
||||||
s_state.file_selector_open = false;
|
s_state.enum_choice_button_value = 0;
|
||||||
s_state.file_selector_directory = false;
|
s_state.enum_choice_button_set = false;
|
||||||
s_state.file_selector_title = {};
|
s_state.file_selector_open = false;
|
||||||
s_state.file_selector_callback = {};
|
s_state.file_selector_directory = false;
|
||||||
s_state.file_selector_current_directory = {};
|
s_state.file_selector_title = {};
|
||||||
s_state.file_selector_filters.clear();
|
s_state.file_selector_callback = {};
|
||||||
s_state.file_selector_items.clear();
|
s_state.file_selector_current_directory = {};
|
||||||
s_state.message_dialog_open = false;
|
s_state.file_selector_filters.clear();
|
||||||
s_state.message_dialog_title = {};
|
s_state.file_selector_items.clear();
|
||||||
s_state.message_dialog_message = {};
|
s_state.message_dialog_open = false;
|
||||||
s_state.message_dialog_buttons = {};
|
s_state.message_dialog_title = {};
|
||||||
s_state.message_dialog_callback = {};
|
s_state.message_dialog_message = {};
|
||||||
|
s_state.message_dialog_buttons = {};
|
||||||
|
s_state.message_dialog_callback = {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiFullscreen::SetSmoothScrolling(bool enabled)
|
void ImGuiFullscreen::SetSmoothScrolling(bool enabled)
|
||||||
|
|
|
@ -130,7 +130,7 @@ void SetFonts(ImFont* medium_font, ImFont* large_font);
|
||||||
bool UpdateLayoutScale();
|
bool UpdateLayoutScale();
|
||||||
|
|
||||||
/// Shuts down, clearing all state.
|
/// Shuts down, clearing all state.
|
||||||
void Shutdown();
|
void Shutdown(bool clear_state);
|
||||||
|
|
||||||
/// Texture cache.
|
/// Texture cache.
|
||||||
const std::shared_ptr<GPUTexture>& GetPlaceholderTexture();
|
const std::shared_ptr<GPUTexture>& GetPlaceholderTexture();
|
||||||
|
|
Loading…
Reference in New Issue