Initial conversion to markdown
This commit is contained in:
parent
a96a114403
commit
5e10794a24
362 changed files with 67353 additions and 0 deletions
109
58-05.md
Normal file
109
58-05.md
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](58-04.html) [Table of Contents](index.html) [Next](59-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**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.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](58-04.html) [Table of Contents](index.html) [Next](59-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Loading…
Reference in a new issue