diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index 98c72742a..126ab5306 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -432,7 +432,7 @@ static GPUTexture* GetTextureForGameListEntryType(GameList::EntryType type); static GPUTexture* GetGameListCover(const GameList::Entry* entry, bool fallback_to_achievements_icon, bool fallback_to_icon); static GPUTexture* GetGameListCoverTrophy(const GameList::Entry* entry, const ImVec2& image_size); -static GPUTexture* GetCoverForCurrentGame(); +static GPUTexture* GetCoverForCurrentGame(const std::string& game_path); static void SwitchToAchievements(); static void SwitchToLeaderboards(); @@ -514,11 +514,7 @@ struct ALIGN_TO_CACHE_LINE UIState bool tried_to_initialize = false; bool pause_menu_was_open = false; bool was_paused_on_quick_menu_open = false; - std::string current_game_title; - std::string current_game_serial; - std::string current_game_path; std::string achievements_user_badge_path; - GameHash current_game_hash = 0; // Resources std::shared_ptr app_icon_texture; @@ -722,23 +718,11 @@ bool FullscreenUI::Initialize() s_state.initialized = true; - // in case we open the pause menu while the game is running - const bool open_main_window = (s_state.current_main_window == MainWindowType::None && !GPUThread::HasGPUBackend() && - !GPUThread::IsGPUBackendRequested()); - if (GPUThread::HasGPUBackend()) - { - Host::RunOnCPUThread([]() { - if (System::IsValid()) - { - FullscreenUI::OnRunningGameChanged(System::GetDiscPath(), System::GetGameSerial(), System::GetGameTitle(), - System::GetGameHash()); - } - }); - } - LoadBackground(); - if (open_main_window) + // in case we open the pause menu while the game is running + if (s_state.current_main_window == MainWindowType::None && !GPUThread::HasGPUBackend() && + !GPUThread::IsGPUBackendRequested()) { ReturnToMainWindow(); ForceKeyNavEnabled(); @@ -1018,24 +1002,6 @@ void FullscreenUI::OnSystemDestroyed() }); } -void FullscreenUI::OnRunningGameChanged(const std::string& path, const std::string& serial, const std::string& title, - GameHash hash) -{ - // NOTE: Called on CPU thread. - if (!IsInitialized()) - return; - - GPUThread::RunOnThread([path = path, title = title, serial = serial, hash = hash]() mutable { - if (!IsInitialized()) - return; - - s_state.current_game_title = std::move(title); - s_state.current_game_serial = std::move(serial); - s_state.current_game_path = std::move(path); - s_state.current_game_hash = hash; - }); -} - void FullscreenUI::PauseForMenuOpen(bool set_pause_menu_open) { s_state.was_paused_on_quick_menu_open = GPUThread::IsSystemPaused(); @@ -1233,10 +1199,6 @@ void FullscreenUI::Shutdown(bool clear_state) s_state.fullscreen_mode_list_cache = {}; s_state.graphics_adapter_list_cache = {}; s_state.hotkey_list_cache = {}; - s_state.current_game_hash = 0; - s_state.current_game_path = {}; - s_state.current_game_serial = {}; - s_state.current_game_title = {}; } DestroyResources(); @@ -1657,7 +1619,7 @@ void FullscreenUI::StartChangeDiscFromFile() }; OpenFileSelector(FSUI_ICONVSTR(ICON_FA_COMPACT_DISC, "Select Disc Image"), false, std::move(callback), - GetDiscImageFilters(), std::string(Path::GetDirectory(s_state.current_game_path))); + GetDiscImageFilters(), std::string(Path::GetDirectory(GPUThread::GetGamePath()))); } void FullscreenUI::BeginChangeDiscOnCPUThread(bool needs_pause) @@ -3735,14 +3697,15 @@ void FullscreenUI::SwitchToGameSettingsForSerial(std::string_view serial, GameHa bool FullscreenUI::SwitchToGameSettings() { - if (s_state.current_game_serial.empty()) + const std::string& serial = GPUThread::GetGameSerial(); + if (serial.empty()) return false; auto lock = GameList::GetLock(); - const GameList::Entry* entry = GameList::GetEntryForPath(s_state.current_game_path); + const GameList::Entry* entry = GameList::GetEntryForPath(GPUThread::GetGamePath()); if (!entry) { - SwitchToGameSettingsForSerial(s_state.current_game_serial, s_state.current_game_hash); + SwitchToGameSettingsForSerial(serial, GPUThread::GetGameHash()); return true; } else @@ -6999,7 +6962,10 @@ void FullscreenUI::DrawPauseMenu() dl->AddRectFilled(ImVec2(0.0f, 0.0f), ImVec2(display_size.x, scaled_top_bar_height), ImGui::GetColorU32(ModAlpha(UIStyle.BackgroundColor, 0.95f)), 0.0f); - GPUTexture* const cover = GetCoverForCurrentGame(); + const std::string& game_title = GPUThread::GetGameTitle(); + const std::string& game_serial = GPUThread::GetGameSerial(); + const std::string& game_path = GPUThread::GetGamePath(); + GPUTexture* const cover = GetCoverForCurrentGame(game_path); const float image_padding = LayoutScale(5.0f); // compensate for font baseline const float image_size = scaled_top_bar_height - scaled_top_bar_padding - scaled_top_bar_padding - image_padding; const ImRect image_rect( @@ -7008,14 +6974,14 @@ void FullscreenUI::DrawPauseMenu() ImVec2(static_cast(cover->GetWidth()), static_cast(cover->GetHeight())))); dl->AddImage(cover, image_rect.Min, image_rect.Max); - if (!s_state.current_game_serial.empty()) - buffer.format("{} - {}", s_state.current_game_serial, Path::GetFileName(s_state.current_game_path)); + if (!game_serial.empty()) + buffer.format("{} - {}", game_serial, Path::GetFileName(game_path)); else - buffer.assign(Path::GetFileName(s_state.current_game_path)); + buffer.assign(Path::GetFileName(game_path)); ImVec2 text_pos = ImVec2(scaled_top_bar_padding + image_size + scaled_top_bar_padding, scaled_top_bar_padding); RenderShadowedTextClipped(dl, UIStyle.Font, UIStyle.LargeFontSize, UIStyle.BoldFontWeight, text_pos, display_size, - title_text_color, s_state.current_game_title); + title_text_color, game_title); text_pos.y += UIStyle.LargeFontSize + scaled_text_spacing; if (Achievements::IsActive()) @@ -7042,9 +7008,9 @@ void FullscreenUI::DrawPauseMenu() title_text_color, buffer); text_pos.y += UIStyle.LargeFontSize + scaled_text_spacing; - if (!s_state.current_game_serial.empty()) + if (!game_serial.empty()) { - const std::time_t cached_played_time = GameList::GetCachedPlayedTimeForSerial(s_state.current_game_serial); + const std::time_t cached_played_time = GameList::GetCachedPlayedTimeForSerial(game_serial); const std::time_t session_time = static_cast(System::GetSessionPlayedTime()); buffer.format(FSUI_FSTR("Session: {}"), GameList::FormatTimespan(session_time, true)); @@ -7110,14 +7076,12 @@ void FullscreenUI::DrawPauseMenu() if (MenuButtonWithoutSummary(FSUI_ICONVSTR(ICON_PF_DOWNLOAD, "Load State"), has_game)) { - BeginTransition( - []() { OpenSaveStateSelector(s_state.current_game_serial, s_state.current_game_path, true); }); + BeginTransition([]() { OpenSaveStateSelector(GPUThread::GetGameSerial(), GPUThread::GetGamePath(), true); }); } if (MenuButtonWithoutSummary(FSUI_ICONVSTR(ICON_PF_DISKETTE, "Save State"), has_game)) { - BeginTransition( - []() { OpenSaveStateSelector(s_state.current_game_serial, s_state.current_game_path, false); }); + BeginTransition([]() { OpenSaveStateSelector(GPUThread::GetGameSerial(), GPUThread::GetGamePath(), false); }); } if (MenuButtonWithoutSummary(FSUI_ICONVSTR(ICON_PF_GAMEPAD_ALT, "Toggle Analog"))) @@ -8925,11 +8889,11 @@ GPUTexture* FullscreenUI::GetTextureForGameListEntryType(GameList::EntryType typ } } -GPUTexture* FullscreenUI::GetCoverForCurrentGame() +GPUTexture* FullscreenUI::GetCoverForCurrentGame(const std::string& game_path) { auto lock = GameList::GetLock(); - const GameList::Entry* entry = GameList::GetEntryForPath(s_state.current_game_path); + const GameList::Entry* entry = GameList::GetEntryForPath(game_path); if (!entry) return s_state.fallback_disc_texture.get(); diff --git a/src/core/fullscreen_ui.h b/src/core/fullscreen_ui.h index 6b902dbfc..7a7b14ce3 100644 --- a/src/core/fullscreen_ui.h +++ b/src/core/fullscreen_ui.h @@ -30,7 +30,6 @@ void OnSystemStarting(); void OnSystemPaused(); void OnSystemResumed(); void OnSystemDestroyed(); -void OnRunningGameChanged(const std::string& path, const std::string& serial, const std::string& title, GameHash hash); void Shutdown(bool clear_state); void Render(); diff --git a/src/core/gpu_thread.cpp b/src/core/gpu_thread.cpp index 6dfc8ab4a..5ebb401fa 100644 --- a/src/core/gpu_thread.cpp +++ b/src/core/gpu_thread.cpp @@ -55,9 +55,8 @@ static constexpr u32 THREAD_SPIN_TIME_US = 50; static constexpr u32 THREAD_SPIN_TIME_US = 200; #endif -static bool Reconfigure(std::string serial, std::optional renderer, bool upload_vram, - std::optional fullscreen, std::optional start_fullscreen_ui, bool recreate_device, - Error* error); +static bool Reconfigure(std::optional renderer, bool upload_vram, std::optional fullscreen, + std::optional start_fullscreen_ui, bool recreate_device, Error* error); // NOTE: Use with care! The handler needs to manually run the destructor. template @@ -85,6 +84,9 @@ static void DestroyGPUPresenterOnThread(); static void SetThreadEnabled(bool enabled); static void UpdateSettingsOnThread(GPUSettings&& new_settings); +static void UpdateGameInfoOnThread(GPUThreadUpdateGameInfoCommand* cmd); +static void GameInfoChanged(bool serial_changed); +static void ClearGameInfoOnThread(); static void UpdateRunIdle(); @@ -115,7 +117,10 @@ struct ALIGN_TO_CACHE_LINE State GPUVSyncMode requested_vsync = GPUVSyncMode::Disabled; bool requested_allow_present_throttle = false; bool requested_fullscreen_ui = false; + std::string game_title; std::string game_serial; + std::string game_path; + GameHash game_hash = 0; }; } // namespace @@ -463,6 +468,14 @@ void GPUThread::Internal::GPUThreadEntryPoint() } break; + case GPUBackendCommandType::UpdateGameInfo: + { + GPUThreadUpdateGameInfoCommand* ccmd = static_cast(cmd); + UpdateGameInfoOnThread(ccmd); + ccmd->~GPUThreadUpdateGameInfoCommand(); + } + break; + case GPUBackendCommandType::Shutdown: { // Should have consumed everything, and be shutdown. @@ -498,15 +511,13 @@ void GPUThread::Internal::DoRunIdle() g_gpu_device->GetMainSwapChain()->ThrottlePresentation(); } -bool GPUThread::Reconfigure(std::string serial, std::optional renderer, bool upload_vram, - std::optional fullscreen, std::optional start_fullscreen_ui, - bool recreate_device, Error* error) +bool GPUThread::Reconfigure(std::optional renderer, bool upload_vram, std::optional fullscreen, + std::optional start_fullscreen_ui, bool recreate_device, Error* error) { INFO_LOG("Reconfiguring GPU thread."); bool result = false; GPUThreadReconfigureCommand* cmd = AllocateCommand(GPUBackendCommandType::Reconfigure); - cmd->game_serial = std::move(serial); cmd->renderer = renderer; cmd->fullscreen = fullscreen; cmd->start_fullscreen_ui = start_fullscreen_ui; @@ -535,7 +546,7 @@ bool GPUThread::StartFullscreenUI(bool fullscreen, Error* error) return true; } - return Reconfigure(std::string(), std::nullopt, false, fullscreen, true, false, error); + return Reconfigure(std::nullopt, false, fullscreen, true, false, error); } bool GPUThread::IsFullscreenUIRequested() @@ -552,7 +563,7 @@ void GPUThread::StopFullscreenUI() return; } - Reconfigure(std::string(), std::nullopt, false, std::nullopt, false, false, nullptr); + Reconfigure(std::nullopt, false, std::nullopt, false, false, nullptr); } std::optional GPUThread::GetRequestedRenderer() @@ -560,17 +571,17 @@ std::optional GPUThread::GetRequestedRenderer() return s_state.requested_renderer; } -bool GPUThread::CreateGPUBackend(std::string serial, GPURenderer renderer, bool upload_vram, bool fullscreen, - bool force_recreate_device, Error* error) +bool GPUThread::CreateGPUBackend(GPURenderer renderer, bool upload_vram, bool fullscreen, bool force_recreate_device, + Error* error) { s_state.requested_renderer = renderer; - return Reconfigure(std::move(serial), renderer, upload_vram, fullscreen ? std::optional(true) : std::nullopt, - std::nullopt, force_recreate_device, error); + return Reconfigure(renderer, upload_vram, fullscreen ? std::optional(true) : std::nullopt, std::nullopt, + force_recreate_device, error); } void GPUThread::DestroyGPUBackend() { - Reconfigure(std::string(), std::nullopt, false, std::nullopt, std::nullopt, false, nullptr); + Reconfigure(std::nullopt, false, std::nullopt, std::nullopt, false, nullptr); s_state.requested_renderer.reset(); } @@ -779,15 +790,14 @@ void GPUThread::ReconfigureOnThread(GPUThreadReconfigureCommand* cmd) // Are we shutting down everything? if (!cmd->renderer.has_value() && !s_state.requested_fullscreen_ui) { + // Serial clear must be after backend destroy, otherwise textures won't dump. DestroyGPUBackendOnThread(); DestroyGPUPresenterOnThread(); DestroyDeviceOnThread(true); - s_state.game_serial = {}; + ClearGameInfoOnThread(); return; } - // Serial clear must be after backend destroy, otherwise textures won't dump. - s_state.game_serial = std::move(cmd->game_serial); g_gpu_settings = std::move(cmd->settings); // Readback old VRAM for hardware renderers. @@ -844,6 +854,8 @@ void GPUThread::ReconfigureOnThread(GPUThreadReconfigureCommand* cmd) INFO_LOG("GPU device recreated in {:.2f}ms", timer.GetTimeMilliseconds()); } + // Full shutdown case handled above. + Assert(cmd->renderer.has_value() || s_state.requested_fullscreen_ui); if (cmd->renderer.has_value()) { Timer timer; @@ -862,6 +874,7 @@ void GPUThread::ReconfigureOnThread(GPUThreadReconfigureCommand* cmd) // No point keeping the presenter around. DestroyGPUBackendOnThread(); DestroyGPUPresenterOnThread(); + ClearGameInfoOnThread(); } } @@ -878,6 +891,7 @@ void GPUThread::ReconfigureOnThread(GPUThreadReconfigureCommand* cmd) // Don't need to present game frames anymore. DestroyGPUPresenterOnThread(); + ClearGameInfoOnThread(); // Don't need timing to run FSUI. g_gpu_device->SetGPUTimingEnabled(false); @@ -889,12 +903,6 @@ void GPUThread::ReconfigureOnThread(GPUThreadReconfigureCommand* cmd) DestroyDeviceOnThread(true); } } - else - { - // Device is no longer needed. - DestroyGPUBackendOnThread(); - DestroyDeviceOnThread(true); - } } void GPUThread::DestroyGPUBackendOnThread() @@ -965,7 +973,6 @@ void GPUThread::SetThreadEnabled(bool enabled) const bool fullscreen = Host::IsFullscreen(); const bool requested_fullscreen_ui = s_state.requested_fullscreen_ui; const std::optional requested_renderer = s_state.requested_renderer; - std::string serial = s_state.game_serial; // Force VRAM download, we're recreating. if (requested_renderer.has_value()) @@ -979,7 +986,7 @@ void GPUThread::SetThreadEnabled(bool enabled) } // Shutdown reconfigure. - Reconfigure(std::string(), std::nullopt, false, false, false, false, nullptr); + Reconfigure(std::nullopt, false, false, false, false, nullptr); // Thread should be idle at this point. Reset the FIFO. ResetCommandFIFO(); @@ -988,8 +995,8 @@ void GPUThread::SetThreadEnabled(bool enabled) s_state.use_gpu_thread = enabled; Error error; - if (!Reconfigure(std::move(serial), requested_renderer, requested_renderer.has_value(), fullscreen, - requested_fullscreen_ui, true, &error)) + if (!Reconfigure(requested_renderer, requested_renderer.has_value(), fullscreen, requested_fullscreen_ui, true, + &error)) { ERROR_LOG("Reconfigure failed: {}", error.GetDescription()); ReportFatalErrorAndShutdown(fmt::format("Reconfigure failed: {}", error.GetDescription())); @@ -1100,8 +1107,8 @@ void GPUThread::UpdateSettings(bool gpu_settings_changed, bool device_settings_c INFO_LOG("Reconfiguring after device settings changed."); Error error; - if (!Reconfigure(System::GetGameSerial(), s_state.requested_renderer, s_state.requested_renderer.has_value(), - std::nullopt, std::nullopt, true, &error)) [[unlikely]] + if (!Reconfigure(s_state.requested_renderer, s_state.requested_renderer.has_value(), std::nullopt, std::nullopt, + true, &error)) [[unlikely]] { Host::ReportErrorAsync("Error", fmt::format("Failed to recreate GPU device: {}", error.GetDescription())); } @@ -1134,6 +1141,71 @@ void GPUThread::UpdateSettings(bool gpu_settings_changed, bool device_settings_c } } +void GPUThread::UpdateGameInfo(const std::string& title, const std::string& serial, const std::string& path, + GameHash hash, bool wake_thread /*= true*/) +{ + if (!s_state.use_gpu_thread) + { + const bool serial_changed = (s_state.game_serial != serial); + s_state.game_title = title; + s_state.game_serial = serial; + s_state.game_path = path; + s_state.game_hash = hash; + GameInfoChanged(serial_changed); + return; + } + + GPUThreadUpdateGameInfoCommand* cmd = + AllocateCommand(GPUBackendCommandType::UpdateGameInfo, title, serial, path, hash); + + if (wake_thread) + PushCommandAndWakeThread(cmd); + else + PushCommand(cmd); +} + +void GPUThread::ClearGameInfo() +{ + if (!s_state.use_gpu_thread) + { + ClearGameInfoOnThread(); + return; + } + + PushCommandAndWakeThread(AllocateCommand(GPUBackendCommandType::UpdateGameInfo)); +} + +void GPUThread::UpdateGameInfoOnThread(GPUThreadUpdateGameInfoCommand* cmd) +{ + DEV_LOG("Updating game info on GPU thread: {}/{}", cmd->game_serial, cmd->game_title); + const bool serial_changed = (s_state.game_serial != cmd->game_serial); + s_state.game_title = std::move(cmd->game_title); + s_state.game_serial = std::move(cmd->game_serial); + s_state.game_path = std::move(cmd->game_path); + s_state.game_hash = cmd->game_hash; + GameInfoChanged(serial_changed); +} + +void GPUThread::GameInfoChanged(bool serial_changed) +{ + if (!serial_changed) + return; + + if (HasGPUBackend()) + GPUTextureCache::GameSerialChanged(); + if (SaveStateSelectorUI::IsOpen()) + SaveStateSelectorUI::RefreshList(); +} + +void GPUThread::ClearGameInfoOnThread() +{ + DEV_LOG("Clearing game info on GPU thread."); + s_state.game_hash = 0; + s_state.game_path = {}; + s_state.game_serial = {}; + s_state.game_title = {}; +} + void GPUThread::ReportFatalErrorAndShutdown(std::string_view reason) { DebugAssert(IsOnThread()); @@ -1389,24 +1461,26 @@ void GPUThread::UpdateRunIdle() Host::OnGPUThreadRunIdleChanged(new_flag); } +const std::string& GPUThread::GetGameTitle() +{ + DebugAssert(IsOnThread()); + return s_state.game_title; +} + const std::string& GPUThread::GetGameSerial() { DebugAssert(IsOnThread()); return s_state.game_serial; } -void GPUThread::SetGameSerial(std::string serial) +const std::string& GPUThread::GetGamePath() { - DebugAssert(!IsOnThread() || !s_state.use_gpu_thread); - RunOnThread([serial = std::move(serial)]() mutable { - const bool changed = (s_state.game_serial != serial); - s_state.game_serial = std::move(serial); - if (changed) - { - if (HasGPUBackend()) - GPUTextureCache::GameSerialChanged(); - if (SaveStateSelectorUI::IsOpen()) - SaveStateSelectorUI::RefreshList(); - } - }); + DebugAssert(IsOnThread()); + return s_state.game_path; +} + +GameHash GPUThread::GetGameHash() +{ + DebugAssert(IsOnThread()); + return s_state.game_hash; } diff --git a/src/core/gpu_thread.h b/src/core/gpu_thread.h index 32921a997..42f03c6c4 100644 --- a/src/core/gpu_thread.h +++ b/src/core/gpu_thread.h @@ -3,7 +3,7 @@ #pragma once -#include "common/types.h" +#include "types.h" #include #include @@ -46,12 +46,11 @@ void StopFullscreenUI(); /// Backend control. std::optional GetRequestedRenderer(); -bool CreateGPUBackend(std::string serial, GPURenderer renderer, bool upload_vram, bool fullscreen, - bool force_recreate_device, Error* error); +bool CreateGPUBackend(GPURenderer renderer, bool upload_vram, bool fullscreen, bool force_recreate_device, + Error* error); void DestroyGPUBackend(); bool HasGPUBackend(); bool IsGPUBackendRequested(); -void SetGameSerial(std::string serial); /// Re-presents the current frame. Call when things like window resizes happen to re-display /// the current frame with the correct proportions. Should only be called from the CPU thread. @@ -67,6 +66,9 @@ void ResizeDisplayWindow(s32 width, s32 height, float scale); const WindowInfo& GetRenderWindowInfo(); void UpdateSettings(bool gpu_settings_changed, bool device_settings_changed, bool thread_changed); +void UpdateGameInfo(const std::string& title, const std::string& serial, const std::string& path, GameHash hash, + bool wake_thread = true); +void ClearGameInfo(); /// Triggers an abnormal system shutdown and waits for it to destroy the backend. void ReportFatalErrorAndShutdown(std::string_view reason); @@ -84,7 +86,10 @@ bool GetRunIdleReason(RunIdleReason reason); void SetRunIdleReason(RunIdleReason reason, bool enabled); bool IsRunningIdle(); bool IsSystemPaused(); +const std::string& GetGameTitle(); const std::string& GetGameSerial(); +const std::string& GetGamePath(); +GameHash GetGameHash(); GPUThreadCommand* AllocateCommand(GPUBackendCommandType command, u32 size); void PushCommand(GPUThreadCommand* cmd); diff --git a/src/core/gpu_thread_commands.h b/src/core/gpu_thread_commands.h index dbfad3d95..cafb9375e 100644 --- a/src/core/gpu_thread_commands.h +++ b/src/core/gpu_thread_commands.h @@ -31,6 +31,7 @@ enum class GPUBackendCommandType : u8 AsyncBackendCall, Reconfigure, UpdateSettings, + UpdateGameInfo, Shutdown, ClearVRAM, ClearDisplay, @@ -71,7 +72,6 @@ struct GPUThreadReconfigureCommand : public GPUThreadCommand { Error* error_ptr; bool* out_result; - std::string game_serial; std::optional renderer; std::optional fullscreen; std::optional start_fullscreen_ui; @@ -89,6 +89,21 @@ struct GPUThreadUpdateSettingsCommand : public GPUThreadCommand GPUSettings settings; }; +struct GPUThreadUpdateGameInfoCommand : public GPUThreadCommand +{ + GPUThreadUpdateGameInfoCommand() = default; + GPUThreadUpdateGameInfoCommand(const std::string& game_title_, const std::string& game_serial_, + const std::string& game_path_, const GameHash& game_hash_) + : game_title(game_title_), game_serial(game_serial_), game_path(game_path_), game_hash(game_hash_) + { + } + + std::string game_title; + std::string game_serial; + std::string game_path; + GameHash game_hash; +}; + struct GPUThreadAsyncCallCommand : public GPUThreadCommand { GPUThreadAsyncCallCommand() = default; diff --git a/src/core/system.cpp b/src/core/system.cpp index bf7b73e4f..635eed816 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -1193,7 +1193,7 @@ void System::RecreateGPU(GPURenderer renderer) StopMediaCapture(); Error error; - if (!GPUThread::CreateGPUBackend(s_state.running_game_serial, renderer, true, false, false, &error)) + if (!GPUThread::CreateGPUBackend(renderer, true, false, false, &error)) { ERROR_LOG("Failed to switch to {} renderer: {}", Settings::GetRendererName(renderer), error.GetDescription()); Panic("Failed to switch renderer."); @@ -1910,24 +1910,23 @@ bool System::Initialize(std::unique_ptr disc, DiscRegion disc_region, b // TODO: Drop class g_gpu.Initialize(); + // Game info must be set prior to backend creation because of texture replacements. + // We don't do it in UpdateRunningGame() when booting because it can fail in a number of locations. + GPUThread::UpdateGameInfo(s_state.running_game_title, s_state.running_game_serial, s_state.running_game_path, + s_state.running_game_hash, false); + // This can fail due to the application being closed during startup. - if (!GPUThread::CreateGPUBackend(s_state.running_game_serial, - force_software_renderer ? GPURenderer::Software : g_settings.gpu_renderer, false, + if (!GPUThread::CreateGPUBackend(force_software_renderer ? GPURenderer::Software : g_settings.gpu_renderer, false, fullscreen, false, error)) { + // Game info has to be manually cleared since the backend won't shutdown naturally. + GPUThread::ClearGameInfo(); return false; } if (g_settings.gpu_pgxp_enable) CPU::PGXP::Initialize(); - // Was startup cancelled? (e.g. shading compilers took too long and the user closed the application) - if (IsStartupCancelled()) - { - Error::SetStringView(error, TRANSLATE_SV("System", "Startup was cancelled.")); - return false; - } - DMA::Initialize(); Pad::Initialize(); Timers::Initialize(); @@ -4221,15 +4220,15 @@ void System::UpdateRunningGame(const std::string& path, CDImage* image, bool boo } if (s_state.running_game_serial != prev_serial) - { - GPUThread::SetGameSerial(s_state.running_game_serial); UpdateSessionTime(prev_serial); - } UpdateRichPresence(booting); - FullscreenUI::OnRunningGameChanged(s_state.running_game_path, s_state.running_game_serial, s_state.running_game_title, - s_state.running_game_hash); + if (!booting) + { + GPUThread::UpdateGameInfo(s_state.running_game_title, s_state.running_game_serial, s_state.running_game_path, + s_state.running_game_hash); + } Host::OnSystemGameChanged(s_state.running_game_path, s_state.running_game_serial, s_state.running_game_title, s_state.running_game_hash);