Différence entre «tampon» et «tableau» dans OpenGL?

12

Quand je lis la doc sur webGL ou OpenGL, on peut voir quelques modèles dans la façon dont les noms des fonctions et des objets sont utilisés. Mais je ne peux pas comprendre la différence entre un objet tampon et un tableau.

Il existe des «objets de tampon de vertex», des «objets de tableau de vertex» et même une sorte de «tableau de tampon» ou de «arraybuffer».

Dans le contexte OpenGL, quand quelque chose est "tableau" et quand il devrait être appelé un "tampon" à la place?

coobit
la source
Un peu de perspective, pensez à récupérer les données sur le réseau et à stocker un journal de tout ce qui a été reçu. Vous devez lire le socket et mettre les données reçues quelque part afin de pouvoir les faire circuler, c'est un tampon. Il peut souvent s'agir d'un type de liste simple de portée locale et alloué dynamiquement. Parfois, c'est aussi simple qu'un char* buffer = socketRead();(pseudocode). Le journal, d'autre part, vit tout au long du cycle de vie de l'application. Donc, vous créez un tableau quelque part et commencez à lire le socket, chaque fois que vous obtenez des données que vous écrivez ce morceau dans le tableau, vous donnant une liste soignée de toutes les données que vous avez reçues.
Kevin

Réponses:

5

La dénomination de Vertex Array Object est quelque peu regrettable. Il y a trois choses différentes qui apparaissent (apparaissaient) dans / avec / autour de votre application, et qui sont (ont été, historiquement) nommées différemment, avec "tableau" ou "tampon" dans le nom (enfin, il y a aussi des objets framebuffer, mais je l'ignorerai).

  1. Des données qui vivent dans votre application, formellement et factuellement, mais qui sont extraites par OpenGL en une seule fois (par opposition à sommet par sommet). Il était une fois ce que vous appelleriez un tableau de sommets .
    L'objectif était de rendre l'accès plus efficace car OpenGL pouvait simplement copier le tout en une seule fois à un moment bien défini lorsque vous avez promis que les données étaient cohérentes et les pousser sur AGP ou autre chose dans un bloc. Cela n'existe plus.
  2. Données obscurcies et accessibles par une poignée qui peut être "liée", c'est-à-dire rendue active. Les données peuvent en fait vivre dans la mémoire principale, ou sur la carte graphique, ou être déplacées vers une région mappable PCIe, peu importe, mais dans les deux cas, vous ne les possédez pas formellement (même si elles se trouvent physiquement dans la RAM et si les données proviennent de votre application ) - à moins que vous ne l'ayez actuellement "mappé" via l'API correspondante, récupérant un pointeur accessible en écriture (et parfois lisible). Vous êtes également limité dans votre capacité à contrôler ce qui arrive aux données (vous pouvez donner quelques indices, mais c'est à peu près tout).
    OpenGL peut déplacer ces données plus ou moins librement, et vous êtes uniquement autorisé / capable de copier vers / depuis le tampon via l'API correspondante ou d'accéder aux données pendant qu'elles sont mappées. C'est ce que vous appelez un objet tampon ( objet tampon de sommet s'il contient des sommets, mais ce n'est pas vraiment le cas, pourrait aussi bien être des données d'image ou des uniformes, seuls les sommets étaient les premiers à être pris en charge, il était une fois).
    L'intention est de garantir qu'OpenGL peut (en principe) faire ce qu'il veut, il peut même pousser le tampon sur PCIe de manière spéculative avant même de dessiner. Cela fonctionne parce que vous ne possédez pas les données (OpenGL le fait!) Et que vous ne pouvez y accéder que via l'API donnée, il est donc connu à tout moment que les données sont valides. Le pilote peut même choisir de jeter la mémoire tampon sur la carte graphique lorsqu'il a besoin de mémoire pour quelque chose de différent et de la restaurer ultérieurement à partir de sa copie secrète si nécessaire.
  3. Un abus de langage vraiment stupide pour lequel un bien meilleur nom serait quelque chose comme un ensemble de tampons ou un ensemble de descripteurs, c'est le tristement célèbre objet tableau de sommets . Ce n'est, de votre point de vue, rien d'autre qu'un ensemble de poignées de tampon regroupées sous une autre poignée obscure (que vous pouvez lier). En réalité, la réalité est un peu plus compliquée. En fait, VAO est beaucoup plus proche du fonctionnement du matériel réel. Les cartes graphiques ont un petit nombre (souvent quelque chose comme 2, 4 ou 8) d'ensembles de descripteurs (non seulement pour les tampons, mais aussi pour les échantillonneurs) avec chacune une ou plusieurs entrées, entre lesquelles ils peuvent basculer très efficacement .
    Désormais, l'objectif de l'objet vertex array est de réduire le nombre d'appels d'API et de réduire le nombre de vérifications de cohérence qu'OpenGL doit effectuer en interne, et bien sûr, d'utiliser le matériel tel qu'il fonctionne. Si vous liez 5 tampons, chacun doit passer par des vérifications éventuellement coûteuses, et chacun est un candidat pour les échecs de cache dans le pilote, plus chacun nécessite de communiquer avec la carte graphique pour changer un descripteur, etc. etc. Si vous à la place lier un VAO, le pilote peut (souvent) simplement changer le jeu de descripteurs sur la carte graphique, et c'est fait.
Damon
la source
8

Un objet de tableau de sommet (VAO) est un objet qui contient un ou plusieurs objets de tampon de sommet et est conçu pour stocker les informations d'un objet rendu complet.

(tiré de khronos )

Chaque tampon a tendance à constituer un attribut d'un tableau de sommets (objet). Un VAO peut contenir de nombreux attributs de sommet (par exemple position, couleur, UV). Chacun peut être conservé dans son propre tampon, où le tampon indique une série d'octets contigus non formatés, et où vous devez spécifier explicitement la taille (type) par élément de tampon pour les appels OpenGL côté CPU et le travail du shader côté GPU.

C'est une façon. Les autres façons dont cela peut fonctionner sont:

  • Tous les attributs sont stockés entrelacés dans un seul tampon, OU
  • Certains des attributs existent dans leurs propres tampons dédiés, tandis que d'autres partagent des tampons.

Le diagramme ci-dessous illustre ces deux derniers cas.

entrez la description de l'image ici

Bottom line: Si l'expression "vertex array" est utilisée sans qualification dans OpenGL, vous pouvez supposer que cela signifie VAO, ce qui, dans un contexte OpenGL (spécifiquement) est une chose très différente d'un tampon.

MODIFIER votre commentaire: GL_ARRAY_BUFFERindique une intention d'utiliser cet objet tampon pour les données d'attribut de sommet, comme décrit ci-dessus. En effet, les tampons ne sont pas utilisés uniquement pour les attributs de sommet. Cependant, comme c'est le cas d'utilisation le plus courant et que vous posez des questions sur les VAO, je n'entrerai pas dans les autres; voici cependant une liste des autres types de tampons qui peuvent être configurés.

Ingénieur
la source
Les tampons sont donc: 1.résident dans le GPU, 2.la plupart du temps contiennent un type de données (uniquement le sommet, seulement la couleur ect), 3.Les données sont entrelacées, c'est-à-dire 111122223333 ect. 4. ne fournit aucune méthode pour accéder aux données (pas le tampon [2] ou le tampon [vertex_3434]). Maintenant, les tableaux sont: 1. Collecte de tampons, 2. Stocker des informations sur la façon d'analyser les tampons qu'il contient. , taille d'un élément, décalages, afin que les données des tampons soient accessibles correctement. non?
coobit
1. Des tampons existent aux deux extrémités et sont transférés entre le CPU et le GPU (potentiellement en avant et en arrière), sinon comment rempliriez-vous les données à télécharger sur le GPU lors du chargement d'un maillage à partir du disque?. Oui, les éléments sont de type uniforme dans tout le tampon, mais selon la technologie que vous utilisez, chaque élément tampon peut être soit une primitive soit un structtype. Les données peuvent être entrelacées ou être complètement uniformes, par tampon. Vous pouvez les indexer, tout comme avec un tableau C traditionnel sur le CPU. Array objets (utilisez cette terminologie correcte ou finissez par vous embrouiller!) ... (suite ci-dessous)
Ingénieur
2. Oui, et vous devez vous assurer explicitement que vos déclarations de tampon dans le shader correspondront aux spécifications que vous définissez sur votre VAO côté CPU: "Tous les états liés à la définition des données utilisées par le processeur de vertex sont encapsulés dans un vertex objet tableau. " (khronos docs)
Ingénieur
Donc, juste pour clouer davantage ... Comment les gens travaillaient-ils avant qu'OA n'utilise que BO? Ou bien AO était toujours présent dans OpenGL et c'est juste VAO qui a été introduit plus tard que VBO?
coobit
@coobit io7m.com/documents/history-vertex-spec - cela vous donne une idée des différences entre le pipeline fixe (old school) OpenGL, 3Dfx etc. et le pipeline moderne et programmable OpenGL et Direct3D.
Ingénieur
5

Cette terminologie est enracinée dans l'histoire d'OpenGL. Ce qui est important à retenir, c'est que, pour la plupart des versions GL qui sont pertinentes ici, OpenGL a évolué de manière incrémentielle et en ajoutant de nouvelles fonctionnalités à une API déjà existante plutôt que de changer l'API.

La première version d'OpenGL n'avait aucun de ces types d'objets. Le dessin a été réalisé en émettant plusieurs appels glBegin / glEnd, et un problème avec ce modèle était qu'il était très inefficace, en termes de surcharge d'appel de fonction.

OpenGL 1.1 a pris les premières mesures pour y remédier en introduisant des tableaux de vertex. Au lieu de spécifier directement les données de sommet, vous pouvez désormais les obtenir à partir de tableaux C / C ++ - d'où le nom. Donc, un tableau de sommets n'est que cela - un tableau de sommets et l'état GL requis pour les spécifier.

La prochaine évolution majeure est venue avec GL 1.5 et a permis de stocker des données de vertex array dans la mémoire GPU plutôt que dans la mémoire système ("côté client"). Une faiblesse de la spécification GL 1.1 vertex array était que l'ensemble complet des données de vertex devait être transféré au GPU chaque fois que vous vouliez l'utiliser; s'il était déjà sur le GPU, ce transfert pourrait être évité et des gains de performances potentiels pourraient être réalisés.

Un nouveau type d'objet GL a donc été créé pour permettre le stockage de ces données sur le GPU. Tout comme un objet de texture est utilisé pour stocker des données de texture, un objet tampon de sommet stocke des données de sommet. Il s'agit en fait d'un cas particulier d'un type d'objet tampon plus général qui peut stocker des données non spécifiques.

L'API pour l'utilisation des objets de tampon de vertex était adossée à l'API de tableaux de vertex déjà existante, c'est pourquoi vous voyez des choses étranges comme la conversion de décalages d'octets en pointeurs. Nous avons donc maintenant une API de tableaux de sommets qui stocke simplement l'état, les données étant obtenues à partir d'objets tampons plutôt qu'à partir de tableaux en mémoire.

Cela nous amène presque à la fin de notre histoire. L'API résultante était assez verbeuse lorsqu'il s'agissait de spécifier l'état du tableau de sommets, donc une autre voie d'optimisation était de créer un nouveau type d'objet qui collectait tout cet état ensemble, permettait plusieurs changements d'état de tableau de sommets dans un seul appel d'API et autorisait les GPU pour effectuer potentiellement des optimisations en raison de pouvoir savoir à l'avance quel état allait être utilisé.

Entrez l'objet de tableau de sommets, qui collecte tout cela ensemble.

Donc, pour résumer, un tableau de sommets a commencé sa vie comme une collection d'états et de données (stockés dans un tableau) pour dessiner avec. Un tampon de vertex remplace le stockage de la matrice en mémoire par un type d'objet GL, laissant la matrice de vertex juste en état. Un objet tableau de sommets n'est qu'un objet conteneur pour cet état, ce qui permet de le modifier plus facilement et avec moins d'appels d'API.

Maximus Minimus
la source
0

Je n'ai pas travaillé avec OpenGL depuis un certain temps, donc je n'ai peut-être qu'à moitié raison. De manière générale: les tampons stockent un tableau de mémoire non formatée. Un tableau est un terme général de mémoire contiguë.

Un tampon doit être lié au contexte, tandis qu'un tableau n'est qu'un tableau de données. Si je me souviens bien, les données du tampon sont destinées à être copiées sur la carte graphique (d'où la reliure).

J'espère que ça aide un peu

Juicef
la source
Qu'est-ce que GL_ARRAY_BUFFER alors? Pourquoi cela s'appelait ainsi? Selon votre hypothèse, il s'agit de "mémoire contiguë non formatée" :)
coobit
Eh bien, cet exemple particulier n'est qu'un identifiant d'un tampon (auquel vous liez votre tableau). Le tampon de tableau (dans votre exemple) est utilisé pour les attributs de sommet, donc vous liez fondamentalement votre tableau d'attributs de sommet à un tampon. Cela semble déroutant alors laissez-moi vous donner un exemple. Vous avez un tableau du côté du processeur qui pourrait être la couleur, la normale, les positions, etc., et maintenant vous voulez que le GPU y accède. C'est lorsque le bindBuffer arrive, mappant fondamentalement votre "cpu-array" sur le "gpu-array".
Juicef
Quant à savoir pourquoi il a été appelé ainsi, je ne peux pas répondre à cela. Je suppose que c'est parce que vous avez un tableau de données différentes qui y
entrent