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

Skip to content

Commit 0ee9b7c

Browse files
author
Alexis Ronez
committed
Caught up with all the updates to the English version
1 parent 5a93951 commit 0ee9b7c

15 files changed

Lines changed: 379 additions & 160 deletions

fr/01_Vue_d'ensemble.md

Lines changed: 66 additions & 61 deletions
Large diffs are not rendered by default.

fr/02_Environnement_de_développement.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,8 @@ Compilez les exemples Vulkan ainsi :
218218
./build_examples.sh
219219
```
220220

221-
Si la compilation a réussi, vous avez normalement un exécutable "./examples/build/cube". Lancez-le depuis le
222-
dossier "examples/build" avec la commande "./cube" et assurez-vous que vous obtenez la fenêtre suivante :
221+
Si la compilation a réussi, vous avez normalement un exécutable "./examples/build/vkcube". Lancez-le depuis le
222+
dossier "examples/build" avec la commande "./vkcube" et assurez-vous que vous obtenez la fenêtre suivante :
223223

224224
![](/images/cube_demo_nowindow.png)
225225

@@ -313,7 +313,7 @@ int main() {
313313

314314
Nous allons maintenant créer un makefile pour compiler et lancer ce code. Créez un fichier "makefile". Je pars du
315315
principe que vous connaissez déjà les bases de makefile, dont les variables et les règles. Sinon vous pouvez trouver des
316-
introductions claires sur internet, par exemple [ici](http://mrbook.org/blog/tutorials/make/).
316+
introductions claires sur internet, par exemple [ici](https://makefiletutorial.com/).
317317

318318
Nous allons d'abord définir quelques variables pour simplifier le reste du fichier. Définissez `VULKAN_SDK_PATH`, qui se
319319
réfère à l'emplacement du dossier "x86_64" dans le SDK, par exemple :
@@ -388,7 +388,7 @@ utiliser les validation layers et devons donc lui indiquer leur localisation ave
388388

389389
```make
390390
test: VulkanTest
391-
LD_LIBRARY_PATH=$(VULKAN_SDK_PATH)/lib VK_LAYER_PATH=$(VULKAN_SDK_PATH)/etc/explicit_layer.d ./VulkanTest
391+
LD_LIBRARY_PATH=$(VULKAN_SDK_PATH)/lib VK_LAYER_PATH=$(VULKAN_SDK_PATH)/etc/vulkan/explicit_layer.d ./VulkanTest
392392
```
393393

394394
Vous devriez désormais avoir un makefile ressemblant à ceci :
@@ -405,7 +405,7 @@ VulkanTest: main.cpp
405405
.PHONY: test clean
406406

407407
test: VulkanTest
408-
LD_LIBRARY_PATH=$(VULKAN_SDK_PATH)/lib VK_LAYER_PATH=$(VULKAN_SDK_PATH)/etc/explicit_layer.d ./VulkanTest
408+
LD_LIBRARY_PATH=$(VULKAN_SDK_PATH)/lib VK_LAYER_PATH=$(VULKAN_SDK_PATH)/etc/vulkan/explicit_layer.d ./VulkanTest
409409

410410
clean:
411411
rm -f VulkanTest

fr/03_Dessiner_un_triangle/00_Mise_en_place/01_Instance.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ dignostiquer les erreurs lors de l'exécution, par exemple en reconnaissant le n
2424
s'appelle `VkApplicationInfo` :
2525

2626
```c++
27-
VkApplicationInfo appInfo = {};
28-
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
29-
appInfo.pApplicationName = "Hello Triangle";
30-
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
31-
appInfo.pEngineName = "No Engine";
32-
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
33-
appInfo.apiVersion = VK_API_VERSION_1_0;
27+
void createInstance() {
28+
VkApplicationInfo appInfo = {};
29+
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
30+
appInfo.pApplicationName = "Hello Triangle";
31+
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
32+
appInfo.pEngineName = "No Engine";
33+
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
34+
appInfo.apiVersion = VK_API_VERSION_1_0;
35+
}
3436
```
3537

3638
Comme mentionné précédemment, la plupart des structures Vulkan vous demandent d'expliciter leur propre type dans le

fr/03_Dessiner_un_triangle/00_Mise_en_place/02_Validation_layers.md

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ layers pour le logical device que pour le physical device, que nous verrons
5757
5858
Nous allons maintenant activer les validations layers fournies par le SDK de LunarG. Comme les extensions, nous devons
5959
indiquer leurs nom. Au lieu de devoir spécifier les noms de chacune d'entre elles, nous pouvons les activer à l'aide
60-
d'un nom générique : `VK_LAYER_LUNARG_standard_validation`.
60+
d'un nom générique : `VK_LAYER_KHRONOS_validation`.
6161
6262
Mais ajoutons d'abord deux variables spécifiant les layers à activer et si le programme doit en effet les activer. J'ai
6363
choisi d'effectuer ce choix selon si le programme est compilé en mode debug ou non. La macro `NDEBUG` fait partie
@@ -68,7 +68,7 @@ const int WIDTH = 800;
6868
const int HEIGHT = 600;
6969
7070
const std::vector<const char*> validationLayers = {
71-
"VK_LAYER_LUNARG_standard_validation"
71+
"VK_LAYER_KHRONOS_validation"
7272
};
7373
7474
#ifdef NDEBUG
@@ -128,10 +128,8 @@ void createInstance() {
128128
}
129129
```
130130

131-
Lancez maintenant le programme en mode debug et assurez-vous qu'il fonctionne. Si vous obtenez une erreur, vérifiez
132-
votre installation du SDK. Si aucune layer n'est disponible, ou seulement très peu, vous vous trouvez peut-être dans le
133-
cas dû à [ce bug](https://vulkan.lunarg.com/app/issues/578e8c8d5698c020d71580fc) (vous aurez besoin d'un compte pour
134-
voir cette page).
131+
Lancez maintenant le programme en mode debug et assurez-vous qu'il fonctionne. Si vous obtenez une erreur, référez-vous
132+
à la FAQ.
135133

136134
Modifions enfin la structure `VkCreateInstanceInfo` pour inclure les noms des validation layers à utiliser lorsqu'elles
137135
sont activées :
@@ -368,6 +366,62 @@ void cleanup() {
368366
Si vous exécutez le programme maintenant, vous devriez constater que le message n'apparait plus. Si vous voulez voir
369367
quel fonction a lancé un appel au messager, vous pouvez insérer un point d'arrêt dans la fonction de rappel.
370368

369+
## Déboguer la création et la destruction de l'instance
370+
371+
Même si nous avons mis en place un système de déboguage très efficace, deux fonctions passent sous le radar. Comme il
372+
est nécessaire d'avoir une instance pour appeler `vkCreateDebugUtilsMessengerEXT`, la création de l'instance n'est pas
373+
couverte par le messager. Le même problème apparait avec la destruction de l'instance.
374+
375+
En lisant
376+
[la documentation](https://github.com/KhronosGroup/Vulkan-Docs/blob/master/appendices/VK_EXT_debug_utils.txt#L120) on
377+
voit qu'il existe un messager spécifiquement créé pour ces deux fonctions. Il suffit de passer un pointeur vers une
378+
instance de `VkDebugUtilsMessengerCreateInfoEXT` au membre `pNext` de `VkInstanceCreateInfo`. Plaçons le remplissage de
379+
la structure de création du messager dans une fonction :
380+
381+
```c++
382+
void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) {
383+
createInfo = {};
384+
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
385+
createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
386+
createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
387+
createInfo.pfnUserCallback = debugCallback;
388+
}
389+
...
390+
void setupDebugMessenger() {
391+
if (!enableValidationLayers) return;
392+
VkDebugUtilsMessengerCreateInfoEXT createInfo;
393+
populateDebugMessengerCreateInfo(createInfo);
394+
if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
395+
throw std::runtime_error("failed to set up debug messenger!");
396+
}
397+
}
398+
```
399+
400+
Nous pouvons réutiliser cette fonctin dans `createInstance` :
401+
402+
```c++
403+
void createInstance() {
404+
...
405+
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo;
406+
if (enableValidationLayers) {
407+
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
408+
createInfo.ppEnabledLayerNames = validationLayers.data();
409+
populateDebugMessengerCreateInfo(debugCreateInfo);
410+
createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo;
411+
} else {
412+
createInfo.enabledLayerCount = 0;
413+
414+
createInfo.pNext = nullptr;
415+
}
416+
...
417+
}
418+
```
419+
420+
La variable `debugCreateInfo` est en-dehors du `if` pour qu'elle ne soit pas détruite avant l'appel à
421+
`vkCreateInstance`. La structure fournie à la création de l'instance à travers la structure `VkInstanceCreateInfo`
422+
mènera à la création d'un messager spécifique aux deux fonctions qui sera détruit automatiquement à la destruction de
423+
l'instance.
424+
371425
## Configuration
372426

373427
Les validation layers peuvent être paramétrées de nombreuses autres manières que juste avec les informations que nous

fr/03_Dessiner_un_triangle/00_Mise_en_place/04_Logical_device_et_queues.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,10 @@ capacité, par exemple parce qu'ils ne supportent que les compute shaders. Nous
9494
dans le chapitre dédié à la swap chain.
9595

9696
Comme dit dans le chapitre sur les validation layers, nous activerons les mêmes que celles que nous avons spécifiées
97-
lors de la création de l'instance. Nous n'avons pour l'instant besoin d'aucune validation layer en particulier.
97+
lors de la création de l'instance. Nous n'avons pour l'instant besoin d'aucune validation layer en particulier. Notez
98+
que le standard ne fait plus la différence entre les extensions de l'instance et celles du device, au point que les
99+
paramètres `enabledLayerCount` et `ppEnabledLayerNames` seront probablement ignorés. Nous les remplissons quand même
100+
pour s'assurer de la bonne compatibilité avec les anciennes implémentations.
98101

99102
```c++
100103
createInfo.enabledExtensionCount = 0;

fr/03_Dessiner_un_triangle/01_Présentation/00_Window_surface.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,13 @@ createInfo.hinstance = GetModuleHandle(nullptr);
5050
Nous pouvons extraire `HWND` de la fenêtre à l'aide de la fonction `glfwGetWin32Window`. La fonction
5151
`GetModuleHandle` fournit une référence au `HINSTANCE` du thread courant.
5252

53-
La surface peut ensuite être crée avec `vkCreatWin32SurfaceKHR`, fonction que nous devons encore charger nous mêmes.
54-
L'appel inclut simplement l'instance, la structure contenant les informations, l'allocateur optionnel et un pointeur
55-
sur la variable qui contiendra la référence.
53+
La surface peut maintenant être crée avec `vkCreateWin32SurfaceKHR`. Cette fonction prend en paramètre une instance, des
54+
détails sur la création de la surface, l'allocateur optionel et la variable dans laquelle placer la référence. Bien que
55+
cette fonction fasse partie d'une extension, elle est si communément utilisée qu'elle est chargée par défaut par Vulkan.
56+
Nous n'avons ainsi pas à la charger à la main :
5657

5758
```c++
58-
auto CreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR) vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR");
59-
60-
if (!CreateWin32SurfaceKHR || CreateWin32SurfaceKHR(instance, &createInfo, nullptr, &surface) != VK_SUCCESS) {
59+
if (vkCreateWin32SurfaceKHR(instance, &createInfo, nullptr, &surface) != VK_SUCCESS) {
6160
throw std::runtime_error("échec de la creation d'une window surface!");
6261
}
6362
```

fr/03_Dessiner_un_triangle/01_Présentation/01_Swap_chain.md

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,18 @@ chargement. Lancez le code et vérifiez que votre carte graphique est capable de
7272
la disponibilité de la queue de présentation implique que l'extension de la swap chain est supportée. Mais soyons
7373
tout de mêmes explicites pour cela aussi.
7474

75-
L'activation de l'extension ne requiert qu'un léger changement à la structure de création du logical device :
75+
## Activation des extensions du device
76+
77+
L'utilisation de la swap chain nécessite l'extension `VK_KHR_swapchain`. Son activation ne requiert qu'un léger
78+
changement à la structure de création du logical device :
7679

7780
```c++
7881
createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
7982
createInfo.ppEnabledExtensionNames = deviceExtensions.data();
8083
```
8184

85+
Supprimez bien l'ancienne ligne `createInfo.enabledExtensionCount = 0;`.
86+
8287
## Récupérer des détails à propos du support de la swap chain
8388

8489
Vérifier que la swap chain est disponible n'est pas suffisant. Nous devons vérifier qu'elle est compatible avec notre
@@ -205,17 +210,7 @@ Pour l'espace de couleur nous utiliserons sRGB si possible, car il en résulte
205210
compliqué donc nous utilserons un espace linéaire pour manipuler les couleurs. Le format le plus commun est
206211
`VK_FORMAT_B8G8R8A8_UNORM`.
207212
208-
Dans le meilleur des mondes la surface n'a pas de format préféré, ce que Vulkan indique en ne retournant qu'un seul
209-
`VkSurfaceFormatKHR` dont la valeur du membre `format` est `VK_FORMAT_UNDEFINED`.
210-
211-
```c++
212-
if (availableFormats.size() == 1 && availableFormats[0].format == VK_FORMAT_UNDEFINED) {
213-
return {VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR};
214-
}
215-
```
216-
217-
Si nous ne pouvons choisir librement le format, nous itérerons toute la liste et choisirons la meilleure combinaison
218-
pour nous si elle est disponible :
213+
Itérons dans la liste et voyons si le meilleur est disponible :
219214
220215
```c++
221216
for (const auto& availableFormat : availableFormats) {
@@ -230,9 +225,6 @@ prendrons le premier format disponible.
230225

231226
```c++
232227
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) {
233-
if (availableFormats.size() == 1 && availableFormats[0].format == VK_FORMAT_UNDEFINED) {
234-
return {VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR};
235-
}
236228

237229
for (const auto& availableFormat : availableFormats) {
238230
if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
@@ -267,15 +259,15 @@ Seul `VK_PRESENT_MODE_FIFO_KHR` est toujours disponible. Nous aurons donc encore
267259
un choix, car le mode que nous choisirons préférentiellement est `VK_PRESENT_MODE_MAILBOX_KHR` :
268260
269261
```c++
270-
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR> availablePresentModes) {
262+
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes) {
271263
return VK_PRESENT_MODE_FIFO_KHR;
272264
}
273265
```
274266

275267
Je pense que le triple buffering est un très bon compromis. Vérifions si ce mode est disponible :
276268

277269
```c++
278-
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR> availablePresentModes) {
270+
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes) {
279271
for (const auto& availablePresentMode : availablePresentModes) {
280272
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
281273
return availablePresentMode;
@@ -290,7 +282,7 @@ Malheuresement certains drivers ne supportent pas bien `VK_PRESENT_MODE_FIFO_KHR
290282
`VK_PRESENT_MODE_IMMEDIATE_MODE` si `VK_PRESENT_MODE_MAILBOX_KHR` n'est pas disponible :
291283
292284
```c++
293-
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR> availablePresentModes) {
285+
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes) {
294286
VkPresentModeKHR bestMode = VK_PRESENT_MODE_FIFO_KHR;
295287
296288
for (const auto& availablePresentMode : availablePresentModes) {
@@ -368,21 +360,30 @@ void createSwapChain() {
368360
}
369361
```
370362

371-
Il existe en fait encore une dernière chose que nous devons choisir, mais c'est suffisement simple pour ne pas mériter
372-
de fonction. Nous devons déterminer le nombre d'images dans la swap chain. L'implémentation spécifie le minimum
373-
nécessaire à un bon fonctionnement, et nous essayerons d'en avoir une de plus que ce nombre pour pouvoir implémenter
374-
correctement le triple buffering.
363+
Il nous reste une dernière chose à faire : déterminer le nombre d'images dans la swap chain. L'implémentation décide
364+
d'un minimum nécessaire pour fonctionner :
365+
366+
```c++
367+
uint32_t imageCount = swapChainSupport.capabilities.minImageCount;
368+
```
369+
370+
Se contenter du minimum pose cependant un problème. Il est possible que le driver fasse attendre notre programme car il
371+
n'a pas fini certaines opérations, ce que nous ne voulons pas. Il est recommandé d'utiliser au moins une image de plus
372+
que ce minimum :
375373

376374
```c++
377375
uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
376+
```
377+
378+
Il nous faut également prendre en compte le maximum d'images supportées par l'implémentation. La valeur `0` signifie
379+
qu'il n'y a pas de maximum autre que la mémoire.
380+
381+
```c++
378382
if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) {
379383
imageCount = swapChainSupport.capabilities.maxImageCount;
380384
}
381385
```
382386

383-
La valeur `0` pour `maxImageCount` signifie que la seule limite est la mémoire, c'est pourquoi dans ce cas nous
384-
laissons `imageCount` à la valeur que nous avons déterminée.
385-
386387
Comme la tradition le veut avec Vulkan, la création d'une swap chain nécessite de remplir une grande structure. Elle
387388
commence de manière familière :
388389

@@ -525,18 +526,15 @@ Ces images ont été crées par l'implémentation avec la swap chain et elles se
525526
destruction de la swap chain, nous n'aurons donc rien à rajouter dans la fonction `cleanup`.
526527

527528
Ajoutons le code nécessaire à la récupération des références à la fin de `createSwapChain`, juste après l'appel à
528-
`vkCreateSwapchainKHR`. Cette récupération est quasiment identique à la procédure standarde pour récupérer des tableaux
529-
d'objets.
529+
`vkCreateSwapchainKHR`. Comme notre logique n'a au final informé Vulkan que d'un minimum pour le nombre d'images dans la
530+
swap chain, nous devons nous enquérir du nombre d'images avant de redimensionner le conteneur.
530531

531532
```c++
532533
vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);
533534
swapChainImages.resize(imageCount);
534535
vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data());
535536
```
536537
537-
Notez que lorsque nous avons créé la swap chain nous avons indiqué une valeur `minImageCount`, mais nous ne pouvons
538-
nous y fier car l'implémentation peut en créer plus, et c'est pourquoi nous devons demander le nombre d'images.
539-
540538
Une dernière chose : gardez dans des variables le format et le nombre d'images de la swap chain, nous en aurons
541539
besoin dans de futurs chapitres.
542540

0 commit comments

Comments
 (0)