97 lines
4.7 KiB
Markdown
97 lines
4.7 KiB
Markdown
**LISTING 58.4 L58-4.ASM**
|
|
|
|
; Inner loop to draw a single texture-mapped vertical column,
|
|
; rather than a horizontal scanline. Maxed-out 32-bit version.
|
|
;
|
|
; At this point:
|
|
; EAX = sum of integral X & Y source pointer advances
|
|
; ECX = source pointer increment to advance one in Y
|
|
; EDX = fractional source texture Y coordinate in lower
|
|
; 15 bits of DX, fractional source texture X coord
|
|
; in high word of EDX, bit 15 set to 0
|
|
; ESI = initial source texture pointer
|
|
; EDI = initial destination pointer
|
|
; EBP = fractional Y advance in lower 15 bits of BP,
|
|
; fractional X advance in high word of EBP, bit
|
|
; 15 set to 0
|
|
|
|
SCANOFFSET=0
|
|
|
|
REPT LOOP_UNROLL
|
|
|
|
mov bl,[esi] ;get image pixel
|
|
add edx,ebp ;advance frac Y in DX,
|
|
; frac X in high word of EDX
|
|
adc esi,eax ;advance source pointer by integral
|
|
; X & Y amount, also accounting for
|
|
; carry from X fractional addition
|
|
mov [edi+SCANOFFSET],bl ;set screen pixel
|
|
; (located here to avoid 486
|
|
; AGI from previous byte op)
|
|
test dh,80h ;carry from Y fractional addition?
|
|
jz short @F ;no
|
|
add esi,ecx ;yes, advance Y by one
|
|
; (produces Pentium AGI for MOV BL,[ESI])
|
|
and dh,not 80h ;reset the Y fractional carry bit
|
|
@@:
|
|
|
|
SCANOFFSET = SCANOFFSET + SCANWIDTH
|
|
|
|
ENDM
|
|
|
|
And there you have it: A five to 10-times speedup of a decent assembly
|
|
language texture mapper. All it took was some help from my friends, a
|
|
good, stiff jolt of right-brain thinking, and some solid left-brain
|
|
polishing—plus the knowledge that such a speedup was possible. Treat
|
|
every optimization task as if John Miles has just written to inform you
|
|
that he's made it faster than your wildest dreams, and you'll be amazed
|
|
at what you can do!
|
|
|
|
### Texture Mapping Notes {#Heading8}
|
|
|
|
Listing 58.3 contains no 486 pipeline stalls; it has Pentium stalls, but
|
|
not much can be done for them because of the size prefix on **ADD
|
|
EDX,ECX**, which takes 1 cycle to go through the U-pipe, and shuts down
|
|
the V-pipe for that cycle. Listing 58.4, on the other hand, has been
|
|
rearranged to eliminate all Pentium stalls save one. When the Y
|
|
coordinate fractional part carries and ESI advances, the code executes
|
|
as follows:
|
|
|
|
|
|
ADD ESI,ECX ;cycle 1 U-pipe
|
|
AND DH,NOT 80H ;cycle 1 V-pipe
|
|
;cycle 2 idle AGI on ESI
|
|
MOV BL,[ESI] ;cycle 3 U-pipe
|
|
ADD EDX,EBP ;cycle 3 V-pipe
|
|
|
|
However, I don't see any way to eliminate this last AGI, which happens
|
|
about half the time; even with it, the Pentium execution time for
|
|
Listing 58.4 is 5.5 cycles. That's 61 nanoseconds—a highly respectable
|
|
16 million texture-mapped pixels per second—on a 90 MHz Pentium.
|
|
|
|
The type of texture mapping discussed in both this and earlier chapters
|
|
doesn't do perspective correction when mapping textures. Why that is and
|
|
how to handle perspective correction is a topic for a whole separate
|
|
book, but be aware that the textures on some large polygons (not the
|
|
polygon edges themselves) drawn with the code in this chapter will
|
|
appear to be unnaturally bowed, although small polygons should look
|
|
fine.
|
|
|
|
Finally, we never did get rid of the last jump in the texture mapper,
|
|
yet John Miles claimed no jumps at all. How did he do it? I'm not sure,
|
|
but I'd guess that he used a two-entry look-up table, based on the Y
|
|
carry, to decide how much to advance the source pointer in Y. However, I
|
|
couldn't come up with any implementation of this approach that didn't
|
|
take 0.5 to 1 cycle more than the test-and-jump approach, so either I
|
|
didn't come up with an adequately efficient implementation of the table,
|
|
John saved a cycle somewhere else, or perhaps John implemented his code
|
|
in a 32-bit segment, but used the less-efficient table in his fervor to
|
|
get rid of the final jump. The knowledge that I apparently came up with
|
|
a different solution than John highlights that the technical aspects of
|
|
John's implementation were, in truth, totally irrelevant to my
|
|
optimization efforts; the only actual effect John's code had on me was
|
|
to make me *believe* a texture mapper could run that fast.
|
|
|
|
Believe it! And while you're at it, give both halves of your brain equal
|
|
time—and watch out for aliens in short skirts, 60's bouffant hairdos,
|
|
and an undue interest in either half.
|