73 lines
4.3 KiB
Markdown
73 lines
4.3 KiB
Markdown
------------------------ --------------------------------- --------------------
|
||
[Previous](57-03.html) [Table of Contents](index.html) [Next](58-01.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
Within Listing 57.2, all the important optimization is in the loop that
|
||
draws across each destination scan line, near the end of the listing.
|
||
One optimization is elimination of the call to the set-pixel routine
|
||
used to draw each pixel in Listing 57.1. Function calls are expensive
|
||
operations, to be avoided when performance matters. Also, although Mode
|
||
X (the undocumented 320x240 256-color VGA mode X-Sharp runs in) doesn’t
|
||
lend itself well to pixel-oriented operations like line drawing or
|
||
texture mapping, the inner loop has been set up to minimize Mode X’s
|
||
overhead. A rotating plane mask is maintained in AL, with DX pointing to
|
||
the Map Mask register; thus, only a rotate and an **OUT** are required
|
||
to select the plane to which to write, cycling from plane 0 through
|
||
plane 3 and wrapping back to 0. Better yet, because we know that we’re
|
||
simply stepping horizontally across the destination scan line, we can
|
||
use a clever optimization to both step the destination and reduce the
|
||
overhead of maintaining the mask. Two copies of the current plane mask
|
||
are maintained, one in each nibble of AL. (The Map Mask register pays
|
||
attention only to the lower nibble.) Then, when one copy rotates out of
|
||
the lower nibble, the other copy rotates into the lower nibble and is
|
||
ready to be used. This approach eliminates the need to test for the mask
|
||
wrapping from plane 3 to plane 0, all the more so because a carry is
|
||
generated when wrapping occurs, and that carry can be added to DI to
|
||
advance the screen pointer. (Check out the next chapter, however, to see
|
||
the best Map Mask optimization of all—setting it once and leaving it
|
||
unchanged.)
|
||
|
||
In all, the overhead of drawing each pixel is reduced from a call to the
|
||
set-pixel routine and full calculation of the screen address and plane
|
||
mask to five instructions and no branches. This is an excellent example
|
||
of converting full, from-scratch calculations to incremental processing,
|
||
whereby only information that has changed since the last operation (the
|
||
plane mask moving one pixel, for example) is recalculated.
|
||
|
||
Incremental processing and knowing where the cycles go are both
|
||
important in the final optimization in Listing 57.2, speeding up the
|
||
retrieval of pixels from the texture map. This operation looks very
|
||
efficient in Listing 57.1, consisting of only two adds and the macro
|
||
**GET- IMAGE-PIXEL**. However, those adds are fixed-point adds, so they
|
||
take four instructions apiece, and the macro hides not only conversion
|
||
from fixed-point to integer, but also a time-consuming multiplication.
|
||
Incremental approaches are excellent at avoiding multiplication, because
|
||
cumulative additions can often replace multiplication. That’s the case
|
||
with stepping through the source texture in Listing 57.2; ten
|
||
instructions, with a maximum of two branches, replace all the texture
|
||
calculations of Listing 57.1. Listing 57.2 simply detects when the
|
||
fractional part of the source x or y coordinate turns over and advances
|
||
the source texture pointer accordingly.
|
||
|
||
As you might expect, all this optimization is pretty hard to implement,
|
||
and makes Listing 57.2 much more complicated than Listing 57.1. Is it
|
||
worth the trouble? Indeed it is. Listing 57.2 is more than twice as fast
|
||
as Listing 57.1, and the difference is very noticeable when large,
|
||
texture-mapped areas are animated. Whether more than doubling
|
||
performance is significant is a matter of opinion, I suppose, but
|
||
imagine that you’re in William Gibson’s *Neuromancer*, trying to crack a
|
||
corporate database. Which texture-mapping routine would you rather have
|
||
interfacing you to Cyberspace?
|
||
|
||
I’m always interested in getting your feedback on and hearing about
|
||
potential improvements to X-Sharp. Contact me through the publisher.
|
||
There is no truth to the rumor that I can be reached under the alias
|
||
“sheep-shearer,” at least not for another 9,999 sheep.
|
||
|
||
------------------------ --------------------------------- --------------------
|
||
[Previous](57-03.html) [Table of Contents](index.html) [Next](58-01.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
* * * * *
|
||
|
||
Graphics Programming Black Book © 2001 Michael Abrash
|