@ -62,6 +62,7 @@ CVAR_DEFINE_AUTO( host_limitlocal, "0", 0, "apply cl_cmdrate and rate to loopbac
@@ -62,6 +62,7 @@ CVAR_DEFINE_AUTO( host_limitlocal, "0", 0, "apply cl_cmdrate and rate to loopbac
CVAR_DEFINE ( host_maxfps , " fps_max " , " 72 " , FCVAR_ARCHIVE | FCVAR_FILTERABLE , " host fps upper limit " ) ;
static CVAR_DEFINE_AUTO ( host_framerate , " 0 " , FCVAR_FILTERABLE , " locks frame timing to this value in seconds " ) ;
static CVAR_DEFINE ( host_sleeptime , " sleeptime " , " 1 " , FCVAR_ARCHIVE | FCVAR_FILTERABLE , " milliseconds to sleep for each frame. higher values reduce fps accuracy " ) ;
static CVAR_DEFINE_AUTO ( host_sleeptime_debug , " 0 " , 0 , " print sleeps between frames " ) ;
CVAR_DEFINE ( con_gamemaps , " con_mapfilter " , " 1 " , FCVAR_ARCHIVE , " when true show only maps in game folder " ) ;
void Sys_PrintUsage ( void )
@ -618,66 +619,104 @@ double Host_CalcFPS( void )
@@ -618,66 +619,104 @@ double Host_CalcFPS( void )
return fps ;
}
/*
= = = = = = = = = = = = = = = = = = =
Host_FilterTime
Returns false if the time is too short to run a frame
= = = = = = = = = = = = = = = = = = =
*/
qboolean Host_FilterTime ( float time )
static qboolean Host_Autosleep ( double dt , double scale )
{
static double oldtime ;
double fps , scale = sys_timescale . value ;
double targetframetime , fps ;
int sleep ;
host . realtime + = time * scale ;
fps = Host_CalcFPS ( ) ;
// clamp the fps in multiplayer games
if ( fps ! = 0.0 )
{
static int sleeps ;
double targetframetime ;
int sleeptime = Host_CalcSleep ( ) ;
if ( fps < = 0 )
return true ;
// limit fps to withing tolerable range
fps = bound ( MIN_FPS , fps , MAX_FPS ) ;
// limit fps to withing tolerable range
fps = bound ( MIN_FPS , fps , MAX_FPS ) ;
if ( Host_IsDedicated ( ) )
targetframetime = ( 1.0 / ( fps + 1.0 ) ) ;
else targetframetime = ( 1.0 / fps ) ;
if ( Host_IsDedicated ( ) )
targetframetime = ( 1.0 / ( fps + 1.0 ) ) ;
else targetframetime = ( 1.0 / fps ) ;
sleep = Host_CalcSleep ( ) ;
if ( sleep = = 0 ) // no sleeps between frames, much simpler code
{
if ( dt < targetframetime * scale )
return false ;
}
else
{
static double timewindow ; // allocate a time window for sleeps
static int counter ; // for debug
static double realsleeptime ;
const double sleeptime = sleep * 0.001 ;
if ( ( host . realtime - oldtime ) < targetframetime * scale )
if ( dt < targetframetime * scale )
{
if ( sleeptime > 0 & & sleeps > 0 )
// if we have allocated time window, try to sleep
if ( timewindow > realsleeptime )
{
Sys_Sleep ( sleeptime ) ;
sleeps - - ;
// Sys_Sleep isn't guaranteed to sleep an exact amount of milliseconds
// so we measure the real sleep time and use it to decrease the window
double t1 = Sys_DoubleTime ( ) , t2 ;
Sys_Sleep ( sleep ) ; // in msec!
t2 = Sys_DoubleTime ( ) ;
realsleeptime = t2 - t1 ;
timewindow - = realsleeptime ;
if ( host_sleeptime_debug . value )
{
counter + + ;
Con_NPrintf ( counter , " %d: %.4f %.4f " , counter , timewindow , realsleeptime ) ;
}
}
return false ;
}
if ( sleeptime > 0 & & sleeps < = 0 )
// if we exhausted this time window, allocate a new one after new frame
if ( timewindow < = realsleeptime )
{
if ( host . status = = HOST_FRAME )
{
// give few sleeps this frame with small margin
double targetsleeptime = targetframetime - host . pureframetime * 2 ;
double targetsleeptime = targetframetime - host . pureframetime * 2 ;
// don't sleep if we can't keep up with the framerate
if ( targetsleeptime > 0 )
sleeps = targetsleeptime / ( sleeptime * 0.001 ) ;
else sleeps = 0 ;
}
else
if ( targetsleeptime > 0 )
timewindow = targetsleeptime ;
else timewindow = 0 ;
realsleeptime = sleeptime ; // reset in case CPU was too busy
if ( host_sleeptime_debug . value )
{
// always sleep at least once in minimized/nofocus state
sleeps = 1 ;
counter = 0 ;
Con_NPrintf ( 0 , " tgt = %.4f, pft = %.4f, wnd = %.4f " , targetframetime , host . pureframetime , timewindow ) ;
}
}
}
return true ;
}
/*
= = = = = = = = = = = = = = = = = = =
Host_FilterTime
Returns false if the time is too short to run a frame
= = = = = = = = = = = = = = = = = = =
*/
qboolean Host_FilterTime ( float time )
{
static double oldtime ;
double dt ;
double scale = sys_timescale . value ;
host . realtime + = time * scale ;
dt = host . realtime - oldtime ;
// clamp the fps in multiplayer games
if ( ! Host_Autosleep ( dt , scale ) )
return false ;
host . frametime = host . realtime - oldtime ;
host . realframetime = bound ( MIN_FRAMETIME , host . frametime , MAX_FRAMETIME ) ;
oldtime = host . realtime ;
@ -1181,6 +1220,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
@@ -1181,6 +1220,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Cvar_RegisterVariable ( & host_maxfps ) ;
Cvar_RegisterVariable ( & host_framerate ) ;
Cvar_RegisterVariable ( & host_sleeptime ) ;
Cvar_RegisterVariable ( & host_sleeptime_debug ) ;
Cvar_RegisterVariable ( & host_gameloaded ) ;
Cvar_RegisterVariable ( & host_clientloaded ) ;
Cvar_RegisterVariable ( & host_limitlocal ) ;