From 9f758b0032a94182eecbef24c4ed53c65590830b Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 26 Mar 2019 10:40:43 +0100 Subject: [PATCH] - implement vid_maxfps --- .../vulkan/system/vk_framebuffer.cpp | 40 +++++++++++++++++++ src/rendering/vulkan/system/vk_framebuffer.h | 3 ++ 2 files changed, 43 insertions(+) diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index ca667e5d34..3ab6b51e8c 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -59,10 +59,14 @@ #include "vulkan/system/vk_swapchain.h" #include "doomerrors.h" +#include +#include + void Draw2D(F2DDrawer *drawer, FRenderState &state); void DoWriteSavePic(FileWriter *file, ESSType ssformat, uint8_t *scr, int width, int height, sector_t *viewsector, bool upsidedown); EXTERN_CVAR(Bool, vid_vsync) +EXTERN_CVAR(Int, vid_maxfps) EXTERN_CVAR(Bool, r_drawvoxels) EXTERN_CVAR(Int, gl_tonemap) EXTERN_CVAR(Int, screenblocks) @@ -189,6 +193,8 @@ void VulkanFrameBuffer::Update() Flush3D.Unclock(); + FPSLimit(); + Finish.Reset(); Finish.Clock(); @@ -217,6 +223,40 @@ void VulkanFrameBuffer::Update() Super::Update(); } +void VulkanFrameBuffer::FPSLimit() +{ + using namespace std::chrono; + using namespace std::this_thread; + + if (vid_maxfps <= 0 || vid_vsync) + return; + + uint64_t targetWakeTime = fpsLimitTime + 1'000'000 / vid_maxfps; + + while (true) + { + fpsLimitTime = duration_cast(steady_clock::now().time_since_epoch()).count(); + int64_t timeToWait = targetWakeTime - fpsLimitTime; + + if (timeToWait > 1'000'000 || timeToWait <= 0) + { + break; + } + + if (timeToWait <= 2'000'000) + { + // We are too close to the deadline. OS sleep is not precise enough to wake us before it elapses. + // Yield execution and check time again. + sleep_for(nanoseconds(0)); + } + else + { + // Sleep, but try to wake before deadline. + sleep_for(milliseconds(timeToWait - 1'000'000)); + } + } +} + void VulkanFrameBuffer::DeleteFrameObjects() { FrameDeleteList.Images.clear(); diff --git a/src/rendering/vulkan/system/vk_framebuffer.h b/src/rendering/vulkan/system/vk_framebuffer.h index 6926063052..0e0d26fcf8 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.h +++ b/src/rendering/vulkan/system/vk_framebuffer.h @@ -107,6 +107,7 @@ private: void CopyScreenToBuffer(int w, int h, void *data); void UpdateShadowMap(); void DeleteFrameObjects(); + void FPSLimit(); std::unique_ptr mShaderManager; std::unique_ptr mSamplerManager; @@ -131,6 +132,8 @@ private: int lastSwapWidth = 0; int lastSwapHeight = 0; + + uint64_t fpsLimitTime = 0; }; inline VulkanFrameBuffer *GetVulkanFrameBuffer() { return static_cast(screen); }