Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-42813

QQuickRenderControl issues in a multithread environment

    XMLWordPrintable

Details

    • 6179550a0ca761bfabd4f6c67103f5397a306df0

    Description

      I'm trying to use QQuickRenderControl to drive QQ2 rendering from a secondary thread.

      The setup is as follows:

      In the GUI thread these objects get created:

      • QWindow (target of rendering)
      • QOpenGLContext
      • QQuickRenderControl
      • QQuickWindow (never show()n or create()d), plus the engine etc.

      When receiving an expose event:

      • QQuickRenderControl gets initialized
      • A secondary thread gets created
      • QOpenGLContext gets moved to that secondary thread

      When QQuickRenderControl emits its signals notifying a redraw is necessary:

      • polishItems gets called in the GUI thread
      • the secondary thread gets notified of the need of repaint

      I'm ignoring QQuickWindow signals in this scenario because I don't understand how am I supposed to use them.

      When the secondary thread gets notified, the steps done are:

      • sync (with locking)
      • render

      (The locking happens of a mutex shared between the GUI thread and the worker thread. The GUI thread locks that mutex when it creates it; unlocks that mutex when the event dispatcher emits "aboutToBlock"; and relocks it when the event dispatcher emits "awake". This seems to work on Linux but not on Mac, need to debug that out).

      Now this in theory is how everything should work in a threaded scenario, however the very first sync from the render thread spits several warnings:

      QObject::setParent: Cannot set parent, new parent is in a different thread
      QObject::setParent: Cannot set parent, new parent is in a different thread
      QObject::setParent: Cannot set parent, new parent is in a different thread
      

      Breakpointing shows the problems are inside the SG code. The first call to sync() causes Renderer to be created (inside qsgbatchedrenderer.cpp), in whose constructor there's code like

          if (!m_shaderManager) {
              m_shaderManager = new ShaderManager(ctx);
              m_shaderManager->setObjectName(QStringLiteral("__qt_ShaderManager"));
              m_shaderManager->setParent(ctx);
              QObject::connect(ctx, SIGNAL(invalidated()), m_shaderManager, SLOT(invalidated()), Qt::DirectConnection);
          }
      

      But "ctx" lives in the wrong thread, i.e. the main thread, and that setParent hence fails emitting the warning.

      I've also tried:

      • adding a polish() + sync() in the main thread after initializing the QQuickRenderControl, the result was a crash in font code (created in one thread, used in another)
      • moving QQuickRenderControl initialization onto the worker thread, the result was several warnings about using stuff from wrong threads

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            lagocs Laszlo Agocs
            peppe Giuseppe D'Angelo
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes