perf(sync): scope frame-loop barriers to swapchain image + real per-pass stages (#115)

The inter-pass and acquire/present barriers in the frame loop set both
stage masks to ALL_COMMANDS, and the inter-pass dependency used a
queue-wide VkMemoryBarrier — fully serialising against every pipeline
stage and flushing all caches every frame, when all the next pass needs
is the swapchain image the previous one wrote.

Replace the inter-pass global VkMemoryBarrier with an image memory
barrier scoped to the swapchain image's single colour subresource (as
the intra-pass UI barrier already does), and derive the barrier stage
masks per pass: RenderPass::SwapchainStage() is overridden by UIRenderer
(COMPUTE_SHADER) and RTPass (RAY_TRACING_SHADER), so a compute->compute
edge only serialises COMPUTE while an RT pass pulls in RAY_TRACING — the
acquire/present frame-edge masks use the real union of the frame's
passes (SwapchainStageUnion). The base default and the empty-passes
fallback are the conservative COMPUTE | RAY_TRACING | TRANSFER union, so
a polymorphic or un-overridden pass can only be over- not
under-synchronised.

Adds SwapchainBarrierScope (pure CPU) pinning the per-pass derivation,
the union narrowing, and the inter-pass barrier scope; FrameLoopSync
already drives the real GPU frame loop with validation enabled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
catbot 2026-06-17 19:44:33 +00:00
commit 9414863cff
6 changed files with 316 additions and 8 deletions

View file

@ -35,6 +35,13 @@ export namespace Crafter {
RTPass(PipelineRTVulkan* p) : pipeline(p) {}
// An RT pass writes the swapchain image from the ray-tracing pipeline,
// so the frame loop's barriers must wait on RAY_TRACING_SHADER — using
// the compute stage here would under-synchronise and corrupt the image.
VkPipelineStageFlags SwapchainStage() const override {
return VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
}
void Record(VkCommandBuffer cmd, std::uint32_t frameIdx, Window& window) override {
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline->pipeline);
// NVIDIA descriptor-heap AS-read workaround (issue #15 / #7): feed