137 lines
7.3 KiB
Markdown
137 lines
7.3 KiB
Markdown
Chapter 63\
|
|
Floating-Point for Real-Time 3-D {#Heading1}
|
|
---------------------------------
|
|
|
|
### Knowing When to Hurl Conventional Math Wisdom Out the Window {#Heading2}
|
|
|
|
In a crisis, sometimes it's best to go with the first solution that
|
|
comes into your head—but not very often.
|
|
|
|
When I turned 16, my mother had an aging, three-cylinder Saab—not one of
|
|
the sporty Saabs that appeared in the late '70s, but a blunt-nosed,
|
|
ungainly little wagon that seated up to seven people in sardine-like
|
|
comfort, with two of them perched on the gas tank. That was the car I
|
|
learned to drive on, and the one I took whenever I wanted to go
|
|
somewhere and my mother didn't need it.
|
|
|
|
My father's car, on the other hand, was a Volvo sedan, only a couple of
|
|
years old and easily the classiest car my family had ever owned. To the
|
|
best of my recollection, as of New Year's of my senior year, I had never
|
|
driven that car. However, I was going to a New Year's party—in fact, I
|
|
was going to chauffeur four other people—and for reasons lost in the
|
|
mists of time, I was allowed to take the Volvo. So, one crystal clear,
|
|
stunningly cold night, I picked up my passengers, who included Robin
|
|
Viola, Kathy Smith, Jude Hawron...and Alan, whose last name I'll omit in
|
|
case he wants to run for president someday.
|
|
|
|
The party was at Craig Alexander's house, way out in the middle of
|
|
nowhere, and it was a good one. I heard Al Green for the first time,
|
|
much beer was consumed (none by me, though), and around 2 a.m., we
|
|
decided it was time to head home. So we piled into the Volvo, cranked
|
|
the heat up to the max, and set off.
|
|
|
|
We had gone about five miles when I sensed Alan was trying to tell me
|
|
something. As I turned toward him, he said, quite expressively,
|
|
"BLEARGH!" and deposited a considerable volume of what had until
|
|
recently been beer and chips into his lap.
|
|
|
|
Mind you, this wasn't just any car Alan was tossing his cookies in—it
|
|
was my father's prized Volvo. My reactions were up to the task; without
|
|
a moment's hesitation, I shouted, "Do it out the window! Open the
|
|
window!" Alan obligingly rolled the window down and, with flawless aim,
|
|
sent some more erstwhile beer and chips on its way.
|
|
|
|
And it was here that I learned that fast decisions are not necessarily
|
|
good decisions. A second after the liquid flew out the window, there was
|
|
a loud smacking sound, and a yelp from Robin, as the sodden mass hit the
|
|
slipstream and splattered along the length of the car. At that point, I
|
|
did what I should have done in the first place; I stopped the car so
|
|
Alan could get out and finish being sick in peace, while I assessed the
|
|
full dimensions of the disaster. Not only was the rear half of the car
|
|
on the passenger side—including Robin's window, accounting for the
|
|
yelp—covered, but the noxious substance had frozen solid. It looked like
|
|
someone had melted an enormous candle, or possibly put cake frosting on
|
|
the car.
|
|
|
|
The next morning, my father was remarkably good-natured about the whole
|
|
thing, considering, although I don't remember ever actually driving the
|
|
Volvo again. My penance consisted of cleaning the car, no small
|
|
punishment considering that I had to take a hair dryer out to our
|
|
unheated garage and melt and clean the gunk one small piece at a time.
|
|
|
|
One thing I learned from this debacle is to pull over very, very quickly
|
|
if anyone shows signed of being ill, a bit of wisdom that has proven
|
|
useful a suprising number of times over the years. More important,
|
|
though, is the lesson that it almost always pays to take at least a few
|
|
seconds to size up a crisis situation and choose an effective response,
|
|
and that's served me well more times than I can count.
|
|
|
|
There's a surprisingly close analog to this in programming. Often, when
|
|
faced with a problem in his or her code, a programmer's response is to
|
|
come up with a solution as quickly as possible and immediately hack it
|
|
in. For all but the simplest problems, though, there are side effects
|
|
and design issues involved that should be thought through before any
|
|
coding is done. I try to think of bugs and other problem situations as
|
|
opportunities to reexamine how my code works, as well as chances to
|
|
detect and correct structural defects I hadn't previously suspected; in
|
|
fact, I'm often able to simplify code as I fix a bug, thanks to the
|
|
understanding I gain in the process.
|
|
|
|
Taking that a step farther, it's useful to reexamine assumptions
|
|
periodically even if no bugs are involved. You might be surprised at how
|
|
quickly assumptions that once were completely valid can deteriorate.
|
|
|
|
For example, consider floating-point math.
|
|
|
|
### Not Your Father's Floating-Point {#Heading3}
|
|
|
|
Until last year, I had never done any serious floating-point (FP)
|
|
optimization, for the perfectly good reason that FP math had never been
|
|
fast enough for any of the code I needed to write. It was an article of
|
|
faith that FP, while undeniably convenient, because of its automatic
|
|
support for constant precision over an enormous range of magnitudes, was
|
|
just not fast enough for real-time programming, so I, like pretty much
|
|
everyone else doing 3-D, expended a lot of time and effort in making
|
|
fixed-point do the job.
|
|
|
|
That article of faith was true up through the 486, but all the old
|
|
assumptions are out the window on the Pentium, for three reasons: faster
|
|
FP instructions, a pipelined floating-point unit (FPU), and the magic of
|
|
a parallel FXCH. Taken together, these mean that FP addition and
|
|
subtraction are nearly as fast as integer operations, and FP
|
|
multiplication and division have the potential to be much faster—all
|
|
with the range and precision advantages of FP. Better yet, the FPU has
|
|
its own set of eight registers, so the use of floating-point can help
|
|
relieve pressure on the x86's integer registers, as well.
|
|
|
|
One effect of all this is that with the Pentium, floating-point on the
|
|
x86 has gone from being irrelevant to real-time 3-D to being a key
|
|
element. Quake uses FP all the way down into the inner loop of the span
|
|
rasterizer, performing several FP operations every 16 pixels.
|
|
|
|
Floating-point has not only become important for real-time 3-D on the
|
|
PC, but will soon become even more crucial. Hardware accelerators will
|
|
take care of texture mapping and will increase feasible scene
|
|
complexity, meaning the CPU will do less bit-twiddling and will have far
|
|
more vertices to transform and project, and far more motion physics and
|
|
line-of-sight calculations and the like as well.
|
|
|
|
By way of getting you started with floating-point for real-time 3-D, in
|
|
this chapter I'll examine the basics of Pentium FP optimization, then
|
|
look at how some key mathematical techniques for 3-D—dot product, cross
|
|
product, transformation, and projection—can be accelerated.
|
|
|
|
### Pentium Floating-Point Optimization {#Heading4}
|
|
|
|
I'm going to assume you're already familiar with x86 FP code in general;
|
|
for additional information, check out Intel's *Pentium Processor User's
|
|
Manual* (order \#241430-001; 1-800-548-4725), a book that you should
|
|
have if you're doing Pentium programming of any sort. I'd also recommend
|
|
taking a look around [http://www.intel.com](http://www.intel.com).
|
|
|
|
I'm going to focus on six core instructions in this section: FLD, FST,
|
|
FADD, FSUB, FMUL, and FDIV. First, let's look at cycle times for these
|
|
instructions. FLD takes 1 cycle; the value is pushed onto the FP stack
|
|
and ready for use on the next cycle. FST takes 2 cycles, although when
|
|
storing to memory, there's a potential extra cycle that can be lost, as
|
|
I'll describe shortly.
|