Jump to content
  • Advertisement
Sign in to follow this  
Chase85

QueryPerformanceCounter Question

This topic is 4455 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
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!