2017-08-06 5 views
1

J'ai prévu d'écrire une couche d'abstraction API pour mon moteur de rendu. Les deux API que je veux inclure sont D3D11 et D3D12. J'ai donc commencé par écrire des interfaces et leurs implémentations respectives pour chaque API.Couche d'abstraction de l'API - évite le mélange des interfaces API

L'extrait de code ci-dessous examplifies ceci:

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

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

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

Jusqu'à présent, si bon. Maintenant, au problème réel: Si j'ai une autre interface avec une méthode qui nécessite un IDevice* comme paramètre, comment puis-je m'assurer que le «bon» périphérique est passé?

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

Je sais que je pourrais appeler dynamic_cast sur les pointeurs IDevice* chaque fois et vérifier nullptr mais qui est pénible et coûteuse en ce qui concerne la performance.

Y at-il une solution élégante à ce problème? Est-ce que quelqu'un d'entre vous sait comment les moteurs de jeu professionnels/commerciaux font face à cela?

+5

Vous ne devez pas vous soucier du type 'IDevice' qui est passé. C'est tout le point des interfaces abstraites. – juanchopanza

+1

J'ai mis à jour parce que beaucoup de gens essaient de faire ce genre de chose avec leurs moteurs graphiques. Mon expérience est un peu différente cependant. J'essaie de coller à une version de l'API avec une version donnée, évitant ainsi tous ces problèmes. Chaque API que vous prenez en charge double le nombre de tests à effectuer. – Robinson

Répondre

1

Vous ne serez pas en mesure de résumer D3D11 et D3D12 ensemble, sauf si vous allez plus loin dans l'abstraction que d'un simple emballage de leur interface. Leur conception est trop symétriquement opposée. Ce dont vous avez besoin est de concevoir une seule interface de moteur de rendu très abstrait. Des choses comme Material, Image ou Model devrait être le bas strict le long des choses secondaires comme Scene ou RenderList.

En ce qui concerne le soutien de plusieurs API graphique dans une seule application, vous vous trompez ici, il n'y a pas de point dans un chemin de code D3D11 si vous avez D3D12, le choix devrait être D3D11/GL par rapport D3D12/Vulkan. Et ce n'est pas à cause de la similarité API, c'est à cause de l'ensemble de fonctionnalités dont vous avez besoin dans votre application.

Parce que soyez avis, D3D12 n'est pas destiné à remplacer D3D11, les premiers existent pour 1% d'applications comme les jeux AAA ou GPGPU lourd sur un grand ensemble de données. Si vous n'êtes pas déjà un expert au D3D11 et que vous ne savez pas exactement pourquoi vous devez utiliser D3D12, ne l'utilisez pas!