Skip to content

fix: use one render-finished semaphore per swapchain image - #183

Closed
TommyRadan wants to merge 1 commit into
masterfrom
claude/issue-151-review-fhps2h
Closed

fix: use one render-finished semaphore per swapchain image#183
TommyRadan wants to merge 1 commit into
masterfrom
claude/issue-151-review-fhps2h

Conversation

@TommyRadan

Copy link
Copy Markdown
Owner

Summary

Fixes the Vulkan validation error from #151: VUID-vkQueueSubmit-pSignalSemaphores-00067 — the swapchain render-finished semaphore was reused across frames.

The backend signaled and present-waited on a single device-wide m_render_finished semaphore. The in-flight fence only gates the submit, not the present, so with 3 swapchain images frame N+1's submit could re-signal the semaphore while frame N's present was still using it.

Changes

  • vk_device.hpp: m_render_finished is now a std::vector<VkSemaphore> (one per swapchain image) instead of a single handle.
  • create_swapchain / destroy_swapchain: create and destroy the per-image semaphores alongside the swapchain, so the count tracks image-count changes on resize.
  • create_sync_objects / destroy_sync_objects: now own only m_image_available and m_in_flight_fence.
  • submit: signals and present-waits on m_render_finished[m_current_image_index].

A semaphore tied to a specific image is not re-signaled until that image is re-acquired — already gated by the acquire/fence flow — so the reuse hazard is gone. m_image_available and m_in_flight_fence are unchanged (single-frame-in-flight model).

Testing

  • Configured + built the AlphaEngine target (Ninja, Debug) — links cleanly.
  • clang-format-18 clean on both changed files.

Note: the validation message itself wasn't re-run — this was built in a headless container with no GPU/display, so the fix is verified by build + code reasoning rather than a live capture.

Closes #151


Generated by Claude Code

The Vulkan backend signaled and present-waited on a single device-wide
m_render_finished semaphore every frame. The in-flight fence only gates
the submit, not the present, so with 3 swapchain images frame N+1's
submit could re-signal the semaphore while frame N's present was still
using it, tripping VUID-vkQueueSubmit-pSignalSemaphores-00067.

Use one render-finished semaphore per swapchain image, indexed by the
acquired image index, and tie its lifetime to the swapchain so it tracks
image-count changes on resize. A semaphore bound to a specific image is
not re-signaled until that image is re-acquired, which the acquire/fence
flow already gates, so the reuse hazard is gone.

Closes #151
@github-actions

Copy link
Copy Markdown

CI build artifacts

Windows Debug and Release builds are attached to the workflow run summary under Artifacts:

  • AlphaEngine-windows-Debug — Debug AlphaEngine.exe + Khronos validation layer
  • AlphaEngine-windows-Release — Release AlphaEngine.exe

Run #249 — commit 28ec044.

@TommyRadan TommyRadan closed this Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Vulkan: swapchain render-finished semaphore is reused across frames (validation error)

1 participant