• Advertisement
Sign in to follow this  

QueryPerformanceCounter Question

This topic is 4183 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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 :(

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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...

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by Chase85
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...


May I ask what's the problem if you get a double that's 'too small'?

Anyways, here is how I usually would do it:

void CFrameRate::BeginFrame()
{
QueryPerformanceCounter((LARGE INTEGER*)&i64start);
}
void CFrameRate::EndFrame()
{
QueryPerformanceCounter((LARGE INTEGER*)&end);
long long i64diff = i64end - i64start;
double dFrametime = (double)i64diff / (double)QPCFreq;
double dFPS = 1.0 / dFrametime;
}

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
Not really. QPC is the preferred method of timers in game dev.

Share this post


Link to post
Share on other sites
:) I'm aware of that doc, but I'd like to know why the timer in boost implementation puts down the QPC for reasons cited above. Or are they just talking thru their collective hat(s)? ;)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement