diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2021-09-15 13:28:44 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2021-09-17 12:46:36 +0200 |
commit | 0a1cefa4c58d2a668e816d1b1581bbbd85700b7a (patch) | |
tree | 3fe524a744abfcc212d0f05d0fb32500d2226b2c /src/gui | |
parent | 092dc581ceb63e851af7a48c02cf72926a6f4986 (diff) |
rhi: Allow testing renderpass compatibility without the objects
Follow what has been done for QRhiShaderResourceBindings. Have a way
to retrieve an opaque blob (that just happens to be a list of integers)
so that a simple == comparison can be used to determine compatibility
even when the objects from which the blob was retrieved are no longer
alive.
The contract is the following:
bool a = rp1->isCompatible(rp2);
bool b = rp1->serializedFormat() == rp2->serializedFormat();
assert(a == b);
Change-Id: I45e7d05eeb6dfa2b2de474da0a0644912aaf174a
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Christian Strømme <christian.stromme@qt.io>
(cherry picked from commit 43a42fa19693d8ee1a52a5723aa026ee1ccd5de2)
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/rhi/qrhi.cpp | 24 | ||||
-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 | 21 | ||||
-rw-r--r-- | src/gui/rhi/qrhimetal_p_p.h | 4 | ||||
-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 | 49 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan_p_p.h | 4 |
12 files changed, 121 insertions, 1 deletions
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index 7343c477d5..fb662acbfa 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -2746,7 +2746,17 @@ QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const \l{QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()}{created} from the same QRhiTextureRenderTarget are always compatible. - \sa newCompatibleRenderPassDescriptor() + Similarly to QRhiShaderResourceBindings, compatibility can also be tested + without having two existing objects available. Extracting the opaque blob by + calling serializedFormat() allows testing for compatibility by comparing the + returned vector to another QRhiRenderPassDescriptor's + serializedFormat(). This has benefits in certain situations, because it + allows testing the compatibility of a QRhiRenderPassDescriptor with a + QRhiGraphicsPipeline even when the QRhiRenderPassDescriptor the pipeline was + originally built was is no longer available (but the data returned from its + serializedFormat() still is). + + \sa newCompatibleRenderPassDescriptor(), serializedFormat() */ /*! @@ -2771,6 +2781,18 @@ QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const */ /*! + \fn QVector<quint32> QRhiRenderPassDescriptor::serializedFormat() const + + \return a vector of integers containing an opaque blob describing the data + relevant for \l{isCompatible()}{compatibility}. Given two + QRhiRenderPassDescriptor objects \c rp1 and \c rp2, if the data returned + from this function is identical, then \c{rp1->isCompatible(rp2)}, and vice + versa hold true as well. + + \sa isCompatible() + */ + +/*! \return a pointer to a backend-specific QRhiNativeHandles subclass, such as QRhiVulkanRenderPassNativeHandles. The returned value is \nullptr when exposing the underlying native resources is not supported by the backend. diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index d31838f52f..acd04f299c 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -993,6 +993,8 @@ public: virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const = 0; + virtual QVector<quint32> serializedFormat() const = 0; + protected: QRhiRenderPassDescriptor(QRhiImplementation *rhi); }; diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index 71faece6c1..8e94d70502 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -3371,6 +3371,11 @@ QRhiRenderPassDescriptor *QD3D11RenderPassDescriptor::newCompatibleRenderPassDes return new QD3D11RenderPassDescriptor(m_rhi); } +QVector<quint32> QD3D11RenderPassDescriptor::serializedFormat() const +{ + return {}; +} + 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 63705ccd0e..ddeb68a193 100644 --- a/src/gui/rhi/qrhid3d11_p_p.h +++ b/src/gui/rhi/qrhid3d11_p_p.h @@ -151,6 +151,7 @@ struct QD3D11RenderPassDescriptor : public QRhiRenderPassDescriptor void destroy() override; bool isCompatible(const QRhiRenderPassDescriptor *other) const override; QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override; + QVector<quint32> serializedFormat() const override; }; struct QD3D11RenderTargetData diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index 31b4d8cd51..04ad9d83dd 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -4769,6 +4769,11 @@ QRhiRenderPassDescriptor *QGles2RenderPassDescriptor::newCompatibleRenderPassDes return new QGles2RenderPassDescriptor(m_rhi); } +QVector<quint32> QGles2RenderPassDescriptor::serializedFormat() const +{ + return {}; +} + 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 ae5c90be24..4d18e9c60f 100644 --- a/src/gui/rhi/qrhigles2_p_p.h +++ b/src/gui/rhi/qrhigles2_p_p.h @@ -199,6 +199,7 @@ struct QGles2RenderPassDescriptor : public QRhiRenderPassDescriptor void destroy() override; bool isCompatible(const QRhiRenderPassDescriptor *other) const override; QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override; + QVector<quint32> serializedFormat() const override; }; struct QGles2RenderTargetData diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index e169550ee4..6bdcfd70c8 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -2924,6 +2924,7 @@ bool QMetalSampler::create() QMetalRenderPassDescriptor::QMetalRenderPassDescriptor(QRhiImplementation *rhi) : QRhiRenderPassDescriptor(rhi) { + serializedFormatData.reserve(16); } QMetalRenderPassDescriptor::~QMetalRenderPassDescriptor() @@ -2962,6 +2963,18 @@ bool QMetalRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *ot return true; } +void QMetalRenderPassDescriptor::updateSerializedFormat() +{ + serializedFormatData.clear(); + auto p = std::back_inserter(serializedFormatData); + + *p++ = colorAttachmentCount; + *p++ = hasDepthStencil; + for (int i = 0; i < colorAttachmentCount; ++i) + *p++ = colorFormat[i]; + *p++ = hasDepthStencil ? dsFormat : 0; +} + QRhiRenderPassDescriptor *QMetalRenderPassDescriptor::newCompatibleRenderPassDescriptor() const { QMetalRenderPassDescriptor *rp = new QMetalRenderPassDescriptor(m_rhi); @@ -2969,9 +2982,15 @@ QRhiRenderPassDescriptor *QMetalRenderPassDescriptor::newCompatibleRenderPassDes rp->hasDepthStencil = hasDepthStencil; memcpy(rp->colorFormat, colorFormat, sizeof(colorFormat)); rp->dsFormat = dsFormat; + rp->updateSerializedFormat(); return rp; } +QVector<quint32> QMetalRenderPassDescriptor::serializedFormat() const +{ + return serializedFormatData; +} + QMetalReferenceRenderTarget::QMetalReferenceRenderTarget(QRhiImplementation *rhi) : QRhiRenderTarget(rhi), d(new QMetalRenderTargetData) @@ -3042,6 +3061,7 @@ QRhiRenderPassDescriptor *QMetalTextureRenderTarget::newCompatibleRenderPassDesc else if (m_desc.depthStencilBuffer()) rpD->dsFormat = int(QRHI_RES(QMetalRenderBuffer, m_desc.depthStencilBuffer())->d->format); + rpD->updateSerializedFormat(); return rpD; } @@ -3953,6 +3973,7 @@ QRhiRenderPassDescriptor *QMetalSwapChain::newCompatibleRenderPassDescriptor() rpD->dsFormat = MTLPixelFormatDepth32Float_Stencil8; #endif + rpD->updateSerializedFormat(); return rpD; } diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h index 2aafde7c0d..72a4d82888 100644 --- a/src/gui/rhi/qrhimetal_p_p.h +++ b/src/gui/rhi/qrhimetal_p_p.h @@ -146,6 +146,9 @@ struct QMetalRenderPassDescriptor : public QRhiRenderPassDescriptor void destroy() override; bool isCompatible(const QRhiRenderPassDescriptor *other) const override; QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override; + QVector<quint32> serializedFormat() const override; + + void updateSerializedFormat(); // there is no MTLRenderPassDescriptor here as one will be created for each pass in beginPass() @@ -155,6 +158,7 @@ struct QMetalRenderPassDescriptor : public QRhiRenderPassDescriptor bool hasDepthStencil = false; int colorFormat[MAX_COLOR_ATTACHMENTS]; int dsFormat; + QVector<quint32> serializedFormatData; }; struct QMetalRenderTargetData; diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp index 4706b37461..894caf8f35 100644 --- a/src/gui/rhi/qrhinull.cpp +++ b/src/gui/rhi/qrhinull.cpp @@ -793,6 +793,11 @@ QRhiRenderPassDescriptor *QNullRenderPassDescriptor::newCompatibleRenderPassDesc return new QNullRenderPassDescriptor(m_rhi); } +QVector<quint32> QNullRenderPassDescriptor::serializedFormat() const +{ + return {}; +} + 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 5905047fda..24fb426503 100644 --- a/src/gui/rhi/qrhinull_p_p.h +++ b/src/gui/rhi/qrhinull_p_p.h @@ -109,6 +109,7 @@ struct QNullRenderPassDescriptor : public QRhiRenderPassDescriptor void destroy() override; bool isCompatible(const QRhiRenderPassDescriptor *other) const override; QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override; + QVector<quint32> serializedFormat() const override; }; struct QNullRenderTargetData diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 45fb106a10..c59b459a5b 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -6131,6 +6131,7 @@ bool QVkSampler::create() QVkRenderPassDescriptor::QVkRenderPassDescriptor(QRhiImplementation *rhi) : QRhiRenderPassDescriptor(rhi) { + serializedFormatData.reserve(32); } QVkRenderPassDescriptor::~QVkRenderPassDescriptor() @@ -6223,6 +6224,46 @@ bool QVkRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other return true; } +void QVkRenderPassDescriptor::updateSerializedFormat() +{ + serializedFormatData.clear(); + auto p = std::back_inserter(serializedFormatData); + + *p++ = attDescs.count(); + *p++ = colorRefs.count(); + *p++ = resolveRefs.count(); + *p++ = hasDepthStencil; + + auto serializeAttachmentData = [&p](const VkAttachmentDescription &a, bool used) { + *p++ = used ? a.format : 0; + *p++ = used ? a.samples : 0; + *p++ = used ? a.loadOp : 0; + *p++ = used ? a.storeOp : 0; + *p++ = used ? a.stencilLoadOp : 0; + *p++ = used ? a.stencilStoreOp : 0; + *p++ = used ? a.initialLayout : 0; + *p++ = used ? a.finalLayout : 0; + }; + + for (int i = 0, ie = colorRefs.count(); i != ie; ++i) { + const uint32_t attIdx = colorRefs[i].attachment; + *p++ = attIdx; + serializeAttachmentData(attDescs[attIdx], attIdx != VK_ATTACHMENT_UNUSED); + } + + if (hasDepthStencil) { + const uint32_t attIdx = dsRef.attachment; + *p++ = attIdx; + serializeAttachmentData(attDescs[attIdx], attIdx != VK_ATTACHMENT_UNUSED); + } + + for (int i = 0, ie = resolveRefs.count(); i != ie; ++i) { + const uint32_t attIdx = resolveRefs[i].attachment; + *p++ = attIdx; + serializeAttachmentData(attDescs[attIdx], attIdx != VK_ATTACHMENT_UNUSED); + } +} + QRhiRenderPassDescriptor *QVkRenderPassDescriptor::newCompatibleRenderPassDescriptor() const { QVkRenderPassDescriptor *rpD = new QVkRenderPassDescriptor(m_rhi); @@ -6247,10 +6288,16 @@ QRhiRenderPassDescriptor *QVkRenderPassDescriptor::newCompatibleRenderPassDescri return nullptr; } + rpD->updateSerializedFormat(); rhiD->registerResource(rpD); return rpD; } +QVector<quint32> QVkRenderPassDescriptor::serializedFormat() const +{ + return serializedFormatData; +} + const QRhiNativeHandles *QVkRenderPassDescriptor::nativeHandles() { nativeHandlesStruct.renderPass = rp; @@ -6348,6 +6395,7 @@ QRhiRenderPassDescriptor *QVkTextureRenderTarget::newCompatibleRenderPassDescrip } rp->ownsRp = true; + rp->updateSerializedFormat(); rhiD->registerResource(rp); return rp; } @@ -7122,6 +7170,7 @@ QRhiRenderPassDescriptor *QVkSwapChain::newCompatibleRenderPassDescriptor() } rp->ownsRp = true; + rp->updateSerializedFormat(); rhiD->registerResource(rp); return rp; } diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h index 52473891d1..f2a3a809d3 100644 --- a/src/gui/rhi/qrhivulkan_p_p.h +++ b/src/gui/rhi/qrhivulkan_p_p.h @@ -186,8 +186,11 @@ struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor void destroy() override; bool isCompatible(const QRhiRenderPassDescriptor *other) const override; QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override; + QVector<quint32> serializedFormat() const override; const QRhiNativeHandles *nativeHandles() override; + void updateSerializedFormat(); + VkRenderPass rp = VK_NULL_HANDLE; bool ownsRp = false; QVarLengthArray<VkAttachmentDescription, 8> attDescs; @@ -196,6 +199,7 @@ struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor QVarLengthArray<VkSubpassDependency, 2> subpassDeps; bool hasDepthStencil = false; VkAttachmentReference dsRef; + QVector<quint32> serializedFormatData; QRhiVulkanRenderPassNativeHandles nativeHandlesStruct; int lastActiveFrameSlot = -1; }; |