2017-10-07 7 views
1

J'ai appris un peu le rendu des métaux de base, et je suis coincé avec quelques concepts de base:Combien de fois le vertex shader est-il appelé avec du métal?

Je sais que nous pouvons envoyer des données vertex shader en utilisant:

renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0) 

Et nous pouvons le récupérer dans le shader avec:

vertex float4 basic_vertex(const device VertexIn* vertexIn [[ buffer(0) ]], unsigned int vid [[ vertex_id ]]) 

Si je comprends bien, la fonction de sommet sera appelée une fois par chaque sommet, et vertex_id mettra à jour à chaque appel pour contenir l'index de sommet.

La question est, d'où vient ce vertex_id?

Je pourrais envoyer au shader plus de données avec différentes tailles:

renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0) 
renderEncoder.setVertexBuffer(vertexBuffer2, offset: 0, index: 1) 

Si VertexBuffer a 3 éléments, et vertexBuffer2 a 10 éléments ... combien de fois sont la fonction de sommet appelé? dix?

Merci!

Répondre

3

Cela est déterminé par l'appel de dessin que vous effectuez sur l'encodeur de commande de rendu. Prenez la méthode de tirage simple:

drawPrimitives(type:vertexStart:vertexCount:) 

Le vertexCount détermine combien de fois votre fonction est appelée sommet. Les vertex ID transmis à la fonction vertex sont compris entre vertexStart et vertexStart + vertexCount - 1.

Si vous considérez une autre méthode de tirage:

drawPrimitives(type:vertexStart:vertexCount:instanceCount:) 

qui va sur la même plage d'ID de sommet. Cependant, il appelle votre fonction vertex vertexCount * instanceCount fois. Il y aura instanceCount appels avec le vertex ID étant vertexStart. L'ID d'instance s'étendra de 0 à instanceCount - 1 pour ces appels. De même, il y aura instanceCount appels avec le vertex ID étant vertexStart + 1 (en supposant vertexCount >= 2), un avec chaque ID d'instance en [0..instanceCount-1]. Etc.

Les autres méthodes de dessin ont diverses autres options, mais elles n'affectent généralement pas le nombre de fois que la fonction vertex est appelée. Par exemple, baseInstance décale la plage des ID d'instance, mais pas sa taille.

Les différentes méthodes drawIndexedPrimitives() obtiennent les ID de vertex spécifiques à partir d'un tampon au lieu d'énumérer tous les ID de vertex dans une plage. Ce tampon peut contenir un ID de vertex donné dans plusieurs emplacements. Pour ce cas, je ne pense pas qu'il soit défini si la fonction vertex peut être appelée plusieurs fois pour le même identifiant de vertex et le même identifiant d'instance. Le métal essayera vraisemblablement d'éviter l'effort de duplication, mais il pourrait finir par être plus rapide d'appeler simplement la fonction vertex pour chaque index dans le tampon d'index même si plusieurs de ces index finissent par avoir le même identifiant de vertex.

La relation entre les vertex et les données dans les tampons que vous passez à l'étape de traitement des vertex vous appartient entièrement. Vous n'avez aucun tampon à passer. Par exemple, une fonction de vertex peut générer des informations de vertex entièrement par calcul uniquement à partir de l'ID de vertex et de l'ID d'instance.

Il est bien entendu courant que certaines au moins des mémoires tampons contiennent des tableaux de données par sommet indexées en utilisant l'ID de sommet. Les autres tampons peuvent être des données uniformes qui sont identiques pour tous les sommets (c'est-à-dire que vous n'indexez pas dans ce tampon en utilisant l'ID de vertex). Le métal lui-même ne le sait pas, cependant.