web-dev-qa-db-fra.com

pourquoi les appels de tirage sont-ils chers?

en supposant que les données de texture, de sommet et de shader sont déjà sur la carte graphique, vous n'avez pas besoin d'envoyer beaucoup de données à la carte. il y a quelques octets pour identifier les données, et probablement une matrice 4x4, et quelques autres paramètres assortis.

alors d'où viennent tous les frais généraux? les opérations nécessitent-elles une poignée de main avec le GPU?

pourquoi l'envoi d'un maillage unique contenant un tas de petits modèles, calculés sur le processeur, est-il souvent plus rapide que l'envoi de l'id du sommet et des matrices de transformation? (la deuxième option semble qu'il devrait y avoir moins de données envoyées, sauf si les modèles sont plus petits qu'une matrice 4x4)

50
notallama

Tout d'abord, je suppose qu'avec "appels d'appel", vous voulez dire la commande qui indique au GPU de rendre un certain ensemble de sommets sous forme de triangles avec un certain état (shaders, état de fusion, etc.).

Les appels par tirage au sort ne sont pas nécessairement coûteux. Dans les anciennes versions de Direct3D, de nombreux appels nécessitaient un changement de contexte, ce qui était coûteux, mais ce n'est pas le cas dans les versions plus récentes.

La principale raison de faire moins d'appels de dessin est que le matériel graphique peut transformer et rendre les triangles beaucoup plus rapidement que vous ne pouvez les soumettre. Si vous soumettez quelques triangles avec chacun appel, vous serez complètement lié par le CPU et le GPU sera principalement inactif. Le CPU ne pourra pas alimenter le GPU assez rapidement.

Faire un appel unique avec deux triangles n'est pas cher, mais si vous soumettez trop peu de données à chaque appel, vous n'aurez pas assez de temps CPU pour soumettre autant de géométrie que possible au GPU.

Il y a des coûts réels à faire des appels de tirage, cela nécessite la mise en place d'un tas d'état (quel ensemble de sommets utiliser, quel shader utiliser et ainsi de suite), et les changements d'état ont un coût à la fois du côté matériel (mise à jour d'un tas des registres) et côté conducteur (valider et traduire vos appels qui définissent l'état).

Mais le coût principal des appels de tirage ne s'applique que si chaque appel soumet trop peu de données , car cela vous rendra lié au processeur et vous empêchera de utiliser pleinement le matériel.

Tout comme Josh l'a dit, les appels draw peuvent également entraîner le vidage du tampon de commande, mais d'après mon expérience, cela se produit généralement lorsque vous appelez SwapBuffers, pas lors de la soumission de la géométrie. Les pilotes vidéo essaient généralement de mettre en mémoire tampon autant qu'ils peuvent s'en tirer (plusieurs images parfois!) Pour éliminer le plus de parallélisme possible du GPU.

Vous devriez lire la présentation de nVidia Batch Batch Batch! , il est assez ancien mais couvre exactement ce sujet.

57
Joakim Hårsman

Les API graphiques comme Direct3D traduisent leurs appels au niveau de l'API en commandes indépendantes des périphériques et les mettent en file d'attente dans un tampon. Le vidage de ce tampon, pour effectuer le travail réel, est coûteux - à la fois parce qu'il implique que le travail réel est maintenant effectué et parce qu'il peut entraîner un passage du mode utilisateur au mode noyau sur la puce (et vice-versa), ce qui n'est pas le cas pas cher.

Jusqu'à ce que le tampon soit vidé, le GPU est capable de faire un travail de préparation en parallèle avec le CPU, tant que le CPU ne fait pas de demande de blocage (comme le mappage des données vers le CPU). Mais le GPU ne préparera pas - et ne pourra pas - tout avant d'avoir besoin de dessiner. Ce n'est pas parce que des données de sommet ou de texture sont sur la carte qu'elles ne sont pas encore correctement arrangées et peuvent ne pas être arrangées tant que les dispositions de sommet ne sont pas définies ou que les ombrages ne sont pas liés, et cetera. La majeure partie du travail réel se produit pendant l'appel de vidage et de tirage de commande.

Le SDK DirectX a un section sur le profilage précis des performances D3D qui, bien que n'étant pas directement lié à votre question, peut fournir des indications sur ce qui est ou n'est pas cher et (dans certains cas) pourquoi.

cet article de blog (et les articles de suivi ici et ici ), qui fournissent un bon aperçu de la logique, faible processus opérationnel de niveau du GPU.

Mais, essentiellement (pour essayer de répondre directement à vos questions), la raison pour laquelle les appels sont chers n'est pas qu'il y a nécessairement beaucoup de données à transférer , mais plutôt qu'il y a une grande quantité de travail au-delà de l'envoi de données sur le bus qui est différé jusqu'à ce que le tampon de commande soit vidé.

12
Josh

Réponse courte: le pilote met en mémoire tampon une partie ou la totalité du travail réel jusqu'à ce que vous appeliez draw. Cela apparaîtra comme un temps relativement prévisible passé dans l'appel de tirage, en fonction de la quantité d'état qui a changé.

Cela se fait pour plusieurs raisons:

  • pour éviter de faire un travail inutile: Si vous définissez (inutilement) le même état plusieurs fois avant de dessiner, vous pouvez éviter de faire un travail coûteux à chaque fois que cela se produit. Cela devient en fait un phénomène assez courant dans une grande base de code, par exemple un moteur de jeu de production.
  • être en mesure de concilier ce qui est en interne des états interdépendants au lieu de les traiter immédiatement avec des informations incomplètes

Autre (s) réponse (s):

  • Le tampon utilisé par le pilote pour stocker les commandes de rendu est plein et l'application attend effectivement que le GPU traite une partie du travail précédent. Cela apparaîtra généralement comme des blocs de temps extrêmement grands dans un appel de tirage aléatoire dans une trame.
  • Le nombre d'images que le pilote est autorisé à mettre en mémoire tampon a été atteint et l'application attend sur le GPU pour en traiter une. Cela apparaîtra généralement comme un gros bloc de temps dans le premier appel de tirage dans une trame, ou sur Présent à la fin de la trame précédente.
2
Zoner