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 (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<AudioStream> 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);
}

View file

@ -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();

View file

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

View file

@ -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 <cctype>
@ -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)

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.
void HostDisplayResized();
/// Renders the display.
bool PresentDisplay(bool allow_skip_present);
void InvalidateDisplay();
//////////////////////////////////////////////////////////////////////////
// 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);
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<SystemBootParameters> 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();
}