How to compute frame rate

Started by
8 comments, last by sunrisefe 13 years, 11 months ago
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.
Advertisement
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?
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.
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 :-)
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.
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 timeinline 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]
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_;};
I trust exceptions about as far as I can throw them.
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.
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.htmlstruct 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_;}
I trust exceptions about as far as I can throw them.
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.

This topic is closed to new replies.

Advertisement