From 5637fc7804fb1da12e3364fef77763938532e864 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 12 Jan 2026 18:25:31 +1000 Subject: [PATCH] ImGuiManager: Run idle when OSD messages are present So we don't miss them. --- src/core/gpu_thread.cpp | 21 +++++++++++-- src/core/gpu_thread.h | 9 +++--- src/util/imgui_manager.cpp | 63 ++++++++++++++++++++++++++++++++------ 3 files changed, 78 insertions(+), 15 deletions(-) diff --git a/src/core/gpu_thread.cpp b/src/core/gpu_thread.cpp index 905027494..c8ec0b17f 100644 --- a/src/core/gpu_thread.cpp +++ b/src/core/gpu_thread.cpp @@ -1485,6 +1485,22 @@ void GPUThread::SetRunIdleReason(RunIdleReason reason, bool enabled) if (((s_state.run_idle_reasons & bit) != 0) == enabled) return; + if (Log::IsLogVisible(Log::Level::Dev, Log::Channel::GPUThread)) + { + static constexpr const std::array reason_strings = { + "NoGPUBackend", "SystemPaused", "OSDMessagesActive", "FullscreenUIActive", + "NotificationsActive", "LoadingScreenActive", "AchievementOverlaysActive", + }; + for (u32 i = 0; i < reason_strings.size(); ++i) + { + if (static_cast(1u << i) == reason) + { + DEV_COLOR_LOG(StrongYellow, "Setting run idle reason '{}' to {}", reason_strings[i], enabled); + break; + } + } + } + s_state.run_idle_reasons = enabled ? (s_state.run_idle_reasons | bit) : (s_state.run_idle_reasons & ~bit); UpdateRunIdle(); } @@ -1508,8 +1524,9 @@ void GPUThread::UpdateRunIdle() static_cast(RunIdleReason::SystemPaused) | static_cast(RunIdleReason::LoadingScreenActive); static constexpr u8 ACTIVATE_MASK = - static_cast(RunIdleReason::FullscreenUIActive) | static_cast(RunIdleReason::NotificationsActive) | - static_cast(RunIdleReason::LoadingScreenActive) | static_cast(RunIdleReason::AchievementOverlaysActive); + static_cast(RunIdleReason::OSDMessagesActive) | static_cast(RunIdleReason::FullscreenUIActive) | + static_cast(RunIdleReason::NotificationsActive) | static_cast(RunIdleReason::LoadingScreenActive) | + static_cast(RunIdleReason::AchievementOverlaysActive); const bool new_flag = (g_gpu_device && ((s_state.run_idle_reasons & REQUIRE_MASK) != 0) && ((s_state.run_idle_reasons & ACTIVATE_MASK) != 0)); diff --git a/src/core/gpu_thread.h b/src/core/gpu_thread.h index a3bdac3c4..f7f07882f 100644 --- a/src/core/gpu_thread.h +++ b/src/core/gpu_thread.h @@ -36,10 +36,11 @@ enum class RunIdleReason : u8 { NoGPUBackend = (1 << 0), SystemPaused = (1 << 1), - FullscreenUIActive = (1 << 2), - NotificationsActive = (1 << 3), - LoadingScreenActive = (1 << 4), - AchievementOverlaysActive = (1 << 5), + OSDMessagesActive = (1 << 2), + FullscreenUIActive = (1 << 3), + NotificationsActive = (1 << 4), + LoadingScreenActive = (1 << 5), + AchievementOverlaysActive = (1 << 6), }; /// Starts Big Picture UI. diff --git a/src/util/imgui_manager.cpp b/src/util/imgui_manager.cpp index 324ba8aa6..07e3038e9 100644 --- a/src/util/imgui_manager.cpp +++ b/src/util/imgui_manager.cpp @@ -15,6 +15,7 @@ #include "core/gpu_thread.h" #include "core/host.h" #include "core/settings.h" +#include "core/system_private.h" #include "common/assert.h" #include "common/bitutils.h" @@ -24,6 +25,7 @@ #include "common/log.h" #include "common/string_util.h" #include "common/thirdparty/usb_key_code_data.h" +#include "common/threading.h" #include "common/timer.h" #include "IconsEmoji.h" @@ -101,6 +103,7 @@ static void AddOSDMessage(OSDMessageType type, std::string key, std::string icon std::string message); static void RemoveKeyedOSDMessage(std::string key); static void ClearOSDMessages(); +static void UpdateOSDMessageRunIdle(const std::unique_lock& lock); static void AcquirePendingOSDMessages(Timer::Value current_time); static void DrawOSDMessages(Timer::Value current_time); static void CreateSoftwareCursorTextures(); @@ -868,6 +871,41 @@ void ImGuiManager::AddOSDMessage(OSDMessageType type, std::string key, std::stri .text = std::move(message), .type = type, }); + + // trigger run idle on first message + if (s_state.osd_posted_messages.size() == 1) + UpdateOSDMessageRunIdle(lock); +} + +void ImGuiManager::UpdateOSDMessageRunIdle(const std::unique_lock& lock) +{ + static constexpr auto cb = []() { + GPUThread::SetRunIdleReason(GPUThread::RunIdleReason::OSDMessagesActive, + (!s_state.osd_active_messages.empty() || !s_state.osd_posted_messages.empty())); + }; + + if (GPUThread::IsOnThread()) + { + cb(); + return; + } + + if (System::GetCoreThreadHandle().IsCallingThread()) + { + GPUThread::RunOnThread([]() { + const std::unique_lock lock(s_state.osd_messages_lock); + cb(); + }); + } + else + { + Host::RunOnCoreThread([]() { + GPUThread::RunOnThread([]() { + const std::unique_lock lock(s_state.osd_messages_lock); + cb(); + }); + }); + } } void ImGuiManager::RemoveKeyedOSDMessage(std::string key) @@ -880,6 +918,8 @@ void ImGuiManager::RemoveKeyedOSDMessage(std::string key) .text = {}, .type = OSDMessageType::MaxCount, }); + if (s_state.osd_posted_messages.size() == 1) + UpdateOSDMessageRunIdle(lock); } void ImGuiManager::ClearOSDMessages() @@ -894,16 +934,8 @@ void ImGuiManager::ClearOSDMessages() void ImGuiManager::AcquirePendingOSDMessages(Timer::Value current_time) { - std::atomic_thread_fence(std::memory_order_acquire); - if (s_state.osd_posted_messages.empty()) - return; - - std::unique_lock lock(s_state.osd_messages_lock); - for (;;) + while (!s_state.osd_posted_messages.empty()) { - if (s_state.osd_posted_messages.empty()) - break; - PostedOSDMessage& new_msg = s_state.osd_posted_messages.front(); // MaxCount is used to indicate removal of a message. @@ -1151,9 +1183,22 @@ void ImGuiManager::DrawOSDMessages(Timer::Value current_time) void ImGuiManager::RenderOSDMessages() { + s_state.osd_messages_lock.lock(); + if (s_state.osd_posted_messages.empty() && s_state.osd_active_messages.empty()) + { + s_state.osd_messages_lock.unlock(); + return; + } + const Timer::Value current_time = Timer::GetCurrentValue(); AcquirePendingOSDMessages(current_time); + s_state.osd_messages_lock.unlock(); + DrawOSDMessages(current_time); + + // last one displayed? + if (s_state.osd_active_messages.empty()) + GPUThread::SetRunIdleReason(GPUThread::RunIdleReason::OSDMessagesActive, false); } void Host::AddOSDMessage(OSDMessageType type, std::string message)