Saturday, March 27, 2010

Resolving the D3DX9 versioning problem

I've decided to resolve the old "This application has failed to start because d3dx9_38.dll was not found" problem by dynamically loading the DLL and entrypoints instead. The way I do it is by counting down from a sufficiently high number (DirectQ is known to work with versions up to the latest, which is 42), attempting to load the DLL for that number, and if succeeding attempting to load all of the entry points for the functions I use. If all of those succeed I accept that DLL as the version I'm going to use.

This is a far more acceptable solution to me than enforcing a specific version of D3D9 on you, and will even work with your crusty old Windows 2000 RTM machine that you put the first version of DirectX 9 on and have never upgraded since. At some point in the future it might even be possible to make the D3DX version used user-selectable, so that you can - for example - experiment with differences between using the D3D9 and D3D10 shader compilers and pick the one that works best for you.

If all of this sounds suspiciously like the old wglGetProcAddress malarkey that you had to do when setting up OpenGL, well that's because it is. Frankly I smell a rat, and think that this is something that MS should have put into a single master DLL so that pain from it wouldn't be inflicted on the rest of us. Oh well.

On the other hand the advantages of being able to experiment with different versions due to using dynamic loading are a Good Thing to have, so it's an ill wind etc...

Update: I can now dynamically load different versions of the D3DX DLL at runtime (including while a map is playing). This is pretty neat and will enable you to select between the D3D9 and D3D10 shader compilers if you want (I don't know if the D3D11 compiler is available to D3D9, although from a check of my XP box it looks like it is).

It's controlled by a d3dx_version cvar which defaults to 42, the highest version I have tested with. The lowest legal value is 24, basically because there are no prior versions of the DLLs available. Setting it to -1 will use the best available version.

From the looks of things, 33 appears to be the D3D10 compiler and 42 appears to be the D3D11 compiler. Note that my HLSL shaders don't compile on any version prior to 32, so it'll revert back to fixed mode.

This of course isn't robustly tested, so you shouldn't be wildly switching between different versions at run time (and then complaining to me that it crashes).

1 comments:

Coranth said...

Hmmm... your next project will be getting DirectX 11 to work with Windows XP, I'm sure... :)

Why the hell don't Microsoft think like you do? Dunderheads!