fix(window): silence per-frame and setup-path Vulkan validation errors (#153)
Two distinct validation errors the native frame loop emitted, both originating in Crafter.Graphics with no consumer-side influence. Problem 1 — per-frame acquire-barrier access/stage mismatch. The acquire->GENERAL barrier hardcoded dstAccessMask = SHADER_WRITE|TRANSFER_WRITE but used the per-pass stage union as its dst stage mask. For an all-compute frame the union narrows to COMPUTE_SHADER, which does not support TRANSFER_WRITE, so VUID-02820 fired every frame. Derive the access mask from the same stage union via a new SwapchainWriterAccess() helper (mirroring SwapchainStageUnion), and apply it to both the acquire dst and present src masks for symmetry. Problem 2 — mid-session StartInit/FinishInit (and GetCmd/EndCmd) reuse the shared drawCmdBuffers[currentBuffer]. With no steady-state wait-idle the loop's last submission of that buffer may still be in flight when scene setup runs (building map meshes / acceleration structures), so the old code re-began (VUID-00049) and re-submitted (VUID-00071) a pending buffer, and resources freed in the StartInit..FinishInit bracket could still be referenced by it. Drain the queue at the start of StartInit/GetCmd before re-recording; setup is rare, so a wait-idle is fine (FinishInit/EndCmd already wait-idle at the end). Tests: extend SwapchainBarrierScope with SwapchainWriterAccess coverage (pure CPU), and add SetupCmdBufferReuse — a real-frame-loop regression test driving a compute pass plus interleaved mid-session StartInit rounds, asserting the validation layer stays silent. Verified both halves fail (reproducing the exact VUIDs) when their respective fix is reverted. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
7720f0a9bc
commit
7316e51dca
5 changed files with 265 additions and 4 deletions
|
|
@ -69,6 +69,26 @@ export namespace Crafter {
|
|||
return stages;
|
||||
}
|
||||
|
||||
// The access mask matching a swapchain-writer stage union, for the
|
||||
// frame-edge barriers (acquire dst / present src). A barrier's access mask
|
||||
// must only contain access flags supported by its accompanying stage mask
|
||||
// (VUID-vkCmdPipelineBarrier-pImageMemoryBarriers-02820): TRANSFER_WRITE is
|
||||
// not a valid access for COMPUTE/RAY_TRACING stages, so hardcoding both
|
||||
// SHADER_WRITE and TRANSFER_WRITE fires the VUID every frame on an
|
||||
// all-compute frame. The swapchain image is written as a storage image by
|
||||
// compute/RT passes (SHADER_WRITE) and only via TRANSFER_WRITE when a
|
||||
// transfer-stage pass is present, so derive the access bits from the same
|
||||
// per-pass stage union the barrier's stage mask uses instead of hardcoding.
|
||||
inline VkAccessFlags SwapchainWriterAccess(VkPipelineStageFlags stages) {
|
||||
VkAccessFlags access = 0;
|
||||
if (stages & (VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
|
||||
| VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR))
|
||||
access |= VK_ACCESS_SHADER_WRITE_BIT;
|
||||
if (stages & VK_PIPELINE_STAGE_TRANSFER_BIT)
|
||||
access |= VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
return access;
|
||||
}
|
||||
|
||||
// The inter-pass swapchain barrier (replacing the old queue-wide
|
||||
// VkMemoryBarrier at the #115 location). Scoped to the swapchain image's
|
||||
// single colour subresource so only that image's shader caches round-trip —
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue