HELP! How to lock FPS Correctly

Started by
18 comments, last by clashie 14 years, 9 months ago
Quote:Original post by phresnel
Personally I am a big fan of fixed timesteps. Glenn Fiedler has a good article about that: Fix your timestep.


it's really a good article!
http://hi.baidu.com/probill
Advertisement
Hi!
What do you experienced programmers think of that?

initializing:
QueryPerformanceFrequency((_LARGE_INTEGER*)(&Sys_Freq));

Main loop:
...	while( delta < Sys_Freq/MAX_FPS ) // maximize fps	{	QueryPerformanceCounter((_LARGE_INTEGER*)(&ticks));		delta = ticks - PrevTicks;	}	PrevTicks = ticks;...


Why is timeGetTime used more in games than QueryPerformanceCounter?
Quote:Original post by szecs
Hi!
What do you experienced programmers think of that?


I don't know if I qualify as "experienced", but what I think is that your approach is a great way of literally "doing nothing" by wasting CPU cycles and pointlessly hogging ressources that could be used by other threads/processes. And since you a) can't rely on being woken up in time even after a sleep(0) (depending on the platform should give up the remaining time slice so someone else can do something useful) and b) can't control when the scheduler will put you to sleep and for how long it's pretty likely that you won't do the next frame when you intended to.

With time based movement that's not a big issue. With fixed time steps, you will correct accumulated errors by occasionally doing two steps. With the "sitting on my thumbs"-approach you will end up waiting longer than intended by 15-100ms (or longer, depending on the platform), pretend that it was exactly 16.6ms and after a few seconds your object will be nowhere near the position it should be.

I might be missing some factor that fixes the issue, but from my understanding the approach is not just wasteful, but also won't work the way you expect.
f@dzhttp://festini.device-zero.de
It's not clear, that you are saying (I'm not so good in English), But this method is precise(ok not too precise, but enough), but wasteful, that's truth (same wasteful as running on full 3000 fps, but my videocard doesn't like it)

I don't use sleep().

The rest of the code:
	__int64 ticks, delta = 0;	while( delta < Sys_Freq/MAX_FPS )	{	QueryPerformanceCounter((_LARGE_INTEGER*)(&ticks));		delta = ticks - PrevTicks;	}	PrevTicks = ticks;	Frame_Per_Sec = (double)Sys_Freq/delta;

for example particle motion:
double dt = 1.0/Frame_Per_Sec;		Particles.vx += accel[0]*dt;		Particles.vy += accel[1]*dt;		Particles.vz += accel[2]*dt;		Particles.x += Particles.vx*dt;		Particles.y += Particles.vy*dt;		Particles.z += Particles.vz*dt;


How can this wasting be replaced when using QueryPerformanceCounter?
For some reason, the VSYNC doesn't work, but that's OFF.

[Edited by - szecs on July 3, 2009 3:40:29 AM]
Oh no, I'm like "abaraba", maybe I should look into the fixed thing.
SORRY!
You CANNOT control the FPS speed of your program on a PC.

If you try to lock the framerate with vsync, I might disable it in my graphics card utility. Or my PC may not be fast enough to keep up.

The gaffer article linked to is encouraging you to fix your logic timestep but to render as fast as possible. It then explains how to use interpolation to smooth out the artifacts this can create.

It really is the best solution. On a PC, trying to run everything at a fixed FPS is simply not workable.
Quote:Original post by szecsWhy is timeGetTime used more in games than QueryPerformanceCounter?

QueryPerformanceCounter is broken on a range of AMD processors, and you can't expect end users to download a driver update to fix it, because most won't. Personally, I think QueryPerformanceCounter is the best option because it has the highest resolution, but you need to use a secondary timing method as well, and compare the delta from both methods, switching to the secondary result if the difference between the two is ever over a certain threshold.

On the topic in general, I just want to add that I agree with those recommending the timing method discussed by Glenn Fiedler. His article should be considered the Gospel on game timing as far as I'm concerned, and it's from a guy who worked on heavy-duty networked physics-laden FPSs, so you know it covers all bases. Time-based movement is fine for very simple games with no networking and no real physics though.
Quote:Original post by szecs
I don't use sleep().


But unless you're on some kind of console with different rules, the OS and the scheduler are deciding when and for how long you get to run. It doesn't matter if you use sleep(), at some point the OS will decide that you've been running long enough and that it's someone elses turn. And nobody knows when you get to continue. So in a way using sleep() (as bad a solution as it is) might still be better than this approach, because at least the scheduler will know when you want to run again.

However, in the rest of your code it seems that you DO use the time that has really passed, so all movements should still be correct.

Just keep in mind that a worst case will look like this:

loop, loop, loop, 1ms left to wait, OS puts you to sleep, 10-200ms later you finally get to continue, delta is now Sys_Freq/MAX_FPS + X (with X being 0-x00ms). Eventually you didn't do any better than someone using sleep() (or even worse), but wasted more ressources.
f@dzhttp://festini.device-zero.de
The while code is only used to limit the framerate, because my demo runs at nearly 3000 fps without it, and my videocard emits a strange noise, I don't know , maybe the cooler.
But it's clear for me now that it isn't a good method I'm using, but I don't really want to go deeper in the thing, I'm only a hobby "programmer". But thanks for the replies anyway.
Quote:Original post by szecs
The while code is only used to limit the framerate, because my demo runs at nearly 3000 fps without it, and my videocard emits a strange noise, I don't know , maybe the cooler.
But it's clear for me now that it isn't a good method I'm using, but I don't really want to go deeper in the thing, I'm only a hobby "programmer". But thanks for the replies anyway.



The noise you hear is 'coil whine'. It's harmless.

This topic is closed to new replies.

Advertisement