Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 31f9497

Browse files
author
Alexis Ronez
committed
Rephrased Uniform buffers -> Descriptor layout and buffer
1 parent 0f14be8 commit 31f9497

1 file changed

Lines changed: 36 additions & 32 deletions

File tree

fr/05_Uniform_buffers/00_Descriptor_layout_et_buffer.md

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,28 @@
33
Nous pouvons maintenant passer des données à chaque groupe d'invocation de vertex shaders. Mais qu'en est-il des
44
variables globales? Nous allons enfin passer à la 3D, et nous avons besoin d'une matrice model-view-projection. Nous
55
pourrions la transmettre avec les vertices, mais cela serait un gachis de mémoire et, de plus, nous devrions mettre à
6-
jour le vertex buffer à chaque frame, alors qu'il est très bien dans se mémoire à hautes performances.
6+
jour le vertex buffer à chaque frame, alors qu'il est très bien rangé dans se mémoire à hautes performances.
77

8-
La solution fournie par Vulkan consiste à utiliser des *descripteurs de ressource* (ou *resource descriptors*). Un
9-
descripteur permet à des shaders d'accéder librement à des ressources telles que les buffers ou les images. Nous allons
10-
créer un buffer qui contiendra les matrices de transformation. Nous ferons en sorte que le vertex shader puisse y
11-
accéder. Il y a trois parties à l'utilisation d'un descripteur de ressource :
8+
La solution fournie par Vulkan consiste à utiliser des *descripteurs de ressource* (ou *resource descriptors*), qui
9+
font correspondre des données en mémoire à une variable shader. Un descripteur permet à des shaders d'accéder
10+
librement à des ressources telles que les buffers ou les *images*. Attention, Vulkan donne un sens particulier au
11+
terme image. Nous verrons cela bientôt. Nous allons pour l'instant créer un buffer qui contiendra les matrices de
12+
transformation. Nous ferons en sorte que le vertex shader puisse y accéder. Il y a trois parties à l'utilisation d'un
13+
descripteur de ressources :
1214

1315
* Spécifier l'organisation des descripteurs durant la création de la pipeline
14-
* Allouer un set de descripteurs depuis une pool de descritpeurs
16+
* Allouer un set de descripteurs depuis une pool de descritpeurs (encore un objet de gestion de mémoire)
1517
* Lier le descripteur pour les opérations de rendu
1618

17-
L'*organisation du descripteur* indique le type de ressources qui seront accedées par la pipeline. Cela ressemble sur
18-
le principe à indiquer les attachements accédés. Un *set de descripteurs* spécifie le buffer ou l'image qui sera lié à
19-
ce descripteur, de la même manière qu'un framebuffer doit indiquer les ressources qui le composent.
19+
L'*organisation du descripteur* (descriptor layout) indique le type de ressources qui seront accedées par la
20+
pipeline. Cela ressemble sur le principe à indiquer les attachements accédés. Un *set de descripteurs* (descriptor
21+
set) spécifie le buffer ou l'image qui sera lié à ce descripteur, de la même manière qu'un framebuffer doit indiquer
22+
les ressources qui le composent.
2023

2124
Il existe plusieurs types de descripteurs, mais dans ce chapitre nous ne verrons que les *uniform buffer objects* (UBO).
2225
Nous en verrons d'autres plus tard, et leur utilisation sera très similaire. Rentrons dans le vif du sujet et supposons
23-
maintenant que nous voulons que toutes les invocations du vertex shader que nous avons mis en place accèdent tous à la
24-
structure C suivante :
26+
maintenant que nous voulons que toutes les invocations du vertex shader que nous avons codé accèdent à la structure C
27+
suivante :
2528

2629
```c++
2730
struct UniformBufferObject {
@@ -82,15 +85,15 @@ void main() {
8285
```
8386
8487
L'ordre des variables `in`, `out` et `uniform` n'a aucune importance. La directive `binding` est assez semblable à
85-
`location` ; elle permet de fournir l'indice du binding. Nous allons le référencer dans l'organisation du descripteur.
88+
`location` ; elle permet de fournir l'indice du binding. Nous allons l'indiquer dans l'organisation du descripteur.
8689
Notez le changement dans la ligne calculant `gl_Position`, qui prend maintenant en compte la matrice MVP. La dernière
8790
composante du vecteur ne sera plus à `0`, car elle sert à diviser les autres coordonnées en fonction de leur distance à
8891
la caméra pour créer un effet de profondeur.
8992
9093
## Organisation du set de descripteurs
9194
92-
La prochaine étape consiste à définir l'UBO du côté du C++. Nous devons aussi informer Vulkan que nous voulons
93-
l'utiliser dans le vertex shader.
95+
La prochaine étape consiste à définir l'UBO côté C++. Nous devons aussi informer Vulkan que nous voulons l'utiliser
96+
dans le vertex shader.
9497
9598
```c++
9699
struct UniformBufferObject {
@@ -104,9 +107,9 @@ Nous pouvons faire correspondre parfaitement la déclaration en C++ avec celle d
104107
martrices sont stockées d'une manière compatible bit à bit avec l'interprétation de ces données par les shaders. Nous
105108
pouvons ainsi utiliser `memcpy` sur une structure `UniformBufferObject` vers un `VkBuffer`.
106109

107-
Nous devons fournir des informations sur chacun des descriptors utilisés par les shaders lors de la création de la
110+
Nous devons fournir des informations sur chacun des descripteurs utilisés par les shaders lors de la création de la
108111
pipeline, similairement aux entrées du vertex shader. Nous allons créer une fonction pour gérer toute cette information,
109-
et donc pour créer le set de descripteurs. Elle s'appelera `createDescriptorSetLayout` et sera appelée juste avant la
112+
et ainsi pour créer le set de descripteurs. Elle s'appelera `createDescriptorSetLayout` et sera appelée juste avant la
110113
finalisation de la création de la pipeline.
111114

112115
```c++
@@ -145,18 +148,18 @@ hiérarchique. Nous n'utilisons pas cette possiblité et indiquons donc `1`.
145148
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
146149
```
147150

148-
Nous devons aussi informer Vulkan sur les étapes shaders qui accèderont à cette ressource. Le champ de bits `stageFlags`
151+
Nous devons aussi informer Vulkan des étapes shaders qui accèderont à cette ressource. Le champ de bits `stageFlags`
149152
permet de combiner toutes les étapes shader concernées. Vous pouvez aussi fournir la valeur
150153
`VK_SHADER_STAGE_ALL_GRAPHICS`. Nous mettons uniquement `VK_SHADER_STAGE_VERTEX_BIT`.
151154

152155
```c++
153-
uboLayoutBinding.pImmutableSamplers = nullptr; // Optionnel
156+
uboLayoutBinding.pImmutableSamplers = nullptr; // Optionel
154157
```
155158

156159
Le champ `pImmutableSamplers` n'a de sens que pour les descripteurs liés aux samplers d'images. Nous nous attaquerons à
157160
ce sujet plus tard. Vous pouvez le mettre à `nullptr`.
158161

159-
Tous les `binding` des descripteurs sont ensuite combinés en un seul objet `VkDescriptorSetLayout`. Créez pour cela un
162+
Tous les liens des descripteurs sont ensuite combinés en un seul objet `VkDescriptorSetLayout`. Créez pour cela un
160163
nouveau membre donnée :
161164

162165
```c++
@@ -165,7 +168,8 @@ VkPipelineLayout pipelineLayout;
165168
```
166169

167170
Nous pouvons créer cet objet à l'aide de la fonction `vkCreateDescriptorSetLayout`. Cette fonction prend en argument une
168-
structure du type `VkDescriptorSetLayoutCreateInfo` qui contient un tableau fait des structures décrivant les bindings :
171+
structure de type `VkDescriptorSetLayoutCreateInfo`. Elle contient un tableau contenant les structures qui décrivent les
172+
bindings :
169173

170174
```c++
171175
VkDescriptorSetLayoutCreateInfo layoutInfo = {};
@@ -174,7 +178,7 @@ layoutInfo.bindingCount = 1;
174178
layoutInfo.pBindings = &uboLayoutBinding;
175179

176180
if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
177-
throw std::runtime_error("echec lors de la creation d'un set de descripteurs!");
181+
throw std::runtime_error("echec de la creation d'un set de descripteurs!");
178182
}
179183
```
180184

@@ -190,7 +194,7 @@ pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
190194

191195
Vous vous demandez peut-être pourquoi il est possible de spécifier plusieurs set de descripteurs dans cette structure,
192196
dans la mesure où un seul inclut tous les `bindings` d'une pipeline. Nous y reviendrons dans le chapitre suivant, quand
193-
nous nous intéresserons aux pools de descriptors.
197+
nous nous intéresserons aux pools de descripteurs.
194198

195199
L'objet que nous avons créé ne doit être détruit que lorsque le programme se termine.
196200

@@ -208,7 +212,7 @@ void cleanup() {
208212

209213
Dans le prochain chapitre nous référencerons le buffer qui contient les données de l'UBO. Mais nous devons bien sûr
210214
d'abord créer ce buffer. Comme nous allons accéder et modifier les données du buffer à chaque frame, il est assez
211-
inutile d'utiliser un buffer intermédiaire. Ce serait même en fait contre-productif en terme de performance.
215+
inutile d'utiliser un buffer intermédiaire. Ce serait même en fait contre-productif en terme de performances.
212216

213217
Comme des frames peuvent être "in flight" pendant que nous essayons de modifier le contenu du buffer, nous allons avoir
214218
besoin de plusieurs buffers. Nous pouvons soit en avoir un par frame, soit un par image de la swap chain. Comme nous
@@ -250,7 +254,7 @@ void createUniformBuffer() {
250254
}
251255
```
252256

253-
Nous allons créer une autre fonction qui mettra à jour le buffer et appliquera à son contenu une transformation à chaque
257+
Nous allons créer une autre fonction qui mettra à jour le buffer en appliquant à son contenu une transformation à chaque
254258
frame. Nous n'utiliserons donc pas `vkMapMemory` ici. Le buffer doit être détruit à la fin du programme :
255259

256260
```c++
@@ -268,9 +272,9 @@ void cleanup() {
268272
}
269273
```
270274

271-
## Mise à jour des données uniform
275+
## Mise à jour des données uniformes
272276

273-
Créez la fonction `updateUniformBuffer` et appelez-la dans `drawFrame` juste après que nous avons déterminé l'image de
277+
Créez la fonction `updateUniformBuffer` et appelez-la dans `drawFrame`, juste après que nous avons déterminé l'image de
274278
la swap chain que nous devons acquérir :
275279

276280
```c++
@@ -313,7 +317,7 @@ dont nous avons besoin pour implémenter la 3D. La macro `GLM_FORCE_RADIANS` per
313317
représentation des angles.
314318

315319
Pour que la rotation s'exécute à une vitesse indépendante du FPS, nous allons utiliser les fonctionnalités de mesure
316-
précise contenues dans `<chrono>`.
320+
précise de la librairie standrarde C++. Incluez donc `<chrono>` :
317321

318322
```c++
319323
void updateUniformBuffer(uint32_t currentImage) {
@@ -324,7 +328,7 @@ void updateUniformBuffer(uint32_t currentImage) {
324328
}
325329
```
326330
327-
Nous commençons donc par inclure la logique de calcul du temps écoulé, mesuré en secondes et stocké dans un `float`.
331+
Nous commençons donc par écrire la logique de calcul du temps écoulé, mesuré en secondes et stocké dans un `float`.
328332
329333
Nous allons ensuite définir les matrices model, view et projection stockées dans l'UBO. La rotation sera implémentée
330334
comme une simple rotation autour de l'axe Z en fonction de la variable `time` :
@@ -335,7 +339,7 @@ ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0
335339
```
336340

337341
La fonction `glm::rotate` accepte en argument une matrice déjà existante, un angle de rotation et un axe de rotation. Le
338-
constructeur `glm::mat4(1.0)` crée une matrice d'identité. Avec la multiplication `time * glm::radians(90.0f)` la
342+
constructeur `glm::mat4(1.0)` crée une matrice identité. Avec la multiplication `time * glm::radians(90.0f)` la
339343
géométrie tournera de 90 degrés par seconde.
340344

341345
```c++
@@ -352,7 +356,7 @@ ubo.proj = glm::perspective(glm::radians(45.0f), swapChainExtent.width / (float)
352356

353357
J'ai opté pour un champ de vision de 45 degrés. Les autres paramètres de `glm::perspective` sont le ratio et les plans
354358
near et far. Il est important d'utiliser l'étendue actuelle de la swap chain pour calculer le ratio, afin d'utiliser les
355-
valeurs qui prennent en compte les redimensionnements.
359+
valeurs qui prennent en compte les redimensionnements de la fenêtre.
356360

357361
```c++
358362
ubo.proj[1][1] *= -1;
@@ -362,7 +366,7 @@ GLM a été conçue pour OpenGL, qui utilise les coordonnées de clip et de l'ax
362366
compenser cela consiste à changer le signe de l'axe Y dans la matrice de projection.
363367

364368
Maintenant que toutes les transformations sont définies nous pouvons copier les données dans le buffer uniform actuel.
365-
Nous utilisons le même procédé que pour le vertex buffer, hormis le buffer intermédiaire.
369+
Nous utilisons la première technique que nous avons vue pour la copie de données dans un buffer.
366370

367371
```c++
368372
void* data;
@@ -374,7 +378,7 @@ vkUnmapMemory(device, uniformBuffersMemory[currentImage]);
374378
Utiliser un UBO de cette manière n'est pas le plus efficace pour transmettre des données fréquemment mises à jour. Une
375379
meilleure pratique consiste à utiliser les *push constants*, que nous aborderons peut-être dans un futur chapitre.
376380
377-
Dans un avenir plus proche nous allons lier les sets de descirptors au `VkBuffer` contenant les données des matrices,
381+
Dans un avenir plus proche nous allons lier les sets de descripteurs au `VkBuffer` contenant les données des matrices,
378382
afin que le vertex shader puisse y avoir accès.
379383
380384
[Code C++](/code/21_descriptor_layout.cpp) /

0 commit comments

Comments
 (0)