vulkan 中渲染通道、命令缓冲区和清除附件之间的关系是什么?

C. *_*ler 4 renderer vulkan

我目前正在学习 vulkan 并遇到了上述问题,我似乎无法通过阅读规范来回答。

查看规范和代码示例时,它始终是相同的简化工作流程:

begin commandbuffer 
    begin renderpass
        bind stuff (pipeline, buffers, descriptor sets)
        draw
    end renderpass
end commandbuffer

create_submit_info
submit_to_graphics_queue
Run Code Online (Sandbox Code Playgroud)

现在我有点不清楚的第一件事是何时清除附件。如果我使用 LOAD_OP_CLEAR 创建我的附件,那么我必须为 提供明确的值VkRenderPassBeginInfo,但每个命令缓冲区都包含一个vkBeginRenderpass. 那么这是否意味着每个提交的命令缓冲区都会启动一个新的渲染通道并清除附件?这听起来不对。

如果我指定 LOAD_OP_DONT_CARE 那么我必须使用vkCmdClear哪种请求单独的命令缓冲区来清除附件。这也不对。

那么有人可以为我澄清命令缓冲区和渲染通道之间的关系吗?

还是对它的误解vkCmdBeginRenderPass?当一个渲染通道已经在运行时,它实际上不是开始一个新的渲染通道吗?!

感谢您的帮助。

Ekz*_*uzy 5

命令缓冲区负责存储稍后提交到队列并由硬件处理的命令。这是在 Vulkan 中执行操作的唯一方法 - 记录它们然后提交。但重要的是每个命令缓冲区都完全独立于所有其他命令缓冲区。如果要执行特定作业,则需要将设置适当状态的所有必要命令记录到命令缓冲区中。如果你想在另一个命令缓冲区中执行类似的工作,你需要在另一个命令缓冲区中记录相同的命令集,因为命令缓冲区之间没有状态共享。他们都是独立的。(有一些例外,但它们与本讨论无关,因为它们仅涉及辅助命令缓冲区)。

接下来,在 Vulkan 中渲染只能发生在渲染通道内。渲染通道是对绘制命令划分的步骤(称为子通道)以及这些绘图命令(附件)所需的渲染资源(以及它们之间的关系)的一般定义。但这只是描述,元数据。您可以定义这些附件的使用方式(作为颜色附件、作为深度附件、作为输入附件)以及它们在每个子通道中的布局。您还可以定义在渲染过程之前(加载操作)和渲染过程之后(存储操作)如何处理每个附件。

现在用于这些附件的实际资源是通过帧缓冲区定义的。通过这种方式,您可以对各种图像集执行类似的渲染操作(通过使用各种但兼容的帧缓冲区),而无需重新创建渲染通道。渲染过程中应该使用哪个帧缓冲区是在您开始渲染过程时定义的。

现在,当我们结合上述信息、渲染通道和命令缓冲区时,我们得到:每个命令缓冲区都是独立的,因此渲染必须在单个命令缓冲区(不包括辅助命令缓冲区)期间开始和结束。所以这也意味着您需要在单个命令缓冲区中开始和结束渲染过程(当然,您也可以在单个命令缓冲区中开始和结束多个渲染过程)。

那么这是否意味着每个提交的命令缓冲区都会启动一个新的渲染通道并清除附件?

如果您想要一个仅通过执行计算着色器来执行数学计算的命令缓冲区,那么您不需要渲染通道。所以这样的命令缓冲区不需要开始和结束任何渲染过程,也不需要清除任何附件。但是如果你想在命令缓冲区中渲染,那么是的,每个这样的命令缓冲区都必须开始(和结束)一个渲染通道。如果渲染涉及清除,那么每个需要执行此类操作的命令缓冲区也需要清除附件。

还是对 vkCmdBeginRenderPass 的误解?当一个渲染通道已经在运行时,它实际上不是开始一个新的渲染通道吗?!

vkCmdBeginRenderPass()开始一个新的渲染通道,是的,但在单个命令缓冲区中你不能启动另一个渲染通道,直到前一个渲染通道结束。您必须显式地启动和结束渲染过程。只有在那之后你才能开始另一个渲染通道(在同一个命令缓冲区中)。

至于清除,它们也在渲染通道开始时定义,这允许您清除具有不同颜色的附件。这样您就不必每次要更改“背景”颜色时都创建单独的渲染通道。

还有一件事关于附件清除:除非真的有必要,否则使用渲染通道清除 ( LOAD_OP_CLEAR) 而不是显式清除 ( vkCmdClear()),因为它们可能会损害性能(据我所知,大多数供应商都推荐使用渲染通道清除)。

我希望这个希望能澄清这个话题。