Sign in to follow this  
dbgamer

Abstract for DirectX 9 and 10

Recommended Posts

How do you program your game so that it is abstract enough to handle both DirectX 9 and 10 (& maybe 11?) I've been looking for "Abstract DirectX class" / "Managed DirectX" / "DirectX wrapper" but I've got nothing so far. So, I have been googling this for a half hour, and I think I just don't have the terminology correct. I would like to be able to use DirectX 10 methods to do things, but fall back on DirectX 9. Correct things to look for, links, tutorials, anything would be very helpful. Thank you, Matt

Share this post


Link to post
Share on other sites
If you are asking this probably you should attempt it but anyway here's an easy approach (god bless OOP xD)

First you need to create an interface something like:

class IRendererInterface
{
virtual HRESULT InitSystem(int adapter, bool fullscreen...) = 0;
};




then you should code you renderers inheriting from the interface. Like this:

class cDirect3D9Renderer : public IRendererInterface
{
public:
HRESULT InitSystem(int adapter, bool fullscreen...) = 0
{
DoSomemagic();
}
}





You can use a runtime loaded DLL approach to select the actual renderer.

Note: Code here doesn't intends to be actually usable, it's just an example and it's probably wrong xD.

Share this post


Link to post
Share on other sites
There was a presentation about making an engine work with both DX9 and DX10 but I can't find it...I think it was about Hellgate: London but I can't remember.

You could use the interface method proposed by fladur...it can certainly be a clean way to handle it. However if you do this you will end up with a lot of virtual function calls, which have a higher overhead than normal member function calls. To get around that you can use some form of compile-time polymorphism"

1. wrap API-specific code in #ifdefs (pretty ugly)
2. have different .cpp files for different DX versions, and only compile one file depending on which version you're building (requires mucking around with build settings, still usually requires some #ifdefs)
3. use templates (has all of the normal downsides of using templates)

Share this post


Link to post
Share on other sites
Quote:
Original post by MJP
You could use the interface method proposed by fladur...it can certainly be a clean way to handle it. However if you do this you will end up with a lot of virtual function calls, which have a higher overhead than normal member function calls. To get around that you can use some form of compile-time polymorphism"

You certanly worried me about the processor overhead for calling a lot of virtual functions. So can you tell where can I get more info (possibly from you xD) about the performance between calling a virtual function and a "normal" one. As my renderer calls a lot of virtual functions.

Thanks

Share this post


Link to post
Share on other sites
Quote:
Original post by fladur
You certanly worried me about the processor overhead for calling a lot of virtual functions. So can you tell where can I get more info (possibly from you xD) about the performance between calling a virtual function and a "normal" one. As my renderer calls a lot of virtual functions.
A normal function call is just a case of moving the this pointer into ecx, then calling the function.
A virtual function call involves an additional pointer indirection to lookup the v-table, and a couple of additions to get the function address.

It's not a huge overhead, but if you're calling the function several thousand times per frame, you may begin to notice the difference.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
Quote:
Original post by fladur
You certanly worried me about the processor overhead for calling a lot of virtual functions. So can you tell where can I get more info (possibly from you xD) about the performance between calling a virtual function and a "normal" one. As my renderer calls a lot of virtual functions.
A normal function call is just a case of moving the this pointer into ecx, then calling the function.
A virtual function call involves an additional pointer indirection to lookup the v-table, and a couple of additions to get the function address.

It's not a huge overhead, but if you're calling the function several thousand times per frame, you may begin to notice the difference.


Hmm... so probably this is not a good idea for my PreRender() Render() and PostRender() methods :S

Share this post


Link to post
Share on other sites
Quote:
Original post by fladur
Hmm... so probably this is not a good idea for my PreRender() Render() and PostRender() methods :S
Only if you're calling them a few thousand times per frame.

I really wouldn't worry about it unless you're making in excess of 10,000 of these calls per frame - and even then, if it's the cleanest way to do it then it's probably worth the small overhead.

Share this post


Link to post
Share on other sites
I don't know if such middleware exists. The game engines however usually support many rendering APIs. I suggest that you should try one of them if you don't have to write the low-level code for juggling the triangles.

I've implemented some kind of an abstract rendering class myself. It supports DX9, DX10 OpenGL2 and OpenGL3. It worked but required a lot of overhead. In general I had to emulate the DX10 features using the DX9 and OpenGL APIs. Here are some of my design decisions:

  1. The abstract class is designed with DX10 in mind. The feature set was slightly reduced for easier DX9/OpenGL emulation.

  2. Each shader was written several times for each of the APIs.

  3. DX9 and OpenGL2 do not support constant buffers (uniform blocks). Special comments that group the shader variables together and define their offsets in a group were placed in the shader code and parsed at run-time. This information was used to emulate the constant buffers.

Share this post


Link to post
Share on other sites
Quote:
Original post by Decibit
I don't know if such middleware exists. The game engines however usually support many rendering APIs. I suggest that you should try one of them if you don't have to write the low-level code for juggling the triangles.

I've implemented some kind of an abstract rendering class myself. It supports DX9, DX10 OpenGL2 and OpenGL3. It worked but required a lot of overhead. In general I had to emulate the DX10 features using the DX9 and OpenGL APIs. Here are some of my design decisions:

  1. The abstract class is designed with DX10 in mind. The feature set was slightly reduced for easier DX9/OpenGL emulation.

  2. Each shader was written several times for each of the APIs.

  3. DX9 and OpenGL2 do not support constant buffers (uniform blocks). Special comments that group the shader variables together and define their offsets in a group were placed in the shader code and parsed at run-time. This information was used to emulate the constant buffers.


There are a lot of this middlewares i can list a few here:

  • Ogre3D

  • Irrlitch

  • And more...

Share this post


Link to post
Share on other sites
Yeah the actual overhead depends on the platform. On consoles virtual functions might mean instant death, on PC's it may not really matter. In general you really have to be pushing the system pretty hard before function call overhead becomes a significant factor.

Share this post


Link to post
Share on other sites
Virtual functions are the easiest way of doing it. Your actual rendering is going to be far more expensive than the tiny bit of overhead those add.

If you want to support down to DX9-level hardware, you can do it all with DX11 and use its feature levels to run on much older hardware (unless you are only looking to support DX9 natively to maintain Xp compatibility). Then you can use only a single api and not have to duplicate a lot of code.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this