The Event Model and Managed DirectX


Managed DirectX has plenty of events that it captures and fires in a normal application. Every single managed graphics object hooks certain events on the device to ensure that it can behave correctly.

For example, when a device is reset (due to a window resize or a switch to or from full screen), any object stored in the default memory pool needs to be disposed. Many objects also have something to do after the device is reset. In the default case, each object that needs to be disposed before a reset hooks the DeviceLost event, and the items who also have post-reset work hook the DeviceReset event.

This scenario doesn't even consider the fact that each object hooks the device's Dispose event. In short, if events are being hooked, every Direct3D object will have a hook on the device. So why is this a problem?

Take this seemingly "safe" code as an example (assuming swapChain is a valid swap chain and device is a valid Direct3D device):

 device.SetRenderTarget(0, swapChain.GetBackBuffer(0, BackBufferType.Mono)); device.DrawPrimitives(PrimitiveType.TriangleList, 0, 500); 

Looks simple enough, just using the back buffer of the swap chain as the render target. However, if the events are being hooked, a lot more is going on here. The GetBackBuffer call returns a new surface representing the current back buffer of the swap chain. This object hooks the device lost and disposing events, which are at least three allocations (the actual surface, along with the two event handlers).

Worse than that, this object (which is only used for a brief period of time) is never collected, as long as the device is still alive, because it has hooked events on the device. This memory (and these objects) are never reclaimed. The objects eventually get promoted to generation two, and memory usage on your application will just as steadily rise. Imagine a game running at 60 frames per second, each frame calling this code.

To think, we haven't hit the end of the problems yet either! Imagine the game running at 60 frames per second that has been running for 2 minutes. The device's dispose event has 7,200 objects hooked, and the Dispose method is invoked because the application is shutting down. It takes a significant amount of time to propagate this event, so it appears that your application has locked up (when in reality it is simply notifying every object that the device is now gone).

A more efficient way of writing this code is something like the following:

 using (Surface buffer = swapChain.GetBackBuffer(0, BackBufferType.Mono)) {     device.SetRenderTarget(0, buffer);     device.DrawPrimitives(PrimitiveType.TriangleList, 0, 500); } 

In this scenario, you get rid of the objects immediately. Yet you still have the underlying "problem" of the event hooking.

An even better solution is to turn off the event hooking within Direct3D completely. You can use a static property on the device to do this:

 Device.IsUsingEventHandlers = false;  

If you do this before you create your device, you completely turn off the internal event handling for Direct3D. Beware of doing it, though, because you need to manage the object lifetimes yourself. Remember from early in the book, the sample framework does this management automatically. Now you know the reason.

The default behavior of device hooks is extremely convenient, but if you want top performance, you might want to avoid the default event code. At least understand when and how the events are hooked, and structure your code to be as fast as possible (such as using the second code snippet over the first).



Beginning 3D Game Programming
Beginning 3D Game Programming
ISBN: 0672326612
EAN: 2147483647
Year: 2003
Pages: 191
Authors: Tom Miller

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net