33Nous avons maintenant un vertex buffer fonctionnel. Par contre il n'est pas dans la mémoire la plus optimale posible
44pour la carte graphique. Il serait préférable d'utiliser une mémoire ` VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ` ,
55mais de telles mémoires ne sont pas accessibles depuis le CPU. Dans ce chapitre nous allons créer deux vertex buffers.
6- Le premier, un * buffer intermédiaire* , sera stocké dans de la mémoire accessible depuis le CPU, et nous y mettrons nos
7- données. Le second sera directement dans la carte graphique, et nous y copierons les données des vertices depuis le
8- buffer intermédiaire.
6+ Le premier, un buffer intermédiaire ( * staging buffer * ) , sera stocké dans de la mémoire accessible depuis le CPU, et
7+ nous y mettrons nos données. Le second sera directement dans la carte graphique, et nous y copierons les données des
8+ vertices depuis le buffer intermédiaire.
99
1010## Queue de transfert
1111
@@ -43,7 +43,7 @@ void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyF
4343 bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
4444
4545 if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) {
46- throw std::runtime_error("echec lors de la creation d'un buffer!");
46+ throw std::runtime_error("echec de la creation d'un buffer!");
4747 }
4848
4949 VkMemoryRequirements memRequirements;
@@ -55,7 +55,7 @@ void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyF
5555 allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
5656
5757 if (vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) {
58- throw std::runtime_error("echec lors de l'allocation de memoire!");
58+ throw std::runtime_error("echec de l'allocation de memoire!");
5959 }
6060
6161 vkBindBufferMemory(device, buffer, bufferMemory, 0);
@@ -112,9 +112,10 @@ graphique. Dans ce chapitre nous allons utiliser deux nouvelles valeurs pour les
112112* ` VK_BUFFER_USAGE_TRANSFER_DST_BIT ` : le buffer peut être utilisé comme destination pour un transfert de mémoire
113113
114114Le ` vertexBuffer ` est maintenant alloué à partir d'un type de mémoire local au device, ce qui implique en général que
115- nous ne pouvons pas utiliser ` vkMapMemory ` . Nous pouvons cependant bien sûr copier les données depuis le buffer
116- intermédiaire. Nous indiquons que nous voulons transmettre des données entre des buffers à l'aide des valeurs que nous
117- avons vues juste au-dessus. Nous pouvons combiner ces informations avec par exemple ` VK_BUFFER_USAGE_VERTEX_BUFFER_BIT ` .
115+ nous ne pouvons pas utiliser ` vkMapMemory ` . Nous pouvons cependant bien sûr y copier les données depuis le buffer
116+ intermédiaire. Nous pouvons indiquer que nous voulons transmettre des données entre ces buffers à l'aide des valeurs
117+ que nous avons vues juste au-dessus. Nous pouvons combiner ces informations avec par exemple
118+ ` VK_BUFFER_USAGE_VERTEX_BUFFER_BIT ` .
118119
119120Nous allons maintenant écrire la fonction ` copyBuffer ` , qui servira à recopier le contenu du buffer intermédiaire dans
120121le véritable buffer.
@@ -125,10 +126,11 @@ void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
125126}
126127```
127128
128- Les opérations de transfert de mémoire sont réalisée à travers un command buffer, comme pour l'affichage. Nous devons
129+ Les opérations de transfert de mémoire sont réalisées à travers un command buffer, comme pour l'affichage. Nous devons
129130commencer par allouer des command buffers temporaires. Vous devriez d'ailleurs utiliser une autre command pool pour
130131tous ces command buffer temporaires, afin de fournir à l'implémentation une occasion d'optimiser la gestion de la
131- mémoire. Utilisez alors `VK_COMMAND_POOL_CREATE_TRANSIENT_BIT` pendant la création de la command pool.
132+ mémoire séparément des graphismes. Si vous le faites, utilisez `VK_COMMAND_POOL_CREATE_TRANSIENT_BIT` pendant la
133+ création de la command pool, car les commands buffers ne seront utilisés qu'une seule fois.
132134
133135```c++
134136void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
@@ -160,16 +162,16 @@ terminée avant de sortir de la fonction. Il est alors préférable d'informer l
160162
161163```c++
162164VkBufferCopy copyRegion = {};
163- copyRegion.srcOffset = 0; // Optionnel
164- copyRegion.dstOffset = 0; // Optionnel
165+ copyRegion.srcOffset = 0; // Optionel
166+ copyRegion.dstOffset = 0; // Optionel
165167copyRegion.size = size;
166168vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region);
167169```
168170
169171La copie est réalisée à l'aide de la commande ` vkCmdCopyBuffer ` . Elle prend les buffers de source et d'arrivée comme
170172arguments, et un tableau des régions à copier. Ces régions sont décrites dans des structures de type ` VkBufferCopy ` , qui
171173consistent en un décalage dans le buffer source, le nombre d'octets à copier et le décalage dans le buffer d'arrivée. Il
172- n'est pas ici possible d'indiquer ` VK_WHOLE_SIZE ` .
174+ n'est ici pas possible d'indiquer ` VK_WHOLE_SIZE ` .
173175
174176``` c++
175177vkEndCommandBuffer (commandBuffer);
@@ -202,7 +204,7 @@ vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
202204
203205N'oubliez pas de libérer le command buffer utilisé pour l'opération de transfert.
204206
205- Nous pouvons maintenant appeler `copyBuffer` depuis la fonction `createVertexBuffer` pour que les vertices soient enfin
207+ Nous pouvons maintenant appeler `copyBuffer` depuis la fonction `createVertexBuffer` pour que les sommets soient enfin
206208stockées dans la mémoire locale.
207209
208210```c++
@@ -226,14 +228,16 @@ donc le détruire.
226228
227229Lancez votre programme pour vérifier que vous voyez toujours le même triangle. L'amélioration n'est peut-être pas
228230flagrante, mais il est clair que la mémoire permet d'améliorer les performances, préparant ainsi le terrain
229- pour de la géométrie plus complexe.
231+ pour le chargement de géométrie plus complexe.
230232
231233## Conclusion
232234
233235Notez que dans une application réelle, vous ne devez pas allouer de la mémoire avec `vkAllocateMemory` pour chaque
234236buffer. De toute façon le nombre d'appel à cette fonction est limité, par exemple à 4096, et ce même sur des cartes
235- graphiques comme les GTX 1080. La bonne pratique consiste à allouer une grande zone de mémoire et d'utiliser un objet
236- pour créer des décalages pour chacun des buffers.
237+ graphiques comme les GTX 1080. La bonne pratique consiste à allouer une grande zone de mémoire et d'utiliser un
238+ gestionnaire pour créer des décalages pour chacun des buffers. Il est même préférable d'utiliser un buffer pour
239+ plusieurs types de données (sommets et uniformes par exemple) et de séparer ces types grâce à des indices dans le
240+ buffer (voyez encore [ce même article](https://developer.nvidia.com/vulkan-memory-management)).
237241
238242Vous pouvez implémenter votre propre solution, ou bien utiliser la librairie
239243[VulkanMemoryAllocator](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator) crée par GPUOpen. Pour ce
0 commit comments