From afaf5ddafda3f258360ad5d17f70fdfc3fa910a0 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 30 Aug 2023 20:34:48 +1000 Subject: [PATCH] System: Centralize frame presentation --- src/core/host.cpp | 51 +---------------- src/core/host.h | 4 -- src/core/hotkeys.cpp | 1 - src/core/system.cpp | 101 ++++++++++++++++++++++++++-------- src/core/system.h | 4 ++ src/duckstation-qt/qthost.cpp | 16 +----- 6 files changed, 86 insertions(+), 91 deletions(-) diff --git a/src/core/host.cpp b/src/core/host.cpp index 89de08735..3bf172f1b 100644 --- a/src/core/host.cpp +++ b/src/core/host.cpp @@ -275,7 +275,7 @@ void Host::UpdateDisplayWindow() // If we're paused, re-present the current frame at the new window size. if (System::IsValid() && System::IsPaused()) - RenderDisplay(false); + System::InvalidateDisplay(); } void Host::ResizeDisplayWindow(s32 width, s32 height, float scale) @@ -292,7 +292,7 @@ void Host::ResizeDisplayWindow(s32 width, s32 height, float scale) if (System::IsValid()) { if (System::IsPaused()) - RenderDisplay(false); + System::InvalidateDisplay(); System::HostDisplayResized(); } @@ -338,50 +338,3 @@ std::unique_ptr Host::CreateAudioStream(AudioBackend backend, u32 s } #endif - -void Host::RenderDisplay(bool skip_present) -{ - Host::BeginPresentFrame(); - - // acquire for IO.MousePos. - std::atomic_thread_fence(std::memory_order_acquire); - - if (!skip_present) - { - FullscreenUI::Render(); - ImGuiManager::RenderTextOverlays(); - ImGuiManager::RenderOSDMessages(); - ImGuiManager::RenderSoftwareCursors(); - } - - // Debug windows are always rendered, otherwise mouse input breaks on skip. - ImGuiManager::RenderOverlayWindows(); - ImGuiManager::RenderDebugWindows(); - - bool do_present; - if (g_gpu && !skip_present) - do_present = g_gpu->PresentDisplay(); - else - do_present = g_gpu_device->BeginPresent(skip_present); - - if (do_present) - { - g_gpu_device->RenderImGui(); - g_gpu_device->EndPresent(); - } - else - { - // Still need to kick ImGui or it gets cranky. - ImGui::Render(); - } - - ImGuiManager::NewFrame(); - - if (g_gpu) - g_gpu->RestoreGraphicsAPIState(); -} - -void Host::InvalidateDisplay() -{ - RenderDisplay(false); -} diff --git a/src/core/host.h b/src/core/host.h index e432d6072..c8424efa5 100644 --- a/src/core/host.h +++ b/src/core/host.h @@ -104,10 +104,6 @@ void ReleaseGPUDevice(); /// Called before drawing the OSD and other display elements. void BeginPresentFrame(); -/// Provided by the host; renders the display. -void RenderDisplay(bool skip_present); -void InvalidateDisplay(); - namespace Internal { /// Retrieves the base settings layer. Must call with lock held. SettingsInterface* GetBaseSettingsLayer(); diff --git a/src/core/hotkeys.cpp b/src/core/hotkeys.cpp index 801d34a44..0af471965 100644 --- a/src/core/hotkeys.cpp +++ b/src/core/hotkeys.cpp @@ -55,7 +55,6 @@ static void HotkeyModifyResolutionScale(s32 increment) g_gpu->RestoreGraphicsAPIState(); g_gpu->UpdateSettings(); System::ClearMemorySaveStates(); - Host::InvalidateDisplay(); } } diff --git a/src/core/system.cpp b/src/core/system.cpp index 9117f5cad..6c64f0566 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -37,6 +37,7 @@ #include "util/audio_stream.h" #include "util/cd_image.h" #include "util/gpu_device.h" +#include "util/imgui_manager.h" #include "util/ini_settings_interface.h" #include "util/input_manager.h" #include "util/iso_reader.h" @@ -54,6 +55,7 @@ #include "fmt/chrono.h" #include "fmt/format.h" +#include "imgui.h" #include "xxhash.h" #include @@ -1109,6 +1111,7 @@ void System::PauseSystem(bool paused) PlatformMisc::ResumeScreensaver(); Host::OnSystemPaused(); + InvalidateDisplay(); } else { @@ -1173,7 +1176,7 @@ bool System::LoadState(const char* filename) ResetPerformanceCounters(); ResetThrottler(); - Host::RenderDisplay(false); + InvalidateDisplay(); Log_VerbosePrintf("Loading state took %.2f msec", load_timer.GetTimeMilliseconds()); return true; } @@ -1764,6 +1767,15 @@ void System::FrameDone() if (s_cheat_list) s_cheat_list->Apply(); +#ifdef WITH_CHEEVOS + if (Achievements::IsActive()) + Achievements::FrameUpdate(); +#endif + +#ifdef WITH_DISCORD_PRESENCE + PollDiscordPresence(); +#endif + if (s_frame_step_request) { s_frame_step_request = false; @@ -1811,27 +1823,10 @@ void System::FrameDone() SaveRunaheadState(); } -#ifdef WITH_CHEEVOS - if (Achievements::IsActive()) - Achievements::FrameUpdate(); -#endif - -#ifdef WITH_DISCORD_PRESENCE - PollDiscordPresence(); -#endif - const Common::Timer::Value current_time = Common::Timer::GetCurrentValue(); if (current_time < s_next_frame_time || s_display_all_frames || s_last_frame_skipped) { - s_last_frame_skipped = false; - - const bool skip_present = g_gpu_device->ShouldSkipDisplayingFrame(); - Host::RenderDisplay(skip_present); - if (!skip_present && g_gpu_device->IsGPUTimingEnabled()) - { - s_accumulated_gpu_time += g_gpu_device->GetAndResetAccumulatedGPUTime(); - s_presents_since_last_update++; - } + s_last_frame_skipped = !PresentDisplay(true); } else if (current_time >= s_next_frame_time) { @@ -1928,6 +1923,8 @@ void System::SingleStepCPU() g_gpu->FlushRender(); SPU::GeneratePendingSamples(); + InvalidateDisplay(); + s_system_executing = false; } @@ -1966,7 +1963,7 @@ void System::RecreateSystem() ResetPerformanceCounters(); ResetThrottler(); - Host::RenderDisplay(false); + InvalidateDisplay(); if (was_paused) PauseSystem(true); @@ -3488,7 +3485,7 @@ void System::CheckForSettingsChanges(const Settings& old_settings) { // if debug device/threaded presentation change, we need to recreate the whole display const bool recreate_device = (g_settings.gpu_use_debug_device != old_settings.gpu_use_debug_device || - g_settings.gpu_threaded_presentation != old_settings.gpu_threaded_presentation); + g_settings.gpu_threaded_presentation != old_settings.gpu_threaded_presentation); Host::AddFormattedOSDMessage(5.0f, TRANSLATE("OSDMessage", "Switching to %s%s GPU renderer."), Settings::GetRendererName(g_settings.gpu_renderer), @@ -3594,7 +3591,7 @@ void System::CheckForSettingsChanges(const Settings& old_settings) g_settings.runahead_frames != old_settings.runahead_frames) { g_gpu->UpdateSettings(); - Host::InvalidateDisplay(); + InvalidateDisplay(); } if (g_settings.gpu_widescreen_hack != old_settings.gpu_widescreen_hack || @@ -3909,7 +3906,7 @@ void System::DoRewind() s_next_frame_time += s_frame_period; - Host::RenderDisplay(false); + InvalidateDisplay(); Host::PumpMessagesOnCPUThread(); Throttle(); @@ -4578,7 +4575,6 @@ void System::ToggleSoftwareRendering() Host::AddKeyedFormattedOSDMessage("SoftwareRendering", 5.0f, TRANSLATE("OSDMessage", "Switching to %s renderer..."), Settings::GetRendererDisplayName(new_renderer)); RecreateGPU(new_renderer); - Host::InvalidateDisplay(); ResetPerformanceCounters(); } @@ -4644,6 +4640,63 @@ void System::HostDisplayResized() g_gpu->UpdateResolutionScale(); } +bool System::PresentDisplay(bool allow_skip_present) +{ + const bool skip_present = allow_skip_present && g_gpu_device->ShouldSkipDisplayingFrame(); + + Host::BeginPresentFrame(); + + // acquire for IO.MousePos. + std::atomic_thread_fence(std::memory_order_acquire); + + if (!skip_present) + { + FullscreenUI::Render(); + ImGuiManager::RenderTextOverlays(); + ImGuiManager::RenderOSDMessages(); + ImGuiManager::RenderSoftwareCursors(); + } + + // Debug windows are always rendered, otherwise mouse input breaks on skip. + ImGuiManager::RenderOverlayWindows(); + ImGuiManager::RenderDebugWindows(); + + bool do_present; + if (g_gpu && !skip_present) + do_present = g_gpu->PresentDisplay(); + else + do_present = g_gpu_device->BeginPresent(skip_present); + + if (do_present) + { + g_gpu_device->RenderImGui(); + g_gpu_device->EndPresent(); + + if (g_gpu_device->IsGPUTimingEnabled()) + { + s_accumulated_gpu_time += g_gpu_device->GetAndResetAccumulatedGPUTime(); + s_presents_since_last_update++; + } + } + else + { + // Still need to kick ImGui or it gets cranky. + ImGui::Render(); + } + + ImGuiManager::NewFrame(); + + if (g_gpu) + g_gpu->RestoreGraphicsAPIState(); + + return do_present; +} + +void System::InvalidateDisplay() +{ + PresentDisplay(false); +} + void System::SetTimerResolutionIncreased(bool enabled) { #if defined(_WIN32) diff --git a/src/core/system.h b/src/core/system.h index 5686797df..0de401ef7 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -448,6 +448,10 @@ void RequestDisplaySize(float scale = 0.0f); /// Call when host display size changes, use with "match display" aspect ratio setting. void HostDisplayResized(); +/// Renders the display. +bool PresentDisplay(bool allow_skip_present); +void InvalidateDisplay(); + ////////////////////////////////////////////////////////////////////////// // Memory Save States (Rewind and Runahead) ////////////////////////////////////////////////////////////////////////// diff --git a/src/duckstation-qt/qthost.cpp b/src/duckstation-qt/qthost.cpp index 18605f143..530556785 100644 --- a/src/duckstation-qt/qthost.cpp +++ b/src/duckstation-qt/qthost.cpp @@ -415,8 +415,6 @@ void EmuThread::applySettings(bool display_osd_messages /* = false */) } System::ApplySettings(display_osd_messages); - if (!FullscreenUI::IsInitialized() && System::IsPaused()) - redrawDisplayWindow(); } void EmuThread::reloadGameSettings(bool display_osd_messages /* = false */) @@ -428,8 +426,6 @@ void EmuThread::reloadGameSettings(bool display_osd_messages /* = false */) } System::ReloadGameSettings(display_osd_messages); - if (!FullscreenUI::IsInitialized() && System::IsPaused()) - redrawDisplayWindow(); } void EmuThread::updateEmuFolders() @@ -509,11 +505,7 @@ void EmuThread::bootSystem(std::shared_ptr params) setInitialState(params->override_fullscreen); - if (!System::BootSystem(std::move(*params))) - return; - - // force a frame to be drawn to repaint the window - Host::InvalidateDisplay(); + System::BootSystem(std::move(*params)); } void EmuThread::bootOrLoadState(std::string path) @@ -606,7 +598,7 @@ void EmuThread::redrawDisplayWindow() if (!g_gpu_device || System::IsShutdown()) return; - Host::RenderDisplay(false); + System::InvalidateDisplay(); } void EmuThread::toggleFullscreen() @@ -726,7 +718,6 @@ void Host::OnSystemPaused() { emit g_emu_thread->systemPaused(); g_emu_thread->startBackgroundControllerPollTimer(); - Host::InvalidateDisplay(); } void Host::OnSystemResumed() @@ -1137,7 +1128,6 @@ void EmuThread::singleStepCPU() return; System::SingleStepCPU(); - Host::InvalidateDisplay(); } void EmuThread::dumpRAM(const QString& filename) @@ -1342,7 +1332,7 @@ void EmuThread::run() System::Internal::IdlePollUpdate(); if (g_gpu_device) { - Host::RenderDisplay(false); + System::PresentDisplay(false); if (!g_gpu_device->IsVsyncEnabled()) g_gpu_device->ThrottlePresentation(); }