summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2021-03-16 16:33:27 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2021-03-19 10:46:23 +0000
commit19384f2e8f50bad0a0775f7b2e10aff3372bcbb5 (patch)
treedbf1589023f98726177a7a92dcc20a46778589ff
parent969337bcfd6af6d91b988e4b412703274a0b5877 (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.cpp40
-rw-r--r--src/gui/rhi/qrhi_p.h2
-rw-r--r--src/gui/rhi/qrhid3d11.cpp5
-rw-r--r--src/gui/rhi/qrhid3d11_p_p.h1
-rw-r--r--src/gui/rhi/qrhigles2.cpp5
-rw-r--r--src/gui/rhi/qrhigles2_p_p.h1
-rw-r--r--src/gui/rhi/qrhimetal.mm10
-rw-r--r--src/gui/rhi/qrhimetal_p_p.h1
-rw-r--r--src/gui/rhi/qrhinull.cpp5
-rw-r--r--src/gui/rhi/qrhinull_p_p.h1
-rw-r--r--src/gui/rhi/qrhivulkan.cpp137
-rw-r--r--src/gui/rhi/qrhivulkan_p_p.h2
-rw-r--r--tests/auto/gui/rhi/qrhi/tst_qrhi.cpp45
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();