Comment savoir si j'abrège trop étroitement les API graphiques?

23

Lorsque vous créez un moteur de rendu qui prend en charge plusieurs API graphiques, vous voudrez généralement résumer votre code dans une sorte de bibliothèque de bas niveau liée à certaines API graphiques comme OpenGL, Vulkan, D3D11 et ainsi de suite;

Ils fonctionnent très différemment les uns des autres, il est donc essentiel de créer une bonne API générique; J'ai lu que vous souhaitiez généralement utiliser un "back-end" qui implémente les fonctionnalités de base pour chaque API que vous souhaitez prendre en charge, et un "front-end" qui est ce qui est utilisé par le programmeur pour dessiner des éléments sur le écran.

Comment savoir si je fais trop d'abstraction serrée?

Gabriele Vierti
la source
5
Êtes-vous sûr à 100% que votre wrapper + Vulkan ou D3D11 est plus rapide que de toujours utiliser OpenGL?
Mooing Duck
@Mooing Duck s'il est utilisé correctement, oui.
Gabriele Vierti
4
J'en doute sérieusement. La plupart des gains dans Vulkan proviennent du fait d'être de très bas niveau et de faire les choses d'une manière très particulière et spécifique. Quelque chose qui est assez générique pour faire la même chose de manière transparente dans OpenGL ou D3D ne peut certainement pas faire cela. Réimplémenter les mêmes choses qu'OpenGL (comme le font de nombreux tutoriels Vulkan, ironiquement) donne 99,99% des mêmes performances, avec 20 fois le travail.
Damon
@Damon, c'est vrai, mais les nouvelles API sont spécifiquement conçues (et non adaptées comme OpenGL) pour fonctionner sur les gpus modernes; en parlant de Vulkan, vous pouvez à peu près utiliser la même API sur chaque plate-forme prise en charge, contrairement à OpenGL, où vous devez utiliser la version "Embedded Systems". À part moins de frais généraux et de fonctionnalités sophistiquées, nous n'avons pas beaucoup, mais à l'avenir, nous pourrions avoir des techniques assez surprenantes qui pourraient s'exécuter plus rapidement en utilisant Vk ou D3D12 plutôt qu'en OGL ou D3D11
Gabriele Vierti

Réponses:

44

Tout d'abord, demandez-vous si cela en vaut la peine de prendre en charge plusieurs API graphiques. L'utilisation d'OpenGL couvrira la plupart des plates-formes et sera "assez bonne" pour tous les projets, sauf les plus ambitieux graphiquement. À moins que vous ne travailliez pour un très grand studio de jeu qui peut se permettre de consacrer plusieurs milliers d'heures-personnes à la mise en œuvre et au test de plusieurs backends de rendu et à moins qu'il n'y ait des fonctionnalités spécifiques à DirectX ou Vulcan, vous avez vraiment voulez montrer, cela ne vaut généralement pas la peine . Surtout si l'on considère que vous pouvez économiser beaucoup de travail en utilisant une couche d'abstraction créée par quelqu'un d'autre (une bibliothèque ou un moteur de jeu tiers).

Mais supposons que vous ayez déjà évalué vos options et êtes arrivé à la conclusion qu'il est à la fois viable et vaut le temps de lancer la vôtre.

Ensuite, les principaux programmeurs sont le juge principal de l'architecture logicielle de votre couche d'abstraction.

  • Sont-ils capables d'implémenter les systèmes de jeu qu'ils souhaitent implémenter sans avoir à s'interroger sur des détails de bas niveau?
  • Sont-ils capables d'ignorer complètement qu'il existe plusieurs API graphiques?
  • Serait-il théoriquement possible d'ajouter un autre backend de rendu sans changer le code frontal?

Si oui, vous avez réussi.

Philipp
la source
2
Une suggestion supplémentaire: vaut-il la peine de souligner que le but est d'atteindre les objectifs dans les puces avec le minimum d'effort - juste atteindre la cible et ne pas aller plus loin? Sinon, chacun d'eux peut se transformer en un lapin pour le développeur typique qui (moi y compris) ne sait souvent pas quand laisser assez bien seul. :) Et aussi que le seul moyen fiable de juger du succès est de développer et de tester l'API de manière itérative avec des utilisateurs réels ; il est impossible de deviner avec précision et conduit à un scénario de lapin de suringénierie.
bob
5
Je voudrais ajouter que, si vous avez vraiment avez pour soutenir les bibliothèques graphiques multiples, il y a certainement un impromptu qui fait tout ce que vous avez besoin, même si vous vraiment ne devriez pas rouler votre propre. (Bien sûr, il y a des exceptions, mais si vous êtes assez inexpérimenté pour demander "à quel point je dois faire une abstraction", vous ne travaillez probablement pas sur un projet qui vous oblige à le faire)
Fund Monica's Lawsuit
Je ne suis pas un développeur graphique, mais en regardant les cadres de compatibilité de l'histoire des bases de données et des systèmes d'exploitation, j'ajouterais que cela ne vaut certainement pas la peine de créer votre propre cadre général . Le framework devra presque certainement sacrifier les performances pour la compatibilité, ce qui signifie probablement que vous ne pouvez pas faire grand-chose avec ces fonctionnalités spécialisées de toute façon. Les cadres existants sont presque certains de mieux gérer ces problèmes en raison d'une utilisation plus large. Maintenant, si vous avez le budget énorme que vous décrivez et que vous souhaitez créer un cadre spécialisé (par exemple pour un jeu ou une série), cela pourrait être plus faisable.
jpmc26
6

Commencez par identifier ce dont vous avez réellement besoin dans la partie «wrapper» de l'API. C'est généralement très, très simple: vous avez besoin des ressources de base (tampons, shaders, textures, état du pipeline) et d'un moyen d'utiliser ces ressources pour construire un cadre en soumettant des appels de tirage.

Essayez de garder toute logique de haut niveau hors de la partie wrapper de l'API. Si vous implémentez une technique d'élimination de scène intelligente dans cette partie de l'API, vous êtes maintenant prêt à dupliquer cette logique dans toutes les implémentations du backend. C'est beaucoup d'efforts supplémentaires, alors restez simple. La gestion de scène doit faire partie d'une partie de niveau supérieur de l'API qui utilise l'encapsuleur plutôt que de faire partie de l'encapsuleur lui-même.

Choisissez les cibles que vous soutiendrez et comprenez-les. Il est difficile d'écrire des wrappers décents pour «tout», et vous n'avez probablement pas besoin de le faire (sans doute vous n'avez pas besoin d'écrire un seul wrapper, comme indiqué dans la réponse de Philipp ). Il est presque impossible d'écrire un wrapper décent si vous ne connaissez pas déjà les API que vous allez encapsuler.

Évaluez régulièrement l'état de votre API. Il doit en général avoir une surface plus petite que les API enveloppées sous-jacentes; si vous vous trouvez à créer des types de wrapper un à un pour chaque structure D3D ou chaque appel de fonction OpenGL, vous vous éloignez probablement du cap.

Regardez ce qui s'est passé auparavant. Sokol et BGFX sont des API qui fournissent des niveaux d'agnosticisme qui peuvent vous être utiles et sont relativement faciles à comprendre (les premiers en particulier).


la source
3

Un autre point qui n'a pas encore été mentionné et que vous devez prendre en compte est vos objectifs de performance. Si votre objectif est d'avoir une bibliothèque graphique qui donnera de bonnes performances sur une plate-forme matérielle bon marché, mais également utilisable sur une variété de plates-formes qui sont beaucoup plus puissantes mais utilisent une API différente, il peut être judicieux de concevoir votre API autour quelles que soient les abstractions utilisées nativement sur la plateforme où les performances sont un problème. Même si cela entraîne une dégradation de la vitesse de 50% sur les plates-formes les plus puissantes, cela peut valoir la peine s'il permet une amélioration de la vitesse de 20% sur la plate-forme où les performances comptent le plus.

supercat
la source