• Advertisement
Sign in to follow this  

QueryPerformanceCounter Question

This topic is 4271 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
Sign in to follow this  

  • Advertisement