Vulkan validation errors: per-frame acquire-barrier dstAccessMask/stage mismatch + setup-path cmd-buffer/buffer lifecycle #153
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Catcrafts/Crafter.Graphics#153
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
A native Vulkan build with the validation layer enabled spams validation errors every frame and during scene/resource setup. Reproduced on
Crafter.Graphics-de99a5fdd55628a1driving the 3DForts consumer (3DForts/3DForts#202), NVIDIA RTX 4090, driver 610.43.02, Khronos validation layer 1.4.350. All of the errors below originate in Crafter.Graphics; the consumer has no way to influence them.There are three distinct problems.
1. Per-frame error: acquire barrier
dstAccessMaskis inconsistent with its stage mask (the spammy one)Every single frame the layer logs:
Root cause
acquireBarrier(the swapchain UNDEFINED/PRESENT_SRC → GENERAL transition at the top ofWindow::Render) hardcodes both access bits:implementations/Crafter.Graphics-Window.cpp:490but the barrier is submitted with the per-pass stage union as its dst stage mask:
implementations/Crafter.Graphics-Window.cpp:836,840For an all-compute frame (every menu frame, and the typical game frame — passes only override
SwapchainStage()toCOMPUTE_SHADER),swapWriterStages == VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT.VK_ACCESS_TRANSFER_WRITE_BITis not a supported access type for the compute stage, so VUID-02820 fires — once per frame, forever.This is the same inconsistency the surrounding code was careful to avoid for the inter-pass and present barriers (those derive stages from
SwapchainStageUnion/SwapchainStage()and only useSHADER_*access). The acquire barrier'sdstAccessMaskwas never narrowed to match.Proposed fix
Derive
acquireBarrier.dstAccessMaskfrom the sameswapWriterStagesunion, patched per frame alongsideoldLayout/image(right afterswapWriterStagesis computed at line 836, before thevkCmdPipelineBarrierat line 840):(The hardcoded init at line 490 can then drop the bits, or be left as a harmless default since it's overwritten each frame.)
Note: the present barrier at line 502 has the mirror-image latent inconsistency —
srcAccessMask = VK_ACCESS_SHADER_WRITE_BITwithsrcStageMask = swapWriterStages. It doesn't currently fire (SHADER_WRITE is valid for COMPUTE/RT), but if a transfer-stage pass ever writes the image its src access would be missingTRANSFER_WRITE. Worth applying the same derivation for symmetry.2. Command-buffer / buffer lifecycle errors during scene/resource setup (fired once per match start)
When the consumer enters a Game scene (
Lobby_HostStart/Lobby_Start, which creates map meshes / RT acceleration structures / uploads), the layer logs the following burst, all on the same command buffer handle:The only
vkQueueSubmitcall sites in the library are inCrafter.Graphics-Window.cpp(the per-frame render loop and the screenshot path), so the offending command buffer is one ofdrawCmdBuffers[]. The reports say it was re-begun and re-submitted while still pending, and that three buffers were destroyed (immediately, not via the #101 deferred-deletion queue) while that submission was still in flight.This looks like a missing fence wait on the resource-setup path that runs synchronously during a scene transition (outside the normal
Render()fence gate atWindow.cpp:808), and/or an immediateBuffer::Clear()where aDeferredClear()is required. I couldn't pin the exact site from the consumer side — it needs someone with the command-buffer/setup architecture in hand. Reproduction is deterministic: it fires once on the first match start, every run.Vulkan validation errors: per-frame acquire-barrier dstAccessMask/stage mismatch + setup-path cmd-buffer/buffer lifecycle + forced GPU-AVto Vulkan validation errors: per-frame acquire-barrier dstAccessMask/stage mismatch + setup-path cmd-buffer/buffer lifecycle