Archive for the ‘Game Programming’ Category

I’ve taken back up a hobby project of mine from some years ago: an XNA game.  This has been a learning experience for me, with the biggest lesson learned being, despite all these years in programming and design in games, I’m still as ignorant about programming as a most men are about women (HA!).

Example number one: I had put together a flock of renderables, and observed a rather distressing artifact: they rendered extremely slowly, and stuttered every couple seconds.  Now, this sort of behavior has a pretty obvious source, if you’ve worked in any kind of automatically-garbage-collected language, like java or C#.  I was creating objects frequently, then deleting them, which happens when the garbage collector runs a  pass.  Since deleting unreferenced objects takes a bit of time, if you’re deleting a lot of things at once, you expect the program to halt for a bit while that happens.  So here I was, deleting a bunch of crap every couple seconds, probably in a draw call.

Yep, there were ‘news’ in my draw calls; in fact, I wasn’t just creating new objects, I was allocating and de-allocating vertex buffers every frame.  In my defense, I wasn’t sure of the XNA paradigm here, but really, this should have been kind of obvious.  Allocating a vertex buffer involves contacting the video card and saying “Hey, I need some space to store vertex data.  Here’s what that entails, now give me enough space to hold x number of verts of that sort”.  Contacting the video card is a lengthy process; generally, you want to do that as little as possible, passing along the smallest amount of information every frame as possible, using the fastest possible channels.  Yet here I was, trying to get the video card to perform an expensive operation, on top of the expense of garbage collection, every frame.

I quickly switch to allocating the vert buffer on object creation, setting the data in the buffer when it was initialized (or changed), and never touching it again.  Most of the stuff you’re going to do to objects, like translations or rotations, could be done much faster using a vert shader.  That sped up rendering dramatically and killed the stuttering.

I then learned that, even when you don’t do anything special, passing shader constants to the video card can be expensive, as can DrawPrimitive calls (which is one of the functions you call to render the data in the vert buffer).  I really couldn’t tell you the upper limit, though 5,000 calls was enough to begin bogging down my personal machine in debug mode (release ran fine).  At this point, I feel no obligation to attempt to optimize that, as 5,000 onscreen objects is excessive.  However, should I need to, I could attempt to implement instancing in XNA.

Instancing in graphics is a bit akin to instancing as MMO players know it for MMOs.  Basically, you tell the video card to use this one set of verts (say a model, like a tree or some ground cover or foliage) a bunch of times.  You then tell it that the special data (shader constants) for each instance of that vert set is over here in this other place, and tell it to go.  While you still have to pass over all that constant data, it’s still less data then passing over all those constants plus all the verts, it happens in a single stream, and reduces some of the overhead on the card for draw calls.

I might have to do that for any kind of particle system I might want…

Read Full Post »