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?
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.
@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.
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.
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?
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.
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.