rhi: metal: Add enablers for pre-querying window stuff on the gui thread
Pick-to: 6.5 Task-number: QTBUG-97518 Change-Id: Ia8fb5128149c9f91ebedfa914d1fe3e3d49774dc Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
parent
a2e38207da
commit
f486d1f4d2
@ -5636,6 +5636,49 @@ bool QRhi::probe(QRhi::Implementation impl, QRhiInitParams *params)
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*!
|
||||
\struct QRhiSwapChainProxyData
|
||||
\internal
|
||||
\inmodule QtGui
|
||||
*/
|
||||
|
||||
/*!
|
||||
Generates and returns a QRhiSwapChainProxyData struct containing opaque
|
||||
data specific to the backend and graphics API specified by \a impl. \a
|
||||
window is the QWindow a swapchain is targeting.
|
||||
|
||||
The returned struct can be passed to QRhiSwapChain::setProxyData(). This
|
||||
makes sense in threaded rendering systems: this static function is expected
|
||||
to be called on the \b{main (gui) thread}, unlike all QRhi operations, then
|
||||
transferred to the thread working with the QRhi and QRhiSwapChain and passed
|
||||
on to the swapchain. This allows doing native platform queries that are
|
||||
only safe to be called on the main thread, for example to query the
|
||||
CAMetalLayer from a NSView, and then passing on the data to the
|
||||
QRhiSwapChain living on the rendering thread. With the Metal example, doing
|
||||
the view.layer access on a dedicated rendering thread causes a warning in
|
||||
the Xcode Thread Checker. With the data proxy mechanism, this is avoided.
|
||||
|
||||
When threads are not involved, generating and passing on the
|
||||
QRhiSwapChainProxyData is not required: backends are guaranteed to be able
|
||||
to query whatever is needed on their own, and if everything lives on the
|
||||
main (gui) thread, that should be sufficient.
|
||||
|
||||
\note \a impl should match what the QRhi is created with. For example,
|
||||
calling with QRhi::Metal on a non-Apple platform will not generate any
|
||||
useful data.
|
||||
*/
|
||||
QRhiSwapChainProxyData QRhi::updateSwapChainProxyData(QRhi::Implementation impl, QWindow *window)
|
||||
{
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
|
||||
if (impl == Metal)
|
||||
return QRhiMetal::updateSwapChainProxyData(window);
|
||||
#else
|
||||
Q_UNUSED(impl);
|
||||
Q_UNUSED(window);
|
||||
#endif
|
||||
return {};
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the backend type for this QRhi.
|
||||
*/
|
||||
|
@ -1361,6 +1361,11 @@ Q_DECLARE_TYPEINFO(QRhiSwapChainHdrInfo, Q_RELOCATABLE_TYPE);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiSwapChainHdrInfo &);
|
||||
#endif
|
||||
|
||||
struct QRhiSwapChainProxyData
|
||||
{
|
||||
void *reserved[2] = {};
|
||||
};
|
||||
|
||||
class Q_GUI_EXPORT QRhiSwapChain : public QRhiResource
|
||||
{
|
||||
public:
|
||||
@ -1390,6 +1395,9 @@ public:
|
||||
QWindow *window() const { return m_window; }
|
||||
void setWindow(QWindow *window) { m_window = window; }
|
||||
|
||||
QRhiSwapChainProxyData proxyData() const { return m_proxyData; }
|
||||
void setProxyData(const QRhiSwapChainProxyData &d) { m_proxyData = d; }
|
||||
|
||||
Flags flags() const { return m_flags; }
|
||||
void setFlags(Flags f) { m_flags = f; }
|
||||
|
||||
@ -1425,6 +1433,7 @@ protected:
|
||||
int m_sampleCount = 1;
|
||||
QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
|
||||
QSize m_currentPixelSize;
|
||||
QRhiSwapChainProxyData m_proxyData;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiSwapChain::Flags)
|
||||
@ -1810,6 +1819,8 @@ public:
|
||||
|
||||
QRhiStats statistics() const;
|
||||
|
||||
static QRhiSwapChainProxyData updateSwapChainProxyData(Implementation impl, QWindow *window);
|
||||
|
||||
protected:
|
||||
QRhi();
|
||||
|
||||
|
@ -789,6 +789,15 @@ bool QRhiRenderTargetAttachmentTracker::isUpToDate(const QRhiTextureRenderTarget
|
||||
return resIdList == currentResIdList;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T *qrhi_objectFromProxyData(QRhiSwapChainProxyData *pd, QWindow *window, QRhi::Implementation impl, uint objectIndex)
|
||||
{
|
||||
Q_ASSERT(objectIndex < std::size(pd->reserved));
|
||||
if (!pd->reserved[objectIndex]) // // was not set, no other choice, do it here, whatever thread this is
|
||||
*pd = QRhi::updateSwapChainProxyData(impl, window);
|
||||
return static_cast<T *>(pd->reserved[objectIndex]);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -5501,6 +5501,9 @@ QRhiRenderTarget *QMetalSwapChain::currentFrameRenderTarget()
|
||||
return &rtWrapper;
|
||||
}
|
||||
|
||||
// view.layer should ideally be called on the main thread, otherwise the UI
|
||||
// Thread Checker in Xcode drops a warning. Hence trying to proxy it through
|
||||
// QRhiSwapChainProxyData instead of just calling this function directly.
|
||||
static inline CAMetalLayer *layerForWindow(QWindow *window)
|
||||
{
|
||||
Q_ASSERT(window);
|
||||
@ -5513,13 +5516,24 @@ static inline CAMetalLayer *layerForWindow(QWindow *window)
|
||||
return static_cast<CAMetalLayer *>(view.layer);
|
||||
}
|
||||
|
||||
// If someone calls this, it is hopefully from the main thread, and they will
|
||||
// then set the returned data on the QRhiSwapChain, so it won't need to query
|
||||
// the layer on its own later on.
|
||||
QRhiSwapChainProxyData QRhiMetal::updateSwapChainProxyData(QWindow *window)
|
||||
{
|
||||
QRhiSwapChainProxyData d;
|
||||
d.reserved[0] = layerForWindow(window);
|
||||
return d;
|
||||
}
|
||||
|
||||
QSize QMetalSwapChain::surfacePixelSize()
|
||||
{
|
||||
Q_ASSERT(m_window);
|
||||
CAMetalLayer *layer = d->layer;
|
||||
if (!layer)
|
||||
layer = layerForWindow(m_window);
|
||||
layer = qrhi_objectFromProxyData<CAMetalLayer>(&m_proxyData, m_window, QRhi::Metal, 0);
|
||||
|
||||
Q_ASSERT(layer);
|
||||
int height = (int)layer.bounds.size.height;
|
||||
int width = (int)layer.bounds.size.width;
|
||||
width *= layer.contentsScale;
|
||||
@ -5593,7 +5607,7 @@ bool QMetalSwapChain::createOrResize()
|
||||
return false;
|
||||
}
|
||||
|
||||
d->layer = layerForWindow(window);
|
||||
d->layer = qrhi_objectFromProxyData<CAMetalLayer>(&m_proxyData, window, QRhi::Metal, 0);
|
||||
Q_ASSERT(d->layer);
|
||||
|
||||
chooseFormats();
|
||||
|
@ -329,6 +329,7 @@ public:
|
||||
~QRhiMetal();
|
||||
|
||||
static bool probe(QRhiMetalInitParams *params);
|
||||
static QRhiSwapChainProxyData updateSwapChainProxyData(QWindow *window);
|
||||
|
||||
bool create(QRhi::Flags flags) override;
|
||||
void destroy() override;
|
||||
|
Loading…
Reference in New Issue
Block a user