From 864528303a601b95b207b96e93d1c4ee22f940d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 15 Aug 2023 21:32:19 +0200 Subject: [PATCH] Use the new frame timing to implement the menu throttle directly --- Common/GPU/Vulkan/VulkanRenderManager.cpp | 8 +++++--- Common/System/System.h | 2 +- Core/Core.cpp | 16 ---------------- Core/FrameTiming.cpp | 14 ++++++++++++-- Core/FrameTiming.h | 10 ++++++++-- Core/HLE/sceDisplay.cpp | 2 +- SDL/SDLMain.cpp | 8 -------- UI/NativeApp.cpp | 3 ++- 8 files changed, 29 insertions(+), 34 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 44e2ed1baa..284a017ea6 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -306,9 +306,11 @@ bool VulkanRenderManager::CreateBackbuffers() { INFO_LOG(G3D, "Starting Vulkan compiler thread"); compileThread_ = std::thread(&VulkanRenderManager::CompileThreadFunc, this); - if (USE_PRESENT_WAIT && vulkan_->Extensions().KHR_present_wait && vulkan_->GetPresentMode() == VK_PRESENT_MODE_FIFO_KHR) { - INFO_LOG(G3D, "Starting Vulkan present wait thread"); - presentWaitThread_ = std::thread(&VulkanRenderManager::PresentWaitThreadFunc, this); + if (USE_PRESENT_WAIT) { + if (vulkan_->Extensions().KHR_present_wait && vulkan_->GetPresentMode() == VK_PRESENT_MODE_FIFO_KHR) { + INFO_LOG(G3D, "Starting Vulkan present wait thread"); + presentWaitThread_ = std::thread(&VulkanRenderManager::PresentWaitThreadFunc, this); + } } } return true; diff --git a/Common/System/System.h b/Common/System/System.h index 9652c0d32a..13047d6457 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -142,7 +142,7 @@ enum SystemProperty { SYSPROP_SYSTEMVERSION, SYSPROP_DISPLAY_XRES, SYSPROP_DISPLAY_YRES, - SYSPROP_DISPLAY_REFRESH_RATE, + SYSPROP_DISPLAY_REFRESH_RATE, // Note that this might not be very efficient - might want to cache. SYSPROP_DISPLAY_LOGICAL_DPI, SYSPROP_DISPLAY_DPI, SYSPROP_DISPLAY_COUNT, diff --git a/Core/Core.cpp b/Core/Core.cpp index 6dc3fd759a..714e7f257a 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -214,23 +214,7 @@ void Core_RunLoop(GraphicsContext *ctx) { return; } - bool menuThrottle = (GetUIState() != UISTATE_INGAME || !PSP_IsInited()) && GetUIState() != UISTATE_EXIT; - - double startTime; - if (menuThrottle) { - startTime = time_now_d(); - } - NativeFrame(ctx); - - if (menuThrottle) { - // Simple throttling to not burn the GPU in the menu. - // TODO: This should move into NativeFrame. Also, it's only necessary in MAILBOX or IMMEDIATE presentation modes. - double diffTime = time_now_d() - startTime; - int sleepTime = (int)(1000.0 / refreshRate) - (int)(diffTime * 1000.0); - if (sleepTime > 0) - sleep_ms(sleepTime); - } } void Core_DoSingleStep() { diff --git a/Core/FrameTiming.cpp b/Core/FrameTiming.cpp index c61430eddb..748c4538ee 100644 --- a/Core/FrameTiming.cpp +++ b/Core/FrameTiming.cpp @@ -48,6 +48,7 @@ void FrameTiming::Reset(Draw::DrawContext *draw) { presentMode = GetBestImmediateMode(draw->GetDeviceCaps().presentModesSupported); presentInterval = 0; } + setTimestepCalled_ = false; } Draw::PresentMode ComputePresentMode(Draw::DrawContext *draw, int *interval) { @@ -99,18 +100,27 @@ void FrameTiming::BeforeCPUSlice() { cpuSliceStartTime = time_now_d(); } -void FrameTiming::EndOfCPUSlice(float scaledTimeStep) { +void FrameTiming::SetTimeStep(float scaledTimeStep) { _dbg_assert_(usePresentTiming); double now = time_now_d(); cpuTime = now - cpuSliceStartTime; - this->timeStep = scaledTimeStep; + this->timeStep = scaledTimeStep + nudge_; // Sync up lastPresentTime with the current time if it's way off. if (lastPresentTime < now - 0.5f) { lastPresentTime = now; } + setTimestepCalled_ = true; +} + +void FrameTiming::AfterCPUSlice() { + if (!setTimestepCalled_) { + // We're in the menu or something. + usePresentTiming = true; + SetTimeStep(1.0f / 60.0f); + } } void FrameTiming::BeforePresent() { diff --git a/Core/FrameTiming.h b/Core/FrameTiming.h index c068e01f1e..5aa4fde5fb 100644 --- a/Core/FrameTiming.h +++ b/Core/FrameTiming.h @@ -8,7 +8,8 @@ namespace Draw { class DrawContext; } -struct FrameTiming { +class FrameTiming { +public: // Some backends won't allow changing this willy nilly. Draw::PresentMode presentMode; int presentInterval; @@ -27,9 +28,14 @@ struct FrameTiming { void Reset(Draw::DrawContext *draw); void BeforeCPUSlice(); - void EndOfCPUSlice(float scaledTimeStep); + void SetTimeStep(float scaledTimeStep); + void AfterCPUSlice(); void BeforePresent(); void AfterPresent(); + +private: + bool setTimestepCalled_ = false; + double nudge_ = 0.0; }; extern FrameTiming g_frameTiming; diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index f49353c936..c1fb54ff32 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -648,7 +648,7 @@ void __DisplayFlip(int cyclesLate) { if (Core_NextFrame()) { gpu->CopyDisplayToOutput(true); DisplayFireActualFlip(); - g_frameTiming.EndOfCPUSlice(scaledTimestep); + g_frameTiming.SetTimeStep(scaledTimestep); gpuStats.numFlips++; goto finishUp; } else { diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 86bd191316..ec0e32bb42 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -1489,14 +1489,6 @@ int main(int argc, char *argv[]) { graphicsContext->ThreadStart(); } - // Simple throttling to not burn the GPU in the menu. - if (GetUIState() != UISTATE_INGAME || !PSP_IsInited() || renderThreadPaused) { - double diffTime = time_now_d() - startTime; - int sleepTime = (int)(1000.0 / 60.0) - (int)(diffTime * 1000.0); - if (sleepTime > 0) - sleep_ms(sleepTime); - } - g_frameCount++; } diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 74062aac47..0abf6f1d5e 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1164,12 +1164,13 @@ void NativeFrame(GraphicsContext *graphicsContext) { g_screenManager->getUIContext()->SetTintSaturation(g_Config.fUITint, g_Config.fUISaturation); - // All actual rendering happen in here. g_frameTiming.BeforeCPUSlice(); + // All actual rendering happen in here. g_screenManager->render(); if (g_screenManager->getUIContext()->Text()) { g_screenManager->getUIContext()->Text()->OncePerFrame(); } + g_frameTiming.AfterCPUSlice(); ui_draw2d.PopDrawMatrix(); ui_draw2d_front.PopDrawMatrix();