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()} {
std::vector<VkAttachmentDescription> attachmentDescriptors;
std::vector<VkAttachmentReference> colorAttachmentReferences;
std::vector<VkAttachmentReference> resolveAttachmentReferences;
std::optional<VkAttachmentReference> depthStencilAttachmentReference;
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(),
.pResolveAttachments = resolveAttachmentReferences.data(),
.pDepthStencilAttachment = depthStencilAttachmentReference.has_value()
? &depthStencilAttachmentReference.value()
: nullptr,
};
std::array<VkSubpassDependency, 2> dependencies;
dependencies[0] = {
.srcSubpass = VK_SUBPASS_EXTERNAL,
.dstSubpass = 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(),
};
VK_CHECK(vkCreateRenderPass(device_, &rpci, nullptr, &renderPass_));
context.setVkObjectname(renderPass_, VK_OBJECT_TYPE_RENDER_PASS,
"Render pass: " + name);
}