11## Introduction
22
33Les buffers sont pour Vulkan des emplacements mémoire qui peuvent permettre de stocker des données quelconques sur la
4- carte graphique. Nous pouvons en particulier y placer les données représentant les vertices , et ce que nous allons
5- faire dans ce chapitre. Nous verrons plus tard d'autres utilisation répandues. Au contraire des autres objets que nous
6- avons rencontré les buffers n'allouent pas de mémoire. Il nous faudra gérer la mémoire nous-mêmes .
4+ carte graphique. Nous pouvons en particulier y placer les données représentant les sommets , et c'est ce que nous allons
5+ faire dans ce chapitre. Nous verrons plus tard d'autres utilisations répandues. Au contraire des autres objets que nous
6+ avons rencontré les buffers n'allouent pas eux-mêmes de mémoire. Il nous faudra gérer la mémoire à la main .
77
88## Création d'un buffer
99
@@ -49,15 +49,14 @@ Le premier champ de cette structure s'appelle `size`. Il spécifie la taille du
4949bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
5050```
5151
52- Le deuxième champ, appelé ` usage ` , permet d'informer Vulkan de la manière dont nous utiliserons le buffer. Nous pouvons
53- indiquer plusieurs valeurs représentant les utilisations possibles. Dans notre cas nous ne mettons que la valeur qui
54- correspond à un vertex buffer.
52+ Le deuxième champ, appelé ` usage ` , correspond à l'utilisation type du buffer. Nous pouvons indiquer plusieurs valeurs
53+ représentant les utilisations possibles. Dans notre cas nous ne mettons que la valeur qui correspond à un vertex buffer.
5554
5655``` c++
5756bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
5857```
5958
60- De la même manière que les images de la swap chain, les buffers peuvent soit être possédés par une queue family, ou bien
59+ De la même manière que les images de la swap chain, les buffers peuvent soit être gérés par une queue family, ou bien
6160être partagés entre plusieurs queue families. Notre buffer ne sera utilisé que par la queue des graphismes, nous
6261pouvons donc rester en mode exclusif.
6362
@@ -80,7 +79,7 @@ void createVertexBuffer() {
8079 bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
8180
8281 if (vkCreateBuffer(device, &bufferInfo, nullptr, &vertexBuffer) != VK_SUCCESS) {
83- throw std::runtime_error("echec lors de la creation d'un vertex buffer!");
82+ throw std::runtime_error("echec de la creation d'un vertex buffer!");
8483 }
8584}
8685```
@@ -113,10 +112,10 @@ La structure que la fonction nous remplit possède trois membres :
113112* `size` : le nombre d'octets dont le buffer a besoin, ce qui peut différer de ce que nous avons écrit en préparant le
114113buffer
115114* `alignment` : le décalage en octets entre le début de la mémoire allouée pour lui et le début des données du buffer,
116- ce qui est déterminé par les valeurs que nous avons fournies dans `usage` et `flags`
115+ ce que le driver détermine avec les valeurs que nous avons fournies dans `usage` et `flags`
117116* `memoryTypeBits` : champs de bits combinant les types de mémoire qui conviennent au buffer
118117
119- Les cartes graphiques offrent plusieurs types de mémoire. Ils diffèrenent en performance et en opérations disponibles.
118+ Les cartes graphiques offrent plusieurs types de mémoire. Ils diffèrent en performance et en opérations disponibles.
120119Nous devons considérer ce dont le buffer a besoin en même temps que ce dont nous avons besoin pour sélectionner le
121120meilleur type de mémoire possible. Créons une fonction `findMemoryType` pour y isoler cette logique.
122121
@@ -197,9 +196,8 @@ VkBuffer vertexBuffer;
197196VkDeviceMemory vertexBufferMemory;
198197
199198...
200-
201199if (vkAllocateMemory(device, &allocInfo, nullptr , &vertexBufferMemory) != VK_SUCCESS) {
202- throw std::runtime_error("echec lors d'une allocation de memoire!");
200+ throw std::runtime_error("echec d'une allocation de memoire!");
203201}
204202```
205203
@@ -212,7 +210,8 @@ vkBindBufferMemory(device, vertexBuffer, vertexBufferMemory, 0);
212210Les trois premiers paramètres sont évidents. Le quatrième indique le décalage entre le début de la mémoire et le début
213211du buffer. Nous avons alloué cette mémoire spécialement pour ce buffer, nous pouvons donc mettre `0`. Si vous décidez
214212d'allouer un grand espace mémoire pour y mettre plusieurs buffers, sachez qu'il faut que ce nombre soit divisible par
215- `memRequirements.alignement`.
213+ `memRequirements.alignement`. Notez que cette stratégie est la manière recommandée de gérer la mémoire des GPUs (voyez
214+ [cet article](https://developer.nvidia.com/vulkan-memory-management)).
216215
217216Il est évident que cette allocation dynamique de mémoire nécessite que nous libérions l'emplacement nous-mêmes. Comme la
218217mémoire est liée au buffer, et que le buffer sera nécessaire à toutes les opérations de rendu, nous ne devons la libérer
@@ -261,7 +260,11 @@ manières de régler ce problème :
261260d'accéder à la mémoire
262261
263262Nous utiliserons la première approche qui nous assure une cohérence permanente. Cette méthode est moins performante que
264- le flushing explicite, mais nous verrons dès le prochain chapitre que cela n'a aucune importance.
263+ le flushing explicite, mais nous verrons dès le prochain chapitre que cela n'a aucune importance car nous changerons
264+ complètement de stratégie.
265+
266+ Remarquez également l'utilisation de ` memcpy ` qui indique la compatibilité bit-à-bit des structures avec la
267+ représentation sur la carte graphique.
265268
266269## Lier le vertex buffer
267270
@@ -278,11 +281,11 @@ vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offsets);
278281vkCmdDraw(commandBuffers[ i] , static_cast<uint32_t>(vertices.size()), 1, 0, 0);
279282```
280283
281- La fonction `vkCmbBindVertexBuffers ` lie des vertex buffers aux bindings. Le deuxième et le troisième paramètre
282- indiquent un décalage et le nombre de bindings auquel ce buffer correspond . L'avant-dernier paramètre est le tableau de
283- vertex buffers à lier, et le dernier est un tableau de décalages en octets entre le début d'un buffer et le début des
284- données. Il est d'ailleurs préférable d'appeler `vkCmdDraw` avec la taille du tableau de vertices plutôt qu'avec un
285- nombre écrit à la main.
284+ La fonction `vkCmdBindVertexBuffers ` lie des vertex buffers aux bindings. Les deuxième et troisième paramètres indiquent
285+ l'indice du premier binding auquel le buffer correspond et le nombre de bindings qu'il contiendra . L'avant-dernier
286+ paramètre est le tableau de vertex buffers à lier, et le dernier est un tableau de décalages en octets entre le début
287+ d'un buffer et le début des données. Il est d'ailleurs préférable d'appeler `vkCmdDraw` avec la taille du tableau de
288+ vertices plutôt qu'avec un nombre écrit à la main.
286289
287290Lancez maintenant le programme; vous devriez voir le triangle habituel apparaître à l'écran.
288291
@@ -300,7 +303,7 @@ const std::vector<Vertex> vertices = {
300303
301304![ ] ( /images/triangle_white.png )
302305
303- Dans le prochain chapitre nous verrons une autre manière de copier les données dans un buffer. Elle est plus performante
306+ Dans le prochain chapitre nous verrons une autre manière de copier les données vers un buffer. Elle est plus performante
304307mais nécessite plus de travail.
305308
306309[ Code C++] ( /code/18_vertex_buffer.cpp ) /
0 commit comments