System: Centralize frame presentation

This commit is contained in:
Stenzek 2023-08-30 20:34:48 +10:00
parent 358f87a74d
commit afaf5ddafd
6 changed files with 86 additions and 91 deletions

View file

@ -275,7 +275,7 @@ void Host::UpdateDisplayWindow()
// If we're paused, re-present the current frame at the new window size. // If we're paused, re-present the current frame at the new window size.
if (System::IsValid() && System::IsPaused()) if (System::IsValid() && System::IsPaused())
RenderDisplay(false); System::InvalidateDisplay();
} }
void Host::ResizeDisplayWindow(s32 width, s32 height, float scale) 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::IsValid())
{ {
if (System::IsPaused()) if (System::IsPaused())
RenderDisplay(false); System::InvalidateDisplay();
System::HostDisplayResized(); System::HostDisplayResized();
} }
@ -338,50 +338,3 @@ std::unique_ptr<AudioStream> Host::CreateAudioStream(AudioBackend backend, u32 s
} }
#endif #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);
}

View file

@ -104,10 +104,6 @@ void ReleaseGPUDevice();
/// Called before drawing the OSD and other display elements. /// Called before drawing the OSD and other display elements.
void BeginPresentFrame(); void BeginPresentFrame();
/// Provided by the host; renders the display.
void RenderDisplay(bool skip_present);
void InvalidateDisplay();
namespace Internal { namespace Internal {
/// Retrieves the base settings layer. Must call with lock held. /// Retrieves the base settings layer. Must call with lock held.
SettingsInterface* GetBaseSettingsLayer(); SettingsInterface* GetBaseSettingsLayer();

View file

@ -55,7 +55,6 @@ static void HotkeyModifyResolutionScale(s32 increment)
g_gpu->RestoreGraphicsAPIState(); g_gpu->RestoreGraphicsAPIState();
g_gpu->UpdateSettings(); g_gpu->UpdateSettings();
System::ClearMemorySaveStates(); System::ClearMemorySaveStates();
Host::InvalidateDisplay();
} }
} }

View file

@ -37,6 +37,7 @@
#include "util/audio_stream.h" #include "util/audio_stream.h"
#include "util/cd_image.h" #include "util/cd_image.h"
#include "util/gpu_device.h" #include "util/gpu_device.h"
#include "util/imgui_manager.h"
#include "util/ini_settings_interface.h" #include "util/ini_settings_interface.h"
#include "util/input_manager.h" #include "util/input_manager.h"
#include "util/iso_reader.h" #include "util/iso_reader.h"
@ -54,6 +55,7 @@
#include "fmt/chrono.h" #include "fmt/chrono.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "imgui.h"
#include "xxhash.h" #include "xxhash.h"
#include <cctype> #include <cctype>
@ -1109,6 +1111,7 @@ void System::PauseSystem(bool paused)
PlatformMisc::ResumeScreensaver(); PlatformMisc::ResumeScreensaver();
Host::OnSystemPaused(); Host::OnSystemPaused();
InvalidateDisplay();
} }
else else
{ {
@ -1173,7 +1176,7 @@ bool System::LoadState(const char* filename)
ResetPerformanceCounters(); ResetPerformanceCounters();
ResetThrottler(); ResetThrottler();
Host::RenderDisplay(false); InvalidateDisplay();
Log_VerbosePrintf("Loading state took %.2f msec", load_timer.GetTimeMilliseconds()); Log_VerbosePrintf("Loading state took %.2f msec", load_timer.GetTimeMilliseconds());
return true; return true;
} }
@ -1764,6 +1767,15 @@ void System::FrameDone()
if (s_cheat_list) if (s_cheat_list)
s_cheat_list->Apply(); s_cheat_list->Apply();
#ifdef WITH_CHEEVOS
if (Achievements::IsActive())
Achievements::FrameUpdate();
#endif
#ifdef WITH_DISCORD_PRESENCE
PollDiscordPresence();
#endif
if (s_frame_step_request) if (s_frame_step_request)
{ {
s_frame_step_request = false; s_frame_step_request = false;
@ -1811,27 +1823,10 @@ void System::FrameDone()
SaveRunaheadState(); 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(); const Common::Timer::Value current_time = Common::Timer::GetCurrentValue();
if (current_time < s_next_frame_time || s_display_all_frames || s_last_frame_skipped) if (current_time < s_next_frame_time || s_display_all_frames || s_last_frame_skipped)
{ {
s_last_frame_skipped = false; s_last_frame_skipped = !PresentDisplay(true);
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++;
}
} }
else if (current_time >= s_next_frame_time) else if (current_time >= s_next_frame_time)
{ {
@ -1928,6 +1923,8 @@ void System::SingleStepCPU()
g_gpu->FlushRender(); g_gpu->FlushRender();
SPU::GeneratePendingSamples(); SPU::GeneratePendingSamples();
InvalidateDisplay();
s_system_executing = false; s_system_executing = false;
} }
@ -1966,7 +1963,7 @@ void System::RecreateSystem()
ResetPerformanceCounters(); ResetPerformanceCounters();
ResetThrottler(); ResetThrottler();
Host::RenderDisplay(false); InvalidateDisplay();
if (was_paused) if (was_paused)
PauseSystem(true); 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 // 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 || 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."), Host::AddFormattedOSDMessage(5.0f, TRANSLATE("OSDMessage", "Switching to %s%s GPU renderer."),
Settings::GetRendererName(g_settings.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_settings.runahead_frames != old_settings.runahead_frames)
{ {
g_gpu->UpdateSettings(); g_gpu->UpdateSettings();
Host::InvalidateDisplay(); InvalidateDisplay();
} }
if (g_settings.gpu_widescreen_hack != old_settings.gpu_widescreen_hack || 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; s_next_frame_time += s_frame_period;
Host::RenderDisplay(false); InvalidateDisplay();
Host::PumpMessagesOnCPUThread(); Host::PumpMessagesOnCPUThread();
Throttle(); Throttle();
@ -4578,7 +4575,6 @@ void System::ToggleSoftwareRendering()
Host::AddKeyedFormattedOSDMessage("SoftwareRendering", 5.0f, TRANSLATE("OSDMessage", "Switching to %s renderer..."), Host::AddKeyedFormattedOSDMessage("SoftwareRendering", 5.0f, TRANSLATE("OSDMessage", "Switching to %s renderer..."),
Settings::GetRendererDisplayName(new_renderer)); Settings::GetRendererDisplayName(new_renderer));
RecreateGPU(new_renderer); RecreateGPU(new_renderer);
Host::InvalidateDisplay();
ResetPerformanceCounters(); ResetPerformanceCounters();
} }
@ -4644,6 +4640,63 @@ void System::HostDisplayResized()
g_gpu->UpdateResolutionScale(); 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) void System::SetTimerResolutionIncreased(bool enabled)
{ {
#if defined(_WIN32) #if defined(_WIN32)

View file

@ -448,6 +448,10 @@ void RequestDisplaySize(float scale = 0.0f);
/// Call when host display size changes, use with "match display" aspect ratio setting. /// Call when host display size changes, use with "match display" aspect ratio setting.
void HostDisplayResized(); void HostDisplayResized();
/// Renders the display.
bool PresentDisplay(bool allow_skip_present);
void InvalidateDisplay();
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Memory Save States (Rewind and Runahead) // Memory Save States (Rewind and Runahead)
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View file

@ -415,8 +415,6 @@ void EmuThread::applySettings(bool display_osd_messages /* = false */)
} }
System::ApplySettings(display_osd_messages); System::ApplySettings(display_osd_messages);
if (!FullscreenUI::IsInitialized() && System::IsPaused())
redrawDisplayWindow();
} }
void EmuThread::reloadGameSettings(bool display_osd_messages /* = false */) 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); System::ReloadGameSettings(display_osd_messages);
if (!FullscreenUI::IsInitialized() && System::IsPaused())
redrawDisplayWindow();
} }
void EmuThread::updateEmuFolders() void EmuThread::updateEmuFolders()
@ -509,11 +505,7 @@ void EmuThread::bootSystem(std::shared_ptr<SystemBootParameters> params)
setInitialState(params->override_fullscreen); setInitialState(params->override_fullscreen);
if (!System::BootSystem(std::move(*params))) System::BootSystem(std::move(*params));
return;
// force a frame to be drawn to repaint the window
Host::InvalidateDisplay();
} }
void EmuThread::bootOrLoadState(std::string path) void EmuThread::bootOrLoadState(std::string path)
@ -606,7 +598,7 @@ void EmuThread::redrawDisplayWindow()
if (!g_gpu_device || System::IsShutdown()) if (!g_gpu_device || System::IsShutdown())
return; return;
Host::RenderDisplay(false); System::InvalidateDisplay();
} }
void EmuThread::toggleFullscreen() void EmuThread::toggleFullscreen()
@ -726,7 +718,6 @@ void Host::OnSystemPaused()
{ {
emit g_emu_thread->systemPaused(); emit g_emu_thread->systemPaused();
g_emu_thread->startBackgroundControllerPollTimer(); g_emu_thread->startBackgroundControllerPollTimer();
Host::InvalidateDisplay();
} }
void Host::OnSystemResumed() void Host::OnSystemResumed()
@ -1137,7 +1128,6 @@ void EmuThread::singleStepCPU()
return; return;
System::SingleStepCPU(); System::SingleStepCPU();
Host::InvalidateDisplay();
} }
void EmuThread::dumpRAM(const QString& filename) void EmuThread::dumpRAM(const QString& filename)
@ -1342,7 +1332,7 @@ void EmuThread::run()
System::Internal::IdlePollUpdate(); System::Internal::IdlePollUpdate();
if (g_gpu_device) if (g_gpu_device)
{ {
Host::RenderDisplay(false); System::PresentDisplay(false);
if (!g_gpu_device->IsVsyncEnabled()) if (!g_gpu_device->IsVsyncEnabled())
g_gpu_device->ThrottlePresentation(); g_gpu_device->ThrottlePresentation();
} }