Merge "rhi: Make it possible to clone a QRhiRenderPassDescriptor"
This commit is contained in:
commit
98e4652a96
@ -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()
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user