Vulkan Depth buffer is either 0 or 1. Never inbetween

1k views Asked by At

I am having a problem with the depth buffer/test not working. When I check with RenderDoc I see that the depth buffer is always just 1 where an object has been rendered: depth_example. I am expecting a sort of smooth gradient between black and white.

Edit: GIF of problem

I have been trying to fix this issue since yesterday and have tried numerous things, such as: changing pipeline settings, changing renderpass settings, checking framebuffer & depth texture setup and even changing the projection/view matrices.

The validation layers have not been throwing out any errors and I have been using RenderDoc to test/debug.

I have saved and uploaded a RenderDoc capture of the application in the state it was in before I tried making changes if anyone would like to look: RenderDoc Capture

I will post some of the code I think is relevant below, but before that I should mention that I am using GLM to create the rendering matrics with the GLM_FORCE_DEPTH_ZERO_TO_ONE + GLM_FORCE_LEFT_HANDED defines.

rasterizerState.depthClampEnable = false;
rasterizerState.rasterizerDiscardEnable = false;
rasterizerState.polygonMode = vk::PolygonMode::eFill;
rasterizerState.lineWidth = 1.0f;
rasterizerState.cullMode = vk::CullModeFlagBits::eBack;
rasterizerState.frontFace = vk::FrontFace::eCounterClockwise;
rasterizerState.depthBiasEnable = false;

depthStencilState.depthTestEnable = true;
depthStencilState.depthWriteEnable = true;
depthStencilState.depthCompareOp = vk::CompareOp::eLess;
depthStencilState.depthBoundsTestEnable = false;
depthStencilState.stencilTestEnable = false;
vk::ImageCreateInfo imageInfo{};
imageInfo.imageType = vk::ImageType::e2D;
imageInfo.format = depthFormat;
imageInfo.extent.width = m_swapchainWidth;
imageInfo.extent.height = m_swapchainHeight;
imageInfo.extent.depth = 1.0f;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.samples = vk::SampleCountFlagBits::e1;
imageInfo.tiling = vk::ImageTiling::eOptimal;
imageInfo.usage = vk::ImageUsageFlagBits::eDepthStencilAttachment | vk::ImageUsageFlagBits::eTransferSrc;

allocator.Allocate(imageInfo, VMA_MEMORY_USAGE_GPU_ONLY, &m_depthStencil.Image, &m_depthStencil.Allocation);

vk::ImageViewCreateInfo imageViewInfo{};
imageViewInfo.viewType = vk::ImageViewType::e2D;
imageViewInfo.image = m_depthStencil.Image;
imageViewInfo.format = depthFormat;
imageViewInfo.subresourceRange.baseMipLevel = 0;
imageViewInfo.subresourceRange.levelCount = 1;
imageViewInfo.subresourceRange.baseArrayLayer = 0;
imageViewInfo.subresourceRange.layerCount = 1;
imageViewInfo.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eDepth;
if (depthFormat >= vk::Format::eD16UnormS8Uint)
{
    imageViewInfo.subresourceRange.aspectMask |= vk::ImageAspectFlagBits::eStencil;
}
vk::AttachmentDescription depthAttachment{};
depthAttachment.format = m_context->GetDepthFormat();
depthAttachment.samples = vk::SampleCountFlagBits::e1;
depthAttachment.loadOp = vk::AttachmentLoadOp::eClear;
depthAttachment.storeOp = vk::AttachmentStoreOp::eDontCare;
depthAttachment.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
depthAttachment.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
depthAttachment.initialLayout = vk::ImageLayout::eUndefined;
depthAttachment.finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;

vk::AttachmentReference depthAttachmentRef{};
depthAttachmentRef.attachment = 1;
depthAttachmentRef.layout = vk::ImageLayout::eDepthStencilAttachmentOptimal;

vk::SubpassDependency dependency{};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
dependency.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
dependency.srcAccessMask = {};
dependency.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;
renderPassInfo.dependencyCount = 1;
renderPassInfo.pDependencies = &dependency;
auto TransformComponent::GetTransform() const -> glm::mat4
{
    auto rot = glm::eulerAngleXYZ(Rotation.x, Rotation.y, Rotation.z);
    return glm::translate(glm::mat4(1.0f), Position) * rot * glm::scale(glm::mat4(1.0f), Scale);
}
auto TransformComponent::GetView() const -> glm::mat4
{
    auto transform = glm::translate(glm::mat4(1.0f), Position);
    transform = glm::rotate(transform, glm::radians(Rotation.y), { 0, 1.0f, 0 });
    transform = glm::rotate(transform, glm::radians(Rotation.x), { 1.0f, 0, 0 });
    return glm::inverse(transform);
}
auto CameraComponent::GetProj() const -> glm::mat4
{
    auto windowSize = Application::Get()->GetWindow()->GetSize();
    auto proj = glm::perspective(glm::radians(FieldOfView), windowSize.x / (float)windowSize.y, Near, Far);
    proj[1][1] *= -1.0f;
    return proj;
}
2

There are 2 answers

0
jdtec On

I also had this problem and setting the viewport minDepth & maxDepth as suggested by @pezcode in a comment above fixes it.

0
Ricky Casavecchia On

I had a problem with the exact same symptoms but my issue tuned out to be the near & far parameters for my perspective matrix. I had this which was causing the issue...

projection_ = glm::perspective(glm::radians(70.0f), static_cast<float>(windowWidth_) / static_cast<float>(windowHeight_), 0.0f, 1.0f);

Fixed it with this...

projection_ = glm::perspective(glm::radians(70.0f), static_cast<float>(windowWidth_) / static_cast<float>(windowHeight_), 0.1f, 10.0f);

I'm guessing the 0.0f near plane parameter was the issue. Maybe a divide by zero or something, still need to look into it more to better understand but the issue is fixed.