Skip to main content
GameDev.net gamedev.net
🔒 Locked

Having support for DX9 , DX10 , DX11

Started by Xsy Nov 4, 2009 at 11:44 AM 13 replies 8.9k views
Original Post
Xsy
Xsy
Hello. I want my game to support different software and hardware platforms automatically. Example of what I want to do: * User has Windows7 - DX11 Device will be created , if user has old hardware , the device will be created with the appropriate feature level. * User has Windows Vista - If user has a DX10 compatible hardware a DX10 device will be created , if the user has only DX9 compatible hardware than a DX9 device will be created. * User has Windows XP - Only a DX9 device will be created. My question is how I determine this? How do I determine using C++ the windows ( Or the Directx version installed ) the user is running and the hardware type so I can make this selection on the application start.
Erik Rufelt
Erik Rufelt
Try to create the DX11 device, and if it doesn't work, jump down one level. DX11 is available on Vista too if you get the latest updates from Windows Update (SP2 and platform update).
The problem is that if you link to D3D11 in your app, it will fail to start if the D3D11 DLLs aren't available on the system. So to get the same app running on different systems like that, you need to dynamically load D3D11.dll etc. with the LoadLibrary Function.

Xsy
Xsy
Quote:
Original post by Erik Rufelt
Try to create the DX11 device, and if it doesn't work, jump down one level. DX11 is available on Vista too if you get the latest updates from Windows Update (SP2 and platform update).
The problem is that if you link to D3D11 in your app, it will fail to start if the D3D11 DLLs aren't available on the system. So to get the same app running on different systems like that, you need to dynamically load D3D11.dll etc. with the LoadLibrary Function.


Ok that sounds simple enough. But what about people with Windows XP? Isn't XP missing a core component (WDDM) so even loading DX11 DLL's wont help , or would it?

Thank's for the fast reply :>
Erik Rufelt
Erik Rufelt
What I mean is, D3D11.dll isn't available on XP, so LoadLibrary will return an error. Which is OK, you just handle that in your app. If you add D3D11.lib in your project link dependencies however, your app will fail to start with an error box. So you need to load it dynamically, and if it fails, you load D3D10.dll or D3D9.dll instead. (For D3D10/11 you might need to load DXGI.dll also, if you want to use those functions).
Once you have a library handle, you use the GetProcAddress Function, to get a function in that library. For example if you want the D3D11CreateDevice function, you use GetProcAddress(hD3D11Lib, "D3D11CreateDevice"). That will give you the function pointer, and you use that to create your D3D11 device. After that the usage of the ID3D11Device object is the same as before.
You also have to check the return code from the function of course, since someone could put the D3D11.dll DLL on their XP system, but the D3D11CreateDevice function would fail in that case.
Mike.Popoloski
Mike.Popoloski
Quote:
Original post by Erik RufeltIf you add D3D11.lib in your project link dependencies however, your app will fail to start with an error box. So you need to load it dynamically, and if it fails, you load D3D10.dll or D3D9.dll instead.

This is not entirely true. Linking D3D11.lib technically has no bearing on what happens at runtime. It's statically linked to your program at compile time. If you also set a project setting to delay-load the appropriate DLLs (in this case, D3D11.dll and friends), the DLLs won't be loaded until they are called at runtime. You don't even need to use LoadLibrary.

In addition, D3D11 supports hardware all the way down to D3D9 level hardware, so as long as the appropriate drivers are installed you only have to write one version of your code that targets D3D11 and avoids using newer features if you're running on older hardware and you can avoid integrating at least D3D10.

D3D11 is still only supported on Vista and Win7 though, so you may still want a D3D9 renderer if XP support is crucial.
Mike Popoloski | Journal | SlimDX
david_watt78
david_watt78
There is no reason to support dx10. It is obsolete as of dx11 and dx11 feature levels since its supported by vista and 7. The real issue you will face is whether you will support the different features such as tesselation, geometry shaders, and compute shaders. None of these are supported in dx9 if you aren't using any of these features there is no reason to use anything other than dx9. If you are you will have a lot of issue with needing many different sets of shaders and software implementations of features not supported.
Xsy
Xsy
Thank's everyone. Basically I figured out what to do. I found a function (http://msdn.microsoft.com/en-us/library/ms724451%28VS.85%29.aspx) to help me figure out what windows the machine is running. If it's XP , I initiate the DX9 Renderer , if it's Vista or 7 I initiate a DX11 Device with an appropriate feature level.
Erik Rufelt
Erik Rufelt
Quote:
Original post by Mike.Popoloski
Quote:
Original post by Erik RufeltIf you add D3D11.lib in your project link dependencies however, your app will fail to start with an error box. So you need to load it dynamically, and if it fails, you load D3D10.dll or D3D9.dll instead.

This is not entirely true. Linking D3D11.lib technically has no bearing on what happens at runtime. It's statically linked to your program at compile time. If you also set a project setting to delay-load the appropriate DLLs (in this case, D3D11.dll and friends), the DLLs won't be loaded until they are called at runtime. You don't even need to use LoadLibrary.


How does this work if the appropriate DLLs aren't available, and the program should still run?
I have very limited experience with this so perhaps I just don't understand the process, but how would I write the following for example without LoadLibrary:
#include <DXGI.h>#include <cstdio>typedef HRESULT (WINAPI * LPCREATEDXGIFACTORY1)(REFIID, void**);int main() {	HMODULE hDXGI = LoadLibrary(TEXT("dxgi.dll"));	if(hDXGI == NULL) {		DWORD dwErr = GetLastError();		printf("Failed to load dxgi.dll: %u\n", dwErr);	}	else {		LPCREATEDXGIFACTORY1 pCreateDXGIFactory1 = (LPCREATEDXGIFACTORY1)GetProcAddress(hDXGI, "CreateDXGIFactory1");		if(pCreateDXGIFactory1 == NULL) {			DWORD dwErr = GetLastError();			printf("Failed to get the CreateDXGIFactory1 function: %u\n", dwErr);		}		else {			IDXGIFactory1 *pFactory;						HRESULT hResult = pCreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory);			if(FAILED(hResult)) {				printf("CreateDXGIFactory1 failed: 0x%08x\n", hResult);			}			else {				// Use pFactory				printf("IDXGIFactory1 created!\n");								pFactory->Release();			}		}				FreeLibrary(hDXGI);	}		return 0;}
Mike.Popoloski
Mike.Popoloski
You use a function like the one referenced above to determine which version of Windows you are running, and if you're on a non-supported system simply be sure to not call any D3D11 functions. As long as you never call a function from the DLL, it won't try to be loaded by the OS.
Mike Popoloski | Journal | SlimDX
Erik Rufelt
Erik Rufelt
I see. It doesn't work if the system could potentially have support though, as with D3D11. DXGI.dll in this case may or may not also be version 1.1.
Mike.Popoloski
Mike.Popoloski
Potentially have support? You are including the DirectX redist in your installer, so you know that it has support.
Mike Popoloski | Journal | SlimDX
ET3D
ET3D
Note that while DX11 is available for Vista, it won't necessarily exist on all Vista machine. It'd be a good idea to detect this and recommend to the user to install the update.

As for DX9/DX11, I think that it's best to use just one API. Using both DX9 and DX11 will complicate your program's design and implementation considerably. Which one to use will depend on the target audience, but I think that for a game that's being started at this point in time, using DX11 is reasonable for a non-casual game, and making DX10 hardware the base requirement is also possible. The Steam Hardware Survey shows that 70% of users have DX10 hardware, and almost 50% have Vista/Win7. If you're doing an advanced game, it will take quite a bit of time to develop, and by then the majority of gamers are likely to have DX10 capable systems, IMO.
Namethatnobodyelsetook
Namethatnobodyelsetook
As pointed out, you'd ship with, and install either the D3D11 or D3D9 runtimes based on which version of windows is present, so no error handling of delayload is technically required, but it's probably good practice to handle the error cases properly.

We use the delayload technique for XInput (since not everyone has a 360 controller... it's true!) If you attempt to use the DLL, and it cannot be loaded, an exception is thrown, at which point you can stop trying to use that library.

bool InitXInputAndCheckIfXInputAvailable(){    __try     {         XInputEnable(true);    }     __except (EXCEPTION_EXECUTE_HANDLER)    {         return false;    }    return true;}
Xsy
Xsy
ET3D : Yes you are quiet right , some Vista users might still not have the DX11 update , I should definitely address that. About using multiple API's , it's a decision I made a while back because I want to share the game with friends and family , and most of them still only have XP , while a few got Vista and some got W7 ( Including myself ). So I started programming my game with support for several renderers in mind. I currently have a DX11 renderer and happily my design is abstracted enough so I can easily add a DX9 renderer with not much effort.

Namethatnobodyelsetook : Well handling errors is always a good practice , and this case is not an exception to the rule :)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.