Yet Another Question on Game Loop

I'm trying to implement a game loop like Casey's, i.e. a variable fixed timestep, in SDL2. Currently I do something along the lines of:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
SDL_DisplayMode display_mode = {0};
int display_index = SDL_GetWindowDisplayIndex(window);
SDL_GetCurrentDisplayMode(display_index, &display_mode);
u32 refresh_rate = (display_mode.refresh_rate == 0) ? 60 : display_mode.refresh_rate;

if (SDL_GL_SetSwapInterval(-1) < 0) {
  if (SDL_GL_SetSwapInterval(1) < 0) {
   
  }
}

r32 frame_dt = 1 / refresh_rate;


The following situations I have considered:
  1. Refresh rate is a fixed 60Hz. opengl has a reasonable time of 16ms to display buffer
  2. Refresh rate is a fixed 144Hz or 240Hz. 6.9ms or even 4.2ms seems too much of a strain for the average gpu. Is this right? Overcome this with a manual 60fps loop. Will this solution cause tearing?
  3. Refresh rate is variable or cannot be determined. Overcome this with a manual 60fps loop. Will this solution cause tearing?


In situations 2 or 3, the solution I can think of involves using
1
SDL_Sleep(time_to_wait)
According to SDL2, the granularity of this should be assumed to be 10ms. However, it seems likely to me that the situation may arise where we only have to wait say 5ms, i.e. a time below 10ms and will obviously overshoot this. So, it seems the way around this is to do cpu churning:
1
while (need_to_wait) ;
This is obviously not efficient code, yet I can only think of writing platform specific code to set the granularity of the os scheduler as an alternative. Any suggestions and answers to my questions would be most appreciated.
Thank you!

Edited by Sara on Reason: Initial post
Any solution that doesn't use vsync is going to result in screen tearing to some degree. If you want to avoid screen tearing while still trying to run at a custom refresh rate, you can use triple buffering. But keep in mind that you're likely to run into stuttering, especially if your game loop timing is inexact (due to timer granularity for example, as you mentioned), or if the display's refresh rate is not an integer multiple of the custom refresh rate (for example, 60 vs 144).

To avoid both tearing and stuttering on all monitors, you have to run your game loop in lockstep with the refresh rate, e.g. via vsync and double buffering - there is really no other way to do it.
Hi Miles. Thank you for your answers.
I still don't understand how you could lockstep game loop with vsync if the refresh rate is 144Hz or 240Hz as won't the average gpu not have enough time to render so frequently?
Also, how can this be done on variable refresh rate monitors? Does the refresh rate have to be calculated every frame?
These situations don't seem that extraordinary, yet I'm struggling to understand how to handle them effectively without tearing or stuttering.
If someone is buying enthusiast hardware like a high-refresh-rate monitor, it's generally assumed that they know what king of GPU they need to run the games they want to run at that framerate. In my experience, even a mid-range card like an rx580 or gtx1060 can run most games at 1080p at 144hz on decent graphics settings.

If your game is graphically demanding and you're worried about missing frames, then you should write your game loop in such a way that your game tick is no longer tied to your framerate. There are lots of different ways to do this, depending on your game's needs. Whatever you choose is going to be some kind of tradeoff between determinism, consistency, smoothness, accuracy, efficiency, latency, and code complexity.

For variable refresh rate monitors, if you mean something like freesync, then that's not something I have any experience with personally, but my understanding is that you more or less just render at whatever framerate you like and the monitor does its best to accomodate, though I don't know what exactly what the code to do that would look like. If instead you mean monitors that allow the user to explicitly choose the refresh rate, then that's no different from the game's point of view than a normal fixed-refresh-rate monitor.