Vulkan - 在 vkCmdPipelineBarrier 命令中设置的渲染过程中存在 "stages"
Vulkan - what "stages" exist out of a render pass for setting in vkCmdPipelineBarrier command
提交 vkCmdPipelineBarrier
渲染通道外的 srcStageMask/dstStageMask
时可以设置哪些阶段,因为在这种情况下没有子通道绑定点到图形管道?
在子通道中提交 vkCmdPipelineBarrier
时的相同问题,该子通道具有到计算管道的绑定点,我猜它没有像 VK_PIPELINE_STAGE_VERTEX_SHADER_BIT 这样的阶段,也许还有更多。
谢谢
编辑
首先,感谢@Nicol Bolas 的评论,无法在子通道中间调度计算着色器。
我想澄清一下我的问题:
假设我有一个图像,在渲染过程之后将具有 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL 的布局。
renderpass 之后,我想用新数据更新图像并希望将其布局更改为 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL。
因此,在录制完vkCmdEndRenderPass后,我录制了一个vkCmdPipelineBarrier命令如下:
const VkImageMemoryBarrier imageMemoryBarrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
nullptr,
VK_ACCESS_SHADER_READ_BIT, // srcAccessMask
VK_ACCESS_TRANSFER_WRITE_BIT, // dstAccessMask
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // oldLayout
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // newLayout
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
image,
{ // subresourceRange
VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
0, // baseMipLevel
VK_REMAINING_MIP_LEVELS, // levelCount
0, // baseArrayLayer
VK_REMAINING_ARRAY_LAYERS // layerCount
}
};
vkCmdPipelineBarrier(currentCommandBuffer,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
0,
0, nullptr,
0, nullptr,
1, &imageMemoryBarrier);
这确保只要 renderpass 中的先前命令仍未穿过片段着色器阶段,过渡就会等待。
但是,如果 vulkan 在 renderpass 执行完成后执行 vkCmdPipelineBarrier 怎么办?现在没有绑定管道,没有阶段 - 这是否意味着屏障将进入无休止的等待状态,直到新的渲染通道开始并且片段着色器阶段将发生?
只需检查 Valid Usage.
所有这些都是允许的,除了那些在整个设备上禁用其功能的(例如几何着色器),或者那些队列系列不支持的。
对于子通道依赖项,只允许 pipelineBindPoint
管道支持的那些(即目前只有图形)。
我认为让你深感困惑的主要问题是你认为pipeline是一个有限状态机。但是pipeline不是FSM,是pipeline(顾名思义)。它始终存在(就像它的所有阶段一样),即使当前没有流经管道。
具体来说,您的屏障用英语简单地说:“在我开始将此图像复制到此图像之后记录的任何命令之前,请确保在我完成读取此图像之前记录的所有命令作为纹理。”
当阶段“存在”不是有效问题时(如上所述);存在与不存在并不是他们真正拥有的属性。正如您在障碍的语义中看到的那样,改变它的含义甚至都没有关系。
某些阶段被有效用法所禁止,但这更多的是为了减少混淆。即使他们不被禁止,也不会改变任何事情。这些阶段的障碍将只是无操作,或者会转化为逻辑上更早或更晚的阶段。
如果我没看错,那么你要同步的是:
您希望确保在前面的渲染通道完成读取图像之前,图像不会被新数据覆盖。
为此,您设置了同步障碍
Execution: FRAGMENT_SHADER -> TRANSFER
Memory: SHADER_READ -> TRANSFER_WRITE
Layout: SHADER_READ_ONLY_OPTIMAL -> TRANSFER_DST_OPTIMAL
虽然这些同步参数确保了正确性,但实际上它们有点多余。 srcAccessMask
用于需要“可用”的内存,这意味着 ~ 转移到 L2 内存中,以便以后可以访问它。
这是你的屏障中不需要的部分,因为内存已经可用(在L2内存中),否则无法正确读取。
即最佳障碍如下:
Execution: FRAGMENT_SHADER -> TRANSFER
Memory: 0 -> TRANSFER_WRITE
Layout: SHADER_READ_ONLY_OPTIMAL -> TRANSFER_DST_OPTIMAL
现在回答关于
的问题
But what if vulkan executes vkCmdPipelineBarrier after renderpass execution already finished?
像上面那些记录的障碍告诉你的 GPU 是这样的:
- 在当前队列中,等待具有
FRAGMENT_SHADER
阶段的所有先前命令完成其 FRAGMENT_SHADER
阶段,然后再继续其 TRANSFER
阶段中的后续命令。
这也意味着:
- 如果队列中没有之前的命令,则屏障的要求已经满足,可以立即继续执行后续命令。
- 如果队列中有可能不会经过
FRAGMENT_SHADER
个阶段的命令,我们不会等待它们。
- 障碍适用于曾经提交给队列的每个命令。 (但大多数命令将不再“运行中”,而是已经被删除,因为它们已完成执行。)屏障的
src
依赖性 never 指的是某些东西以后可能会提交,只针对之前提交过的东西。
如果您对这些事情有困难,您可能想看看 Introduction to Vulkan lecture which covers such synchronization topics from 22:28 以后的内容。
提交 vkCmdPipelineBarrier
渲染通道外的 srcStageMask/dstStageMask
时可以设置哪些阶段,因为在这种情况下没有子通道绑定点到图形管道?
在子通道中提交 vkCmdPipelineBarrier
时的相同问题,该子通道具有到计算管道的绑定点,我猜它没有像 VK_PIPELINE_STAGE_VERTEX_SHADER_BIT 这样的阶段,也许还有更多。
谢谢
编辑
首先,感谢@Nicol Bolas 的评论,无法在子通道中间调度计算着色器。
我想澄清一下我的问题:
假设我有一个图像,在渲染过程之后将具有 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL 的布局。
renderpass 之后,我想用新数据更新图像并希望将其布局更改为 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL。
因此,在录制完vkCmdEndRenderPass后,我录制了一个vkCmdPipelineBarrier命令如下:
const VkImageMemoryBarrier imageMemoryBarrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
nullptr,
VK_ACCESS_SHADER_READ_BIT, // srcAccessMask
VK_ACCESS_TRANSFER_WRITE_BIT, // dstAccessMask
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // oldLayout
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // newLayout
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
image,
{ // subresourceRange
VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
0, // baseMipLevel
VK_REMAINING_MIP_LEVELS, // levelCount
0, // baseArrayLayer
VK_REMAINING_ARRAY_LAYERS // layerCount
}
};
vkCmdPipelineBarrier(currentCommandBuffer,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
0,
0, nullptr,
0, nullptr,
1, &imageMemoryBarrier);
这确保只要 renderpass 中的先前命令仍未穿过片段着色器阶段,过渡就会等待。
但是,如果 vulkan 在 renderpass 执行完成后执行 vkCmdPipelineBarrier 怎么办?现在没有绑定管道,没有阶段 - 这是否意味着屏障将进入无休止的等待状态,直到新的渲染通道开始并且片段着色器阶段将发生?
只需检查 Valid Usage.
所有这些都是允许的,除了那些在整个设备上禁用其功能的(例如几何着色器),或者那些队列系列不支持的。
对于子通道依赖项,只允许 pipelineBindPoint
管道支持的那些(即目前只有图形)。
我认为让你深感困惑的主要问题是你认为pipeline是一个有限状态机。但是pipeline不是FSM,是pipeline(顾名思义)。它始终存在(就像它的所有阶段一样),即使当前没有流经管道。
具体来说,您的屏障用英语简单地说:“在我开始将此图像复制到此图像之后记录的任何命令之前,请确保在我完成读取此图像之前记录的所有命令作为纹理。”
当阶段“存在”不是有效问题时(如上所述);存在与不存在并不是他们真正拥有的属性。正如您在障碍的语义中看到的那样,改变它的含义甚至都没有关系。
某些阶段被有效用法所禁止,但这更多的是为了减少混淆。即使他们不被禁止,也不会改变任何事情。这些阶段的障碍将只是无操作,或者会转化为逻辑上更早或更晚的阶段。
如果我没看错,那么你要同步的是:
您希望确保在前面的渲染通道完成读取图像之前,图像不会被新数据覆盖。
为此,您设置了同步障碍
Execution: FRAGMENT_SHADER -> TRANSFER
Memory: SHADER_READ -> TRANSFER_WRITE
Layout: SHADER_READ_ONLY_OPTIMAL -> TRANSFER_DST_OPTIMAL
虽然这些同步参数确保了正确性,但实际上它们有点多余。 srcAccessMask
用于需要“可用”的内存,这意味着 ~ 转移到 L2 内存中,以便以后可以访问它。
这是你的屏障中不需要的部分,因为内存已经可用(在L2内存中),否则无法正确读取。
即最佳障碍如下:
Execution: FRAGMENT_SHADER -> TRANSFER
Memory: 0 -> TRANSFER_WRITE
Layout: SHADER_READ_ONLY_OPTIMAL -> TRANSFER_DST_OPTIMAL
现在回答关于
的问题But what if vulkan executes vkCmdPipelineBarrier after renderpass execution already finished?
像上面那些记录的障碍告诉你的 GPU 是这样的:
- 在当前队列中,等待具有
FRAGMENT_SHADER
阶段的所有先前命令完成其FRAGMENT_SHADER
阶段,然后再继续其TRANSFER
阶段中的后续命令。
这也意味着:
- 如果队列中没有之前的命令,则屏障的要求已经满足,可以立即继续执行后续命令。
- 如果队列中有可能不会经过
FRAGMENT_SHADER
个阶段的命令,我们不会等待它们。 - 障碍适用于曾经提交给队列的每个命令。 (但大多数命令将不再“运行中”,而是已经被删除,因为它们已完成执行。)屏障的
src
依赖性 never 指的是某些东西以后可能会提交,只针对之前提交过的东西。
如果您对这些事情有困难,您可能想看看 Introduction to Vulkan lecture which covers such synchronization topics from 22:28 以后的内容。