Debug functions to assert which phase the render thread and main thread are in
-
In more complex applications it would make code easier to reason about and guard against regressions to be able to do things like this in debug builds:
Q_ASSERT(QSG::isGuiBlocked()); Q_ASSERT(QSG::isRenderThread()); Q_ASSERT(QSG::isUpdatingPaintNodes()); Q_ASSERT(QQuickItem::isUpdating()); Q_ASSERT(QQuickItem::isUpdatingPolish());
Regarding thread detection, currently AFAIK we can only robustly detect the Qt UI thread, not the render thread. I have this:
inline bool isQtUI() { return QCoreApplication::instance() && QThread::currentThread() == QCoreApplication::instance()->thread(); }
I think there should also be a standard function for this in the Qt API, at least in debug.
Just wanted to double check if there is anything like these functions already before I consider adding my own solution. I would especially like to be able to robustly assert that the render thread is current.
-
I did this as a workable but not ideal solution to checking if we are on the render thread...
#define QT_REQUIRE_RENDER_THREAD() Q_ASSERT(util::thread::isQtRender())
constexpr auto kRenderThreadName = "Qt Render Thread"; inline bool isQtRender() { Q_ASSERT(QThread::currentThread()); return QThread::currentThread()->objectName() == kRenderThreadName; }
class NameRenderThreadJob : public QRunnable { public: void run() override { QThread::currentThread()->setObjectName(kRenderThreadName); } };
And add this to the constructor of our
QQuickWindow
/QQuickView
subclasses, which thankfully in our project are used in all cases:scheduleRenderJob(new util::thread::NameRenderThreadJob(), QQuickWindow::BeforeSynchronizingStage);
So just manually naming the Qt Render Thread QObject and crossing my fingers that none of the asserts will be checked before the name is set.
-
I think
NoStage
is actually a better choice thanBeforeSynchronizingStage
for this:
https://doc.qt.io/qt-6/qquickwindow.html#scheduleRenderJobUpdate: No, use
BeforeSynchronizingStage
.If stage is NoStage, job will be run at the earliest opportunity whenever the render thread is not busy rendering a frame.
So I thought perhaps NoStage would cause the render job to run earlier than with BeforeSynchronizingStage. But in my tests this was not the case. Probably this is key: "whenever the render thread is not busy".
-
Better solution using metaObject():
constexpr auto kQtRenderThreadClassName = "QSGRenderThread"; bool util::thread::isQtRender() { Q_ASSERT(QThread::currentThread()); QString threadName { QThread::currentThread()->metaObject()->className() }; return threadName == kQtRenderThreadClassName; }