1

Coming from a basic understanding of OpenGL programming, all required drawing operations are performed in a sequence, once per frame redraw. The performance of the hardware dictates essentially how fast this happens. As I understand, a game will attempt to draw as quickly as possible so redraw operations are essentially wrapped in a while loop. The graphics operations (graphics engine) will then be optimised to ensure the frame rate is acceptable for the application.

Graphics hardware supporting Vertical Synchronisation however locks frame rates to the display rate. A first question would be how should a graphics engine interact with the hardware synchronisation? Is this even possible or does the renderer work at maximum speed and the hardware selectively calls up the latest frame, discarding all unused previous frames..?

The motivation for this question is not that I am immediately intending to write a graphics engine, instead am debugging an issue with an existing system where the graphics of a moving scene appear to stutter onscreen. Symptomatically, the stutter is slight when VSync is turned off, when it is turned on either there is a significant and periodic stutter or alternatively the stutter is resolved entirely. I am somewhat clutching at straws as to what is happening or why, want to understand some more background information on graphics systems.

Summarily the question would be on how one is expected to interact with hardware redraw events and if that is even possible. However any additional information would be welcome.

J Collins
  • 2,106
  • 1
  • 23
  • 30

2 Answers2

1

A first question would be how should a graphics engine interact with the hardware synchronisation?

To avoid flicker modern rendering systems use double buffering i.e. there are two color plane buffers and after finishing drawing to one, the display readout pointer is set to the finished buffer plane. This buffer swap can happen synchronized or non-synchronized. With V-Sync enabled the buffer swap will be synchronized and the rendering thread blocks until the buffer swap happened.

Since with double buffering mandates buffer swaps this implicitly introduces a synchronization mechanism. This is how interactive rendering systems lock onto the display refresh.

Symptomatically, the stutter is slight when VSync is turned off, when it is turned on either there is a significant and periodic stutter or alternatively the stutter is resolved entirely.

This sounds like a badly written animation loop that assumes constant framerate locked onto the display refresh rate, based on the assumption that frames render faster than a display refresh interval and the buffer swap can be issued in time for the next retrace to happen.

The only robust way to deal with vertical synchronization is to actually measure the time between frame renderings and advance the rendering loop by that amount of time.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • 1
    Just to add a little footnote to this answer, there's a great analysis of time-steps here http://gafferongames.com/game-physics/fix-your-timestep/. The idea is to fix the time-step, executing multiple iterations of it (linearly interpolating between each) within the time available. – Robinson Apr 12 '13 at 15:37
  • Thanks datenwolf, that description of blocking the rendering thread perfectly answers the question. To be crystal clear though, you're saying the game's rendering loop will continue to operate in an unconstrained fashion, but each update will be blocked by the hardware, effectively causing the loop to synchronise with it. Also Robinson that was a good read, had only hypothesised about the possibility of frame interpolation before now, that is really cool. – J Collins Apr 13 '13 at 17:09
  • @JCollins: If you conclude each game loop iteration with a swap buffers, it will block there until the buffer swap happens, which can be synchronized to display refresh. so it depends on how you define "unconstrained". You'll definitely observe some delay in loop execution. – datenwolf Apr 13 '13 at 17:27
0

This is a guess, but:

The Problem Isn't Vertical Synchronization

I don't know what OS you're working with, but there are various ways to get information about the monitor and how fast the screen is refreshing (for the purposes of this answer, we'll assume your monitor is somewhat recent and redraws at a rate of 60 Hz, or 60 times every second, or once every 16.66666... milliseconds).

Renderers are usually paired up with an "Logic" side to the application: input, ui calculations, simulation running, etc. etc. It seems like the logic side of your application is running fast enough, but the Rendering side - i.e., the Draw Call as its commonly summed up into - is bounding the speed of your application.

Vertical Synchronization can exacerbate this in that if your Draw Call is made to happen every 16.66666 milliseconds - but it takes much longer than 16.666666 milliseconds - then you perceive a frame rate drop (i.e. frames will "stutter" because they're taking too long to produce a single frame). VSync - and the enabling or disabling thereof - is not something that bottlenecks your code: it just says "hey, since the Hardware is only going to take 1 frame from us every 16.666666 milliseconds, why make more draw calls than just one every 16.66666 milliseconds? As long as we do one draw call once for every passing of this time, our application will look as fluid as possible, and we don't have to waste time making more calls than that!"

The problem with that is that it assumes your code is going to run fast enough to make it in those 16.6666 milliseconds. If it does not, stuttering, lagging, visual artifacts, frozen frames, and other things manifest themselves on screen.

When you turn off VSync, you're telling your Render Call to be called as often as possible, as fast as possible. This may give it some extra wiggle room alongside the Logic call to get a frame rendered, so that when the Hardware Says "I'm gonna take a picture and put it on the screen now!" it's all prettied up, just in time, to get into posture and say cheese! (though by what you say, it barely makes it).

What To Do:

Start by profiling your code. Find out what functions are taking the most time. Judging by the stutter, something in your code is taking longer than is expected and is giving you undesirable performance. Make sure to profile first to find the critical sections of where you're burning away time, and figure out how to keep it correct and make it just as fast. You may want to figure out what's being called in the Render Call and profile the time it takes to complete one cycle of that specifically. Then time the Logic call(s) and see how long it takes to execute those as well. Then, chop away.

Good luck!

  • Thanks ThePhD, I have access to a previous generation of code (which I can only assume is logically similar to the current generation.) We are writing the underlying logic for updating the scene, and I can see that the loop our logic operates in (@~1000Hz) is asynchronous from the main loop. I am yet to find the top-most drawing routine to evaluate whether it is synchronous with refresh or no, and don't know what the 'right' strategy is either way. Environment is Windows 7 rendering at 60Hz. As for frame rates, the only information I can gather is that with VSync off I see 90-400FPS. – J Collins Apr 12 '13 at 12:33