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

Skip to content

Commit 9b84ec3

Browse files
committed
Fix frames in flight sync edge case
1 parent dacc62c commit 9b84ec3

1 file changed

Lines changed: 52 additions & 2 deletions

File tree

fr/03_Dessiner_un_triangle/03_Effectuer_le_rendu/02_Rendu_et_présentation.md

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -539,8 +539,58 @@ void createSyncObjects() {
539539
}
540540
```
541541

542-
Le programme devrait maintenant fonctionner normalement et la perte de mémoire ne devrait plus exister! Et nous avons
543-
maintenant implémenté tout ce qu'il faut pour s'assurer que nous n'avons jamais plus de deux frames en vol!
542+
La fuite de mémoire n'est plus, mais le programme ne fonctionne pas encore correctement. Si `MAX_FRAMES_IN_FLIGHT` est
543+
plus grand que le nombre d'images de la swapchain ou que `vkAcquireNextImageKHR` ne retourne pas les images dans l'ordre,
544+
alors il est possible que nous lancions le rendu dans une image qui est déjà *en vol*. Pour éviter ça, nous devons pour
545+
chaque image de la swapchain si une frame en vol est en train d'utiliser celle-ci. Cette correspondance permettra de suivre
546+
les images en vol par leur fences respective, de cette façon nous aurons immédiatement un objet de synchronisation à attendre
547+
avant qu'une nouvelle frame puisse utiliser cette image.
548+
549+
Tout d'abord, ajoutez une nouvelle liste nommée `imagesInFlight`:
550+
551+
```c++
552+
std::vector<VkFence> inFlightFences;
553+
std::vector<VkFence> imagesInFlight;
554+
size_t currentFrame = 0;
555+
```
556+
557+
Préparez-la dans `CreateSyncObjects`:
558+
559+
```c++
560+
void createSyncObjects() {
561+
imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
562+
renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
563+
inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
564+
imagesInFlight.resize(swapChainImages.size(), VK_NULL_HANDLE);
565+
566+
...
567+
}
568+
```
569+
570+
Initiallement aucune frame n'utilise d'image, donc on peut explicitement l'initialiser à *pas de fence*. Maintenant, nous allons modifier
571+
`drawFrame` pour attendre la fin de n'importe quelle frame qui serait en train d'utiliser l'image qu'on nous assigné pour la nouvelle frame.
572+
573+
```c++
574+
void drawFrame() {
575+
...
576+
577+
vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
578+
579+
// Vérifier si une frame précédente est en train d'utiliser cette image (il y a une fence à attendre)
580+
if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
581+
vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
582+
}
583+
// Marque l'image comme étant à nouveau utilisée par cette frame
584+
imagesInFlight[imageIndex] = inFlightFences[currentFrame];
585+
586+
...
587+
}
588+
```
589+
590+
Nous avons implémenté tout ce qui est nécessaire à la synchronisation pour certifier qu'il n'y a pas plus de deux frames de travail
591+
dans la queue et que ces frames n'utilise pas accidentellement la même image. Notez qu'il est tout à fait normal pour d'autre parties du code,
592+
comme le nettoyage final, de se reposer sur des mécanismes de synchronisation plus durs comme `vkDeviceWaitIdle`. Vous devriez décider
593+
de la bonne approche à utiliser en vous basant sur vos besoins de performances.
544594

545595
Pour en apprendre plus sur la synchronisation rendez vous sur
546596
[ces exemples complets](https://github.com/KhronosGroup/Vulkan-Docs/wiki/Synchronization-Examples#swapchain-image-acquire-and-present)

0 commit comments

Comments
 (0)