Ah, the good ol’ render loop. Everyone’s favorite topic of conversation. As I’m sure everyone is aware, the Managed DirectX samples that shipped with the DirectX9 SDK as well as the Summer 2003 update used the ‘dreaded’ DoEvents() loop I speak so negatively about at times. People also probably have realized my book used the ‘infamous’ Paint/Invalidate method. I never really made any recomendations in the earlier posts about which way was better, and really, I don’t plan on it now. So why am I writing this now?!?!
If you read David’s post about the upcoming 2004 Update, you may have noticed that he mentions the DoEvents() methods that samples used to employ is gone. In all reality, along with the new sample framework, the samples themselves actually never use the Windows Forms classes anymore either. The actual render window and render loop are all run through P/Invoke calls into win32, and I figured I’d take a quick minute to explain the reasoning behind it.
Obviously the idea of using DirectX is for game development. Sure, there are plenty of other non-game development scenarios that DirectX is great for (data visualization, medical imaging, etc), but what drives our API are the game developers. If you know any game developers (or are one yourself), you’re probably vastly aware that while the game is running (and rendering), things need to happen quickly, and predictably. With all the benefits of managed code, one thing that can be hard to achieve is that ‘predictability’, particularly when you’re dealing with the garbage collector.
So let’s say you decided to use Windows Forms for your rendering window, and you wanted to watch what the mouse was doing, so you hook the MouseMove event. Aside from the ‘cost’ of the Invoke call to call into your handler, a managed object (the mouse event arguments) is created. *Every* time. Now, the garbage collector is quite efficient, and very speedy, so this alone could be easily handled. The problem arises when your own ‘short lived’ objects get promoted to a new generation due to the extra collections these events are taking. Generation 0 collections won’t have any effect on your game, generation 2 collections on the other hand will.
Thus the new sample framework doesn’t rely on these constructs at all. This is probably one of the ‘most efficient’ rendering loop available in the managed space currently, but the code doesn’t necessarily follow many of the constructs you see in the managed world. So, when deciding on the method you want to use to drive your rendering, you need to ask yourself what’s more important? Performance, or conformance? In the case of the updated sample framework, we’ve chosen performance. Your situation may be different.