Abstract for DirectX 9 and 10

Started by
10 comments, last by Decibit 14 years, 1 month ago
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
Advertisement
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.
Don't forget to visit my blog here.
Hey! Just let noobs be noobs, after all, we once were noobs right?
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)
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
Don't forget to visit my blog here.
Hey! Just let noobs be noobs, after all, we once were noobs right?
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.
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

Don't forget to visit my blog here.
Hey! Just let noobs be noobs, after all, we once were noobs right?
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.
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.

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...

Don't forget to visit my blog here.
Hey! Just let noobs be noobs, after all, we once were noobs right?
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.

This topic is closed to new replies.

Advertisement