Sign in to follow this  
sunrisefe

How to compute frame rate

Recommended Posts

sunrisefe    102
I use SetTimer(0,1000/30,NULL) and render scene in OnTimer function, where is wrong with following code to calculate PFS? DWORD preTime,curTime,pfs; preTime = GetTickCount(); //here is the code to render scene curTime = GetTickCount(); pfs = 1000 / (curTime - preTime); when I debug the code, error is "Integer division by zero", how to fix it? Thank you.

Share this post


Link to post
Share on other sites
Wkter    100
I just tried adding your code to my existing project, I get no error.
Maybe you have another division in your code that causes the error?

Share this post


Link to post
Share on other sites
Erik Rufelt    5901
GetTickCount probably doesn't have high enough precision, so if your framerate is high enough curTime and preTime will have the same value, which will give you a division by zero. For example if GetTickCount returns milliseconds, a framerate of above 1000 will give this error.

From the documentation for GetTickCount:
Quote:
The resolution of the GetTickCount function is limited to the resolution of the system timer, which is typically in the range of 10 milliseconds to 16 milliseconds. The resolution of the GetTickCount function is also affected by adjustments made by the GetSystemTimeAdjustment function.


So it would be enough with 100 FPS to give you this error. You could use timeGetTime together with timeBeginPeriod to get 1 ms precision, or QueryPerformanceCounter for very high precision.

Share this post


Link to post
Share on other sites
Slyfox    157
I would suggest that your curtime and pretime variables are returning the same values as GetTickCount is not very precise with modern cpus resulting in a devision by zero hence the error. Try setting a breakpoint and stepping through to check the values (f9 - set break point and f10 to step through) this is assuming you are using visual studio.

A much better and more precise way to calculate frame rate if you are using DirectX is to use the functions QueryPerformanceCounter() and QueryPerformanceFrequency() you can find out all you need about these functions within the help files of visual studio.

edit: oops someone beat me to it :-)

Share this post


Link to post
Share on other sites
Mussi    4407
Also you are not calculating frames per second, as the name says: count the number of frames your draw in one second. So if this is to display FPS you should count the frames for a second, if this is to have frame independent movement/animation than you should do what you did, except for the 1000 / dt and start using a high precision timer like QueryPerformanceCounter.

Share this post


Link to post
Share on other sites
sunrisefe    102
Thank you all very much.
If use QueryPerformanceFrequency and QueryPerformanceCounter to get high precision time, following code is right? Furthermore, I use SetTimer(0,1000/30,NULL) and render scene in OnTimer function in MFC, why the PFS is higher than 200 but the animation is very slow? I put SetTimer(0,1000/30,NULL) in OnCreate(LPCREATESTRUCT lpCreateStruct) and render scene in OnTimer(UINT_PTR nIDEvent), does that matters with animation speed? Why the PFS is high while the animation is slow? Thank you.

//here is OnTimer
<div class="source">
 
void Myclass::OnTimer(UINT_PTR nIDEvent)
{
//calculate PFS
float currentTime,preTime,pfs;
preTime = GetTime();
//here is the code to render scene
currentTime = GetTime();
PFS = 1.f/(currentTime - preTime);
}


//here is the func to get high precision time
inline float GetTime()
{
static BOOL init = FALSE;
static BOOL hires = FALSE;
static __int64 freq = 1;
if(!init)
{
hires = QueryPerformanceFrequency((LARGE_INTEGER *)&freq);
if(!hires)
freq = 1000;
init = true;
}

__int64 now;

if(hires)
QueryPerformanceCounter((LARGE_INTEGER *)&now);//
else
now = GetTickCount();

return (float)((double)now / (double)freq);
}




[Edited by - sunrisefe on April 24, 2010 11:21:04 PM]

Share this post


Link to post
Share on other sites
Storyyeller    215
Well that looks correct, although I'm not sure why hires is set to false.

You may also want to stick it in a class, because that way you can measure the time of different things simultaneously, rather then having a single global timer.

Here's a version I found online which works great for me.

#include <windows.h>

/// Create a Timer, which will immediately begin counting
/// up from 0.0 seconds.
/// You can call reset() to make it start over.
class Timer {
public:
Timer() {
reset();
}
/// reset() makes the timer start over counting from 0.0 seconds.
void reset() {
unsigned __int64 pf;
QueryPerformanceFrequency( (LARGE_INTEGER *)&pf );
freq_ = 1.0 / (double)pf;
QueryPerformanceCounter( (LARGE_INTEGER *)&baseTime_ );
}
/// seconds() returns the number of seconds (to very high resolution)
/// elapsed since the timer was last created or reset().
double seconds() {
unsigned __int64 val;
QueryPerformanceCounter( (LARGE_INTEGER *)&val );
return (val - baseTime_) * freq_;
}
/// seconds() returns the number of milliseconds (to very high resolution)
/// elapsed since the timer was last created or reset().
double milliseconds() {
return seconds() * 1000.0;
}
private:
double freq_;
unsigned __int64 baseTime_;
};

Share this post


Link to post
Share on other sites
sunrisefe    102
Thank you, Storyyeller. Now it works when get high precision time, but I use SetTimer(0,1000/30,NULL) and render scene in OnTimer function in MFC, why the PFS is higher than 200 but the animation is very slow? I put SetTimer(0,1000/30,NULL) in OnCreate(LPCREATESTRUCT lpCreateStruct) and render scene in OnTimer(UINT_PTR nIDEvent), does that matters with animation speed? Why the PFS is high while the animation is slow? Thank you.

Share this post


Link to post
Share on other sites
Storyyeller    215
I just realized that the original code has the problem of including windows.h in a header, which leads to macro problems and namespace clashes everywhere.

Here's my attempt to fix it. Did I do it right?


#pragma once

//This code is a modified version of the code from http://www.mindcontrol.org/~hplus/misc/simple-timer.html

struct QPC_DataMembersStruct;

/// Create a Timer, which will immediately begin counting
/// up from 0.0 seconds.
/// You can call reset() to make it start over.
class QPCTimer
{
public:
QPCTimer();
~QPCTimer();

/// reset() makes the timer start over counting from 0.0 seconds.
void reset();

/// seconds() returns the number of seconds (to very high resolution)
/// elapsed since the timer was last created or reset().
double seconds();

/// seconds() returns the number of milliseconds (to very high resolution)
/// elapsed since the timer was last created or reset().
double milliseconds() {return seconds() * 1000.0;}

private:
QPC_DataMembersStruct* opaque;
};




#include "timer.h"

#include <windows.h>

struct QPC_DataMembersStruct
{
double freq_;
unsigned __int64 baseTime_;
};

QPCTimer::QPCTimer(): opaque(new QPC_DataMembersStruct())
{
reset();
}

QPCTimer::~QPCTimer()
{
delete opaque;
opaque = NULL;
}

void QPCTimer::reset()
{
unsigned __int64 pf;
QueryPerformanceFrequency( (LARGE_INTEGER *) &pf );
opaque->freq_ = 1.0 / (double)pf;
QueryPerformanceCounter( (LARGE_INTEGER *) &(opaque->baseTime_) );
}

double QPCTimer::seconds()
{
unsigned __int64 val;
QueryPerformanceCounter( (LARGE_INTEGER *)&val );
return (val - opaque->baseTime_) * opaque->freq_;
}

Share this post


Link to post
Share on other sites
sunrisefe    102
Storyyeller, yes it works to get time. Only 5 seconds return when render on frame, but the animation moves very very slowly, I cannt figure out what is wrong.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this