rhi: vk: Prevent WAW hazard reported from sync validation with offscreen rt

...when a QVkRenderBuffer is used as depth-stencil (i.e. a "throwaway"
depth-stencil buffer that is a lazily allocated / transient VkImage
under the hood). Such a resource is not tracked by the
QRhiPassResourceTracker, so do an explicit barrier in beginPass
instead of having it generated by the tracker.

Fixes: QTBUG-89764
Change-Id: Ice794f44342175f712ea56f450270cbb8929f516
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
Laszlo Agocs 2021-01-04 16:58:38 +01:00
parent 5f8efb2597
commit f0d1a50333
2 changed files with 45 additions and 4 deletions

View File

@ -1340,8 +1340,8 @@ bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
rpInfo.subpassCount = 1;
rpInfo.pSubpasses = &subpassDesc;
// don't yet know the correct initial/final access and stage stuff for the
// implicit deps at this point, so leave it to the resource tracking to
// generate barriers
// implicit deps at this point, so leave it to the resource tracking and
// activateTextureRenderTarget() to generate barriers
VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, &rpD->rp);
if (err != VK_SUCCESS) {
@ -2147,8 +2147,17 @@ void QRhiVulkan::activateTextureRenderTarget(QVkCommandBuffer *cbD, QVkTextureRe
resolveTexD->lastActiveFrameSlot = currentFrameSlot;
}
}
if (rtD->m_desc.depthStencilBuffer())
QRHI_RES(QVkRenderBuffer, rtD->m_desc.depthStencilBuffer())->lastActiveFrameSlot = currentFrameSlot;
if (rtD->m_desc.depthStencilBuffer()) {
QVkRenderBuffer *rbD = QRHI_RES(QVkRenderBuffer, rtD->m_desc.depthStencilBuffer());
Q_ASSERT(rbD->m_type == QRhiRenderBuffer::DepthStencil);
// We specify no explicit VkSubpassDependency for an offscreen render
// target, meaning we need an explicit barrier for the depth-stencil
// buffer to avoid a write-after-write hazard (as the implicit one is
// not sufficient). Textures are taken care of by the resource tracking
// but that excludes the (content-wise) throwaway depth-stencil buffer.
depthStencilExplicitBarrier(cbD, rbD);
rbD->lastActiveFrameSlot = currentFrameSlot;
}
if (rtD->m_desc.depthTexture()) {
QVkTexture *depthTexD = QRHI_RES(QVkTexture, rtD->m_desc.depthTexture());
trackedRegisterTexture(&passResTracker, depthTexD,
@ -2804,6 +2813,37 @@ void QRhiVulkan::trackedImageBarrier(QVkCommandBuffer *cbD, QVkTexture *texD,
s.stage = stage;
}
void QRhiVulkan::depthStencilExplicitBarrier(QVkCommandBuffer *cbD, QVkRenderBuffer *rbD)
{
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::NoPass);
VkImageMemoryBarrier barrier;
memset(&barrier, 0, sizeof(barrier));
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
barrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
barrier.image = rbD->image;
const VkPipelineStageFlags stages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
QVkCommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QVkCommandBuffer::Command::ImageBarrier;
cmd.args.imageBarrier.srcStageMask = stages;
cmd.args.imageBarrier.dstStageMask = stages;
cmd.args.imageBarrier.count = 1;
cmd.args.imageBarrier.index = cbD->pools.imageBarrier.count();
cbD->pools.imageBarrier.append(barrier);
}
void QRhiVulkan::subresourceBarrier(QVkCommandBuffer *cbD, VkImage image,
VkImageLayout oldLayout, VkImageLayout newLayout,
VkAccessFlags srcAccess, VkAccessFlags dstAccess,

View File

@ -817,6 +817,7 @@ public:
VkAccessFlags access, VkPipelineStageFlags stage);
void trackedImageBarrier(QVkCommandBuffer *cbD, QVkTexture *texD,
VkImageLayout layout, VkAccessFlags access, VkPipelineStageFlags stage);
void depthStencilExplicitBarrier(QVkCommandBuffer *cbD, QVkRenderBuffer *rbD);
void subresourceBarrier(QVkCommandBuffer *cbD, VkImage image,
VkImageLayout oldLayout, VkImageLayout newLayout,
VkAccessFlags srcAccess, VkAccessFlags dstAccess,