2017-08-06 30 views
1

我一直在计划为我的渲染引擎编写一个API抽象层。我想包含的两个API是D3D11和D3D12。 因此,我开始通过为每个API编写一些接口和它们各自的实现。API抽象层 - 避免混合API接口

下面的代码片段examplifies这样的:

class IDevice 
{ 
    //... (pure) virtual methods 
}; 

class CD3D11Device : public IDevice 
{ 
    //... virtual method implementations 
}; 

class CD3D12Device : public IDevice 
{ 
    //... virtual method implementations 
}; 

到目前为止好。现在到实际问题: 如果我有一个方法,需要IDevice*作为参数的另一个接口,我如何确保“正确的”设备通过?

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 
    } 
}; 

我知道我可以每次打电话dynamic_castIDevice*指针和检查nullptr但针对的是性能繁琐和昂贵。

有没有一些优雅的解决这个问题?你们有没有人知道专业/商业游戏引擎如何应对?

+5

你不应该关心哪个'IDevice'类型被传递。这就是抽象接口的全部要点。 – juanchopanza

+1

我高举起来是因为很多人试图用他们的图形引擎来做这种事情。虽然我的经验有点不同。我尝试使用任何给定的发行版来坚持一个API版本,以避免所有这些问题。您支持的每个API都会使您必须执行的测试量翻倍。 – Robinson

回答

1

您将无法抽象D3D11D3D12在一起,除非你走更远的路在抽象比他们的接口仅仅是包装。他们的设计过于对称。你需要的是设计一个高度抽象的渲染引擎接口。诸如Material,ImageModel之类的东西应该是严格的底线,如SceneRenderList

至于在单个应用程序来支持多图形API,你得到它错在这里,有一个D3D11代码路径没有意义,如果你有D3D12,应选择D3D11/GLD3D12/Vulkan。这不是因为API的相似性,这是因为您的应用程序需要功能集。

因为是建议,D3D12不是要取代D3D11,前者对于大型数据集中的AAA游戏或重型GPGPU等应用程序存在1%。如果您不是D3D11的专家,并且不知道为什么您必须使用D3D12,请不要使用它!