vulkan 创建Render Pass

RenderPass::RenderPass(const Context& context,
                       const std::vector<std::shared_ptr<Texture>> attachments,
                       const std::vector<std::shared_ptr<Texture>> resolveAttachments,
                       const std::vector<VkAttachmentLoadOp>& loadOp,
                       const std::vector<VkAttachmentStoreOp>& storeOp,
                       const std::vector<VkImageLayout>& layout,
                       VkPipelineBindPoint bindPoint, const std::string& name)
    : device_{context.device()} {
  // ASSERT(attachments.size() == loadOp.size() && attachments.size() == storeOp.size() &&
  //            attachments.size() == layout.size(),
  //        "The sizes of the attachments and their load and store operations and final "
  //        "layouts must match");
  // ASSERT(resolveAttachments.empty() || (attachments.size() ==
  // resolveAttachments.size()));

  std::vector<VkAttachmentDescription> attachmentDescriptors;
  std::vector<VkAttachmentReference> colorAttachmentReferences;
  std::vector<VkAttachmentReference> resolveAttachmentReferences;
  std::optional<VkAttachmentReference> depthStencilAttachmentReference;

  // 这个for循环是attachments的大小,传入的是swapchain()->texture(0),也就是只传入了一个Texture
  for (uint32_t index = 0; index < attachments.size(); ++index) {
    attachmentDescriptors.emplace_back(VkAttachmentDescription{
        .format = attachments[index]->vkFormat(),
        .samples = attachments[index]->VkSampleCount(),
        .loadOp = loadOp[index],
        .storeOp = storeOp[index],
        .stencilLoadOp = attachments[index]->isStencil()
                             ? loadOp[index]
                             : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
        .stencilStoreOp = attachments[index]->isStencil()
                              ? storeOp[index]
                              : VK_ATTACHMENT_STORE_OP_DONT_CARE,
        .initialLayout = attachments[index]->vkLayout(),
        .finalLayout = layout[index],
    });

    if (attachments[index]->isStencil() || attachments[index]->isDepth()) {
      depthStencilAttachmentReference = VkAttachmentReference{
          .attachment = index,
          .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
      };
    } else {
      colorAttachmentReferences.emplace_back(VkAttachmentReference{
          .attachment = index,
          .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
      });
    }
  }

  const uint32_t numAttachments = attachmentDescriptors.size();
  for (uint32_t index = 0; index < resolveAttachments.size(); ++index) {
    attachmentDescriptors.emplace_back(VkAttachmentDescription{
        .format = resolveAttachments[index]->vkFormat(),
        .samples = VK_SAMPLE_COUNT_1_BIT,
        .loadOp = loadOp[index + numAttachments],
        .storeOp = storeOp[index + numAttachments],
        .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
        .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
        .initialLayout = resolveAttachments[index]->vkLayout(),
        .finalLayout = layout[index + numAttachments],
    });

    resolveAttachmentReferences.emplace_back(VkAttachmentReference{
        .attachment = static_cast<uint32_t>(attachmentDescriptors.size() - 1),
        .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
    });
  }

  const VkSubpassDescription spd = {
      .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
      .colorAttachmentCount = static_cast<uint32_t>(colorAttachmentReferences.size()),
      .pColorAttachments = colorAttachmentReferences.data(), // 设置了colorAttachment的索引和布局信息
      .pResolveAttachments = resolveAttachmentReferences.data(), // 如果用了多重采样,就使用解析附件,将多重采样的渲染结果解析到非多重采样的纹理中
      .pDepthStencilAttachment = depthStencilAttachmentReference.has_value()
                                     ? &depthStencilAttachmentReference.value()
                                     : nullptr,
  };

  std::array<VkSubpassDependency, 2> dependencies;
  dependencies[0] = {
      .srcSubpass = VK_SUBPASS_EXTERNAL, // 表示依赖源是外部,通常指代前一个渲染通道或其他队列
      .dstSubpass = 0, // 表示依赖目标是第一个子通道(索引为 0)
      .srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, // 表示所有管线阶段的结束
      .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
                      VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
                      VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
                      VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // 表示多个目标管线阶段,包括颜色附件输出、早期和晚期片段测试以及片段着色器阶段。
      .srcAccessMask = VK_ACCESS_MEMORY_READ_BIT, // 表示对内存的读取访问
      .dstAccessMask =
          VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
          VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
          VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,// 表示目标多个附件的读写访问权限,包括颜色附件、深度模板附件和着色器读取。
  }; // 这条依赖确保从外部资源读取的数据能够正确地传递到渲染过程中的第一个子通道,进行颜色输出、深度模板测试和片段着色等操作

  dependencies[1] = {
      .srcSubpass = 0,
      .dstSubpass = VK_SUBPASS_EXTERNAL,
      .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
                      VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
                      VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
      .dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
      .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
                       VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
                       VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
      .dstAccessMask =
          VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
          VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
          VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
  };


  const VkRenderPassCreateInfo rpci = {
      .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
      .attachmentCount = static_cast<uint32_t>(attachmentDescriptors.size()),
      .pAttachments = attachmentDescriptors.data(),
      .subpassCount = 1,
      .pSubpasses = &spd,
      .dependencyCount = 2,
      .pDependencies =
          dependencies.data(),  // being extra liberal with this, in production this
                                // should be carefully provided depending upon each pass
  };

  VK_CHECK(vkCreateRenderPass(device_, &rpci, nullptr, &renderPass_));
  context.setVkObjectname(renderPass_, VK_OBJECT_TYPE_RENDER_PASS,
                          "Render pass: " + name);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值