Is there a way to use the qglcontext of the glwidget from other threads. Because I need to do some texture uploading from other threads. However after the texture upload or even during it context must be also in the service of my rendering glwidget. Is there a documentation or a solid (assumption free) answer for this?
OpenGL does not support multithreaded rendering, all OpenGL calls must be performed from the thread where context was created. But if you whant to just load textures, you may load it from other threads, than post the results to that thread from wich OpenGL context was created for example to glTexImage2D, as image info. To do so must be add some thread management (signals e.t.c...).
For more information look at Concurrency and OpenGL.
also QGLWidget multithreaded example?.
To work from other threads you must create separate contexts with them or perform some sharing context management.
From official Qt documentation:
As of Qt version 4.8, support for doing threaded GL rendering has been improved. There are three scenarios that we currently support:
Buffer swapping in a thread.
Swapping buffers in a double buffered context may be a synchronous, locking call that may be a costly operation in some GL implementations. Especially so on embedded devices. It's not optimal to have the CPU idling while the GPU is doing a buffer swap. In those cases it is possible to do the rendering in the main thread and do the actual buffer swap in a separate thread. This can be done with the following steps:
Call doneCurrent() in the main thread when the rendering is finished.
Call QGLContext::moveToThread(swapThread) to transfer ownership of the context to the swapping thread.
Notify the swapping thread that it can grab the context.
Make the rendering context current in the swapping thread with makeCurrent() and then call swapBuffers().
Call doneCurrent() in the swapping thread.
Call QGLContext::moveToThread(qApp->thread()) and notify the main thread that swapping is done.
Doing this will free up the main thread so that it can continue with, for example, handling UI events or network requests. Even if there is a context swap involved, it may be preferable compared to having the main thread wait while the GPU finishes the swap operation. Note that this is highly implementation dependent.
Texture uploading in a thread.
Doing texture uploads in a thread may be very useful for applications handling large amounts of images that needs to be displayed, like for instance a photo gallery application. This is supported in Qt through the existing bindTexture() API. A simple way of doing this is to create two sharing QGLWidgets. One is made current in the main GUI thread, while the other is made current in the texture upload thread. The widget in the uploading thread is never shown, it is only used for sharing textures with the main thread. For each texture that is bound via bindTexture(), notify the main thread so that it can start using the texture.
Using QPainter to draw into a QGLWidget in a thread.
In Qt 4.8, it is possible to draw into a QGLWidget using a QPainter in a separate thread. Note that this is also possible for QGLPixelBuffers and QGLFramebufferObjects. Since this is only supported in the GL 2 paint engine, OpenGL 2.0 or OpenGL ES 2.0 is required.
QGLWidgets can only be created in the main GUI thread. This means a call to doneCurrent() is necessary to release the GL context from the main thread, before the widget can be drawn into by another thread. You then need to call QGLContext::moveToThread() to transfer ownership of the context to the thread in which you want to make it current. Also, the main GUI thread will dispatch resize and paint events to a QGLWidget when the widget is resized, or parts of it becomes exposed or needs redrawing. It is therefore necessary to handle those events because the default implementations inside QGLWidget will try to make the QGLWidget's context current, which again will interfere with any threads rendering into the widget. Reimplement QGLWidget::paintEvent() and QGLWidget::resizeEvent() to notify the rendering thread that a resize or update is necessary, and be careful not to call the base class implementation. If you are rendering an animation, it might not be necessary to handle the paint event at all since the rendering thread is doing regular updates. Then it would be enough to reimplement QGLWidget::paintEvent() to do nothing.
As a general rule when doing threaded rendering: be aware that binding and releasing contexts in different threads have to be synchronized by the user. A GL rendering context can only be current in one thread at any time. If you try to open a QPainter on a QGLWidget and the widget's rendering context is current in another thread, it will fail.
In addition to this, rendering using raw GL calls in a separate thread is supported.
Related
I am making my first game and I am stuck with one problem. I have a world where you can walk free, but then when you meet the enemy you will switch to battle and when you are switching to battle, I need to load all the models that will be rendered in the battle scene. The loading takes about ~5 seconds and I want to make the loading screen. So, I rendered the loading screen in the main thread, but how can I load 3d models and build different VAO and VBO at the same time? I made a new thread for this loading, but I read online "don't use threads for generating VAOs". What is the best solution to make this loading? Should I just preload all the models in the main thread before the game starts? Personally, for me it seems not right to load all the 3d models in the beginning of the game.
Assuming you have two windows, you can bind each context of the window to separate threads. Problems will arise if you share data between them (proper locking is mandatory).
See glfwMakeContextCurrent:
This function makes the OpenGL or OpenGL ES context of the specified window current on the calling thread. A context must only be made current on a single thread at a time and each thread can have only a single current context at a time.
Thread safety:This function may be called from any thread.
See glfwSwapBuffers:
This function swaps the front and back buffers of the specified window when rendering with OpenGL or OpenGL ES.
Thread safety:This function may be called from any thread.
Some functions in GLFW can only be called from the 'main' thread (nor from callbacks), e.g. glfwPollEvents, but other than that, bind the context to a thread, perform your OpenGl calls and swap the buffers. As said before, as long as you don't share any buffers, there should be no problem.
I am working on a project that will use OpenCL to render graphics for display in a QOpenGLWidget. The recommended way to do this seems to be creating a second QOpenGLContext beside the one already present in the QOpenGLWidget, then create a thread where this secondary context can live together with the OpenCL code.
This way Qt can go about it's day as usual with the eventloop running in the main thread. And whenever the QOpenGLWidget decides to paint it will simply fetch data from a buffer prepared in the second thread by the secondary context and the OpenCL inter-op set up there.
This all sounds great on paper, but I am having some problems getting this to work. My question is about how to make the secondary QOpenGLContext "current" in the thread. Because QOpenGLContext::makeCurrent() takes a mandatory QSurface as parameter, and the only surface I have is the one that is available from my QOpenGLWidget, but using that in the secondary thread does not work. I get the following error:
Cannot make QOpenGLContext current in a different thread
So what surface should I use? Or, is there something I missed, or should do differently?
You can create and use a QOffscreenSurface for this purpose.
I am experimenting with Qt for a new layout for an instrument simulation program at work. Our current sim is running everything in a single window (we've used both glut (old) and fltk), it uses glViewport(...) and glScissor(...) to split instrument readouts into their own views, and then it uses some form of "ortho2D" calls to create their own virtual pixel space. The simulator currently updates the instruments and then draws each in their own viewport one by one, all in the same thread.
We want to find a better approach, and we settled on Qt. I am working under a few big constraints:
Each of the instrument panels still need to be in their OpenGL viewport. There are a lot of buttons and a lot of instruments. My tentative solution is to use a QOpenGLWidget for each. I have made progress on this.
The sim is not just a pretty readout, but also simulates many of the instruments as feedback for the instrument designers, so it sometimes has a hefty CPU load. It isn't a full hardware emulator, but it does simulate the logic. I don't think that it's feasible to tell the instruments to update themselves at the beginning of its associated widget's paintEvent(...) method, so I want simulation updates to run in a separate thread.
Our customers may have old computers and thus more recent versions of OpenGL have been ruled out. We are still using glBegin() and glEnd() and everything in between, and the instruments draw a crap ton of variable symbols, so drawing is takes a lot of time and I want to split drawing off into it's own thread. I don't yet know if OpenGL 3 is on the table, which will be necessary (I think) for rendering to off-screen buffers.
Problem: QOpenGLWidget does not have on overrideable "update" method, and it only draws during the widgets' paintEvent(...) and paintGL(...) calls.
Tentative Solution: Split the simulator into three threads:
GUI: Runs user input, paintEvent(...), and paintGL(...).
Simulator: Runs all instrument logic and updates values for symbology.
Drawing: Renders latest symbology to an offscreen buffer (will use a frame buffer object (FBO)).
In this design, cross-thread talking is cyclic and one-way, with the GUI thread providing input, the simulator thread taking that input into account on its next loop, the drawing thread reading the latest symbology and rendering it to the FBO and setting a "next frame available" flag to true (or maybe emitting a signal), and then the paintGL(...) method will take that FBO and spit it out to the widget, thus keeping event processing down and GUI responsiveness up. Continue this cycle.
Bottom line question: I've read here that GUI operations cannot be done in a separate thread, so is my approach even feasible?
If feasible, any other caution or suggestions would be appreciated.
Each OpenGL widget has its own OpenGL context, and these contexts are QObjects and thus can be moved to other threads. As with any otherwise non-threadsafe object, you should only access them from their thread().
Additionally - and this is also portable to QML - you could use worker functors to compute display lists that are then submitted to the render thread to be converted into draw calls. The render thread doesn't do any logic and doesn't compute anything: it takes data (vertex arrays, etc.) and submits it for drawing. The worker functors would be submitted for execution on a thread pool using QtConcurrent::run.
You can thus have a main thread, a render thread (perhaps one per widget, but not necessarily), and functors that run your simulation steps.
In any case, convoluting logic and rendering is a very bad idea. Whether you're doing drawing using QPainter on a raster widget, or using QPainter on an QOpenGLWidget, or using direct OpenGL calls, the thread that does the drawing should not have to compute what's to be drawn.
If you don't want to mess with OpenGL calls, and you can represent most of your work as array-based QPainter calls (e.g. drawRects, drawPolygons), these translate almost directly into OpenGL draw calls and the OpenGL backend will render them just as quickly as if you hand-coded the draw calls. QPainter does all this for you if you use it on a QOpenGLWidget!
I'm writing a program in Qt, which runs 10 worker threads which calculate the trajectory of an object in space. They also have to draw the path of the object. I have a "Body" class deriving QGraphicsEllipseItem and it has a QPainterPath in it. The "Simulation" class takes a list of obstacles in the world, and the body to simulate and runs until the body collides with something. Simulation runs in a separate thread ( done with moveToThread, not by subclassing QThread). When the body collides, the Simulation emits a signal saying that it finished. When all threads have finished I'd like to draw the paths (I do it by invoking a method in "Body" which enables path drawing in its draw method).
Unfortunately I get ASSERT errors :
ASSERT: "!unindexedItems.contains(item)" in file graphicsview\qgraphicsscenebsptreeindex.cpp, line 364
They happen seemingly randomly. I've tried different connection types, to no result.
I'm starting the threads in a loop.
I'm using Qt 5.0
Generally speaking, with Qt you can't do any GUI operations outside of the GUI thread (i.e. the thread that is executing QApplication::exec(), which is typically the main() thread).
So if you have multiple threads manipulating QGraphicsItems (especially QGraphicsItems that are currently part of a QGraphicsScene), that is likely the cause of your assertion failures. That is, when the Qt GUI thread is doing its window refresh, it is reading data from the various QGraphicsItem objects as part of its calculations, and it expects the QGraphicsItems to remain constant for the duration of the refresh operation. If a QGraphicsItem is changed (by another thread) while the refresh routine is executing, then the calculations made by the main thread can become wrong/corrupted, and that occasionally causes an assertion failure (and/or other unwanted behaviors).
If you really need to use multiple threads, what you'll probably need to do is have the threads do all their calculations on their own private data structures that the Qt GUI thread has no access to. Then when the threads have computed their results, they should send the results back to the Qt GUI thread (via queued connection or QApplication::postEvent()). The GUI thread can then look at the results and use them to update the QGraphicsItems, etc; this will be "safe" because this update can't happen in the middle of a window update.
If that sounds like too much work, then you might consider just doing everything in the GUI thread; it will be much easier and simpler to make everything work reliably that way.
As mentioned by Jeremy, Qt rendering must be done on the main thread.
While you could move it all to the main thread, you've likely chosen to create separate ones for efficiency, especially as collision detection can be processor intensive. The best way to handle this is to split the modelling of the objects and their physics from their rendering, as you would in a Model / View / Controller pattern.
Create representations of the body instances that are not derived from any QGraphicsItem/Objects. These can then do their calculations on separate threads and have signals to graphics objects that are running in the main thread, which updates each body instance's graphic representation, allowing real-time rendering of the trajectories.
I have a MFC document/view C++ graphics application that does all its drawing to an off screen bitmap, and then copys that to the supplied CDC pointer in the OnDraw method. Over the last couple of days I've been looking to place the drawing component in a seperate worker thread, so it doesn't stall the GUI. I seem to get a fair number of MFC GDI related asserts firing when I do this, e,g,
VERIFY(::MoveToEx(m_hAttribDC, x, y, &point)
So a few questions;
Are there any problems with using worker threads with MFC & GDI?
Are there issues using MFC GDI objects across threads?
Do GDI objects have to be declared locally to a thread?
While it is possible the issue is resource/locking related, the drawing thread has its own provate CDC and CBitmap that it uses for all the drawing, and only copies the bitmap back to the main thread when it hasz excludive access via a mutex. The code has also been tested by direct calling rather than as a seperate thread to prove the problem does relate to threading.
Device contexts can be used by any thread (the only thing you must be aware of is that the thread which did the GetDC should also call ReleaseDC), but are not inherently thread safe. You have to ensure that only one caller is accessing the DC at any given point in time, but you seem to have taken care of that, from what you write.
What do you mean by Do GDI thread have to be declared locally to a thread ? They must be allocated and freed in the same thread, but they can be created/used in any thread. Once again, you are responsible not to use such a resource from two threads simultaneously.
You should probably check the series of posts from Raymond Chen on the subject:
Thread affinity of user interface objects, part 1: Window handles
Thread affinity of user interface objects, part 2: Device contexts
Thread affinity of user interface objects, part 3: Menus, icons, cursors, and accelerator tables
Thread affinity of user interface objects, part 4: GDI objects and other notes on affinity
Thread affinity of user interface objects, part 5: Object clean-up
and be sure that you don't link to the single threaded versions of the C/MFC libraries.
Raymond Chen has posted about this on his blog:
http://blogs.msdn.com/oldnewthing/archive/2005/10/11/479587.aspx
(There are other blog posts about thread affinity of windows objects which might be helpful to you).
Apparently for DCs you need to do the Get/Release on the same thread.
Hope that helps!