QueryPerformanceCounter Question

Started by
14 comments, last by nife 17 years, 8 months ago
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 :(
_______________________"C allows you to shoot yourself in the foot, C++ allows you to re-use the Bullet, Assembly allows you to Create the Bullet from Molecules"
Advertisement
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.

"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin

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...
_______________________"C allows you to shoot yourself in the foot, C++ allows you to re-use the Bullet, Assembly allows you to Create the Bullet from Molecules"
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...
_______________________"C allows you to shoot yourself in the foot, C++ allows you to re-use the Bullet, Assembly allows you to Create the Bullet from Molecules"
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
_______________________"C allows you to shoot yourself in the foot, C++ allows you to re-use the Bullet, Assembly allows you to Create the Bullet from Molecules"
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
Every time you implement a singleton, God kills a kitten. Please, think of the kittens!
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
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...
_______________________"C allows you to shoot yourself in the foot, C++ allows you to re-use the Bullet, Assembly allows you to Create the Bullet from Molecules"

This topic is closed to new replies.

Advertisement