Display: Allow unthrottle to skip only flipping.

Before, it either flipped continuously, or forced frameskip on.  This
makes it so you can still draw frames, but skip actual flips.

This is useful when games draw things only in a single frame and reuse
later.  It's also useful when measuring speed improvements if you already
get 100% speed on a device.
This commit is contained in:
Unknown W. Brackets 2020-05-24 14:57:18 -07:00 committed by Henrik Rydgård
parent 2c237fdea1
commit 4ef63843d2
6 changed files with 51 additions and 10 deletions

View file

@ -529,11 +529,11 @@ static int DefaultInternalResolution() {
#endif
}
static bool DefaultFrameskipUnthrottle() {
static int DefaultUnthrottleMode() {
#if PPSSPP_PLATFORM(ANDROID) || defined(USING_QT_UI) || PPSSPP_PLATFORM(UWP) || PPSSPP_PLATFORM(IOS)
return true;
return (int)UnthrottleMode::SKIP_DRAW;
#else
return false;
return (int)UnthrottleMode::CONTINUOUS;
#endif
}
@ -705,6 +705,28 @@ struct ConfigTranslator {
typedef ConfigTranslator<GPUBackend, GPUBackendToString, GPUBackendFromString> GPUBackendTranslator;
static int UnthrottleModeFromString(const std::string &s) {
if (!strcasecmp(s.c_str(), "CONTINUOUS"))
return (int)UnthrottleMode::CONTINUOUS;
if (!strcasecmp(s.c_str(), "SKIP_DRAW"))
return (int)UnthrottleMode::SKIP_DRAW;
if (!strcasecmp(s.c_str(), "SKIP_FLIP"))
return (int)UnthrottleMode::SKIP_FLIP;
return DefaultUnthrottleMode();
}
std::string UnthrottleModeToString(int v) {
switch (UnthrottleMode(v)) {
case UnthrottleMode::CONTINUOUS:
return "CONTINUOUS";
case UnthrottleMode::SKIP_DRAW:
return "SKIP_DRAW";
case UnthrottleMode::SKIP_FLIP:
return "SKIP_FLIP";
}
return "CONTINUOUS";
}
static ConfigSetting graphicsSettings[] = {
ConfigSetting("EnableCardboardVR", &g_Config.bEnableCardboardVR, false, true, true),
ConfigSetting("CardboardScreenSize", &g_Config.iCardboardScreenSize, 50, true, true),
@ -734,7 +756,7 @@ static ConfigSetting graphicsSettings[] = {
ReportedConfigSetting("AutoFrameSkip", &g_Config.bAutoFrameSkip, false, true, true),
ConfigSetting("FrameRate", &g_Config.iFpsLimit1, 0, true, true),
ConfigSetting("FrameRate2", &g_Config.iFpsLimit2, -1, true, true),
ConfigSetting("FrameSkipUnthrottle", &g_Config.bFrameSkipUnthrottle, &DefaultFrameskipUnthrottle, true, false),
ConfigSetting("UnthrottleMode", &g_Config.iUnthrottleMode, &DefaultUnthrottleMode, &UnthrottleModeToString, &UnthrottleModeFromString, true, true),
#if defined(USING_WIN_UI)
ConfigSetting("RestartRequired", &g_Config.bRestartRequired, false, false),
#endif

View file

@ -161,8 +161,8 @@ public:
bool bVSync;
int iFrameSkip;
int iFrameSkipType;
int iUnthrottleMode; // See UnthrottleMode in ConfigValues.h.
bool bAutoFrameSkip;
bool bFrameSkipUnthrottle;
bool bEnableCardboardVR; // Cardboard Master Switch
int iCardboardScreenSize; // Screen Size (in %)

View file

@ -110,3 +110,9 @@ enum class AutoLoadSaveState {
OLDEST = 1,
NEWEST = 2,
};
enum class UnthrottleMode {
CONTINUOUS = 0,
SKIP_DRAW = 1,
SKIP_FLIP = 2,
};

View file

@ -561,7 +561,7 @@ static void DoFrameTiming(bool &throttle, bool &skipFrame, float timestep) {
// we have nothing to do here.
bool doFrameSkip = g_Config.iFrameSkip != 0;
bool unthrottleNeedsSkip = g_Config.bFrameSkipUnthrottle;
bool unthrottleNeedsSkip = g_Config.iUnthrottleMode == (int)UnthrottleMode::SKIP_DRAW;
if (g_Config.bVSync && GetGPUBackend() == GPUBackend::VULKAN) {
// Vulkan doesn't support the interval setting, so we force frameskip.
unthrottleNeedsSkip = true;
@ -758,7 +758,7 @@ void __DisplayFlip(int cyclesLate) {
bool duplicateFrames = g_Config.bRenderDuplicateFrames && g_Config.iFrameSkip == 0;
bool unthrottleNeedsSkip = g_Config.bFrameSkipUnthrottle;
bool unthrottleNeedsSkip = g_Config.iUnthrottleMode != (int)UnthrottleMode::CONTINUOUS;
if (g_Config.bVSync && GetGPUBackend() == GPUBackend::VULKAN) {
// Vulkan doesn't support the interval setting, so we force frameskip.
unthrottleNeedsSkip = true;
@ -794,11 +794,24 @@ void __DisplayFlip(int cyclesLate) {
hasNotifiedSlow = true;
}
bool forceNoFlip = false;
// Alternative to frameskip unthrottle, where we draw everything.
// Useful if skipping a frame breaks graphics or for checking drawing speed.
if (g_Config.iUnthrottleMode == (int)UnthrottleMode::SKIP_FLIP && !FrameTimingThrottled()) {
static double lastFlip = 0;
double now = time_now_d();
if ((now - lastFlip) < 1.0f / System_GetPropertyFloat(SYSPROP_DISPLAY_REFRESH_RATE)) {
forceNoFlip = true;
} else {
lastFlip = now;
}
}
// Setting CORE_NEXTFRAME causes a swap.
const bool fbReallyDirty = gpu->FramebufferReallyDirty();
if (fbReallyDirty || noRecentFlip || postEffectRequiresFlip) {
// Check first though, might've just quit / been paused.
if (Core_NextFrame()) {
if (!forceNoFlip && Core_NextFrame()) {
gpu->CopyDisplayToOutput(fbReallyDirty);
if (fbReallyDirty) {
actualFlips++;

View file

@ -382,7 +382,7 @@ int main(int argc, const char* argv[])
g_Config.iButtonPreference = PSP_SYSTEMPARAM_BUTTON_CROSS;
g_Config.iLockParentalLevel = 9;
g_Config.iInternalResolution = 1;
g_Config.bFrameSkipUnthrottle = false;
g_Config.iUnthrottleMode = (int)UnthrottleMode::CONTINUOUS;
g_Config.bEnableLogging = fullLog;
g_Config.iNumWorkerThreads = 1;
g_Config.bSoftwareSkinning = true;

View file

@ -342,7 +342,7 @@ void retro_init(void)
#endif
g_Config.bEnableLogging = true;
g_Config.bFrameSkipUnthrottle = false;
g_Config.iUnthrottleMode = (int)UnthrottleMode::CONTINUOUS;
g_Config.bMemStickInserted = PSP_MEMORYSTICK_STATE_INSERTED;
g_Config.iGlobalVolume = VOLUME_MAX - 1;
g_Config.iAltSpeedVolume = -1;