QueryPerformanceCounter Question
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 :(
Are you trying to convert the value to a double or a float? Neither have enough precision to substract two close-together QPC results.
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 Chase85CFrameRate::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...
I went with this for right now
if (dFrameTime < 0.001f) dFrameTime = 0.001f;
It's lying to itself... I wish i could be completely accurate with nothing on the screen... if (dFrameTime < 0.001f) dFrameTime = 0.001f; brings the FPS to lock at 999.99
if (dFrameTime < 0.001f) dFrameTime = 0.001f;
It's lying to itself... I wish i could be completely accurate with nothing on the screen... if (dFrameTime < 0.001f) dFrameTime = 0.001f; brings the FPS to lock at 999.99
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...
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement