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;
|
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.
|
\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 &);
|
Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiSwapChainHdrInfo &);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct QRhiSwapChainProxyData
|
||||||
|
{
|
||||||
|
void *reserved[2] = {};
|
||||||
|
};
|
||||||
|
|
||||||
class Q_GUI_EXPORT QRhiSwapChain : public QRhiResource
|
class Q_GUI_EXPORT QRhiSwapChain : public QRhiResource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -1390,6 +1395,9 @@ public:
|
|||||||
QWindow *window() const { return m_window; }
|
QWindow *window() const { return m_window; }
|
||||||
void setWindow(QWindow *window) { m_window = 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; }
|
Flags flags() const { return m_flags; }
|
||||||
void setFlags(Flags f) { m_flags = f; }
|
void setFlags(Flags f) { m_flags = f; }
|
||||||
|
|
||||||
@ -1425,6 +1433,7 @@ protected:
|
|||||||
int m_sampleCount = 1;
|
int m_sampleCount = 1;
|
||||||
QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
|
QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
|
||||||
QSize m_currentPixelSize;
|
QSize m_currentPixelSize;
|
||||||
|
QRhiSwapChainProxyData m_proxyData;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiSwapChain::Flags)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiSwapChain::Flags)
|
||||||
@ -1810,6 +1819,8 @@ public:
|
|||||||
|
|
||||||
QRhiStats statistics() const;
|
QRhiStats statistics() const;
|
||||||
|
|
||||||
|
static QRhiSwapChainProxyData updateSwapChainProxyData(Implementation impl, QWindow *window);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QRhi();
|
QRhi();
|
||||||
|
|
||||||
|
@ -789,6 +789,15 @@ bool QRhiRenderTargetAttachmentTracker::isUpToDate(const QRhiTextureRenderTarget
|
|||||||
return resIdList == currentResIdList;
|
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
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -5501,6 +5501,9 @@ QRhiRenderTarget *QMetalSwapChain::currentFrameRenderTarget()
|
|||||||
return &rtWrapper;
|
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)
|
static inline CAMetalLayer *layerForWindow(QWindow *window)
|
||||||
{
|
{
|
||||||
Q_ASSERT(window);
|
Q_ASSERT(window);
|
||||||
@ -5513,13 +5516,24 @@ static inline CAMetalLayer *layerForWindow(QWindow *window)
|
|||||||
return static_cast<CAMetalLayer *>(view.layer);
|
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()
|
QSize QMetalSwapChain::surfacePixelSize()
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_window);
|
Q_ASSERT(m_window);
|
||||||
CAMetalLayer *layer = d->layer;
|
CAMetalLayer *layer = d->layer;
|
||||||
if (!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 height = (int)layer.bounds.size.height;
|
||||||
int width = (int)layer.bounds.size.width;
|
int width = (int)layer.bounds.size.width;
|
||||||
width *= layer.contentsScale;
|
width *= layer.contentsScale;
|
||||||
@ -5593,7 +5607,7 @@ bool QMetalSwapChain::createOrResize()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->layer = layerForWindow(window);
|
d->layer = qrhi_objectFromProxyData<CAMetalLayer>(&m_proxyData, window, QRhi::Metal, 0);
|
||||||
Q_ASSERT(d->layer);
|
Q_ASSERT(d->layer);
|
||||||
|
|
||||||
chooseFormats();
|
chooseFormats();
|
||||||
|
@ -329,6 +329,7 @@ public:
|
|||||||
~QRhiMetal();
|
~QRhiMetal();
|
||||||
|
|
||||||
static bool probe(QRhiMetalInitParams *params);
|
static bool probe(QRhiMetalInitParams *params);
|
||||||
|
static QRhiSwapChainProxyData updateSwapChainProxyData(QWindow *window);
|
||||||
|
|
||||||
bool create(QRhi::Flags flags) override;
|
bool create(QRhi::Flags flags) override;
|
||||||
void destroy() override;
|
void destroy() override;
|
||||||
|
Loading…
Reference in New Issue
Block a user