Optional FPS Limiter for running games too, use the Slider GUI object in the config to specify custom limits.
Make it way more accurate by excluding the SDL_Wait time and microsecond precision. Differential Revision: https://code.wildfiregames.com/D109 Refs #2882 Reviewed By: Vladislav This was SVN commit r19507.
This commit is contained in:
parent
dd9b83626e
commit
4a5f302ce1
@ -125,6 +125,9 @@ forcealphatest = false
|
||||
; Color of the sky (in "r g b" format)
|
||||
skycolor = "0 0 0"
|
||||
|
||||
[adaptivefps]
|
||||
session = 60 ; Throttle FPS in running games (prevents 100% CPU workload).
|
||||
menu = 30 ; Throttle FPS in menus only.
|
||||
|
||||
[hotkey]
|
||||
; Each one of the specified keys will trigger the action on the left
|
||||
@ -329,9 +332,6 @@ scale = 1.0 ; GUI scaling factor, for improved compatibili
|
||||
[gui.gamesetup]
|
||||
enabletips = true ; Enable/Disable tips during gamesetup (for newcomers)
|
||||
|
||||
[gui.menu]
|
||||
limitfps = true ; Limit FPS in the menus and loading screen
|
||||
|
||||
[gui.session]
|
||||
camerajump.threshold = 40 ; How close do we have to be to the actual location in order to jump back to the previous one?
|
||||
timeelapsedcounter = false ; Show the game duration in the top right corner
|
||||
|
@ -171,6 +171,7 @@ function setupControl(option, i, category)
|
||||
if (callbackFunction)
|
||||
Engine[callbackFunction](+this.value);
|
||||
updateOptionPanel();
|
||||
control.tooltip = this.value;
|
||||
};
|
||||
}(key, callbackFunction, minvalue, maxvalue);
|
||||
|
||||
|
@ -205,10 +205,16 @@
|
||||
"parameters": { "config": "vsync" }
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"label": "Limit FPS in Menus",
|
||||
"tooltip": "Limit FPS to 50 in all menus, to save power.",
|
||||
"parameters": { "config": "gui.menu.limitfps" }
|
||||
"type": "slider",
|
||||
"label": "FPS throttling in menus",
|
||||
"tooltip": "To save CPU workload, throttle render frequency in all menus. Set to maximum to disable throttling.",
|
||||
"parameters": { "config": "adaptivefps.menu", "min": 20, "max": 100 }
|
||||
},
|
||||
{
|
||||
"type": "slider",
|
||||
"label": "FPS throttling in games",
|
||||
"tooltip": "To save CPU workload, throttle render frequency in running games. Set to maximum to disable throttling.",
|
||||
"parameters": { "config": "adaptivefps.session", "min": 20, "max": 100 }
|
||||
}
|
||||
],
|
||||
"soundSetting":
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2016 Wildfire Games.
|
||||
/* Copyright (C) 2017 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -31,6 +31,8 @@ that of Atlas depending on commandline parameters.
|
||||
#define MINIMAL_PCH 2
|
||||
#include "lib/precompiled.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "lib/debug.h"
|
||||
#include "lib/status.h"
|
||||
#include "lib/secure_crt.h"
|
||||
@ -92,6 +94,8 @@ void kill_mainloop();
|
||||
static int g_ResizedW;
|
||||
static int g_ResizedH;
|
||||
|
||||
static std::chrono::high_resolution_clock::time_point lastFrameTime;
|
||||
|
||||
// main app message handler
|
||||
static InReaction MainInputHandler(const SDL_Event_* ev)
|
||||
{
|
||||
@ -178,6 +182,31 @@ static void PumpEvents()
|
||||
g_TouchInput.Frame();
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally throttle the render frequency in order to
|
||||
* prevent 100% workload of the currently used CPU core.
|
||||
*/
|
||||
inline static void LimitFPS()
|
||||
{
|
||||
if (g_VSync)
|
||||
return;
|
||||
|
||||
double fpsLimit = 0.0;
|
||||
CFG_GET_VAL(g_Game && g_Game->IsGameStarted() ? "adaptivefps.session" : "adaptivefps.menu", fpsLimit);
|
||||
|
||||
// Keep in sync with options.json
|
||||
if (fpsLimit < 20.0 || fpsLimit >= 100.0)
|
||||
return;
|
||||
|
||||
double wait = 1000.0 / fpsLimit -
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::high_resolution_clock::now() - lastFrameTime).count() / 1000.0;
|
||||
|
||||
if (wait > 0.0)
|
||||
SDL_Delay(wait);
|
||||
|
||||
lastFrameTime = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
static int ProgressiveLoad()
|
||||
{
|
||||
@ -275,7 +304,7 @@ static void Frame()
|
||||
// If we are not running a multiplayer game, disable updates when the game is
|
||||
// minimized or out of focus and relinquish the CPU a bit, in order to make
|
||||
// debugging easier.
|
||||
if(g_PauseOnFocusLoss && !g_NetClient && !g_app_has_focus)
|
||||
if (g_PauseOnFocusLoss && !g_NetClient && !g_app_has_focus)
|
||||
{
|
||||
PROFILE3("non-focus delay");
|
||||
need_update = false;
|
||||
@ -283,22 +312,6 @@ static void Frame()
|
||||
SDL_Delay(10);
|
||||
}
|
||||
|
||||
// Throttling: limit update and render frequency to the minimum to 50 FPS
|
||||
// in the "inactive" state, so that other windows get enough CPU time,
|
||||
// (and it's always nice for power+thermal management).
|
||||
// TODO: when the game performance is high enough, implementing a limit for
|
||||
// in-game framerate might be sensible.
|
||||
const float maxFPSMenu = 50.0;
|
||||
bool limit_fps = false;
|
||||
CFG_GET_VAL("gui.menu.limitfps", limit_fps);
|
||||
if (limit_fps && (!g_Game || !g_Game->IsGameStarted()))
|
||||
{
|
||||
float remainingFrameTime = (1000.0 / maxFPSMenu) - realTimeSinceLastFrame;
|
||||
if (remainingFrameTime > 0)
|
||||
SDL_Delay(remainingFrameTime);
|
||||
}
|
||||
|
||||
|
||||
// this scans for changed files/directories and reloads them, thus
|
||||
// allowing hotloading (changes are immediately assimilated in-game).
|
||||
ReloadChangedFiles();
|
||||
@ -351,7 +364,7 @@ static void Frame()
|
||||
g_Console->Update(realTimeSinceLastFrame);
|
||||
|
||||
ogl_WarnIfError();
|
||||
if(need_render)
|
||||
if (need_render)
|
||||
{
|
||||
Render();
|
||||
|
||||
@ -363,6 +376,8 @@ static void Frame()
|
||||
g_Profiler.Frame();
|
||||
|
||||
g_GameRestarted = false;
|
||||
|
||||
LimitFPS();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user