I have 2 graphical pipelines. One pipeline draws firstly and second pipeline uses result of swapchain image from first pipeline and overlays with new data. It works correctly if resolve attachment for MSAA is not used in the renderpass. But first pipeline result clears if MSAA is used in second pipeline. Second pipeline renderpass simple executes loadOp = overlay ? VK_ATTACHMENT_LOAD_OP_LOAD: VK_ATTACHMENT_LOAD_OP_CLEAR. As I understand rasterization state fills initially MSAA image and after that it resolves to framebuffer attachment. And previous swapchain image cannot be loaded. Does someone know the way to load previous swapchain image when MSAA is used?
renderpass creation looks like
{
bool use_msaa = numSamples != VK_SAMPLE_COUNT_1_BIT;
std::vector<VkAttachmentDescription> renderPassAttachments;
uint32_t attachmentReferenceCounter = 0;
std::vector<VkAttachmentReference> subPassColorAttachments;
std::vector<VkAttachmentReference> subPassDepthStencilAttachments;
std::vector<VkAttachmentReference> subPassResolveAttachments;
std::vector<VkAttachmentReference> subPassInputAttachments;
VkAttachmentDescription colorAttachment = {};
colorAttachment.format = format; //The format of the color attachment should match the format of the swap chain images
colorAttachment.samples = numSamples;
colorAttachment.loadOp = overlay ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR ; //VK_ATTACHMENT_LOAD_OP_LOAD//clear on init or load
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; //store stage result
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; //don't care - it is only for depth buffer
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;//don't care - it is only for depth buffer
if (initialLayout == VK_IMAGE_LAYOUT_UNDEFINED && finalLayout == VK_IMAGE_LAYOUT_UNDEFINED)
{
if (overlay)
{
initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
if (use_msaa)
{
finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
else
{
finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
}
}
else
{
initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
if (use_msaa)
{
finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
else
{
finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
}
}
}
colorAttachment.initialLayout = initialLayout; //undefined image layout in the memory
colorAttachment.finalLayout = finalLayout; //VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - presentation
colorAttachment.flags = 0;
renderPassAttachments.push_back(colorAttachment);
VkAttachmentReference color_reference = {};
color_reference.attachment = attachmentReferenceCounter++;
color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
subPassColorAttachments.push_back(color_reference);
/////////////////////////////////////////////////////////////
//2nd
if (include_depth)
{
VkAttachmentDescription depthAttachment = {};
depthAttachment.format = depth_format;
depthAttachment.samples = numSamples;
depthAttachment.loadOp = overlay ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR; //VK_ATTACHMENT_LOAD_OP_CLEAR;
depthAttachment.storeOp = overlay ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE;// VK_ATTACHMENT_STORE_OP_STORE; //
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;// VK_ATTACHMENT_LOAD_OP_LOAD; //
depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;// VK_ATTACHMENT_STORE_OP_STORE; //
depthAttachment.initialLayout = overlay_depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED ;//
depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
depthAttachment.flags = 0;
renderPassAttachments.push_back(depthAttachment);
VkAttachmentReference depth_reference = {};
depth_reference.attachment = attachmentReferenceCounter++;
depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
subPassDepthStencilAttachments.push_back(depth_reference);
}
/////////////////////////////////////////////////////////////
//3d
if (use_msaa) //framebuffer image == resolve attachment
{
VkAttachmentDescription colorAttachmentResolve = {};
colorAttachmentResolve.format = format;
colorAttachmentResolve.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachmentResolve.loadOp = overlay ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;// VK_ATTACHMENT_LOAD_OP_DONT_CARE;//
colorAttachmentResolve.storeOp = VK_ATTACHMENT_STORE_OP_STORE;// VK_ATTACHMENT_STORE_OP_DONT_CARE;// ;
colorAttachmentResolve.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachmentResolve.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachmentResolve.initialLayout = overlay ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachmentResolve.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
renderPassAttachments.push_back(colorAttachmentResolve);
VkAttachmentReference colorAttachmentResolveRef = {};
colorAttachmentResolveRef.attachment = attachmentReferenceCounter;
colorAttachmentResolveRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
subPassResolveAttachments.push_back(colorAttachmentResolveRef);
attachmentReferenceCounter++;
}
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.flags = 0;
subpass.inputAttachmentCount = static_cast<uint32_t>(subPassInputAttachments.size());
subpass.pInputAttachments = subPassInputAttachments.data();
subpass.colorAttachmentCount = static_cast<uint32_t>(subPassColorAttachments.size());
subpass.pColorAttachments = subPassColorAttachments.data();
subpass.pResolveAttachments = subPassResolveAttachments.data();
subpass.pDepthStencilAttachment = subPassDepthStencilAttachments.data();
subpass.preserveAttachmentCount = 0;
subpass.pPreserveAttachments = nullptr;
es in the dependency graph.*/
std::vector<VkSubpassDependency> dependencies;
VkSubpassDependency colorAttachmentDependency = {};
colorAttachmentDependency.srcSubpass = VK_SUBPASS_EXTERNAL;
colorAttachmentDependency.dstSubpass = 0;
colorAttachmentDependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
colorAttachmentDependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
colorAttachmentDependency.srcAccessMask = 0;
colorAttachmentDependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
colorAttachmentDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
dependencies.push_back(colorAttachmentDependency);
VkRenderPassCreateInfo rp_info = {};
rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
rp_info.pNext = nullptr;
rp_info.attachmentCount = static_cast<uint32_t>(renderPassAttachments.size());
rp_info.pAttachments = renderPassAttachments.data();
rp_info.subpassCount = 1;
rp_info.pSubpasses = &subpass;
rp_info.dependencyCount = static_cast<uint32_t>(dependencies.size());
rp_info.pDependencies = dependencies.data();
if (vkCreateRenderPass(m_vk_logical_device, &rp_info, nullptr, &m_renderPass) != VK_SUCCESS)
{
throw std::runtime_error("failed to create render pass!");
}
}