I've been planning on writing an API abstraction layer for my rendering engine. The two APIs I want to include are D3D11 and D3D12. So I started by writing some interfaces and their respective implementation for each API.
The following code snippet examplifies this:
class IDevice
{
//... (pure) virtual methods
};
class CD3D11Device : public IDevice
{
//... virtual method implementations
};
class CD3D12Device : public IDevice
{
//... virtual method implementations
};
So far so good. Now to the actual problem:
If I have another interface with a method that requires a IDevice*
as parameter, how can I ensure that the "right" device is passed?
class ISomeClass
{
public:
virtual void foo(IDevice* pDev) = 0;
};
class CD3D11SomeClass : public ISomeClass
{
public:
virtual void foo(IDevice* pDev) override
{
// should only be passed CD3D11Device
}
};
class CD3D12SomeClass : public ISomeClass
{
public:
virtual void foo(IDevice* pDev) override
{
// should only be passed CD3D12Device
}
};
I know that I could call dynamic_cast
on the IDevice*
pointers every time and check for nullptr
but that is tedious as well as expensive in respect to performance.
Is there some elegant solution to this problem? Does anybody of you guys know how professional/commercial game engines cope with that?
You won't be able to abstract D3D11
and D3D12
together unless you go way farther in the abstraction than a mere wrapping of their interface. Their design are too symmetrically opposed. What you need is to design a single highly abstract rendering engine interface. Things like Material
, Image
or Model
should be the strict bottom along side things like Scene
or RenderList
.
As for the support of multiple graphics API in a single application, you get it wrong here, there is no point in a D3D11
code path if you have D3D12
, the choice should be D3D11/GL
versus D3D12/Vulkan
. And this is not because of API similarity, it is because of the feature set you need in your application.
Because be advice, D3D12
is not meant to replace D3D11
, the former exist for an 1% of applications like AAA games or heavy GPGPU on large dataset. If you are not an expert at D3D11
already and don't know why precisely you have to use D3D12
, don't use it !