Monitor is set to 60 Hz, but when I run my game higher than 60 FPS it looks smoother. How can that be?

Started by
6 comments, last by m_waddams 2 months, 2 weeks ago

Currently I'm defaulting to 60 FPS, so a simplification of what I'm doing looks like this:

float refreshRate = 1.0f / 60.0f;

while (!quit)
{
    timeAccumulator += timer.tick();

    if (timeAccumulator > refreshRate)
    {
        render();
    
        timeAccumulator -= refreshRate;
    }
}

Which does what you would expect: render the game roughly every 0.0167 seconds, which I confirmed by logging the time between render calls to the console to ensure there were no large outliers. However, when I remove the FPS cap, and let it render on every iteration of the main loop, it scrolls noticeably smoother, which I did not expect, because my monitor is set to a 60 Hz refresh rate. My understanding is that even though the game might try to render faster than 60 FPS, it should not visually be any different because it is limited by the speed of the monitor, correct? So what am I misunderstanding here to account for this?

Advertisement

It would be rather amazing if your own refresh rate matched the vertical blank of the monitor 🙂
Since it won't, you are actually losing frames.

I see. How is this corrected for then? Do people refresh at a slightly higher rate than the monitor to account for this? Or is there a more precise solution?

Depends on how good you are at finishing in time.

In principle, finishing a single nano-second before the next monitor sync is good, but that is a lot harder to achieve than being ready 4 milliseconds before the deadline.

@JackOfCandles Most people use the vsync. That gives you your timer automatically. If you then see your graphics stutter, you know your update loop takes too long, and either need to optimize, or lower your framerate. Keep in mind that if you blindly follow vsync your game runs at the monitor's speed, so on 144Hz will probably be unplayable 🙂

EDIT: DISREGARD! I found the answer, my nvidia settings were turning VSync off, instead of “Use the 3D application setting”. I will leave this up however in case it may help someone else in the future. I will add, I am appearing to get a stutter now, but I think that's due to a flaw in my code, so I will continue to investigate that.

m_waddams said:

@JackOfCandles Most people use the vsync. That gives you your timer automatically. If you then see your graphics stutter, you know your update loop takes too long, and either need to optimize, or lower your framerate. Keep in mind that if you blindly follow vsync your game runs at the monitor's speed, so on 144Hz will probably be unplayable 🙂

Ah, that makes sense, thank you! I'm using OpenGL + SDL, and I did a little googling and found this: https://wiki.libsdl.org/SDL2/SDL_GL_SetSwapInterval​ which sounds like it's what I want. I removed the FPS cap in my own code, and added in a call to that function (which is returning a success result), like this:

if (SDL_GL_SetSwapInterval(1) == -1) {
    std::cout << "Failed to set swap interval with error: " << SDL_GetError() << std::endl;
}

However, when I use FrameView to display the frame rate, it is still showing an FPS in the thousands, whereas when I start various games from my steam library, the overlay display on those shows it locked in at 60 FPS. Here's a screenshot of a test app I made with nothing but a square and some diagnostic text (ignore the FPS = 60 in the top right corner, that's coming from the setting that is no longer being used in my code). Is there maybe something I'm still missing? Why would that not be locked to 60 FPS like everything else?

I don't know FrameView , but it would seem pretty pointless to display the capped FPS. I think it's displaying how many frames it actually rendered, not how many are sent to the monitor. (Then again, why would it render so many unnecessary frames, hmm)
Turning on vsync only caps (only sends on vsync), it will not change your main loop (thank heavens 🙂)

I don't know how SDL works, but maybe this thread helps.

This topic is closed to new replies.

Advertisement