From 0e80b3b527c594274e83a4337eaa3e293c81544e Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 28 Jun 2023 11:57:22 +0200 Subject: [PATCH] rhi: vulkan: Include multiViewCount in renderpass compatibility Change-Id: I3185ce27c52c138053fee4805eccbe3575b9433a Reviewed-by: Andy Nichols --- src/gui/rhi/qrhivulkan.cpp | 20 +++++++---- src/gui/rhi/qrhivulkan_p.h | 2 ++ tests/auto/gui/rhi/qrhi/tst_qrhi.cpp | 53 ++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 7 deletions(-) diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 8f40ac192d..0067425edd 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -1285,6 +1285,7 @@ bool QRhiVulkan::createDefaultRenderPass(QVkRenderPassDescriptor *rpD, bool hasD rpD->colorRefs.append({ 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }); rpD->hasDepthStencil = hasDepthStencil; + rpD->multiViewCount = 0; if (hasDepthStencil) { // clear on load + no store + lazy alloc + transient image should play @@ -1397,6 +1398,7 @@ bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD, } } Q_ASSERT(multiViewCount == 0 || multiViewCount >= 2); + rpD->multiViewCount = uint32_t(multiViewCount); rpD->hasDepthStencil = depthStencilBuffer || depthTexture; if (rpD->hasDepthStencil) { @@ -6504,6 +6506,8 @@ bool QVkRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other return false; if (hasDepthStencil != o->hasDepthStencil) return false; + if (multiViewCount != o->multiViewCount) + return false; for (int i = 0, ie = colorRefs.size(); i != ie; ++i) { const uint32_t attIdx = colorRefs[i].attachment; @@ -6543,6 +6547,7 @@ void QVkRenderPassDescriptor::updateSerializedFormat() *p++ = colorRefs.size(); *p++ = resolveRefs.size(); *p++ = hasDepthStencil; + *p++ = multiViewCount; auto serializeAttachmentData = [this, &p](uint32_t attIdx) { const bool used = attIdx != VK_ATTACHMENT_UNUSED; @@ -6586,6 +6591,7 @@ QRhiRenderPassDescriptor *QVkRenderPassDescriptor::newCompatibleRenderPassDescri rpD->resolveRefs = resolveRefs; rpD->subpassDeps = subpassDeps; rpD->hasDepthStencil = hasDepthStencil; + rpD->multiViewCount = multiViewCount; rpD->dsRef = dsRef; VkRenderPassCreateInfo rpInfo; @@ -6723,7 +6729,7 @@ bool QVkTextureRenderTarget::create() QRHI_RES_RHI(QRhiVulkan); QVarLengthArray views; - uint32_t multiViewCount = 0; + d.multiViewCount = 0; d.colorAttCount = 0; int attIndex = 0; @@ -6736,8 +6742,8 @@ bool QVkTextureRenderTarget::create() Q_ASSERT(texD->flags().testFlag(QRhiTexture::RenderTarget)); const bool is1D = texD->flags().testFlag(QRhiTexture::OneDimensional); const bool isMultiView = it->multiViewCount() >= 2; - if (isMultiView && multiViewCount == 0) - multiViewCount = uint32_t(it->multiViewCount()); + if (isMultiView && d.multiViewCount == 0) + d.multiViewCount = it->multiViewCount(); VkImageViewCreateInfo viewInfo = {}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewInfo.image = texD->image; @@ -6798,7 +6804,7 @@ bool QVkTextureRenderTarget::create() d.resolveAttCount = 0; attIndex = 0; - Q_ASSERT(multiViewCount == 0 || multiViewCount >= 2); + Q_ASSERT(d.multiViewCount == 0 || d.multiViewCount >= 2); for (auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) { if (it->resolveTexture()) { QVkTexture *resTexD = QRHI_RES(QVkTexture, it->resolveTexture()); @@ -6808,8 +6814,8 @@ bool QVkTextureRenderTarget::create() VkImageViewCreateInfo viewInfo = {}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewInfo.image = resTexD->image; - viewInfo.viewType = multiViewCount ? VK_IMAGE_VIEW_TYPE_2D_ARRAY - : VK_IMAGE_VIEW_TYPE_2D; + viewInfo.viewType = d.multiViewCount ? VK_IMAGE_VIEW_TYPE_2D_ARRAY + : VK_IMAGE_VIEW_TYPE_2D; viewInfo.format = resTexD->vkformat; viewInfo.components.r = VK_COMPONENT_SWIZZLE_R; viewInfo.components.g = VK_COMPONENT_SWIZZLE_G; @@ -6819,7 +6825,7 @@ bool QVkTextureRenderTarget::create() viewInfo.subresourceRange.baseMipLevel = uint32_t(it->resolveLevel()); viewInfo.subresourceRange.levelCount = 1; viewInfo.subresourceRange.baseArrayLayer = uint32_t(it->resolveLayer()); - viewInfo.subresourceRange.layerCount = qMax(1u, multiViewCount); + viewInfo.subresourceRange.layerCount = qMax(1, d.multiViewCount); VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &resrtv[attIndex]); if (err != VK_SUCCESS) { qWarning("Failed to create render target resolve image view: %d", err); diff --git a/src/gui/rhi/qrhivulkan_p.h b/src/gui/rhi/qrhivulkan_p.h index d7671fb49b..02af3d90dc 100644 --- a/src/gui/rhi/qrhivulkan_p.h +++ b/src/gui/rhi/qrhivulkan_p.h @@ -162,6 +162,7 @@ struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor QVarLengthArray resolveRefs; QVarLengthArray subpassDeps; bool hasDepthStencil = false; + uint32_t multiViewCount = 0; VkAttachmentReference dsRef; QVector serializedFormatData; QRhiVulkanRenderPassNativeHandles nativeHandlesStruct; @@ -178,6 +179,7 @@ struct QVkRenderTargetData int colorAttCount = 0; int dsAttCount = 0; int resolveAttCount = 0; + int multiViewCount = 0; QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList; static const int MAX_COLOR_ATTACHMENTS = 8; }; diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp index 942ee06fe4..914bc0ec7c 100644 --- a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp +++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp @@ -4582,6 +4582,59 @@ void tst_QRhi::renderPassDescriptorCompatibility() } else { qDebug("Skipping texture format dependent tests"); } + + if (rhi->isFeatureSupported(QRhi::MultiView)) { + { + QScopedPointer texArr(rhi->newTextureArray(QRhiTexture::RGBA8, 2, QSize(512, 512), 1, QRhiTexture::RenderTarget)); + QVERIFY(texArr->create()); + QRhiColorAttachment multiViewAtt(texArr.data()); + multiViewAtt.setMultiViewCount(2); + QRhiTextureRenderTargetDescription rtDesc(multiViewAtt); + QScopedPointer rt(rhi->newTextureRenderTarget(rtDesc)); + QScopedPointer rpDesc(rt->newCompatibleRenderPassDescriptor()); + rt->setRenderPassDescriptor(rpDesc.data()); + QVERIFY(rt->create()); + + QScopedPointer rt2(rhi->newTextureRenderTarget(rtDesc)); + QScopedPointer rpDesc2(rt2->newCompatibleRenderPassDescriptor()); + rt2->setRenderPassDescriptor(rpDesc2.data()); + QVERIFY(rt2->create()); + + QVERIFY(rpDesc->isCompatible(rpDesc2.data())); + QVERIFY(rpDesc2->isCompatible(rpDesc.data())); + QCOMPARE(rpDesc->serializedFormat(), rpDesc2->serializedFormat()); + + QScopedPointer rpDescClone(rpDesc->newCompatibleRenderPassDescriptor()); + QVERIFY(rpDesc->isCompatible(rpDescClone.data())); + QVERIFY(rpDesc2->isCompatible(rpDescClone.data())); + QCOMPARE(rpDesc->serializedFormat(), rpDescClone->serializedFormat()); + + // With Vulkan the multiViewCount really matters since it is baked + // in to underlying native object (VkRenderPass). Verify that the + // compatibility check fails when the view count differs. Other + // backends cannot do this test since they will likely report the + // rps being compatible regardless. + if (impl == QRhi::Vulkan) { + QRhiColorAttachment nonMultiViewAtt(texArr.data()); + QRhiTextureRenderTargetDescription rtDesc3(nonMultiViewAtt); + QScopedPointer rt3(rhi->newTextureRenderTarget(rtDesc3)); + QScopedPointer rpDesc3(rt3->newCompatibleRenderPassDescriptor()); + rt3->setRenderPassDescriptor(rpDesc3.data()); + QVERIFY(rt3->create()); + + QVERIFY(!rpDesc->isCompatible(rpDesc3.data())); + QVERIFY(!rpDesc2->isCompatible(rpDesc3.data())); + QVERIFY(rpDesc->serializedFormat() != rpDesc3->serializedFormat()); + + QScopedPointer rpDesc3Clone(rpDesc3->newCompatibleRenderPassDescriptor()); + QVERIFY(!rpDesc->isCompatible(rpDesc3Clone.data())); + QVERIFY(!rpDesc2->isCompatible(rpDesc3Clone.data())); + QVERIFY(rpDesc->serializedFormat() != rpDesc3Clone->serializedFormat()); + } + } + } else { + qDebug("Skipping multiview dependent tests"); + } } void tst_QRhi::renderPassDescriptorClone_data()