Rework the present mode settings, refactor.

This commit is contained in:
Henrik Rydgård committed 2025-10-20 21:28:38 +02:00
1 parent 4c0b011b0e
commit 042cf87248
65 files changed
+284 -175

No files matched your search

+53 -57
View File
@@ -22,6 +22,7 @@
#include "ppsspp_config.h"
#include "Common/Profiler/Profiler.h"
#include "Common/Log.h"
#include "Common/System/Display.h"
#include "Common/TimeUtil.h"
#include "Core/RetroAchievements.h"
@@ -56,22 +57,6 @@ void WaitUntil(double now, double timestamp, const char *reason) {
#endif
}
inline Draw::PresentMode GetBestImmediateMode(Draw::PresentMode supportedModes) {
if (supportedModes & Draw::PresentMode::MAILBOX) {
return Draw::PresentMode::MAILBOX;
} else {
return Draw::PresentMode::IMMEDIATE;
}
}
void FrameTiming::Reset(Draw::DrawContext *draw) {
if (g_Config.bVSync || !(draw->GetDeviceCaps().presentModesSupported & (Draw::PresentMode::MAILBOX | Draw::PresentMode::IMMEDIATE))) {
presentMode = Draw::PresentMode::FIFO;
} else {
presentMode = GetBestImmediateMode(draw->GetDeviceCaps().presentModesSupported);
}
}
void FrameTiming::DeferWaitUntil(double until, double *curTimePtr) {
_dbg_assert_(until > 0.0);
waitUntil_ = until;
@@ -89,54 +74,65 @@ void FrameTiming::PostSubmit() {
}
}
Draw::PresentMode ComputePresentMode(Draw::DrawContext *draw) {
_assert_(draw);
void FrameTiming::ComputePresentMode(Draw::DrawContext *draw, bool fastForward) {
_dbg_assert_(draw);
if (!draw) {
fastForwardSkipFlip_ = true;
presentMode_ = Draw::PresentMode::FIFO;
return;
}
Draw::PresentMode mode = Draw::PresentMode::FIFO;
_dbg_assert_(draw->GetDeviceCaps().presentModesSupported != (Draw::PresentMode)0);
if (draw->GetDeviceCaps().presentModesSupported & (Draw::PresentMode::IMMEDIATE | Draw::PresentMode::MAILBOX)) {
// Switch to immediate if desired and possible.
bool wantInstant = false;
if (!g_Config.bVSync) {
wantInstant = true;
if (draw->GetDeviceCaps().presentModesSupported == Draw::PresentMode::FIFO) {
// Only FIFO mode is supported (like on iOS and some GLES backends).
fastForwardSkipFlip_ = true;
presentMode_ = Draw::PresentMode::FIFO;
return;
}
// More than one present mode is supported. Use careful logic.
// The user has requested vsync off.
if (!g_Config.bVSync) {
if (draw->GetDeviceCaps().presentModesSupported & Draw::PresentMode::IMMEDIATE) {
// Use immediate mode, whether fast-forwarding or not.
presentMode_ = Draw::PresentMode::IMMEDIATE;
fastForwardSkipFlip_ = false;
return;
}
// Inconsistent state - vsync is off but immediate mode is not supported.
// We will simply force on VSync.
g_Config.bVSync = true;
}
if (PSP_CoreParameter().fastForward && NetworkAllowSpeedControl()) {
wantInstant = true;
// At this point, vsync is always on. What decides now is whether MAILBOX or IMMEDIATE is available,
// and also if we need an unsynced mode.
// OK, vsync is requested (or immediate is not available). If mailbox is supported, it works the same as IMMEDIATE above.
if (g_Config.bLowLatencyPresent) {
// Use mailbox if available. It works fine for both fast-forward and normal.
if (draw->GetDeviceCaps().presentModesSupported & Draw::PresentMode::MAILBOX) {
presentMode_ = Draw::PresentMode::MAILBOX;
fastForwardSkipFlip_ = false;
return;
}
// We could force off lowLatencyPresent here, but it's no good when changing between backends.
// So let's leave it on in the background, maybe the user just went from Vulkan to OpenGL.
}
FPSLimit limit = PSP_CoreParameter().fpsLimit;
if (!NetworkAllowSpeedControl()) {
limit = FPSLimit::NORMAL;
}
if (limit != FPSLimit::NORMAL) {
int limit;
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1)
limit = g_Config.iFpsLimit1;
else if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2)
limit = g_Config.iFpsLimit2;
else
limit = PSP_CoreParameter().analogFpsLimit;
// For an alternative speed that is a clean factor of 60, the user probably still wants vsync.
// TODO: Should take the user's display refresh rate into account...
if (limit == 0 || (limit >= 0 && limit != 15 && limit != 30 && limit != 60)) {
wantInstant = true;
}
}
if (wantInstant && g_Config.bVSync && !draw->GetDeviceCaps().presentInstantModeChange) {
// If in vsync mode (which will be FIFO), and the backend can't switch immediately,
// stick to FIFO.
wantInstant = false;
}
// The outer if checks that instant modes are available.
if (wantInstant) {
mode = GetBestImmediateMode(draw->GetDeviceCaps().presentModesSupported);
// At this point, low-latency mode is not available, and vsync is on. We see if we can use INSTANT
// mode for fast-forwarding, or if we need to resort to frameskipping.
if (draw->GetDeviceCaps().presentInstantModeChange) {
if (fastForward) {
presentMode_ = Draw::PresentMode::IMMEDIATE;
fastForwardSkipFlip_ = false;
return;
}
}
return mode;
// Finally, fallback to FIFO mode, with skip-flip in fast-forward.
presentMode_ = Draw::PresentMode::FIFO;
fastForwardSkipFlip_ = true;
}