我的设置是这样的:
大多数在线代码示例都使用渲染通道和子通道依赖项,但我使用的是动态渲染扩展,因此
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 检查)。另外,由于问题是深度测试无法正常工作,我预计问题是:
管道已按应有的方式配置 - 设置是从启用深度缓冲并工作的其他项目复制/粘贴的。因此,这就是步骤 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
,以便可以在全屏四元着色器中对其进行采样。我在这里没有收到任何验证消息,并且我可以在屏幕上看到最终图像 - 只是没有进行适当的深度测试。
我可能做错了什么?我希望我正确地提出了问题,否则如果我错过了重要的一步,请告诉我。
事实证明我的问题出乎我的意料 - 我不小心忘记在命令缓冲区记录期间设置
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 行内容与找出错误所在相关。如果这对其他人有帮助,我很高兴!