Logo Spiria

Une introduction à la nouvelle génération d'API graphiques (telles que Vulkan et DirectX 12)

25 septembre 2015.

Les API actuelles, OpenGL 4.x et DirectX 11, ont considérablement amélioré leurs fonctionnalités au fil des ans, depuis les premières versions. L’une des mises à jour les plus importantes a probablement été l’introduction du pipeline programmable pour remplacer l’ancien pipeline à fonction fixe. Alors que le pipeline à fonction fixe nécessitait que l’application définisse l’état de chaque pixel (couleur, texture, mélange, etc.), le pipeline programmable utilise des shaders capables d’effectuer presque n’importe quel type d’opération en utilisant des modèles mathématiques intégrés.

API actuelles

Les fonctionnalités d'OpenGL 4.x et de DirectX 11 ont été grandement améliorées au fil des années depuis les premières versions.

L'une des mises à jour les plus importantes a probablement été l'introduction du pipeline programmable pour remplacer l'ancien pipeline à fonction fixe.

Alors que le pipeline à fonction fixe nécessitait que l'application définisse l'état de chaque pixel (couleur, texture, mélange, etc.), le pipeline programmable utilise des shaders capables d'effectuer presque n'importe quel type d'opération en utilisant des modèles mathématiques intégrés :

  • Transformation de la matrice dans le vertex shader
  • Interpolation de mélange et de coloration dans le pixel shader
  • Subdivision de primitives dans le shader de tessellation
  • Transformation primitive dans le shader de géométrie
  • Et plus encore

Cependant, ces API ayant été conçues avant que le multithreading ne soit largement disponible, les applications ne sont généralement capables d'utiliser que des threads uniques du CPU pour effectuer des opérations sur le GPU.

Par conséquent, plus une application doit modifier les états du GPU, valider ces états et effectuer tout travail supplémentaire en coulisse, plus le CPU se bloque, laissant le GPU tourner au ralenti.

C'est pourquoi les API de nouvelle génération ont été conçues en tenant compte de la capacité de multithreading du CPU.

Nouvelles API

De nouvelles API adaptées au multithreading permettent aux applications de créer et de remplir des tampons de commande (objets contenant des commandes de rendu GPU) à partir de plusieurs threads CPU simultanément, qui sont ensuite mis en file d'attente vers le GPU par un autre thread CPU.

Une fois générés, les tampons de commande peuvent être exécutés à tout moment, avec une faible surcharge du CPU et sans que les pilotes aient besoin de valider ou de compiler quoi que ce soit dans la boucle de rendu. Cela réduit l'utilisation du CPU par rapport aux anciennes API, où les états du GPU doivent être modifiés chaque fois qu'une texture, un mode de fusion ou un shader différent est utilisé.

Exemple : Rendu de 3 maillages différents utilisant des shaders et des textures différents.
Condition préalable : les données pour les maillages, les shaders et les textures ont été pré-générées/préchargées.

Initialisation des objets graphiques

  • Anciennes API

Les opérations graphiques sont exécutées de manière séquentielle. Plus il y a de tampons, d'effets ou de textures créés, plus il faut de temps pour effectuer toutes les opérations.

  • Nouvelles API

 

Chaque tampon de commande peut être créé indépendamment des autres ; seule l'opération d'envoi exige que toutes les commandes soient finalisées.
Le temps nécessaire pour réaliser toutes les opérations sera à peu près équivalent à la somme du tampon de commande le plus long + l'opération d'envoi.

  • Comparaison

Vous pouvez constater que l'initialisation sera probablement plus rapide dans les nouvelles API, puisque la charge de travail est répartie entre tous les threads CPU disponibles. De plus, avec les nouvelles API, les threads 0 à 2 du CPU ne traitent pas avec le GPU ; ils créent simplement des tampons qui stockent les commandes et les pointeurs mémoire. Seul le thread 3 du CPU communique réellement avec le GPU, en lui envoyant des commandes à traiter.

Boucle de rendu

  • Anciennes API

  • Nouvelles API

  

  • Comparison

Comme vous pouvez le constater, la boucle de rendu devient plus simple, ayant moins d'opérations à exécuter. Pour rappel, sous les anciennes API, l'état du GPU était modifié à chaque opération de liaison, ce qui entraînait souvent une validation synchrone du GPU et du pilote, et finalement une perte de cycles CPU et GPU.

Effets d'ombrage

Enfin, les nouvelles API exigent que les shaders soient précompilés au format bytecode. Cela peut sembler fastidieux, mais cela signifie qu'au moment de l'exécution, les shaders se chargent plus rapidement - aucune compilation n'est nécessaire - et, mieux encore, sont moins sujets aux erreurs, puisqu'ils sont précuits et prévalidés.