summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2021-09-15 13:28:44 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2021-09-17 12:46:36 +0200
commit0a1cefa4c58d2a668e816d1b1581bbbd85700b7a (patch)
tree3fe524a744abfcc212d0f05d0fb32500d2226b2c /src/gui
parent092dc581ceb63e851af7a48c02cf72926a6f4986 (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.cpp24
-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.mm21
-rw-r--r--src/gui/rhi/qrhimetal_p_p.h4
-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.cpp49
-rw-r--r--src/gui/rhi/qrhivulkan_p_p.h4
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;
};