Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

GLUT glutSwapBuffers() and Vertical Sync

1,098 views
Skip to first unread message

Dave

unread,
Jun 8, 2007, 10:54:45 AM6/8/07
to
Hi All,
I'm wondering if any of you gurus can help me with this?. I'm using
vertical sync enabled because without it, I get a certain amount of
screen ripping for ymy GLUT applicatio which is not acceptable. With
vertical sync on it is usual for glutSwapBuffers() to block until the
sync happens which effectively regulates a glut application to say,
60Hz.

The problem I have, is that my application has two glut windows
rendered from the same thread. To do this, it needs to call
glutSwapBuffers() twice, once for each window. My problem is that this
reduces the frame rate. My guess is that this is because glut waits
for the vertical sync for both glutSwapBuffers() which effective
halves the frame rate of my application even though the application
can easily run faster than this!. Typically, I'm reduced to 20Hz even
though the the application will run at > 100Hz with the vertical sync
disabled.

Has anyone any ideas?. Can I tell GLUT to sync both windows
simultaneously?.

Thanks for any comments/suggestions in advance,
Dave

fungus

unread,
Jun 8, 2007, 6:18:50 PM6/8/07
to
On Jun 8, 4:54 pm, Dave <dave_m_mo...@post2me.freeserve.co.uk> wrote:
>
> Has anyone any ideas?. Can I tell GLUT to sync both windows
> simultaneously?.
>

What happens if you:

a) Enable sync
b) Swap window A
c) Disable sync
b) Swap window B

--
<\___/>
/ O O \
\_____/ FTB. Remove my socks for email address.


Governments, like diapers, should be changed often,
and for the same reason.


Dave

unread,
Jun 10, 2007, 11:55:08 AM6/10/07
to
On 8 Jun, 23:18, fungus <openglMYSO...@artlum.com> wrote:
> On Jun 8, 4:54 pm, Dave <dave_m_mo...@post2me.freeserve.co.uk> wrote:
>
>
>
> > Has anyone any ideas?. Can I tell GLUT to sync both windows
> > simultaneously?.
>
> What happens if you:
>
> a) Enable sync
> b) Swap window A
> c) Disable sync
> b) Swap window B

Oh, I didn't realise you could do that dynamically - I was just using
the options in the Video properties via right-clicking the desktop.
I'm not sure the results would be good though, as at least one of the
windows would be swapped unsynchronised which, presumably, would cause
ripping.

Personally, I think this is a GLUT issue. Even if I do this:

1). render window 1
2). render window 2
3). glutSwapBuffers() for window 1
4). glutSwapBuffers() for window 2

I still get the same problem even though both glutSwapBuffers() are
pretty much immediately after each other. I don't know what glut does
with these calls - it's as if I want a glutSwapMultiBuffer() function.
I guess my question to GLUT experts out there would be: Why can't I
sync 2 windows to the same vertical sync?.

ju...@liimatta.org

unread,
Jun 10, 2007, 3:29:26 PM6/10/07
to
On Jun 10, 6:55 pm, Dave <dave_m_mo...@post2me.freeserve.co.uk> wrote:
> Oh, I didn't realise you could do that dynamically - I was just using
> the options in the Video properties via right-clicking the desktop.
> I'm not sure the results would be good though, as at least one of the
> windows would be swapped unsynchronised which, presumably, would cause
> ripping.

One rule-of-thumb is to keep in mind how the hardware (often) works;
they don't really synchronize or wait for vertical retrace per-se,
it's goes more along these lines:

- When the vertical retrace occurs, the hardware looks up the address
to start generating/sending image to the display device.

That's pretty much it. When the driver writes to this address, NOTHING
HAPPENS. ZIP. ZILCH. The address isn't changed in mid-frame in any
way, the hardware jogs along and generates the image from a base
address and that's it.

You can write into this register 1000 times if you want, but ONLY the
value that is written into the register last has effect when the
retrace occurs.

The tearing comes from the fact, that the application is still writing
into memory which is being read by the DAC or chip generating the
values for the DVI, whatnot.

If you want to avoid writing into memory which is still being used by
the DAC/whatnot, you want to block the image generation with wait-for-
retrace. Ofcourse, this wait is waste of time, and it's always nice if
the hardware can generate new image and not just wait around for some
synchronous event.

For asynchronous operation of the driver, more buffers are needed: one
which is being displayed (DAC reads from it), one where image is being
generated (GPU writes into this one) and one pending for the next
vertical retrace.

This is known as "triple buffering". One word of caution: this causes
latency, the images are lagging behind one extra frame. Also important
to notice that modern flat displays like TFT introduce their own
latency. You might be 4-5 frame behind displaying the frames you are
generating. *outch*

This depends on hardware, drivers, display devices etc. you are using.
How this maps to GLUT, or any possible application that might utilize
the display driver is combination of many factors as can be observed.

Regarding your windows syncing question, the reason for this could be
that the window contents are blitted into the display memory; it's not
a simple register value write. What does the glutSwapBuffers() do
internally, the sourcecode is available AFAIK. The GLUT is just a
wrapper on top of the display drivers, it doesn't go beyond that into
the details of the OGL implementation.

Dave

unread,
Jun 11, 2007, 3:49:12 AM6/11/07
to

> For asynchronous operation of the driver, more buffers are needed: one
> which is being displayed (DAC reads from it), one where image is being
> generated (GPU writes into this one) and one pending for the next
> vertical retrace.

Isn't this what double buffering is for?. For a double buffered
application, the code should never render into the display buffer.
Consequently I can only assume that the rippng occurs because the
retrace happens whilst the buffers are being swapped which is odd
because I would have thought that swapping abuffer would be an atomic
opertaion - you just reassign the value of the pointers pointing to
the display and rendering buffers.


ju...@liimatta.org

unread,
Jun 11, 2007, 9:28:08 AM6/11/07
to
On Jun 11, 10:49 am, Dave <dave_m_mo...@post2me.freeserve.co.uk>
wrote:

> > For asynchronous operation of the driver, more buffers are needed: one
> > which is being displayed (DAC reads from it), one where image is being
> > generated (GPU writes into this one) and one pending for the next
> > vertical retrace.
>
> Isn't this what double buffering is for?.

If you are fine waiting until the front buffer is completely refreshed
into the display device, then it's again available as render target.

You **wait** until you know when the front buffer is completely
refreshed, and available. When you are triple buffering, you don't
have to wait. You have a spare buffer available as render target
immediately.


> For a double buffered
> application, the code should never render into the display buffer.

That would be catastrophic failure from point of view of continuity,
not just minor tearing issue. :)

> Consequently I can only assume that the rippng occurs because the
> retrace happens whilst the buffers are being swapped which is odd
> because I would have thought that swapping abuffer would be an atomic
> opertaion - you just reassign the value of the pointers pointing to
> the display and rendering buffers.

The tearing happens because you see two frames simultaneously in the
same refresh cycle. it's safe to assume that we are seeing
discontinuity between two completed frames.

This has various implications which we could speculate further, but we
have established that there are more than one completed frame existing
simultaneously for this to be possible.

What can we extrapolate from all this?

If we only have one buffer, we can't do jack. We would see the
contents being generated. Not good.

If we have two buffers, we can generate in back buffer and display in
front buffer. We must synchronize the swap so that we don't
accidentally at any time see the non-complete frame being generated.

First case is not good. Second one can't tear. Follow?

The third case is that we have more buffers. This is the case that
even *allows* us to perceive tearing WITHOUT major defects such as
seeing non-complete frames being drawn block-by-block,fragment-by-
fragment, or whatever granularity is used for (burst?) memory writes
into the frame buffer.

We can *blit* into the front buffer, or we can do logical address
swap. The address swap relies on vertical refresh. The blit doesn't ;
we can by-pass the synchronization that is feature of the hardware due
to common implementation by blitting the contents. This is case when
tearing is easily explained.

It is also possible to implement page flip where the address can be
changed in middle of a refresh cycle, but much less likely. If you
have hardware and driver which does this, that could also explain the
flickering. It still wouldn't change anything, though, since blit or
address swap, you are still doing it mid cycle and get tearing. :)


Greg Couch

unread,
Jun 11, 2007, 7:14:10 PM6/11/07
to
Dave <dave_m...@post2me.freeserve.co.uk> writes:

>> For asynchronous operation of the driver, more buffers are needed: one
>> which is being displayed (DAC reads from it), one where image is being
>> generated (GPU writes into this one) and one pending for the next
>> vertical retrace.

>Isn't this what double buffering is for?. For a double buffered
>application, the code should never render into the display buffer.
>Consequently I can only assume that the rippng occurs because the
>retrace happens whilst the buffers are being swapped which is odd

>because I would have thought that swapping a buffer would be an atomic


>opertaion - you just reassign the value of the pointers pointing to
>the display and rendering buffers.

OpenGL swapbuffers is designed to work with multiple windows. It's a
"quality of implementation" issue, so if it doesn't work, it's a poorly
written graphics driver. So please share what graphics card and driver
you're having problems with.

A properly written swapbuffer won't block your application until it
tries to do more OpenGL commands to the same window before the swapbuffer
has been done. Using separate OpenGL contexts for the two windows might
help the driver figure that out (not sure since I always do).

Also, this may be one of those differences between workstation and
consumer/gaming graphics cards. The consumer/gaming graphics card
drivers are optimized for a single graphics window (often fullscreen).
The workstation graphics card drivers organize the framebuffer
memory differently to make concurrent graphics windows work better.
Workstation graphics drivers support per-window stereo, overlay planes,
fast overlapped graphics window clipping, better anti-aliased lines,
and possibly more (if you know of more differences, I'd like to hear
about them).

Examples of consumer/gaming graphics cards would be ATI Radeon or NVidia
GeForce cards. And examples of workstation graphics cards would be 3DLabs
Wildcat, ATI FireGL, Matrox Parhelia, or NVidia Quadro graphics cards.
Stay away workstation graphics cards that are designed for 2D work, like
the NVidia Quadro NVS series. (And only buy notebooks where the graphics
driver is updatable by the graphics chip vendor -- unupgradable notebook
graphics drivers are a tech support nightmare.)

Greg Couch
UCSF Computer Graphics Lab
http://www.cgl.ucsf.edu/chimera/

Jan Bruns

unread,
Jun 13, 2007, 7:55:57 AM6/13/07
to

<ju...@liimatta.org>:
> Dave:

>> > For asynchronous operation of the driver, more buffers are needed: one
>> > which is being displayed (DAC reads from it), one where image is being
>> > generated (GPU writes into this one) and one pending for the next
>> > vertical retrace.

>> Isn't this what double buffering is for?.

> If you are fine waiting until the front buffer is completely refreshed
> into the display device, then it's again available as render target.

> You **wait** until you know when the front buffer is completely
> refreshed, and available. When you are triple buffering, you don't
> have to wait. You have a spare buffer available as render target
> immediately.

You count the primary surface also as a buffer. Ok.

With a total of one surface, we see the painter-algo at work.

With a total of two or more surfaces swaped unsynced, we never
need to wait, but still see some distortion (some parts of the
screen old, some parts new).
With a total of two surfaces swaped synced, we have no visual
artifacts, but CPU and GPU must wait for the retrace, because
the GPU has no surface to render to, and the CPU should wait
because the application should be held from streaming too many
frames in advance. The GPU would be

idle = frames_per_s * v_retrace_intervall/2

per second, on average (over difrent scenes).

With a total of three surfaces swaped synced, we have no visual
artifacts, but CPU must wait for the retrace, because the
application should be held from streaming too many frames in
advance. Because of this and/or because the GPU might have
both backbuffers already complete until the synced flip happens,
the GPU would become

idle = chance_both_full * frames_per_s * v_retrace_intervall/2

per second on average (over difrent scenes), where chance_both_full
would probably be 50% on average. The drawback is, that if
chance_both_full is less than 100%, we have no influence about
the number of v_retraces a given specific is displayed.

That's also ugly. A rotating cube fully correct displayed at a
rate of 15 fps can look much smoother than at 75fps with every
3rd frame dropped.

Gruss

Jan Bruns

ju...@liimatta.org

unread,
Jun 13, 2007, 6:03:23 PM6/13/07
to
On Jun 13, 2:55 pm, "Jan Bruns" <testzugang_janbr...@arcor.de> wrote:

Extra detail; the render target memory layout is often tiled. If the
DAC/DVI chip don't support tiled addressing a tiled-to-linear blit is
needed, so the "painting" will never be visible anyway. Kind of
slipped my mind when making earlier posts.. but one key reason why the
blits are more likely than changing the address? =)

0 new messages