Sign in to follow this  

framerate calculation error - alternative way?

This topic is 3311 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

hi, my almost finished game do all the graphic-stuff framerate independent. so i have to calculate the framerate wich should be no problem. but i have a mysterious (for me ;) problem doing this. Here my code for calculating the framerate:
void TicTimer(void) {
	double static FPS, tmpFPS;
	double static AvarageFPSStartTime;
	LONGLONG static lastFrame;
	LONGLONG CurrentFrame;
	double static AvarageFPSCounter;

	if (freq > 0) {
		QueryPerformanceCounter((LARGE_INTEGER*)&CurrentFrame);
		elapsed = CurrentFrame - lastFrame;
		if(elapsed > 0) FPS = (double)((double)freq / (double)elapsed);
		else FPS = 1;
	} else {
		timeBeginPeriod(1);
		CurrentFrame = timeGetTime();
		timeEndPeriod(1);
		elapsed = CurrentFrame - lastFrame;
		if(elapsed > 0) FPS = 1000.0/elapsed;
		else FPS = 1;
	}
	
	fFrameRate = fFrameRate*0.9f + FPS*0.1f;

	lastFrame = CurrentFrame;
}

i think this should be right. in my game i do some realtime sound-synthesis (its a sound-toy-game). when i exclude the soundsynthesis in my code the framerate-calculation is stable (60 frames like my monitor) but when i do the synthesis the framerate is rising! and changing all the time. but when i measure the framerate with an external tool (FRAPS) it shows allways the constant 60 frames which is right. so there must be an error in my calculation code but i can't find it. can anybody help me? i doing all the stuff in c++/directx. is there any other way for calculating the framerate? do anybody know how fraps is doing this?

Share this post


Link to post
Share on other sites
What is 'freq'?

When you say your framerate is rising and changing all the time, could you give a few more details. What range of values is it changing between, or how far / fast is it rising?

Share this post


Link to post
Share on other sites
freq is the performance-counter frequency at the start of the game. so if freq is 0 this means that the pc has not any performance-counter.
but that does not matter even with the normal timeGetTime the framerate is changing.
the framerate is changing very fast (a few times per second) between 60 and round about 170 frames. which is very strange because without the soundsynthesis switched on the framerate is stable at the monitor frequency (60 frames).

Share this post


Link to post
Share on other sites
even without the performance counter (by using timeGetTime) the framrate is changing. how could i manipulate the performance counter?

the way i doing the framerate calculation should be ok!? then the sound- synthesis must distorting the measuring of the time for one frame in any way!?
i dont know what to do. ok, i will have one more look at my code.

Share this post


Link to post
Share on other sites
without vsync the framerate is also changing between 300 and 500 fps when the fraps fps counter is almost stable at 330 fps.

strange thing i tested:
in every frame the checkDSStream function is testing if the directsound ringbuffer is ready to fill. with the directsound-methode "GetCurrentPosition" i get the current soundcard-read-position of my ringbuffer. if the readposition is in the first half of the buffer, the second half of the buffer will be filled with data and vice versa. the DSStreamData function is filling the buffer. the for loop represent all the sound calculations (i replaced the original calculations with this useless calculation only for testing). the loop should waste time.


void checkDSStream() {
DWORD playPos;

lpDSBuffer->GetCurrentPosition(&playPos,NULL);

if(playPos < 8192*2 && soundBufferSwap == 0) {
soundBufferSwap = 1;
for(long i=0;i<10000000;i++) dummy = (i*0.01f)*(i*0.01f)*(i*0.01f)*(i*0.01f);

// DSStreamData(1);

} else if(playPos >= 8192*2 && soundBufferSwap == 1) {
soundBufferSwap = 0;
for(long i=0;i<10000000;i++) dummy = (i*0.01f)*(i*0.01f)*(i*0.01f)*(i*0.01f);

// DSStreamData(0);
}
}



when i commend the DDStramData (like in the code above) i obviously can't hear any sound. but the framerate is also changing. when i rise the number of loopcycles of the for-loop the framerate is also rising.

if i'm changing the checkDSStram() like this (for testing):
void checkDSStream() {
DWORD playPos;

lpDSBuffer->GetCurrentPosition(&playPos,NULL);
for(long i=0;i<10000000;i++) dummy = (i*0.01f)*(i*0.01f)*(i*0.01f)*(i*0.01f);

}


the framerate is falling when i'm rising the loopcycles like normal. the only difference between the codes is that in the top code the calculation is not done every single frame (the soundbuffer will not be filled every frame only when the readposition has passed half the buffer) and in the second code the calculation is done every frame.

so how could this cause the framerate risings?
i would be very pleased if anybody have a suggestion.



Share this post


Link to post
Share on other sites
What's this for?

fFrameRate = fFrameRate*0.9f + FPS*0.1f;


It looks a bit dubious to me. Is it meant to 'smooth out' the framerate? If you want an FPS counter that is nice to look at, I just count how many ticks run in a second and update the counter at the end of that second. The number only changes once a second so it's nice to look at (not some flickering number).

Otherwise, the immediate framerate is 1 divided by the time step, which it looks like you're doing correctly.

Share this post


Link to post
Share on other sites
fFrameRate = fFrameRate*0.9f + FPS*0.1f;

is for smoothing. it's the eaysiest way. of course you can do it in some other way. but that doesn't matter.

now i have isolated my problem. when i'm doing some calculations every single frame like this:

for(long i=0;i<10000000;i++) dummy = (i*0.01f)*(i*0.01f)*(i*0.01f);

the framrate is going down to stable 25fps (on my pc). but when i do this calculation evere 10ths frame (or something like that but not every single frame) the framerate is rising and changing all the time. i suppose the framerate should still going down but it is rising and going wild. how could that be?

and of course the framerate shown by the external FRAPS framerate counter is allways stable 60 frames. only when i doing the calcultion every single frame the framerate is also going down to 25fps.

do anybody have any suggestions?

Share this post


Link to post
Share on other sites
ok, here is the final problem:

i saved all the frametimes in a file. when i dont't do this stupid calculation:

for(long i=0;i<10000000;i++) dummy = (i*0.01f)*(i*0.01f)*(i*0.01f);

the time for doing one frame is around 20ms. when i do this calculation every 5th frame the time for rendering this frame will cause 100ms. that obviously ok. but the frame after this stupid calculation will only cause 1ms and so the framerate is rising up to 1000fps in this frame.

how could that be?

Share this post


Link to post
Share on other sites
I may be off, but this is what it looks like from your posts:

Your first checkDSStream listing indicates to me that something like this is happening:
Frame 1: Stream. Takes 16.7 ms.
Frame 2: No need to stream yet. Takes 1 ms.
Frame 3: No need to stream yet. Takes 1 ms.
Frame 4: Stream. Takes 16.7 ms.
etc.

So essentially, since you're calculating your frame rate by the amount of time each frame takes, and NOT by the number of... well... frames in a second... your getting wide fluctuations depending on how long that frame takes to do what it does... obviously it will take longer on the frames that are doing more, and so they will indicate a lower fps. As someone else suggested, try just counting the number of frames each second and you should see results similar to what fraps is giving you.

Also... that for loop you have with the dummy variable... are you doing your timings in a release build (you probably should only time things in release build anyway...) Because if you are, that for loop is most likely just going to get optimized out completely. If you're not... your timings don't really mean much.

Cheers
-Scott

Share this post


Link to post
Share on other sites
Quote:
Original post by spuckfunkel
ok, here is the final problem:

i saved all the frametimes in a file. when i dont't do this stupid calculation:

for(long i=0;i<10000000;i++) dummy = (i*0.01f)*(i*0.01f)*(i*0.01f);

the time for doing one frame is around 20ms. when i do this calculation every 5th frame the time for rendering this frame will cause 100ms. that obviously ok. but the frame after this stupid calculation will only cause 1ms and so the framerate is rising up to 1000fps in this frame.

how could that be?


Remember that the amount of time it takes to do the next frame is dependent on many things:
- What code are you executing this frame? This is the obvious one, and usually the more code you execute, the longer the frame will take.
- What are the conditions to execute code. Do you skip doing things if, say, a directsound buffer isn't ready to be streamed to yet? If so, obviously you execute less code this frame.
- Your local multitasking OS. Not a very big one, but it could make a difference. Does the OS switch to another thread and do stuff and switch back? This will cause slight fluctuations naturally. Are they big enough to matter? Depends on many things...
- And other stuff too. What if you miss a vsync and your frames are aligned to wait on the next vsync. If you miss it by 10 ns you will still have to wait on the next one. What if you do all your calculations and the next vsync is ready right then and there. This frame will take less time than the one that you had to wait on the vsync to come.

You should really probably time your FPS in a different manner. If you don't want to update only once per second, at least accumulate a few of them and update your FPS every 10 frames or something. This will give you much better smoothing and more accurate results.

Right now you're not really measuring FPS... just time-per-frame scaled to the number of the latest interval per second...

Cheers
-Scott

Share this post


Link to post
Share on other sites
wow, was it realy so easy? i recoded the fps part. now i'm mesauring how many frames are build per second like this:

void TicTimer(void) {
int static tickCount;
DWORD static lastTime;
DWORD currentTime;

currentTime = timeGetTime();
tickCount++;
if(currentTime > lastTime+1000) {
lastTime = currentTime;
fFrameRate = tickCount;
tickCount = 0;
}
}



and wow, now i have always a stable framecount (60fps) like FRAPS. what a shame. it was so easy. only a logical error by myself.

is the timeGetTime() (with timeBeginPeriod(1)) function ok for doing things like this? or should i use the performance counter? can i set the period of the timeGetTime counter by timeBeginPeriod(1) at the start of my game for all the time or should i set the period before every single call of timeGetTime like this:

timeBeginPeriod(1);
currentTime = timeGetTime();
timeEndPeriod(1);



thanks everyone for your comments. i'm very pleased that this community exist. have a nice day (what a good feeling to solve a problem).

anybody who are interested in what i'm doing, here are some videos of my game:

http://de.youtube.com/watch?v=4HE3gZtO734<
http://de.youtube.com/watch?v=FsmhVlTpTsc<
http://de.youtube.com/watch?v=mc7GzIPJudw<
http://de.youtube.com/watch?v=YxPORaU8bMU<

Share this post


Link to post
Share on other sites
Quote:
Original post by spuckfunkel
anybody who are interested in what i'm doing, here are some videos of my game:
http://de.youtube.com/watch?v=4HE3gZtO734<
http://de.youtube.com/watch?v=FsmhVlTpTsc<
http://de.youtube.com/watch?v=mc7GzIPJudw<
http://de.youtube.com/watch?v=YxPORaU8bMU<
I don't know exactly what it does, but it is certainly very pretty.

Share this post


Link to post
Share on other sites
Quote:
Original post by spuckfunkel
fFrameRate = fFrameRate*0.9f + FPS*0.1f;

is for smoothing. it's the eaysiest way.


I believe you probably wanted something more like an exponential moving average:

fFrameRate += k * (FPS - fFrameRate);

where k is a constant coefficient (0..1) which controls the rate of decay of the importance of past observations. The most recent observations have the most significance, but no observation is truely discarded.

Share this post


Link to post
Share on other sites

This topic is 3311 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.

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