61 lines
3.8 KiB
Markdown
61 lines
3.8 KiB
Markdown
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.
|