Thursday 18 April 2013

Working with D3D9 device Reset()

...lost context and going fullscreen!

At work I got the opportunity (sigh) to work with some DirectX rendering for video pipelines.

A lot of fun was spent in trying to make the graphics card behave correctly during a context restore. When switching fullscreen or changing modes there are very precise steps you must follow or you get very cryptic error messages (by the way using M$ tools is no fun at all and I'll explain why) .

First of all when you switch to fullscreen you need to call Reset() on your device with the new backbuffer size, which *must* correspond to one of the resolution supported by your device (and don't forget to set the refresh rate too).

Before doing so you absolutely need to delete any surface, shader and whatever you allocated with a Get* method, using a proper Release() call. Beware *not* to delete your d3ddevice [1]. Then you just recreate all surfaces and you are done, it make sense to reuse the same initialization code for this purpose.

If you don't do this procedure you can get different results, but usually you'll just get a lot of D3DERR_DEVICELOST after a Present(), and only after it (so don't bother checking for this error anywhere else). Other rendering functions such as StretchRect() will just silently fail.

In order to avoid leaks of any kind and check for other errors you might be tempted to use DirectX Control Panel and turn on the Debug version of DirectX. This might work, but beware that on some architectures (I'm looking at you, NVIDIA ION) you might get a lot of exceptions (especially in within Reset()) that make no sense at all [2]. While normally these reports are useful and the breaks help you find mistakes, sometime it just get frustrating when there is a bug on someone else's code.

So if you get desperate in debugging a perfectly working restoration code, just try disabling debug mode or run your code on another architecture...

[1] Actually you can delete the d3ddevice, but then you don't have to call Reset() and have to recreate both the device and the surfaces again. It works but screen glitches a lot and it's a plain waste of resources.
[2] Error such as "Lost Device Due to Display Uniqueness Change" and "Could not get exclusive mode when we thought we could". If you Google them you'll get a lot of information on how to properly do a context restore, but the solution might be closer than you thing.

No comments:

Post a Comment



All the projects here are under a Creative Commons 3.0 licence! You can use and distribute them as you like (just quote the author so he knows his work is not useless)!

If you wish to get in touch with me write at projectsymphony@gmail.com