【问题标题】:API abstraction layer - avoid mixing of API interfacesAPI 抽象层 - 避免 API 接口的混合
【发布时间】:2017-08-06 18:42:38
【问题描述】:

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

以下代码 sn-p 对此进行了举例说明:

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

我知道我可以每次都在IDevice* 指针上调用dynamic_cast 并检查nullptr,但这在性能方面既乏味又昂贵。

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

【问题讨论】:

  • 你不应该关心传递了哪个IDevice 类型。这就是抽象接口的全部意义所在。
  • 我投了赞成票,因为很多人试图用他们的图形引擎做这种事情。不过我的经历有点不同。我尝试在任何给定版本中坚持一个 API 版本,以避免所有这些问题。您支持的每个 API 都会使您必须执行的测试量翻倍。

标签: c++ interface directx-11 directx-12 abstraction-layer


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 2016-10-02
    • 1970-01-01
    • 2011-02-25
    • 2011-11-11
    • 2019-03-19
    • 2015-08-18
    相关资源
    最近更新 更多