
DOOM 3 BFG Technical Note [pdf] - angersock
http://fabiensanglard.net/doom3_documentation/DOOM-3-BFG-Technical-Note.pdf
======
mcphilip
I love reading about the development of the doom series. One of my early
exposures to reading non-trivial code came from studying the (very
surprisingly complex) damage output of the BFG9000:

[http://www.gamers.org/docs/FAQ/bfgfaq/#3A](http://www.gamers.org/docs/FAQ/bfgfaq/#3A)

~~~
tadfisher
I used to play competitive DOOM (was in the ZDaemon top 10 almost a decade
ago), and while the BFG9000 was certainly the most powerful weapon in the
game, it was also the most seriously misunderstood.

New players would always attempt to spam the BFG in a crowded room, then duck
behind a corner or run away. Due to the mechanics of the BFG, this is the
opposite of the correct strategy.

A short time after a BFG impact with any surface or object, the game basically
performs a cluster of hitscans radiating from the _player_ in the direction
the shot was fired. Thus the most effective BFG strategy is to stand to the
side of an entrance to a crowded room, shoot the BFG at a wall, and strafe
toward the entrance until as many enemies as possible come into view.

Get the timing right, and you turn the room into an uninhabitable no-man's
land until your six shots run out (ten if you grab the ammo backpack).

I miss those days :)

------
angersock
What's really interesting is the section on linked-lists: author seems to
suggest that yeah, arrays of pointers have much better performance.

I'm curious what sort of performance they run into in MT environments--
lockless applications are handy with linked-lists.

~~~
eliasmacpherson
I only clicked to see the comments because it said Doom 3.

Thanks for posting the article and thanks for pointing out the section on
linked lists. I agree that that section is really interesting. In what sense
do you mean lockless applications - applications built around compare and swap
primitives or something else?

I can't really follow what:

"byte otherMembers[64]" is used for.

What useful data is stored in there? If pointers are 32bit and cache lines are
64bit, the comment:

"// over a cache line worth of other members"

doesn't really make sense because you can only fit two full addresses per
cache line.

It's a shame that the idList type he is suggesting in favour of the other
types, a resizeable heap array, is not declared in the body of the pdf. Might
be worth looking it up.

The distinction between non-intrusive and intrusive linked lists is new to me,
I didn't know there was a word for that!

This is the best "link" I've found on them:

[http://www.altdevblogaday.com/2011/12/06/intrusive-
lists/](http://www.altdevblogaday.com/2011/12/06/intrusive-lists/)

~~~
hrydgard
Cache lines on modern architectures are usually 64 or sometimes even 128
bytes, not bits.

~~~
eliasmacpherson
Thank you, I misread this from the article as saying 64 bit cache lines:
"(assuming 32 bit pointers and 64 byte cache lines)"

So:

byte otherMembers[64];

is 512bits of addresses to other members, that will hold 16 32bit addresses.

From the article: "In the case of an array with pointers there may still be a
cache miss when reading the ‘valid’ flag but there will be at most one
additional cache miss every 16 pointers"

so idList must use operator[] to sensibly iterate over otherMembers.

class idMyClass {

    
    
        bool valid;
        byte otherMembers[64]; // over a cache line worth of other members
    

};

idList< idMyClass * > myObjects;

for ( int i = 0; i < myObjects.Num(); i++ ) {

    
    
        if (myObjects[i]>valid ) {
        }
    
    }

------
larrik
Very interesting. I'm just sad they dropped Linux support in the process, just
before Linux gaming is taking off.

~~~
mortyseinfeld
Oh really? What makes you think Linux gaming is just about to take off?
Something to do with Valve?

~~~
pachydermic
Between that and the humble indie bundles (or just indie games in general), I
think it's fair to say Linux gaming is looking much more exciting and
healthier than it has ever been in the past (at least the recent past).

Does that mean it's "about to take off?" I guess we'll just have to wait and
see. I certainly hope so. Games have always meant pushing technological
boundaries, so if games get big on Linux it will hopefully move the whole OS
forwards. Finally, the year of the Linux desktop is upon us! (...don't worry
about those pesky locked-down mobile devices)

Well... a man can dream, at least.

------
npinguy
I swear, as a C#/Java/Javascript developer, reading stuff like this just makes
me feel like a shitty developer. I know I'm a very competent programmer and
architect but I feel like I could not grasp this kind of low level
optimization even if I tried.

~~~
breckinloggins
Trust me, if you're really a good developer you'd be able to swap all this
stuff in your head in a reasonable amount of time.

For example: I'm not generally a Java guy and I'm not an Android expert, but I
once had to create an android touch interface to some custom hardware... and
it had to run on one of the first "embedded tablet-like" systems available
(this was 2009-ish).

In a month or so, I went from knowing nothing about Android and being
extremely rusty with Java to:

\- Doing nifty tricks in Java to make code DRY and maintainable

\- Writing a fancy flashy Android app

\- Using the NDK to write a native component that integrated the app with a
couple of device drivers

\- Deeply investigating the performance characteristics of the Dalvik VM and
tuning all sorts of things (both in the OS and in my code) to keep things
working smoothly

Could I do any of this again right this second? Nope. I've moved to other
projects and other technologies and all this has been swapped out of my head.
But the point is that I could get back there again if I needed to.

As a "good developer", you would no doubt experience something similar in this
situation. If someone sat you down with a poorly-performing game, some C++
code, and pointed you to enough reference information and profiling tools, in
a few weeks you, too, would be talking about cache misses and alignment
boundaries and SIMD intrinsics, and...

The funny thing about tech jargon is 99% of it sounds like gibberish even to
those of us who've been there before! Don't be too hard on yourself :)

------
drill_sarge
the newer virtual texturing stuff is much more interesting

[http://s09.idav.ucdavis.edu/talks/05-JP_id_Tech_5_Challenges...](http://s09.idav.ucdavis.edu/talks/05-JP_id_Tech_5_Challenges.pdf)

edit:

[http://mrelusive.com/publications/presentations/2012_siggrap...](http://mrelusive.com/publications/presentations/2012_siggraph/Virtual_Texturing_in_Software_and_Hardware_final.pdf)

------
Tibbes
Does anyone know the purpose of the self-assignment on page 3? (in the body of
_IsWriteCombined_ )

    
    
      DWORD error = GetLastError();
      error = error

~~~
corysama
I often do that just to have a statement on which to place a breakpoint. It
gets optimized out, but in debug builds it works fine. Putting a breakpoint on
a line that just deals with the error code immediately after the error code
will reliably display the error in the Auto Variables watch window in VStudio
maligning it very convenient for rapid debugging.

------
null_ptr
No need for the scribd link, Firefox's built-in PDF reader has taken all the
Pain out of PDFs for me :)

~~~
adamnemecek
I think that those are added automatically, scribd was in YC after all.

~~~
steveklabnik
That is correct on both counts.

