1- Les anciens APIs définissaient des configurations par défaut pour toutes les étapes à fonction fixée de la pipeline
1+ Les anciens APIs définissaient des configurations par défaut pour toutes les étapes à fonction fixée de la pipeline
22graphique. Avec Vulkan vous devez être explicite dans ce domaine également et devrez donc configurer la fonction de
33mélange par exemple. Dans ce chapitre nous remplirons toutes les structures nécessaires à la configuration des étapes à
44fonction fixée.
55
66## Entrée des sommets
77
8- La structure ` VkPipelineVertexInputStateCreateInfo ` décrit le format des sommets envoyés au vertex shader. Elle
8+ La structure ` VkPipelineVertexInputStateCreateInfo ` décrit le format des sommets envoyés au vertex shader. Elle
99fait cela de deux manières :
1010
11- * Liens (bindings) : espace entre les données et information sur ces données; sont-elles par sommet ou par instance?
11+ * Liens (bindings) : espace entre les données et information sur ces données; sont-elles par sommet ou par instance?
1212(voyez [ l'instanciation] ( https://en.wikipedia.org/wiki/Geometry_instancing ) )
1313* Descriptions d'attributs : types d'attributs passés au vertex shader, de quels bindings les charger et avec quel
1414décalage entre eux.
@@ -26,20 +26,20 @@ vertexInputInfo.pVertexAttributeDescriptions = nullptr; // Optionnel
2626```
2727
2828Les membres ` pVertexBindingDescriptions ` et ` pVertexAttributeDescriptions ` pointent vers un tableau de structures
29- décrivant les détails du chargement des données des sommets. Ajoutez cette structure à la fonction
29+ décrivant les détails du chargement des données des sommets. Ajoutez cette structure à la fonction
3030` createGraphicsPipeline ` juste après le tableau ` shaderStages ` .
3131
3232## Input assembly
3333
3434La structure ` VkPipelineInputAssemblyStateCreateInfo ` décrit la nature de la géométrie voulue quand les sommets sont
35- reliés, et permet d'activer ou non la réévaluation des vertices. La première information est décrite dans le membre
35+ reliés, et permet d'activer ou non la réévaluation des vertices. La première information est décrite dans le membre
3636` topology ` et peut prendre ces valeurs :
3737
3838* ` VK_PRIMITIVE_TOPOLOGY_POINT_LIST ` : chaque sommet est un point
3939* ` VK_PRIMITIVE_TOPOLOGY_LINE_LIST ` : dessine une ligne liant deux sommet en n'utilisant ces derniers qu'une seule fois
40- * ` VK_PRIMITIVE_TOPOLOGY_LINE_STRIP ` : le dernier sommet de chaque ligne est utilisée comme premier sommet
40+ * ` VK_PRIMITIVE_TOPOLOGY_LINE_STRIP ` : le dernier sommet de chaque ligne est utilisée comme premier sommet
4141pour la ligne suivante
42- * ` VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST ` : dessine un triangle en utilisant trois sommets, sans en réutiliser pour le
42+ * ` VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST ` : dessine un triangle en utilisant trois sommets, sans en réutiliser pour le
4343triangle suivant
4444* ` VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP ` : le deuxième et troisième sommets sont utilisées comme les deux premiers
4545pour le triangle suivant
@@ -50,7 +50,7 @@ une combinaison de sommet qu'une seule fois au lieu de d'avoir les mêmes donné
5050vous mettez le membre ` primitiveRestartEnable ` à la valeur ` VK_TRUE ` , il devient alors possible d'interrompre les
5151liaisons des vertices pour les modes ` _STRIP ` en utilisant l'index spécial ` 0xFFFF ` ou ` 0xFFFFFFFF ` .
5252
53- Nous n'afficherons que des triangles dans ce tutoriel, nous nous contenterons donc de remplir la structure de
53+ Nous n'afficherons que des triangles dans ce tutoriel, nous nous contenterons donc de remplir la structure de
5454cette manière :
5555
5656``` c++
@@ -83,15 +83,15 @@ Les valeurs `minDepth` et `maxDepth` indiquent l'étendue des valeurs de profond
8383valeurs doivent être dans ` [0.0f, 1.0f] ` mais ` minDepth ` peut être supérieure à ` maxDepth ` . Si vous ne faites rien de
8484particulier contentez-vous des valeurs ` 0.0f ` et ` 1.0f ` .
8585
86- Alors que les viewports définissent la transformation de l'image vers le framebuffer, les rectangles de ciseaux
87- définissent la région de pixels qui sera conservée. Tout pixel en dehors des rectangles de ciseaux seront
86+ Alors que les viewports définissent la transformation de l'image vers le framebuffer, les rectangles de ciseaux
87+ définissent la région de pixels qui sera conservée. Tout pixel en dehors des rectangles de ciseaux seront
8888éliminés par le rasterizer. Ils fonctionnent plus comme un filtre que comme une transformation. Les différence sont
8989illustrée ci-dessous. Notez que le rectangle de ciseau dessiné sous l'image de gauche n'est qu'une des possibilités :
9090tout rectangle plus grand que le viewport aurait fonctionné.
9191
9292![ ] ( /images/viewports_scissors.png )
9393
94- Dans ce tutoriel nous voulons dessiner sur la totalité du framebuffer, et ce sans transformation. Nous
94+ Dans ce tutoriel nous voulons dessiner sur la totalité du framebuffer, et ce sans transformation. Nous
9595définirons donc un rectangle de ciseaux couvrant tout le frambuffer :
9696
9797``` c++
@@ -100,9 +100,9 @@ scissor.offset = {0, 0};
100100scissor.extent = swapChainExtent;
101101```
102102
103- Le viewport et le rectangle de ciseau se combinent en un *viewport state* à l'aide de la structure
104- `VkPipelineViewportStateCreateInfo`. Il est possible sur certaines cartes graphiques d'utiliser plusieurs viewports
105- et rectangles de ciseaux, c'est pourquoi la structure permet d'envoyer des tableaux de ces deux données.
103+ Le viewport et le rectangle de ciseau se combinent en un *viewport state* à l'aide de la structure
104+ `VkPipelineViewportStateCreateInfo`. Il est possible sur certaines cartes graphiques d'utiliser plusieurs viewports
105+ et rectangles de ciseaux, c'est pourquoi la structure permet d'envoyer des tableaux de ces deux données.
106106L'utilisation de cette possibilité nécessite de l'activer au préalable lors de la création du logical device.
107107
108108```c++
@@ -116,12 +116,12 @@ viewportState.pScissors = &scissor;
116116
117117## Rasterizer
118118
119- Le rasterizer récupère la géométrie définie par des sommets et calcule les fragments qu'elle recouvre. Ils sont ensuite
119+ Le rasterizer récupère la géométrie définie par des sommets et calcule les fragments qu'elle recouvre. Ils sont ensuite
120120traités par le fragment shaders. Il réalise également un
121121[ test de profondeur] ( https://en.wikipedia.org/wiki/Z-buffering ) , le
122122[ face culling] ( https://en.wikipedia.org/wiki/Back-face_culling ) et le test de ciseau pour vérifier si le fragment doit
123123effectivement être traité ou non. Il peut être configuré pour émettre des fragments remplissant tous les polygones ou
124- bien ne remplissant que les cotés (wireframe rendering). Tout cela se configure dans la structure
124+ bien ne remplissant que les cotés (wireframe rendering). Tout cela se configure dans la structure
125125` VkPipelineRasterizationStateCreateInfo ` .
126126
127127``` c++
@@ -130,15 +130,15 @@ rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
130130rasterizer.depthClampEnable = VK_FALSE;
131131```
132132
133- Si le membre ` depthClampEnable ` est mis à ` VK_TRUE ` , les fragments au-delà des plans near et far ne pas supprimés
134- mais affichés à cette distance. Cela est utile dans quelques situations telles que les shadow maps. Cela aussi doit
133+ Si le membre ` depthClampEnable ` est mis à ` VK_TRUE ` , les fragments au-delà des plans near et far ne pas supprimés
134+ mais affichés à cette distance. Cela est utile dans quelques situations telles que les shadow maps. Cela aussi doit
135135être explicitement activé lors de la mise en place du logical device.
136136
137137``` c++
138138rasterizer.rasterizerDiscardEnable = VK_FALSE;
139139```
140140
141- Si le membre ` rasterizerDiscardEnable ` est mis à ` VK_TRUE ` , aucune géométrie ne passe l'étape du rasterizer, ce qui
141+ Si le membre ` rasterizerDiscardEnable ` est mis à ` VK_TRUE ` , aucune géométrie ne passe l'étape du rasterizer, ce qui
142142désactive purement et simplement toute émission de donnée vers le frambuffer.
143143
144144``` c++
@@ -165,8 +165,8 @@ rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
165165rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
166166```
167167
168- Le membre ` cullMode ` détermine quel type de face culling utiliser. Vous pouvez désactiver tout ce filtrage,
169- n'éliminer que les faces de devant, que celles de derrière ou éliminer toutes les faces. Le membre ` frontFace `
168+ Le membre ` cullMode ` détermine quel type de face culling utiliser. Vous pouvez désactiver tout ce filtrage,
169+ n'éliminer que les faces de devant, que celles de derrière ou éliminer toutes les faces. Le membre ` frontFace `
170170indique l'ordre d'évaluation des vertices pour dire que la face est devant ou derrière, qui est le sens des
171171aiguilles d'une montre ou le contraire.
172172
@@ -178,7 +178,7 @@ rasterizer.depthBiasSlopeFactor = 0.0f; // Optionnel
178178```
179179
180180Le rasterizer peut altérer la profondeur en y ajoutant une valeur constante ou en la modifiant selon l'inclinaison du
181- fragment. Ces possibilités sont parfois exploitées pour le shadow mapping mais nous ne les utiliserons pas. Laissez
181+ fragment. Ces possibilités sont parfois exploitées pour le shadow mapping mais nous ne les utiliserons pas. Laissez
182182` depthBiasEnabled ` à la valeur ` VK_FALSE ` .
183183
184184## Multisampling
@@ -206,21 +206,21 @@ Nous reverrons le multisampling plus tard, pour l'instant laissez-le désactivé
206206
207207## Tests de profondeur et de pochoir
208208
209- Si vous utilisez un buffer de profondeur (depth buffer) et/ou de pochoir (stencil buffer) vous devez configurer les
210- tests de profondeur et de pochoir avec la structure ` VkPipelineDepthStencilStateCreateInfo ` . Nous n'avons aucun de
209+ Si vous utilisez un buffer de profondeur (depth buffer) et/ou de pochoir (stencil buffer) vous devez configurer les
210+ tests de profondeur et de pochoir avec la structure ` VkPipelineDepthStencilStateCreateInfo ` . Nous n'avons aucun de
211211ces buffers donc nous indiquerons ` nullptr ` à la place d'une structure. Nous y reviendrons au chapitre sur le depth
212212buffering.
213213
214214## Color blending
215215
216- La couleur donnée par un fragment shader doit être combinée avec la couleur déjà présente dans le framebuffer. Cette
216+ La couleur donnée par un fragment shader doit être combinée avec la couleur déjà présente dans le framebuffer. Cette
217217opération s'appelle color blending et il y a deux manières de la réaliser :
218218
219219* Mélanger linéairement l'ancienne et la nouvelle couleur pour créer la couleur finale
220220* Combiner l'ancienne et la nouvelle couleur à l'aide d'une opération bit à bit
221221
222- Il y a deux types de structures pour configurer le color blending. La première,
223- ` VkPipelineColorBlendAttachmentState ` , contient une configuration pour chaque framebuffer et la seconde,
222+ Il y a deux types de structures pour configurer le color blending. La première,
223+ ` VkPipelineColorBlendAttachmentState ` , contient une configuration pour chaque framebuffer et la seconde,
224224` VkPipelineColorBlendStateCreateInfo ` contient les paramètres globaux pour ce color blending. Dans notre cas nous
225225n'avons qu'un seul framebuffer :
226226
@@ -236,7 +236,7 @@ colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // Optionnel
236236colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; // Optionnel
237237```
238238
239- Cette structure spécifique de chaque framebuffer vous permet de configurer le color blending. L'opération sera
239+ Cette structure spécifique de chaque framebuffer vous permet de configurer le color blending. L'opération sera
240240effectuée à peu près comme ce pseudocode le montre :
241241
242242``` c++
@@ -250,12 +250,12 @@ if (blendEnable) {
250250finalColor = finalColor & colorWriteMask;
251251```
252252
253- Si ` blendEnable ` vaut ` VK_FALSE ` la nouvelle couleur du fragment shader est inscrite dans le framebuffer sans
254- modification et sans considération de la valeur déjà présente dans le framebuffer. Sinon les deux opérations de
255- mélange sont exécutées pour former une nouvelle couleur. Un AND binaire lui est appliquée avec ` colorWriteMask ` pour
253+ Si ` blendEnable ` vaut ` VK_FALSE ` la nouvelle couleur du fragment shader est inscrite dans le framebuffer sans
254+ modification et sans considération de la valeur déjà présente dans le framebuffer. Sinon les deux opérations de
255+ mélange sont exécutées pour former une nouvelle couleur. Un AND binaire lui est appliquée avec ` colorWriteMask ` pour
256256déterminer les canaux devant passer.
257257
258- L'utilisation la plus commune du mélange de couleurs utilise le canal alpha pour déterminer l'opacité du matériau et
258+ L'utilisation la plus commune du mélange de couleurs utilise le canal alpha pour déterminer l'opacité du matériau et
259259donc le mélange lui-même. La couleur finale devrait alors être calculée ainsi :
260260
261261``` c++
@@ -276,7 +276,7 @@ colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
276276colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
277277```
278278
279- Vous pouvez trouver toutes les opérations possibles dans les énumérations ` VkBlendFactor ` et ` VkBlendOp ` dans la
279+ Vous pouvez trouver toutes les opérations possibles dans les énumérations ` VkBlendFactor ` et ` VkBlendOp ` dans la
280280spécification.
281281
282282La seconde structure doit posséder une référence aux structures spécifiques des framebuffers. Vous pouvez également y
@@ -304,34 +304,34 @@ ce cas les résultats des invocations du fragment shader seront écrits directem
304304
305305## États dynamiques
306306
307- Un petit nombre d'états que nous avons spécifiés dans les structures précédentes peuvent en fait être altérés
307+ Un petit nombre d'états que nous avons spécifiés dans les structures précédentes peuvent en fait être altérés
308308sans avoir à recréer la pipeline. On y trouve la taille du viewport, la largeur des lignes et les constantes de mélange.
309309Pour cela vous devrez remplir la structure ` VkPipelineDynamicStateCreateInfo ` comme suit :
310310
311311``` c++
312- VkDynamicState dynamicStates[] = {
312+ std::vector< VkDynamicState> dynamicStates = {
313313 VK_DYNAMIC_STATE_VIEWPORT,
314314 VK_DYNAMIC_STATE_LINE_WIDTH
315315};
316316
317317VkPipelineDynamicStateCreateInfo dynamicState{};
318318dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
319- dynamicState.dynamicStateCount = 2 ;
320- dynamicState.pDynamicStates = dynamicStates;
319+ dynamicState.dynamicStateCount = static_cast < uint32_t >(dynamicStates.size()) ;
320+ dynamicState.pDynamicStates = dynamicStates.data() ;
321321```
322322
323- Les valeurs données lors de la configuration seront ignorées et vous devrez en fournir au moment du rendu. Nous y
323+ Les valeurs données lors de la configuration seront ignorées et vous devrez en fournir au moment du rendu. Nous y
324324reviendrons plus tard. Cette structure peut être remplacée par ` nullptr ` si vous ne voulez pas utiliser de dynamisme
325325sur ces états.
326326
327327## Pipeline layout
328328
329- Les variables ` uniform ` dans les shaders sont des données globales similaires aux états dynamiques. Elles doivent
330- être déterminées lors du rendu pour altérer les calculs des shaders sans avoir à les recréer. Elles sont très utilisées
331- pour fournir les matrices de transformation au vertex shader et pour créer des samplers de texture dans les fragment
329+ Les variables ` uniform ` dans les shaders sont des données globales similaires aux états dynamiques. Elles doivent
330+ être déterminées lors du rendu pour altérer les calculs des shaders sans avoir à les recréer. Elles sont très utilisées
331+ pour fournir les matrices de transformation au vertex shader et pour créer des samplers de texture dans les fragment
332332shaders.
333333
334- Ces variables doivent être configurées lors de la création de la pipeline en créant une variable
334+ Ces variables doivent être configurées lors de la création de la pipeline en créant une variable
335335de type ` VkPipelineLayout ` . Même si nous n'en utilisons pas dans nos shaders actuels nous devons en créer un vide.
336336
337337Créez un membre donnée pour stocker la structure car nous en aurons besoin plus tard.
@@ -355,8 +355,8 @@ if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout
355355}
356356```
357357
358- Cette structure informe également sur les _ push constants_ , une autre manière de passer des valeurs dynamiques au
359- shaders que nous verrons dans un futur chapitre. Le pipeline layout sera utilisé pendant toute la durée du
358+ Cette structure informe également sur les _ push constants_ , une autre manière de passer des valeurs dynamiques au
359+ shaders que nous verrons dans un futur chapitre. Le pipeline layout sera utilisé pendant toute la durée du
360360programme, nous devons donc le détruire dans la fonction ` cleanup ` :
361361
362362``` c++
@@ -368,8 +368,8 @@ void cleanup() {
368368
369369## Conclusion
370370
371- Voila tout ce qu'il y a à savoir sur les étapes à fonction fixée! Leur configuration représente un gros travail
372- mais nous sommes au courant de tout ce qui se passe dans la pipeline graphique, ce qui réduit les chances de
371+ Voila tout ce qu'il y a à savoir sur les étapes à fonction fixée! Leur configuration représente un gros travail
372+ mais nous sommes au courant de tout ce qui se passe dans la pipeline graphique, ce qui réduit les chances de
373373comportement imprévu à cause d'un paramètre par défaut oublié.
374374
375375Il reste cependant encore un objet à créer avant du finaliser la pipeline graphique. Cet objet s'appelle
0 commit comments