Vulkan 深度测试不适用于动态渲染并延迟

问题描述 投票:0回答:1

我的设置是这样的:

  1. 将小场景(即单个 3D 模型)渲染到具有 1 个颜色和 1 个深度附件的帧缓冲区中。
  2. 将颜色缓冲区渲染为全屏四边形

大多数在线代码示例都使用渲染通道和子通道依赖项,但我使用的是动态渲染扩展,因此

VkRenderingInfo
VkRenderingAttachmentInfo
vkCmdBeginRendering
。该设置与使用交换链和交换链深度缓冲区的动态渲染相同,我已经工作得很好。所以我正在考虑扩展这个系统并尝试延迟。然而,似乎没有执行深度测试,因为每个片段都通过了深度测试(通过可视化深度缓冲区和来自 Renderdoc 进行检查时可以清楚地看到这一点)。

这是我每帧的命令缓冲区记录:

// 1) begin recording on the command buffer
// 2) begin dynamic rendering on the framebuffer
// 3) bind main pipeline and set dynamic states
// 4) bind and render model, including descriptor sets and push constants
// 5) end dynamic rendering on the framebuffer

// 6) begin dynamic rendering on the swapchain
// 7) bind the quad pipeline
// 8) bind framebuffer color attachment for reading (descriptor set)
// 9) draw fullscreen quad
// 10) end dynamic rendering on the swapchain
// 11) end recording on the command buffer

步骤 6-11 运行良好(使用 Renderdoc 检查)。另外,由于问题是深度测试无法正常工作,我预计问题是:

  1. 主管道如何配置;或
  2. 如何为帧缓冲区配置动态渲染

管道已按应有的方式配置 - 设置是从启用深度缓冲并工作的其他项目复制/粘贴的。因此,这就是步骤 2 中发生的情况:

// color attachment pipeline barrier, omitted here.
// depth attachment pipeline barrier, shown below:
VkImageMemoryBarrier depthBarrier{};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.pNext = nullptr;
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 = graphicsQueueFamilyIndex;
barrier.dstQueueFamilyIndex = graphicsQueueFamilyIndex;
barrier.image = framebuffer->depthAttachment.image;
barrier.subresourceRange.aspectMask
    = VK_IMAGE_ASPECT_DEPTH_BIT
    | VK_IMAGE_ASPECT_STENCIL_BIT;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;

const VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
const VkPipelineStageFlags dstStageMask
    = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
    | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;

vkCmdPipelineBarrier(
    cmdBuf, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1, &depthBarrier);

VkRenderingAttachmentInfo colorInfo{};
colorInfo.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
colorInfo.pNext = nullptr;
colorInfo.imageView = framebuffer->colorAttachment.imageView;
colorInfo.imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL;
colorInfo.resolveMode = VK_RESOLVE_MODE_NONE;
colorInfo.resolveImageView = VK_NULL_HANDLE;
colorInfo.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorInfo.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorInfo.clearValue = { .color = { .float32 = {0.1f, 0.1f, 0.1f, 1.0f} } }

VkRenderingAttachmentInfo depthInfo{};
depthInfo.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
depthInfo.pNext = nullptr;
depthInfo.imageView = framebuffer->depthAttachment.imageView;
depthInfo.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
depthInfo.resolveMode = VK_RESOLVE_MODE_NONE;
depthInfo.resolveImageView = VK_NULL_HANDLE;
depthInfo.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depthInfo.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
depthInfo.clearValue = { .depthStencil = { 1.0f, 0 } };

VkRenderingInfo renderingInfo{};
renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
renderingInfo.pNext = nullptr;
renderingInfo.flags = 0;
renderingInfo.renderArea = { 0U, 0U, framebuffer->width, framebuffer->height };
renderingInfo.layerCount = 1;
renderingInfo.viewMask = 0;
renderingInfo.colorAttachmentCount = 1;
renderingInfo.pColorAttachments = &colorInfo;
renderingInfo.pDepthAttachment = &depthInfo;
renderingInfo.pStencilAttachment = nullptr;

vkCmdBeginRendering(cmdBuf, &renderingInfo);

步骤 3 和 4 之前已经测试过,应该可以正常工作。步骤 5 结束帧缓冲区上的动态渲染,它仅将颜色附件转换为

VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
,以便可以在全屏四元着色器中对其进行采样。我在这里没有收到任何验证消息,并且我可以在屏幕上看到最终图像 - 只是没有进行适当的深度测试。


我可能做错了什么?我希望我正确地提出了问题,否则如果我错过了重要的一步,请告诉我。

c++ vulkan depth-buffer depth-testing
1个回答
0
投票

事实证明我的问题出乎我的意料 - 我不小心忘记在命令缓冲区记录期间设置

vkCmdSetViewport
的深度范围:

VkViewport viewport{};
viewport.x = 0.0f; viewport.y = 0.0f; // upper-left corner
viewport.width = static_cast<float>(size.x);
viewport.height = static_cast<float>(size.y);
viewport.minDepth = depthRange.x; // <-- this should probably be 0
viewport.maxDepth = depthRange.y; // <-- this should probably be 1

vkCmdSetViewport(cmdBuf, 0, 1, &viewport);

即使使用深度缓冲区,启用深度测试+写入,纠正障碍,视口变换也会强制所有深度值变为

depthRange
- 我不确定我在这里的理解是否正确..

对于任何想知道的人来说,我设置的障碍效果很好。

发布 Vulkan 问题相当困难,因为可能有 100 行内容与找出错误所在相关。如果这对其他人有帮助,我很高兴!

© www.soinside.com 2019 - 2024. All rights reserved.