From aa7fbd03292a6441ec3d154ea6d4ea1a378efc8b Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Mon, 15 Mar 2021 00:36:27 -0400 Subject: [PATCH 1/4] Add foreground FPS limit As reported in issue #13, PoB tends to use significant CPU and GPU resources while in the foreground. This change exposes a foreground frame rate limit that can be configured via a CVar (vid_fgfps) that defaults to a 30 FPS limit and allows a 5-120 FPS range. A setting of 30 feels responsive and reduces the resource usage by a modest amount. CPU usage hovers around 4% on my 16-core system with this change, as opposed to 6% usage with the current build. Similarly, GPU usage hovers around 18-20% with the 30 FPS limit and around 25-28% with the current build. There may be a better place to situate the sleep that is introduced for this, but this seemed like a reasonable place for someone who is not very familiar with this code. I also removed the reference to tiff.lib in the Debug configuration since that is unused and not a vcpkg dependency. --- SimpleGraphic.vcxproj | 2 +- config.h | 1 + engine/core/core_video.cpp | 3 +++ engine/system/sys_video.h | 2 ++ engine/system/win/sys_main.cpp | 11 +++++++++++ engine/system/win/sys_video.cpp | 2 ++ 6 files changed, 20 insertions(+), 1 deletion(-) diff --git a/SimpleGraphic.vcxproj b/SimpleGraphic.vcxproj index 16f239c..8cdfba3 100644 --- a/SimpleGraphic.vcxproj +++ b/SimpleGraphic.vcxproj @@ -120,7 +120,7 @@ <GenerateDebugInformation>true</GenerateDebugInformation> <EnableUAC>false</EnableUAC> <AdditionalLibraryDirectories>$(SolutionDir)vcpkg\installed\x86-windows-static\lib;%(AdditionalLibraryDirectories)LuaJIT/src;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> - <AdditionalDependencies>gif.lib;jpeg.lib;lzma.lib;libpng16.lib;lua51.lib;tiff.lib;zlib.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalDependencies>gif.lib;jpeg.lib;lzma.lib;libpng16.lib;lua51.lib;zlib.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> diff --git a/config.h b/config.h index f484d5a..6d466dc 100644 --- a/config.h +++ b/config.h @@ -18,5 +18,6 @@ #define CFG_VID_DEFDISPLAY "-1" #define CFG_VID_DEFFULLSCREEN "0" #define CFG_VID_DEFRESIZABLE "0" +#define CFG_VID_DEFFGFPS "30" #define CFG_VID_MINWIDTH 1280 #define CFG_VID_MINHEIGHT 720 \ No newline at end of file diff --git a/engine/core/core_video.cpp b/engine/core/core_video.cpp index f6bfcf1..e347d6d 100644 --- a/engine/core/core_video.cpp +++ b/engine/core/core_video.cpp @@ -48,6 +48,7 @@ class core_video_c: public core_IVideo, public conCmdHandler_c { conVar_c* vid_fullscreen; conVar_c* vid_resizable; conVar_c* vid_last; + conVar_c* vid_fgfps; void C_Vid_Apply(IConsole* conHnd, args_c &args); void C_Vid_ModeList(IConsole* conHnd, args_c &args); @@ -71,6 +72,7 @@ core_video_c::core_video_c(sys_IMain* sysHnd) vid_fullscreen = sys->con->Cvar_Add("vid_fullscreen", CV_ARCHIVE, CFG_VID_DEFFULLSCREEN); vid_resizable = sys->con->Cvar_Add("vid_resizable", CV_ARCHIVE|CV_CLAMP, CFG_VID_DEFRESIZABLE, 0, 3); vid_last = sys->con->Cvar_Add("vid_last", CV_ARCHIVE, ""); + vid_fgfps = sys->con->Cvar_Add("vid_fgfps", CV_ARCHIVE|CV_CLAMP, CFG_VID_DEFFGFPS, 5, 120); Cmd_Add("vid_apply", 0, "", this, &core_video_c::C_Vid_Apply); Cmd_Add("vid_modeList", 0, "", this, &core_video_c::C_Vid_ModeList); @@ -111,6 +113,7 @@ void core_video_c::Apply(bool shown) set.depth = 0; set.minSize[0] = CFG_VID_MINWIDTH; set.minSize[1] = CFG_VID_MINHEIGHT; + set.fgfps = vid_fgfps->intVal; sys->video->Apply(&set); } diff --git a/engine/system/sys_video.h b/engine/system/sys_video.h index 461a95e..1e8a39b 100644 --- a/engine/system/sys_video.h +++ b/engine/system/sys_video.h @@ -22,6 +22,7 @@ struct sys_vidSave_s { int size[2] = {}; int pos[2] = {}; bool maximised = false; + int fgfps = 0; }; // Video settings structure @@ -32,6 +33,7 @@ struct sys_vidSet_s { int mode[2] = {}; // Resolution or window size int depth = 0; // Bit depth int minSize[2] = {}; // Minimum size for resizable windows + int fgfps = 0; // Foreground FPS limit sys_vidSave_s save; // Saved state }; diff --git a/engine/system/win/sys_main.cpp b/engine/system/win/sys_main.cpp index 84ab748..42504ec 100644 --- a/engine/system/win/sys_main.cpp +++ b/engine/system/win/sys_main.cpp @@ -11,6 +11,9 @@ #include <eh.h> +#include <chrono> +#include <thread> + // ====== // Locals // ====== @@ -777,7 +780,15 @@ bool sys_main_c::Run(int argc, char** argv) while (exitFlag == false) { RunMessages(); + const auto frameStart = std::chrono::high_resolution_clock::now(); core->Frame(); + const auto frameEnd = std::chrono::high_resolution_clock::now(); + using FpMilliseconds = std::chrono::duration<float, std::chrono::milliseconds::period>; + const auto frameDuration = std::chrono::duration_cast<FpMilliseconds>(frameEnd - frameStart); + const auto minimumFrameDuration = FpMilliseconds(1000.0f / video->vid.fgfps); + if (frameDuration < minimumFrameDuration) { + std::this_thread::sleep_for(minimumFrameDuration - frameDuration); + } if (threadError) { Error(threadError); diff --git a/engine/system/win/sys_video.cpp b/engine/system/win/sys_video.cpp index 6d8d81b..891c8a7 100644 --- a/engine/system/win/sys_video.cpp +++ b/engine/system/win/sys_video.cpp @@ -275,6 +275,8 @@ int sys_video_c::Apply(sys_vidSet_s* set) vid.size[0] = wrec.right; vid.size[1] = wrec.bottom; + vid.fgfps = cur.fgfps; + // Process any messages generated during application sys->RunMessages(); From 2dec7930bf1171d4a22ed3b7642bd20c62c85d04 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Tue, 16 Mar 2021 05:01:18 -0400 Subject: [PATCH 2/4] Revert tiff.lib removal --- SimpleGraphic.vcxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SimpleGraphic.vcxproj b/SimpleGraphic.vcxproj index 8cdfba3..16f239c 100644 --- a/SimpleGraphic.vcxproj +++ b/SimpleGraphic.vcxproj @@ -120,7 +120,7 @@ <GenerateDebugInformation>true</GenerateDebugInformation> <EnableUAC>false</EnableUAC> <AdditionalLibraryDirectories>$(SolutionDir)vcpkg\installed\x86-windows-static\lib;%(AdditionalLibraryDirectories)LuaJIT/src;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> - <AdditionalDependencies>gif.lib;jpeg.lib;lzma.lib;libpng16.lib;lua51.lib;zlib.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalDependencies>gif.lib;jpeg.lib;lzma.lib;libpng16.lib;lua51.lib;tiff.lib;zlib.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> From ab3f87db23dea1294ce550f2a95067bfab25796c Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Tue, 16 Mar 2021 05:25:51 -0400 Subject: [PATCH 3/4] Incorporate review feedback --- config.h | 1 + engine/core/core_video.cpp | 3 +++ engine/system/sys_video.h | 2 ++ engine/system/win/sys_main.cpp | 11 ----------- engine/system/win/sys_video.cpp | 1 + ui_main.cpp | 20 ++++++++++++++++---- 6 files changed, 23 insertions(+), 15 deletions(-) diff --git a/config.h b/config.h index 6d466dc..21f388b 100644 --- a/config.h +++ b/config.h @@ -19,5 +19,6 @@ #define CFG_VID_DEFFULLSCREEN "0" #define CFG_VID_DEFRESIZABLE "0" #define CFG_VID_DEFFGFPS "30" +#define CFG_VID_DEFBGFPS "5" #define CFG_VID_MINWIDTH 1280 #define CFG_VID_MINHEIGHT 720 \ No newline at end of file diff --git a/engine/core/core_video.cpp b/engine/core/core_video.cpp index e347d6d..fbe0b25 100644 --- a/engine/core/core_video.cpp +++ b/engine/core/core_video.cpp @@ -49,6 +49,7 @@ class core_video_c: public core_IVideo, public conCmdHandler_c { conVar_c* vid_resizable; conVar_c* vid_last; conVar_c* vid_fgfps; + conVar_c* vid_bgfps; void C_Vid_Apply(IConsole* conHnd, args_c &args); void C_Vid_ModeList(IConsole* conHnd, args_c &args); @@ -73,6 +74,7 @@ core_video_c::core_video_c(sys_IMain* sysHnd) vid_resizable = sys->con->Cvar_Add("vid_resizable", CV_ARCHIVE|CV_CLAMP, CFG_VID_DEFRESIZABLE, 0, 3); vid_last = sys->con->Cvar_Add("vid_last", CV_ARCHIVE, ""); vid_fgfps = sys->con->Cvar_Add("vid_fgfps", CV_ARCHIVE|CV_CLAMP, CFG_VID_DEFFGFPS, 5, 120); + vid_bgfps = sys->con->Cvar_Add("vid_bgfps", CV_ARCHIVE | CV_CLAMP, CFG_VID_DEFBGFPS, 5, 120); Cmd_Add("vid_apply", 0, "", this, &core_video_c::C_Vid_Apply); Cmd_Add("vid_modeList", 0, "", this, &core_video_c::C_Vid_ModeList); @@ -114,6 +116,7 @@ void core_video_c::Apply(bool shown) set.minSize[0] = CFG_VID_MINWIDTH; set.minSize[1] = CFG_VID_MINHEIGHT; set.fgfps = vid_fgfps->intVal; + set.bgfps = vid_bgfps->intVal; sys->video->Apply(&set); } diff --git a/engine/system/sys_video.h b/engine/system/sys_video.h index 1e8a39b..b5bff56 100644 --- a/engine/system/sys_video.h +++ b/engine/system/sys_video.h @@ -23,6 +23,7 @@ struct sys_vidSave_s { int pos[2] = {}; bool maximised = false; int fgfps = 0; + int bgfps = 0; }; // Video settings structure @@ -34,6 +35,7 @@ struct sys_vidSet_s { int depth = 0; // Bit depth int minSize[2] = {}; // Minimum size for resizable windows int fgfps = 0; // Foreground FPS limit + int bgfps = 0; // Background FPS limit sys_vidSave_s save; // Saved state }; diff --git a/engine/system/win/sys_main.cpp b/engine/system/win/sys_main.cpp index 42504ec..84ab748 100644 --- a/engine/system/win/sys_main.cpp +++ b/engine/system/win/sys_main.cpp @@ -11,9 +11,6 @@ #include <eh.h> -#include <chrono> -#include <thread> - // ====== // Locals // ====== @@ -780,15 +777,7 @@ bool sys_main_c::Run(int argc, char** argv) while (exitFlag == false) { RunMessages(); - const auto frameStart = std::chrono::high_resolution_clock::now(); core->Frame(); - const auto frameEnd = std::chrono::high_resolution_clock::now(); - using FpMilliseconds = std::chrono::duration<float, std::chrono::milliseconds::period>; - const auto frameDuration = std::chrono::duration_cast<FpMilliseconds>(frameEnd - frameStart); - const auto minimumFrameDuration = FpMilliseconds(1000.0f / video->vid.fgfps); - if (frameDuration < minimumFrameDuration) { - std::this_thread::sleep_for(minimumFrameDuration - frameDuration); - } if (threadError) { Error(threadError); diff --git a/engine/system/win/sys_video.cpp b/engine/system/win/sys_video.cpp index 891c8a7..6eedae3 100644 --- a/engine/system/win/sys_video.cpp +++ b/engine/system/win/sys_video.cpp @@ -276,6 +276,7 @@ int sys_video_c::Apply(sys_vidSet_s* set) vid.size[1] = wrec.bottom; vid.fgfps = cur.fgfps; + vid.bgfps = cur.bgfps; // Process any messages generated during application sys->RunMessages(); diff --git a/ui_main.cpp b/ui_main.cpp index f9622e0..17be353 100644 --- a/ui_main.cpp +++ b/ui_main.cpp @@ -6,6 +6,9 @@ #include "ui_local.h" +#include <chrono> +#include <thread> + // ====== // Locals // ====== @@ -373,6 +376,8 @@ void ui_main_c::ScriptInit() void ui_main_c::Frame() { + const auto frameStart = std::chrono::high_resolution_clock::now(); + auto fpsLimit = sys->video->vid.fgfps; if (!sys->video->IsVisible() || sys->conWin->IsVisible() || restartFlag || didExit) { framesSinceWindowHidden = 0; } @@ -380,8 +385,7 @@ void ui_main_c::Frame() framesSinceWindowHidden++; } else if (!sys->video->IsActive() && !sys->video->IsCursorOverWindow()) { - sys->Sleep(100); - return; + fpsLimit = sys->video->vid.bgfps; } if (renderer) { @@ -425,8 +429,8 @@ void ui_main_c::Frame() } //sys->con->Printf("Finishing up...\n"); - if ( !sys->video->IsActive() ) { - sys->Sleep(100); + if ( sys->video->IsActive() ) { + fpsLimit = sys->video->vid.fgfps; } while (restartFlag) { @@ -436,6 +440,14 @@ void ui_main_c::Frame() } ScriptInit(); } + + using FpMilliseconds = std::chrono::duration<float, std::chrono::milliseconds::period>; + const auto minimumFrameDuration = FpMilliseconds(1000.0f / fpsLimit); + const auto frameEnd = std::chrono::high_resolution_clock::now(); + const auto frameDuration = std::chrono::duration_cast<FpMilliseconds>(frameEnd - frameStart); + if (frameDuration < minimumFrameDuration) { + std::this_thread::sleep_for(minimumFrameDuration - frameDuration); + } } void ui_main_c::ScriptShutdown() From 9f28e3ee80c9dd8dbf5a0b30007af7650cdd0e96 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Tue, 16 Mar 2021 05:30:26 -0400 Subject: [PATCH 4/4] Formatting --- engine/core/core_video.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/core/core_video.cpp b/engine/core/core_video.cpp index fbe0b25..2e1b630 100644 --- a/engine/core/core_video.cpp +++ b/engine/core/core_video.cpp @@ -74,7 +74,7 @@ core_video_c::core_video_c(sys_IMain* sysHnd) vid_resizable = sys->con->Cvar_Add("vid_resizable", CV_ARCHIVE|CV_CLAMP, CFG_VID_DEFRESIZABLE, 0, 3); vid_last = sys->con->Cvar_Add("vid_last", CV_ARCHIVE, ""); vid_fgfps = sys->con->Cvar_Add("vid_fgfps", CV_ARCHIVE|CV_CLAMP, CFG_VID_DEFFGFPS, 5, 120); - vid_bgfps = sys->con->Cvar_Add("vid_bgfps", CV_ARCHIVE | CV_CLAMP, CFG_VID_DEFBGFPS, 5, 120); + vid_bgfps = sys->con->Cvar_Add("vid_bgfps", CV_ARCHIVE|CV_CLAMP, CFG_VID_DEFBGFPS, 5, 120); Cmd_Add("vid_apply", 0, "", this, &core_video_c::C_Vid_Apply); Cmd_Add("vid_modeList", 0, "", this, &core_video_c::C_Vid_ModeList);