Forum

Windows Quake - Improved Timer

Post tutorials on how to do certain tasks within game or engine code here.

Moderator: InsideQC Admins

Windows Quake - Improved Timer

Postby mh » Sun May 15, 2011 6:59 pm

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

Postby qbism » Sun May 15, 2011 11:00 pm

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:
User avatar
qbism
 
Posts: 1230
Joined: Thu Nov 04, 2004 5:51 am

Postby mh » Sun May 15, 2011 11:07 pm

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

Re: Windows Quake - Improved Timer

Postby qbism » Tue Jan 08, 2013 11:54 pm

I just applied this and it fixed timing acceleration problem (Benny Hill) on an intel p6100 2.0ghz with Win7 x64. Thanks!
User avatar
qbism
 
Posts: 1230
Joined: Thu Nov 04, 2004 5:51 am


Return to Programming Tutorials

Who is online

Users browsing this forum: No registered users and 1 guest