来自先前子通道的 Vulkan 输入附件
Vulkan input attachment from previous subpass
我正在尝试使用在子通道 0 中创建的颜色附件作为子通道 1 中的输入附件。但是有一个问题我无法解决。
我目前的问题如下,我尝试使用 VK_ATTACHMENT_LOAD_OP_CLEAR
清除传递开头的附件 0,但出现错误。
Cannot clear attachment 0 with invalid first layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL.
这对我来说似乎很奇怪,附件 0 不会得到布局 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
直到子通道 1 它是输入附件,而当布局仍然是 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
时清除应该已经发生了(据我所知)。
我现在尝试在验证错误后继续 运行,附件 0 确实 被清除,这让我更加不确定。我显然可以忽略验证错误,但可能会发生一些奇怪的事情,这可能会在以后引起问题,所以我没有足够的自信来忽略它。
这是会给出错误的最少代码:
VkAttachmentDescription attachments[1] {};
attachments[0].format = VK_FORMAT_R16G16B16A16_SFLOAT;
attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentReference pass_0_ColorAttachments[1];
pass_0_ColorAttachments[0].attachment = 0;
pass_0_ColorAttachments[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentReference pass_1_InputAttachments[1];
pass_1_InputAttachments[0].attachment = 0;
pass_1_InputAttachments[0].layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkSubpassDescription subpasses[2] {};
subpasses[0].colorAttachmentCount = 1;
subpasses[0].pColorAttachments = pass_0_ColorAttachments;
subpasses[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpasses[1].inputAttachmentCount = 1;
subpasses[1].pInputAttachments = pass_1_InputAttachments;
subpasses[1].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
VkSubpassDependency subpassDependancies[1] {};
subpassDependancies[0].srcSubpass = 0;
subpassDependancies[0].dstSubpass = 1;
subpassDependancies[0].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
subpassDependancies[0].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
subpassDependancies[0].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
subpassDependancies[0].dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
subpassDependancies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
VkRenderPassCreateInfo renderpassCreateInfo {};
renderpassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderpassCreateInfo.attachmentCount = 1;
renderpassCreateInfo.pAttachments = attachments;
renderpassCreateInfo.subpassCount = 2;
renderpassCreateInfo.pSubpasses = subpasses;
renderpassCreateInfo.dependencyCount = 1;
renderpassCreateInfo.pDependencies = subpassDependancies;
VkRenderPass renderPass;
vkCreateRenderPass(device, &renderpassCreateInfo, nullptr, &renderPass);
下一部分仅在无法指定 VK_ATTACHMENT_LOAD_OP_CLEAR
用于首先用作颜色附件并在稍后的子通道中用作输入附件的附件时才相关(我看不出为什么这是不可能的,除非vulkan 在每个子通道执行加载操作)。所以这是一个单独的问题。
我可以不使用 VK_ATTACHMENT_LOAD_OP_CLEAR
,而是使用 vkCmdClearAttachments
手动清除附件并使用 VK_ATTACHMENT_LOAD_OP_DONT_CARE
进行附件的加载操作。
我在调用 vkCmdClearAttachments
时遇到崩溃错误
我启动了命令缓冲区记录和渲染通道,在第一个子通道中调用:
VkClearAttachment clearAtts[] = {{VK_IMAGE_ASPECT_COLOR_BIT, 1, {0,0,0,0}}};
VkClearRect rect = {{{0,0}, {1,1}}, 0, 1};
vkCmdClearAttachments(vkCommandBuffer, 1, clearAtts, 1, &rect);
{1,1}作为范围说明这不是问题
您遇到了同样的问题. It's a bug in the validation layer in 1.0.17. It would appear that the current Github head 已修复,但该修复不在 1.0.21 版本中。
但是您仍然需要修复下面的问题 ;)
subpassDependancies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
您不会将图像作为彩色附件来阅读。您将把它作为输入附件来阅读。来自片段着色器。所以这意味着 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
.
如果这修复了错误,那么我猜验证层被你古怪的依赖访问掩码弄糊涂了。因此它无法在子通道 0 和 1 之间建立有效的依赖链,因此认为子通道 1 是第一个。
此外,您的 srcStageMask
和 dstStageMask
位 way 过度指定。每个图形阶段都不会写入图像,每个图形阶段之后也不会访问它。您只将图像作为颜色附件写入,您只会在片段着色器中读取它。
所以你的 srcStageMask
应该只是 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
,而你的 dstStageMask
应该是 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
。
我正在尝试使用在子通道 0 中创建的颜色附件作为子通道 1 中的输入附件。但是有一个问题我无法解决。
我目前的问题如下,我尝试使用 VK_ATTACHMENT_LOAD_OP_CLEAR
清除传递开头的附件 0,但出现错误。
Cannot clear attachment 0 with invalid first layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL.
这对我来说似乎很奇怪,附件 0 不会得到布局 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
直到子通道 1 它是输入附件,而当布局仍然是 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
时清除应该已经发生了(据我所知)。
我现在尝试在验证错误后继续 运行,附件 0 确实 被清除,这让我更加不确定。我显然可以忽略验证错误,但可能会发生一些奇怪的事情,这可能会在以后引起问题,所以我没有足够的自信来忽略它。
这是会给出错误的最少代码:
VkAttachmentDescription attachments[1] {};
attachments[0].format = VK_FORMAT_R16G16B16A16_SFLOAT;
attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentReference pass_0_ColorAttachments[1];
pass_0_ColorAttachments[0].attachment = 0;
pass_0_ColorAttachments[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentReference pass_1_InputAttachments[1];
pass_1_InputAttachments[0].attachment = 0;
pass_1_InputAttachments[0].layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkSubpassDescription subpasses[2] {};
subpasses[0].colorAttachmentCount = 1;
subpasses[0].pColorAttachments = pass_0_ColorAttachments;
subpasses[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpasses[1].inputAttachmentCount = 1;
subpasses[1].pInputAttachments = pass_1_InputAttachments;
subpasses[1].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
VkSubpassDependency subpassDependancies[1] {};
subpassDependancies[0].srcSubpass = 0;
subpassDependancies[0].dstSubpass = 1;
subpassDependancies[0].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
subpassDependancies[0].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
subpassDependancies[0].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
subpassDependancies[0].dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
subpassDependancies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
VkRenderPassCreateInfo renderpassCreateInfo {};
renderpassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderpassCreateInfo.attachmentCount = 1;
renderpassCreateInfo.pAttachments = attachments;
renderpassCreateInfo.subpassCount = 2;
renderpassCreateInfo.pSubpasses = subpasses;
renderpassCreateInfo.dependencyCount = 1;
renderpassCreateInfo.pDependencies = subpassDependancies;
VkRenderPass renderPass;
vkCreateRenderPass(device, &renderpassCreateInfo, nullptr, &renderPass);
下一部分仅在无法指定 VK_ATTACHMENT_LOAD_OP_CLEAR
用于首先用作颜色附件并在稍后的子通道中用作输入附件的附件时才相关(我看不出为什么这是不可能的,除非vulkan 在每个子通道执行加载操作)。所以这是一个单独的问题。
我可以不使用 VK_ATTACHMENT_LOAD_OP_CLEAR
,而是使用 vkCmdClearAttachments
手动清除附件并使用 VK_ATTACHMENT_LOAD_OP_DONT_CARE
进行附件的加载操作。
我在调用 vkCmdClearAttachments
时遇到崩溃错误
我启动了命令缓冲区记录和渲染通道,在第一个子通道中调用:
VkClearAttachment clearAtts[] = {{VK_IMAGE_ASPECT_COLOR_BIT, 1, {0,0,0,0}}};
VkClearRect rect = {{{0,0}, {1,1}}, 0, 1};
vkCmdClearAttachments(vkCommandBuffer, 1, clearAtts, 1, &rect);
{1,1}作为范围说明这不是问题
您遇到了同样的问题
但是您仍然需要修复下面的问题 ;)
subpassDependancies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
您不会将图像作为彩色附件来阅读。您将把它作为输入附件来阅读。来自片段着色器。所以这意味着 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
.
如果这修复了错误,那么我猜验证层被你古怪的依赖访问掩码弄糊涂了。因此它无法在子通道 0 和 1 之间建立有效的依赖链,因此认为子通道 1 是第一个。
此外,您的 srcStageMask
和 dstStageMask
位 way 过度指定。每个图形阶段都不会写入图像,每个图形阶段之后也不会访问它。您只将图像作为颜色附件写入,您只会在片段着色器中读取它。
所以你的 srcStageMask
应该只是 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
,而你的 dstStageMask
应该是 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
。