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>