1

我一直在计划为我的渲染引擎编写一个 API 抽象层。我想要包含的两个 API 是 D3D11 和 D3D12。因此,我首先为每个 API 编写了一些接口及其各自的实现。

以下代码片段对此进行了举例说明:

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

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

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

到目前为止,一切都很好。现在到实际问题:如果我有另一个接口,其中的方法需要一个IDevice*as 参数,我如何确保传递“正确”的设备?

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_cast但这在性能方面既乏味又昂贵。IDevice*nullptr

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

4

1 回答 1

1

除非您在抽象中走得更远,而不是仅仅包装它们的接口,否则您将无法抽象D3D11和在一起。D3D12他们的设计太对称了。你需要的是设计一个单一的高度抽象的渲染引擎接口。之类的东西MaterialImageModel应该是严格的底部沿边之类的Scene东西RenderList

至于在单个应用程序中支持多个图形 API,你在这里弄错了,D3D11如果你有,那么代码路径没有意义D3D12,选择应该是D3D11/GLvs D3D12/Vulkan。这不是因为 API 相似,而是因为您的应用程序中需要的功能集。

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

于 2017-08-07T16:20:56.550 回答