Windows Quake - Improved Timer

Post tutorials on how to do certain tasks within game or engine code here.
Post Reply
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Windows Quake - Improved Timer

Post 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;
}
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
qbism
Posts: 1236
Joined: Thu Nov 04, 2004 5:51 am
Contact:

Post 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:
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Post 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.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
qbism
Posts: 1236
Joined: Thu Nov 04, 2004 5:51 am
Contact:

Re: Windows Quake - Improved Timer

Post by qbism »

I just applied this and it fixed timing acceleration problem (Benny Hill) on an intel p6100 2.0ghz with Win7 x64. Thanks!
Post Reply