Hello, I am trying to understand using multiple render passes. I have a chain of render passes:
std::array<VkAttachmentDescription, 4> attachments{};
// shadow map attachment
attachments[0].format = _point_light_shadow_map.image_info.getFormat();
attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[0].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
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;
// color attachment
attachments[1].format = VK_FORMAT_R8G8B8A8_UNORM;
attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[1].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
// depth attachment
attachments[2].format = _vk_dev.get()->depth_image.getFormat();
attachments[2].samples = VK_SAMPLE_COUNT_1_BIT;
attachments[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[2].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attachments[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachments[2].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
// post processing attachment
attachments[3].format = _vk_dev.get()->getFormat();
attachments[3].samples = VK_SAMPLE_COUNT_1_BIT;
attachments[3].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[3].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
attachments[3].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachments[3].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[3].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[3].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
VkAttachmentReference shadow_attachment_reference{};
shadow_attachment_reference.attachment = 0;
shadow_attachment_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkAttachmentReference color_attachment_reference{};
color_attachment_reference.attachment = 1;
color_attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentReference depth_attachment_reference{};
depth_attachment_reference.attachment = 2;
depth_attachment_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkAttachmentReference post_processing_attachment_reference{};
post_processing_attachment_reference.attachment = 3;
post_processing_attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
//shadow map render pass dependency
std::array<VkSubpassDependency, 2> dependency{};
dependency[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependency[0].dstSubpass = 0;
dependency[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency[0].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependency[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
dependency[0].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dependency[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
dependency[1].srcSubpass = 0;
dependency[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependency[1].srcStageMask = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
dependency[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependency[1].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dependency[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
dependency[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
std::array<VkSubpassDescription, 1> shadow_subpasses{};
shadow_subpasses[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
shadow_subpasses[0].pDepthStencilAttachment = &shadow_attachment_reference;
VkRenderPassCreateInfo shadow_create_info{};
shadow_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
shadow_create_info.subpassCount = shadow_subpasses.size();
shadow_create_info.pSubpasses = shadow_subpasses.data();
shadow_create_info.dependencyCount = dependency.size();
shadow_create_info.pDependencies = dependency.data();
shadow_create_info.attachmentCount = attachments.size();
shadow_create_info.pAttachments = attachments.data();
VK_CHECK(vkCreateRenderPass(_vk_dev.get()->device, &shadow_create_info, nullptr, &_shadow_render_pass));
// offscreen render pass dependency
dependency[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependency[0].dstSubpass = 0;
dependency[0].srcStageMask = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
dependency[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependency[0].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dependency[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
dependency[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
dependency[1].srcSubpass = 0;
dependency[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependency[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependency[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependency[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
dependency[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
std::array<VkSubpassDescription, 1> subpasses{};
subpasses[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpasses[0].colorAttachmentCount = 1;
subpasses[0].pColorAttachments = &color_attachment_reference;
subpasses[0].pDepthStencilAttachment = &depth_attachment_reference;
VkRenderPassCreateInfo create_info{};
create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
create_info.subpassCount = subpasses.size();
create_info.pSubpasses = subpasses.data();
create_info.dependencyCount = dependency.size();
create_info.pDependencies = dependency.data();
create_info.attachmentCount = attachments.size();
create_info.pAttachments = attachments.data();
VK_CHECK(vkCreateRenderPass(_vk_dev.get()->device, &create_info, nullptr, &_offscreen_render_pass));
// post processing render pass dependency
dependency[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependency[0].dstSubpass = 0;
dependency[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependency[0].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependency[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
dependency[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
dependency[1].srcSubpass = 0;
dependency[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependency[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependency[1].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependency[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependency[1].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dependency[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
std::array<VkSubpassDescription, 1> post_processing_subpasses{};
post_processing_subpasses[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
post_processing_subpasses[0].pColorAttachments = &post_processing_attachment_reference;
post_processing_subpasses[0].colorAttachmentCount = 1;
VkRenderPassCreateInfo post_processing_create_info{};
post_processing_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
post_processing_create_info.subpassCount = post_processing_subpasses.size();
post_processing_create_info.pSubpasses = post_processing_subpasses.data();
post_processing_create_info.dependencyCount = dependency.size();
post_processing_create_info.pDependencies = dependency.data();
post_processing_create_info.attachmentCount = attachments.size();
post_processing_create_info.pAttachments = attachments.data();
VK_CHECK(vkCreateRenderPass(_vk_dev.get()->device, &post_processing_create_info, nullptr, &_post_processing_render_pass));
It works well but I don`t know if it is good to create attachments and bind all of them to all render passes and then create framebuffers with all the attachments. I think it would be better to use attachments that I use in the specific render pass. I have tried to experiment but Vulkan says about render pass compatibility. And when I tried to create render passes with different amount of subpasses Vulkan also complained about it. Can you tell me how to do it correctly? Thanks for help.