Vulkan渲染通道:为何srcStageMask中需包含VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
首先给出Sascha Willems教程中的渲染通道依赖定义代码:
.srcSubpass = VK_SUBPASS_EXTERNAL; .dstSubpass = 0; .srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; .srcAccessMask = 0; .dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; .dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
技术疑问
为何需要在srcStageMask中指定VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT?若仅等待VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT阶段完成,其之前的所有渲染阶段(包括EARLY_FRAGMENT测试阶段)理应已执行完毕,这样是否足够?
解答
这得从Vulkan的阶段依赖规则说起——阶段依赖只保证指定的源阶段完成,不自动包含该阶段之前的所有阶段。
如果只在srcStageMask里写VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,Vulkan只会确保外部提交的渲染任务中,COLOR_ATTACHMENT_OUTPUT阶段的操作完成,但不保证更早的EARLY_FRAGMENT_TESTS阶段已经结束。而当前子通道的EARLY_FRAGMENT_TESTS阶段要写入深度/模板附件,要是外部任务的同阶段操作还在跑,就会引发资源竞争,导致数据错误。
加上VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,是明确告诉Vulkan:必须等外部任务的深度模板测试(EARLY阶段)和颜色输出这两个阶段都完成,当前子通道的对应阶段才能开始写操作。这样才能彻底避免跨提交的资源冲突,保证渲染结果的正确性。
另外,srcAccessMask设为0是因为这里不需要等待外部对附件的读/写访问,只是要确保外部的对应阶段执行完毕,避免阶段重叠导致的资源竞争。
内容的提问来源于stack exchange,提问作者NightRadio

