📄 dubtrip.htm
字号:
scan all the lines on the screen, and then come back to the top fo the
screen. You can't say "Okay, Big Blue Gun, on my mark, Aim pixel
100,100 and shoot n number of electrons!". The guns always shoot in
the same pattern, and if the pixel you just changed was just passed by the
guns, then too bad, it'll have to wait for the next pass before it's
updated. The time it takes for the monitor to scan the whole screen is
it's refresh rate, which is typically 75Hz in most monitors.
<P>Maybe some of you will start to see where I'm getting at
with all this, big grins on their faces. If the whole idea behind page
flipping is to present clean images instantaneously to the user, how
can we do so if the monitor device is not instantaneous?
<P>See, if we flip our screen at any time, we will most likely
flip in the middle of the monitor scanning process; that means that our
monitor will most likely scan part of a a frane, then as we flip it'll
scan another image, displaying the top part of the first one, then the
bottom part of the second. The effects of this perhaps won't be as obvious
to the eye as the non-buffered situation we had at first, but our images
certainly won't be clean. For example, suppose that I had an image that
would be moving left in my game, it would so something like this:
<P align=center><IMG height=68 src="title2.jpg" width=460>
<P>The bottom part of the image is shifted left. If the game is
fast enough and it updates its images fast enough the eye may not notice,
but it's certainly not a chance I'd recommend you to take.
<P>The solution to this is to only flip during the vertical
retrace period of the monitor. The vertical retrace period is the red
line on our first diagram, it is the period when the electrons are going
back to the top of the display; the guns aren't "shooting"
during this interval - they are simply repositioning themselves for the
next pass. When beggining this vertical retrace, the monitor sends a
special signal, called the vertical sync signal, to notify that
it is going back to the top of its image and it is okay to flip now.
<P>So what do need to do to synchronize to this vertical sync
signal ? Well, nothing, videocards often will only flip when the monitor
is in its vertical sync period, so you don't have the choice anyways. When
using DirectX, everything is handled for you; when you ask DirectX to flip
an image, it says "Okay, I'll put this on my agenda", and flips
whenever the time is right.
<P>Alas, alas, this vertical sync signal brings another bunch
of troubles all its own...
<H3><FONT COLOR=YELLOW><I>The Bad Effects of Buffering</I></FONT></H3>
<P>This whole buffering and synchronizing stuff
also brings up plenty of troubles. The first trouble is relatively obvious
: your game's framerate can never be any higher than the monitor's
framerate. This is not a big problem however, since most monitors output
75 images per second, which is already triple what you get on television.
But it tells us there is an upper limit to teh amount of performance your
game can provide, and no optimization in the world will make your game go
past that limit unless you dump the page flipping.
<P>There is a much more serious problem. To
explain this, let's first look at a simple time graph that shows how the
monitor updates the screen:
<P align=center><IMG height=155 src="vsync.gif" width=424></p>
<P>Now, as I stated earlier, we can only flip the
screen within the VSync interval. Now let's say that our game is fast, and
it can update its screen twice as fast as the monitor. So it makes its
picture, and it asks for the flip. DirectX says "Sure, I'll do it
when it's time". Good. So our game just goes on and writes its data
to the other available buffer...
<P>Wait. There is no other available buffer. The
primary buffer is currently beig scanned by the monitor, so we can't touch
it, and the back buffer is the one our game has just finished drawing.
What can we do ? Nothing. You wait. Now you could use this idle
time to do something else, like make calculations, update the game's AI,
etc, but there are very few tasks a game could do that can just be picked
up like that, just when there is time to do it. So all you can do is wait.
The next thing you know, your prime-time game capable of running at 75
frames per second is only running at 38, losing half your time.
This is easily illustrated by the next example:
<P align=center><IMG height=223 src="vsync2.gif" width=480></P>
<P>This is a worst-case scenario, with the monitor
running at 75Hz. The blue line tracks where the monitor is scanning from,
and the yellow line tracks where the game is writing to. At first, the
monitor scans from the 1st surface, and the game writes onto the second
surface. In this scenario, the game is just the same speed as the monitor,
i.e. it finishes its drawing right when the monitor is starting a new
scan. Unfortunately, at that point it's already too late : the game should
finish drawing before the monitor's vertical sync (the red
blocks).
<P>In this case, the game issues its flip request
just a split-nanosecond too late, right when the VSync has finished. This
is indicated by the violet arrows. The game (yellow line), should go to
the other surface to continue, but it can't; the monitor's already there
(traffic jam). So it waits in the middle, doing nothing. It's only when
the flip request is processed, when the monitor finally gets off the 1st
surface, that the game can get on it and begin its next drawing, in a
neverending cycle.
<P>In this case, the game has enough "juice" to be
able to output 75 frames per second. But because it is constantly waiting
for the monitor, the best that this game will get is half the monitor's
framerate, or 37.5 frames per second, losing almost half of its
efficiency. In double-buffered schemes, you very often get framerates that
are only simple fractions of the monitor's framerate : 75, or 37.5 which
is 75/2, 25 which is 75/3, 18.75 which is 75/4, and so forth. You can
verify this with the <A href="screenbench.zip">ScreenBench</A>
utility I made.
<P>Performance-wise, this means that you could do vast amounts
of optimization without any effect on your framerate, up until you reach a
certain threshold of optimization where your framerate would climb
significantly - it's like if your game could only shift into certain
predefined speeds.
<H3><FONT COLOR=YELLOW><I>Enter Triple Buffering</I></FONT></H3>
<P>So what's the solution? Well, the solution is to add a
third "lane", another buffer, kind of a "backup" that
the game can rely on. DirectX (and Armagammon) handles the details of
setting triple buffering, you can simply specify how many buffers you
want.
<P>This diagram illustrates how triple buffering works:
<P align=center><IMG height=300 src="vsync3.gif" width=480>
<P>I think the graph speaks for itself. With triple buffering,
the game (yellow line), always has some place to go, it's never
"blocked" by the monitor, and it never waits between two lines.
In this case, the game can gain its full speed, and reach the monitor's
framerate (75Hz). Note that even with triple buffering the best framerate
you will be able to get is the monitor's framerate.
<P>The downside of triple buffering is that you have to pay for
the extra video memory you will be using (don't try setting up triple
buffering with one of the three surfaces in system memory, you can only
gain a negative performance hit this way); your extra surface will cost
you around half a meg of video memory in 8-bit graphics mode, a full meg
in 16-bit graphics mode. Some videocards still come equipped with only 2
or 4 megs of video memory, and on these cards triple buffering can only be
setup in the most basic screen resolution modes.
<H3><FONT COLOR=YELLOW><I>Conclusion</I></FONT></H3>
<P>Despite these minor shortcomings, I think it's worth it to
setup triple buffering whenever there's room for it on the videocard; it
will provide you with a much more flexible framerate.</P>
<!--Bottom Navigation-->
<A NAME="bottom"></A>
<!--End Bottom Navigation-->
</STRONG>
</FONT>
<!--End Body-->
<!--Bottom-->
<BR>
<IMG SRC="gradbar.jpg">
<BR>
<FONT SIZE=2 COLOR=#8B8B8B FACE=Helvetica>
<I><font color="#FBFBFB">T</font><font color="#F7F7F7">h</font><font color="#F3F3F3">e</font><font color="#EFEFEF"> </font><font color="#EBEBEB">G</font><font color="#E7E7E7">a</font><font color="#E3E3E3">m</font><font color="#DFDFDF">e</font><font color="#DBDBDB"> </font><font color="#D7D7D7">P</font><font color="#D3D3D3">r</font><font color="#CFCFCF">o</font><font color="#CBCBCB">g</font><font color="#C7C7C7">r</font><font color="#C3C3C3">a</font><font color="#BFBFBF">m</font><font color="#BBBBBB">m</font><font color="#B7B7B7">i</font><font color="#B3B3B3">n</font><font color="#AFAFAF">g</font><font color="#ABABAB"> </font><font color="#A7A7A7">M</font><font color="#A3A3A3">e</font><font color="#9F9F9F">g</font><font color="#9B9B9B">a</font><font color="#979797">S</font><font color="#939393">i</font><font color="#8F8F8F">t</font><font color="#8B8B8B">e</font> -
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -