ToxiCore ToxiCore - 1 month ago 17
C++ Question

How to use a DepthBuffer as InputAttachment in Vulkan?

I have some trouble implementing my DepthBuffer as InputAttachment of a secondary subpass. I want to use the depth information of my first subpass. How can I archieve this? It seems that my current code gives me just an empty buffer..

My depth buffer is setup as follows:

create_info.imageType = VK_IMAGE_TYPE_2D;
create_info.format = VK_FORMAT_D32_SFLOAT;
create_info.mipLevels = 1;
create_info.arrayLayers = 1;
create_info.samples = VK_SAMPLE_COUNT_1_BIT;
create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
create_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;


I then use the following layout transition:

VkImageMemoryBarrier layout_transition_barrier{};
{
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
barrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image;
barrier.subresourceRange = { VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, 1 };
}


This works totally fine for rendering..
The VkAttachmentReference I use has the layout
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
and I use it as an
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
.

In my fragment shader I then use
layout (set = 0, binding = 1) uniform sampler2D inputDepth;
to access it, however without any success.. the information I get is only zeros for any color channel.




Further I use this dependency:

VkSubpassDependency dependency{};
{
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dependency.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
}


and this descritpion

static VkAttachmentDescription depth_input_attachment{};
{
depth_input_attachment.format = VK_FORMAT_D32_SFLOAT;
depth_input_attachment.samples = VK_SAMPLE_COUNT_1_BIT;
depth_input_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
depth_input_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depth_input_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
depth_input_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depth_input_attachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
depth_input_attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
}

Answer

If you're doing subpasses (and not multiple render passes) and want to use your depth buffer as an inputAttachment and want to use an attachment as an input for a second subpass,

layout (set = 0, binding = 1) uniform sampler2D inputDepth

is not the correct syntax to sample from that in your shader.

Sampling from an input attachment requires a special syntax:

layout (input_attachment_index = n, binding = m) uniform subpassInput inputDepth;

This also requires a descriptor of type VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT instead of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER. Note that the actual descriptor for input attachments does not require a sampler.

If you're instead trying to sample your depth attachment in a second render pass, make sure that the storeOp of the attachment description is set to store.