[Future Technology Research Index] [SGI Tech/Advice Index] [Nintendo64 Tech Info Index]


[WhatsNew] [P.I.] [Indigo] [Indy] [O2] [Indigo2] [Crimson] [Challenge] [Onyx] [Octane] [Origin] [Onyx2]

Ian's SGI Depot: FOR SALE! SGI Systems, Parts, Spares and Upgrades

(check my current auctions!)

The Effects of Double Buffering
on Animation Frame Rates

(thanks to Allan Schaffer of Silicon Graphics Inc. for this information)
I asked: Why should double buffering slow down an animation in terms of how many polygons get rendered per second?

Allan Replied: The nature of double-buffering is that the buffer swaps (must) occur during the monitor's vertical retrace. Assuming a 60Hz video refresh rate, this means that buffer swaps could happen, at most, every 1/60th of a second or every 16.66ms.

In doublebuffer mode, when an application calls swapbuffers [or the OpenGL equivalent], the application will block(*) until the moment that the next buffer swap can occur, which is at the beginning of the next vertical retrace.

(*) actually, on some platforms the call to swapbuffers() blocks, on some the "next" IRIS GL/OpenGL call made blocks.

So this means, if your application only takes, say, 6ms to finish all the rendering it needs to do before the buffer swap, it will then wait another 10.66 ms until the video retrace begins.

Likewise, if the application takes 20ms to render a frame, it will have to wait until the next vertical retrace (16.6+16.6) before the buffer swap occurs and the application can continue - so roughly 13ms spent blocked, not doing anything.

This is why us performance-oriented folks cringe when we hear someone quoting double buffered results in a benchmark. They could be misleading by just about any amount. For one terrible example, consider:

   while (1) {                           while (1) {
      color(RED);                          color(RED);
      draw-a-polygon();                    draw-a-polygon();
      swapbuffers();                     }
   }

The left-hand result can be no faster than the refresh rate of the monitor, probably 60 loops/sec. The right-hand result is probably millions of loops/sec.

Likewise, consider:

   while (1) {                           while (1) {
      draw-20-ms-worth-of-stuff();         draw-20-ms-worth-of-stuff();
      color(RED);                          color(RED);
      draw-a-polygon();                    draw-a-polygon();
      swapbuffers();                     }
   }

The left-hand [doublebuffered] result, in this case, can be no faster than 30 loops/sec (assuming a monitor running at 60Hz). The right-hand [singlebuffered] result is probably closer to 50/sec.

Visually:

   |     |     |     |     |     |     |
   |L----->wwww|L----->wwww|L----->wwww|
   |     |     |     |     |     |     |
   |     |     |     |     |     |     |
   |R----->R----->R----->R----->R----->|
   |     |     |     |     |     |     |

   time-->

The vertical lines are monitor video retraces, spaced 16.66ms apart. The "L----->" is the amount of time the left-hand example spends doing actual rendering. The "wwww" is how much time it spends waiting for the next retrace after it finishes. The "R---->" is how much time the right-hand example spends rendering.

Hope this makes sense. :-)

Allan
Silicon Graphics

PS. For extra credit, relate this to how/why doublebuffered applications always render at an integer divisor of the monitor refresh rate -- ie 60Hz, 30Hz, 20Hz, 15Hz, 12Hz etc.


Extra Information

(Allan received a question from someone who, having read the above information, wanted to know when one should use double buffering. Here is Allan's response...)


> I read your explanation on the effects of double-buffering
> and performance. It makes perfect sense. I always thought
> double-buffering would increase performance, so when is it
> a good idea to use it?

For most applications, smooth animation or the smooth presentation of finished rendered images is an absolute requirement, so doublebuffering is a necessity.

Doublebuffering is a technique whereby the graphics subsystem displays one finished image (or frame) to the user while the application & hardware render the next frame out of sight. Without it, the user would see the work-in-progress versions of new frames, which would be distracting and unconvincing. For example, in the case of drawing a car, they'd be able to watch as each wheel was filled in, the body, windows, etc..

Imagine piloting a flight simulator and watching each frame as the ground and individual trees were drawn in, then cleared, then drawn in again, etc. When you got in a real airplane and this didn't happen, you'd be confused, and your passengers in trouble. :-)

The criticism of doublebuffering in this context is that it prevents the measurement of true graphics performance. Important to note: on very slow or not-so-capable systems this doesn't matter much because those systems take so long to render a new frame anyways. Say they're running fast enough to render a new frame 5 times per second, or every 200 milliseconds -- it's only going to be at most another 16 milliseconds (8% extra) before the swapbuffers() would take effect. No big deal for them.

But if the same image were being rendered by a very-high-performance system like SGI's InfiniteReality, let's assume an almost worst-case example and say that the image would only take 17 milliseconds to generate. [Since it's quite likely that the IR would be more than 10 times faster than a PC-based graphics board :-)]. In that case, an extra 16 milliseconds as you wait for the next vertical retrace would amount to a considerable timing delay -- almost 50% !

It could be even worse. Imagine the percentages if the InfiniteReality was capable of rendering the benchmark image 1000 times per second, but due to doublebuffering was instructed to only display at most 60 frames per second!

A best case example would be if the SGI took exactly 16.666666 milliseconds to render the new image. In that case, the buffer swap would happen immediately, ie 0% delay.

The failure to avoid this arbitrary 0% - 50% (or more) variance in a benchmark program is why we cringe so much whenever I see benchmarks made in doublebuffer mode. The well-written ones do not do this of course. But there are always a few -- the new "Indy3D" benchmark someone posted to comp.sys.sgi.graphics a few days ago, for example -- that continue to make this mistake.

Hope this helps. :-)

Allan

-- 
Allan Schaffer                                               
allan@sgi.com
Silicon Graphics                              
http://reality.sgi.com/allan


Ian's SGI Depot: FOR SALE! SGI Systems, Parts, Spares and Upgrades

(check my current auctions!)
[WhatsNew] [P.I.] [Indigo] [Indy] [O2] [Indigo2] [Crimson] [Challenge] [Onyx] [Octane] [Origin] [Onyx2]
[Future Technology Research Index] [SGI Tech/Advice Index] [Nintendo64 Tech Info Index]