Page 1 of 1

Windows Quake - Improved Timer

Posted: Sun May 15, 2011 6:59 pm
by mh
Not so much a tutorial as it is an invitation to critique and suggestions for further possible improvements and refinements. If you think it's crap, some words on why you think it's crap would be nice.

The background.

We have two main methods of timing on Windows: QueryPerformanceCounter and timeGetTime. QueryPerformanceCounter sucks because it's unstable on many PCs but it does have high resolution. timeGetTime sucks because it's resolution - while quite high - isn't high enough for Quakes 72 FPS but it is stable on all PCs.

So what I did was use timeGetTime as a solid baseline and QueryPerformanceCounter to fill in the sub-millisecond gaps:

Code: Select all

double Sys_FloatTime (void)
{
	static qboolean firsttime = true;
	static __int64 qpcfreq = 0;
	static __int64 currqpccount = 0;
	static __int64 lastqpccount = 0;
	static double qpcfudge = 0;
	DWORD currtime = 0;
	static DWORD lasttime = 0;
	static DWORD starttime = 0;

	if (firsttime)
	{
		timeBeginPeriod (1);
		starttime = lasttime = timeGetTime ();
		QueryPerformanceFrequency ((LARGE_INTEGER *) &qpcfreq);
		QueryPerformanceCounter ((LARGE_INTEGER *) &lastqpccount);
		firsttime = false;
		return 0;
	}

	// get the current time from both counters
	currtime = timeGetTime ();
	QueryPerformanceCounter ((LARGE_INTEGER *) &currqpccount);

	if (currtime != lasttime)
	{
		// requery the frequency in case it changes (which it can on multicore machines)
		QueryPerformanceFrequency ((LARGE_INTEGER *) &qpcfreq);

		// store back times and calc a fudge factor as timeGetTime can overshoot on a sub-millisecond scale
		qpcfudge = ((double) (currqpccount - lastqpccount) / (double) qpcfreq) - ((double) (currtime - lasttime) * 0.001);
		lastqpccount = currqpccount;
		lasttime = currtime;
	}
	else qpcfudge = 0;

	// the final time is the base from timeGetTime plus an addition from QPC
	return ((double) (currtime - starttime) * 0.001) + ((double) (currqpccount - lastqpccount) / (double) qpcfreq) + qpcfudge;
}

Posted: Sun May 15, 2011 11:00 pm
by qbism
Can QPC stability level be determined within a few frames, and then decide which one to use? Or is it possible that QPC be stable for a while and then go whacko?

And you know it should be Sys_DoubleTime :twisted:

Posted: Sun May 15, 2011 11:07 pm
by mh
qbism wrote:Can QPC stability level be determined within a few frames, and then decide which one to use? Or is it possible that QPC be stable for a while and then go whacko?
The latter, and in fact it can see-saw between being completely wild and stable over a period of time too.
qbism wrote:And you know it should be Sys_DoubleTime :twisted:
Yup, I just called it Sys_FloatTime for consistency with the ID Quake source.

Re: Windows Quake - Improved Timer

Posted: Tue Jan 08, 2013 11:54 pm
by qbism
I just applied this and it fixed timing acceleration problem (Benny Hill) on an intel p6100 2.0ghz with Win7 x64. Thanks!