Graphics Layers for different for Directx11 and Directx12

Started by
11 comments, last by andur 9 years, 10 months ago

Hi .

Well I'm in the middle of developing a graphics engine and I heard about the Directx12 . I want that in future I can get Directx12 support to my engine with minimal effort . So I think I have to create a Graphics layer that objects call that and that layer get in to contact with the graphics API.

How should this be done ? Is there any standandard form ? any example ?

Advertisement
My engine has 7 rendering back-ends, with plans to support 4 more, including D3D12 :D

The approach I take is that I have header files full of platform-agnostic structures/enum/interfaces/functions, e.g.
• an enum of comparison modes for depth testing,
• a struct describing the depth/stencil state,
• a device class, contexts, states, etc
• a CreateDevice function
etc

I then have many cpp files that implement then stuff in these headers, e.g. I'd have a single Device.h, and then Device_D3D11.cpp, Device_D3D9.cpp, etc...

I then compile the exe using only one set of these cpp files - e.g. I'd end up with Game_D3D11.exe, Game_D3D12.exe, etc...
You can then have a 'launcher' exe choose the right one automagically -- when the user runs Game.exe, it will check for D3D 12, 11 and 9 compatibility and then run the appropriate exe.


As for your actual platform-agnostic API, you need to take care in how you design it. If you model it on just one back-end-API, then that implementation will be a simple wrapper, but the implementations for other back-ends may involve complicated emulation.
You need to find a common abstraction that's easily implemented on all of your target back-ends.

That's nice . I think this the fastest way . Maybe function pointers come handy at this situation . Instead of havina a launcher the application can in realtime assign appropriate functions that the platform supports to the pointers . And then application moves on with calling only these function pointers .

I then have many cpp files that implement then stuff in these headers, e.g. I'd have a single Device.h, and then Device_D3D11.cpp, Device_D3D9.cpp, etc...

This is what we do at work.

Maybe function pointers come handy at this situation . Instead of havina a launcher the application can in realtime assign appropriate functions that the platform supports to the pointers . And then application moves on with calling only these function pointers .


That would be a great way to make a mess of your code, and since the application would link to both Direct3D 11 and Direct3D 12, only people running Direct3D 12 could run it, making Direct3D 11 a useless parasitic twin.

If you took anything away from what Hodgman said let it be the part regarding multiple executables. This is standard in the industry for a reason.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

That would be a great way to make a mess of your code, and since the application would link to both Direct3D 11 and Direct3D 12, only people running Direct3D 12 could run it, making Direct3D 11 a useless parasitic twin.


You could, of course, push the API specific code into a DLL and at runtime detect and load the correct DLL in which would remove that problem.

Granted, it brings with it other things to consider but it's also not an uncommon way to do things.

Since I am using c# there is no concept of headers or such things . What I am thinking right now is using interfaces , delegates and virtual methods to make things clear .

When I link direct3d11 and direct3d12 to my project (sharpdx versions in my case) they are loaded but as far as I don't initialize a device on direct3d12 is that going to cause a problem ?

When I don't initialize the direct3d12 device how is that going to cause a problem ?

Since I am using c# there is no concept of headers or such things . What I am thinking right now is using interfaces , delegates and virtual methods to make things clear .

When I link direct3d11 and direct3d12 to my project (sharpdx versions in my case) they are loaded but as far as I don't initialize a device on direct3d12 is that going to cause a problem ?

When I don't initialize the direct3d12 device how is that going to cause a problem ?

At least you need to provide many final compiled objects (EXEs or DLLs) as many platform you want to support since if you put and link all together in a single executable you will require the final user to have a system supporting all those implementations!

As Hodgman and phantom suggested:

- you can provide many different executables as many platform you want to support (e.g.: game11.exe, game12.exe, gameOGL.exe)

- you pack every single API stuffs implementation into a DLL for each platform and then dynamically link the right DLL to the final executable depending on which platform the executable is running (eg: game.exe, gfx11.dll, gfx12.dll, gfxogl.dll)

You can also provide a luncher and let the user choose the implementation supported by the system, using one of the above solutions (eg: luncher.exe, game11.exe, game12.exe, gameOGL.exe OR luncher.exe, game.exe, gfx11.dll, gfx12.dll, gfxogl.dll).

In my opinion the DLL option is better for maintenance reasons.

This matter is valid not only for graphics or gaming, but for every software that need to target multiple platforms and systems requirements.

"Recursion is the first step towards madness." - "Skegg?ld, Skálm?ld, Skildir ro Klofnir!"
Direct3D 12 quick reference: https://github.com/alessiot89/D3D12QuickRef/

We also do things similar to how Hodgman described, except in our cases we have "Windows" and "PS4" platforms that extend into areas beyond just the graphics API's.

In my hobby project i have some abstract classes(interfaces) for graphics rendering like: Vertex Buffer, Shader, Texture etc.

Any new rendering system(OGL, DirectX) needs to implement those classes.

Also i'm loading it as .dll plugin so it libraries can be run-swapped and there is no need for recompiling code for those subsystems.

The biggest price you pay for this interfacing are cache misses which can damage your cpu performance, but for home projects that shouldn't be that big problem

Since I am using c# there is no concept of headers or such things . What I am thinking right now is using interfaces , delegates and virtual methods to make things clear .

When I link direct3d11 and direct3d12 to my project (sharpdx versions in my case) they are loaded but as far as I don't initialize a device on direct3d12 is that going to cause a problem ?

When I don't initialize the direct3d12 device how is that going to cause a problem ?

To be honest I don't think you should be worrying about this right now. D3D12 is at least a year away, we don't yet know what the interface is going to be like, so trying to pre-empt an unreleased API version doesn't seem like good sense. It would be better to focus on doing a good job with D3D11 instead.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

This topic is closed to new replies.

Advertisement