On Thursday, 22 February 2007 at  6:29, The Watermelon wrote:
> I was browsing through the game loop/frame related source to find out why
> the game uses so much cpu time,then I suddenly found out that this function
> is borked:
> void SDL_framerateDelay(FPSmanager * manager)
> {
>    Uint32 current_ticks;
>    Uint32 target_ticks;
>    Uint32 the_delay;
>    /*
>     * Next frame
>     */
>    manager->framecount++;
>    /*
>     * Get/calc ticks
>     */
>    current_ticks = SDL_GetTicks();
>    target_ticks = manager->lastticks + (Uint32) ((float)
> manager->framecount * manager->rateticks);
>    if (current_ticks <= target_ticks) {
> the_delay = target_ticks - current_ticks;
> SDL_Delay(the_delay); // <- it will never get there
>    } else {
> manager->framecount = 0;
> manager->lastticks = SDL_GetTicks();
>    }
> }

What about (pseudocode)

        current_ticks = SDL_GetTicks()
        frame_ticks = current_ticks - last_ticks;
        actual_ticks = rate_ticks - frame_ticks;
        if (actual_ticks > 0)
                SDL_Delay(target_ticks - actual_ticks);
        last_ticks = current_ticks;

The framecount here is useless, as there's no use in waiting even longer
if you haven't met the previous deadline. Then add an actual framerate
counter in a way that SDL_GetTicks only get called once per frame.

Also the delay should be completely disabled when vsync is active, else
it'll only add more useless waiting.

> it will never get to the line SDL_Delay(the_delay); because SDL_GetTicks()
> gets the time in ms since SDL lib is firstly initialized.
> a wz game frame would probably take quite a few ms so current_ticks is
> always greater than target_ticks(lastticks + 1000/framelimits * 1(always one
> because it gets reseted every time)),this bug will end up as a busy cpu
> loop,that explains why wz uses so much cpu time.

Well, the delay is only meant to be called when there is time per frame
left, so if current_ticks is larger than one frame in the target frame
rate, the game runs too slow and you don't delay.

> basically the SDL tick caculations are pointless,since the framerateDelay is
> called per game cycle.
> so it should be:
> void SDL_framerateDelay(FPSmanager * manager)
> {
> manager->framecount++;
> SDL_Delay((Uint32)manager->rateticks);
> manager->lastticks = SDL_GetTicks();
> }

Now you add a delay of one targetted frame duration each frame, so you
can't ever reach that rate.

I tested the original code, an immediate return and your variant. The
first two both had roughly the same frame rate, yours was a bit slower
(23 fps vs. 17 fps, or 10 fps vs. 8 fps with more units shown, both at
1526x1174, the first scene at 640x480 is 30 fps vs. 20 fps, all with
vsync on. With vsync off the first scene is 35 fps vs. 23 fps (640x480

> with this change my old pc(1.4Ghz) can run a debug build with limited
> optimization flags with 200 gamefps(capped by SDL) with 80%-90% cpu
> usage,while it ran with a optimized-to-death release build with the
> default(60gamefps actually the limits got ignored due to this bug) with 100%
> cpu without this change

Have you actually looked at the framerate with your changes? If you do
not reach the target frame rate it's no surprise when the game runs at
100%, and at less when you add unconditional delays.

"Where humor is concerned there are no standards -- no one can say what is
good or bad, although you can be sure that everyone will.
                -- John Kenneth Galbraith

Warzone-dev mailing list

Reply via email to