0
\$\begingroup\$

My game loop currently looks something like this:

while (!quit) {
    takeInput(); // Input is sampled however fast loop can run

    time_now = get_time()
    time_passed += (time_now - time_prev);
    time_prev = time_now;

    while (time_passed > SOME_TIME) {
        update(); // Update is done over fixed time-step for determinism
        time_passed -= SOME_TIME_STEP; // This time step is less than or equal to SOME_TIME
    }
    render(time_passed); // Render using interpolation from previously updated position and velocity
}

Basically, I take input as fast as I can, run the movement and physics only in discreet chunks of time after certain period and interpolate the difference in the renderer. The renderer is set to draw at Vsync (using SDL_GL_SetSwapInterval(-1)) and currently, the value of SOME_TIME is set so that update() runs at half of display's refresh frequency (but with a minimum bound of SOME_TIME_STEP which is set to 5 millisecond).

The problem is that I am running the renderer as fast as I can which is submitting frames continuously. Because I am currently loading a test level, the game loop is basically finishing up in a few microseconds (unless there is something wrong with how I am calculating time too). As far as I understand, my program will submit frames to the driver way faster than it is going to draw (because of Vsync) and this should lead to some type of periodic locking up/lagging.

So my question is, how to I prevent this? Should I put the render call in a time bound loop too just like update()? Should I call sleep() manually instead of relying on graphics driver for Vsync?

\$\endgroup\$
2
  • \$\begingroup\$ sleep guarantees that the thread will sleep at least the amount of time you ask for, not exactly the amount of time you ask for. The delay is generally longer than what you ask for, so it should not be used. Perhaps limiting the amount of render call to one very 1/60 th of a second would be enough? \$\endgroup\$
    – Vaillancourt
    Commented Oct 8, 2016 at 5:17
  • \$\begingroup\$ You can use a sync object in opengl to find out when the gpu has finished processing. You can find more information about it here: > khronos.org/opengl/wiki/Sync_Object Also see this similar question: > stackoverflow.com/questions/21557279/… \$\endgroup\$
    – Kyy13
    Commented Feb 22, 2018 at 15:46

2 Answers 2

1
\$\begingroup\$

As far as I understand, my program will submit frames to the driver way faster than it is going to draw (because of Vsync) and this should lead to some type of periodic locking up/lagging.

Not it wont. The video driver doesn't buffer frames indefinitely.

The video driver buffers at most 1 frame (double buffering) or 2 frames (triple buffering).

If your render loop attempts to draw faster than the display the video driver can display it will sleep/hold your thread until the vblank happens and a render back buffer becomes available.

Which is at most 1 frame time (eg: 16ms at 60Hz).

You don't need to put your thread to sleep, the video driver takes care of that.

If you put your thread to sleep manually the video driver can't force the OS to wake up your thread when the vertical blank signal happens because it doesn't know that's what you're waiting for. That could cause your app to sleep for easily 10ms longer than it should.

\$\endgroup\$
0
\$\begingroup\$

In SDL2 is standard practice as far as I know to use an SDL_Delay to delay the game loop after you've completed all rendering of textures and game logic.

Here is code that will delay you to a 60 FPS game, you can adjust the number accordingly:

#define FRAMES_PER_SECOND 60

uint32_t timer = 0;

while(1)
{
    /* Game logic... rendering... */

    if(SDL_TICKS_PASSED(timer, SDL_GetTicks()))
    {
        SDL_Delay(timer - SDL_GetTicks());
    }

    /* Global Timer */
    timer = SDL_GetTicks() + (1000 / framesPerSecond);
}

Because SDL_GetTicks() can overflow, you must use SDL_TICKS_PASSED which is a builtin SDL2 macro based that allows integer overflow into the equation.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .