116 lines
7.1 KiB
HTML
116 lines
7.1 KiB
HTML
<HTML>
|
|
<HEAD>
|
|
<META name=vsisbn content="1576101746">
|
|
<META name=vstitle content="Michael Abrash's Graphics Programming Black Book, Special Edition">
|
|
<META name=vsauthor content="Michael Abrash">
|
|
<META name=vspublisher content="The Coriolis Group">
|
|
<META name=vspubdate content="07/01/97">
|
|
<META name=vscategory content="Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<TITLE>Michael Abrash's Graphics Programming Black Book Special Edition: Heinlein's Crystal Ball, Spock's Brain, and the 9-Cycle Dare</TITLE>
|
|
|
|
<!-- HEADER -->
|
|
<!-- Empty Reference Subhead -->
|
|
|
|
<!--ISBN=1576101746//-->
|
|
<!--TITLE=Michael Abrash's Graphics Programming Black Book Special Edition//-->
|
|
<!--AUTHOR=Michael Abrash//-->
|
|
<!--PUBLISHER=The Coriolis Group, Inc.//-->
|
|
<!--CHAPTER=58//-->
|
|
<!--PAGES=1089-1091//-->
|
|
<!--UNASSIGNED1//-->
|
|
<!--UNASSIGNED2//--></HEAD><BODY LINK=#0000FF ALINK=#000099 VLINK=#0000FF BGCOLOR=#FFFFFF>
|
|
|
|
<CENTER>
|
|
<TABLE BORDER>
|
|
<TR>
|
|
<TD><A HREF="58-03.html">Previous</A></TD>
|
|
<TD><A HREF="index.html">Table of Contents</A></TD>
|
|
<TD><A HREF="58-05.html">Next</A></TD>
|
|
</TR>
|
|
</TABLE>
|
|
</CENTER>
|
|
<P><BR></P>
|
|
<P>All of the above optimizations together get us to 10 cycles—<I>very</I> close to John Miles, but not there yet. We have one more trick up our sleeve, though: Suppose we point SS to the segment containing our textures, and point DS to the screen? (This requires either setting up a stack in the texture segment or ensuring that interrupts and other stack activity can’t happen while SS points to that segment.) Then, we could swap the functions of SI and BP; that would let us use BP, which accesses SS by default, to get at the textures, and DI to access the screen—all with no segment prefixes at all. By gosh, that would get us exactly one more cycle, and would bring us down to the same 9 cycles John Miles attained; Listing 58.3 shows that code. At long last, the Holy Grail attained and our honor defended, we can rest.</P>
|
|
<P>Or can we?</P>
|
|
<P><B>LISTING 58.3 L58-3.ASM</B></P>
|
|
<!-- CODE SNIP //-->
|
|
<PRE>
|
|
; Inner loop to draw a single texture-mapped vertical column,
|
|
; rather than a horizontal scanline. Maxed-out 16-bit version.
|
|
;
|
|
; At this point:
|
|
; AX = source pointer increment to advance one in Y
|
|
; ECX = fractional Y advance in lower 15 bits of CX,
|
|
; fractional X advance in high word of ECX, bit
|
|
; 15 set to 0
|
|
</PRE>
|
|
<!-- END CODE SNIP //-->
|
|
<P><A NAME="Fig7"><!-- </A><A HREF="javascript:displayWindow('images/58-07.jpg',407,289 )"> --><IMG SRC="images/58-07.jpg"><BR><!-- </A>
|
|
<BR><A HREF="javascript:displayWindow('images/58-07.jpg',407,289)"> --><FONT COLOR="#000077"><B>Figure 58.7</B></FONT></A> <I>Final method for advancing source texture pointer.</I>
|
|
</P>
|
|
<!-- CODE //-->
|
|
<PRE>
|
|
; EDX = fractional source texture Y coordinate in lower
|
|
; 15 bits of CX, fractional source texture X coord
|
|
; in high word of ECX, bit 15 set to 0
|
|
; SI = sum of integral X & Y source pointer advances
|
|
; DS:DI = initial destination pointer
|
|
; SS:BP = initial source texture pointer
|
|
|
|
SCANOFFSET=0
|
|
|
|
REPT LOOP_UNROLL
|
|
|
|
mov bl,[bp] ;get texture pixel
|
|
mov [di+SCANOFFSET],bl ;set screen pixel
|
|
|
|
add edx,ecx ;advance frac Y in DX,
|
|
; frac X in high word of EDX
|
|
adc bp,si ;advance source pointer by integral
|
|
; X & Y amount, also accounting for
|
|
; carry from X fractional addition
|
|
test dh,80h ;carry from Y fractional addition?
|
|
jz @F ;no
|
|
add bp,ax ;yes, advance Y by one
|
|
and dh,not 80h ;reset the Y fractional carry bit
|
|
@@:
|
|
|
|
SCANOFFSET = SCANOFFSET + SCANWIDTH
|
|
|
|
ENDM
|
|
</PRE>
|
|
<!-- END CODE //-->
|
|
<H4 ALIGN="LEFT"><A NAME="Heading7"></A><FONT COLOR="#000077">Don’t Stop Thinking about Those Cycles</FONT></H4>
|
|
<P>Remember what I said at the outset, that knowing something has been done makes it much easier to do? A corollary is that pushing past that point, once attained, is very difficult. It’s only natural to want to relax in the satisfaction of a job well done; then, too, the very nature of the work changes. Getting from 44 cycles down to John’s 9 cycles was a huge leap, but we knew it could be done—therefore the nature of the problem was to figure out <I>how</I> it was done; in cases like this, if we’re sharp enough (and of course we are!), we’re guaranteed eventual gratification. Now that we’ve reached John’s level of performance, the problem becomes <I>whether</I> the code can be made faster yet, and that’s a different kettle of fish altogether, for it may well be that after thinking about it for a while, we’ll conclude that it can’t. Not only will we have wasted time, but we’ll also never be sure we were right; we’ll know only that <I>we</I> couldn’t find a solution. That way lies madness.</P>
|
|
<P>And yet—<I>someone</I> has to blaze the trail to higher performance, and that someone might as well be us. Let’s look for weaknesses in Listing 58.3. None are readily apparent; the only cycle that looks even slightly wasted is the size prefix on <B>ADD EDX,ECX</B>. As it turns out, that cycle really <I>is</I> wasted, for there’s a way to make the size prefix vanish without losing the benefits of 32-bit instructions: Move the code into a 32-bit segment and make <I>all</I> the instructions 32-bit. That’s what Listing 58.4 does; this code is similar to Listing 58.3, but runs in 8 cycles per pixel, a 12.5 percent speedup over Listing 58.3. Whether Listing 58.4 actually draws more pixels per second than Listing 58.3 depends on whether display memory is fast enough to handle pixels as rapidly as Listing 58.4 can deliver them. That speed, one pixel every 122 nanoseconds on a 486/66, is one that ISA adapters can’t hope to match, but fast VLB and PCI adapters can handle with ease. Be aware, too, that cache misses when reading the source texture will generally reduce performance below the calculated 8-cycles-per-pixel level, especially because textures, which can be scanned across at any angle, are rarely accessed at consecutive addresses, which is the arrangement that would make for the fewest cache misses.</P><P><BR></P>
|
|
<CENTER>
|
|
<TABLE BORDER>
|
|
<TR>
|
|
<TD><A HREF="58-03.html">Previous</A></TD>
|
|
<TD><A HREF="index.html">Table of Contents</A></TD>
|
|
<TD><A HREF="58-05.html">Next</A></TD>
|
|
</TR>
|
|
</TABLE>
|
|
</CENTER>
|
|
|
|
<hr width="90%" size="1" noshade>
|
|
<div align="center">
|
|
<font face="Verdana,sans-serif" size="1">Graphics Programming Black Book © 2001 Michael Abrash</font>
|
|
</div>
|
|
<!-- all of the reference materials (books) have the footer and subfoot reveresed -->
|
|
<!-- reference_subfoot = footer -->
|
|
<!-- reference_footer = subfoot -->
|
|
|
|
<!-- BEGIN SUB FOOTER -->
|
|
</BODY>
|
|
</HTML>
|
|
|
|
<!-- END FOOTER -->
|
|
|
|
|