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
|
native resources. That is only done when calling the \c create() function of a
|
||||||
subclass, for example, QRhiBuffer::create() or QRhiTexture::create().
|
subclass, for example, QRhiBuffer::create() or QRhiTexture::create().
|
||||||
|
|
||||||
\li The exception is
|
\li The exceptions are
|
||||||
QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() and
|
QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor(),
|
||||||
QRhiSwapChain::newCompatibleRenderPassDescriptor(). There is no \c create()
|
QRhiSwapChain::newCompatibleRenderPassDescriptor(), and
|
||||||
operation for these and the returned object is immediately active.
|
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
|
\li The resource objects themselves are treated as immutable: once a
|
||||||
resource has create() called, changing any parameters via the setters, such as,
|
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
|
\return true if the \a other QRhiRenderPassDescriptor is compatible with
|
||||||
this one, meaning \c this and \a other can be used interchangebly in
|
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
|
allowing a different QRhiRenderPassDescriptor and
|
||||||
QRhiShaderResourceBindings to be used in combination with the pipeline, as
|
QRhiShaderResourceBindings to be used in combination with the pipeline, as
|
||||||
long as they are compatible.
|
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 bool isCompatible(const QRhiRenderPassDescriptor *other) const = 0;
|
||||||
virtual const QRhiNativeHandles *nativeHandles();
|
virtual const QRhiNativeHandles *nativeHandles();
|
||||||
|
|
||||||
|
virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QRhiRenderPassDescriptor(QRhiImplementation *rhi);
|
QRhiRenderPassDescriptor(QRhiImplementation *rhi);
|
||||||
};
|
};
|
||||||
|
@ -3281,6 +3281,11 @@ bool QD3D11RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *ot
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRhiRenderPassDescriptor *QD3D11RenderPassDescriptor::newCompatibleRenderPassDescriptor() const
|
||||||
|
{
|
||||||
|
return new QD3D11RenderPassDescriptor(m_rhi);
|
||||||
|
}
|
||||||
|
|
||||||
QD3D11ReferenceRenderTarget::QD3D11ReferenceRenderTarget(QRhiImplementation *rhi)
|
QD3D11ReferenceRenderTarget::QD3D11ReferenceRenderTarget(QRhiImplementation *rhi)
|
||||||
: QRhiRenderTarget(rhi),
|
: QRhiRenderTarget(rhi),
|
||||||
d(rhi)
|
d(rhi)
|
||||||
|
@ -143,6 +143,7 @@ struct QD3D11RenderPassDescriptor : public QRhiRenderPassDescriptor
|
|||||||
~QD3D11RenderPassDescriptor();
|
~QD3D11RenderPassDescriptor();
|
||||||
void destroy() override;
|
void destroy() override;
|
||||||
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
|
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
|
||||||
|
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QD3D11RenderTargetData
|
struct QD3D11RenderTargetData
|
||||||
|
@ -4549,6 +4549,11 @@ bool QGles2RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *ot
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRhiRenderPassDescriptor *QGles2RenderPassDescriptor::newCompatibleRenderPassDescriptor() const
|
||||||
|
{
|
||||||
|
return new QGles2RenderPassDescriptor(m_rhi);
|
||||||
|
}
|
||||||
|
|
||||||
QGles2ReferenceRenderTarget::QGles2ReferenceRenderTarget(QRhiImplementation *rhi)
|
QGles2ReferenceRenderTarget::QGles2ReferenceRenderTarget(QRhiImplementation *rhi)
|
||||||
: QRhiRenderTarget(rhi),
|
: QRhiRenderTarget(rhi),
|
||||||
d(rhi)
|
d(rhi)
|
||||||
|
@ -193,6 +193,7 @@ struct QGles2RenderPassDescriptor : public QRhiRenderPassDescriptor
|
|||||||
~QGles2RenderPassDescriptor();
|
~QGles2RenderPassDescriptor();
|
||||||
void destroy() override;
|
void destroy() override;
|
||||||
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
|
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
|
||||||
|
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QGles2RenderTargetData
|
struct QGles2RenderTargetData
|
||||||
|
@ -2900,6 +2900,16 @@ bool QMetalRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *ot
|
|||||||
return true;
|
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)
|
QMetalReferenceRenderTarget::QMetalReferenceRenderTarget(QRhiImplementation *rhi)
|
||||||
: QRhiRenderTarget(rhi),
|
: QRhiRenderTarget(rhi),
|
||||||
d(new QMetalRenderTargetData)
|
d(new QMetalRenderTargetData)
|
||||||
|
@ -145,6 +145,7 @@ struct QMetalRenderPassDescriptor : public QRhiRenderPassDescriptor
|
|||||||
~QMetalRenderPassDescriptor();
|
~QMetalRenderPassDescriptor();
|
||||||
void destroy() override;
|
void destroy() override;
|
||||||
bool isCompatible(const QRhiRenderPassDescriptor *other) const 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()
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRhiRenderPassDescriptor *QNullRenderPassDescriptor::newCompatibleRenderPassDescriptor() const
|
||||||
|
{
|
||||||
|
return new QNullRenderPassDescriptor(m_rhi);
|
||||||
|
}
|
||||||
|
|
||||||
QNullReferenceRenderTarget::QNullReferenceRenderTarget(QRhiImplementation *rhi)
|
QNullReferenceRenderTarget::QNullReferenceRenderTarget(QRhiImplementation *rhi)
|
||||||
: QRhiRenderTarget(rhi),
|
: QRhiRenderTarget(rhi),
|
||||||
d(rhi)
|
d(rhi)
|
||||||
|
@ -105,6 +105,7 @@ struct QNullRenderPassDescriptor : public QRhiRenderPassDescriptor
|
|||||||
~QNullRenderPassDescriptor();
|
~QNullRenderPassDescriptor();
|
||||||
void destroy() override;
|
void destroy() override;
|
||||||
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
|
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
|
||||||
|
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QNullRenderTargetData
|
struct QNullRenderTargetData
|
||||||
|
@ -1174,6 +1174,28 @@ VkFormat QRhiVulkan::optimalDepthStencilFormat()
|
|||||||
return optimalDsFormat;
|
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)
|
bool QRhiVulkan::createDefaultRenderPass(QVkRenderPassDescriptor *rpD, bool hasDepthStencil, VkSampleCountFlagBits samples, VkFormat colorFormat)
|
||||||
{
|
{
|
||||||
// attachment list layout is color (1), ds (0-1), resolve (0-1)
|
// 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->colorRefs.append({ 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL });
|
||||||
|
|
||||||
|
rpD->hasDepthStencil = hasDepthStencil;
|
||||||
|
|
||||||
if (hasDepthStencil) {
|
if (hasDepthStencil) {
|
||||||
// clear on load + no store + lazy alloc + transient image should play
|
// clear on load + no store + lazy alloc + transient image should play
|
||||||
// nicely with tiled GPUs (no physical backing necessary for ds buffer)
|
// 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 });
|
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.
|
// Replace the first implicit dep (TOP_OF_PIPE / ALL_COMMANDS) with our own.
|
||||||
VkSubpassDependency subpassDeps[2];
|
VkSubpassDependency subpassDep;
|
||||||
memset(subpassDeps, 0, sizeof(subpassDeps));
|
memset(&subpassDep, 0, sizeof(subpassDep));
|
||||||
subpassDeps[0].srcSubpass = VK_SUBPASS_EXTERNAL;
|
subpassDep.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||||
subpassDeps[0].dstSubpass = 0;
|
subpassDep.dstSubpass = 0;
|
||||||
subpassDeps[0].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
subpassDep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
subpassDeps[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
subpassDep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
subpassDeps[0].srcAccessMask = 0;
|
subpassDep.srcAccessMask = 0;
|
||||||
subpassDeps[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
subpassDep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
|
rpD->subpassDeps.append(subpassDep);
|
||||||
if (hasDepthStencil) {
|
if (hasDepthStencil) {
|
||||||
subpassDeps[1].srcSubpass = VK_SUBPASS_EXTERNAL;
|
memset(&subpassDep, 0, sizeof(subpassDep));
|
||||||
subpassDeps[1].dstSubpass = 0;
|
subpassDep.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||||
subpassDeps[1].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
|
subpassDep.dstSubpass = 0;
|
||||||
|
subpassDep.srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
|
||||||
| VK_PIPELINE_STAGE_LATE_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;
|
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
subpassDeps[1].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
subpassDep.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
subpassDeps[1].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
|
subpassDep.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
|
||||||
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
|
rpD->subpassDeps.append(subpassDep);
|
||||||
}
|
}
|
||||||
|
|
||||||
VkRenderPassCreateInfo rpInfo;
|
VkRenderPassCreateInfo rpInfo;
|
||||||
memset(&rpInfo, 0, sizeof(rpInfo));
|
VkSubpassDescription subpassDesc;
|
||||||
rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
fillRenderPassCreateInfo(&rpInfo, &subpassDesc, rpD);
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, &rpD->rp);
|
VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, &rpD->rp);
|
||||||
if (err != VK_SUCCESS) {
|
if (err != VK_SUCCESS) {
|
||||||
@ -1278,8 +1282,6 @@ bool QRhiVulkan::createDefaultRenderPass(QVkRenderPassDescriptor *rpD, bool hasD
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpD->hasDepthStencil = hasDepthStencil;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1377,25 +1379,14 @@ bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSubpassDescription subpassDesc;
|
// rpD->subpassDeps stays empty: don't yet know the correct initial/final
|
||||||
memset(&subpassDesc, 0, sizeof(subpassDesc));
|
// access and stage stuff for the implicit deps at this point, so leave it
|
||||||
subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
// to the resource tracking and activateTextureRenderTarget() to generate
|
||||||
subpassDesc.colorAttachmentCount = uint32_t(rpD->colorRefs.count());
|
// barriers.
|
||||||
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;
|
|
||||||
|
|
||||||
VkRenderPassCreateInfo rpInfo;
|
VkRenderPassCreateInfo rpInfo;
|
||||||
memset(&rpInfo, 0, sizeof(rpInfo));
|
VkSubpassDescription subpassDesc;
|
||||||
rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
fillRenderPassCreateInfo(&rpInfo, &subpassDesc, rpD);
|
||||||
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
|
|
||||||
|
|
||||||
VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, &rpD->rp);
|
VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, &rpD->rp);
|
||||||
if (err != VK_SUCCESS) {
|
if (err != VK_SUCCESS) {
|
||||||
@ -6149,9 +6140,39 @@ bool QVkRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// subpassDeps is not included
|
||||||
|
|
||||||
return true;
|
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()
|
const QRhiNativeHandles *QVkRenderPassDescriptor::nativeHandles()
|
||||||
{
|
{
|
||||||
nativeHandlesStruct.renderPass = rp;
|
nativeHandlesStruct.renderPass = rp;
|
||||||
|
@ -185,6 +185,7 @@ struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor
|
|||||||
~QVkRenderPassDescriptor();
|
~QVkRenderPassDescriptor();
|
||||||
void destroy() override;
|
void destroy() override;
|
||||||
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
|
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
|
||||||
|
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
|
||||||
const QRhiNativeHandles *nativeHandles() override;
|
const QRhiNativeHandles *nativeHandles() override;
|
||||||
|
|
||||||
VkRenderPass rp = VK_NULL_HANDLE;
|
VkRenderPass rp = VK_NULL_HANDLE;
|
||||||
@ -192,6 +193,7 @@ struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor
|
|||||||
QVarLengthArray<VkAttachmentDescription, 8> attDescs;
|
QVarLengthArray<VkAttachmentDescription, 8> attDescs;
|
||||||
QVarLengthArray<VkAttachmentReference, 8> colorRefs;
|
QVarLengthArray<VkAttachmentReference, 8> colorRefs;
|
||||||
QVarLengthArray<VkAttachmentReference, 8> resolveRefs;
|
QVarLengthArray<VkAttachmentReference, 8> resolveRefs;
|
||||||
|
QVarLengthArray<VkSubpassDependency, 2> subpassDeps;
|
||||||
bool hasDepthStencil = false;
|
bool hasDepthStencil = false;
|
||||||
VkAttachmentReference dsRef;
|
VkAttachmentReference dsRef;
|
||||||
QRhiVulkanRenderPassNativeHandles nativeHandlesStruct;
|
QRhiVulkanRenderPassNativeHandles nativeHandlesStruct;
|
||||||
|
@ -97,6 +97,8 @@ private slots:
|
|||||||
void srbWithNoResource();
|
void srbWithNoResource();
|
||||||
void renderPassDescriptorCompatibility_data();
|
void renderPassDescriptorCompatibility_data();
|
||||||
void renderPassDescriptorCompatibility();
|
void renderPassDescriptorCompatibility();
|
||||||
|
void renderPassDescriptorClone_data();
|
||||||
|
void renderPassDescriptorClone();
|
||||||
|
|
||||||
void renderToTextureSimple_data();
|
void renderToTextureSimple_data();
|
||||||
void renderToTextureSimple();
|
void renderToTextureSimple();
|
||||||
@ -3361,7 +3363,7 @@ void tst_QRhi::renderPassDescriptorCompatibility()
|
|||||||
|
|
||||||
QScopedPointer<QRhi> rhi(QRhi::create(impl, initParams, QRhi::Flags(), nullptr));
|
QScopedPointer<QRhi> rhi(QRhi::create(impl, initParams, QRhi::Flags(), nullptr));
|
||||||
if (!rhi)
|
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
|
// Note that checking compatibility is only relevant with backends where
|
||||||
// there is a concept of renderpass descriptions (Vulkan, and partially
|
// 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()
|
void tst_QRhi::pipelineCache_data()
|
||||||
{
|
{
|
||||||
rhiTestData();
|
rhiTestData();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user