Skip to content

v0.3.0 — runtime-vkDeviceWaitIdle-is-gone

Latest

Choose a tag to compare

@devin-ai-integration devin-ai-integration released this 26 Apr 21:43
· 79 commits to VCK since this release

The runtime-vkDeviceWaitIdle-is-gone release. Multi-queue, timeline-driven, fence-honest.

Merged via PR #4 (commit ee29ea6).
CI: green on the Windows runner (build.bat [A] — all 13 examples).

Added

  • Dedicated compute + transfer queues. VulkanDevice::FindQueueFamilies picks compute-only and transfer-only families when the vendor exposes them (AMD / NVIDIA almost always; Intel iGPUs often don't). Fallback to graphics is logged via VCKLog::Notice.
  • Timeline semaphore feature chain. VulkanDevice::Initialize enables VK_KHR_timeline_semaphore when the adapter supports it. VulkanDevice::HasTimelineSemaphores() reports the capability.
  • FrameScheduler owns one timeline. EndFrame signals a monotonic per-slot value; BeginFrame waits with one vkWaitSemaphores. Per-slot fences kept as a fallback.
  • FrameScheduler::FrameTimeline() / SlotToken(slot) / DrainInFlight(). Public timeline accessors + scheduler-owned full drain that doesn't touch the device globally.
  • Scheduler-aware HandleLiveResize. Drains via DrainInFlight(), recreates the swapchain with drainedExternally=true, leaves independent compute / transfer work alone during resize.
  • Secondary command buffer API. VulkanCommand::AllocateSecondary / FreeSecondary / BeginSecondary(cb, inheritance) / EndSecondary / ExecuteSecondaries(primary, …). Caller serialises pool access (rule 18).
  • VMM cross-family staging. When the transfer family differs from graphics, VMM records a release barrier on transfer, waits on the per-submit fence, then records an acquire barrier on graphics (Vulkan §7.7.4).
  • VMM per-submit fence. SubmitStagingCmd no longer calls vkQueueWaitIdle.
  • Config::DeviceCfg knobs. enableTimelineSemaphores, enableDedicatedComputeQueue, enableDedicatedTransferQueue (rule 19 — zero cost when off).
  • Example [13] SecondaryCmdExample. Per-slot secondary re-recorded each frame; primary opens the render pass with VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS. Uses scheduler-aware resize.
  • Example [12] EasyCubeExample. Cube via Primitives::Cube() + VertexLayout + PushConstants + VCKMath (carried over from v0.2.1).
  • docs/Overview.md. One-page tour: what VCK is / gives / never takes / modern v0.3 optimisations / why it's fresh / honest pick-vs-no-pick summary.
  • Rules 18–22. External synchronisation, zero-cost-for-unused, example parity, ABI stability (VCK.h is the surface), no ownership of user handles.

Changed

  • Rule 4 allow-list. Only Shutdown() paths may call vkDeviceWaitIdle. Concrete blocking sites: OneTimeCommand::End, VMM::SubmitStagingCmd, FrameScheduler::WaitInFlightFence (timeline or fence), DrainInFlight, BackpressureGovernor::WaitIfOverrun, Swapchain::Recreate default fallback (scheduler-aware path passes drainedExternally=true).
  • Rule 14 tightened. Every failure returns an explicit bool AND logs via VCKLog::Error(\"<subsystem>\", …). Silent false is a bug.
  • Logging. All LogVk call sites migrated to VCKLog::{Info,Notice,Warn,Error}.
  • build.bat / build.sh. Menus run [1][13], [A] builds all.
  • VCK.h. Repository layout, class index, config knobs, and .cpp function indexes synced to v0.3 surface (rule 21).

Fixed

  • VulkanOneTimeCommand::End no longer hangs when vkQueueSubmit fails (short-circuiting fence wait + warn-fallback path).
  • VMM staging cmd buffer now allocated from a transfer-family pool (was: graphics pool submitted to transfer queue, spec violation).
  • VMM fallback path now wraps vkQueueSubmit / vkQueueWaitIdle in VK_CHECK (rule 14).
  • VMM no longer records acquire barriers when the matching transfer submit failed (no more stale oldLayout=TRANSFER_DST_OPTIMAL on UNDEFINED images).
  • VulkanDevice::Shutdown nulls m_ComputeQueue / m_TransferQueue so post-shutdown getters fall through to the nulled graphics queue.
  • FrameScheduler::WaitInFlightFence timeline path now resets the first-frame VK_FENCE_CREATE_SIGNALED_BIT fence (avoids VUID-vkQueueSubmit-fence-00064 on first pass per slot).
  • SecondaryCmdExample::Run() matches the established `if (window.IsMinimized()) { window.WaitEvents(); continue; }` pattern.

Compatibility

  • VulkanSwapchain::Recreate gained an optional drainedExternally=false parameter; existing call sites keep their behaviour.
  • Legacy HandleLiveResize overloads kept (still call vkDeviceWaitIdle); the scheduler-aware overload is the recommended v0.3 path.
  • Dedicated compute / transfer queues default ON; opt out via cfg.device.enableDedicated*Queue = false.

Where to start

  • New? Read docs/Overview.md (10 min), then Hello VCK.
  • Upgrading from v0.2.x? Migrate LogVk callers to VCKLog::*; switch HandleLiveResize callers that own a FrameScheduler to the scheduler-aware overload; opt into dedicated queues / timeline by leaving the new DeviceCfg knobs at their default true.
  • Auditing? All 22 rules in docs/Design.md. Allow-list lives in rule 4; status / caveats / roadmap track shipped vs deferred.