Vulkan:可以在 renderpass 之前生成辅助命令缓冲区吗?

Vulkan: Possible to generate secondary command buffers before renderpass?

---------------- 原始问题------------------------

在 Vulkan 中,

为了开始向辅助命令缓冲区发出命令,是否必须已经获取图像并在主命令缓冲区上调用 vkCmdBeginRenderPass()?

我是菜鸟,但对我来说就是这样。

------------------------ 编辑 #2 ------------------ --------------

是的,可以这样做:

  1. 可能异步处理逻辑并在辅助命令缓冲区中记录绘制调用。
  2. 检查是否记录了辅助命令缓冲区:如果没有,转到#1,否则继续。
  3. 获取图像
  4. 启动主命令缓冲区;启动渲染通道。
  5. 执行之前记录的辅助命令缓冲区
  6. 提交
  7. 现在

为了开始记录辅助命令缓冲区,您必须使用 VkCommandBufferInheritanceInfo 对象调用 vkBeginCommandBuffer。如果要在渲染过程中执行辅助 CB,则必须提供:

  1. 传递的 VkRenderPass 对象将在其中执行。请注意,此对象 不是 vkCmdBeginRenderPass 的产物。

  2. 上述VkRenderPass子通道的索引,该二级CB将在其中执行。

有一个可选的 VkFramebuffer,用于指定要渲染到的图像。但如前所述,这是 可选的。 规范说提供此数据可能有助于提高性能,但它仍然是可选的。

所以不,辅助 CB 没有要求在主 CB 上有一个活动的渲染通道实例,它将在其中执行。

这取决于您对二级命令缓冲区的 "issuing" 命令的含义以及您要记录在这些二级命令缓冲区中的命令。

并非所有命令都可以记录在辅助命令缓冲区中。但是有些命令可以被记录并且与渲染(因此与渲染通道)没有任何关系——数据复制、时间戳(计时器查询)这些都是例子。它们与渲染通道没有任何关联,因此不需要您启动渲染通道。

但是如果你想记录绘图命令,并且你可能知道,绘图只能在渲染过程中完成,那么渲染过程需要已经开始(在调用这个辅助命令缓冲区的主命令缓冲区中).

至于 vkAcquireNextImageKHR() 函数 - 此函数是独立的。如果 by "issuing" 你的意思是录音,那么你不需要调用这个函数。您可以记录您想要的任何(有效)命令。记录只是准备命令供以后使用,用于提交。这同样适用于你的问题的标题:

Possible to generate secondary command buffers before renderpass?

我知道这(希望)只是一个糟糕的措辞,但您可以随时记录任何命令缓冲区。重要的是提交和记录在提交的命令缓冲区中的命令顺序。那么你想如何在渲染过程之前生成一个命令缓冲区呢?如果您想记录绘图命令并开始渲染过程,您需要一个渲染过程 object。如果你想从一个主命令缓冲区中调用一个辅助命令缓冲区,并且如果这个辅助命令缓冲区绘制了一些东西,那么你需要先记录一个渲染过程开始命令。之后,您可以调用辅助命令缓冲区。但是这个辅助命令缓冲区必须已经记录:

Each element of pCommandBuffers must be in the pending or executable state.

所以你需要先记录一个辅助命令缓冲区,然后你可以记录一个调用这个辅助命令缓冲区的主命令缓冲区。

但是如果你想提交一个使用交换链图像的命令缓冲区,那么这个图像必须已经获取。正如我(和其他人)在您的其他问题中所描述的那样(难以理解帧缓冲区的循环 ),如果尚未获取此图像,则无法提交使用交换链图像的命令。但是提交和图像获取与命令缓冲区记录无关。您可以更早地记录命令缓冲区。您甚至可以 pre-record 用于各种交换链图像的各种命令缓冲区。同样,记录只是为以后使用准备命令。实际使用发生在提交时。所以你只能提交那些使用已经获取的交换链图像的命令缓冲区。

希望对您有所帮助 ;-).

是的,可以做我想做的事情,即在必须开始记录主命令缓冲区之前将绘图命令记录到辅助命令缓冲区。

问题是 two-fold。

  1. 我没有在 VkCommandBufferBeginInfo 的 'flags' 成员上为辅助缓冲区设置 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT。
  2. 验证层的错误具有误导性,它说:"No active render pass found at draw-time in Pipeline (0x12)!"。这导致我尝试错误的解决方案。