[perf][MEDIUM] Single shared semaphore pair prevents multiple frames in flight #41

Closed
opened 2026-06-16 16:51:29 +02:00 by jorijnvdgraaf · 1 comment

Subsystem: Window / swapchain / frame loop
Location: implementations/Crafter.Graphics-Window.cpp:417-431, 675-682, 805-817
Impact: MEDIUM (enabler) · Effort: Medium

Problem

Exactly one presentComplete and one renderComplete semaphore exist for the Window's lifetime, baked into the shared submitInfo. With one pair you cannot have frame N's render-complete and frame N+1's acquire pending simultaneously. There are also zero fences in the class.

Proposed fix

std::array<Semaphores, numFrames> indexed by a free-running CPU frame counter % numFramesnot by currentBuffer (the image index isn't known until after acquire). Acquire signals frameSemaphores[frame].presentComplete; submit waits on it and signals frameSemaphores[frame].renderComplete; present waits on renderComplete.

Correctness caveat

Today this is not an active race — the wait-idle masks it. It only becomes a fix once the wait-idle is removed. Per-frame semaphores alone also cause command-buffer use-after-free; the per-frame fences are mandatory. Bundle with the vkQueueWaitIdle issue.

**Subsystem:** Window / swapchain / frame loop **Location:** `implementations/Crafter.Graphics-Window.cpp:417-431, 675-682, 805-817` **Impact:** MEDIUM (enabler) · **Effort:** Medium ### Problem Exactly one `presentComplete` and one `renderComplete` semaphore exist for the Window's lifetime, baked into the shared `submitInfo`. With one pair you cannot have frame N's render-complete and frame N+1's acquire pending simultaneously. There are also zero fences in the class. ### Proposed fix `std::array<Semaphores, numFrames>` indexed by a free-running **CPU frame counter % numFrames** — *not* by `currentBuffer` (the image index isn't known until after acquire). Acquire signals `frameSemaphores[frame].presentComplete`; submit waits on it and signals `frameSemaphores[frame].renderComplete`; present waits on `renderComplete`. ### Correctness caveat Today this is *not* an active race — the wait-idle masks it. It only becomes a fix once the wait-idle is removed. Per-frame semaphores **alone** also cause command-buffer use-after-free; the per-frame fences are mandatory. **Bundle with the vkQueueWaitIdle issue.**
Author
Owner

Merged into #40 — per-frame fences and per-frame semaphores are a single, mutually-dependent deliverable (neither is correct on its own), so tracking them as one issue. Closing in favor of #40.

Merged into #40 — per-frame fences and per-frame semaphores are a single, mutually-dependent deliverable (neither is correct on its own), so tracking them as one issue. Closing in favor of #40.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Catcrafts/Crafter.Graphics#41
No description provided.