summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2021-01-04 16:58:38 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2021-01-06 16:18:20 +0100
commitf0d1a50333f3945369077a48ba7f2bdf228276cc (patch)
tree734e66599deb3b384903a03136c8fe4e03a09cb6 /src/gui/rhi
parent5f8efb259774040303f37d00b6307afd22857af2 (diff)
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>
Diffstat (limited to 'src/gui/rhi')
-rw-r--r--src/gui/rhi/qrhivulkan.cpp48
-rw-r--r--src/gui/rhi/qrhivulkan_p_p.h1
2 files changed, 45 insertions, 4 deletions
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index 394a578e9f..aa287ce1b9 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -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,
diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h
index 7fdb108da4..31edcc6924 100644
--- a/src/gui/rhi/qrhivulkan_p_p.h
+++ b/src/gui/rhi/qrhivulkan_p_p.h
@@ -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,