From 1aa3a657c01c42f38f51b9594af5de3f5e911223 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 19 Feb 2013 00:44:22 +0100 Subject: [PATCH] Very rough and basic implementation of frameskipping. --- Core/Config.cpp | 2 + Core/Config.h | 1 + Core/HLE/sceDisplay.cpp | 69 ++++++++++++++++++++++++--------- Windows/PPSSPP.vcxproj.filters | 4 +- Windows/WndMainWindow.cpp | 9 ++++- Windows/ppsspp.rc | Bin 56832 -> 56972 bytes Windows/resource.h | 3 +- android/jni/MenuScreens.cpp | 3 ++ 8 files changed, 69 insertions(+), 22 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index fc5019750c..fd22d7b7df 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -68,6 +68,7 @@ void CConfig::Load(const char *iniFileName) graphics->Get("LinearFiltering", &bLinearFiltering, false); graphics->Get("SSAA", &SSAntiAliasing, 0); graphics->Get("VBO", &bUseVBO, false); + graphics->Get("FrameSkip", &iFrameSkip, 0); #ifdef USING_GLES2 graphics->Get("AnisotropyLevel", &iAnisotropyLevel, 0); #else @@ -131,6 +132,7 @@ void CConfig::Save() graphics->Set("LinearFiltering", bLinearFiltering); graphics->Set("SSAA", SSAntiAliasing); graphics->Set("VBO", bUseVBO); + graphics->Set("FrameSkip", iFrameSkip); graphics->Set("AnisotropyLevel", iAnisotropyLevel); graphics->Set("DisableG3DLog", bDisableG3DLog); graphics->Set("VertexCache", bVertexCache); diff --git a/Core/Config.h b/Core/Config.h index 93554eeeb4..d39325cc4e 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -59,6 +59,7 @@ public: bool bLinearFiltering; bool bUseVBO; bool bStretchToDisplay; + int iFrameSkip; // 0 = off; 1 = auto; (future: 2 = skip every 2nd frame; 3 = skip every 3rd frame etc). int iWindowZoom; // for Windows bool SSAntiAliasing; //for Windows, too diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 9ec7d75303..46b297a928 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -89,7 +89,8 @@ static int isVblank; static int numSkippedFrames; static bool hasSetMode; // Don't include this in the state, time increases regardless of state. -static double lastFrameTime; +static double curFrameTime; +static double nextFrameTime; std::vector vblankWaitingThreads; @@ -129,7 +130,8 @@ void __DisplayInit() { vCount = 0; hCount = 0; hCountTotal = 0; - lastFrameTime = 0; + curFrameTime = 0.0; + nextFrameTime = 0.0; InitGfxState(); } @@ -191,7 +193,7 @@ float calculateFPS() static int lastFpsFrame = 0; static double lastFpsTime = 0.0; static double fps = 0.0; - + time_update(); double now = time_now_d(); @@ -274,25 +276,56 @@ void DoFrameTiming(bool &throttle, bool &skipFrame, bool &skipFlip) { #endif skipFlip = false; skipFrame = false; - if (PSP_CoreParameter().headLess) throttle = false; - if (throttle) { - // Best place to throttle the frame rate on non vsynced platforms is probably here. Let's try it. - time_update(); - if (lastFrameTime == 0.0) - lastFrameTime = time_now_d(); - - // First, check if we are already behind. - // Wait until it's time. - while (time_now_d() < lastFrameTime + 1.0 / 60.0) { - Common::SleepCurrentThread(1); - time_update(); + // Check if the frameskipping code should be enabled. If neither throttling or frameskipping is on, + // we have nothing to do here. + bool doFrameSkip = g_Config.iFrameSkip == 1; + if (!throttle && !doFrameSkip) + return; + + time_update(); + + curFrameTime = time_now_d(); + if (nextFrameTime == 0.0) + nextFrameTime = time_now_d() + 1.0 / 60.0; + + if (curFrameTime > nextFrameTime && doFrameSkip) { + // Argh, we are falling behind! Let's skip a frame and see if we catch up. + skipFrame = true; + skipFlip = true; + INFO_LOG(HLE,"FRAMESKIP %i", numSkippedFrames); + } + + if (curFrameTime < nextFrameTime && throttle) + { + // If time gap is huge just jump (somebody unthrottled) + if (nextFrameTime - curFrameTime > 1.0 / 30.0) { + nextFrameTime = curFrameTime + 1.0 / 60.0; + } else { + // Wait until we've catched up. + while (time_now_d() < nextFrameTime) { + Common::SleepCurrentThread(1); + time_update(); + } } - // Advance lastFrameTime by a constant amount each frame, - // but don't let it get too far behind. - lastFrameTime = std::max(lastFrameTime + 1.0 / 60.0, time_now_d() - 1.5 / 60.0); + curFrameTime = time_now_d(); + } + // Advance lastFrameTime by a constant amount each frame, + // but don't let it get too far behind as things can get very jumpy. + const double maxFallBehindFrames = 5.5; + + if (throttle || doFrameSkip) { + nextFrameTime = std::max(nextFrameTime + 1.0 / 60.0, time_now_d() - maxFallBehindFrames / 60.0); + } else { + nextFrameTime = nextFrameTime + 1.0 / 60.0; + } + + // Max 6 skipped frames in a row - 10 fps is really the bare minimum for playability. + if (numSkippedFrames >= 4) { + skipFrame = false; + skipFlip = false; } } diff --git a/Windows/PPSSPP.vcxproj.filters b/Windows/PPSSPP.vcxproj.filters index d2538d562b..6c0a8b3408 100644 --- a/Windows/PPSSPP.vcxproj.filters +++ b/Windows/PPSSPP.vcxproj.filters @@ -209,10 +209,12 @@ Android - Android + + Windows + diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 2f3b07e531..b97678aad5 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -73,8 +73,7 @@ namespace MainWindow void Init(HINSTANCE hInstance) { -#ifdef THEMES - WTL::CTheme::IsThemingSupported(); +#ifdef THEMES WTL::CTheme::IsThemingSupported(); #endif //Register classes WNDCLASSEX wcex; @@ -447,6 +446,11 @@ namespace MainWindow gpu->Resized(); // easy way to force a clear... break; + case ID_OPTIONS_FRAMESKIP: + g_Config.iFrameSkip = !g_Config.iFrameSkip; + UpdateMenus(); + break; + case ID_FILE_EXIT: DestroyWindow(hWnd); break; @@ -712,6 +716,7 @@ namespace MainWindow CHECKITEM(ID_OPTIONS_DISABLEG3DLOG, g_Config.bDisableG3DLog); CHECKITEM(ID_OPTIONS_VERTEXCACHE, g_Config.bVertexCache); CHECKITEM(ID_OPTIONS_SHOWFPS, g_Config.bShowFPSCounter); + CHECKITEM(ID_OPTIONS_FRAMESKIP, g_Config.iFrameSkip != 0); UINT enable = !Core_IsStepping() ? MF_GRAYED : MF_ENABLED; EnableMenuItem(menu,ID_EMULATION_RUN, g_State.bEmuThreadStarted ? enable : MF_GRAYED); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index e0a82cd7f4231adcd17ae6abe95c146ffc5fc198..8d0a8e1004b522d9c2d97aa8a0af3f5eafb8b817 100644 GIT binary patch delta 68 zcmZqJ!`!o%d4rADe YWpHH(X7Fb4WC)ntXqUXX!mDF40IV+)Y5)KL delta 18 acmeC#%iOSsd4rAD