From ed26368a3ad556ab5528838e4bf27eb6cd274468 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 28 Jan 2023 13:57:41 +1000 Subject: [PATCH] Achievements: Fix race in notifications GS thread might not initialize fullscreen UI before data finishes parsing. --- .../Settings/AchievementSettingsWidget.cpp | 3 +- pcsx2/Frontend/Achievements.cpp | 39 ++++++++++++------- pcsx2/Frontend/FullscreenUI.cpp | 3 +- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/pcsx2-qt/Settings/AchievementSettingsWidget.cpp b/pcsx2-qt/Settings/AchievementSettingsWidget.cpp index c4951e992d..60aeb79897 100644 --- a/pcsx2-qt/Settings/AchievementSettingsWidget.cpp +++ b/pcsx2-qt/Settings/AchievementSettingsWidget.cpp @@ -105,14 +105,13 @@ void AchievementSettingsWidget::updateEnableState() { const bool enabled = m_dialog->getEffectiveBoolValue("Achievements", "Enabled", false); const bool challenge = m_dialog->getEffectiveBoolValue("Achievements", "ChallengeMode", false); - const bool notifications = m_dialog->getEffectiveBoolValue("Achievements", "Notifications", true); m_ui.testMode->setEnabled(enabled); m_ui.unofficialTestMode->setEnabled(enabled); m_ui.richPresence->setEnabled(enabled); m_ui.challengeMode->setEnabled(enabled); m_ui.leaderboards->setEnabled(enabled && challenge); m_ui.notifications->setEnabled(enabled); - m_ui.soundEffects->setEnabled(enabled && notifications); + m_ui.soundEffects->setEnabled(enabled); m_ui.primedIndicators->setEnabled(enabled); } diff --git a/pcsx2/Frontend/Achievements.cpp b/pcsx2/Frontend/Achievements.cpp index d348ed55d3..f5d5f1e1d9 100644 --- a/pcsx2/Frontend/Achievements.cpp +++ b/pcsx2/Frontend/Achievements.cpp @@ -1033,7 +1033,7 @@ void Achievements::DownloadImage(std::string url, std::string cache_filename) void Achievements::DisplayAchievementSummary() { - if (FullscreenUI::IsInitialized() && EmuConfig.Achievements.Notifications) + if (EmuConfig.Achievements.Notifications) { std::string title = s_game_title; if (ChallengeModeActive()) @@ -1056,24 +1056,30 @@ void Achievements::DisplayAchievementSummary() summary.append("Leaderboard submission is enabled."); } - ImGuiFullscreen::AddNotification(10.0f, std::move(title), std::move(summary), s_game_icon); - - // Technically not going through the resource API, but since we're passing this to something else, we can't. - if (EmuConfig.Achievements.SoundEffects) - Common::PlaySoundAsync(Path::Combine(EmuFolders::Resources, INFO_SOUND_NAME).c_str()); + GetMTGS().RunOnGSThread([title = std::move(title), summary = std::move(summary), icon = s_game_icon]() { + if (FullscreenUI::IsInitialized()) + ImGuiFullscreen::AddNotification(10.0f, std::move(title), std::move(summary), std::move(icon)); + }); } + + // Technically not going through the resource API, but since we're passing this to something else, we can't. + if (EmuConfig.Achievements.SoundEffects) + Common::PlaySoundAsync(Path::Combine(EmuFolders::Resources, INFO_SOUND_NAME).c_str()); } void Achievements::DisplayMasteredNotification() { - if (!FullscreenUI::IsInitialized() || !EmuConfig.Achievements.Notifications) + if (!EmuConfig.Achievements.Notifications) return; std::string title(fmt::format("Mastered {}", s_game_title)); std::string message(fmt::format( "{} achievements, {} points{}", GetAchievementCount(), GetCurrentPointsForGame(), s_challenge_mode ? " (Hardcore Mode)" : "")); - ImGuiFullscreen::AddNotification(20.0f, std::move(title), std::move(message), s_game_icon); + GetMTGS().RunOnGSThread([title = std::move(title), message = std::move(message), icon = s_game_icon]() { + if (FullscreenUI::IsInitialized()) + ImGuiFullscreen::AddNotification(20.0f, std::move(title), std::move(message), std::move(icon)); + }); } void Achievements::GetUserUnlocksCallback(s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data) @@ -1796,7 +1802,10 @@ void Achievements::SubmitLeaderboardCallback(s32 status_code, const std::string& std::string summary = fmt::format( "Your Score: {} (Best: {})\nLeaderboard Position: {} of {}", submitted_score, best_score, response.new_rank, response.num_entries); - ImGuiFullscreen::AddNotification(10.0f, lb->title, std::move(summary), s_game_icon); + GetMTGS().RunOnGSThread([title = lb->title, summary = std::move(summary), icon = s_game_icon]() { + if (FullscreenUI::IsInitialized()) + ImGuiFullscreen::AddNotification(10.0f, std::move(title), std::move(summary), std::move(icon)); + }); } void Achievements::UnlockAchievement(u32 achievement_id, bool add_notification /* = true*/) @@ -1819,7 +1828,7 @@ void Achievements::UnlockAchievement(u32 achievement_id, bool add_notification / Console.WriteLn("Achievement %s (%u) for game %u unlocked", achievement->title.c_str(), achievement_id, s_game_id); - if (FullscreenUI::IsInitialized() && EmuConfig.Achievements.Notifications) + if (EmuConfig.Achievements.Notifications) { std::string title; switch (achievement->category) @@ -1836,11 +1845,15 @@ void Achievements::UnlockAchievement(u32 achievement_id, bool add_notification / break; } - ImGuiFullscreen::AddNotification(15.0f, std::move(title), achievement->description, GetAchievementBadgePath(*achievement)); - if (EmuConfig.Achievements.SoundEffects) - Common::PlaySoundAsync(Path::Combine(EmuFolders::Resources, UNLOCK_SOUND_NAME).c_str()); + GetMTGS().RunOnGSThread( + [title = std::move(title), description = achievement->description, icon = GetAchievementBadgePath(*achievement)]() { + ImGuiFullscreen::AddNotification(15.0f, std::move(title), std::move(description), std::move(icon)); + }); } + if (EmuConfig.Achievements.SoundEffects) + Common::PlaySoundAsync(Path::Combine(EmuFolders::Resources, UNLOCK_SOUND_NAME).c_str()); + if (IsMastered()) DisplayMasteredNotification(); diff --git a/pcsx2/Frontend/FullscreenUI.cpp b/pcsx2/Frontend/FullscreenUI.cpp index 685483c3fa..161cb47bb1 100644 --- a/pcsx2/Frontend/FullscreenUI.cpp +++ b/pcsx2/Frontend/FullscreenUI.cpp @@ -6759,7 +6759,6 @@ void FullscreenUI::DrawAchievementsSettingsPage(std::unique_lock& se const bool enabled = bsi->GetBoolValue("Achievements", "Enabled", false); const bool challenge = bsi->GetBoolValue("Achievements", "ChallengeMode", false); - const bool notifications = bsi->GetBoolValue("Achievements", "Notifications", true); DrawToggleSetting(bsi, ICON_FA_USER_FRIENDS " Rich Presence", "When enabled, rich presence information will be collected and sent to the server where supported.", "Achievements", "RichPresence", @@ -6774,7 +6773,7 @@ void FullscreenUI::DrawAchievementsSettingsPage(std::unique_lock& se enabled); DrawToggleSetting(bsi, ICON_FA_HEADPHONES " Sound Effects", "Plays sound effects for events such as achievement unlocks and leaderboard submissions.", "Achievements", "SoundEffects", true, - enabled && notifications); + enabled); DrawToggleSetting(bsi, ICON_FA_MAGIC " Show Challenge Indicators", "Shows icons in the lower-right corner of the screen when a challenge/primed achievement is active.", "Achievements", "PrimedIndicators", true, enabled);