为什么我的子通道输入附件布局无效?

Why is my subpass input attachment layout invalid?

我正在构建无头 Vulkan 渲染器,无法理解我收到的验证错误:

VUID-VkAttachmentReference-layout-parameter(ERROR / SPEC): msgNum: 1971405941 - Validation
Error: [ VUID-VkAttachmentReference-layout-parameter ] Object 0: handle = 0x7faea7064018, type =
VK_OBJECT_TYPE_DEVICE; | MessageID = 0x75814475 | vkCreateRenderPass: value of pCreateInfo-
>pSubpasses[0].pInputAttachments[1941].layout (3302454) does not fall within the begin..end
range of the core VkImageLayout enumeration tokens and is not an extension added token. The
Vulkan spec states: layout must be a valid VkImageLayout value
(https://vulkan.lunarg.com/doc/view/1.2.162.1/mac/1.2-extensions/vkspec.html#VUID-
VkAttachmentReference-layout-parameter)
    Objects: 1
        [0] 0x7faea7064018, type: 3, name: NULL

我已尽我所能,但我不明白问题出在哪里。我正在关注 this example which shows how to render headless and this 更一般的教程,即使我的代码与这两个示例几乎相同,也会导致 1941 年出现由分段错误引起的确切验证错误。

导致错误的函数代码:

void Renderer::CreateRenderPass(VkFormat depth_format) {
  VkAttachmentDescription attachments[2];
  attachments[0].format = VK_FORMAT_R8G8B8_UNORM;
  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].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  attachments[0].finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;

  attachments[1].format = depth_format;
  attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
  attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

  VkAttachmentReference color_ref;
  color_ref.attachment = 0;
  color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

  VkAttachmentReference depth_ref;
  depth_ref.attachment = 1;
  depth_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

  VkSubpassDescription subpass;
  subpass.colorAttachmentCount = 1;
  subpass.pColorAttachments = &color_ref;
  subpass.pDepthStencilAttachment = &depth_ref;
  subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;

  VkSubpassDependency dependencies[2];

  dependencies[0].dstSubpass = 0;
  dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
  dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
  dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
  dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
  dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
                                | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;

  dependencies[1].srcSubpass = 0;
  dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
  dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
  dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
  dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
  dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
                                | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;

  VkRenderPassCreateInfo render_pass_info;
  render_pass_info.pNext = nullptr;
  render_pass_info.subpassCount = 1;
  render_pass_info.attachmentCount = 2;
  render_pass_info.dependencyCount = 2;
  render_pass_info.pSubpasses = &subpass;
  render_pass_info.pAttachments = attachments;
  render_pass_info.pDependencies = dependencies;
  render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;

  if (vkCreateRenderPass(device_, &render_pass_info, nullptr, &render_pass_))
    throw std::runtime_error("failed to create render pass");
}
VkSubpassDescription subpass;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_ref;
subpass.pDepthStencilAttachment = &depth_ref;
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;

这里有几个成员未初始化。其中subpass.inputAttachmentCountsubpass.pInputAttachments。因此该数组包含垃圾,包括 layout 成员,它是 3302454 的值,是现有 VkImageLayout 枚举数的 none。

感谢@krOoze,我发现问题是我没有初始化很多subpass参数。但他确实提到你还需要将 subpass.pResolveAttachments 设置为空指针。

VkSubpassDescription subpass;
subpass.colorAttachmentCount = 1;
subpass.inputAttachmentCount = 0;
subpass.pInputAttachments = nullptr;
subpass.pResolveAttachments = nullptr;
subpass.pColorAttachments = &color_ref;
subpass.pDepthStencilAttachment = &depth_ref;
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;