1

In the game our Internet-assembled team is programming, we're assuming everybody from our audience will have WAY over fullspeed in the game.

So, to save video RAM, and hopefully give a little more idle time to the graphics card, using V-sync without double buffering would be our best option. So, in OpenGL, we need to know how to do that.

From my understanding, V-sync is when the graphics card is paused once it's done rendering a single frame until that frame has finished being sent to the display device. Double buffering doesn't pause render operations (or maybe it does, or maybe it's implementation-specific; not sure), because it instead draws to a second buffer before copying to the framebuffer, so that the monitor either gets the full frame or no new frame at all (specifically, the last stored image in the framebuffer). Well, we don't need that feature, as long as the graphics card just writes to the framebuffer ONLY when it damn needs to.

This is a pretty slow online game (But it's VERY creative ^_^). There's very little realtime action. Therefore, extremely precise user input is not a necessity; it can be captured from the OS as a single unit any time before rendering a frame.

So, in order to do EXACTLY this, I need to be able to get a "Frame has finished sending to monitor" message from OpenGL. Is it possible? If not, what is the best alternative?

The game is being programmed for Windows only at the moment but should have work done for Linux in a few months.

Andrew D'Addesio
  • 347
  • 3
  • 12
  • Video cards are designed to have enough memory for double-buffering. All games out there use it. Moreover, the driver layers do not give you direct control over "when the frame is sent to the monitor". For that matter, are you ready to handle the cases with multiple monitors ? are you willing to only work fullscreen ? – Bahbar Feb 04 '11 at 08:44

2 Answers2

9

You suffer from a misconception what V-Sync does. There's a part in video RAM that's continously sent to the display device at a constant rate, the frame refresh rate. So immediately after a full frame has been sent the next frame gets sent, after a very short blank time. But the time between sending frames is far shorter than the time it takes to send the full frame.

What happens without V-Sync is, that operations on the contents of the framebuffer get visible, for example if the frame is filled alternating with red and green and there's no V-Sync you'll see red and green bands on the monitor. To avoid this, V-Sync swaps the pointer the display driver uses to access the framebuffer just after a full frame has been sent.

Which brings us to what doublebuffering does. Without doublebuffering there's little use for a V-Sync. The action triggered by V-Sync must happen very, very fast. So this boils down to swapping a pointer or a very fast blitting operation (potentially by simply setting CoW attributes for the GPU's MMU).

Without doublebuffering and no V-Sync the effect is, that one can see the process in which the picture is rendered piece by piece to the framebuffer. Of course if rendering happens faster than a frame period this has the effect that top-down you'll see a only sparsely populated image with more and more content being visible toward the bottem, and somewhere inbetween it'll hit the lower screen edge, wapping around to the top. The intersection line will be moving.

TL;DR: Just use double buffering and enable V-Sync for buffer swap. Don't be afraid of memory consumption. All GPUs in circulation today have more than enough RAM to easily provide the memory for doublebuffered colour planes. Just do the math: 1920x1200 * RGB = 6MiB, even the smallest GPUs in PCs today deliver at least 128MiB of RAM. Mobile devices, let's say iPad 1024*768 * RGB = 2MiB vs. 32MiB for graphics. The UI of the iPad is doublebuffered anyway.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • OK, since "the time between sending frames is far shorter than the time it takes to send the full frame", that ruins my idea. :P I'm not sure I would have figured that out through plain Googling. And 8MB sounds VERY small in comparison to the time given back to me. See, I just needed a speck of information, to learn another step of what's right or wrong. Thanks. – Andrew D'Addesio Feb 04 '11 at 09:18
1

You can use wglGetProcAddress to get the address of wglSwapIntervalEXT, and then call wglSwapIntervalEXT(1); to synchronize updates with the vertical synch. When you do this, you don't get a message at the vertical synch -- instead glFlush simply doesn't return until a vertical retrace has happened, and the screen has been updated. So, you have a WM_PAINT handler that looks something like this:

BeginPaint
wglMakeCurrent
do drawing
glFlush
EndPaint

The glFlush is needed in any case, to ensure the drawing you've done gets sent to the screen.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Allowing the OGL implementation to do the pause sounds more graceful and "intended", but I'll have to run it in a separate thread in order to capture input. (Not a problem.) Additionally, the function you pointed me to uses a separate drawing buffer, which would not have been needed if the rendering had just been done into the framebuffer right after the monitor reads it. I hope I'm not sounding stubborn looking for a specific answer... So if nobody responds with a better solution, then I will go with your (—and the entire Internet's, as plenty of Googling has shown) suggestion. Thanks Jerry. – Andrew D'Addesio Feb 04 '11 at 07:13
  • 1
    Oh hey! Scanning through the OpenGL specs, I found that there is a glX extension glXWaitForMscOML, which waits for MSC (Media Stream Counter), "a counter that is unique to the graphics subsystem and increments for each vertical retrace that occurs". I have extreme doubts that there is an equivalent function for WGL unfortunately. What's interesting is that this could bypass any "Force v-sync off" option the user might have set in his graphics settings. That makes me feel kind of bad :P but it's definitely for the better, in this case. – Andrew D'Addesio Feb 04 '11 at 07:37
  • @ModChipV12: If you had extreme doubts, you may be in for some extreme happiness: http://www.opengl.org/registry/specs/OML/wgl_sync_control.txt – Ben Voigt Feb 21 '11 at 22:29
  • Unfortunately, no one supports it: http://www.kludx.com/capability.php?capability=630 – Ben Voigt Feb 21 '11 at 22:35