diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2021-03-16 16:33:27 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2021-03-19 10:46:23 +0000 |
commit | 19384f2e8f50bad0a0775f7b2e10aff3372bcbb5 (patch) | |
tree | dbf1589023f98726177a7a92dcc20a46778589ff | |
parent | 969337bcfd6af6d91b988e4b412703274a0b5877 (diff) |
rhi: Make it possible to clone a QRhiRenderPassDescriptor
Pick-to: 6.1
Task-number: QTBUG-91888
Change-Id: Ib6d2e639e6c24f3e9a733c6563dc8a6d6da47719
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r-- | src/gui/rhi/qrhi.cpp | 40 | ||||
-rw-r--r-- | src/gui/rhi/qrhi_p.h | 2 | ||||
-rw-r--r-- | src/gui/rhi/qrhid3d11.cpp | 5 | ||||
-rw-r--r-- | src/gui/rhi/qrhid3d11_p_p.h | 1 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2.cpp | 5 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2_p_p.h | 1 | ||||
-rw-r--r-- | src/gui/rhi/qrhimetal.mm | 10 | ||||
-rw-r--r-- | src/gui/rhi/qrhimetal_p_p.h | 1 | ||||
-rw-r--r-- | src/gui/rhi/qrhinull.cpp | 5 | ||||
-rw-r--r-- | src/gui/rhi/qrhinull_p_p.h | 1 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan.cpp | 137 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan_p_p.h | 2 | ||||
-rw-r--r-- | tests/auto/gui/rhi/qrhi/tst_qrhi.cpp | 45 |
13 files changed, 191 insertions, 64 deletions
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index 8d3c56da53..db85730040 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -158,10 +158,12 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general") native resources. That is only done when calling the \c create() function of a subclass, for example, QRhiBuffer::create() or QRhiTexture::create(). - \li The exception is - QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() and - QRhiSwapChain::newCompatibleRenderPassDescriptor(). There is no \c create() - operation for these and the returned object is immediately active. + \li The exceptions are + QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor(), + QRhiSwapChain::newCompatibleRenderPassDescriptor(), and + QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor(). There is no + \c create() operation for these and the returned object is immediately + active. \li The resource objects themselves are treated as immutable: once a resource has create() called, changing any parameters via the setters, such as, @@ -2605,7 +2607,7 @@ QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const } /*! - \fn bool QRhiRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const; + \fn bool QRhiRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const \return true if the \a other QRhiRenderPassDescriptor is compatible with this one, meaning \c this and \a other can be used interchangebly in @@ -2620,6 +2622,34 @@ QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const allowing a different QRhiRenderPassDescriptor and QRhiShaderResourceBindings to be used in combination with the pipeline, as long as they are compatible. + + The exact details of compatibility depend on the underlying graphics API. + Two renderpass descriptors + \l{QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()}{created} + from the same QRhiTextureRenderTarget are always compatible. + + \sa newCompatibleRenderPassDescriptor() + */ + +/*! + \fn QRhiRenderPassDescriptor *QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor() const + + \return a new QRhiRenderPassDescriptor that is + \l{isCompatible()}{compatible} with this one. + + This function allows cloning a QRhiRenderPassDescriptor. The returned + object is ready to be used, and the ownership is transferred to the caller. + Cloning a QRhiRenderPassDescriptor object can become useful in situations + where the object is stored in data structures related to graphics pipelines + (in order to allow creating new pipelines which in turn requires a + renderpass descriptor object), and the lifetime of the renderpass + descriptor created from a render target may be shorter than the pipelines. + (for example, because the engine manages and destroys renderpasses together + with the textures and render targets it was created from) In such a + situation, it can be beneficial to store a cloned version in the data + structures, and thus transferring ownership as well. + + \sa isCompatible() */ /*! diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index f3255eca5b..e0afabc73a 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -951,6 +951,8 @@ public: virtual bool isCompatible(const QRhiRenderPassDescriptor *other) const = 0; virtual const QRhiNativeHandles *nativeHandles(); + virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const = 0; + protected: QRhiRenderPassDescriptor(QRhiImplementation *rhi); }; diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index fef911c22a..3e0ba0820b 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -3281,6 +3281,11 @@ bool QD3D11RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *ot return true; } +QRhiRenderPassDescriptor *QD3D11RenderPassDescriptor::newCompatibleRenderPassDescriptor() const +{ + return new QD3D11RenderPassDescriptor(m_rhi); +} + QD3D11ReferenceRenderTarget::QD3D11ReferenceRenderTarget(QRhiImplementation *rhi) : QRhiRenderTarget(rhi), d(rhi) diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h index 5eb866119f..82cbe5114c 100644 --- a/src/gui/rhi/qrhid3d11_p_p.h +++ b/src/gui/rhi/qrhid3d11_p_p.h @@ -143,6 +143,7 @@ struct QD3D11RenderPassDescriptor : public QRhiRenderPassDescriptor ~QD3D11RenderPassDescriptor(); void destroy() override; bool isCompatible(const QRhiRenderPassDescriptor *other) const override; + QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override; }; struct QD3D11RenderTargetData diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index 1556e45fbf..e3895897e9 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -4549,6 +4549,11 @@ bool QGles2RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *ot return true; } +QRhiRenderPassDescriptor *QGles2RenderPassDescriptor::newCompatibleRenderPassDescriptor() const +{ + return new QGles2RenderPassDescriptor(m_rhi); +} + QGles2ReferenceRenderTarget::QGles2ReferenceRenderTarget(QRhiImplementation *rhi) : QRhiRenderTarget(rhi), d(rhi) diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h index 98f2f98b8a..d30fd89545 100644 --- a/src/gui/rhi/qrhigles2_p_p.h +++ b/src/gui/rhi/qrhigles2_p_p.h @@ -193,6 +193,7 @@ struct QGles2RenderPassDescriptor : public QRhiRenderPassDescriptor ~QGles2RenderPassDescriptor(); void destroy() override; bool isCompatible(const QRhiRenderPassDescriptor *other) const override; + QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override; }; struct QGles2RenderTargetData diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index a736dd511e..ddbd0ea740 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -2900,6 +2900,16 @@ bool QMetalRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *ot return true; } +QRhiRenderPassDescriptor *QMetalRenderPassDescriptor::newCompatibleRenderPassDescriptor() const +{ + QMetalRenderPassDescriptor *rp = new QMetalRenderPassDescriptor(m_rhi); + rp->colorAttachmentCount = colorAttachmentCount; + rp->hasDepthStencil = hasDepthStencil; + memcpy(rp->colorFormat, colorFormat, sizeof(colorFormat)); + rp->dsFormat = dsFormat; + return rp; +} + QMetalReferenceRenderTarget::QMetalReferenceRenderTarget(QRhiImplementation *rhi) : QRhiRenderTarget(rhi), d(new QMetalRenderTargetData) diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h index 4971ecc18c..c8ba5940a8 100644 --- a/src/gui/rhi/qrhimetal_p_p.h +++ b/src/gui/rhi/qrhimetal_p_p.h @@ -145,6 +145,7 @@ struct QMetalRenderPassDescriptor : public QRhiRenderPassDescriptor ~QMetalRenderPassDescriptor(); void destroy() override; bool isCompatible(const QRhiRenderPassDescriptor *other) const override; + QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override; // there is no MTLRenderPassDescriptor here as one will be created for each pass in beginPass() diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp index 32ba27fcf8..29f3bab8b0 100644 --- a/src/gui/rhi/qrhinull.cpp +++ b/src/gui/rhi/qrhinull.cpp @@ -733,6 +733,11 @@ bool QNullRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *oth return true; } +QRhiRenderPassDescriptor *QNullRenderPassDescriptor::newCompatibleRenderPassDescriptor() const +{ + return new QNullRenderPassDescriptor(m_rhi); +} + QNullReferenceRenderTarget::QNullReferenceRenderTarget(QRhiImplementation *rhi) : QRhiRenderTarget(rhi), d(rhi) diff --git a/src/gui/rhi/qrhinull_p_p.h b/src/gui/rhi/qrhinull_p_p.h index 273aee9c3e..d296c0bbf0 100644 --- a/src/gui/rhi/qrhinull_p_p.h +++ b/src/gui/rhi/qrhinull_p_p.h @@ -105,6 +105,7 @@ struct QNullRenderPassDescriptor : public QRhiRenderPassDescriptor ~QNullRenderPassDescriptor(); void destroy() override; bool isCompatible(const QRhiRenderPassDescriptor *other) const override; + QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override; }; struct QNullRenderTargetData diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 34b81671ca..3d5048df1c 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -1174,6 +1174,28 @@ VkFormat QRhiVulkan::optimalDepthStencilFormat() return optimalDsFormat; } +static void fillRenderPassCreateInfo(VkRenderPassCreateInfo *rpInfo, + VkSubpassDescription *subpassDesc, + QVkRenderPassDescriptor *rpD) +{ + memset(subpassDesc, 0, sizeof(VkSubpassDescription)); + subpassDesc->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpassDesc->colorAttachmentCount = uint32_t(rpD->colorRefs.count()); + Q_ASSERT(rpD->colorRefs.count() == rpD->resolveRefs.count()); + subpassDesc->pColorAttachments = !rpD->colorRefs.isEmpty() ? rpD->colorRefs.constData() : nullptr; + subpassDesc->pDepthStencilAttachment = rpD->hasDepthStencil ? &rpD->dsRef : nullptr; + subpassDesc->pResolveAttachments = !rpD->resolveRefs.isEmpty() ? rpD->resolveRefs.constData() : nullptr; + + memset(rpInfo, 0, sizeof(VkRenderPassCreateInfo)); + rpInfo->sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + rpInfo->attachmentCount = uint32_t(rpD->attDescs.count()); + rpInfo->pAttachments = rpD->attDescs.constData(); + rpInfo->subpassCount = 1; + rpInfo->pSubpasses = subpassDesc; + rpInfo->dependencyCount = uint32_t(rpD->subpassDeps.count()); + rpInfo->pDependencies = !rpD->subpassDeps.isEmpty() ? rpD->subpassDeps.constData() : nullptr; +} + bool QRhiVulkan::createDefaultRenderPass(QVkRenderPassDescriptor *rpD, bool hasDepthStencil, VkSampleCountFlagBits samples, VkFormat colorFormat) { // attachment list layout is color (1), ds (0-1), resolve (0-1) @@ -1192,6 +1214,8 @@ bool QRhiVulkan::createDefaultRenderPass(QVkRenderPassDescriptor *rpD, bool hasD rpD->colorRefs.append({ 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }); + rpD->hasDepthStencil = hasDepthStencil; + if (hasDepthStencil) { // clear on load + no store + lazy alloc + transient image should play // nicely with tiled GPUs (no physical backing necessary for ds buffer) @@ -1224,53 +1248,33 @@ bool QRhiVulkan::createDefaultRenderPass(QVkRenderPassDescriptor *rpD, bool hasD rpD->resolveRefs.append({ 2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }); } - VkSubpassDescription subpassDesc; - memset(&subpassDesc, 0, sizeof(subpassDesc)); - subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDesc.colorAttachmentCount = 1; - subpassDesc.pColorAttachments = rpD->colorRefs.constData(); - subpassDesc.pDepthStencilAttachment = hasDepthStencil ? &rpD->dsRef : nullptr; - // Replace the first implicit dep (TOP_OF_PIPE / ALL_COMMANDS) with our own. - VkSubpassDependency subpassDeps[2]; - memset(subpassDeps, 0, sizeof(subpassDeps)); - subpassDeps[0].srcSubpass = VK_SUBPASS_EXTERNAL; - subpassDeps[0].dstSubpass = 0; - subpassDeps[0].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - subpassDeps[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - subpassDeps[0].srcAccessMask = 0; - subpassDeps[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + VkSubpassDependency subpassDep; + memset(&subpassDep, 0, sizeof(subpassDep)); + subpassDep.srcSubpass = VK_SUBPASS_EXTERNAL; + subpassDep.dstSubpass = 0; + subpassDep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + subpassDep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + subpassDep.srcAccessMask = 0; + subpassDep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + rpD->subpassDeps.append(subpassDep); if (hasDepthStencil) { - subpassDeps[1].srcSubpass = VK_SUBPASS_EXTERNAL; - subpassDeps[1].dstSubpass = 0; - subpassDeps[1].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT + memset(&subpassDep, 0, sizeof(subpassDep)); + subpassDep.srcSubpass = VK_SUBPASS_EXTERNAL; + subpassDep.dstSubpass = 0; + subpassDep.srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - subpassDeps[1].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT + subpassDep.dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - subpassDeps[1].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - subpassDeps[1].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT + subpassDep.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + subpassDep.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + rpD->subpassDeps.append(subpassDep); } VkRenderPassCreateInfo rpInfo; - memset(&rpInfo, 0, sizeof(rpInfo)); - rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - rpInfo.attachmentCount = 1; - rpInfo.pAttachments = rpD->attDescs.constData(); - rpInfo.subpassCount = 1; - rpInfo.pSubpasses = &subpassDesc; - rpInfo.dependencyCount = 1; - rpInfo.pDependencies = subpassDeps; - - if (hasDepthStencil) { - rpInfo.attachmentCount += 1; - rpInfo.dependencyCount += 1; - } - - if (samples > VK_SAMPLE_COUNT_1_BIT) { - rpInfo.attachmentCount += 1; - subpassDesc.pResolveAttachments = rpD->resolveRefs.constData(); - } + VkSubpassDescription subpassDesc; + fillRenderPassCreateInfo(&rpInfo, &subpassDesc, rpD); VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, &rpD->rp); if (err != VK_SUCCESS) { @@ -1278,8 +1282,6 @@ bool QRhiVulkan::createDefaultRenderPass(QVkRenderPassDescriptor *rpD, bool hasD return false; } - rpD->hasDepthStencil = hasDepthStencil; - return true; } @@ -1377,25 +1379,14 @@ bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD, } } - VkSubpassDescription subpassDesc; - memset(&subpassDesc, 0, sizeof(subpassDesc)); - subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDesc.colorAttachmentCount = uint32_t(rpD->colorRefs.count()); - Q_ASSERT(rpD->colorRefs.count() == rpD->resolveRefs.count()); - subpassDesc.pColorAttachments = !rpD->colorRefs.isEmpty() ? rpD->colorRefs.constData() : nullptr; - subpassDesc.pDepthStencilAttachment = rpD->hasDepthStencil ? &rpD->dsRef : nullptr; - subpassDesc.pResolveAttachments = !rpD->resolveRefs.isEmpty() ? rpD->resolveRefs.constData() : nullptr; + // rpD->subpassDeps stays empty: 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 and activateTextureRenderTarget() to generate + // barriers. VkRenderPassCreateInfo rpInfo; - memset(&rpInfo, 0, sizeof(rpInfo)); - rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - rpInfo.attachmentCount = uint32_t(rpD->attDescs.count()); - rpInfo.pAttachments = rpD->attDescs.constData(); - 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 and - // activateTextureRenderTarget() to generate barriers + VkSubpassDescription subpassDesc; + fillRenderPassCreateInfo(&rpInfo, &subpassDesc, rpD); VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, &rpD->rp); if (err != VK_SUCCESS) { @@ -6149,9 +6140,39 @@ bool QVkRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other return false; } + // subpassDeps is not included + return true; } +QRhiRenderPassDescriptor *QVkRenderPassDescriptor::newCompatibleRenderPassDescriptor() const +{ + QVkRenderPassDescriptor *rpD = new QVkRenderPassDescriptor(m_rhi); + + rpD->ownsRp = true; + rpD->attDescs = attDescs; + rpD->colorRefs = colorRefs; + rpD->resolveRefs = resolveRefs; + rpD->subpassDeps = subpassDeps; + rpD->hasDepthStencil = hasDepthStencil; + rpD->dsRef = dsRef; + + VkRenderPassCreateInfo rpInfo; + VkSubpassDescription subpassDesc; + fillRenderPassCreateInfo(&rpInfo, &subpassDesc, rpD); + + QRHI_RES_RHI(QRhiVulkan); + VkResult err = rhiD->df->vkCreateRenderPass(rhiD->dev, &rpInfo, nullptr, &rpD->rp); + if (err != VK_SUCCESS) { + qWarning("Failed to create renderpass: %d", err); + delete rpD; + return nullptr; + } + + rhiD->registerResource(rpD); + return rpD; +} + const QRhiNativeHandles *QVkRenderPassDescriptor::nativeHandles() { nativeHandlesStruct.renderPass = rp; diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h index f54439b5f2..bb60fca42a 100644 --- a/src/gui/rhi/qrhivulkan_p_p.h +++ b/src/gui/rhi/qrhivulkan_p_p.h @@ -185,6 +185,7 @@ struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor ~QVkRenderPassDescriptor(); void destroy() override; bool isCompatible(const QRhiRenderPassDescriptor *other) const override; + QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override; const QRhiNativeHandles *nativeHandles() override; VkRenderPass rp = VK_NULL_HANDLE; @@ -192,6 +193,7 @@ struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor QVarLengthArray<VkAttachmentDescription, 8> attDescs; QVarLengthArray<VkAttachmentReference, 8> colorRefs; QVarLengthArray<VkAttachmentReference, 8> resolveRefs; + QVarLengthArray<VkSubpassDependency, 2> subpassDeps; bool hasDepthStencil = false; VkAttachmentReference dsRef; QRhiVulkanRenderPassNativeHandles nativeHandlesStruct; diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp index ccb5f8a783..c4d1dca1bb 100644 --- a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp +++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp @@ -97,6 +97,8 @@ private slots: void srbWithNoResource(); void renderPassDescriptorCompatibility_data(); void renderPassDescriptorCompatibility(); + void renderPassDescriptorClone_data(); + void renderPassDescriptorClone(); void renderToTextureSimple_data(); void renderToTextureSimple(); @@ -3361,7 +3363,7 @@ void tst_QRhi::renderPassDescriptorCompatibility() QScopedPointer<QRhi> rhi(QRhi::create(impl, initParams, QRhi::Flags(), nullptr)); if (!rhi) - QSKIP("QRhi could not be created, skipping testing texture resource updates"); + QSKIP("QRhi could not be created, skipping testing renderpass descriptors"); // Note that checking compatibility is only relevant with backends where // there is a concept of renderpass descriptions (Vulkan, and partially @@ -3511,6 +3513,47 @@ void tst_QRhi::renderPassDescriptorCompatibility() } } +void tst_QRhi::renderPassDescriptorClone_data() +{ + rhiTestData(); +} + +void tst_QRhi::renderPassDescriptorClone() +{ + QFETCH(QRhi::Implementation, impl); + QFETCH(QRhiInitParams *, initParams); + + QScopedPointer<QRhi> rhi(QRhi::create(impl, initParams, QRhi::Flags(), nullptr)); + if (!rhi) + QSKIP("QRhi could not be created, skipping testing renderpass descriptors"); + + // tex and tex2 have the same format + QScopedPointer<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget)); + QVERIFY(tex->create()); + QScopedPointer<QRhiTexture> tex2(rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget)); + QVERIFY(tex2->create()); + + QScopedPointer<QRhiRenderBuffer> ds(rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512))); + QVERIFY(ds->create()); + + QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ tex.data() })); + QScopedPointer<QRhiRenderPassDescriptor> rpDesc(rt->newCompatibleRenderPassDescriptor()); + rt->setRenderPassDescriptor(rpDesc.data()); + QVERIFY(rt->create()); + + QScopedPointer<QRhiRenderPassDescriptor> rpDescClone(rpDesc->newCompatibleRenderPassDescriptor()); + QVERIFY(rpDescClone); + QVERIFY(rpDesc->isCompatible(rpDescClone.data())); + + // rt and rt2 have the same set of attachments + QScopedPointer<QRhiTextureRenderTarget> rt2(rhi->newTextureRenderTarget({ tex2.data() })); + QScopedPointer<QRhiRenderPassDescriptor> rpDesc2(rt2->newCompatibleRenderPassDescriptor()); + rt2->setRenderPassDescriptor(rpDesc2.data()); + QVERIFY(rt2->create()); + + QVERIFY(rpDesc2->isCompatible(rpDescClone.data())); +} + void tst_QRhi::pipelineCache_data() { rhiTestData(); |