2017-08-06 29 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,請不要使用它!