This Article IsCreated at 2023-12-20Last Modified at 2023-12-20Referenced as ia.www.b29

Frame Rate Detection in GLFW

First, some background on GLFW and frame rate and event loop.

In GLFW+OpenGL, if the swap interval is set to 1, glfwSwapBuffers will block until next frame is displayed. If it is set to 2, glfwSwapBuffers calls will return on every two frames of the physical display shown.

frame-swap timeline. every frame is drawn by the previous frame.

Then, it is easy to measure the display refresh rate as time difference between glfwSwapBuffers calls.

Since I have already written the code, please refer to it for how exactly the frame-rate detection can be done.

# download code example and run
git clone --branch fps-detector https://git.envs.net/iacore/nanovg-test
cd nanovg-test
zig build run

Not Much Choice for Application Frame Rate

Let’s say your monitor’s refresh rate is 120Hz. Graphical application using the monitor can only display at 120Hz, 60Hz, 40Hz, 30Hz… which is 1, ½, ⅓, ¼ of the original refresh rate.

Some games just have a list of fixed numbers you can choose from. 50Hz on a 120Hz monitor? :S Witchcraft!

Late Swap and GLX_EXT_swap_control_tear

In the original GLX_EXT_swap_control_tear document, it says

When an unsynchronized swap happens, the missed frame will count towards the minimum number of video frames for the next swap.

From the wording, I think it works like this.

if the frame arrives late,

In the code, it looks like this.

    if (c.glfwExtensionSupported("GLX_EXT_swap_control_tear") != 0) {
        c.glfwSwapInterval(-1);
    } else {
        c.glfwSwapInterval(1);
    }

Bonus Point: Ancient Predictive Trick

I read awhile back that if you can predict the time it takes to run game logic and draw content on screen, you can wait just enough to make the game fraction-of-a-frame more responsive. The player inputs received during the “wait” period will be reflected immediately on the next frame.

program go idle to give the user time to perceive the new frame before checking inputs

On newer monitors with fast refresh rates, this is probably not necessary.