From f10a47ed75d6367bf286cc1c095808b674967ff9 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 2 Mar 2004 21:37:44 +0000 Subject: [PATCH] From David Fries, changed the Win32 Timer init code across to using QueryPerformanceCounter to avoid inaccurate and slow original Sleep based code. --- src/osg/Timer.cpp | 71 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/src/osg/Timer.cpp b/src/osg/Timer.cpp index a2bdb489f..9bf696b72 100644 --- a/src/osg/Timer.cpp +++ b/src/osg/Timer.cpp @@ -47,20 +47,75 @@ const Timer* Timer::instance() } else { - - // use a static here to ensure that the Sleep(..) for 1 sec - // is not incurred more than once per app execution. + // use a static here to ensure that the time to determine + // the cpu frequency is not incurred more than once + // per app execution. static double _tempSecsPerClick=0.0; if (_tempSecsPerClick==0.0) { - Timer_t start_time = tick(); - Sleep (1000); - Timer_t end_time = tick(); + // QueryPerformanceCounter under Windows 2000 Service Pack 3 + // two 2.4 GHz cpus was timed to take about 70 times longer + // than the RDTSC assembly instruction sequence, but if + // that counter is available we use it to quickly determine + // the Time Stamp Counter rate, quickly as in 240 microseconds + LARGE_INTEGER frequency; + if(QueryPerformanceFrequency(&frequency)) + { + //#define DEBUG_TIME_OUTPUT 1 + LARGE_INTEGER QPCstart, QPCstop, + QPCstartAfter, QPCstopAfter; + Timer_t TSCstart, TSCstop; + double QPCSecsPerClock = 1.0/frequency.QuadPart; + double elapsed, last, current, bound; - _tempSecsPerClick = 1.0/(double)(end_time-start_time); + QueryPerformanceCounter(&QPCstart); + TSCstart=tick(); + QueryPerformanceCounter(&QPCstartAfter); + + current = 0; + do + { + // store the seconds per clock + last = current; + // read the clocks + QueryPerformanceCounter(&QPCstop); + TSCstop=tick(); + QueryPerformanceCounter(&QPCstopAfter); + // average before and after to approximate reading + // both clocks at the same time + elapsed = ((QPCstop.QuadPart+QPCstopAfter.QuadPart) + -(QPCstart.QuadPart+QPCstartAfter.QuadPart))/2.0 + *QPCSecsPerClock; + // TSC seconds per clock + current = elapsed / (TSCstop-TSCstart); + // calculate a bound to check against + bound = current/1000000; + // break if current-boundlast + }while(current-bound>last || current+bound