Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

frame limiting

Using GLFW
iamwhosiam
2014-06-10
2014-06-20
  • iamwhosiam
    iamwhosiam
    2014-06-10

    i don't know where else to go with this question, but this following code successfully locked the frame rate in sdl.

    when i ported it to glfw it no longer works. the frame rate it locks too is seemingly random. could someone pretty please take a look at this snippet and help me out?

    double wait_time = 1.0 / (targetFrameRate);
    
    if(glfwGetTime() - frame_start < wait_time)
    {
        double dur = (wait_time - (glfwGetTime() - frame_start));
        Sleep((DWORD)(dur * 1000.0 + 0.5));
    }
    
    frame_start = glfwGetTime();
    

    any help is much appreciated :)

     
  • Doug Binks
    Doug Binks
    2014-06-11

    Where are you calling glfwSwapBuffers()? You should do this before you measure the frame_start time, otherwise you're not taking into account the actual rendering time.

     
  • arampl
    arampl
    2014-06-11

    i'm not using sleep function:

    void renderfps(int framerate) 
    { 
        currentTime = glfwGetTime(); 
    
        if(currentTime - lastTime >= 1.0 / framerate) 
        {
            lastTime = currentTime;
            render(); 
        }
    }
    

    currentTime, lastTime - doubles
    render() is my rendering function with glfwSwapBuffers()

    renderfps(60) - 60 fps, called in the main loop

     
  • iamwhosiam
    iamwhosiam
    2014-06-18

    arampl: i tried this technique and it worked but since the process never sleeps it takes up too much cpu and i dont want my game to be a hog ;)

    doug binks: here's my main loop, i took out the non-relevant bits and i think the functions are pretty self explanatory.

    while( !glfwWindowShouldClose(window) )
    {
    tw_time_frame_start(); // get the start time
    handle_events();
    update_func();

    setup_2d_proj();
    
    draw_func();
    
    glfwSwapBuffers(window);
    
    tw_time_update(); // actual sleep code is in here
    tw_input_update();
    

    }

     
  • Doug Binks
    Doug Binks
    2014-06-18

    @iamwhosiam: At brief glance the code seems reasonable, but this is hard to tell without all the code. I'd advise trying to create a small test app, and if that has problems you could share it with me and I could help debug it.

    I would try a few changes.

    Make sure you time the entire loop, so the start time should be measured after the tw_time_update(). This way if you have any time being taken up inside tw_input_update this is being accounted for.

    Write your code for easy debugging, and make sure you don't pass 0 to Sleep. Example below:

    double wait_time = 1.0 / (targetFrameRate);
    double curr_frame_time = glfwGetTime() - frame_start;
    double dur = 1000.0 * ( wait_time - curr_frame_time ) + 0.5;
    DWORD durDW = (DWORD)dur;
    if( durDW > 0 ) // ensures that we don't have a dur > 0.0 which converts to a durDW of 0.
    {
        Sleep( durDW  );
    }
    
    double frame_end = glfwGetTime();
    // here you could print to file or OutputDebugStream curr_frame_time, frame_end - frame_start and dur.
    frame_start = frame_end;
    

    Note that there is no guarantee that Sleep will return exactly on the time you require. It's possible your odd frame times were due to passing in a 0 value to Sleep, which causes the thread to give up it's time slice.

     
  • Doug Binks
    Doug Binks
    2014-06-18

    Oops - forgot DWORD is unsigned. Make sure to use a signed integer type when converting from double as it's undefined as to what happens for negative values on cast to unsigned int.

     
  • iamwhosiam
    iamwhosiam
    2014-06-20

    ok i made a test app that just creates a window then just calculates frame rate and sleeps and it's still doing it.

    ive uploaded it to http://pastebin.com/E1kGThRn

    one question i have, is should i be setting the swap interval to zero or maybe one? or just leave it default? having vsync on would be cool but im not sure if it would mess with the frame rate. also some peoples computers might just force it off anyway so, just leave it default and make em both work?

     
  • Doug Binks
    Doug Binks
    2014-06-20

    This code works for - I can change the target_frame_rate and never get more, though can get less obviously.

    Note that glfwSetWindowTitle can be expensive, so I moved this into calc_frame_rate inside the if(elapsed>1) so as to change the title only once per second.

    Preferably you should use something like FRAPS or gDEBugger to check frame rate, and this shows a nice solid flat FPS graph for me.

     
  • iamwhosiam
    iamwhosiam
    2014-06-20

    ok, thank u very much for your time :)

     
  • Doug Binks
    Doug Binks
    2014-06-20

    On the question of vsync, I would make that user configurable. I prefer having it on, but some don't. Also note the documentation on glfwSwapInterval and negative swap intervals which can work well.

    Note on Windows the _GLFW_USE_DWM_SWAP_INTERVAL definition (requires a recompile of glfw) controls whether to ignore swap interval settings when the DWM compositing is on, and as you say many drivers can override the application settings.