🔒 Locked
QueryPerformanceCounter Question
Advertisement
Original Post
Hey guys, wondering if any of you ran into the same situation i am having, and if you have a better result than i am... Basically im Calculating FPS and Frame Time using QueryPerformanceCounter... Only one problem, I call and Save the time before the render, then after and compare the two... But the Count QueryPerformanceCounter returns is exactly the same. Now i know it cant be rendering so fast that QPC hasn't changed yet, so i came up with just Sitting on it till it changes with a while(QPC == lasttime); but im wasting proc. clocks with this fix. :( So i tried switching over to the timeGetTime() method and setting timeBeginPeriod(1); same problem. Returning the same time every cycle :(
Post code, if I recall right QueryPerformanceCounter returns a 64bit int. timeGetTime() is a lot less accurate. You can also search google for QueryPerformanceCounter articles, there's a few timers already written using it for games and other applications. You can even search these forums too.
CFrameRate::CFrameRate(void){ uiFrameTimeBufferPos = 0; QueryPerformanceFrequency((LARGE_INTEGER*)&QPCFreq);}CFrameRate::~CFrameRate(void){ }void CFrameRate::BeginFrame(void){ __int64 i64Time = 0; QueryPerformanceCounter((LARGE_INTEGER*)&i64Time); // Get Current Count dThisFrame = (long double)i64Time / (long double)QPCFreq;}void CFrameRate::EndFrame(void){ __int64 i64Time = 0; QueryPerformanceCounter((LARGE_INTEGER*)&i64Time); //while (((long double)i64Time / (long double)QPCFreq) == dThisFrame) //QueryPerformanceCounter((LARGE_INTEGER*)&i64Time); dFrameTime = ((long double)i64Time / (long double)QPCFreq) - dThisFrame; dFPS = 1.0f/dFrameTime; dFrameTimeAvgBuffer[uiFrameTimeBufferPos++] = dFrameTime; if (uiFrameTimeBufferPos == 10) uiFrameTimeBufferPos = 0;}I have commented out what i want to get rid of... Its really buggin me...
Quote:
Original post by Chase85 CFrameRate::CFrameRate(void){ uiFrameTimeBufferPos = 0; QueryPerformanceFrequency((LARGE_INTEGER*)&QPCFreq);}CFrameRate::~CFrameRate(void){ }void CFrameRate::BeginFrame(void){ __int64 i64Time = 0; QueryPerformanceCounter((LARGE_INTEGER*)&i64Time); // Get Current Count dThisFrame = (long double)i64Time / (long double)QPCFreq;}void CFrameRate::EndFrame(void){ __int64 i64Time = 0; QueryPerformanceCounter((LARGE_INTEGER*)&i64Time); //while (((long double)i64Time / (long double)QPCFreq) == dThisFrame) //QueryPerformanceCounter((LARGE_INTEGER*)&i64Time); dFrameTime = ((long double)i64Time / (long double)QPCFreq) - dThisFrame; dFPS = 1.0f/dFrameTime; dFrameTimeAvgBuffer[uiFrameTimeBufferPos++] = dFrameTime; if (uiFrameTimeBufferPos == 10) uiFrameTimeBufferPos = 0;}
I have commented out what i want to get rid of... Its really buggin me...
So as I mentioned before you can't convert it to a double. :-D It does not have enough precision to store the value. You should subtract the long ints first, then convert that to a double and divide by (double)freq. Also, long double and double should be the same size on win32.
Okay only 1 tiny little problem, When dividing the Difference in time now by the Frequency, because it's going so fast i get a double that's too small. I wish i could truncate this someway. It runs amazing if i throw a Sleep(1) in the loop cause it slows it down just enough to about 450 fps. It'll run fine once i get more things on the screen but still there's gotta be a way to get that number regardless...
DOUBLE dxutStaticTimer(){ static BOOL bQPCSupported = TRUE; static LARGE_INTEGER liCurrentTime = { (LONGLONG)0 };; static LARGE_INTEGER liFrequency = { (LONGLONG)0 }; static LARGE_INTEGER liLastTime = { (LONGLONG)0 };; static DOUBLE dTimeFactor = 1.0f; if ( liFrequency.QuadPart != (LONGLONG)0 ) { // QueryPerformanceCounter(...) supported and set, use high precision timer ::QueryPerformanceCounter( &liCurrentTime ); LARGE_INTEGER liElapsed; liElapsed.QuadPart = liCurrentTime.QuadPart - liLastTime.QuadPart; liLastTime.QuadPart = liCurrentTime.QuadPart; return liElapsed.QuadPart * dTimeFactor; } if ( bQPCSupported != TRUE ) { // QueryPerformanceCounter(...) not supported, use low precision timer liCurrentTime.QuadPart = ::timeGetTime(); LARGE_INTEGER liElapsed; liElapsed.QuadPart = liCurrentTime.QuadPart - liLastTime.QuadPart; liLastTime.QuadPart = liCurrentTime.QuadPart; return liElapsed.QuadPart * 0.001f; } if ( bQPCSupported && liFrequency.QuadPart == (LONGLONG)0 ) { // QueryPerformanceCounter(...) not supported or not yet initialized ::QueryPerformanceFrequency( &liFrequency ); if ( !liFrequency.QuadPart ) { bQPCSupported = FALSE; liLastTime.QuadPart = ::timeGetTime(); } else { dTimeFactor /= liFrequency.QuadPart; ::QueryPerformanceCounter( &liLastTime ); } return 0.0f; } return 0.0f;}This works fine for me, and it even should revert back to timeGetTime() in case QPC is not supported.
Edit: it returns the time elapsed since last call( 0 at first call naturally) and in seconds
I usually show my frame times in fractions of milliseconds:
AvgFrameTime: 5.87 ms (170.31 FPS) | Memory: 5.3 MB | Objects: 149
AvgFrameTime: 6.53 ms (153.04 FPS) | Memory: 4.9 MB | Objects: 480
AvgFrameTime: 18.17 ms ( 55.04 FPS) | Memory: 5.2 MB | Objects: 750
AvgFrameTime: 20.73 ms ( 48.23 FPS) | Memory: 3.8 MB | Objects: 750
AvgFrameTime: 20.41 ms ( 49.00 FPS) | Memory: 4.4 MB | Objects: 750
AvgFrameTime: 20.20 ms ( 49.49 FPS) | Memory: 5.0 MB | Objects: 750
AvgFrameTime: 20.47 ms ( 48.85 FPS) | Memory: 3.6 MB | Objects: 750
AvgFrameTime: 20.25 ms ( 49.38 FPS) | Memory: 4.1 MB | Objects: 750
AvgFrameTime: 20.28 ms ( 49.31 FPS) | Memory: 4.8 MB | Objects: 750
AvgFrameTime: 20.33 ms ( 49.18 FPS) | Memory: 3.4 MB | Objects: 750
AvgFrameTime: 20.30 ms ( 49.26 FPS) | Memory: 4.0 MB | Objects: 750
AvgFrameTime: 20.25 ms ( 49.37 FPS) | Memory: 4.6 MB | Objects: 750
AvgFrameTime: 20.26 ms ( 49.36 FPS) | Memory: 5.2 MB | Objects: 750
AvgFrameTime: 20.50 ms ( 48.79 FPS) | Memory: 3.8 MB | Objects: 750
AvgFrameTime: 20.28 ms ( 49.32 FPS) | Memory: 4.3 MB | Objects: 750
AvgFrameTime: 20.42 ms ( 48.98 FPS) | Memory: 4.9 MB | Objects: 750
AvgFrameTime: 5.87 ms (170.31 FPS) | Memory: 5.3 MB | Objects: 149
AvgFrameTime: 6.53 ms (153.04 FPS) | Memory: 4.9 MB | Objects: 480
AvgFrameTime: 18.17 ms ( 55.04 FPS) | Memory: 5.2 MB | Objects: 750
AvgFrameTime: 20.73 ms ( 48.23 FPS) | Memory: 3.8 MB | Objects: 750
AvgFrameTime: 20.41 ms ( 49.00 FPS) | Memory: 4.4 MB | Objects: 750
AvgFrameTime: 20.20 ms ( 49.49 FPS) | Memory: 5.0 MB | Objects: 750
AvgFrameTime: 20.47 ms ( 48.85 FPS) | Memory: 3.6 MB | Objects: 750
AvgFrameTime: 20.25 ms ( 49.38 FPS) | Memory: 4.1 MB | Objects: 750
AvgFrameTime: 20.28 ms ( 49.31 FPS) | Memory: 4.8 MB | Objects: 750
AvgFrameTime: 20.33 ms ( 49.18 FPS) | Memory: 3.4 MB | Objects: 750
AvgFrameTime: 20.30 ms ( 49.26 FPS) | Memory: 4.0 MB | Objects: 750
AvgFrameTime: 20.25 ms ( 49.37 FPS) | Memory: 4.6 MB | Objects: 750
AvgFrameTime: 20.26 ms ( 49.36 FPS) | Memory: 5.2 MB | Objects: 750
AvgFrameTime: 20.50 ms ( 48.79 FPS) | Memory: 3.8 MB | Objects: 750
AvgFrameTime: 20.28 ms ( 49.32 FPS) | Memory: 4.3 MB | Objects: 750
AvgFrameTime: 20.42 ms ( 48.98 FPS) | Memory: 4.9 MB | Objects: 750
Tsk Tsk, im stupid i found my problem :( I was calculating Frames Before Calling Begin Scene and testing if it actually worked, So sometimes BeginScene would return false, and id be calculating a bogus frame thus the 999.999 fps, Now it only Runs when frames are rendered, and i apologize. Thx a ton those guys...
On a related note, I came across this interesting para while reading the documetnation of the timer class in boost libraries:
"... Tests showed that while the precision of these timers was high, the latency was sometimes very much higher than for the std::clock() function, and that is very bad. Furthermore, results using the Win32 API were very dependent on both the compiler (Microsoft and Borland were tested) and the operating system version (Windows NT, Windows 95, etc.) Thus the std::clock() function was much more reliable, and so was retained even on this platform with its own timer API."
Can anyone shed some light by what it means by "higher latency is very bad"? I thought QueryPerformanceCounter was recommended over the standard clock because of it's greater precision and that was that, so is this latency issue something a game developer should be worried about?
"... Tests showed that while the precision of these timers was high, the latency was sometimes very much higher than for the std::clock() function, and that is very bad. Furthermore, results using the Win32 API were very dependent on both the compiler (Microsoft and Borland were tested) and the operating system version (Windows NT, Windows 95, etc.) Thus the std::clock() function was much more reliable, and so was retained even on this platform with its own timer API."
Can anyone shed some light by what it means by "higher latency is very bad"? I thought QueryPerformanceCounter was recommended over the standard clock because of it's greater precision and that was that, so is this latency issue something a game developer should be worried about?
What it means is Precision doesn't necesaraly mean accuracy. Although the number 1.2 is more percise than 1, if the latency was too high sending you that number, the existing number could already be at 2. So you could be sitting here with a precise number of 1.2 but it doesn't necesaraly mean it is correct. What you want is the most Accurate Percise number. I havent had an issue with QPC ever being inaccurate so im happy with it.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement