Possible to use QOpenGLWidget with GLEW *and* render outside of main thread?
-
I have an application that is currently using
QOpenGLWidget
, and GLEW for OpenGL bindings.
This works ok, but its currently doing all rendering from the main thread, and my goal right now is to move OpenGL rendering into its own separate thread.The problem seems to be that I need to call
glewInit()
from the render thread, and I need to passQOpenGLContext
into the render thread or else glewInit will segfault. As I understand I have to call like this to transfer the context:qopenglwidget->context()->moveToThread(renderThread)
So it seems I have to
#include <QOpenGLContext>
in order to manipulate the context in this way. But doing gives a compiler warning that GLEW is incompatible and that Qt is overriding GLEW's functions:
https://github.com/qt/qtbase/blob/5.11/src/gui/kernel/qopenglcontext.h#L55-L56So I really have no idea how to proceed with this, any help would be appreciated.
And in case someone is wondering, the reason for sticking with GLEW and not converting it all over to QOpenGLFunctions is that the application has a "headless" build option that is not supposed to depend on Qt.
-
In general, rendering outside the GUI thread won't do what you want. You need to sync with the GUI system's decision about when to enter paintGL(), which means that at-best, you could add a bunch of complexity for no real benefit.
You'll want to use background threads only for non-drawing functionality like rendering intermediate data to a texture, loading geometry buffers, or loading and compiling shaders and textures. Then in the main thread, you do the actual drawing. Doing it this way will minimize the amount of CPU time you need to use in teh main thread blocking the UI if your frame rate is low, without having to go to unreasonable lengths to fight the GUI system.
If you really want to fight it, you'll basically have to give up on QOpenGLWidget and create a native widget outside of Qt, integrate that native widget into your UI somehow, and be 100% responsible for it. The level of work involved will almost never be worth it. (Multiple threads issuing draw commands to one GPU over one PCI bus, into one final screen display surface will result in less parallel performance boost than some people might imagine.)
-
Hi and welcome to devnet,
Here's a blog post about using QOpenGLContext in a multithreaded environment.
You can have a headless run of your application through the offscreen QPA.
Hope it helps
-
wrosecrans, I'm overwriting
QopenGLView::paintEvent
as suggested in the documentation here:Drawing directly to the QOpenGLWidget's framebuffer outside the GUI/main thread is possible by reimplementing paintEvent() to do nothing. The context's thread affinity has to be changed via QObject::moveToThread(). After that, makeCurrent() and doneCurrent() are usable on the worker thread. Be careful to move the context back to the GUI/main thread afterwards.
This means Qt is no longer calling paintGL directly.
The application I'm working on is OpenSCAD ( https://github.com/openscad/openscad ). In some extreme cases with very complex geometry, the render of a single frame can take multiple seconds, which makes the whole application unresponsive due to blocking the main event loop. So my reasoning for trying to render in another thread is to make the application a little more robust and usable in these cases where render is very slow.
The relevant code is in
src/QGLView.cc
andsrc/GLView.cc
QGLView inherits from QOpengGLWidget and GLView.
GLView includes GLEW and is completely independent of Qt, and is currently used in headless builds as I understand.Sgaist,
I only intend to have one single context, and one single rendering thread for OpenGL(but separate from the main thread).
So the blog post about creating and sharing multiple contexts I think is not really applicable unless I'm misunderstanding.I'm not familiar with QPA but a quick glance looks like it requires Qt5? OpenSCAD still currently supports being built for Qt4 or Qt5, so I don't think I can convert the whole thing over to using QPA as you suggest. I didn't want to muddle the issue in my original post by bringing up the legacy code, but there are preprocessor checks for whether to use QGLWidget (qt4) or QOpenGLWidget (qt5), and I was planning to do the same check for QGLContext/QOpenGLContext.