Skip to content

Fix acquire semaphore lifetime on swapchain rebuild - #1757

Open
pahlevan wants to merge 1 commit into
vsg-dev:masterfrom
pahlevan:codex/fix-buffer-and-swapchain-lifetimes
Open

pahlevan wants to merge 1 commit into
vsg-dev:masterfrom
pahlevan:codex/fix-buffer-and-swapchain-lifetimes

Conversation

@pahlevan

@pahlevan pahlevan commented Oct 29, 2026 •

Copy link
Copy Markdown

Description

Window::buildSwapchain() waits for device idle and clears _frames and _indices, but keeps _availableSemaphores and appends a fresh set. Each rebuild therefore retains another swapchain's acquire semaphores. The stale set can include a semaphore signaled by a VK_SUBOPTIMAL_KHR acquisition; reusing it after the rebuild can trigger VUID-vkAcquireNextImageKHR-semaphore-01286.

Clear the acquire semaphore pool alongside the old frames and indices, after vkDeviceWaitIdle. The existing initialization resets _availableSemaphoreIndex and creates one fresh acquire semaphore per new image. No API or dependency changes.

Type of change

  • Bug fix (non-breaking change)

How Has This Been Tested?

  • Built upstream master e4718bf078a26930e0b6f5932d2537b689fa3969 before and after the change with MSVC x64, Ninja, RelWithDebInfo, shader compiler support disabled.
  • A standalone native-window probe fails before the fix on the first rebuild: 6 acquire semaphores for 3 images. With the fix, all 16 rebuilds retain exactly 3 for 3 images.
  • Backported the same one-line change to downstream's pinned 599a8c5c61cbb993079261b2ada99bd843badf5b. Its separate Qt/Vulkan probe alternates window dimensions 16 times, presents and reads back after each resize. With Khronos validation enabled it completes with 10 validation errors before, 0 after, including the acquire semaphore VUID above. This downstream validation result is distinct from the standalone test of current master.

Test environment: Windows x64, Intel UHD 770, MSVC 14.51, Vulkan SDK 1.4.313.2.

The standalone Windows reproduction links only VSG:

#include <vsg/all.h>
#include <vsg/platform/win32/Win32_Window.h>
#include <iostream>

class ProbeWindow : public vsg::Inherit<vsgWin32::Win32_Window, ProbeWindow>
{
public:
    using Inherit::Inherit;
    size_t acquireSemaphoreCount() const { return _availableSemaphores.size(); }
};

int main()
{
    auto traits = vsg::WindowTraits::create();
    traits->width = 640;
    traits->height = 480;
    traits->debugLayer = true;
    auto window = ProbeWindow::create(traits);
    window->getOrCreateSwapchain();
    for (int i = 0; i < 16; ++i)
    {
        window->resize();
        std::cout << window->acquireSemaphoreCount() << " / "
                  << window->frames().size() << '\n';
        if (window->acquireSemaphoreCount() != window->frames().size()) return 1;
    }
    return 0;
}

Build the snippet as a C++ executable linked to vsg::vsg. Calling resize() intentionally rebuilds the swapchain even with unchanged dimensions, so semaphore retention is deterministic without mouse input or application data.

Rebuilding a swapchain clears its frames and indices but appends new
acquire semaphores to the old pool. Repeated rebuilds retain obsolete
semaphores and can reuse a signaled semaphore after SUBOPTIMAL acquisition.

Clear the acquire semaphore pool after vkDeviceWaitIdle, alongside the
other per-swapchain resources. The existing code resets its index and
creates a fresh semaphore for each new swapchain image.

Validation:
- Windows x64, MSVC, RelWithDebInfo, Intel UHD 770, Vulkan 1.4.313.2.
- Independent probe against master e4718bf: first rebuild retains six
  acquire semaphores for three images before the fix; all sixteen rebuilds
  retain exactly three after the fix.
- Downstream resize/presentation/readback probe on 599a8c5: sixteen
  alternating resizes report ten Khronos validation errors before this
  change and zero after it (semaphore-01286).

This branch has not been deployed

No deployments
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.

1 participant