KhronosGroup / KhronosGroup/Vulkan-Tutorial
`renderFinishedSemaphores` incorrectly allocated per swapchain image instead of per frame in flight
- Dominant language
- C++
- Stars
- 418
- Forks
- 126
- Avg merge
- 11d 6h
- Merged PRs (30d)
- 31
Description
**Page:** https://docs.vulkan.org/tutorial/latest/03_Drawing_a_triangle/03_Drawing/03_Frames_in_flight.html
In `createSyncObjects`, the three sync objects are allocated with inconsistent bounds:
```cpp
// Per swapchain image:
for (size_t i = 0; i < swapChainImages.size(); i++)
renderFinishedSemaphores.emplace_back(...);
// Per frame in flight:
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
presentCompleteSemaphores.emplace_back(...);
inFlightFences.emplace_back(...);
}
```
This contradicts the tutorial's own stated design principle — that resources accessed during rendering must be duplicated per concurrent frame, not per swapchain image — and introduces three concrete problems:
**1. Index mismatch.** `presentCompleteSemaphores` is indexed by `current_frame`; `renderFinishedSemaphores` is indexed by the `image_index` returned from `vkAcquireNextImageKHR`. These are independent values that happen to alias in simple cases but have no guaranteed relationship. The submit/present code mixes two different index schemes without acknowledgment.
**2. Swapchain recreation requires semaphore teardown.** Semaphores keyed by swapchain image count must be destroyed and recreated whenever the swapchain is recreated (resize, etc.), because the image count can change. Semaphores keyed by `MAX_FRAMES_IN_FLIGHT` survive swapchain recreation untouched. The tutorial never addresses this, leaving readers with code that will silently break on resize unless they independently discover and fix the lifetime issue. The [swapchain recreation page](https://docs.vulkan.org/tutorial/latest/03_Drawing_a_triangle/04_Swap_chain_recreation.html) also does not document that the semaphore count could theoretically change on recreation — in practice drivers likely return the same image count, which is probably why this went unnoticed.
**3. Over-allocation.** The Vulkan spec requires `swapChainImages.size() >= MAX_FRAMES_IN_FLIGHT`, so this always creates at least as many `renderFinishedSemaphores` as needed, and usually more.
### Fix
Allocate `renderFinishedSemaphores` in the same loop as the other per-frame resources (bounded by `MAX_FRAMES_IN_FLIGHT`) and index it by `current_frame` at submit/present time, the same as `presentCompleteSemaphores` and `inFlightFences`.
---
*This issue was generated with the assistance of Claude.*
Contributor guide
Research direction
Start with createSyncObjects on the Frames in flight tutorial page, then inspect the submit and present code that indexes the synchronization objects. Allocate renderFinishedSemaphores with the per-frame resources and use current_frame consistently; verify the swapchain recreation page no longer needs to account for their lifetime.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- computer-graphics, documentation
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100